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 #include <functional> // std::function 14 15 namespace skia { 16 namespace textlayout { 17 18 class ParagraphImpl; 19 class Cluster; 20 class Run; 21 22 typedef size_t RunIndex; 23 const size_t EMPTY_RUN = EMPTY_INDEX; 24 25 typedef size_t ClusterIndex; 26 typedef SkRange<size_t> ClusterRange; 27 const size_t EMPTY_CLUSTER = EMPTY_INDEX; 28 const SkRange<size_t> EMPTY_CLUSTERS = EMPTY_RANGE; 29 30 typedef size_t GraphemeIndex; 31 typedef SkRange<GraphemeIndex> GraphemeRange; 32 33 typedef size_t CodepointIndex; 34 typedef SkRange<CodepointIndex> CodepointRange; 35 36 struct RunShifts { RunShiftsRunShifts37 RunShifts() { } RunShiftsRunShifts38 RunShifts(size_t count) { fShifts.push_back_n(count, 0.0); } 39 SkSTArray<128, SkScalar, true> fShifts; 40 }; 41 42 class InternalLineMetrics; 43 class Run { 44 public: 45 Run() = default; 46 Run(ParagraphImpl* master, 47 const SkShaper::RunHandler::RunInfo& info, 48 size_t firstChar, 49 SkScalar lineHeight, 50 size_t index, 51 SkScalar shiftX); ~Run()52 ~Run() {} 53 setMaster(ParagraphImpl * master)54 void setMaster(ParagraphImpl* master) { fMaster = master; } 55 56 SkShaper::RunHandler::Buffer newRunBuffer(); 57 posX(size_t index)58 SkScalar posX(size_t index) const { 59 return fPositions[index].fX + fOffsets[index].fX; 60 } addX(size_t index,SkScalar shift)61 void addX(size_t index, SkScalar shift) { 62 fPositions[index].fX += shift; 63 } posY(size_t index)64 SkScalar posY(size_t index) const { 65 return fPositions[index].fY + fOffsets[index].fY; 66 } size()67 size_t size() const { return fGlyphs.size(); } setWidth(SkScalar width)68 void setWidth(SkScalar width) { fAdvance.fX = width; } setHeight(SkScalar height)69 void setHeight(SkScalar height) { fAdvance.fY = height; } shift(SkScalar shiftX,SkScalar shiftY)70 void shift(SkScalar shiftX, SkScalar shiftY) { 71 fOffset.fX += shiftX; 72 fOffset.fY += shiftY; 73 } advance()74 SkVector advance() const { 75 return SkVector::Make(fAdvance.fX, fFontMetrics.fDescent - fFontMetrics.fAscent); 76 } offset()77 SkVector offset() const { return fOffset; } ascent()78 SkScalar ascent() const { return fFontMetrics.fAscent; } correctAscent()79 SkScalar correctAscent() const { 80 81 if (fHeightMultiplier == 0) { 82 return fFontMetrics.fAscent - fFontMetrics.fLeading / 2; 83 } 84 return fFontMetrics.fAscent * fHeightMultiplier * fFont.getSize() / 85 (fFontMetrics.fDescent - fFontMetrics.fAscent + fFontMetrics.fLeading / 2); 86 } correctDescent()87 SkScalar correctDescent() const { 88 89 if (fHeightMultiplier == 0) { 90 return fFontMetrics.fDescent + fFontMetrics.fLeading / 2; 91 } 92 return fFontMetrics.fDescent * fHeightMultiplier * fFont.getSize() / 93 (fFontMetrics.fDescent - fFontMetrics.fAscent + fFontMetrics.fLeading / 2); 94 } correctLeading()95 SkScalar correctLeading() const { 96 97 if (fHeightMultiplier == 0) { 98 return fFontMetrics.fAscent; 99 } 100 return fFontMetrics.fLeading * fHeightMultiplier * fFont.getSize() / 101 (fFontMetrics.fDescent - fFontMetrics.fAscent + fFontMetrics.fLeading); 102 } font()103 const SkFont& font() const { return fFont; } leftToRight()104 bool leftToRight() const { return fBidiLevel % 2 == 0; } index()105 size_t index() const { return fIndex; } lineHeight()106 SkScalar lineHeight() const { return fHeightMultiplier; } 107 PlaceholderStyle* placeholderStyle() const; isPlaceholder()108 bool isPlaceholder() const { return fPlaceholderIndex != std::numeric_limits<size_t>::max(); } clusterIndex(size_t pos)109 size_t clusterIndex(size_t pos) const { return fClusterIndexes[pos]; } globalClusterIndex(size_t pos)110 size_t globalClusterIndex(size_t pos) const { return fClusterStart + fClusterIndexes[pos]; } 111 SkScalar positionX(size_t pos) const; 112 textRange()113 TextRange textRange() const { return fTextRange; } clusterRange()114 ClusterRange clusterRange() const { return fClusterRange; } 115 master()116 ParagraphImpl* master() const { return fMaster; } 117 isEllipsis()118 bool isEllipsis() const { return fEllipsis; } 119 120 void updateMetrics(InternalLineMetrics* endlineMetrics); 121 setClusterRange(size_t from,size_t to)122 void setClusterRange(size_t from, size_t to) { fClusterRange = ClusterRange(from, to); } clip()123 SkRect clip() const { 124 return SkRect::MakeXYWH(fOffset.fX, fOffset.fY, fAdvance.fX, fAdvance.fY); 125 } 126 127 SkScalar addSpacesAtTheEnd(SkScalar space, Cluster* cluster); 128 SkScalar addSpacesEvenly(SkScalar space, Cluster* cluster); 129 void shift(const Cluster* cluster, SkScalar offset); 130 calculateHeight()131 SkScalar calculateHeight() const { 132 if (fHeightMultiplier == 0) { 133 return fFontMetrics.fDescent - fFontMetrics.fAscent; 134 } 135 return fHeightMultiplier * fFont.getSize(); 136 } 137 SkScalar calculateWidth(size_t start, size_t end, bool clip) const; 138 139 void copyTo(SkTextBlobBuilder& builder, size_t pos, size_t size, SkVector offset) const; 140 141 using ClusterVisitor = std::function<void(size_t glyphStart, 142 size_t glyphEnd, 143 size_t charStart, 144 size_t charEnd, 145 SkScalar width, 146 SkScalar height)>; 147 void iterateThroughClustersInTextOrder(const ClusterVisitor& visitor); 148 149 std::tuple<bool, ClusterIndex, ClusterIndex> findLimitingClusters(TextRange text, bool onlyInnerClusters) const; glyphs()150 SkSpan<const SkGlyphID> glyphs() const { 151 return SkSpan<const SkGlyphID>(fGlyphs.begin(), fGlyphs.size()); 152 } positions()153 SkSpan<const SkPoint> positions() const { 154 return SkSpan<const SkPoint>(fPositions.begin(), fPositions.size()); 155 } offsets()156 SkSpan<const SkPoint> offsets() const { 157 return SkSpan<const SkPoint>(fOffsets.begin(), fOffsets.size()); 158 } clusterIndexes()159 SkSpan<const uint32_t> clusterIndexes() const { 160 return SkSpan<const uint32_t>(fClusterIndexes.begin(), fClusterIndexes.size()); 161 } shifts()162 SkSpan<const SkScalar> shifts() const { return SkSpan<const SkScalar>(fShifts.begin(), fShifts.size()); } 163 164 void commit(); 165 getBounds(size_t pos)166 SkRect getBounds(size_t pos) const { return fBounds[pos]; } 167 resetShifts()168 void resetShifts() { 169 for (auto& r: fShifts) { r = 0; } 170 fSpaced = false; 171 } 172 private: 173 friend class ParagraphImpl; 174 friend class TextLine; 175 friend class InternalLineMetrics; 176 friend class ParagraphCache; 177 friend class OneLineShaper; 178 179 ParagraphImpl* fMaster; 180 TextRange fTextRange; 181 ClusterRange fClusterRange; 182 183 SkFont fFont; 184 SkFontMetrics fFontMetrics; 185 SkScalar fHeightMultiplier; 186 size_t fPlaceholderIndex; 187 bool fEllipsis; 188 size_t fIndex; 189 uint8_t fBidiLevel; 190 SkVector fAdvance; 191 SkVector fOffset; 192 TextIndex fClusterStart; 193 SkShaper::RunHandler::Range fUtf8Range; 194 SkSTArray<128, SkGlyphID, true> fGlyphs; 195 SkSTArray<128, SkPoint, true> fPositions; 196 SkSTArray<128, SkPoint, true> fOffsets; 197 SkSTArray<128, uint32_t, true> fClusterIndexes; 198 SkSTArray<128, SkRect, true> fBounds; 199 200 SkSTArray<128, SkScalar, true> fShifts; // For formatting (letter/word spacing, justification) 201 bool fSpaced; 202 }; 203 204 struct Codepoint { 205 CodepointCodepoint206 Codepoint(GraphemeIndex graphemeIndex, TextIndex textIndex, size_t index) 207 : fGrapheme(graphemeIndex), fTextIndex(textIndex), fIndex(index) { } 208 209 GraphemeIndex fGrapheme; 210 TextIndex fTextIndex; // Used for getGlyphPositionAtCoordinate 211 size_t fIndex; 212 }; 213 214 struct Grapheme { GraphemeGrapheme215 Grapheme(CodepointRange codepoints, TextRange textRange) 216 : fCodepointRange(codepoints), fTextRange(textRange) { } 217 CodepointRange fCodepointRange; 218 TextRange fTextRange; // Used for getRectsForRange 219 }; 220 221 class Cluster { 222 public: 223 enum BreakType { 224 None, 225 CharacterBoundary, // not yet in use (UBRK_CHARACTER) 226 WordBoundary, // calculated for all clusters (UBRK_WORD) 227 WordBreakWithoutHyphen, // calculated only for hyphenated words 228 WordBreakWithHyphen, 229 SoftLineBreak, // calculated for all clusters (UBRK_LINE) 230 HardLineBreak, // calculated for all clusters (UBRK_LINE) 231 }; 232 Cluster()233 Cluster() 234 : fMaster(nullptr) 235 , fRunIndex(EMPTY_RUN) 236 , fTextRange(EMPTY_TEXT) 237 , fGraphemeRange(EMPTY_RANGE) 238 , fStart(0) 239 , fEnd() 240 , fWidth() 241 , fSpacing(0) 242 , fHeight() 243 , fHalfLetterSpacing(0.0) 244 , fWhiteSpaces(false) 245 , fBreakType(None) {} 246 247 Cluster(ParagraphImpl* master, 248 RunIndex runIndex, 249 size_t start, 250 size_t end, 251 SkSpan<const char> text, 252 SkScalar width, 253 SkScalar height); 254 Cluster(TextRange textRange)255 Cluster(TextRange textRange) : fTextRange(textRange), fGraphemeRange(EMPTY_RANGE) { } 256 257 ~Cluster() = default; 258 setMaster(ParagraphImpl * master)259 void setMaster(ParagraphImpl* master) { fMaster = master; } 260 SkScalar sizeToChar(TextIndex ch) const; 261 SkScalar sizeFromChar(TextIndex ch) const; 262 263 size_t roundPos(SkScalar s) const; 264 space(SkScalar shift,SkScalar space)265 void space(SkScalar shift, SkScalar space) { 266 fSpacing += space; 267 fWidth += shift; 268 } 269 setBreakType(BreakType type)270 void setBreakType(BreakType type) { fBreakType = type; } isWhitespaces()271 bool isWhitespaces() const { return fWhiteSpaces; } canBreakLineAfter()272 bool canBreakLineAfter() const { 273 return fBreakType == SoftLineBreak || fBreakType == HardLineBreak; 274 } isHardBreak()275 bool isHardBreak() const { return fBreakType == HardLineBreak; } isSoftBreak()276 bool isSoftBreak() const { return fBreakType == SoftLineBreak; } startPos()277 size_t startPos() const { return fStart; } endPos()278 size_t endPos() const { return fEnd; } width()279 SkScalar width() const { return fWidth; } height()280 SkScalar height() const { return fHeight; } size()281 size_t size() const { return fEnd - fStart; } 282 setHalfLetterSpacing(SkScalar halfLetterSpacing)283 void setHalfLetterSpacing(SkScalar halfLetterSpacing) { fHalfLetterSpacing = halfLetterSpacing; } getHalfLetterSpacing()284 SkScalar getHalfLetterSpacing() const { return fHalfLetterSpacing; } 285 textRange()286 TextRange textRange() const { return fTextRange; } 287 runIndex()288 RunIndex runIndex() const { return fRunIndex; } master()289 ParagraphImpl* master() const { return fMaster; } 290 291 Run* run() const; 292 SkFont font() const; 293 294 SkScalar trimmedWidth(size_t pos) const; 295 296 void setIsWhiteSpaces(); 297 contains(TextIndex ch)298 bool contains(TextIndex ch) const { return ch >= fTextRange.start && ch < fTextRange.end; } 299 belongs(TextRange text)300 bool belongs(TextRange text) const { 301 return fTextRange.start >= text.start && fTextRange.end <= text.end; 302 } 303 startsIn(TextRange text)304 bool startsIn(TextRange text) const { 305 return fTextRange.start >= text.start && fTextRange.start < text.end; 306 } 307 308 private: 309 310 friend ParagraphImpl; 311 312 ParagraphImpl* fMaster; 313 RunIndex fRunIndex; 314 TextRange fTextRange; 315 GraphemeRange fGraphemeRange; 316 317 size_t fStart; 318 size_t fEnd; 319 SkScalar fWidth; 320 SkScalar fSpacing; 321 SkScalar fHeight; 322 SkScalar fHalfLetterSpacing; 323 bool fWhiteSpaces; 324 BreakType fBreakType; 325 }; 326 327 class InternalLineMetrics { 328 public: 329 InternalLineMetrics()330 InternalLineMetrics() { 331 clean(); 332 fForceStrut = false; 333 } 334 InternalLineMetrics(bool forceStrut)335 InternalLineMetrics(bool forceStrut) { 336 clean(); 337 fForceStrut = forceStrut; 338 } 339 InternalLineMetrics(SkScalar a,SkScalar d,SkScalar l)340 InternalLineMetrics(SkScalar a, SkScalar d, SkScalar l) { 341 fAscent = a; 342 fDescent = d; 343 fLeading = l; 344 fForceStrut = false; 345 } 346 InternalLineMetrics(const SkFont & font,bool forceStrut)347 InternalLineMetrics(const SkFont& font, bool forceStrut) { 348 SkFontMetrics metrics; 349 font.getMetrics(&metrics); 350 fAscent = metrics.fAscent; 351 fDescent = metrics.fDescent; 352 fLeading = metrics.fLeading; 353 fForceStrut = forceStrut; 354 } 355 add(Run * run)356 void add(Run* run) { 357 358 if (fForceStrut) { 359 return; 360 } 361 362 fAscent = std::min(fAscent, run->correctAscent()); 363 fDescent = std::max(fDescent, run->correctDescent()); 364 fLeading = std::max(fLeading, run->correctLeading()); 365 } 366 add(InternalLineMetrics other)367 void add(InternalLineMetrics other) { 368 fAscent = std::min(fAscent, other.fAscent); 369 fDescent = std::max(fDescent, other.fDescent); 370 fLeading = std::max(fLeading, other.fLeading); 371 } clean()372 void clean() { 373 fAscent = 0; 374 fDescent = 0; 375 fLeading = 0; 376 } 377 delta()378 SkScalar delta() const { return height() - ideographicBaseline(); } 379 updateLineMetrics(InternalLineMetrics & metrics)380 void updateLineMetrics(InternalLineMetrics& metrics) { 381 if (metrics.fForceStrut) { 382 metrics.fAscent = fAscent; 383 metrics.fDescent = fDescent; 384 metrics.fLeading = fLeading; 385 } else { 386 // This is another of those flutter changes. To be removed... 387 metrics.fAscent = std::min(metrics.fAscent, fAscent - fLeading / 2.0f); 388 metrics.fDescent = std::max(metrics.fDescent, fDescent + fLeading / 2.0f); 389 } 390 } 391 runTop(const Run * run)392 SkScalar runTop(const Run* run) const { 393 return fLeading / 2 - fAscent + run->ascent() + delta(); 394 } 395 height()396 SkScalar height() const { 397 return ::round((double)fDescent - fAscent + fLeading); 398 } 399 alphabeticBaseline()400 SkScalar alphabeticBaseline() const { return fLeading / 2 - fAscent; } ideographicBaseline()401 SkScalar ideographicBaseline() const { return fDescent - fAscent + fLeading; } deltaBaselines()402 SkScalar deltaBaselines() const { return fLeading / 2 + fDescent; } baseline()403 SkScalar baseline() const { return fLeading / 2 - fAscent; } ascent()404 SkScalar ascent() const { return fAscent; } descent()405 SkScalar descent() const { return fDescent; } leading()406 SkScalar leading() const { return fLeading; } setForceStrut(bool value)407 void setForceStrut(bool value) { fForceStrut = value; } 408 409 private: 410 411 friend class TextWrapper; 412 413 SkScalar fAscent; 414 SkScalar fDescent; 415 SkScalar fLeading; 416 bool fForceStrut; 417 }; 418 } // namespace textlayout 419 } // namespace skia 420 421 #endif // Run_DEFINED 422