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 #ifndef OHOS_SUPPORT 80 enum InternalState { 81 kUnknown = 0, 82 kIndexed = 1, // Text is indexed 83 kShaped = 2, // Text is shaped 84 kLineBroken = 5, 85 kFormatted = 6, 86 kDrawn = 7 87 }; 88 #endif 89 90 /* 91 struct BidiRegion { 92 BidiRegion(size_t start, size_t end, uint8_t dir) 93 : text(start, end), direction(dir) { } 94 TextRange text; 95 uint8_t direction; 96 }; 97 */ 98 class ParagraphImpl final : public Paragraph { 99 100 public: 101 102 ParagraphImpl() = default; 103 104 ParagraphImpl(const SkString& text, 105 ParagraphStyle style, 106 SkTArray<Block, true> blocks, 107 SkTArray<Placeholder, true> placeholders, 108 sk_sp<FontCollection> fonts, 109 std::shared_ptr<SkUnicode> unicode); 110 111 ParagraphImpl(const std::u16string& utf16text, 112 ParagraphStyle style, 113 SkTArray<Block, true> blocks, 114 SkTArray<Placeholder, true> placeholders, 115 sk_sp<FontCollection> fonts, 116 std::shared_ptr<SkUnicode> unicode); 117 118 ~ParagraphImpl() override; 119 120 void layout(SkScalar width) override; 121 void paint(SkCanvas* canvas, SkScalar x, SkScalar y) override; 122 void paint(ParagraphPainter* canvas, SkScalar x, SkScalar y) override; 123 void paint(ParagraphPainter* canvas, RSPath* path, SkScalar hOffset, SkScalar vOffset) override; 124 std::vector<TextBox> getRectsForRange(unsigned start, 125 unsigned end, 126 RectHeightStyle rectHeightStyle, 127 RectWidthStyle rectWidthStyle) override; 128 std::vector<TextBox> getRectsForPlaceholders() override; 129 void getLineMetrics(std::vector<LineMetrics>&) override; 130 PositionWithAffinity getGlyphPositionAtCoordinate(SkScalar dx, SkScalar dy) override; 131 SkRange<size_t> getWordBoundary(unsigned offset) override; 132 getApplyRoundingHack()133 bool getApplyRoundingHack() const { return false; } 134 lineNumber()135 size_t lineNumber() override { return fLineNumber; } 136 137 #ifdef OHOS_SUPPORT 138 TextRange getEllipsisTextRange() override; isRunCombinated()139 bool isRunCombinated() const override { return fRuns.size() < fTextStyles.size(); } 140 std::string GetDumpInfo() const override; 141 #endif 142 143 TextLine& addLine(SkVector offset, SkVector advance, 144 TextRange textExcludingSpaces, TextRange text, TextRange textIncludingNewlines, 145 ClusterRange clusters, ClusterRange clustersWithGhosts, SkScalar widthWithSpaces, 146 InternalLineMetrics sizes); 147 text()148 SkSpan<const char> text() const { return SkSpan<const char>(fText.c_str(), fText.size()); } 149 #ifdef OHOS_SUPPORT 150 std::vector<SkUnichar> convertUtf8ToUnicode(const SkString& utf8); 151 std::unique_ptr<Paragraph> createCroppedCopy( 152 size_t startIndex, size_t count = std::numeric_limits<size_t>::max()) override; 153 void initUnicodeText() override; unicodeText()154 const std::vector<SkUnichar>& unicodeText() const override { return fUnicodeText; } getUnicodeIndex(TextIndex index)155 size_t getUnicodeIndex(TextIndex index) const override { 156 if (index >= fUnicodeIndexForUTF8Index.size()) { 157 return fUnicodeIndexForUTF8Index.empty() ? 0 : fUnicodeIndexForUTF8Index.back() + 1; 158 } 159 return fUnicodeIndexForUTF8Index[index]; 160 } 161 #else unicodeText()162 const std::vector<SkUnichar>& unicodeText() const { return fUnicodeText; } getUnicodeIndex(TextIndex index)163 size_t getUnicodeIndex(TextIndex index) const { 164 if (index >= fUnicodeIndexForUTF8Index.size()) { 165 return fUnicodeIndexForUTF8Index.empty() ? 0 : fUnicodeIndexForUTF8Index.back() + 1; 166 } 167 return fUnicodeIndexForUTF8Index[index]; 168 } 169 #endif state()170 InternalState state() const { return fState; } runs()171 SkSpan<Run> runs() { return SkSpan<Run>(fRuns.data(), fRuns.size()); } styles()172 SkSpan<Block> styles() { 173 return SkSpan<Block>(fTextStyles.data(), fTextStyles.size()); 174 } placeholders()175 SkSpan<Placeholder> placeholders() { 176 return SkSpan<Placeholder>(fPlaceholders.data(), fPlaceholders.size()); 177 } lines()178 SkSpan<TextLine> lines() { return SkSpan<TextLine>(fLines.data(), fLines.size()); } paragraphStyle()179 const ParagraphStyle& paragraphStyle() const { return fParagraphStyle; } clusters()180 SkSpan<Cluster> clusters() { return SkSpan<Cluster>(fClusters.begin(), fClusters.size()); } fontCollection()181 sk_sp<FontCollection> fontCollection() const { return fFontCollection; } 182 void formatLines(SkScalar maxWidth); 183 void ensureUTF16Mapping(); 184 SkTArray<TextIndex> countSurroundingGraphemes(TextRange textRange) const; 185 TextIndex findNextGraphemeBoundary(TextIndex utf8) const; 186 TextIndex findPreviousGraphemeBoundary(TextIndex utf8) const; 187 TextIndex findNextGlyphClusterBoundary(TextIndex utf8) const; 188 TextIndex findPreviousGlyphClusterBoundary(TextIndex utf8) const; getUTF16Index(TextIndex index)189 size_t getUTF16Index(TextIndex index) const { 190 return fUTF16IndexForUTF8Index[index]; 191 } 192 193 #ifdef OHOS_SUPPORT getUTF16IndexWithOverflowCheck(TextIndex index)194 size_t getUTF16IndexWithOverflowCheck(TextIndex index) const { 195 if (index >= fUTF16IndexForUTF8Index.size()) { 196 // This branch is entered only if the index of the ellipsis exceeds the size of the fUTF16IndexForUTF8Index 197 return fUTF16IndexForUTF8Index.back(); 198 } 199 return fUTF16IndexForUTF8Index[index]; 200 } getText()201 const SkString& getText() const { return fText; } 202 #endif 203 strutEnabled()204 bool strutEnabled() const { return paragraphStyle().getStrutStyle().getStrutEnabled(); } strutForceHeight()205 bool strutForceHeight() const { 206 return paragraphStyle().getStrutStyle().getForceStrutHeight(); 207 } strutHeightOverride()208 bool strutHeightOverride() const { 209 return paragraphStyle().getStrutStyle().getHeightOverride(); 210 } strutMetrics()211 InternalLineMetrics strutMetrics() const { return fStrutMetrics; } 212 213 SkString getEllipsis() const; 214 WordBreakType getWordBreakType() const; 215 LineBreakStrategy getLineBreakStrategy() const; 216 217 SkSpan<const char> text(TextRange textRange); 218 SkSpan<Cluster> clusters(ClusterRange clusterRange); 219 Cluster& cluster(ClusterIndex clusterIndex); clusterIndex(TextIndex textIndex)220 ClusterIndex clusterIndex(TextIndex textIndex) { 221 auto clusterIndex = this->fClustersIndexFromCodeUnit[textIndex]; 222 SkASSERT(clusterIndex != EMPTY_INDEX); 223 return clusterIndex; 224 } run(RunIndex runIndex)225 Run& run(RunIndex runIndex) { 226 SkASSERT(runIndex < SkToSizeT(fRuns.size())); 227 return fRuns[runIndex]; 228 } 229 230 Run& runByCluster(ClusterIndex clusterIndex); 231 SkSpan<Block> blocks(BlockRange blockRange); 232 Block& block(BlockIndex blockIndex); resolvedFonts()233 SkTArray<ResolvedFontDescriptor> resolvedFonts() const { return fFontSwitches; } 234 markDirty()235 void markDirty() override { 236 if (fState > kIndexed) { 237 fState = kIndexed; 238 } 239 } 240 241 int32_t unresolvedGlyphs() override; 242 std::unordered_set<SkUnichar> unresolvedCodepoints() override; 243 void addUnresolvedCodepoints(TextRange textRange); 244 245 #ifdef OHOS_SUPPORT 246 void setState(InternalState state) override; getState()247 InternalState getState() const override { return state(); } 248 std::vector<TextBlobRecordInfo> getTextBlobRecordInfo() override; hasSkipTextBlobDrawing()249 bool hasSkipTextBlobDrawing() const override { return fSkipTextBlobDrawing; } setSkipTextBlobDrawing(bool state)250 void setSkipTextBlobDrawing(bool state) override { fSkipTextBlobDrawing = state; } 251 bool canPaintAllText() const override; 252 #else 253 void setState(InternalState state); 254 #endif 255 getPicture()256 sk_sp<SkPicture> getPicture() { return fPicture; } 257 widthWithTrailingSpaces()258 SkScalar widthWithTrailingSpaces() { return fMaxWidthWithTrailingSpaces; } 259 260 void resetContext(); 261 void resolveStrut(); 262 263 bool computeCodeUnitProperties(); 264 void applySpacingAndBuildClusterTable(); 265 void buildClusterTable(); 266 bool shapeTextIntoEndlessLine(); 267 void positionShapedTextIntoLine(SkScalar maxWidth); 268 void breakShapedTextIntoLines(SkScalar maxWidth); 269 270 void updateTextAlign(TextAlign textAlign) override; 271 void updateFontSize(size_t from, size_t to, SkScalar fontSize) override; 272 void updateForegroundPaint(size_t from, size_t to, SkPaint paint) override; 273 void updateBackgroundPaint(size_t from, size_t to, SkPaint paint) override; 274 #ifdef OHOS_SUPPORT 275 std::vector<ParagraphPainter::PaintID> updateColor(size_t from, size_t to, SkColor color, 276 UtfEncodeType encodeType) override; 277 SkIRect generatePaintRegion(SkScalar x, SkScalar y) override; exportTextStyles()278 SkTArray<Block, true>& exportTextStyles() override { return fTextStyles; } 279 bool preCalculateSingleRunAutoSpaceWidth(SkScalar floorWidth); 280 bool isAutoSpaceEnabled() const; 281 SkScalar clusterUsingAutoSpaceWidth(const Cluster& cluster) const; 282 void updateSplitRunClusterInfo(const Run& run, bool isSplitRun); 283 void refreshLines(); 284 bool isTailOfLineNeedSplit(const Run& lineLastRun, size_t lineEnd, bool hasGenerated); 285 void generateSplitPoint( 286 std::vector<SplitPoint>& splitPoints, const Run& run, ClusterRange lineRange, size_t lineIndex); 287 void generateSplitPoints(std::vector<SplitPoint>& splitPoints); 288 void generateRunsBySplitPoints(std::vector<SplitPoint>& splitPoints, SkTArray<Run, false>& runs); 289 void splitRuns(); 290 #endif 291 292 void visit(const Visitor&) override; 293 294 void setIndents(const std::vector<SkScalar>& indents) override; 295 int getLineNumberAt(TextIndex codeUnitIndex) const override; 296 bool getLineMetricsAt(int lineNumber, LineMetrics* lineMetrics) const override; 297 TextRange getActualTextRange(int lineNumber, bool includeSpaces) const override; 298 bool getGlyphClusterAt(TextIndex codeUnitIndex, GlyphClusterInfo* glyphInfo) override; 299 bool getClosestGlyphClusterAt(SkScalar dx, 300 SkScalar dy, 301 GlyphClusterInfo* glyphInfo) override; 302 #ifndef USE_SKIA_TXT 303 SkFont getFontAt(TextIndex codeUnitIndex) const override; 304 #else 305 RSFont getFontAt(TextIndex codeUnitIndex) const override; 306 #endif 307 std::vector<FontInfo> getFonts() const override; 308 getEmptyMetrics()309 InternalLineMetrics getEmptyMetrics() const { return fEmptyMetrics; } getStrutMetrics()310 InternalLineMetrics getStrutMetrics() const { return fStrutMetrics; } 311 312 BlockRange findAllBlocks(TextRange textRange); 313 resetShifts()314 void resetShifts() { 315 for (auto& run : fRuns) { 316 run.resetJustificationShifts(); 317 } 318 } 319 resetAutoSpacing()320 void resetAutoSpacing() { 321 for (auto& run : fRuns) { 322 run.resetAutoSpacing(); 323 } 324 } 325 codeUnitHasProperty(size_t index,SkUnicode::CodeUnitFlags property)326 bool codeUnitHasProperty(size_t index, SkUnicode::CodeUnitFlags property) const { 327 return (fCodeUnitProperties[index] & property) == property; 328 } 329 getUnicode()330 SkUnicode* getUnicode() { return fUnicode.get(); } 331 332 SkScalar detectIndents(size_t index) override; 333 getTextSplitRatio()334 SkScalar getTextSplitRatio() const override { return fParagraphStyle.getTextSplitRatio(); } 335 336 #ifndef USE_SKIA_TXT 337 SkFontMetrics measureText() override; 338 #else 339 RSFontMetrics measureText() override; 340 #endif 341 342 #ifdef OHOS_SUPPORT 343 bool needCreateMiddleEllipsis(); 344 Placeholder* getPlaceholderByIndex(size_t placeholderIndex); 345 bool IsPlaceholderAlignedFollowParagraph(size_t placeholderIndex); 346 bool setPlaceholderAlignment(size_t placeholderIndex, PlaceholderAlignment alignment); 347 Block& getBlockByRun(const Run& run); 348 #endif 349 #ifndef USE_SKIA_TXT 350 bool GetLineFontMetrics(const size_t lineNumber, size_t& charNumber, 351 std::vector<SkFontMetrics>& fontMetrics) override; 352 #else 353 bool GetLineFontMetrics(const size_t lineNumber, size_t& charNumber, 354 std::vector<RSFontMetrics>& fontMetrics) override; 355 #endif 356 357 std::vector<std::unique_ptr<TextLineBase>> GetTextLines() override; 358 std::unique_ptr<Paragraph> CloneSelf() override; 359 hash()360 uint32_t& hash() { 361 return hash_; 362 } 363 364 #ifdef OHOS_SUPPORT GetMaxLines()365 size_t GetMaxLines() const override { return fParagraphStyle.getMaxLines(); } setLastAutoSpacingFlag(Cluster::AutoSpacingFlag flag)366 void setLastAutoSpacingFlag(Cluster::AutoSpacingFlag flag) { fLastAutoSpacingFlag = flag; } getLastAutoSpacingFlag()367 const Cluster::AutoSpacingFlag& getLastAutoSpacingFlag() const { return fLastAutoSpacingFlag; } 368 #endif 369 370 private: 371 friend class ParagraphBuilder; 372 friend class ParagraphCacheKey; 373 friend class ParagraphCacheValue; 374 friend class ParagraphCache; 375 #ifdef OHOS_SUPPORT 376 friend struct TextWrapScorer; 377 #endif 378 friend class TextWrapper; 379 friend class OneLineShaper; 380 void computeEmptyMetrics(); 381 382 TextRange resetRangeWithDeletedRange(const TextRange& sourceRange, 383 const TextRange& deletedRange, const size_t& ellSize); 384 void resetTextStyleRange(const TextRange& deletedRange); 385 void resetPlaceholderRange(const TextRange& deletedRange); setSize(SkScalar height,SkScalar width,SkScalar longestLine)386 void setSize(SkScalar height, SkScalar width, SkScalar longestLine) { 387 fHeight = height; 388 fWidth = width; 389 fLongestLine = longestLine; 390 } getSize(SkScalar & height,SkScalar & width,SkScalar & longestLine)391 void getSize(SkScalar& height, SkScalar& width, SkScalar& longestLine) { 392 height = fHeight; 393 width = fWidth; 394 longestLine = fLongestLine; 395 } setIntrinsicSize(SkScalar maxIntrinsicWidth,SkScalar minIntrinsicWidth,SkScalar alphabeticBaseline,SkScalar ideographicBaseline,bool exceededMaxLines)396 void setIntrinsicSize(SkScalar maxIntrinsicWidth, SkScalar minIntrinsicWidth, SkScalar alphabeticBaseline, 397 SkScalar ideographicBaseline, bool exceededMaxLines) { 398 fMaxIntrinsicWidth = maxIntrinsicWidth; 399 fMinIntrinsicWidth = minIntrinsicWidth; 400 fAlphabeticBaseline = alphabeticBaseline; 401 fIdeographicBaseline = ideographicBaseline; 402 fExceededMaxLines = exceededMaxLines; 403 } getIntrinsicSize(SkScalar & maxIntrinsicWidth,SkScalar & minIntrinsicWidth,SkScalar & alphabeticBaseline,SkScalar & ideographicBaseline,bool & exceededMaxLines)404 void getIntrinsicSize(SkScalar& maxIntrinsicWidth, SkScalar& minIntrinsicWidth, SkScalar& alphabeticBaseline, 405 SkScalar& ideographicBaseline, bool& exceededMaxLines) { 406 maxIntrinsicWidth = fMaxIntrinsicWidth; 407 minIntrinsicWidth = fMinIntrinsicWidth; 408 alphabeticBaseline = fAlphabeticBaseline ; 409 ideographicBaseline = fIdeographicBaseline; 410 exceededMaxLines = fExceededMaxLines; 411 } 412 413 #ifdef OHOS_SUPPORT 414 ParagraphPainter::PaintID updateTextStyleColorAndForeground(TextStyle& TextStyle, SkColor color); 415 TextBox getEmptyTextRect(RectHeightStyle rectHeightStyle) const; 416 size_t prefixByteCountUntilChar(size_t index); 417 void copyProperties(const ParagraphImpl& source); 418 std::string_view GetState() const; 419 #endif 420 421 // Input 422 SkTArray<StyleBlock<SkScalar>> fLetterSpaceStyles; 423 SkTArray<StyleBlock<SkScalar>> fWordSpaceStyles; 424 SkTArray<StyleBlock<SkPaint>> fBackgroundStyles; 425 SkTArray<StyleBlock<SkPaint>> fForegroundStyles; 426 SkTArray<StyleBlock<std::vector<TextShadow>>> fShadowStyles; 427 SkTArray<StyleBlock<Decoration>> fDecorationStyles; 428 SkTArray<Block, true> fTextStyles; // TODO: take out only the font stuff 429 SkTArray<Placeholder, true> fPlaceholders; 430 SkString fText; 431 std::vector<SkUnichar> fUnicodeText; 432 433 // Internal structures 434 InternalState fState; 435 SkTArray<Run, false> fRuns; // kShaped 436 SkTArray<Cluster, true> fClusters; // kClusterized (cached: text, word spacing, letter spacing, resolved fonts) 437 SkTArray<SkUnicode::CodeUnitFlags, true> fCodeUnitProperties; 438 SkTArray<size_t, true> fClustersIndexFromCodeUnit; 439 std::vector<size_t> fWords; 440 std::vector<SkScalar> fIndents; 441 std::vector<SkUnicode::BidiRegion> fBidiRegions; 442 // These two arrays are used in measuring methods (getRectsForRange, getGlyphPositionAtCoordinate) 443 // They are filled lazily whenever they need and cached 444 SkTArray<TextIndex, true> fUTF8IndexForUTF16Index; 445 SkTArray<size_t, true> fUTF16IndexForUTF8Index; 446 SkTArray<size_t, true> fUnicodeIndexForUTF8Index; 447 SkOnce fillUTF16MappingOnce; 448 size_t fUnresolvedGlyphs; 449 std::unordered_set<SkUnichar> fUnresolvedCodepoints; 450 451 SkTArray<TextLine, false> fLines; // kFormatted (cached: width, max lines, ellipsis, text align) 452 sk_sp<SkPicture> fPicture; // kRecorded (cached: text styles) 453 454 SkTArray<ResolvedFontDescriptor> fFontSwitches; 455 456 InternalLineMetrics fEmptyMetrics; 457 InternalLineMetrics fStrutMetrics; 458 459 SkScalar fOldWidth; 460 SkScalar fOldHeight; 461 SkScalar fMaxWidthWithTrailingSpaces; 462 std::shared_ptr<SkUnicode> fUnicode; 463 bool fHasLineBreaks; 464 bool fHasWhitespacesInside; 465 TextIndex fTrailingSpaces; 466 SkScalar fLayoutRawWidth {0}; 467 468 size_t fLineNumber { 0 }; 469 uint32_t hash_{0u}; 470 471 #ifdef OHOS_SUPPORT 472 TextRange fEllipsisRange{EMPTY_RANGE}; 473 std::optional<SkRect> fPaintRegion; 474 // just for building cluster table, record the last built unicode autospacing flag; 475 Cluster::AutoSpacingFlag fLastAutoSpacingFlag; 476 bool fSkipTextBlobDrawing{false}; 477 #endif 478 }; 479 } // namespace textlayout 480 } // namespace skia 481 482 483 #endif // ParagraphImpl_DEFINED 484