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