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/TextShadow.h" 25 #include "modules/skparagraph/include/TextStyle.h" 26 #include "modules/skparagraph/src/Run.h" 27 #include "modules/skparagraph/src/TextLine.h" 28 #include "modules/skunicode/include/SkUnicode.h" 29 #include "include/private/SkTHash.h" 30 #include <hilog/log.h> 31 32 #include <memory> 33 #include <string> 34 #include <vector> 35 36 class SkCanvas; 37 38 namespace skia { 39 namespace textlayout { 40 #define LOGD(fmt, ...) \ 41 ::OHOS::HiviewDFX::HiLog::Debug(::OHOS::HiviewDFX::HiLogLabel \ 42 { LOG_CORE, 0xD001402, "2DGraphics" }, "%{public}s: " fmt, __func__, ##__VA_ARGS__) 43 44 class LineMetrics; 45 class TextLine; 46 47 template <typename T> bool operator==(const SkSpan<T>& a, const SkSpan<T>& b) { 48 return a.size() == b.size() && a.begin() == b.begin(); 49 } 50 51 template <typename T> bool operator<=(const SkSpan<T>& a, const SkSpan<T>& b) { 52 return a.begin() >= b.begin() && a.end() <= b.end(); 53 } 54 55 template <typename TStyle> 56 struct StyleBlock { StyleBlockStyleBlock57 StyleBlock() : fRange(EMPTY_RANGE), fStyle() { } StyleBlockStyleBlock58 StyleBlock(size_t start, size_t end, const TStyle& style) : fRange(start, end), fStyle(style) {} StyleBlockStyleBlock59 StyleBlock(TextRange textRange, const TStyle& style) : fRange(textRange), fStyle(style) {} addStyleBlock60 void add(TextRange tail) { 61 SkASSERT(fRange.end == tail.start); 62 fRange = TextRange(fRange.start, fRange.start + fRange.width() + tail.width()); 63 } 64 TextRange fRange; 65 TStyle fStyle; 66 }; 67 68 struct ResolvedFontDescriptor { 69 ResolvedFontDescriptorResolvedFontDescriptor70 ResolvedFontDescriptor(TextIndex index, SkFont font) 71 : fFont(font), fTextStart(index) { } 72 SkFont fFont; 73 TextIndex fTextStart; 74 }; 75 76 enum InternalState { 77 kUnknown = 0, 78 kIndexed = 1, // Text is indexed 79 kShaped = 2, // Text is shaped 80 kLineBroken = 5, 81 kFormatted = 6, 82 kDrawn = 7 83 }; 84 85 /* 86 struct BidiRegion { 87 BidiRegion(size_t start, size_t end, uint8_t dir) 88 : text(start, end), direction(dir) { } 89 TextRange text; 90 uint8_t direction; 91 }; 92 */ 93 class ParagraphImpl final : public Paragraph { 94 95 public: 96 97 ParagraphImpl(const SkString& text, 98 ParagraphStyle style, 99 SkTArray<Block, true> blocks, 100 SkTArray<Placeholder, true> placeholders, 101 sk_sp<FontCollection> fonts, 102 std::shared_ptr<SkUnicode> unicode); 103 104 ParagraphImpl(const std::u16string& utf16text, 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() override; 112 113 void layout(SkScalar width) override; 114 void paint(SkCanvas* canvas, SkScalar x, SkScalar y) override; 115 void paint(ParagraphPainter* canvas, SkScalar x, SkScalar y) override; 116 std::vector<TextBox> getRectsForRange(unsigned start, 117 unsigned end, 118 RectHeightStyle rectHeightStyle, 119 RectWidthStyle rectWidthStyle) override; 120 std::vector<TextBox> getRectsForPlaceholders() override; 121 void getLineMetrics(std::vector<LineMetrics>&) override; 122 PositionWithAffinity getGlyphPositionAtCoordinate(SkScalar dx, SkScalar dy) override; 123 SkRange<size_t> getWordBoundary(unsigned offset) override; 124 getApplyRoundingHack()125 bool getApplyRoundingHack() const { return false; } 126 lineNumber()127 size_t lineNumber() override { return fLineNumber; } 128 129 TextLine& addLine(SkVector offset, SkVector advance, 130 TextRange textExcludingSpaces, TextRange text, TextRange textIncludingNewlines, 131 ClusterRange clusters, ClusterRange clustersWithGhosts, SkScalar widthWithSpaces, 132 InternalLineMetrics sizes); 133 text()134 SkSpan<const char> text() const { return SkSpan<const char>(fText.c_str(), fText.size()); } state()135 InternalState state() const { return fState; } runs()136 SkSpan<Run> runs() { return SkSpan<Run>(fRuns.data(), fRuns.size()); } styles()137 SkSpan<Block> styles() { 138 return SkSpan<Block>(fTextStyles.data(), fTextStyles.size()); 139 } placeholders()140 SkSpan<Placeholder> placeholders() { 141 return SkSpan<Placeholder>(fPlaceholders.data(), fPlaceholders.size()); 142 } lines()143 SkSpan<TextLine> lines() { return SkSpan<TextLine>(fLines.data(), fLines.size()); } paragraphStyle()144 const ParagraphStyle& paragraphStyle() const { return fParagraphStyle; } clusters()145 SkSpan<Cluster> clusters() { return SkSpan<Cluster>(fClusters.begin(), fClusters.size()); } fontCollection()146 sk_sp<FontCollection> fontCollection() const { return fFontCollection; } 147 void formatLines(SkScalar maxWidth); 148 void ensureUTF16Mapping(); 149 SkTArray<TextIndex> countSurroundingGraphemes(TextRange textRange) const; 150 TextIndex findNextGraphemeBoundary(TextIndex utf8) const; 151 TextIndex findPreviousGraphemeBoundary(TextIndex utf8) const; 152 TextIndex findNextGlyphClusterBoundary(TextIndex utf8) const; 153 TextIndex findPreviousGlyphClusterBoundary(TextIndex utf8) const; getUTF16Index(TextIndex index)154 size_t getUTF16Index(TextIndex index) const { 155 return fUTF16IndexForUTF8Index[index]; 156 } 157 strutEnabled()158 bool strutEnabled() const { return paragraphStyle().getStrutStyle().getStrutEnabled(); } strutForceHeight()159 bool strutForceHeight() const { 160 return paragraphStyle().getStrutStyle().getForceStrutHeight(); 161 } strutHeightOverride()162 bool strutHeightOverride() const { 163 return paragraphStyle().getStrutStyle().getHeightOverride(); 164 } strutMetrics()165 InternalLineMetrics strutMetrics() const { return fStrutMetrics; } 166 167 SkString getEllipsis() const; 168 WordBreakType getWordBreakType() const; 169 170 SkSpan<const char> text(TextRange textRange); 171 SkSpan<Cluster> clusters(ClusterRange clusterRange); 172 Cluster& cluster(ClusterIndex clusterIndex); clusterIndex(TextIndex textIndex)173 ClusterIndex clusterIndex(TextIndex textIndex) { 174 auto clusterIndex = this->fClustersIndexFromCodeUnit[textIndex]; 175 SkASSERT(clusterIndex != EMPTY_INDEX); 176 return clusterIndex; 177 } run(RunIndex runIndex)178 Run& run(RunIndex runIndex) { 179 SkASSERT(runIndex < SkToSizeT(fRuns.size())); 180 return fRuns[runIndex]; 181 } 182 183 Run& runByCluster(ClusterIndex clusterIndex); 184 SkSpan<Block> blocks(BlockRange blockRange); 185 Block& block(BlockIndex blockIndex); resolvedFonts()186 SkTArray<ResolvedFontDescriptor> resolvedFonts() const { return fFontSwitches; } 187 markDirty()188 void markDirty() override { 189 if (fState > kIndexed) { 190 fState = kIndexed; 191 } 192 } 193 194 int32_t unresolvedGlyphs() override; 195 std::unordered_set<SkUnichar> unresolvedCodepoints() override; 196 void addUnresolvedCodepoints(TextRange textRange); 197 198 void setState(InternalState state); getPicture()199 sk_sp<SkPicture> getPicture() { return fPicture; } 200 widthWithTrailingSpaces()201 SkScalar widthWithTrailingSpaces() { return fMaxWidthWithTrailingSpaces; } getMaxWidth()202 SkScalar getMaxWidth() { return fOldMaxWidth; } 203 204 void resetContext(); 205 void resolveStrut(); 206 207 bool computeCodeUnitProperties(); 208 void applySpacingAndBuildClusterTable(); 209 void buildClusterTable(); 210 bool shapeTextIntoEndlessLine(); 211 void breakShapedTextIntoLines(SkScalar maxWidth); 212 213 void updateTextAlign(TextAlign textAlign) override; 214 void updateFontSize(size_t from, size_t to, SkScalar fontSize) override; 215 void updateForegroundPaint(size_t from, size_t to, SkPaint paint) override; 216 void updateBackgroundPaint(size_t from, size_t to, SkPaint paint) override; 217 218 void visit(const Visitor&) override; 219 220 void setIndents(const std::vector<SkScalar>& indents) override; 221 int getLineNumberAt(TextIndex codeUnitIndex) const override; 222 bool getLineMetricsAt(int lineNumber, LineMetrics* lineMetrics) const override; 223 TextRange getActualTextRange(int lineNumber, bool includeSpaces) const override; 224 bool getGlyphClusterAt(TextIndex codeUnitIndex, GlyphClusterInfo* glyphInfo) override; 225 bool getClosestGlyphClusterAt(SkScalar dx, 226 SkScalar dy, 227 GlyphClusterInfo* glyphInfo) override; 228 SkFont getFontAt(TextIndex codeUnitIndex) const override; 229 std::vector<FontInfo> getFonts() const override; 230 getEmptyMetrics()231 InternalLineMetrics getEmptyMetrics() const { return fEmptyMetrics; } getStrutMetrics()232 InternalLineMetrics getStrutMetrics() const { return fStrutMetrics; } 233 234 BlockRange findAllBlocks(TextRange textRange); 235 resetShifts()236 void resetShifts() { 237 for (auto& run : fRuns) { 238 run.resetJustificationShifts(); 239 } 240 } 241 242 void scanTextCutPoint(const std::vector<TextCutRecord>& rawTextSize, size_t& start, size_t& end); 243 void middleEllipsisDeal(); codeUnitHasProperty(size_t index,SkUnicode::CodeUnitFlags property)244 bool codeUnitHasProperty(size_t index, SkUnicode::CodeUnitFlags property) const { 245 return (fCodeUnitProperties[index] & property) == property; 246 } 247 getUnicode()248 SkUnicode* getUnicode() { return fUnicode.get(); } 249 250 SkScalar detectIndents(size_t index); 251 getTextSplitRatio()252 SkScalar getTextSplitRatio() const override { return fParagraphStyle.getTextSplitRatio(); } 253 254 SkFontMetrics measureText() override; 255 getEllipsisState()256 bool &getEllipsisState() { return isMiddleEllipsis; } 257 private: 258 friend class ParagraphBuilder; 259 friend class ParagraphCacheKey; 260 friend class ParagraphCacheValue; 261 friend class ParagraphCache; 262 263 friend class TextWrapper; 264 friend class OneLineShaper; 265 266 void computeEmptyMetrics(); 267 void middleEllipsisAddText(size_t charStart, 268 size_t charEnd, 269 SkScalar& allTextWidth, 270 SkScalar width, 271 bool isLeftToRight); 272 void setRunTimeEllipsisWidthForMiddleEllipsis(); 273 void scanRTLTextCutPoint(const std::vector<TextCutRecord>& rawTextSize, size_t& start, size_t& end); 274 void scanLTRTextCutPoint(const std::vector<TextCutRecord>& rawTextSize, size_t& start, size_t& end); 275 276 // Input 277 SkTArray<StyleBlock<SkScalar>> fLetterSpaceStyles; 278 SkTArray<StyleBlock<SkScalar>> fWordSpaceStyles; 279 SkTArray<StyleBlock<SkPaint>> fBackgroundStyles; 280 SkTArray<StyleBlock<SkPaint>> fForegroundStyles; 281 SkTArray<StyleBlock<std::vector<TextShadow>>> fShadowStyles; 282 SkTArray<StyleBlock<Decoration>> fDecorationStyles; 283 SkTArray<Block, true> fTextStyles; // TODO: take out only the font stuff 284 SkTArray<Placeholder, true> fPlaceholders; 285 SkString fText; 286 287 // Internal structures 288 InternalState fState; 289 SkTArray<Run, false> fRuns; // kShaped 290 SkTArray<Cluster, true> fClusters; // kClusterized (cached: text, word spacing, letter spacing, resolved fonts) 291 SkTArray<SkUnicode::CodeUnitFlags, true> fCodeUnitProperties; 292 SkTArray<size_t, true> fClustersIndexFromCodeUnit; 293 std::vector<size_t> fWords; 294 std::vector<SkScalar> fIndents; 295 std::vector<TextCutRecord> rtlTextSize; 296 std::vector<TextCutRecord> ltrTextSize; 297 std::vector<SkUnicode::BidiRegion> fBidiRegions; 298 // These two arrays are used in measuring methods (getRectsForRange, getGlyphPositionAtCoordinate) 299 // They are filled lazily whenever they need and cached 300 SkTArray<TextIndex, true> fUTF8IndexForUTF16Index; 301 SkTArray<size_t, true> fUTF16IndexForUTF8Index; 302 SkOnce fillUTF16MappingOnce; 303 size_t fUnresolvedGlyphs; 304 bool isMiddleEllipsis; 305 std::unordered_set<SkUnichar> fUnresolvedCodepoints; 306 307 SkTArray<TextLine, false> fLines; // kFormatted (cached: width, max lines, ellipsis, text align) 308 sk_sp<SkPicture> fPicture; // kRecorded (cached: text styles) 309 310 SkTArray<ResolvedFontDescriptor> fFontSwitches; 311 312 InternalLineMetrics fEmptyMetrics; 313 InternalLineMetrics fStrutMetrics; 314 315 SkScalar fOldWidth; 316 SkScalar fOldHeight; 317 SkScalar runTimeEllipsisWidth; 318 SkScalar fMaxWidthWithTrailingSpaces; 319 SkScalar fOldMaxWidth; 320 SkScalar allTextWidth; 321 std::shared_ptr<SkUnicode> fUnicode; 322 bool fHasLineBreaks; 323 bool fHasWhitespacesInside; 324 TextIndex fTrailingSpaces; 325 326 size_t fLineNumber; 327 }; 328 } // namespace textlayout 329 } // namespace skia 330 331 332 #endif // ParagraphImpl_DEFINED 333