1 // Copyright 2019 Google LLC. 2 #ifndef ParagraphImpl_DEFINED 3 #define ParagraphImpl_DEFINED 4 5 #include "include/core/SkFont.h" 6 #include "include/core/SkPaint.h" 7 #include "include/core/SkPicture.h" 8 #include "include/core/SkPoint.h" 9 #include "include/core/SkRect.h" 10 #include "include/core/SkRefCnt.h" 11 #include "include/core/SkScalar.h" 12 #include "include/core/SkSpan.h" 13 #include "include/core/SkString.h" 14 #include "include/core/SkTypes.h" 15 #include "include/private/SkBitmaskEnum.h" 16 #include "include/private/SkOnce.h" 17 #include "include/private/SkTArray.h" 18 #include "include/private/SkTemplates.h" 19 #include "modules/skparagraph/include/DartTypes.h" 20 #include "modules/skparagraph/include/FontCollection.h" 21 #include "modules/skparagraph/include/Paragraph.h" 22 #include "modules/skparagraph/include/ParagraphCache.h" 23 #include "modules/skparagraph/include/ParagraphStyle.h" 24 #include "modules/skparagraph/include/TextLineBase.h" 25 #include "modules/skparagraph/include/TextShadow.h" 26 #include "modules/skparagraph/include/TextStyle.h" 27 #include "modules/skparagraph/src/Run.h" 28 #include "modules/skparagraph/src/TextLine.h" 29 #include "modules/skunicode/include/SkUnicode.h" 30 #include "include/private/SkTHash.h" 31 32 #include <memory> 33 #include <string> 34 #include <vector> 35 36 class SkCanvas; 37 38 namespace skia { 39 namespace textlayout { 40 41 class LineMetrics; 42 class TextLine; 43 44 template <typename T> bool operator==(const SkSpan<T>& a, const SkSpan<T>& b) { 45 return a.size() == b.size() && a.begin() == b.begin(); 46 } 47 48 template <typename T> bool operator<=(const SkSpan<T>& a, const SkSpan<T>& b) { 49 return a.begin() >= b.begin() && a.end() <= b.end(); 50 } 51 52 template <typename TStyle> 53 struct StyleBlock { StyleBlockStyleBlock54 StyleBlock() : fRange(EMPTY_RANGE), fStyle() { } StyleBlockStyleBlock55 StyleBlock(size_t start, size_t end, const TStyle& style) : fRange(start, end), fStyle(style) {} StyleBlockStyleBlock56 StyleBlock(TextRange textRange, const TStyle& style) : fRange(textRange), fStyle(style) {} addStyleBlock57 void add(TextRange tail) { 58 SkASSERT(fRange.end == tail.start); 59 fRange = TextRange(fRange.start, fRange.start + fRange.width() + tail.width()); 60 } 61 TextRange fRange; 62 TStyle fStyle; 63 }; 64 65 struct ResolvedFontDescriptor { 66 67 #ifndef USE_SKIA_TXT ResolvedFontDescriptorResolvedFontDescriptor68 ResolvedFontDescriptor(TextIndex index, SkFont font) 69 : fFont(font), fTextStart(index) { } 70 SkFont fFont; 71 #else 72 ResolvedFontDescriptor(TextIndex index, RSFont font) 73 : fFont(font), fTextStart(index) { } 74 RSFont fFont; 75 #endif 76 TextIndex fTextStart; 77 }; 78 79 enum InternalState { 80 kUnknown = 0, 81 kIndexed = 1, // Text is indexed 82 kShaped = 2, // Text is shaped 83 kLineBroken = 5, 84 kFormatted = 6, 85 kDrawn = 7 86 }; 87 88 /* 89 struct BidiRegion { 90 BidiRegion(size_t start, size_t end, uint8_t dir) 91 : text(start, end), direction(dir) { } 92 TextRange text; 93 uint8_t direction; 94 }; 95 */ 96 class ParagraphImpl final : public Paragraph { 97 98 public: 99 100 ParagraphImpl() = default; 101 102 ParagraphImpl(const SkString& text, 103 ParagraphStyle style, 104 SkTArray<Block, true> blocks, 105 SkTArray<Placeholder, true> placeholders, 106 sk_sp<FontCollection> fonts, 107 std::shared_ptr<SkUnicode> unicode); 108 109 ParagraphImpl(const std::u16string& utf16text, 110 ParagraphStyle style, 111 SkTArray<Block, true> blocks, 112 SkTArray<Placeholder, true> placeholders, 113 sk_sp<FontCollection> fonts, 114 std::shared_ptr<SkUnicode> unicode); 115 116 ~ParagraphImpl() override; 117 118 void layout(SkScalar width) override; 119 void paint(SkCanvas* canvas, SkScalar x, SkScalar y) override; 120 void paint(ParagraphPainter* canvas, SkScalar x, SkScalar y) override; 121 void paint(ParagraphPainter* canvas, RSPath* path, SkScalar hOffset, SkScalar vOffset) override; 122 std::vector<TextBox> getRectsForRange(unsigned start, 123 unsigned end, 124 RectHeightStyle rectHeightStyle, 125 RectWidthStyle rectWidthStyle) override; 126 std::vector<TextBox> getRectsForPlaceholders() override; 127 void getLineMetrics(std::vector<LineMetrics>&) override; 128 PositionWithAffinity getGlyphPositionAtCoordinate(SkScalar dx, SkScalar dy) override; 129 SkRange<size_t> getWordBoundary(unsigned offset) override; 130 getApplyRoundingHack()131 bool getApplyRoundingHack() const { return false; } 132 lineNumber()133 size_t lineNumber() override { return fLineNumber; } 134 135 TextLine& addLine(SkVector offset, SkVector advance, 136 TextRange textExcludingSpaces, TextRange text, TextRange textIncludingNewlines, 137 ClusterRange clusters, ClusterRange clustersWithGhosts, SkScalar widthWithSpaces, 138 InternalLineMetrics sizes); 139 text()140 SkSpan<const char> text() const { return SkSpan<const char>(fText.c_str(), fText.size()); } 141 std::vector<SkUnichar> convertUtf8ToUnicode(const SkString& utf8); unicodeText()142 const std::vector<SkUnichar>& unicodeText() const { return fUnicodeText; } getUnicodeIndex(TextIndex index)143 size_t getUnicodeIndex(TextIndex index) const { 144 if (index >= fUnicodeIndexForUTF8Index.size()) { 145 return fUnicodeIndexForUTF8Index.empty() ? 0 : fUnicodeIndexForUTF8Index.back() + 1; 146 } 147 return fUnicodeIndexForUTF8Index[index]; 148 } state()149 InternalState state() const { return fState; } runs()150 SkSpan<Run> runs() { return SkSpan<Run>(fRuns.data(), fRuns.size()); } styles()151 SkSpan<Block> styles() { 152 return SkSpan<Block>(fTextStyles.data(), fTextStyles.size()); 153 } placeholders()154 SkSpan<Placeholder> placeholders() { 155 return SkSpan<Placeholder>(fPlaceholders.data(), fPlaceholders.size()); 156 } lines()157 SkSpan<TextLine> lines() { return SkSpan<TextLine>(fLines.data(), fLines.size()); } paragraphStyle()158 const ParagraphStyle& paragraphStyle() const { return fParagraphStyle; } clusters()159 SkSpan<Cluster> clusters() { return SkSpan<Cluster>(fClusters.begin(), fClusters.size()); } fontCollection()160 sk_sp<FontCollection> fontCollection() const { return fFontCollection; } 161 void formatLines(SkScalar maxWidth); 162 void ensureUTF16Mapping(); 163 SkTArray<TextIndex> countSurroundingGraphemes(TextRange textRange) const; 164 TextIndex findNextGraphemeBoundary(TextIndex utf8) const; 165 TextIndex findPreviousGraphemeBoundary(TextIndex utf8) const; 166 TextIndex findNextGlyphClusterBoundary(TextIndex utf8) const; 167 TextIndex findPreviousGlyphClusterBoundary(TextIndex utf8) const; getUTF16Index(TextIndex index)168 size_t getUTF16Index(TextIndex index) const { 169 return fUTF16IndexForUTF8Index[index]; 170 } 171 strutEnabled()172 bool strutEnabled() const { return paragraphStyle().getStrutStyle().getStrutEnabled(); } strutForceHeight()173 bool strutForceHeight() const { 174 return paragraphStyle().getStrutStyle().getForceStrutHeight(); 175 } strutHeightOverride()176 bool strutHeightOverride() const { 177 return paragraphStyle().getStrutStyle().getHeightOverride(); 178 } strutMetrics()179 InternalLineMetrics strutMetrics() const { return fStrutMetrics; } 180 181 SkString getEllipsis() const; 182 WordBreakType getWordBreakType() const; 183 LineBreakStrategy getLineBreakStrategy() const; 184 185 SkSpan<const char> text(TextRange textRange); 186 SkSpan<Cluster> clusters(ClusterRange clusterRange); 187 Cluster& cluster(ClusterIndex clusterIndex); clusterIndex(TextIndex textIndex)188 ClusterIndex clusterIndex(TextIndex textIndex) { 189 auto clusterIndex = this->fClustersIndexFromCodeUnit[textIndex]; 190 SkASSERT(clusterIndex != EMPTY_INDEX); 191 return clusterIndex; 192 } run(RunIndex runIndex)193 Run& run(RunIndex runIndex) { 194 SkASSERT(runIndex < SkToSizeT(fRuns.size())); 195 return fRuns[runIndex]; 196 } 197 198 Run& runByCluster(ClusterIndex clusterIndex); 199 SkSpan<Block> blocks(BlockRange blockRange); 200 Block& block(BlockIndex blockIndex); resolvedFonts()201 SkTArray<ResolvedFontDescriptor> resolvedFonts() const { return fFontSwitches; } 202 markDirty()203 void markDirty() override { 204 if (fState > kIndexed) { 205 fState = kIndexed; 206 } 207 } 208 209 int32_t unresolvedGlyphs() override; 210 std::unordered_set<SkUnichar> unresolvedCodepoints() override; 211 void addUnresolvedCodepoints(TextRange textRange); 212 213 void setState(InternalState state); getPicture()214 sk_sp<SkPicture> getPicture() { return fPicture; } 215 widthWithTrailingSpaces()216 SkScalar widthWithTrailingSpaces() { return fMaxWidthWithTrailingSpaces; } getMaxWidth()217 SkScalar getMaxWidth() { return fOldMaxWidth; } 218 219 void resetContext(); 220 void resolveStrut(); 221 222 bool computeCodeUnitProperties(); 223 void applySpacingAndBuildClusterTable(); 224 void buildClusterTable(); 225 bool shapeTextIntoEndlessLine(); 226 void positionShapedTextIntoLine(SkScalar maxWidth); 227 void breakShapedTextIntoLines(SkScalar maxWidth); 228 229 void updateTextAlign(TextAlign textAlign) override; 230 void updateFontSize(size_t from, size_t to, SkScalar fontSize) override; 231 void updateForegroundPaint(size_t from, size_t to, SkPaint paint) override; 232 void updateBackgroundPaint(size_t from, size_t to, SkPaint paint) override; 233 #ifdef OHOS_SUPPORT 234 std::vector<ParagraphPainter::PaintID> updateColor(size_t from, size_t to, SkColor color) override; 235 SkIRect generatePaintRegion(SkScalar x, SkScalar y) override; 236 #endif 237 238 void visit(const Visitor&) override; 239 240 void setIndents(const std::vector<SkScalar>& indents) override; 241 int getLineNumberAt(TextIndex codeUnitIndex) const override; 242 bool getLineMetricsAt(int lineNumber, LineMetrics* lineMetrics) const override; 243 TextRange getActualTextRange(int lineNumber, bool includeSpaces) const override; 244 bool getGlyphClusterAt(TextIndex codeUnitIndex, GlyphClusterInfo* glyphInfo) override; 245 bool getClosestGlyphClusterAt(SkScalar dx, 246 SkScalar dy, 247 GlyphClusterInfo* glyphInfo) override; 248 #ifndef USE_SKIA_TXT 249 SkFont getFontAt(TextIndex codeUnitIndex) const override; 250 #else 251 RSFont getFontAt(TextIndex codeUnitIndex) const override; 252 #endif 253 std::vector<FontInfo> getFonts() const override; 254 getEmptyMetrics()255 InternalLineMetrics getEmptyMetrics() const { return fEmptyMetrics; } getStrutMetrics()256 InternalLineMetrics getStrutMetrics() const { return fStrutMetrics; } 257 258 BlockRange findAllBlocks(TextRange textRange); 259 resetShifts()260 void resetShifts() { 261 for (auto& run : fRuns) { 262 run.resetJustificationShifts(); 263 } 264 } 265 resetAutoSpacing()266 void resetAutoSpacing() { 267 for (auto& run : fRuns) { 268 run.resetAutoSpacing(); 269 } 270 } 271 272 void scanTextCutPoint(const std::vector<TextCutRecord>& rawTextSize, size_t& start, size_t& end); 273 bool middleEllipsisDeal(); codeUnitHasProperty(size_t index,SkUnicode::CodeUnitFlags property)274 bool codeUnitHasProperty(size_t index, SkUnicode::CodeUnitFlags property) const { 275 return (fCodeUnitProperties[index] & property) == property; 276 } 277 getUnicode()278 SkUnicode* getUnicode() { return fUnicode.get(); } 279 280 SkScalar detectIndents(size_t index) override; 281 getTextSplitRatio()282 SkScalar getTextSplitRatio() const override { return fParagraphStyle.getTextSplitRatio(); } 283 284 #ifndef USE_SKIA_TXT 285 SkFontMetrics measureText() override; 286 #else 287 RSFontMetrics measureText() override; 288 #endif 289 getEllipsisState()290 bool &getEllipsisState() { return isMiddleEllipsis; } 291 292 #ifndef USE_SKIA_TXT 293 bool GetLineFontMetrics(const size_t lineNumber, size_t& charNumber, 294 std::vector<SkFontMetrics>& fontMetrics) override; 295 #else 296 bool GetLineFontMetrics(const size_t lineNumber, size_t& charNumber, 297 std::vector<RSFontMetrics>& fontMetrics) override; 298 #endif 299 300 std::vector<std::unique_ptr<TextLineBase>> GetTextLines() override; 301 std::unique_ptr<Paragraph> CloneSelf() override; 302 hash()303 uint32_t& hash() { 304 return hash_; 305 } 306 307 #ifdef OHOS_SUPPORT GetMaxLines()308 size_t GetMaxLines() const override { return fParagraphStyle.getMaxLines(); } 309 #endif 310 311 private: 312 friend class ParagraphBuilder; 313 friend class ParagraphCacheKey; 314 friend class ParagraphCacheValue; 315 friend class ParagraphCache; 316 317 friend class TextWrapper; 318 friend class OneLineShaper; 319 320 void computeEmptyMetrics(); 321 void middleEllipsisAddText(size_t charStart, 322 size_t charEnd, 323 SkScalar& allTextWidth, 324 SkScalar width, 325 bool isLeftToRight); 326 SkScalar resetEllipsisWidth(SkScalar ellipsisWidth, size_t& lastRunIndex, const size_t textIndex); 327 void scanRTLTextCutPoint(const std::vector<TextCutRecord>& rawTextSize, size_t& start, size_t& end); 328 void scanLTRTextCutPoint(const std::vector<TextCutRecord>& rawTextSize, size_t& start, size_t& end); 329 void prepareForMiddleEllipsis(SkScalar rawWidth); 330 bool shapeForMiddleEllipsis(SkScalar rawWidth); 331 TextRange resetRangeWithDeletedRange(const TextRange& sourceRange, 332 const TextRange& deletedRange, const size_t& ellSize); 333 void resetTextStyleRange(const TextRange& deletedRange); 334 void resetPlaceholderRange(const TextRange& deletedRange); setSize(SkScalar height,SkScalar width,SkScalar longestLine)335 void setSize(SkScalar height, SkScalar width, SkScalar longestLine) { 336 fHeight = height; 337 fWidth = width; 338 fLongestLine = longestLine; 339 } getSize(SkScalar & height,SkScalar & width,SkScalar & longestLine)340 void getSize(SkScalar& height, SkScalar& width, SkScalar& longestLine) { 341 height = fHeight; 342 width = fWidth; 343 longestLine = fLongestLine; 344 } setIntrinsicSize(SkScalar maxIntrinsicWidth,SkScalar minIntrinsicWidth,SkScalar alphabeticBaseline,SkScalar ideographicBaseline,bool exceededMaxLines)345 void setIntrinsicSize(SkScalar maxIntrinsicWidth, SkScalar minIntrinsicWidth, SkScalar alphabeticBaseline, 346 SkScalar ideographicBaseline, bool exceededMaxLines) { 347 fMaxIntrinsicWidth = maxIntrinsicWidth; 348 fMinIntrinsicWidth = minIntrinsicWidth; 349 fAlphabeticBaseline = alphabeticBaseline; 350 fIdeographicBaseline = ideographicBaseline; 351 fExceededMaxLines = exceededMaxLines; 352 } getIntrinsicSize(SkScalar & maxIntrinsicWidth,SkScalar & minIntrinsicWidth,SkScalar & alphabeticBaseline,SkScalar & ideographicBaseline,bool & exceededMaxLines)353 void getIntrinsicSize(SkScalar& maxIntrinsicWidth, SkScalar& minIntrinsicWidth, SkScalar& alphabeticBaseline, 354 SkScalar& ideographicBaseline, bool& exceededMaxLines) { 355 maxIntrinsicWidth = fMaxIntrinsicWidth; 356 minIntrinsicWidth = fMinIntrinsicWidth; 357 alphabeticBaseline = fAlphabeticBaseline ; 358 ideographicBaseline = fIdeographicBaseline; 359 exceededMaxLines = fExceededMaxLines; 360 } 361 362 #ifdef OHOS_SUPPORT 363 ParagraphPainter::PaintID updateTextStyleColorAndForeground(TextStyle& TextStyle, SkColor color); 364 TextBox getEmptyTextRect(RectHeightStyle rectHeightStyle) const; 365 #endif 366 367 // Input 368 SkTArray<StyleBlock<SkScalar>> fLetterSpaceStyles; 369 SkTArray<StyleBlock<SkScalar>> fWordSpaceStyles; 370 SkTArray<StyleBlock<SkPaint>> fBackgroundStyles; 371 SkTArray<StyleBlock<SkPaint>> fForegroundStyles; 372 SkTArray<StyleBlock<std::vector<TextShadow>>> fShadowStyles; 373 SkTArray<StyleBlock<Decoration>> fDecorationStyles; 374 SkTArray<Block, true> fTextStyles; // TODO: take out only the font stuff 375 SkTArray<Placeholder, true> fPlaceholders; 376 SkString fText; 377 std::vector<SkUnichar> fUnicodeText; 378 379 // Internal structures 380 InternalState fState; 381 SkTArray<Run, false> fRuns; // kShaped 382 SkTArray<Cluster, true> fClusters; // kClusterized (cached: text, word spacing, letter spacing, resolved fonts) 383 SkTArray<SkUnicode::CodeUnitFlags, true> fCodeUnitProperties; 384 SkTArray<size_t, true> fClustersIndexFromCodeUnit; 385 std::vector<size_t> fWords; 386 std::vector<SkScalar> fIndents; 387 std::vector<TextCutRecord> rtlTextSize; 388 std::vector<TextCutRecord> ltrTextSize; 389 std::vector<SkUnicode::BidiRegion> fBidiRegions; 390 // These two arrays are used in measuring methods (getRectsForRange, getGlyphPositionAtCoordinate) 391 // They are filled lazily whenever they need and cached 392 SkTArray<TextIndex, true> fUTF8IndexForUTF16Index; 393 SkTArray<size_t, true> fUTF16IndexForUTF8Index; 394 SkTArray<size_t, true> fUnicodeIndexForUTF8Index; 395 SkOnce fillUTF16MappingOnce; 396 size_t fUnresolvedGlyphs; 397 bool isMiddleEllipsis; 398 std::unordered_set<SkUnichar> fUnresolvedCodepoints; 399 400 SkTArray<TextLine, false> fLines; // kFormatted (cached: width, max lines, ellipsis, text align) 401 sk_sp<SkPicture> fPicture; // kRecorded (cached: text styles) 402 403 SkTArray<ResolvedFontDescriptor> fFontSwitches; 404 405 InternalLineMetrics fEmptyMetrics; 406 InternalLineMetrics fStrutMetrics; 407 408 SkScalar fOldWidth; 409 SkScalar fOldHeight; 410 SkScalar fMaxWidthWithTrailingSpaces; 411 SkScalar fOldMaxWidth; 412 SkScalar allTextWidth; 413 std::shared_ptr<SkUnicode> fUnicode; 414 bool fHasLineBreaks; 415 bool fHasWhitespacesInside; 416 TextIndex fTrailingSpaces; 417 SkScalar fLayoutRawWidth {0}; 418 419 size_t fLineNumber; 420 uint32_t hash_{0u}; 421 422 #ifdef OHOS_SUPPORT 423 std::optional<SkRect> fPaintRegion; 424 #endif 425 }; 426 } // namespace textlayout 427 } // namespace skia 428 429 430 #endif // ParagraphImpl_DEFINED 431