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/base/SkOnce.h" 17 #include "include/private/base/SkTArray.h" 18 #include "include/private/base/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 "src/core/SkTHash.h" 30 31 #include <memory> 32 #include <string> 33 #include <vector> 34 35 class SkCanvas; 36 37 namespace skia { 38 namespace textlayout { 39 40 class LineMetrics; 41 class TextLine; 42 43 template <typename T> bool operator==(const SkSpan<T>& a, const SkSpan<T>& b) { 44 return a.size() == b.size() && a.begin() == b.begin(); 45 } 46 47 template <typename T> bool operator<=(const SkSpan<T>& a, const SkSpan<T>& b) { 48 return a.begin() >= b.begin() && a.end() <= b.end(); 49 } 50 51 template <typename TStyle> 52 struct StyleBlock { StyleBlockStyleBlock53 StyleBlock() : fRange(EMPTY_RANGE), fStyle() { } StyleBlockStyleBlock54 StyleBlock(size_t start, size_t end, const TStyle& style) : fRange(start, end), fStyle(style) {} StyleBlockStyleBlock55 StyleBlock(TextRange textRange, const TStyle& style) : fRange(textRange), fStyle(style) {} addStyleBlock56 void add(TextRange tail) { 57 SkASSERT(fRange.end == tail.start); 58 fRange = TextRange(fRange.start, fRange.start + fRange.width() + tail.width()); 59 } 60 TextRange fRange; 61 TStyle fStyle; 62 }; 63 64 struct ResolvedFontDescriptor { 65 ResolvedFontDescriptorResolvedFontDescriptor66 ResolvedFontDescriptor(TextIndex index, SkFont font) 67 : fFont(font), fTextStart(index) { } 68 SkFont fFont; 69 TextIndex fTextStart; 70 }; 71 72 enum InternalState { 73 kUnknown = 0, 74 kIndexed = 1, // Text is indexed 75 kShaped = 2, // Text is shaped 76 kLineBroken = 5, 77 kFormatted = 6, 78 kDrawn = 7 79 }; 80 81 /* 82 struct BidiRegion { 83 BidiRegion(size_t start, size_t end, uint8_t dir) 84 : text(start, end), direction(dir) { } 85 TextRange text; 86 uint8_t direction; 87 }; 88 */ 89 class ParagraphImpl final : public Paragraph { 90 91 public: 92 93 ParagraphImpl(const SkString& text, 94 ParagraphStyle style, 95 SkTArray<Block, true> blocks, 96 SkTArray<Placeholder, true> placeholders, 97 sk_sp<FontCollection> fonts, 98 std::shared_ptr<SkUnicode> unicode); 99 100 ParagraphImpl(const std::u16string& utf16text, 101 ParagraphStyle style, 102 SkTArray<Block, true> blocks, 103 SkTArray<Placeholder, true> placeholders, 104 sk_sp<FontCollection> fonts, 105 std::shared_ptr<SkUnicode> unicode); 106 107 ~ParagraphImpl() override; 108 109 void layout(SkScalar width) override; 110 void paint(SkCanvas* canvas, SkScalar x, SkScalar y) override; 111 void paint(ParagraphPainter* canvas, SkScalar x, SkScalar y) override; 112 std::vector<TextBox> getRectsForRange(unsigned start, 113 unsigned end, 114 RectHeightStyle rectHeightStyle, 115 RectWidthStyle rectWidthStyle) override; 116 std::vector<TextBox> getRectsForPlaceholders() override; 117 void getLineMetrics(std::vector<LineMetrics>&) override; 118 PositionWithAffinity getGlyphPositionAtCoordinate(SkScalar dx, SkScalar dy) override; 119 SkRange<size_t> getWordBoundary(unsigned offset) override; 120 lineNumber()121 size_t lineNumber() override { return fLines.size(); } 122 123 TextLine& addLine(SkVector offset, SkVector advance, 124 TextRange textExcludingSpaces, TextRange text, TextRange textIncludingNewlines, 125 ClusterRange clusters, ClusterRange clustersWithGhosts, SkScalar widthWithSpaces, 126 InternalLineMetrics sizes); 127 text()128 SkSpan<const char> text() const { return SkSpan<const char>(fText.c_str(), fText.size()); } state()129 InternalState state() const { return fState; } runs()130 SkSpan<Run> runs() { return SkSpan<Run>(fRuns.data(), fRuns.size()); } styles()131 SkSpan<Block> styles() { 132 return SkSpan<Block>(fTextStyles.data(), fTextStyles.size()); 133 } placeholders()134 SkSpan<Placeholder> placeholders() { 135 return SkSpan<Placeholder>(fPlaceholders.data(), fPlaceholders.size()); 136 } lines()137 SkSpan<TextLine> lines() { return SkSpan<TextLine>(fLines.data(), fLines.size()); } paragraphStyle()138 const ParagraphStyle& paragraphStyle() const { return fParagraphStyle; } clusters()139 SkSpan<Cluster> clusters() { return SkSpan<Cluster>(fClusters.begin(), fClusters.size()); } fontCollection()140 sk_sp<FontCollection> fontCollection() const { return fFontCollection; } 141 void formatLines(SkScalar maxWidth); 142 void ensureUTF16Mapping(); 143 TextIndex findNextGraphemeBoundary(TextIndex utf8); 144 TextIndex findPreviousGraphemeBoundary(TextIndex utf8); 145 TextIndex findNextGlyphClusterBoundary(TextIndex utf8); 146 TextIndex findPreviousGlyphClusterBoundary(TextIndex utf8); getUTF16Index(TextIndex index)147 size_t getUTF16Index(TextIndex index) { 148 return fUTF16IndexForUTF8Index[index]; 149 } 150 strutEnabled()151 bool strutEnabled() const { return paragraphStyle().getStrutStyle().getStrutEnabled(); } strutForceHeight()152 bool strutForceHeight() const { 153 return paragraphStyle().getStrutStyle().getForceStrutHeight(); 154 } strutHeightOverride()155 bool strutHeightOverride() const { 156 return paragraphStyle().getStrutStyle().getHeightOverride(); 157 } strutMetrics()158 InternalLineMetrics strutMetrics() const { return fStrutMetrics; } 159 160 SkString getEllipsis() const; 161 162 SkSpan<const char> text(TextRange textRange); 163 SkSpan<Cluster> clusters(ClusterRange clusterRange); 164 Cluster& cluster(ClusterIndex clusterIndex); clusterIndex(TextIndex textIndex)165 ClusterIndex clusterIndex(TextIndex textIndex) { 166 auto clusterIndex = this->fClustersIndexFromCodeUnit[textIndex]; 167 SkASSERT(clusterIndex != EMPTY_INDEX); 168 return clusterIndex; 169 } run(RunIndex runIndex)170 Run& run(RunIndex runIndex) { 171 SkASSERT(runIndex < SkToSizeT(fRuns.size())); 172 return fRuns[runIndex]; 173 } 174 175 Run& runByCluster(ClusterIndex clusterIndex); 176 SkSpan<Block> blocks(BlockRange blockRange); 177 Block& block(BlockIndex blockIndex); resolvedFonts()178 SkTArray<ResolvedFontDescriptor> resolvedFonts() const { return fFontSwitches; } 179 markDirty()180 void markDirty() override { 181 if (fState > kIndexed) { 182 fState = kIndexed; 183 } 184 } 185 186 int32_t unresolvedGlyphs() override; 187 188 void setState(InternalState state); getPicture()189 sk_sp<SkPicture> getPicture() { return fPicture; } 190 widthWithTrailingSpaces()191 SkScalar widthWithTrailingSpaces() { return fMaxWidthWithTrailingSpaces; } 192 193 void resetContext(); 194 void resolveStrut(); 195 196 bool computeCodeUnitProperties(); 197 void applySpacingAndBuildClusterTable(); 198 void buildClusterTable(); 199 bool shapeTextIntoEndlessLine(); 200 void breakShapedTextIntoLines(SkScalar maxWidth); 201 202 void updateTextAlign(TextAlign textAlign) override; 203 void updateFontSize(size_t from, size_t to, SkScalar fontSize) override; 204 void updateForegroundPaint(size_t from, size_t to, SkPaint paint) override; 205 void updateBackgroundPaint(size_t from, size_t to, SkPaint paint) override; 206 207 void visit(const Visitor&) override; 208 getEmptyMetrics()209 InternalLineMetrics getEmptyMetrics() const { return fEmptyMetrics; } getStrutMetrics()210 InternalLineMetrics getStrutMetrics() const { return fStrutMetrics; } 211 212 BlockRange findAllBlocks(TextRange textRange); 213 resetShifts()214 void resetShifts() { 215 for (auto& run : fRuns) { 216 run.resetJustificationShifts(); 217 } 218 } 219 codeUnitHasProperty(size_t index,SkUnicode::CodeUnitFlags property)220 bool codeUnitHasProperty(size_t index, SkUnicode::CodeUnitFlags property) const { 221 return (fCodeUnitProperties[index] & property) == property; 222 } 223 getUnicode()224 SkUnicode* getUnicode() { return fUnicode.get(); } 225 226 private: 227 friend class ParagraphBuilder; 228 friend class ParagraphCacheKey; 229 friend class ParagraphCacheValue; 230 friend class ParagraphCache; 231 232 friend class TextWrapper; 233 friend class OneLineShaper; 234 235 void computeEmptyMetrics(); 236 237 // Input 238 SkTArray<StyleBlock<SkScalar>> fLetterSpaceStyles; 239 SkTArray<StyleBlock<SkScalar>> fWordSpaceStyles; 240 SkTArray<StyleBlock<SkPaint>> fBackgroundStyles; 241 SkTArray<StyleBlock<SkPaint>> fForegroundStyles; 242 SkTArray<StyleBlock<std::vector<TextShadow>>> fShadowStyles; 243 SkTArray<StyleBlock<Decoration>> fDecorationStyles; 244 SkTArray<Block, true> fTextStyles; // TODO: take out only the font stuff 245 SkTArray<Placeholder, true> fPlaceholders; 246 SkString fText; 247 248 // Internal structures 249 InternalState fState; 250 SkTArray<Run, false> fRuns; // kShaped 251 SkTArray<Cluster, true> fClusters; // kClusterized (cached: text, word spacing, letter spacing, resolved fonts) 252 SkTArray<SkUnicode::CodeUnitFlags, true> fCodeUnitProperties; 253 SkTArray<size_t, true> fClustersIndexFromCodeUnit; 254 std::vector<size_t> fWords; 255 std::vector<SkUnicode::BidiRegion> fBidiRegions; 256 // These two arrays are used in measuring methods (getRectsForRange, getGlyphPositionAtCoordinate) 257 // They are filled lazily whenever they need and cached 258 SkTArray<TextIndex, true> fUTF8IndexForUTF16Index; 259 SkTArray<size_t, true> fUTF16IndexForUTF8Index; 260 SkOnce fillUTF16MappingOnce; 261 size_t fUnresolvedGlyphs; 262 263 SkTArray<TextLine, false> fLines; // kFormatted (cached: width, max lines, ellipsis, text align) 264 sk_sp<SkPicture> fPicture; // kRecorded (cached: text styles) 265 266 SkTArray<ResolvedFontDescriptor> fFontSwitches; 267 268 InternalLineMetrics fEmptyMetrics; 269 InternalLineMetrics fStrutMetrics; 270 271 SkScalar fOldWidth; 272 SkScalar fOldHeight; 273 SkScalar fMaxWidthWithTrailingSpaces; 274 275 std::shared_ptr<SkUnicode> fUnicode; 276 bool fHasLineBreaks; 277 bool fHasWhitespacesInside; 278 TextIndex fTrailingSpaces; 279 }; 280 } // namespace textlayout 281 } // namespace skia 282 283 284 #endif // ParagraphImpl_DEFINED 285