• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2019 Google LLC.
2 #ifndef Paragraph_DEFINED
3 #define Paragraph_DEFINED
4 
5 #include "modules/skparagraph/include/FontCollection.h"
6 #include "modules/skparagraph/include/Metrics.h"
7 #include "modules/skparagraph/include/ParagraphStyle.h"
8 #include "modules/skparagraph/include/TextLineBase.h"
9 #include "modules/skparagraph/include/TextStyle.h"
10 #include <unordered_set>
11 #include "drawing.h"
12 
13 class SkCanvas;
14 
15 namespace skia {
16 namespace textlayout {
17 
18 #ifdef OHOS_SUPPORT
19 enum InternalState {
20   kUnknown = 0,
21   kIndexed = 1,     // Text is indexed
22   kShaped = 2,      // Text is shaped
23   kLineBroken = 5,
24   kFormatted = 6,
25   kDrawn = 7
26 };
27 #endif
28 
29 class ParagraphPainter;
30 
31 class Paragraph {
32 
33 public:
34     Paragraph() = default;
35 
36     Paragraph(ParagraphStyle style, sk_sp<FontCollection> fonts);
37 
38     virtual ~Paragraph() = default;
39 
getMaxWidth()40     SkScalar getMaxWidth() { return fWidth; }
41 
getHeight()42     SkScalar getHeight() { return fHeight; }
43 
getMinIntrinsicWidth()44     SkScalar getMinIntrinsicWidth() { return fMinIntrinsicWidth; }
45 
getMaxIntrinsicWidth()46     SkScalar getMaxIntrinsicWidth() { return fMaxIntrinsicWidth; }
47 
getAlphabeticBaseline()48     SkScalar getAlphabeticBaseline() { return fAlphabeticBaseline; }
49 
getIdeographicBaseline()50     SkScalar getIdeographicBaseline() { return fIdeographicBaseline; }
51 
getLongestLine()52     SkScalar getLongestLine() { return fLongestLine; }
53 
getLongestLineWithIndent()54     SkScalar getLongestLineWithIndent() { return fLongestLineWithIndent; }
55 
setLongestLineWithIndent(SkScalar longestLineWithIndent)56     void setLongestLineWithIndent(SkScalar longestLineWithIndent)
57     {
58         fLongestLineWithIndent = longestLineWithIndent;
59     }
60 
getGlyphsBoundsTop()61     SkScalar getGlyphsBoundsTop() { return fGlyphsBoundsTop; }
62 
getGlyphsBoundsBottom()63     SkScalar getGlyphsBoundsBottom() { return fGlyphsBoundsBottom; }
64 
getGlyphsBoundsLeft()65     SkScalar getGlyphsBoundsLeft() { return fGlyphsBoundsLeft; }
66 
getGlyphsBoundsRight()67     SkScalar getGlyphsBoundsRight() { return fGlyphsBoundsRight; }
68 
didExceedMaxLines()69     bool didExceedMaxLines() { return fExceededMaxLines; }
70 
71 #ifdef OHOS_SUPPORT
getParagraphStyle()72     ParagraphStyle& getParagraphStyle() { return fParagraphStyle; }
73 
74     virtual SkTArray<Block, true>& exportTextStyles() = 0;
75 
76     virtual void setState(InternalState state) = 0;
77 
78     virtual InternalState getState() const = 0;
79 #endif
80 
81     virtual void layout(SkScalar width) = 0;
82 
83     virtual void paint(SkCanvas* canvas, SkScalar x, SkScalar y) = 0;
84 
85     virtual void paint(ParagraphPainter* painter, SkScalar x, SkScalar y) = 0;
86 #ifdef USE_SKIA_TXT
87     virtual void paint(ParagraphPainter* painter, RSPath* path, SkScalar hOffset, SkScalar vOffset) = 0;
88 #endif
89     // Returns a vector of bounding boxes that enclose all text between
90     // start and end glyph indexes, including start and excluding end
91     virtual std::vector<TextBox> getRectsForRange(unsigned start,
92                                                   unsigned end,
93                                                   RectHeightStyle rectHeightStyle,
94                                                   RectWidthStyle rectWidthStyle) = 0;
95 
96     virtual std::vector<TextBox> getRectsForPlaceholders() = 0;
97 
98     // Returns the index of the glyph that corresponds to the provided coordinate,
99     // with the top left corner as the origin, and +y direction as down
100     virtual PositionWithAffinity getGlyphPositionAtCoordinate(SkScalar dx, SkScalar dy) = 0;
101 
102     // Finds the first and last glyphs that define a word containing
103     // the glyph at index offset
104     virtual SkRange<size_t> getWordBoundary(unsigned offset) = 0;
105 
106     virtual void getLineMetrics(std::vector<LineMetrics>&) = 0;
107 
108     virtual size_t lineNumber() = 0;
109 
110     virtual TextRange getEllipsisTextRange() = 0;
111 
112     virtual void markDirty() = 0;
113 
114     // This function will return the number of unresolved glyphs or
115     // -1 if not applicable (has not been shaped yet - valid case)
116     virtual int32_t unresolvedGlyphs() = 0;
117     virtual std::unordered_set<SkUnichar> unresolvedCodepoints() = 0;
118 
119     // Experimental API that allows fast way to update some of "immutable" paragraph attributes
120     // but not the text itself
121     virtual void updateTextAlign(TextAlign textAlign) = 0;
122     virtual void updateFontSize(size_t from, size_t to, SkScalar fontSize) = 0;
123     virtual void updateForegroundPaint(size_t from, size_t to, SkPaint paint) = 0;
124     virtual void updateBackgroundPaint(size_t from, size_t to, SkPaint paint) = 0;
125     virtual std::vector<ParagraphPainter::PaintID> updateColor(size_t from, size_t to, SkColor color) = 0;
126 
127     enum VisitorFlags {
128         kWhiteSpace_VisitorFlag = 1 << 0,
129     };
130     struct VisitorInfo {
131         const SkFont&   font;
132         SkPoint         origin;
133         SkScalar        advanceX;
134         int             count;
135         const uint16_t* glyphs;     // count values
136         const SkPoint*  positions;  // count values
137         const uint32_t* utf8Starts; // count+1 values
138         unsigned        flags;
139     };
140 
141     // lineNumber begins at 0. If info is null, this signals the end of that line.
142     using Visitor = std::function<void(int lineNumber, const VisitorInfo*)>;
143     virtual void visit(const Visitor&) = 0;
144 
145     // Editing API
146     virtual int getLineNumberAt(TextIndex codeUnitIndex) const = 0;
147 
148     /* Returns line metrics info for the line
149      *
150      * @param lineNumber    a line number
151      * @param lineMetrics   an address to return the info (in case of null just skipped)
152      * @return              true if the line is found; false if not
153      */
154     virtual bool getLineMetricsAt(int lineNumber, LineMetrics* lineMetrics) const = 0;
155 
156     /* Returns the visible text on the line (excluding a possible ellipsis)
157      *
158      * @param lineNumber    a line number
159      * @param includeSpaces indicates if the whitespaces should be included
160      * @return              the range of the text that is shown in the line
161      */
162     virtual TextRange getActualTextRange(int lineNumber, bool includeSpaces) const = 0;
163 
164     struct GlyphClusterInfo {
165         SkRect fBounds;
166         TextRange fClusterTextRange;
167         TextDirection fGlyphClusterPosition;
168     };
169 
170     /** Finds a glyph cluster for text index
171      *
172      * @param codeUnitIndex   a text index
173      * @param glyphInfo       a glyph cluster info filled if not null
174      * @return                true if glyph cluster was found; false if not
175      */
176     virtual bool getGlyphClusterAt(TextIndex codeUnitIndex, GlyphClusterInfo* glyphInfo) = 0;
177 
178     /** Finds the closest glyph cluster for a visual text position
179      *
180      * @param dx              x coordinate
181      * @param dy              y coordinate
182      * @param glyphInfo       a glyph cluster info filled if not null
183      * @return
184      */
185     virtual bool getClosestGlyphClusterAt(SkScalar dx,
186                                           SkScalar dy,
187                                           GlyphClusterInfo* glyphInfo) = 0;
188 
189 #ifndef USE_SKIA_TXT
190     struct FontInfo {
FontInfoFontInfo191         FontInfo(const SkFont font, const TextRange textRange)
192             : fFont(font), fTextRange(textRange) { }
193         virtual ~FontInfo() = default;
194         FontInfo(const FontInfo& ) = default;
195         SkFont fFont;
196         TextRange fTextRange;
197     };
198 #else
199     struct FontInfo {
FontInfoFontInfo200         FontInfo(const RSFont font, const TextRange textRange)
201             : fFont(font), fTextRange(textRange) { }
202         virtual ~FontInfo() = default;
203         FontInfo(const FontInfo& ) = default;
204         RSFont fFont;
205         TextRange fTextRange;
206     };
207 #endif
208 
209     struct TextCutRecord {
210         size_t charbegin;
211         size_t charOver;
212         SkScalar phraseWidth;
213     };
214 
215     /** Returns the font that is used to shape the text at the position
216      *
217      * @param codeUnitIndex   text index
218      * @return                font info or an empty font info if the text is not found
219      */
220 #ifndef USE_SKIA_TXT
221     virtual SkFont getFontAt(TextIndex codeUnitIndex) const = 0;
222 #else
223     virtual RSFont getFontAt(TextIndex codeUnitIndex) const = 0;
224 #endif
225 
226     /** Returns the information about all the fonts used to shape the paragraph text
227      *
228      * @return                a list of fonts and text ranges
229      */
230     virtual std::vector<FontInfo> getFonts() const = 0;
231 
232     virtual void setIndents(const std::vector<SkScalar>& indents) = 0;
233 
234     virtual SkScalar detectIndents(size_t index) = 0;
235 
236     virtual SkScalar getTextSplitRatio() const = 0;
237 
238 #ifndef USE_SKIA_TXT
239     virtual SkFontMetrics measureText() = 0;
240 #else
241     virtual RSFontMetrics measureText() = 0;
242 #endif
243 
244 #ifndef USE_SKIA_TXT
245     virtual bool GetLineFontMetrics(const size_t lineNumber, size_t& charNumber,
246         std::vector<SkFontMetrics>& fontMetrics) = 0;
247 #else
248     virtual bool GetLineFontMetrics(const size_t lineNumber, size_t& charNumber,
249         std::vector<RSFontMetrics>& fontMetrics) = 0;
250 #endif
251     virtual std::vector<std::unique_ptr<TextLineBase>> GetTextLines() = 0;
252     virtual std::unique_ptr<Paragraph> CloneSelf() = 0;
253 
254 #ifdef OHOS_SUPPORT
255     virtual size_t getUnicodeIndex(TextIndex index) const = 0;
256     virtual const std::vector<SkUnichar>& unicodeText() const = 0;
257     virtual std::unique_ptr<Paragraph> createCroppedCopy(
258             size_t startIndex, size_t count = std::numeric_limits<size_t>::max()) = 0;
259     virtual void initUnicodeText() = 0;
260     virtual size_t GetMaxLines() const = 0;
261     virtual SkIRect generatePaintRegion(SkScalar x, SkScalar y) = 0;
262 #endif
263 
264 protected:
265     sk_sp<FontCollection> fFontCollection;
266     ParagraphStyle fParagraphStyle;
267 
268     // Things for Flutter
269     SkScalar fAlphabeticBaseline;
270     SkScalar fIdeographicBaseline;
271     SkScalar fGlyphsBoundsTop;
272     SkScalar fGlyphsBoundsBottom;
273     SkScalar fGlyphsBoundsLeft;
274     SkScalar fGlyphsBoundsRight;
275     SkScalar fHeight;
276     SkScalar fWidth;
277     SkScalar fMaxIntrinsicWidth;
278     SkScalar fMinIntrinsicWidth;
279     SkScalar fLongestLine;
280     SkScalar fLongestLineWithIndent;
281     bool fExceededMaxLines;
282 };
283 }  // namespace textlayout
284 }  // namespace skia
285 
286 #endif  // Paragraph_DEFINED
287