1 // Copyright 2019 Google LLC. 2 #ifndef Run_DEFINED 3 #define Run_DEFINED 4 5 #include "include/core/SkFontMetrics.h" 6 #include "include/core/SkPoint.h" 7 #include "include/core/SkTextBlob.h" 8 #include "modules/skparagraph/include/DartTypes.h" 9 #include "modules/skparagraph/include/TextStyle.h" 10 #include "modules/skshaper/include/SkShaper.h" 11 #include "src/core/SkSpan.h" 12 #include "src/core/SkTraceEvent.h" 13 14 namespace skia { 15 namespace textlayout { 16 17 class ParagraphImpl; 18 class Cluster; 19 class Run; 20 21 typedef size_t RunIndex; 22 const size_t EMPTY_RUN = EMPTY_INDEX; 23 24 typedef size_t ClusterIndex; 25 typedef SkRange<size_t> ClusterRange; 26 const size_t EMPTY_CLUSTER = EMPTY_INDEX; 27 const SkRange<size_t> EMPTY_CLUSTERS = EMPTY_RANGE; 28 29 typedef size_t GraphemeIndex; 30 typedef SkRange<GraphemeIndex> GraphemeRange; 31 32 typedef size_t CodepointIndex; 33 typedef SkRange<CodepointIndex> CodepointRange; 34 35 typedef size_t BlockIndex; 36 typedef SkRange<size_t> BlockRange; 37 const size_t EMPTY_BLOCK = EMPTY_INDEX; 38 const SkRange<size_t> EMPTY_BLOCKS = EMPTY_RANGE; 39 40 struct RunShifts { RunShiftsRunShifts41 RunShifts() { } RunShiftsRunShifts42 RunShifts(size_t count) { fShifts.push_back_n(count, 0.0); } 43 SkSTArray<128, SkScalar, true> fShifts; 44 }; 45 46 class Run { 47 public: 48 Run() = default; 49 Run(ParagraphImpl* master, 50 const SkShaper::RunHandler::RunInfo& info, 51 SkScalar lineHeight, 52 size_t index, 53 SkScalar shiftX); ~Run()54 ~Run() {} 55 setMaster(ParagraphImpl * master)56 void setMaster(ParagraphImpl* master) { fMaster = master; } 57 58 SkShaper::RunHandler::Buffer newRunBuffer(); 59 size()60 size_t size() const { return fGlyphs.size(); } setWidth(SkScalar width)61 void setWidth(SkScalar width) { fAdvance.fX = width; } setHeight(SkScalar height)62 void setHeight(SkScalar height) { fAdvance.fY = height; } shift(SkScalar shiftX,SkScalar shiftY)63 void shift(SkScalar shiftX, SkScalar shiftY) { 64 fOffset.fX += shiftX; 65 fOffset.fY += shiftY; 66 } advance()67 SkVector advance() const { 68 return SkVector::Make(fAdvance.fX, fFontMetrics.fDescent - fFontMetrics.fAscent); 69 } offset()70 SkVector offset() const { return fOffset; } ascent()71 SkScalar ascent() const { return fFontMetrics.fAscent; } 72 //SkScalar descent() const { return fFontMetrics.fDescent; } 73 //SkScalar leading() const { return fFontMetrics.fLeading; } correctAscent()74 SkScalar correctAscent() const { 75 76 if (fHeightMultiplier == 0 || fHeightMultiplier == 1) { 77 return fFontMetrics.fAscent - fFontMetrics.fLeading / 2; 78 } 79 return fFontMetrics.fAscent * fHeightMultiplier * fFont.getSize() / 80 (fFontMetrics.fDescent - fFontMetrics.fAscent + fFontMetrics.fLeading / 2); 81 } correctDescent()82 SkScalar correctDescent() const { 83 84 if (fHeightMultiplier == 0 || fHeightMultiplier == 1) { 85 return fFontMetrics.fDescent + fFontMetrics.fLeading / 2; 86 } 87 return fFontMetrics.fDescent * fHeightMultiplier * fFont.getSize() / 88 (fFontMetrics.fDescent - fFontMetrics.fAscent + fFontMetrics.fLeading / 2); 89 } correctLeading()90 SkScalar correctLeading() const { 91 92 if (fHeightMultiplier == 0 || fHeightMultiplier == 1) { 93 return fFontMetrics.fAscent; 94 } 95 return fFontMetrics.fLeading * fHeightMultiplier * fFont.getSize() / 96 (fFontMetrics.fDescent - fFontMetrics.fAscent + fFontMetrics.fLeading); 97 } font()98 const SkFont& font() const { return fFont; } leftToRight()99 bool leftToRight() const { return fBidiLevel % 2 == 0; } index()100 size_t index() const { return fIndex; } lineHeight()101 SkScalar lineHeight() const { return fHeightMultiplier; } clusterIndex(size_t pos)102 size_t clusterIndex(size_t pos) const { return fClusterIndexes[pos]; } 103 SkScalar positionX(size_t pos) const; 104 textRange()105 TextRange textRange() { return fTextRange; } clusterRange()106 ClusterRange clusterRange() { return fClusterRange; } 107 setClusterRange(size_t from,size_t to)108 void setClusterRange(size_t from, size_t to) { fClusterRange = ClusterRange(from, to); } clip()109 SkRect clip() const { 110 return SkRect::MakeXYWH(fOffset.fX, fOffset.fY, fAdvance.fX, fAdvance.fY); 111 } 112 113 SkScalar addSpacesAtTheEnd(SkScalar space, Cluster* cluster); 114 SkScalar addSpacesEvenly(SkScalar space, Cluster* cluster); 115 void shift(const Cluster* cluster, SkScalar offset); 116 calculateHeight()117 SkScalar calculateHeight() const { 118 if (fHeightMultiplier == 0 || fHeightMultiplier == 1) { 119 return fFontMetrics.fDescent - fFontMetrics.fAscent; 120 } 121 return fHeightMultiplier * fFont.getSize(); 122 } 123 SkScalar calculateWidth(size_t start, size_t end, bool clip) const; 124 125 void copyTo(SkTextBlobBuilder& builder, size_t pos, size_t size, SkVector offset) const; 126 127 using ClusterVisitor = std::function<void(size_t glyphStart, 128 size_t glyphEnd, 129 size_t charStart, 130 size_t charEnd, 131 SkScalar width, 132 SkScalar height)>; 133 void iterateThroughClustersInTextOrder(const ClusterVisitor& visitor); 134 135 std::tuple<bool, ClusterIndex, ClusterIndex> findLimitingClusters(TextRange); glyphs()136 SkSpan<const SkGlyphID> glyphs() const { 137 return SkSpan<const SkGlyphID>(fGlyphs.begin(), fGlyphs.size()); 138 } positions()139 SkSpan<const SkPoint> positions() const { 140 return SkSpan<const SkPoint>(fPositions.begin(), fPositions.size()); 141 } clusterIndexes()142 SkSpan<const uint32_t> clusterIndexes() const { 143 return SkSpan<const uint32_t>(fClusterIndexes.begin(), fClusterIndexes.size()); 144 } offsets()145 SkSpan<const SkScalar> offsets() const { return SkSpan<const SkScalar>(fOffsets.begin(), fOffsets.size()); } 146 147 private: 148 friend class ParagraphImpl; 149 friend class TextLine; 150 friend class LineMetrics; 151 friend class ParagraphCache; 152 153 ParagraphImpl* fMaster; 154 TextRange fTextRange; 155 ClusterRange fClusterRange; 156 157 SkFont fFont; 158 SkFontMetrics fFontMetrics; 159 SkScalar fHeightMultiplier; 160 size_t fIndex; 161 uint8_t fBidiLevel; 162 SkVector fAdvance; 163 SkVector fOffset; 164 SkShaper::RunHandler::Range fUtf8Range; 165 SkSTArray<128, SkGlyphID, false> fGlyphs; 166 SkSTArray<128, SkPoint, true> fPositions; 167 SkSTArray<128, uint32_t, true> fClusterIndexes; 168 SkSTArray<128, SkScalar, true> fOffsets; // For formatting (letter/word spacing, justification) 169 bool fSpaced; 170 }; 171 172 struct Codepoint { 173 CodepointCodepoint174 Codepoint(GraphemeIndex graphemeIndex, TextIndex textIndex) 175 : fGrapeme(graphemeIndex), fTextIndex(textIndex) { } 176 177 GraphemeIndex fGrapeme; 178 TextIndex fTextIndex; // Used for getGlyphPositionAtCoordinate 179 }; 180 181 struct Grapheme { GraphemeGrapheme182 Grapheme(CodepointRange codepoints, TextRange textRange) 183 : fCodepointRange(codepoints), fTextRange(textRange) { } 184 CodepointRange fCodepointRange; 185 TextRange fTextRange; // Used for getRectsForRange 186 }; 187 188 class Cluster { 189 public: 190 enum BreakType { 191 None, 192 CharacterBoundary, // not yet in use (UBRK_CHARACTER) 193 WordBoundary, // calculated for all clusters (UBRK_WORD) 194 WordBreakWithoutHyphen, // calculated only for hyphenated words 195 WordBreakWithHyphen, 196 SoftLineBreak, // calculated for all clusters (UBRK_LINE) 197 HardLineBreak, // calculated for all clusters (UBRK_LINE) 198 }; 199 Cluster()200 Cluster() 201 : fMaster(nullptr) 202 , fRunIndex(EMPTY_RUN) 203 , fTextRange(EMPTY_TEXT) 204 , fGraphemeRange(EMPTY_RANGE) 205 , fStart(0) 206 , fEnd() 207 , fWidth() 208 , fSpacing(0) 209 , fHeight() 210 , fWhiteSpaces(false) 211 , fBreakType(None) {} 212 213 Cluster(ParagraphImpl* master, 214 RunIndex runIndex, 215 size_t start, 216 size_t end, 217 SkSpan<const char> text, 218 SkScalar width, 219 SkScalar height); 220 Cluster(TextRange textRange)221 Cluster(TextRange textRange) : fTextRange(textRange), fGraphemeRange(EMPTY_RANGE) { } 222 223 ~Cluster() = default; 224 setMaster(ParagraphImpl * master)225 void setMaster(ParagraphImpl* master) { fMaster = master; } 226 SkScalar sizeToChar(TextIndex ch) const; 227 SkScalar sizeFromChar(TextIndex ch) const; 228 229 size_t roundPos(SkScalar s) const; 230 space(SkScalar shift,SkScalar space)231 void space(SkScalar shift, SkScalar space) { 232 fSpacing += space; 233 fWidth += shift; 234 } 235 setBreakType(BreakType type)236 void setBreakType(BreakType type) { fBreakType = type; } isWhitespaces()237 bool isWhitespaces() const { return fWhiteSpaces; } canBreakLineAfter()238 bool canBreakLineAfter() const { 239 return fBreakType == SoftLineBreak || fBreakType == HardLineBreak; 240 } isHardBreak()241 bool isHardBreak() const { return fBreakType == HardLineBreak; } isSoftBreak()242 bool isSoftBreak() const { return fBreakType == SoftLineBreak; } startPos()243 size_t startPos() const { return fStart; } endPos()244 size_t endPos() const { return fEnd; } width()245 SkScalar width() const { return fWidth; } trimmedWidth()246 SkScalar trimmedWidth() const { return fWidth - fSpacing; } lastSpacing()247 SkScalar lastSpacing() const { return fSpacing; } height()248 SkScalar height() const { return fHeight; } size()249 size_t size() const { return fEnd - fStart; } 250 textRange()251 TextRange textRange() const { return fTextRange; } 252 runIndex()253 RunIndex runIndex() const { return fRunIndex; } 254 Run* run() const; 255 SkFont font() const; 256 257 SkScalar trimmedWidth(size_t pos) const; 258 259 void setIsWhiteSpaces(); 260 contains(TextIndex ch)261 bool contains(TextIndex ch) const { return ch >= fTextRange.start && ch < fTextRange.end; } 262 belongs(TextRange text)263 bool belongs(TextRange text) const { 264 return fTextRange.start >= text.start && fTextRange.end <= text.end; 265 } 266 startsIn(TextRange text)267 bool startsIn(TextRange text) const { 268 return fTextRange.start >= text.start && fTextRange.start < text.end; 269 } 270 271 private: 272 273 friend ParagraphImpl; 274 275 ParagraphImpl* fMaster; 276 RunIndex fRunIndex; 277 TextRange fTextRange; 278 GraphemeRange fGraphemeRange; 279 280 size_t fStart; 281 size_t fEnd; 282 SkScalar fWidth; 283 SkScalar fSpacing; 284 SkScalar fHeight; 285 bool fWhiteSpaces; 286 BreakType fBreakType; 287 }; 288 289 class LineMetrics { 290 public: 291 LineMetrics()292 LineMetrics() { clean(); } LineMetrics(bool forceStrut)293 LineMetrics(bool forceStrut) : fForceStrut(forceStrut) { clean(); } 294 LineMetrics(SkScalar a,SkScalar d,SkScalar l)295 LineMetrics(SkScalar a, SkScalar d, SkScalar l) : fForceStrut(false) { 296 fAscent = a; 297 fDescent = d; 298 fLeading = l; 299 } 300 LineMetrics(const SkFont & font,bool forceStrut)301 LineMetrics(const SkFont& font, bool forceStrut) : fForceStrut(forceStrut) { 302 SkFontMetrics metrics; 303 font.getMetrics(&metrics); 304 fAscent = metrics.fAscent; 305 fDescent = metrics.fDescent; 306 fLeading = metrics.fLeading; 307 } 308 add(Run * run)309 void add(Run* run) { 310 311 if (fForceStrut) { 312 return; 313 } 314 315 fAscent = SkTMin(fAscent, run->correctAscent()); 316 fDescent = SkTMax(fDescent, run->correctDescent()); 317 fLeading = SkTMax(fLeading, run->correctLeading()); 318 319 } 320 add(LineMetrics other)321 void add(LineMetrics other) { 322 fAscent = SkTMin(fAscent, other.fAscent); 323 fDescent = SkTMax(fDescent, other.fDescent); 324 fLeading = SkTMax(fLeading, other.fLeading); 325 } clean()326 void clean() { 327 fAscent = 0; 328 fDescent = 0; 329 fLeading = 0; 330 } 331 delta()332 SkScalar delta() const { return height() - ideographicBaseline(); } 333 updateLineMetrics(LineMetrics & metrics)334 void updateLineMetrics(LineMetrics& metrics) { 335 metrics.fAscent = SkTMin(metrics.fAscent, fAscent); 336 metrics.fDescent = SkTMax(metrics.fDescent, fDescent); 337 metrics.fLeading = SkTMax(metrics.fLeading, fLeading); 338 } 339 runTop(Run * run)340 SkScalar runTop(Run* run) const { 341 return fLeading / 2 - fAscent + run->ascent() + delta(); 342 } height()343 SkScalar height() const { return SkScalarRoundToInt(fDescent - fAscent + fLeading); } alphabeticBaseline()344 SkScalar alphabeticBaseline() const { return fLeading / 2 - fAscent; } ideographicBaseline()345 SkScalar ideographicBaseline() const { return fDescent - fAscent + fLeading; } baseline()346 SkScalar baseline() const { return fLeading / 2 - fAscent; } ascent()347 SkScalar ascent() const { return fAscent; } descent()348 SkScalar descent() const { return fDescent; } leading()349 SkScalar leading() const { return fLeading; } 350 351 private: 352 SkScalar fAscent; 353 SkScalar fDescent; 354 SkScalar fLeading; 355 bool fForceStrut; 356 }; 357 } // namespace textlayout 358 } // namespace skia 359 360 #endif // Run_DEFINED 361