• 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/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