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