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