1 // Copyright 2019 Google LLC.
2 #ifndef Run_DEFINED
3 #define Run_DEFINED
4
5 #include "include/core/SkFont.h"
6 #include "include/core/SkFontMetrics.h"
7 #include "include/core/SkPoint.h"
8 #include "include/core/SkRect.h"
9 #include "include/core/SkScalar.h"
10 #include "include/core/SkSpan.h"
11 #include "include/core/SkTypes.h"
12 #include "include/private/SkTArray.h"
13 #include "modules/skparagraph/include/DartTypes.h"
14 #include "modules/skparagraph/include/TextStyle.h"
15 #include "modules/skshaper/include/SkShaper.h"
16
17 #include <math.h>
18 #include <algorithm>
19 #include <functional>
20 #include <limits>
21 #include <tuple>
22
23 #ifdef OHOS_SUPPORT
24 #include "modules/skparagraph/include/ParagraphStyle.h"
25 #endif
26
27 class SkTextBlobBuilder;
28
29 namespace skia {
30 namespace textlayout {
31 constexpr int PARAM_64 = 64;
32
33 class Cluster;
34 class InternalLineMetrics;
35 class ParagraphImpl;
36 class TextLine;
37
38 typedef size_t RunIndex;
39 const size_t EMPTY_RUN = EMPTY_INDEX;
40
41 typedef size_t ClusterIndex;
42 typedef SkRange<size_t> ClusterRange;
43 const size_t EMPTY_CLUSTER = EMPTY_INDEX;
44 const SkRange<size_t> EMPTY_CLUSTERS = EMPTY_RANGE;
45
46 typedef size_t GraphemeIndex;
47 typedef SkRange<GraphemeIndex> GraphemeRange;
48
49 typedef size_t GlyphIndex;
50 typedef SkRange<GlyphIndex> GlyphRange;
51
52 // LTR: [start: end) where start <= end
53 // RTL: [end: start) where start >= end
54 class DirText {
DirText(bool dir,size_t s,size_t e)55 DirText(bool dir, size_t s, size_t e) : start(s), end(e) { }
isLeftToRight()56 bool isLeftToRight() const { return start <= end; }
57 size_t start;
58 size_t end;
59 };
60
61 enum class RoundRectType {
62 NONE,
63 LEFT_ONLY,
64 RIGHT_ONLY,
65 ALL,
66 };
67
68 // first: words length, second: spacing width ratio
69 constexpr SkScalar AUTO_SPACING_WIDTH_RATIO = 8;
70
71 #ifdef OHOS_SUPPORT
72 enum class ScaleOP {
73 COMPRESS,
74 DECOMPRESS,
75 };
76
77 struct SplitPoint {
78 size_t lineIndex;
79 size_t runIndex;
80 size_t headClusterIndex;
81 size_t tailClusterIndex;
82 };
83 #ifdef USE_SKIA_TXT
84 void scaleFontWithCompressionConfig(RSFont& font, ScaleOP op);
85 void metricsIncludeFontPadding(RSFontMetrics* metrics, const RSFont& font);
86 #else
87 void scaleFontWithCompressionConfig(SkFont& font, ScaleOP op);
88 void metricsIncludeFontPadding(SkFontMetrics* metrics, const SkFont& font);
89 #endif
90 #endif
91
92 class Run {
93 public:
94 Run(ParagraphImpl* owner,
95 const SkShaper::RunHandler::RunInfo& info,
96 size_t firstChar,
97 SkScalar heightMultiplier,
98 bool useHalfLeading,
99 SkScalar baselineShift,
100 size_t index,
101 SkScalar shiftX);
102 Run(const Run&) = default;
103 Run& operator=(const Run&) = delete;
104 Run(Run&&) = default;
105 Run& operator=(Run&&) = delete;
106 ~Run() = default;
107
setOwner(ParagraphImpl * owner)108 void setOwner(ParagraphImpl* owner) { fOwner = owner; }
109
110 SkShaper::RunHandler::Buffer newRunBuffer();
111
112 SkScalar posX(size_t index) const;
addX(size_t index,SkScalar shift)113 void addX(size_t index, SkScalar shift) { fPositions[index].fX += shift; }
halfLetterspacing(size_t index)114 SkScalar halfLetterspacing(size_t index) const { return fHalfLetterspacings[index]; }
posY(size_t index)115 SkScalar posY(size_t index) const { return fPositions[index].fY; }
size()116 size_t size() const { return fGlyphs.size(); }
setWidth(SkScalar width)117 void setWidth(SkScalar width) { fAdvance.fX = width; }
setHeight(SkScalar height)118 void setHeight(SkScalar height) { fAdvance.fY = height; }
shift(SkScalar shiftX,SkScalar shiftY)119 void shift(SkScalar shiftX, SkScalar shiftY) {
120 fOffset.fX += shiftX;
121 fOffset.fY += shiftY;
122 }
fAdvanceX()123 SkScalar fAdvanceX() const { return fAdvance.fX; }
advance()124 SkVector advance() const {
125 return SkVector::Make(fAdvance.fX, fFontMetrics.fDescent - fFontMetrics.fAscent + fFontMetrics.fLeading);
126 }
offset()127 SkVector offset() const { return fOffset; }
ascent()128 SkScalar ascent() const { return fFontMetrics.fAscent + fBaselineShift; }
descent()129 SkScalar descent() const { return fFontMetrics.fDescent + fBaselineShift; }
leading()130 SkScalar leading() const { return fFontMetrics.fLeading; }
correctAscent()131 SkScalar correctAscent() const { return fCorrectAscent + fBaselineShift; }
correctDescent()132 SkScalar correctDescent() const { return fCorrectDescent + fBaselineShift; }
correctLeading()133 SkScalar correctLeading() const { return fCorrectLeading; }
134 #ifndef USE_SKIA_TXT
font()135 const SkFont& font() const { return fFont; }
136 #else
font()137 const RSFont& font() const { return fFont; }
138 #endif
leftToRight()139 bool leftToRight() const { return fBidiLevel % 2 == 0; }
getTextDirection()140 TextDirection getTextDirection() const { return leftToRight() ? TextDirection::kLtr : TextDirection::kRtl; }
index()141 size_t index() const { return fIndex; }
heightMultiplier()142 SkScalar heightMultiplier() const { return fHeightMultiplier; }
useHalfLeading()143 bool useHalfLeading() const { return fUseHalfLeading; }
144 #ifdef OHOS_SUPPORT
getRunTotalShift()145 SkScalar getRunTotalShift() const { return fBaselineShift + getVerticalAlignShift(); }
146 #endif
baselineShift()147 SkScalar baselineShift() const { return fBaselineShift; }
148 PlaceholderStyle* placeholderStyle() const;
isPlaceholder()149 bool isPlaceholder() const { return fPlaceholderIndex != std::numeric_limits<size_t>::max(); }
clusterIndex(size_t pos)150 size_t clusterIndex(size_t pos) const { return fClusterIndexes[pos]; }
151 #ifdef OHOS_SUPPORT
152 size_t globalClusterIndex(size_t pos) const;
153 #else
globalClusterIndex(size_t pos)154 size_t globalClusterIndex(size_t pos) const { return fClusterStart + fClusterIndexes[pos]; }
155 #endif
156 SkScalar positionX(size_t pos) const;
157 SkScalar usingAutoSpaceWidth(const Cluster& cluster) const;
textRange()158 TextRange textRange() const { return fTextRange; }
clusterRange()159 ClusterRange clusterRange() const { return fClusterRange; }
160
owner()161 ParagraphImpl* owner() const { return fOwner; }
162
isEllipsis()163 bool isEllipsis() const { return fEllipsis; }
164
165 void calculateMetrics();
166 void updateMetrics(InternalLineMetrics* endlineMetrics);
167
setClusterRange(size_t from,size_t to)168 void setClusterRange(size_t from, size_t to) { fClusterRange = ClusterRange(from, to); }
clip()169 SkRect clip() const {
170 return SkRect::MakeXYWH(fOffset.fX, fOffset.fY, fAdvance.fX, fAdvance.fY);
171 }
getAutoSpacings()172 const SkSTArray<PARAM_64, SkPoint, true>& getAutoSpacings() const {
173 return fAutoSpacings;
174 }
175 void addSpacesAtTheEnd(SkScalar space, Cluster* cluster);
176 SkScalar addSpacesEvenly(SkScalar space, Cluster* cluster);
177 SkScalar addSpacesEvenly(SkScalar space);
178 void shift(const Cluster* cluster, SkScalar offset);
179
180 #ifdef OHOS_SUPPORT
181 Run(const Run& run, size_t runIndex);
182 size_t findSplitClusterPos(size_t target);
183 void updateSplitRunRangeInfo(Run& splitRun, const TextLine& splitLine, size_t headIndex, size_t tailIndex);
184 void updateSplitRunMesureInfo(Run& splitRun, size_t startClusterPos, size_t endClusterPos);
185 void generateSplitRun(Run& splitRun, const SplitPoint& splitPoint);
186 void extendClusterWidth(Cluster* cluster, SkScalar space);
187 bool isTrailingSpaceIncluded(const ClusterRange& fTextLineClusterRange,
188 const ClusterRange& fTextLineGhostClusterRange) const;
189 void updatePlaceholderAlignmentIfNeeded(PlaceholderAlignment& alignment, TextVerticalAlign paragraphAlignment);
190 #endif
calculateHeight(LineMetricStyle ascentStyle,LineMetricStyle descentStyle)191 SkScalar calculateHeight(LineMetricStyle ascentStyle, LineMetricStyle descentStyle) const {
192 auto ascent = ascentStyle == LineMetricStyle::Typographic ? this->ascent()
193 : this->correctAscent();
194 auto descent = descentStyle == LineMetricStyle::Typographic ? this->descent()
195 : this->correctDescent();
196 return descent - ascent;
197 }
198 SkScalar calculateWidth(size_t start, size_t end, bool clip) const;
199
200 #ifndef USE_SKIA_TXT
201 void copyTo(SkTextBlobBuilder& builder, size_t pos, size_t size) const;
202 #else
203 void copyTo(RSTextBlobBuilder& builder, size_t pos, size_t size) const;
204 void copyTo(RSTextBlobBuilder& builder,
205 const RSPath* path,
206 float hOffset,
207 float vOffset,
208 float fTextShift,
209 size_t pos,
210 size_t size) const;
211 #endif
212
213 template<typename Visitor>
214 void iterateThroughClustersInTextOrder(Visitor visitor);
215
216 #ifdef OHOS_SUPPORT
217 template<typename Visitor>
218 void iterateGlyphRangeInTextOrder(const GlyphRange& glyphRange, Visitor visitor);
getVerticalAlignShift()219 SkScalar getVerticalAlignShift() const { return fVerticalAlignShift; }
setVerticalAlignShift(SkScalar verticalAlignShift)220 void setVerticalAlignShift(SkScalar verticalAlignShift) { fVerticalAlignShift = verticalAlignShift; }
221 #endif
222
223 using ClusterVisitor = std::function<void(Cluster* cluster)>;
224 void iterateThroughClusters(const ClusterVisitor& visitor);
225
226 std::tuple<bool, ClusterIndex, ClusterIndex> findLimitingClusters(TextRange text) const;
227 std::tuple<bool, TextIndex, TextIndex> findLimitingGlyphClusters(TextRange text) const;
228 std::tuple<bool, TextIndex, TextIndex> findLimitingGraphemes(TextRange text) const;
glyphs()229 SkSpan<const SkGlyphID> glyphs() const {
230 return SkSpan<const SkGlyphID>(fGlyphs.begin(), fGlyphs.size());
231 }
positions()232 SkSpan<const SkPoint> positions() const {
233 return SkSpan<const SkPoint>(fPositions.begin(), fPositions.size());
234 }
offsets()235 SkSpan<const SkPoint> offsets() const {
236 return SkSpan<const SkPoint>(fOffsets.begin(), fOffsets.size());
237 }
clusterIndexes()238 SkSpan<const uint32_t> clusterIndexes() const {
239 return SkSpan<const uint32_t>(fClusterIndexes.begin(), fClusterIndexes.size());
240 }
241 #ifdef OHOS_SUPPORT
advances()242 SkSpan<const SkPoint> advances() const {
243 return SkSpan<const SkPoint>(fGlyphAdvances.begin(), fGlyphAdvances.size());
244 }
245 #endif
commit()246 void commit() { }
247
resetJustificationShifts()248 void resetJustificationShifts() {
249 fJustificationShifts.reset();
250 }
251
resetAutoSpacing()252 void resetAutoSpacing() {
253 fAutoSpacings.reset();
254 }
255
256 bool isResolved() const;
257
getTopInGroup()258 SkScalar getTopInGroup() const { return fTopInGroup; }
setTopInGroup(SkScalar top)259 void setTopInGroup(SkScalar top) { fTopInGroup = top; }
260
getBottomInGroup()261 SkScalar getBottomInGroup() const { return fBottomInGroup; }
setBottomInGroup(SkScalar bottom)262 void setBottomInGroup(SkScalar bottom) { fBottomInGroup = bottom; }
263
getMaxRoundRectRadius()264 SkScalar getMaxRoundRectRadius() const { return fMaxRoundRectRadius; }
setMaxRoundRectRadius(SkScalar radius)265 void setMaxRoundRectRadius(SkScalar radius) { fMaxRoundRectRadius = radius; }
266
getIndexInLine()267 size_t getIndexInLine() const { return indexInLine; }
setIndexInLine(size_t index)268 void setIndexInLine(size_t index) { indexInLine = index; }
269
270 private:
271 friend class ParagraphImpl;
272 friend class TextLine;
273 friend class InternalLineMetrics;
274 friend class ParagraphCache;
275 friend class OneLineShaper;
276
277 ParagraphImpl* fOwner;
278 TextRange fTextRange;
279 ClusterRange fClusterRange;
280
281 #ifndef USE_SKIA_TXT
282 SkFont fFont;
283 #else
284 RSFont fFont;
285 #endif
286 size_t fPlaceholderIndex;
287 size_t fIndex;
288 SkVector fAdvance;
289 SkVector fOffset;
290 TextIndex fClusterStart;
291 SkShaper::RunHandler::Range fUtf8Range;
292
293 // These fields are not modified after shaping completes and can safely be
294 // shared among copies of the run that are held by different paragraphs.
295 struct GlyphData {
296 SkSTArray<64, SkGlyphID, true> glyphs;
297 SkSTArray<64, SkPoint, true> positions;
298 SkSTArray<64, SkPoint, true> offsets;
299 SkSTArray<64, uint32_t, true> clusterIndexes;
300 #ifdef OHOS_SUPPORT
301 SkSTArray<PARAM_64, SkPoint, true> advances;
302 #endif
303 };
304 std::shared_ptr<GlyphData> fGlyphData;
305 SkSTArray<64, SkGlyphID, true>& fGlyphs;
306 SkSTArray<64, SkPoint, true>& fPositions;
307 SkSTArray<64, SkPoint, true>& fOffsets;
308 SkSTArray<64, uint32_t, true>& fClusterIndexes;
309 #ifdef OHOS_SUPPORT
310 SkSTArray<PARAM_64, SkPoint, true>& fGlyphAdvances;
311 #endif
312 SkSTArray<64, SkPoint, true> fJustificationShifts; // For justification
313 // (current and prev shifts)
314 SkSTArray<PARAM_64, SkPoint, true> fAutoSpacings; // For auto spacing
315 // (current and prev spacings)
316 SkSTArray<PARAM_64, SkScalar, true> fHalfLetterspacings; // For letterspacing
317
318 #ifndef USE_SKIA_TXT
319 SkFontMetrics fFontMetrics;
320 #else
321 RSFontMetrics fFontMetrics;
322 #endif
323 const SkScalar fHeightMultiplier;
324 const bool fUseHalfLeading;
325 const SkScalar fBaselineShift;
326 SkScalar fCorrectAscent;
327 SkScalar fCorrectDescent;
328 SkScalar fCorrectLeading;
329
330 bool fEllipsis;
331 uint8_t fBidiLevel;
332
333 SkScalar fTopInGroup = 0.0f;
334 SkScalar fBottomInGroup = 0.0f;
335 SkScalar fMaxRoundRectRadius = 0.0f;
336 size_t indexInLine;
337 #ifdef OHOS_SUPPORT
338 SkScalar fCompressionBaselineShift{0.0f};
339 SkScalar fVerticalAlignShift{0.0f};
340 #endif
341 };
342
343 template<typename Visitor>
iterateThroughClustersInTextOrder(Visitor visitor)344 void Run::iterateThroughClustersInTextOrder(Visitor visitor) {
345 // Can't figure out how to do it with one code for both cases without 100 ifs
346 // Can't go through clusters because there are no cluster table yet
347 if (leftToRight()) {
348 size_t start = 0;
349 size_t cluster = this->clusterIndex(start);
350 for (size_t glyph = 1; glyph <= this->size(); ++glyph) {
351 auto nextCluster = this->clusterIndex(glyph);
352 if (nextCluster <= cluster) {
353 continue;
354 }
355
356 visitor(start,
357 glyph,
358 fClusterStart + cluster,
359 fClusterStart + nextCluster,
360 this->calculateWidth(start, glyph, glyph == size()),
361 this->calculateHeight(LineMetricStyle::CSS, LineMetricStyle::CSS));
362
363 start = glyph;
364 cluster = nextCluster;
365 }
366 } else {
367 size_t glyph = this->size();
368 size_t cluster = this->fUtf8Range.begin();
369 for (int32_t start = this->size() - 1; start >= 0; --start) {
370 #ifdef OHOS_SUPPORT
371 size_t nextCluster =
372 start == 0 ? this->fUtf8Range.end() : this->clusterIndex(start);
373 #else
374 size_t nextCluster =
375 start == 0 ? this->fUtf8Range.end() : this->clusterIndex(start - 1);
376 #endif
377 if (nextCluster <= cluster) {
378 continue;
379 }
380
381 visitor(start,
382 glyph,
383 fClusterStart + cluster,
384 fClusterStart + nextCluster,
385 this->calculateWidth(start, glyph, glyph == 0),
386 this->calculateHeight(LineMetricStyle::CSS, LineMetricStyle::CSS));
387
388 glyph = start;
389 cluster = nextCluster;
390 }
391 }
392 }
393
394 #ifdef OHOS_SUPPORT
395 template<typename Visitor>
iterateGlyphRangeInTextOrder(const GlyphRange & glyphRange,Visitor visitor)396 void Run::iterateGlyphRangeInTextOrder(const GlyphRange& glyphRange, Visitor visitor) {
397 if (glyphRange.start >= glyphRange.end || glyphRange.end > size()) {
398 return;
399 }
400 if (leftToRight()) {
401 size_t start = glyphRange.start;
402 size_t cluster = this->clusterIndex(start);
403 for (size_t glyph = glyphRange.start + 1; glyph <= glyphRange.end; ++glyph) {
404 auto nextCluster = this->clusterIndex(glyph);
405 if (nextCluster <= cluster) {
406 continue;
407 }
408
409 visitor(start, glyph, fClusterStart + cluster, fClusterStart + nextCluster);
410 start = glyph;
411 cluster = nextCluster;
412 }
413 } else {
414 size_t glyph = glyphRange.end;
415 size_t cluster = this->clusterIndex(glyphRange.end);
416 int32_t glyphStart = std::max((int32_t)glyphRange.start, 0);
417 for (int32_t start = glyphRange.end - 1; start >= glyphStart; --start) {
418 size_t nextCluster = start == 0 ? this->fUtf8Range.end() : this->clusterIndex(start);
419 if (nextCluster <= cluster) {
420 continue;
421 }
422
423 visitor(start, glyph, fClusterStart + cluster, fClusterStart + nextCluster);
424 glyph = start;
425 cluster = nextCluster;
426 }
427 }
428 }
429 #endif
430
431 class Cluster {
432 public:
433
434 #ifdef OHOS_SUPPORT
435 enum AutoSpacingFlag {
436 NoFlag = 0,
437 CJK,
438 Western,
439 Copyright
440 };
441 #endif
442
443 enum BreakType {
444 None,
445 GraphemeBreak, // calculated for all clusters (UBRK_CHARACTER)
446 SoftLineBreak, // calculated for all clusters (UBRK_LINE & UBRK_CHARACTER)
447 HardLineBreak, // calculated for all clusters (UBRK_LINE)
448 };
449
Cluster()450 Cluster()
451 : fOwner(nullptr)
452 , fRunIndex(EMPTY_RUN)
453 , fTextRange(EMPTY_TEXT)
454 , fGraphemeRange(EMPTY_RANGE)
455 , fStart(0)
456 , fEnd()
457 , fWidth()
458 , fHeight()
459 , fHalfLetterSpacing(0.0) {}
460
461 Cluster(ParagraphImpl* owner,
462 RunIndex runIndex,
463 size_t start,
464 size_t end,
465 SkSpan<const char> text,
466 SkScalar width,
467 SkScalar height);
468
Cluster(TextRange textRange)469 Cluster(TextRange textRange) : fTextRange(textRange), fGraphemeRange(EMPTY_RANGE) { }
470
471 Cluster(const Cluster&) = default;
472 ~Cluster() = default;
473
474 SkScalar sizeToChar(TextIndex ch) const;
475 SkScalar sizeFromChar(TextIndex ch) const;
476
477 size_t roundPos(SkScalar s) const;
478
space(SkScalar shift)479 void space(SkScalar shift) {
480 fWidth += shift;
481 }
482
getOwner()483 ParagraphImpl* getOwner() const { return fOwner; }
setOwner(ParagraphImpl * owner)484 void setOwner(ParagraphImpl* owner) { fOwner = owner; }
485
isWhitespaceBreak()486 bool isWhitespaceBreak() const { return fIsWhiteSpaceBreak; }
isIntraWordBreak()487 bool isIntraWordBreak() const { return fIsIntraWordBreak; }
isHardBreak()488 bool isHardBreak() const { return fIsHardBreak; }
isIdeographic()489 bool isIdeographic() const { return fIsIdeographic; }
isWordBreak()490 bool isWordBreak() const { return isWhitespaceBreak() || isHardBreak() || isSoftBreak() || run().isPlaceholder(); }
491 #ifdef OHOS_SUPPORT
isTabulation()492 bool isTabulation() const { return fIsTabulation; }
isPunctuation()493 bool isPunctuation() const { return fIsPunctuation; }
isEllipsis()494 bool isEllipsis() const { return fIsEllipsis; }
needAutoSpacing()495 bool needAutoSpacing() const { return fNeedAutoSpacing; }
enableHyphenBreak()496 void enableHyphenBreak() { fHyphenBreak = true; }
isHyphenBreak()497 bool isHyphenBreak() const { return fHyphenBreak; }
498 bool isStartCombineBreak() const;
499 bool isEndCombineBreak() const;
500 #endif
501
502 bool isSoftBreak() const;
503 bool isGraphemeBreak() const;
canBreakLineAfter()504 bool canBreakLineAfter() const { return isHardBreak() || isSoftBreak(); }
startPos()505 size_t startPos() const { return fStart; }
endPos()506 size_t endPos() const { return fEnd; }
width()507 SkScalar width() const { return fWidth; }
height()508 SkScalar height() const { return fHeight; }
size()509 size_t size() const { return fEnd - fStart; }
510
setHalfLetterSpacing(SkScalar halfLetterSpacing)511 void setHalfLetterSpacing(SkScalar halfLetterSpacing) { fHalfLetterSpacing = halfLetterSpacing; }
getHalfLetterSpacing()512 SkScalar getHalfLetterSpacing() const { return fHalfLetterSpacing; }
513
textRange()514 TextRange textRange() const { return fTextRange; }
515
runIndex()516 RunIndex runIndex() const { return fRunIndex; }
owner()517 ParagraphImpl* owner() const { return fOwner; }
518
519 Run* runOrNull() const;
520 Run& run() const;
521 #ifndef USE_SKIA_TXT
522 SkFont font() const;
523 #else
524 RSFont font() const;
525 #endif
526
527 SkScalar trimmedWidth(size_t pos) const;
528
contains(TextIndex ch)529 bool contains(TextIndex ch) const { return ch >= fTextRange.start && ch < fTextRange.end; }
530
belongs(TextRange text)531 bool belongs(TextRange text) const {
532 return fTextRange.start >= text.start && fTextRange.end <= text.end;
533 }
534
startsIn(TextRange text)535 bool startsIn(TextRange text) const {
536 return fTextRange.start >= text.start && fTextRange.start < text.end;
537 }
538
539 #ifdef OHOS_SUPPORT
getFontSize()540 SkScalar getFontSize() const {
541 return font().GetSize();
542 }
543
getBadgeType()544 TextBadgeType getBadgeType() const { return fBadgeType; }
545
setBadgeType(TextBadgeType badgeType)546 void setBadgeType(TextBadgeType badgeType) {
547 fBadgeType = badgeType;
548 }
549 #endif
550
551 private:
552
553 friend ParagraphImpl;
554
555 ParagraphImpl* fOwner;
556 RunIndex fRunIndex;
557 TextRange fTextRange;
558 GraphemeRange fGraphemeRange;
559
560 size_t fStart;
561 size_t fEnd;
562 SkScalar fWidth;
563 SkScalar fHeight;
564 SkScalar fHalfLetterSpacing;
565
566 bool fIsWhiteSpaceBreak;
567 bool fIsIntraWordBreak;
568 bool fIsHardBreak;
569 bool fIsIdeographic;
570 #ifdef OHOS_SUPPORT
571 bool fIsTabulation;
572 bool fIsPunctuation{false};
573 bool fIsEllipsis{false};
574 bool fNeedAutoSpacing{false}; // depend on last cluster flag
575 bool fHyphenBreak{false};
576 TextBadgeType fBadgeType{TextBadgeType::BADGE_NONE};
577 #endif
578 };
579
580 class InternalLineMetrics {
581 public:
582
InternalLineMetrics()583 InternalLineMetrics() {
584 clean();
585 fForceStrut = false;
586 }
587
InternalLineMetrics(bool forceStrut)588 InternalLineMetrics(bool forceStrut) {
589 clean();
590 fForceStrut = forceStrut;
591 }
592
InternalLineMetrics(SkScalar a,SkScalar d,SkScalar l)593 InternalLineMetrics(SkScalar a, SkScalar d, SkScalar l) {
594 fAscent = a;
595 fDescent = d;
596 fLeading = l;
597 fRawAscent = a;
598 fRawDescent = d;
599 fRawLeading = l;
600 fForceStrut = false;
601 }
602
InternalLineMetrics(SkScalar a,SkScalar d,SkScalar l,SkScalar ra,SkScalar rd,SkScalar rl)603 InternalLineMetrics(SkScalar a, SkScalar d, SkScalar l, SkScalar ra, SkScalar rd, SkScalar rl) {
604 fAscent = a;
605 fDescent = d;
606 fLeading = l;
607 fRawAscent = ra;
608 fRawDescent = rd;
609 fRawLeading = rl;
610 fForceStrut = false;
611 }
612
613 #ifdef OHOS_SUPPORT
614 #ifdef USE_SKIA_TXT
InternalLineMetrics(const RSFont & font,bool forceStrut)615 InternalLineMetrics(const RSFont& font, bool forceStrut) {
616 RSFontMetrics metrics;
617 auto compressFont = font;
618 scaleFontWithCompressionConfig(compressFont, ScaleOP::COMPRESS);
619 compressFont.GetMetrics(&metrics);
620 #else
621 InternalLineMetrics(const SkFont& font, bool forceStrut) {
622 SkFontMetrics metrics;
623 auto compressFont = font;
624 scaleFontWithCompressionConfig(compressFont, ScaleOP::COMPRESS);
625 compressFont.getMetrics(&metrics);
626 #endif
627 metricsIncludeFontPadding(&metrics, font);
628 #else
629 InternalLineMetrics(const SkFont& font, bool forceStrut) {
630 SkFontMetrics metrics;
631 font.getMetrics(&metrics);
632 #endif
633 fAscent = metrics.fAscent;
634 fDescent = metrics.fDescent;
635 fLeading = metrics.fLeading;
636 fRawAscent = metrics.fAscent;
637 fRawDescent = metrics.fDescent;
638 fRawLeading = metrics.fLeading;
639 fForceStrut = forceStrut;
640 }
641
642 void add(Run* run) {
643 if (fForceStrut) {
644 return;
645 }
646 fAscent = std::min(fAscent, run->correctAscent());
647 fDescent = std::max(fDescent, run->correctDescent());
648 fLeading = std::max(fLeading, run->correctLeading());
649
650 fRawAscent = std::min(fRawAscent, run->ascent());
651 fRawDescent = std::max(fRawDescent, run->descent());
652 fRawLeading = std::max(fRawLeading, run->leading());
653 }
654
655 void add(InternalLineMetrics other) {
656 fAscent = std::min(fAscent, other.fAscent);
657 fDescent = std::max(fDescent, other.fDescent);
658 fLeading = std::max(fLeading, other.fLeading);
659 fRawAscent = std::min(fRawAscent, other.fRawAscent);
660 fRawDescent = std::max(fRawDescent, other.fRawDescent);
661 fRawLeading = std::max(fRawLeading, other.fRawLeading);
662 }
663
664 void clean() {
665 fAscent = SK_ScalarMax;
666 fDescent = SK_ScalarMin;
667 fLeading = 0;
668 fRawAscent = SK_ScalarMax;
669 fRawDescent = SK_ScalarMin;
670 fRawLeading = 0;
671 }
672
673 bool isClean() {
674 return (fAscent == SK_ScalarMax &&
675 fDescent == SK_ScalarMin &&
676 fLeading == 0 &&
677 fRawAscent == SK_ScalarMax &&
678 fRawDescent == SK_ScalarMin &&
679 fRawLeading == 0);
680 }
681
682 SkScalar delta() const { return height() - ideographicBaseline(); }
683
684 void updateLineMetrics(InternalLineMetrics& metrics) {
685 if (metrics.fForceStrut) {
686 metrics.fAscent = fAscent;
687 metrics.fDescent = fDescent;
688 metrics.fLeading = fLeading;
689 metrics.fRawAscent = fRawAscent;
690 metrics.fRawDescent = fRawDescent;
691 metrics.fRawLeading = fRawLeading;
692 } else {
693 // This is another of those flutter changes. To be removed...
694 metrics.fAscent = std::min(metrics.fAscent, fAscent - fLeading / 2.0f);
695 metrics.fDescent = std::max(metrics.fDescent, fDescent + fLeading / 2.0f);
696 metrics.fRawAscent = std::min(metrics.fRawAscent, fRawAscent - fRawLeading / 2.0f);
697 metrics.fRawDescent = std::max(metrics.fRawDescent, fRawDescent + fRawLeading / 2.0f);
698 }
699 }
700
701 #ifdef OHOS_SUPPORT
702 SkScalar runTop(const Run* run, LineMetricStyle ascentStyle) const {
703 return fLeading / 2 - fAscent + (ascentStyle == LineMetricStyle::Typographic ?
704 run->ascent() : run->correctAscent() + run->getVerticalAlignShift()) + delta();
705 }
706 #else
707 SkScalar runTop(const Run* run, LineMetricStyle ascentStyle) const {
708 return fLeading / 2 - fAscent +
709 (ascentStyle == LineMetricStyle::Typographic ? run->ascent() : run->correctAscent()) + delta();
710 }
711 #endif
712
713 SkScalar height() const {
714 return ::round((double)fDescent - fAscent + fLeading);
715 }
716
717 void update(SkScalar a, SkScalar d, SkScalar l) {
718 fAscent = a;
719 fDescent = d;
720 fLeading = l;
721 }
722
723 void updateRawData(SkScalar ra, SkScalar rd) {
724 fRawAscent = ra;
725 fRawDescent = rd;
726 }
727
728 SkScalar alphabeticBaseline() const { return fLeading / 2 - fAscent; }
729 SkScalar ideographicBaseline() const { return fDescent - fAscent + fLeading; }
730 SkScalar deltaBaselines() const { return fLeading / 2 + fDescent; }
731 SkScalar baseline() const { return fLeading / 2 - fAscent; }
732 SkScalar ascent() const { return fAscent; }
733 SkScalar descent() const { return fDescent; }
734 SkScalar leading() const { return fLeading; }
735 SkScalar rawAscent() const { return fRawAscent; }
736 SkScalar rawDescent() const { return fRawDescent; }
737 void setForceStrut(bool value) { fForceStrut = value; }
738 bool getForceStrut() const { return fForceStrut; }
739
740 private:
741
742 friend class ParagraphImpl;
743 friend class TextWrapper;
744 friend class TextLine;
745
746 SkScalar fAscent;
747 SkScalar fDescent;
748 SkScalar fLeading;
749
750 SkScalar fRawAscent;
751 SkScalar fRawDescent;
752 SkScalar fRawLeading;
753
754 bool fForceStrut;
755 };
756 } // namespace textlayout
757 } // namespace skia
758
759 #endif // Run_DEFINED
760