Coverage Report

Created: 2024-05-20 07:14

/src/skia/modules/skparagraph/include/Paragraph.h
Line
Count
Source (jump to first uncovered line)
1
// Copyright 2019 Google LLC.
2
#ifndef Paragraph_DEFINED
3
#define Paragraph_DEFINED
4
5
#include "include/core/SkPath.h"
6
#include "modules/skparagraph/include/FontCollection.h"
7
#include "modules/skparagraph/include/Metrics.h"
8
#include "modules/skparagraph/include/ParagraphStyle.h"
9
#include "modules/skparagraph/include/TextStyle.h"
10
#include <unordered_set>
11
12
class SkCanvas;
13
14
namespace skia {
15
namespace textlayout {
16
17
class ParagraphPainter;
18
19
class Paragraph {
20
21
public:
22
    Paragraph(ParagraphStyle style, sk_sp<FontCollection> fonts);
23
24
0
    virtual ~Paragraph() = default;
25
26
0
    SkScalar getMaxWidth() { return fWidth; }
27
28
0
    SkScalar getHeight() { return fHeight; }
29
30
0
    SkScalar getMinIntrinsicWidth() { return fMinIntrinsicWidth; }
31
32
0
    SkScalar getMaxIntrinsicWidth() { return fMaxIntrinsicWidth; }
33
34
0
    SkScalar getAlphabeticBaseline() { return fAlphabeticBaseline; }
35
36
0
    SkScalar getIdeographicBaseline() { return fIdeographicBaseline; }
37
38
0
    SkScalar getLongestLine() { return fLongestLine; }
39
40
0
    bool didExceedMaxLines() { return fExceededMaxLines; }
41
42
    virtual void layout(SkScalar width) = 0;
43
44
    virtual void paint(SkCanvas* canvas, SkScalar x, SkScalar y) = 0;
45
46
    virtual void paint(ParagraphPainter* painter, SkScalar x, SkScalar y) = 0;
47
48
    // Returns a vector of bounding boxes that enclose all text between
49
    // start and end glyph indexes, including start and excluding end
50
    virtual std::vector<TextBox> getRectsForRange(unsigned start,
51
                                                  unsigned end,
52
                                                  RectHeightStyle rectHeightStyle,
53
                                                  RectWidthStyle rectWidthStyle) = 0;
54
55
    virtual std::vector<TextBox> getRectsForPlaceholders() = 0;
56
57
    // Returns the index of the glyph that corresponds to the provided coordinate,
58
    // with the top left corner as the origin, and +y direction as down
59
    virtual PositionWithAffinity getGlyphPositionAtCoordinate(SkScalar dx, SkScalar dy) = 0;
60
61
    // Finds the first and last glyphs that define a word containing
62
    // the glyph at index offset
63
    virtual SkRange<size_t> getWordBoundary(unsigned offset) = 0;
64
65
    virtual void getLineMetrics(std::vector<LineMetrics>&) = 0;
66
67
    virtual size_t lineNumber() = 0;
68
69
    virtual void markDirty() = 0;
70
71
    // This function will return the number of unresolved glyphs or
72
    // -1 if not applicable (has not been shaped yet - valid case)
73
    virtual int32_t unresolvedGlyphs() = 0;
74
    virtual std::unordered_set<SkUnichar> unresolvedCodepoints() = 0;
75
76
    // Experimental API that allows fast way to update some of "immutable" paragraph attributes
77
    // but not the text itself
78
    virtual void updateTextAlign(TextAlign textAlign) = 0;
79
    virtual void updateFontSize(size_t from, size_t to, SkScalar fontSize) = 0;
80
    virtual void updateForegroundPaint(size_t from, size_t to, SkPaint paint) = 0;
81
    virtual void updateBackgroundPaint(size_t from, size_t to, SkPaint paint) = 0;
82
83
    enum VisitorFlags {
84
        kWhiteSpace_VisitorFlag = 1 << 0,
85
    };
86
    struct VisitorInfo {
87
        const SkFont&   font;
88
        SkPoint         origin;
89
        SkScalar        advanceX;
90
        int             count;
91
        const uint16_t* glyphs;     // count values
92
        const SkPoint*  positions;  // count values
93
        const uint32_t* utf8Starts; // count+1 values
94
        unsigned        flags;
95
    };
96
97
    // lineNumber begins at 0. If info is null, this signals the end of that line.
98
    using Visitor = std::function<void(int lineNumber, const VisitorInfo*)>;
99
    virtual void visit(const Visitor&) = 0;
100
101
    struct ExtendedVisitorInfo {
102
        const SkFont&   font;
103
        SkPoint         origin;
104
        SkSize          advance;
105
        int             count;
106
        const uint16_t* glyphs;     // count values
107
        SkPoint*        positions;  // count values
108
        const SkRect*   bounds;     // count values
109
        const uint32_t* utf8Starts; // count+1 values
110
        unsigned        flags;
111
    };
112
    using ExtendedVisitor = std::function<void(int lineNumber, const ExtendedVisitorInfo*)>;
113
    virtual void extendedVisit(const ExtendedVisitor&) = 0;
114
115
    /* Returns path for a given line
116
     *
117
     * @param lineNumber  a line number
118
     * @param dest        a resulting path
119
     * @return            a number glyphs that could not be converted to path
120
     */
121
    virtual int getPath(int lineNumber, SkPath* dest) = 0;
122
123
    /* Returns path for a text blob
124
     *
125
     * @param textBlob    a text blob
126
     * @return            a path
127
     */
128
    static SkPath GetPath(SkTextBlob* textBlob);
129
130
    /* Checks if a given text blob contains
131
     * glyph with emoji
132
     *
133
     * @param textBlob    a text blob
134
     * @return            true if there is such a glyph
135
     */
136
    virtual bool containsEmoji(SkTextBlob* textBlob) = 0;
137
138
    /* Checks if a given text blob contains colored font or bitmap
139
     *
140
     * @param textBlob    a text blob
141
     * @return            true if there is such a glyph
142
     */
143
    virtual bool containsColorFontOrBitmap(SkTextBlob* textBlob) = 0;
144
145
    // Editing API
146
147
    /* Finds the line number of the line that contains the given UTF-8 index.
148
    *
149
    * @param index         a UTF-8 TextIndex into the paragraph
150
    * @return              the line number the glyph that corresponds to the
151
    *                      given codeUnitIndex is in, or -1 if the codeUnitIndex
152
    *                      is out of bounds, or when the glyph is truncated or
153
    *                      ellipsized away.
154
    */
155
    virtual int getLineNumberAt(TextIndex codeUnitIndex) const = 0;
156
157
    /* Finds the line number of the line that contains the given UTF-16 index.
158
    *
159
    * @param index         a UTF-16 offset into the paragraph
160
    * @return              the line number the glyph that corresponds to the
161
    *                      given codeUnitIndex is in, or -1 if the codeUnitIndex
162
    *                      is out of bounds, or when the glyph is truncated or
163
    *                      ellipsized away.
164
    */
165
    virtual int getLineNumberAtUTF16Offset(size_t codeUnitIndex) = 0;
166
167
    /* Returns line metrics info for the line
168
     *
169
     * @param lineNumber    a line number
170
     * @param lineMetrics   an address to return the info (in case of null just skipped)
171
     * @return              true if the line is found; false if not
172
     */
173
    virtual bool getLineMetricsAt(int lineNumber, LineMetrics* lineMetrics) const = 0;
174
175
    /* Returns the visible text on the line (excluding a possible ellipsis)
176
     *
177
     * @param lineNumber    a line number
178
     * @param includeSpaces indicates if the whitespaces should be included
179
     * @return              the range of the text that is shown in the line
180
     */
181
    virtual TextRange getActualTextRange(int lineNumber, bool includeSpaces) const = 0;
182
183
    struct GlyphClusterInfo {
184
        SkRect fBounds;
185
        TextRange fClusterTextRange;
186
        TextDirection fGlyphClusterPosition;
187
    };
188
189
    /** Finds a glyph cluster for text index
190
     *
191
     * @param codeUnitIndex   a text index
192
     * @param glyphInfo       a glyph cluster info filled if not null
193
     * @return                true if glyph cluster was found; false if not
194
     */
195
    virtual bool getGlyphClusterAt(TextIndex codeUnitIndex, GlyphClusterInfo* glyphInfo) = 0;
196
197
    /** Finds the closest glyph cluster for a visual text position
198
     *
199
     * @param dx              x coordinate
200
     * @param dy              y coordinate
201
     * @param glyphInfo       a glyph cluster info filled if not null
202
     * @return                true if glyph cluster was found; false if not
203
     *                        (which usually means the paragraph is empty)
204
     */
205
    virtual bool getClosestGlyphClusterAt(SkScalar dx,
206
                                          SkScalar dy,
207
                                          GlyphClusterInfo* glyphInfo) = 0;
208
209
    // The glyph and grapheme cluster information assoicated with a unicode
210
    // codepoint in the paragraph.
211
    struct GlyphInfo {
212
        SkRect fGraphemeLayoutBounds;
213
        TextRange fGraphemeClusterTextRange;
214
        TextDirection fDirection;
215
        bool fIsEllipsis;
216
    };
217
218
    /** Retrives the information associated with the glyph located at the given
219
     *  codeUnitIndex.
220
     *
221
     * @param codeUnitIndex   a UTF-16 offset into the paragraph
222
     * @param glyphInfo       an optional GlyphInfo struct to hold the
223
     *                        information associated with the glyph found at the
224
     *                        given index
225
     * @return                false only if the offset is out of bounds
226
     */
227
    virtual bool getGlyphInfoAtUTF16Offset(size_t codeUnitIndex, GlyphInfo* glyphInfo) = 0;
228
229
    /** Finds the information associated with the closest glyph to the given
230
     *  paragraph coordinates.
231
     *
232
     * @param dx              x coordinate
233
     * @param dy              y coordinate
234
     * @param glyphInfo       an optional GlyphInfo struct to hold the
235
     *                        information associated with the glyph found. The
236
     *                        text indices and text ranges are described using
237
     *                        UTF-16 offsets
238
     * @return                true if a graphme cluster was found; false if not
239
     *                        (which usually means the paragraph is empty)
240
     */
241
    virtual bool getClosestUTF16GlyphInfoAt(SkScalar dx, SkScalar dy, GlyphInfo* glyphInfo) = 0;
242
243
    struct FontInfo {
244
        FontInfo(const SkFont& font, const TextRange textRange)
245
0
                : fFont(font), fTextRange(textRange) {}
246
0
        virtual ~FontInfo() = default;
247
0
        FontInfo(const FontInfo& ) = default;
248
        SkFont fFont;
249
        TextRange fTextRange;
250
    };
251
252
    /** Returns the font that is used to shape the text at the position
253
     *
254
     * @param codeUnitIndex   text index
255
     * @return                font info or an empty font info if the text is not found
256
     */
257
    virtual SkFont getFontAt(TextIndex codeUnitIndex) const = 0;
258
259
    /** Returns the font used to shape the text at the given UTF-16 offset.
260
     *
261
     * @param codeUnitIndex   a UTF-16 offset in the paragraph
262
     * @return                font info or an empty font info if the text is not found
263
     */
264
    virtual SkFont getFontAtUTF16Offset(size_t codeUnitIndex) = 0;
265
266
    /** Returns the information about all the fonts used to shape the paragraph text
267
     *
268
     * @return                a list of fonts and text ranges
269
     */
270
    virtual std::vector<FontInfo> getFonts() const = 0;
271
272
protected:
273
    sk_sp<FontCollection> fFontCollection;
274
    ParagraphStyle fParagraphStyle;
275
276
    // Things for Flutter
277
    SkScalar fAlphabeticBaseline;
278
    SkScalar fIdeographicBaseline;
279
    SkScalar fHeight;
280
    SkScalar fWidth;
281
    SkScalar fMaxIntrinsicWidth;
282
    SkScalar fMinIntrinsicWidth;
283
    SkScalar fLongestLine;
284
    bool fExceededMaxLines;
285
};
286
}  // namespace textlayout
287
}  // namespace skia
288
289
#endif  // Paragraph_DEFINED