1 // Copyright 2019 Google LLC. 2 #ifndef ParagraphImpl_DEFINED 3 #define ParagraphImpl_DEFINED 4 5 #include "include/core/SkPicture.h" 6 #include "include/private/SkMutex.h" 7 #include "include/private/SkTHash.h" 8 #include "modules/skparagraph/include/Paragraph.h" 9 #include "modules/skparagraph/include/ParagraphStyle.h" 10 #include "modules/skparagraph/include/TextStyle.h" 11 #include "modules/skparagraph/src/FontResolver.h" 12 #include "modules/skparagraph/src/Run.h" 13 #include "modules/skparagraph/src/TextLine.h" 14 15 class SkCanvas; 16 17 namespace skia { 18 namespace textlayout { 19 20 template <typename T> bool operator==(const SkSpan<T>& a, const SkSpan<T>& b) { 21 return a.size() == b.size() && a.begin() == b.begin(); 22 } 23 24 template <typename T> bool operator<=(const SkSpan<T>& a, const SkSpan<T>& b) { 25 return a.begin() >= b.begin() && a.end() <= b.end(); 26 } 27 28 template <typename TStyle> 29 struct StyleBlock { StyleBlockStyleBlock30 StyleBlock() : fRange(EMPTY_RANGE), fStyle() { } StyleBlockStyleBlock31 StyleBlock(size_t start, size_t end, const TStyle& style) : fRange(start, end), fStyle(style) {} StyleBlockStyleBlock32 StyleBlock(TextRange textRange, const TStyle& style) : fRange(textRange), fStyle(style) {} addStyleBlock33 void add(TextRange tail) { 34 SkASSERT(fRange.end == tail.start); 35 fRange = TextRange(fRange.start, fRange.start + fRange.width() + tail.width()); 36 } 37 TextRange fRange; 38 TStyle fStyle; 39 }; 40 41 class ParagraphImpl final : public Paragraph { 42 43 public: 44 45 ParagraphImpl(const SkString& text, 46 ParagraphStyle style, 47 SkTArray<Block, true> blocks, 48 sk_sp<FontCollection> fonts); 49 50 ParagraphImpl(const std::u16string& utf16text, 51 ParagraphStyle style, 52 SkTArray<Block, true> blocks, 53 sk_sp<FontCollection> fonts); 54 ~ParagraphImpl() override; 55 56 void layout(SkScalar width) override; 57 void paint(SkCanvas* canvas, SkScalar x, SkScalar y) override; 58 std::vector<TextBox> getRectsForRange(unsigned start, 59 unsigned end, 60 RectHeightStyle rectHeightStyle, 61 RectWidthStyle rectWidthStyle) override; 62 PositionWithAffinity getGlyphPositionAtCoordinate(SkScalar dx, SkScalar dy) override; 63 SkRange<size_t> getWordBoundary(unsigned offset) override; didExceedMaxLines()64 bool didExceedMaxLines() override { 65 return !fParagraphStyle.unlimited_lines() && fLines.size() > fParagraphStyle.getMaxLines(); 66 } 67 lineNumber()68 size_t lineNumber() override { return fLines.size(); } 69 70 TextLine& addLine(SkVector offset, SkVector advance, TextRange text, TextRange textWithSpaces, 71 ClusterRange clusters, ClusterRange clustersWithGhosts, SkScalar AddLineToParagraph, 72 LineMetrics sizes); 73 text()74 SkSpan<const char> text() const { return fTextSpan; } state()75 InternalState state() const { return fState; } runs()76 SkSpan<Run> runs() { return SkSpan<Run>(fRuns.data(), fRuns.size()); } switches()77 const SkTArray<FontDescr>& switches() const { return fFontResolver.switches(); } styles()78 SkSpan<Block> styles() { 79 return SkSpan<Block>(fTextStyles.data(), fTextStyles.size()); 80 } lines()81 SkSpan<TextLine> lines() { return SkSpan<TextLine>(fLines.data(), fLines.size()); } paragraphStyle()82 const ParagraphStyle& paragraphStyle() const { return fParagraphStyle; } clusters()83 SkSpan<Cluster> clusters() { return SkSpan<Cluster>(fClusters.begin(), fClusters.size()); } fontCollection()84 sk_sp<FontCollection> fontCollection() const { return fFontCollection; } 85 void formatLines(SkScalar maxWidth); 86 shiftCluster(ClusterIndex index,SkScalar shift)87 void shiftCluster(ClusterIndex index, SkScalar shift) { 88 auto& cluster = fClusters[index]; 89 auto& run = fRunShifts[cluster.runIndex()]; 90 for (size_t pos = cluster.startPos(); pos < cluster.endPos(); ++pos) { 91 run.fShifts[pos] = shift; 92 } 93 } 94 posShift(RunIndex index,size_t pos)95 SkScalar posShift(RunIndex index, size_t pos) const { 96 if (fRunShifts.count() == 0) return 0.0; 97 return fRunShifts[index].fShifts[pos]; 98 } 99 lineShift(size_t index)100 SkScalar lineShift(size_t index) { return fLines[index].shift(); } 101 strutEnabled()102 bool strutEnabled() const { return paragraphStyle().getStrutStyle().getStrutEnabled(); } strutForceHeight()103 bool strutForceHeight() const { 104 return paragraphStyle().getStrutStyle().getForceStrutHeight(); 105 } strutHeightOverride()106 bool strutHeightOverride() const { 107 return paragraphStyle().getStrutStyle().getHeightOverride(); 108 } strutMetrics()109 LineMetrics strutMetrics() const { return fStrutMetrics; } 110 measurement()111 Measurement measurement() { 112 return { 113 fAlphabeticBaseline, 114 fIdeographicBaseline, 115 fHeight, 116 fWidth, 117 fMaxIntrinsicWidth, 118 fMinIntrinsicWidth, 119 }; 120 } setMeasurement(Measurement m)121 void setMeasurement(Measurement m) { 122 fAlphabeticBaseline = m.fAlphabeticBaseline; 123 fIdeographicBaseline = m.fIdeographicBaseline; 124 fHeight = m.fHeight; 125 fWidth = m.fWidth; 126 fMaxIntrinsicWidth = m.fMaxIntrinsicWidth; 127 fMinIntrinsicWidth = m.fMinIntrinsicWidth; 128 } 129 130 SkSpan<const char> text(TextRange textRange); 131 SkSpan<Cluster> clusters(ClusterRange clusterRange); 132 Cluster& cluster(ClusterIndex clusterIndex); 133 Run& run(RunIndex runIndex); 134 SkSpan<Block> blocks(BlockRange blockRange); 135 Block& block(BlockIndex blockIndex); 136 markDirty()137 void markDirty() override { fState = kUnknown; } getResolver()138 FontResolver& getResolver() { return fFontResolver; } 139 void setState(InternalState state); getPicture()140 sk_sp<SkPicture> getPicture() { return fPicture; } 141 142 void resetContext(); 143 void resolveStrut(); 144 void resetRunShifts(); 145 void buildClusterTable(); 146 void markLineBreaks(); 147 bool shapeTextIntoEndlessLine(); 148 void breakShapedTextIntoLines(SkScalar maxWidth); 149 void paintLinesIntoPicture(); 150 151 private: 152 friend class ParagraphBuilder; 153 friend class ParagraphCacheKey; 154 friend class ParagraphCacheValue; 155 friend class ParagraphCache; 156 157 friend class TextWrapper; 158 159 BlockRange findAllBlocks(TextRange textRange); 160 void extractStyles(); 161 162 void markGraphemes(); 163 164 // Input 165 SkTArray<StyleBlock<SkScalar>> fLetterSpaceStyles; 166 SkTArray<StyleBlock<SkScalar>> fWordSpaceStyles; 167 SkTArray<StyleBlock<SkPaint>> fBackgroundStyles; 168 SkTArray<StyleBlock<SkPaint>> fForegroundStyles; 169 SkTArray<StyleBlock<std::vector<TextShadow>>> fShadowStyles; 170 SkTArray<StyleBlock<Decoration>> fDecorationStyles; 171 SkTArray<Block, true> fTextStyles; // TODO: take out only the font stuff 172 SkString fText; 173 SkSpan<const char> fTextSpan; 174 175 // Internal structures 176 InternalState fState; 177 SkTArray<Run> fRuns; // kShaped 178 SkTArray<Cluster, true> fClusters; // kClusterized (cached: text, word spacing, letter spacing, resolved fonts) 179 SkTArray<Grapheme, true> fGraphemes; 180 SkTArray<Codepoint, true> fCodePoints; 181 182 SkTArray<RunShifts, true> fRunShifts; 183 SkTArray<TextLine, true> fLines; // kFormatted (cached: width, max lines, ellipsis, text align) 184 sk_sp<SkPicture> fPicture; // kRecorded (cached: text styles) 185 186 LineMetrics fStrutMetrics; 187 FontResolver fFontResolver; 188 189 SkScalar fOldWidth; 190 SkScalar fOldHeight; 191 SkScalar fMaxWidthWithTrailingSpaces; 192 }; 193 } // namespace textlayout 194 } // namespace skia 195 196 #endif // ParagraphImpl_DEFINED 197