xref: /aosp_15_r20/external/skia/modules/skparagraph/src/Run.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker // Copyright 2019 Google LLC.
2*c8dee2aaSAndroid Build Coastguard Worker #ifndef Run_DEFINED
3*c8dee2aaSAndroid Build Coastguard Worker #define Run_DEFINED
4*c8dee2aaSAndroid Build Coastguard Worker 
5*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkFont.h"
6*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkFontMetrics.h"
7*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPoint.h"
8*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRect.h"
9*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkScalar.h"
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSpan.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTypes.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkTArray.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "modules/skparagraph/include/DartTypes.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "modules/skparagraph/include/TextStyle.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "modules/skshaper/include/SkShaper.h"
16*c8dee2aaSAndroid Build Coastguard Worker 
17*c8dee2aaSAndroid Build Coastguard Worker #include <math.h>
18*c8dee2aaSAndroid Build Coastguard Worker #include <algorithm>
19*c8dee2aaSAndroid Build Coastguard Worker #include <functional>
20*c8dee2aaSAndroid Build Coastguard Worker #include <limits>
21*c8dee2aaSAndroid Build Coastguard Worker #include <tuple>
22*c8dee2aaSAndroid Build Coastguard Worker 
23*c8dee2aaSAndroid Build Coastguard Worker class SkTextBlobBuilder;
24*c8dee2aaSAndroid Build Coastguard Worker 
25*c8dee2aaSAndroid Build Coastguard Worker namespace skia {
26*c8dee2aaSAndroid Build Coastguard Worker namespace textlayout {
27*c8dee2aaSAndroid Build Coastguard Worker 
28*c8dee2aaSAndroid Build Coastguard Worker class Cluster;
29*c8dee2aaSAndroid Build Coastguard Worker class InternalLineMetrics;
30*c8dee2aaSAndroid Build Coastguard Worker class ParagraphImpl;
31*c8dee2aaSAndroid Build Coastguard Worker 
32*c8dee2aaSAndroid Build Coastguard Worker typedef size_t RunIndex;
33*c8dee2aaSAndroid Build Coastguard Worker const size_t EMPTY_RUN = EMPTY_INDEX;
34*c8dee2aaSAndroid Build Coastguard Worker 
35*c8dee2aaSAndroid Build Coastguard Worker typedef size_t ClusterIndex;
36*c8dee2aaSAndroid Build Coastguard Worker typedef SkRange<size_t> ClusterRange;
37*c8dee2aaSAndroid Build Coastguard Worker const size_t EMPTY_CLUSTER = EMPTY_INDEX;
38*c8dee2aaSAndroid Build Coastguard Worker const SkRange<size_t> EMPTY_CLUSTERS = EMPTY_RANGE;
39*c8dee2aaSAndroid Build Coastguard Worker 
40*c8dee2aaSAndroid Build Coastguard Worker typedef size_t GraphemeIndex;
41*c8dee2aaSAndroid Build Coastguard Worker typedef SkRange<GraphemeIndex> GraphemeRange;
42*c8dee2aaSAndroid Build Coastguard Worker 
43*c8dee2aaSAndroid Build Coastguard Worker typedef size_t GlyphIndex;
44*c8dee2aaSAndroid Build Coastguard Worker typedef SkRange<GlyphIndex> GlyphRange;
45*c8dee2aaSAndroid Build Coastguard Worker 
46*c8dee2aaSAndroid Build Coastguard Worker // LTR: [start: end) where start <= end
47*c8dee2aaSAndroid Build Coastguard Worker // RTL: [end: start) where start >= end
48*c8dee2aaSAndroid Build Coastguard Worker class DirText {
DirText(bool dir,size_t s,size_t e)49*c8dee2aaSAndroid Build Coastguard Worker     DirText(bool dir, size_t s, size_t e) : start(s), end(e) { }
isLeftToRight()50*c8dee2aaSAndroid Build Coastguard Worker     bool isLeftToRight() const { return start <= end; }
51*c8dee2aaSAndroid Build Coastguard Worker     size_t start;
52*c8dee2aaSAndroid Build Coastguard Worker     size_t end;
53*c8dee2aaSAndroid Build Coastguard Worker };
54*c8dee2aaSAndroid Build Coastguard Worker 
55*c8dee2aaSAndroid Build Coastguard Worker class Run {
56*c8dee2aaSAndroid Build Coastguard Worker public:
57*c8dee2aaSAndroid Build Coastguard Worker     Run(ParagraphImpl* owner,
58*c8dee2aaSAndroid Build Coastguard Worker         const SkShaper::RunHandler::RunInfo& info,
59*c8dee2aaSAndroid Build Coastguard Worker         size_t firstChar,
60*c8dee2aaSAndroid Build Coastguard Worker         SkScalar heightMultiplier,
61*c8dee2aaSAndroid Build Coastguard Worker         bool useHalfLeading,
62*c8dee2aaSAndroid Build Coastguard Worker         SkScalar baselineShift,
63*c8dee2aaSAndroid Build Coastguard Worker         size_t index,
64*c8dee2aaSAndroid Build Coastguard Worker         SkScalar shiftX);
65*c8dee2aaSAndroid Build Coastguard Worker     Run(const Run&) = default;
66*c8dee2aaSAndroid Build Coastguard Worker     Run& operator=(const Run&) = delete;
67*c8dee2aaSAndroid Build Coastguard Worker     Run(Run&&) = default;
68*c8dee2aaSAndroid Build Coastguard Worker     Run& operator=(Run&&) = delete;
69*c8dee2aaSAndroid Build Coastguard Worker     ~Run() = default;
70*c8dee2aaSAndroid Build Coastguard Worker 
setOwner(ParagraphImpl * owner)71*c8dee2aaSAndroid Build Coastguard Worker     void setOwner(ParagraphImpl* owner) { fOwner = owner; }
72*c8dee2aaSAndroid Build Coastguard Worker 
73*c8dee2aaSAndroid Build Coastguard Worker     SkShaper::RunHandler::Buffer newRunBuffer();
74*c8dee2aaSAndroid Build Coastguard Worker 
posX(size_t index)75*c8dee2aaSAndroid Build Coastguard Worker     SkScalar posX(size_t index) const { return fPositions[index].fX; }
addX(size_t index,SkScalar shift)76*c8dee2aaSAndroid Build Coastguard Worker     void addX(size_t index, SkScalar shift) { fPositions[index].fX += shift; }
posY(size_t index)77*c8dee2aaSAndroid Build Coastguard Worker     SkScalar posY(size_t index) const { return fPositions[index].fY; }
size()78*c8dee2aaSAndroid Build Coastguard Worker     size_t size() const { return fGlyphs.size(); }
setWidth(SkScalar width)79*c8dee2aaSAndroid Build Coastguard Worker     void setWidth(SkScalar width) { fAdvance.fX = width; }
setHeight(SkScalar height)80*c8dee2aaSAndroid Build Coastguard Worker     void setHeight(SkScalar height) { fAdvance.fY = height; }
shift(SkScalar shiftX,SkScalar shiftY)81*c8dee2aaSAndroid Build Coastguard Worker     void shift(SkScalar shiftX, SkScalar shiftY) {
82*c8dee2aaSAndroid Build Coastguard Worker         fOffset.fX += shiftX;
83*c8dee2aaSAndroid Build Coastguard Worker         fOffset.fY += shiftY;
84*c8dee2aaSAndroid Build Coastguard Worker     }
advance()85*c8dee2aaSAndroid Build Coastguard Worker     SkVector advance() const {
86*c8dee2aaSAndroid Build Coastguard Worker         return SkVector::Make(fAdvance.fX, fFontMetrics.fDescent - fFontMetrics.fAscent + fFontMetrics.fLeading);
87*c8dee2aaSAndroid Build Coastguard Worker     }
offset()88*c8dee2aaSAndroid Build Coastguard Worker     SkVector offset() const { return fOffset; }
ascent()89*c8dee2aaSAndroid Build Coastguard Worker     SkScalar ascent() const { return fFontMetrics.fAscent + fBaselineShift; }
descent()90*c8dee2aaSAndroid Build Coastguard Worker     SkScalar descent() const { return fFontMetrics.fDescent + fBaselineShift; }
leading()91*c8dee2aaSAndroid Build Coastguard Worker     SkScalar leading() const { return fFontMetrics.fLeading; }
correctAscent()92*c8dee2aaSAndroid Build Coastguard Worker     SkScalar correctAscent() const { return fCorrectAscent + fBaselineShift; }
correctDescent()93*c8dee2aaSAndroid Build Coastguard Worker     SkScalar correctDescent() const { return fCorrectDescent + fBaselineShift; }
correctLeading()94*c8dee2aaSAndroid Build Coastguard Worker     SkScalar correctLeading() const { return fCorrectLeading; }
font()95*c8dee2aaSAndroid Build Coastguard Worker     const SkFont& font() const { return fFont; }
leftToRight()96*c8dee2aaSAndroid Build Coastguard Worker     bool leftToRight() const { return fBidiLevel % 2 == 0; }
getTextDirection()97*c8dee2aaSAndroid Build Coastguard Worker     TextDirection getTextDirection() const { return leftToRight() ? TextDirection::kLtr : TextDirection::kRtl; }
index()98*c8dee2aaSAndroid Build Coastguard Worker     size_t index() const { return fIndex; }
heightMultiplier()99*c8dee2aaSAndroid Build Coastguard Worker     SkScalar heightMultiplier() const { return fHeightMultiplier; }
useHalfLeading()100*c8dee2aaSAndroid Build Coastguard Worker     bool useHalfLeading() const { return fUseHalfLeading; }
baselineShift()101*c8dee2aaSAndroid Build Coastguard Worker     SkScalar baselineShift() const { return fBaselineShift; }
102*c8dee2aaSAndroid Build Coastguard Worker     PlaceholderStyle* placeholderStyle() const;
isPlaceholder()103*c8dee2aaSAndroid Build Coastguard Worker     bool isPlaceholder() const { return fPlaceholderIndex != std::numeric_limits<size_t>::max(); }
clusterIndex(size_t pos)104*c8dee2aaSAndroid Build Coastguard Worker     size_t clusterIndex(size_t pos) const { return fClusterIndexes[pos]; }
globalClusterIndex(size_t pos)105*c8dee2aaSAndroid Build Coastguard Worker     size_t globalClusterIndex(size_t pos) const { return fClusterStart + fClusterIndexes[pos]; }
106*c8dee2aaSAndroid Build Coastguard Worker     SkScalar positionX(size_t pos) const;
107*c8dee2aaSAndroid Build Coastguard Worker 
textRange()108*c8dee2aaSAndroid Build Coastguard Worker     TextRange textRange() const { return fTextRange; }
clusterRange()109*c8dee2aaSAndroid Build Coastguard Worker     ClusterRange clusterRange() const { return fClusterRange; }
110*c8dee2aaSAndroid Build Coastguard Worker 
owner()111*c8dee2aaSAndroid Build Coastguard Worker     ParagraphImpl* owner() const { return fOwner; }
112*c8dee2aaSAndroid Build Coastguard Worker 
isEllipsis()113*c8dee2aaSAndroid Build Coastguard Worker     bool isEllipsis() const { return fEllipsis; }
114*c8dee2aaSAndroid Build Coastguard Worker 
115*c8dee2aaSAndroid Build Coastguard Worker     void calculateMetrics();
116*c8dee2aaSAndroid Build Coastguard Worker     void updateMetrics(InternalLineMetrics* endlineMetrics);
117*c8dee2aaSAndroid Build Coastguard Worker 
setClusterRange(size_t from,size_t to)118*c8dee2aaSAndroid Build Coastguard Worker     void setClusterRange(size_t from, size_t to) { fClusterRange = ClusterRange(from, to); }
clip()119*c8dee2aaSAndroid Build Coastguard Worker     SkRect clip() const {
120*c8dee2aaSAndroid Build Coastguard Worker         return SkRect::MakeXYWH(fOffset.fX, fOffset.fY, fAdvance.fX, fAdvance.fY);
121*c8dee2aaSAndroid Build Coastguard Worker     }
122*c8dee2aaSAndroid Build Coastguard Worker 
123*c8dee2aaSAndroid Build Coastguard Worker     void addSpacesAtTheEnd(SkScalar space, Cluster* cluster);
124*c8dee2aaSAndroid Build Coastguard Worker     SkScalar addSpacesEvenly(SkScalar space, Cluster* cluster);
125*c8dee2aaSAndroid Build Coastguard Worker     SkScalar addSpacesEvenly(SkScalar space);
126*c8dee2aaSAndroid Build Coastguard Worker     void shift(const Cluster* cluster, SkScalar offset);
127*c8dee2aaSAndroid Build Coastguard Worker     void extend(const Cluster* cluster, SkScalar offset);
128*c8dee2aaSAndroid Build Coastguard Worker 
calculateHeight(LineMetricStyle ascentStyle,LineMetricStyle descentStyle)129*c8dee2aaSAndroid Build Coastguard Worker     SkScalar calculateHeight(LineMetricStyle ascentStyle, LineMetricStyle descentStyle) const {
130*c8dee2aaSAndroid Build Coastguard Worker         auto ascent = ascentStyle == LineMetricStyle::Typographic ? this->ascent()
131*c8dee2aaSAndroid Build Coastguard Worker                                     : this->correctAscent();
132*c8dee2aaSAndroid Build Coastguard Worker         auto descent = descentStyle == LineMetricStyle::Typographic ? this->descent()
133*c8dee2aaSAndroid Build Coastguard Worker                                       : this->correctDescent();
134*c8dee2aaSAndroid Build Coastguard Worker         return descent - ascent;
135*c8dee2aaSAndroid Build Coastguard Worker     }
136*c8dee2aaSAndroid Build Coastguard Worker     SkScalar calculateWidth(size_t start, size_t end, bool clip) const;
137*c8dee2aaSAndroid Build Coastguard Worker 
138*c8dee2aaSAndroid Build Coastguard Worker     void copyTo(SkTextBlobBuilder& builder, size_t pos, size_t size) const;
139*c8dee2aaSAndroid Build Coastguard Worker 
140*c8dee2aaSAndroid Build Coastguard Worker     template<typename Visitor>
141*c8dee2aaSAndroid Build Coastguard Worker     void iterateThroughClustersInTextOrder(Visitor visitor);
142*c8dee2aaSAndroid Build Coastguard Worker 
143*c8dee2aaSAndroid Build Coastguard Worker     using ClusterVisitor = std::function<void(Cluster* cluster)>;
144*c8dee2aaSAndroid Build Coastguard Worker     void iterateThroughClusters(const ClusterVisitor& visitor);
145*c8dee2aaSAndroid Build Coastguard Worker 
146*c8dee2aaSAndroid Build Coastguard Worker     std::tuple<bool, ClusterIndex, ClusterIndex> findLimitingClusters(TextRange text) const;
147*c8dee2aaSAndroid Build Coastguard Worker     std::tuple<bool, TextIndex, TextIndex> findLimitingGlyphClusters(TextRange text) const;
148*c8dee2aaSAndroid Build Coastguard Worker     std::tuple<bool, TextIndex, TextIndex> findLimitingGraphemes(TextRange text) const;
glyphs()149*c8dee2aaSAndroid Build Coastguard Worker     SkSpan<const SkGlyphID> glyphs() const {
150*c8dee2aaSAndroid Build Coastguard Worker         return SkSpan<const SkGlyphID>(fGlyphs.begin(), fGlyphs.size());
151*c8dee2aaSAndroid Build Coastguard Worker     }
positions()152*c8dee2aaSAndroid Build Coastguard Worker     SkSpan<const SkPoint> positions() const {
153*c8dee2aaSAndroid Build Coastguard Worker         return SkSpan<const SkPoint>(fPositions.begin(), fPositions.size());
154*c8dee2aaSAndroid Build Coastguard Worker     }
offsets()155*c8dee2aaSAndroid Build Coastguard Worker     SkSpan<const SkPoint> offsets() const {
156*c8dee2aaSAndroid Build Coastguard Worker         return SkSpan<const SkPoint>(fOffsets.begin(), fOffsets.size());
157*c8dee2aaSAndroid Build Coastguard Worker     }
clusterIndexes()158*c8dee2aaSAndroid Build Coastguard Worker     SkSpan<const uint32_t> clusterIndexes() const {
159*c8dee2aaSAndroid Build Coastguard Worker         return SkSpan<const uint32_t>(fClusterIndexes.begin(), fClusterIndexes.size());
160*c8dee2aaSAndroid Build Coastguard Worker     }
161*c8dee2aaSAndroid Build Coastguard Worker 
commit()162*c8dee2aaSAndroid Build Coastguard Worker     void commit() { }
163*c8dee2aaSAndroid Build Coastguard Worker 
resetJustificationShifts()164*c8dee2aaSAndroid Build Coastguard Worker     void resetJustificationShifts() {
165*c8dee2aaSAndroid Build Coastguard Worker         fJustificationShifts.clear();
166*c8dee2aaSAndroid Build Coastguard Worker     }
167*c8dee2aaSAndroid Build Coastguard Worker 
168*c8dee2aaSAndroid Build Coastguard Worker     bool isResolved() const;
169*c8dee2aaSAndroid Build Coastguard Worker private:
170*c8dee2aaSAndroid Build Coastguard Worker     friend class ParagraphImpl;
171*c8dee2aaSAndroid Build Coastguard Worker     friend class TextLine;
172*c8dee2aaSAndroid Build Coastguard Worker     friend class InternalLineMetrics;
173*c8dee2aaSAndroid Build Coastguard Worker     friend class ParagraphCache;
174*c8dee2aaSAndroid Build Coastguard Worker     friend class OneLineShaper;
175*c8dee2aaSAndroid Build Coastguard Worker 
176*c8dee2aaSAndroid Build Coastguard Worker     ParagraphImpl* fOwner;
177*c8dee2aaSAndroid Build Coastguard Worker     TextRange fTextRange;
178*c8dee2aaSAndroid Build Coastguard Worker     ClusterRange fClusterRange;
179*c8dee2aaSAndroid Build Coastguard Worker 
180*c8dee2aaSAndroid Build Coastguard Worker     SkFont fFont;
181*c8dee2aaSAndroid Build Coastguard Worker     size_t fPlaceholderIndex;
182*c8dee2aaSAndroid Build Coastguard Worker     size_t fIndex;
183*c8dee2aaSAndroid Build Coastguard Worker     SkVector fAdvance;
184*c8dee2aaSAndroid Build Coastguard Worker     SkVector fOffset;
185*c8dee2aaSAndroid Build Coastguard Worker     TextIndex fClusterStart;
186*c8dee2aaSAndroid Build Coastguard Worker     SkShaper::RunHandler::Range fUtf8Range;
187*c8dee2aaSAndroid Build Coastguard Worker 
188*c8dee2aaSAndroid Build Coastguard Worker     // These fields are not modified after shaping completes and can safely be
189*c8dee2aaSAndroid Build Coastguard Worker     // shared among copies of the run that are held by different paragraphs.
190*c8dee2aaSAndroid Build Coastguard Worker     struct GlyphData {
191*c8dee2aaSAndroid Build Coastguard Worker         skia_private::STArray<64, SkGlyphID, true> glyphs;
192*c8dee2aaSAndroid Build Coastguard Worker         skia_private::STArray<64, SkPoint, true> positions;
193*c8dee2aaSAndroid Build Coastguard Worker         skia_private::STArray<64, SkPoint, true> offsets;
194*c8dee2aaSAndroid Build Coastguard Worker         skia_private::STArray<64, uint32_t, true> clusterIndexes;
195*c8dee2aaSAndroid Build Coastguard Worker     };
196*c8dee2aaSAndroid Build Coastguard Worker     std::shared_ptr<GlyphData> fGlyphData;
197*c8dee2aaSAndroid Build Coastguard Worker     skia_private::STArray<64, SkGlyphID, true>& fGlyphs;
198*c8dee2aaSAndroid Build Coastguard Worker     skia_private::STArray<64, SkPoint, true>& fPositions;
199*c8dee2aaSAndroid Build Coastguard Worker     skia_private::STArray<64, SkPoint, true>& fOffsets;
200*c8dee2aaSAndroid Build Coastguard Worker     skia_private::STArray<64, uint32_t, true>& fClusterIndexes;
201*c8dee2aaSAndroid Build Coastguard Worker 
202*c8dee2aaSAndroid Build Coastguard Worker     skia_private::STArray<64, SkPoint, true> fJustificationShifts; // For justification
203*c8dee2aaSAndroid Build Coastguard Worker                                                                    // (current and prev shifts)
204*c8dee2aaSAndroid Build Coastguard Worker 
205*c8dee2aaSAndroid Build Coastguard Worker     SkFontMetrics fFontMetrics;
206*c8dee2aaSAndroid Build Coastguard Worker     const SkScalar fHeightMultiplier;
207*c8dee2aaSAndroid Build Coastguard Worker     const bool fUseHalfLeading;
208*c8dee2aaSAndroid Build Coastguard Worker     const SkScalar fBaselineShift;
209*c8dee2aaSAndroid Build Coastguard Worker     SkScalar fCorrectAscent;
210*c8dee2aaSAndroid Build Coastguard Worker     SkScalar fCorrectDescent;
211*c8dee2aaSAndroid Build Coastguard Worker     SkScalar fCorrectLeading;
212*c8dee2aaSAndroid Build Coastguard Worker 
213*c8dee2aaSAndroid Build Coastguard Worker     bool fEllipsis;
214*c8dee2aaSAndroid Build Coastguard Worker     uint8_t fBidiLevel;
215*c8dee2aaSAndroid Build Coastguard Worker };
216*c8dee2aaSAndroid Build Coastguard Worker 
217*c8dee2aaSAndroid Build Coastguard Worker template<typename Visitor>
iterateThroughClustersInTextOrder(Visitor visitor)218*c8dee2aaSAndroid Build Coastguard Worker void Run::iterateThroughClustersInTextOrder(Visitor visitor) {
219*c8dee2aaSAndroid Build Coastguard Worker     // Can't figure out how to do it with one code for both cases without 100 ifs
220*c8dee2aaSAndroid Build Coastguard Worker     // Can't go through clusters because there are no cluster table yet
221*c8dee2aaSAndroid Build Coastguard Worker     if (leftToRight()) {
222*c8dee2aaSAndroid Build Coastguard Worker         size_t start = 0;
223*c8dee2aaSAndroid Build Coastguard Worker         size_t cluster = this->clusterIndex(start);
224*c8dee2aaSAndroid Build Coastguard Worker         for (size_t glyph = 1; glyph <= this->size(); ++glyph) {
225*c8dee2aaSAndroid Build Coastguard Worker             auto nextCluster = this->clusterIndex(glyph);
226*c8dee2aaSAndroid Build Coastguard Worker             if (nextCluster <= cluster) {
227*c8dee2aaSAndroid Build Coastguard Worker                 continue;
228*c8dee2aaSAndroid Build Coastguard Worker             }
229*c8dee2aaSAndroid Build Coastguard Worker 
230*c8dee2aaSAndroid Build Coastguard Worker             visitor(start,
231*c8dee2aaSAndroid Build Coastguard Worker                     glyph,
232*c8dee2aaSAndroid Build Coastguard Worker                     fClusterStart + cluster,
233*c8dee2aaSAndroid Build Coastguard Worker                     fClusterStart + nextCluster,
234*c8dee2aaSAndroid Build Coastguard Worker                     this->calculateWidth(start, glyph, glyph == size()),
235*c8dee2aaSAndroid Build Coastguard Worker                     this->calculateHeight(LineMetricStyle::CSS, LineMetricStyle::CSS));
236*c8dee2aaSAndroid Build Coastguard Worker 
237*c8dee2aaSAndroid Build Coastguard Worker             start = glyph;
238*c8dee2aaSAndroid Build Coastguard Worker             cluster = nextCluster;
239*c8dee2aaSAndroid Build Coastguard Worker         }
240*c8dee2aaSAndroid Build Coastguard Worker     } else {
241*c8dee2aaSAndroid Build Coastguard Worker         size_t glyph = this->size();
242*c8dee2aaSAndroid Build Coastguard Worker         size_t cluster = this->fUtf8Range.begin();
243*c8dee2aaSAndroid Build Coastguard Worker         for (int32_t start = this->size() - 1; start >= 0; --start) {
244*c8dee2aaSAndroid Build Coastguard Worker             size_t nextCluster =
245*c8dee2aaSAndroid Build Coastguard Worker                     start == 0 ? this->fUtf8Range.end() : this->clusterIndex(start - 1);
246*c8dee2aaSAndroid Build Coastguard Worker             if (nextCluster <= cluster) {
247*c8dee2aaSAndroid Build Coastguard Worker                 continue;
248*c8dee2aaSAndroid Build Coastguard Worker             }
249*c8dee2aaSAndroid Build Coastguard Worker 
250*c8dee2aaSAndroid Build Coastguard Worker             visitor(start,
251*c8dee2aaSAndroid Build Coastguard Worker                     glyph,
252*c8dee2aaSAndroid Build Coastguard Worker                     fClusterStart + cluster,
253*c8dee2aaSAndroid Build Coastguard Worker                     fClusterStart + nextCluster,
254*c8dee2aaSAndroid Build Coastguard Worker                     this->calculateWidth(start, glyph, glyph == 0),
255*c8dee2aaSAndroid Build Coastguard Worker                     this->calculateHeight(LineMetricStyle::CSS, LineMetricStyle::CSS));
256*c8dee2aaSAndroid Build Coastguard Worker 
257*c8dee2aaSAndroid Build Coastguard Worker             glyph = start;
258*c8dee2aaSAndroid Build Coastguard Worker             cluster = nextCluster;
259*c8dee2aaSAndroid Build Coastguard Worker         }
260*c8dee2aaSAndroid Build Coastguard Worker     }
261*c8dee2aaSAndroid Build Coastguard Worker }
262*c8dee2aaSAndroid Build Coastguard Worker 
263*c8dee2aaSAndroid Build Coastguard Worker class Cluster {
264*c8dee2aaSAndroid Build Coastguard Worker public:
265*c8dee2aaSAndroid Build Coastguard Worker     enum BreakType {
266*c8dee2aaSAndroid Build Coastguard Worker         None,
267*c8dee2aaSAndroid Build Coastguard Worker         GraphemeBreak,  // calculated for all clusters (UBRK_CHARACTER)
268*c8dee2aaSAndroid Build Coastguard Worker         SoftLineBreak,  // calculated for all clusters (UBRK_LINE & UBRK_CHARACTER)
269*c8dee2aaSAndroid Build Coastguard Worker         HardLineBreak,  // calculated for all clusters (UBRK_LINE)
270*c8dee2aaSAndroid Build Coastguard Worker     };
271*c8dee2aaSAndroid Build Coastguard Worker 
Cluster()272*c8dee2aaSAndroid Build Coastguard Worker     Cluster()
273*c8dee2aaSAndroid Build Coastguard Worker             : fOwner(nullptr)
274*c8dee2aaSAndroid Build Coastguard Worker             , fRunIndex(EMPTY_RUN)
275*c8dee2aaSAndroid Build Coastguard Worker             , fTextRange(EMPTY_TEXT)
276*c8dee2aaSAndroid Build Coastguard Worker             , fGraphemeRange(EMPTY_RANGE)
277*c8dee2aaSAndroid Build Coastguard Worker             , fStart(0)
278*c8dee2aaSAndroid Build Coastguard Worker             , fEnd()
279*c8dee2aaSAndroid Build Coastguard Worker             , fWidth()
280*c8dee2aaSAndroid Build Coastguard Worker             , fHeight()
281*c8dee2aaSAndroid Build Coastguard Worker             , fHalfLetterSpacing(0.0) {}
282*c8dee2aaSAndroid Build Coastguard Worker 
283*c8dee2aaSAndroid Build Coastguard Worker     Cluster(ParagraphImpl* owner,
284*c8dee2aaSAndroid Build Coastguard Worker             RunIndex runIndex,
285*c8dee2aaSAndroid Build Coastguard Worker             size_t start,
286*c8dee2aaSAndroid Build Coastguard Worker             size_t end,
287*c8dee2aaSAndroid Build Coastguard Worker             SkSpan<const char> text,
288*c8dee2aaSAndroid Build Coastguard Worker             SkScalar width,
289*c8dee2aaSAndroid Build Coastguard Worker             SkScalar height);
290*c8dee2aaSAndroid Build Coastguard Worker 
Cluster(TextRange textRange)291*c8dee2aaSAndroid Build Coastguard Worker     Cluster(TextRange textRange) : fTextRange(textRange), fGraphemeRange(EMPTY_RANGE) { }
292*c8dee2aaSAndroid Build Coastguard Worker 
293*c8dee2aaSAndroid Build Coastguard Worker     Cluster(const Cluster&) = default;
294*c8dee2aaSAndroid Build Coastguard Worker     ~Cluster() = default;
295*c8dee2aaSAndroid Build Coastguard Worker 
296*c8dee2aaSAndroid Build Coastguard Worker     SkScalar sizeToChar(TextIndex ch) const;
297*c8dee2aaSAndroid Build Coastguard Worker     SkScalar sizeFromChar(TextIndex ch) const;
298*c8dee2aaSAndroid Build Coastguard Worker 
299*c8dee2aaSAndroid Build Coastguard Worker     size_t roundPos(SkScalar s) const;
300*c8dee2aaSAndroid Build Coastguard Worker 
space(SkScalar shift)301*c8dee2aaSAndroid Build Coastguard Worker     void space(SkScalar shift) {
302*c8dee2aaSAndroid Build Coastguard Worker         fWidth += shift;
303*c8dee2aaSAndroid Build Coastguard Worker     }
304*c8dee2aaSAndroid Build Coastguard Worker 
getOwner()305*c8dee2aaSAndroid Build Coastguard Worker     ParagraphImpl* getOwner() const { return fOwner; }
setOwner(ParagraphImpl * owner)306*c8dee2aaSAndroid Build Coastguard Worker     void setOwner(ParagraphImpl* owner) { fOwner = owner; }
307*c8dee2aaSAndroid Build Coastguard Worker 
isWhitespaceBreak()308*c8dee2aaSAndroid Build Coastguard Worker     bool isWhitespaceBreak() const { return fIsWhiteSpaceBreak; }
isIntraWordBreak()309*c8dee2aaSAndroid Build Coastguard Worker     bool isIntraWordBreak() const { return fIsIntraWordBreak; }
isHardBreak()310*c8dee2aaSAndroid Build Coastguard Worker     bool isHardBreak() const { return fIsHardBreak; }
isIdeographic()311*c8dee2aaSAndroid Build Coastguard Worker     bool isIdeographic() const { return fIsIdeographic; }
312*c8dee2aaSAndroid Build Coastguard Worker 
313*c8dee2aaSAndroid Build Coastguard Worker     bool isSoftBreak() const;
314*c8dee2aaSAndroid Build Coastguard Worker     bool isGraphemeBreak() const;
canBreakLineAfter()315*c8dee2aaSAndroid Build Coastguard Worker     bool canBreakLineAfter() const { return isHardBreak() || isSoftBreak(); }
startPos()316*c8dee2aaSAndroid Build Coastguard Worker     size_t startPos() const { return fStart; }
endPos()317*c8dee2aaSAndroid Build Coastguard Worker     size_t endPos() const { return fEnd; }
width()318*c8dee2aaSAndroid Build Coastguard Worker     SkScalar width() const { return fWidth; }
height()319*c8dee2aaSAndroid Build Coastguard Worker     SkScalar height() const { return fHeight; }
size()320*c8dee2aaSAndroid Build Coastguard Worker     size_t size() const { return fEnd - fStart; }
321*c8dee2aaSAndroid Build Coastguard Worker 
setHalfLetterSpacing(SkScalar halfLetterSpacing)322*c8dee2aaSAndroid Build Coastguard Worker     void setHalfLetterSpacing(SkScalar halfLetterSpacing) { fHalfLetterSpacing = halfLetterSpacing; }
getHalfLetterSpacing()323*c8dee2aaSAndroid Build Coastguard Worker     SkScalar getHalfLetterSpacing() const { return fHalfLetterSpacing; }
324*c8dee2aaSAndroid Build Coastguard Worker 
textRange()325*c8dee2aaSAndroid Build Coastguard Worker     TextRange textRange() const { return fTextRange; }
326*c8dee2aaSAndroid Build Coastguard Worker 
runIndex()327*c8dee2aaSAndroid Build Coastguard Worker     RunIndex runIndex() const { return fRunIndex; }
owner()328*c8dee2aaSAndroid Build Coastguard Worker     ParagraphImpl* owner() const { return fOwner; }
329*c8dee2aaSAndroid Build Coastguard Worker 
330*c8dee2aaSAndroid Build Coastguard Worker     Run* runOrNull() const;
331*c8dee2aaSAndroid Build Coastguard Worker     Run& run() const;
332*c8dee2aaSAndroid Build Coastguard Worker     SkFont font() const;
333*c8dee2aaSAndroid Build Coastguard Worker 
334*c8dee2aaSAndroid Build Coastguard Worker     SkScalar trimmedWidth(size_t pos) const;
335*c8dee2aaSAndroid Build Coastguard Worker 
contains(TextIndex ch)336*c8dee2aaSAndroid Build Coastguard Worker     bool contains(TextIndex ch) const { return ch >= fTextRange.start && ch < fTextRange.end; }
337*c8dee2aaSAndroid Build Coastguard Worker 
belongs(TextRange text)338*c8dee2aaSAndroid Build Coastguard Worker     bool belongs(TextRange text) const {
339*c8dee2aaSAndroid Build Coastguard Worker         return fTextRange.start >= text.start && fTextRange.end <= text.end;
340*c8dee2aaSAndroid Build Coastguard Worker     }
341*c8dee2aaSAndroid Build Coastguard Worker 
startsIn(TextRange text)342*c8dee2aaSAndroid Build Coastguard Worker     bool startsIn(TextRange text) const {
343*c8dee2aaSAndroid Build Coastguard Worker         return fTextRange.start >= text.start && fTextRange.start < text.end;
344*c8dee2aaSAndroid Build Coastguard Worker     }
345*c8dee2aaSAndroid Build Coastguard Worker 
346*c8dee2aaSAndroid Build Coastguard Worker private:
347*c8dee2aaSAndroid Build Coastguard Worker 
348*c8dee2aaSAndroid Build Coastguard Worker     friend ParagraphImpl;
349*c8dee2aaSAndroid Build Coastguard Worker 
350*c8dee2aaSAndroid Build Coastguard Worker     ParagraphImpl* fOwner;
351*c8dee2aaSAndroid Build Coastguard Worker     RunIndex fRunIndex;
352*c8dee2aaSAndroid Build Coastguard Worker     TextRange fTextRange;
353*c8dee2aaSAndroid Build Coastguard Worker     GraphemeRange fGraphemeRange;
354*c8dee2aaSAndroid Build Coastguard Worker 
355*c8dee2aaSAndroid Build Coastguard Worker     size_t fStart;
356*c8dee2aaSAndroid Build Coastguard Worker     size_t fEnd;
357*c8dee2aaSAndroid Build Coastguard Worker     SkScalar fWidth;
358*c8dee2aaSAndroid Build Coastguard Worker     SkScalar fHeight;
359*c8dee2aaSAndroid Build Coastguard Worker     SkScalar fHalfLetterSpacing;
360*c8dee2aaSAndroid Build Coastguard Worker 
361*c8dee2aaSAndroid Build Coastguard Worker     bool fIsWhiteSpaceBreak;
362*c8dee2aaSAndroid Build Coastguard Worker     bool fIsIntraWordBreak;
363*c8dee2aaSAndroid Build Coastguard Worker     bool fIsHardBreak;
364*c8dee2aaSAndroid Build Coastguard Worker     bool fIsIdeographic;
365*c8dee2aaSAndroid Build Coastguard Worker };
366*c8dee2aaSAndroid Build Coastguard Worker 
367*c8dee2aaSAndroid Build Coastguard Worker class InternalLineMetrics {
368*c8dee2aaSAndroid Build Coastguard Worker public:
369*c8dee2aaSAndroid Build Coastguard Worker 
InternalLineMetrics()370*c8dee2aaSAndroid Build Coastguard Worker     InternalLineMetrics() {
371*c8dee2aaSAndroid Build Coastguard Worker         clean();
372*c8dee2aaSAndroid Build Coastguard Worker         fForceStrut = false;
373*c8dee2aaSAndroid Build Coastguard Worker     }
374*c8dee2aaSAndroid Build Coastguard Worker 
InternalLineMetrics(bool forceStrut)375*c8dee2aaSAndroid Build Coastguard Worker     InternalLineMetrics(bool forceStrut) {
376*c8dee2aaSAndroid Build Coastguard Worker         clean();
377*c8dee2aaSAndroid Build Coastguard Worker         fForceStrut = forceStrut;
378*c8dee2aaSAndroid Build Coastguard Worker     }
379*c8dee2aaSAndroid Build Coastguard Worker 
InternalLineMetrics(SkScalar a,SkScalar d,SkScalar l)380*c8dee2aaSAndroid Build Coastguard Worker     InternalLineMetrics(SkScalar a, SkScalar d, SkScalar l) {
381*c8dee2aaSAndroid Build Coastguard Worker         fAscent = a;
382*c8dee2aaSAndroid Build Coastguard Worker         fDescent = d;
383*c8dee2aaSAndroid Build Coastguard Worker         fLeading = l;
384*c8dee2aaSAndroid Build Coastguard Worker         fRawAscent = a;
385*c8dee2aaSAndroid Build Coastguard Worker         fRawDescent = d;
386*c8dee2aaSAndroid Build Coastguard Worker         fRawLeading = l;
387*c8dee2aaSAndroid Build Coastguard Worker         fForceStrut = false;
388*c8dee2aaSAndroid Build Coastguard Worker     }
389*c8dee2aaSAndroid Build Coastguard Worker 
InternalLineMetrics(SkScalar a,SkScalar d,SkScalar l,SkScalar ra,SkScalar rd,SkScalar rl)390*c8dee2aaSAndroid Build Coastguard Worker     InternalLineMetrics(SkScalar a, SkScalar d, SkScalar l, SkScalar ra, SkScalar rd, SkScalar rl) {
391*c8dee2aaSAndroid Build Coastguard Worker         fAscent = a;
392*c8dee2aaSAndroid Build Coastguard Worker         fDescent = d;
393*c8dee2aaSAndroid Build Coastguard Worker         fLeading = l;
394*c8dee2aaSAndroid Build Coastguard Worker         fRawAscent = ra;
395*c8dee2aaSAndroid Build Coastguard Worker         fRawDescent = rd;
396*c8dee2aaSAndroid Build Coastguard Worker         fRawLeading = rl;
397*c8dee2aaSAndroid Build Coastguard Worker         fForceStrut = false;
398*c8dee2aaSAndroid Build Coastguard Worker     }
399*c8dee2aaSAndroid Build Coastguard Worker 
InternalLineMetrics(const SkFont & font,bool forceStrut)400*c8dee2aaSAndroid Build Coastguard Worker     InternalLineMetrics(const SkFont& font, bool forceStrut) {
401*c8dee2aaSAndroid Build Coastguard Worker         SkFontMetrics metrics;
402*c8dee2aaSAndroid Build Coastguard Worker         font.getMetrics(&metrics);
403*c8dee2aaSAndroid Build Coastguard Worker         fAscent = metrics.fAscent;
404*c8dee2aaSAndroid Build Coastguard Worker         fDescent = metrics.fDescent;
405*c8dee2aaSAndroid Build Coastguard Worker         fLeading = metrics.fLeading;
406*c8dee2aaSAndroid Build Coastguard Worker         fRawAscent = metrics.fAscent;
407*c8dee2aaSAndroid Build Coastguard Worker         fRawDescent = metrics.fDescent;
408*c8dee2aaSAndroid Build Coastguard Worker         fRawLeading = metrics.fLeading;
409*c8dee2aaSAndroid Build Coastguard Worker         fForceStrut = forceStrut;
410*c8dee2aaSAndroid Build Coastguard Worker     }
411*c8dee2aaSAndroid Build Coastguard Worker 
add(Run * run)412*c8dee2aaSAndroid Build Coastguard Worker     void add(Run* run) {
413*c8dee2aaSAndroid Build Coastguard Worker         if (fForceStrut) {
414*c8dee2aaSAndroid Build Coastguard Worker             return;
415*c8dee2aaSAndroid Build Coastguard Worker         }
416*c8dee2aaSAndroid Build Coastguard Worker         fAscent = std::min(fAscent, run->correctAscent());
417*c8dee2aaSAndroid Build Coastguard Worker         fDescent = std::max(fDescent, run->correctDescent());
418*c8dee2aaSAndroid Build Coastguard Worker         fLeading = std::max(fLeading, run->correctLeading());
419*c8dee2aaSAndroid Build Coastguard Worker 
420*c8dee2aaSAndroid Build Coastguard Worker         fRawAscent = std::min(fRawAscent, run->ascent());
421*c8dee2aaSAndroid Build Coastguard Worker         fRawDescent = std::max(fRawDescent, run->descent());
422*c8dee2aaSAndroid Build Coastguard Worker         fRawLeading = std::max(fRawLeading, run->leading());
423*c8dee2aaSAndroid Build Coastguard Worker     }
424*c8dee2aaSAndroid Build Coastguard Worker 
add(InternalLineMetrics other)425*c8dee2aaSAndroid Build Coastguard Worker     void add(InternalLineMetrics other) {
426*c8dee2aaSAndroid Build Coastguard Worker         fAscent = std::min(fAscent, other.fAscent);
427*c8dee2aaSAndroid Build Coastguard Worker         fDescent = std::max(fDescent, other.fDescent);
428*c8dee2aaSAndroid Build Coastguard Worker         fLeading = std::max(fLeading, other.fLeading);
429*c8dee2aaSAndroid Build Coastguard Worker         fRawAscent = std::min(fRawAscent, other.fRawAscent);
430*c8dee2aaSAndroid Build Coastguard Worker         fRawDescent = std::max(fRawDescent, other.fRawDescent);
431*c8dee2aaSAndroid Build Coastguard Worker         fRawLeading = std::max(fRawLeading, other.fRawLeading);
432*c8dee2aaSAndroid Build Coastguard Worker     }
433*c8dee2aaSAndroid Build Coastguard Worker 
clean()434*c8dee2aaSAndroid Build Coastguard Worker     void clean() {
435*c8dee2aaSAndroid Build Coastguard Worker         fAscent = SK_ScalarMax;
436*c8dee2aaSAndroid Build Coastguard Worker         fDescent = SK_ScalarMin;
437*c8dee2aaSAndroid Build Coastguard Worker         fLeading = 0;
438*c8dee2aaSAndroid Build Coastguard Worker         fRawAscent = SK_ScalarMax;
439*c8dee2aaSAndroid Build Coastguard Worker         fRawDescent = SK_ScalarMin;
440*c8dee2aaSAndroid Build Coastguard Worker         fRawLeading = 0;
441*c8dee2aaSAndroid Build Coastguard Worker     }
442*c8dee2aaSAndroid Build Coastguard Worker 
isClean()443*c8dee2aaSAndroid Build Coastguard Worker     bool isClean() {
444*c8dee2aaSAndroid Build Coastguard Worker         return (fAscent == SK_ScalarMax &&
445*c8dee2aaSAndroid Build Coastguard Worker                 fDescent == SK_ScalarMin &&
446*c8dee2aaSAndroid Build Coastguard Worker                 fLeading == 0 &&
447*c8dee2aaSAndroid Build Coastguard Worker                 fRawAscent == SK_ScalarMax &&
448*c8dee2aaSAndroid Build Coastguard Worker                 fRawDescent == SK_ScalarMin &&
449*c8dee2aaSAndroid Build Coastguard Worker                 fRawLeading == 0);
450*c8dee2aaSAndroid Build Coastguard Worker     }
451*c8dee2aaSAndroid Build Coastguard Worker 
delta()452*c8dee2aaSAndroid Build Coastguard Worker     SkScalar delta() const { return height() - ideographicBaseline(); }
453*c8dee2aaSAndroid Build Coastguard Worker 
updateLineMetrics(InternalLineMetrics & metrics)454*c8dee2aaSAndroid Build Coastguard Worker     void updateLineMetrics(InternalLineMetrics& metrics) {
455*c8dee2aaSAndroid Build Coastguard Worker         if (metrics.fForceStrut) {
456*c8dee2aaSAndroid Build Coastguard Worker             metrics.fAscent = fAscent;
457*c8dee2aaSAndroid Build Coastguard Worker             metrics.fDescent = fDescent;
458*c8dee2aaSAndroid Build Coastguard Worker             metrics.fLeading = fLeading;
459*c8dee2aaSAndroid Build Coastguard Worker             metrics.fRawAscent = fRawAscent;
460*c8dee2aaSAndroid Build Coastguard Worker             metrics.fRawDescent = fRawDescent;
461*c8dee2aaSAndroid Build Coastguard Worker             metrics.fRawLeading = fRawLeading;
462*c8dee2aaSAndroid Build Coastguard Worker         } else {
463*c8dee2aaSAndroid Build Coastguard Worker             // This is another of those flutter changes. To be removed...
464*c8dee2aaSAndroid Build Coastguard Worker             metrics.fAscent = std::min(metrics.fAscent, fAscent - fLeading / 2.0f);
465*c8dee2aaSAndroid Build Coastguard Worker             metrics.fDescent = std::max(metrics.fDescent, fDescent + fLeading / 2.0f);
466*c8dee2aaSAndroid Build Coastguard Worker             metrics.fRawAscent = std::min(metrics.fRawAscent, fRawAscent - fRawLeading / 2.0f);
467*c8dee2aaSAndroid Build Coastguard Worker             metrics.fRawDescent = std::max(metrics.fRawDescent, fRawDescent + fRawLeading / 2.0f);
468*c8dee2aaSAndroid Build Coastguard Worker         }
469*c8dee2aaSAndroid Build Coastguard Worker     }
470*c8dee2aaSAndroid Build Coastguard Worker 
runTop(const Run * run,LineMetricStyle ascentStyle)471*c8dee2aaSAndroid Build Coastguard Worker     SkScalar runTop(const Run* run, LineMetricStyle ascentStyle) const {
472*c8dee2aaSAndroid Build Coastguard Worker         return fLeading / 2 - fAscent +
473*c8dee2aaSAndroid Build Coastguard Worker           (ascentStyle == LineMetricStyle::Typographic ? run->ascent() : run->correctAscent()) + delta();
474*c8dee2aaSAndroid Build Coastguard Worker     }
475*c8dee2aaSAndroid Build Coastguard Worker 
height()476*c8dee2aaSAndroid Build Coastguard Worker     SkScalar height() const {
477*c8dee2aaSAndroid Build Coastguard Worker         return ::round((double)fDescent - fAscent + fLeading);
478*c8dee2aaSAndroid Build Coastguard Worker     }
479*c8dee2aaSAndroid Build Coastguard Worker 
update(SkScalar a,SkScalar d,SkScalar l)480*c8dee2aaSAndroid Build Coastguard Worker     void update(SkScalar a, SkScalar d, SkScalar l) {
481*c8dee2aaSAndroid Build Coastguard Worker         fAscent = a;
482*c8dee2aaSAndroid Build Coastguard Worker         fDescent = d;
483*c8dee2aaSAndroid Build Coastguard Worker         fLeading = l;
484*c8dee2aaSAndroid Build Coastguard Worker     }
485*c8dee2aaSAndroid Build Coastguard Worker 
updateRawData(SkScalar ra,SkScalar rd)486*c8dee2aaSAndroid Build Coastguard Worker     void updateRawData(SkScalar ra, SkScalar rd) {
487*c8dee2aaSAndroid Build Coastguard Worker         fRawAscent = ra;
488*c8dee2aaSAndroid Build Coastguard Worker         fRawDescent = rd;
489*c8dee2aaSAndroid Build Coastguard Worker     }
490*c8dee2aaSAndroid Build Coastguard Worker 
alphabeticBaseline()491*c8dee2aaSAndroid Build Coastguard Worker     SkScalar alphabeticBaseline() const { return fLeading / 2 - fAscent; }
ideographicBaseline()492*c8dee2aaSAndroid Build Coastguard Worker     SkScalar ideographicBaseline() const { return fDescent - fAscent + fLeading; }
deltaBaselines()493*c8dee2aaSAndroid Build Coastguard Worker     SkScalar deltaBaselines() const { return fLeading / 2 + fDescent; }
baseline()494*c8dee2aaSAndroid Build Coastguard Worker     SkScalar baseline() const { return fLeading / 2 - fAscent; }
ascent()495*c8dee2aaSAndroid Build Coastguard Worker     SkScalar ascent() const { return fAscent; }
descent()496*c8dee2aaSAndroid Build Coastguard Worker     SkScalar descent() const { return fDescent; }
leading()497*c8dee2aaSAndroid Build Coastguard Worker     SkScalar leading() const { return fLeading; }
rawAscent()498*c8dee2aaSAndroid Build Coastguard Worker     SkScalar rawAscent() const { return fRawAscent; }
rawDescent()499*c8dee2aaSAndroid Build Coastguard Worker     SkScalar rawDescent() const { return fRawDescent; }
setForceStrut(bool value)500*c8dee2aaSAndroid Build Coastguard Worker     void setForceStrut(bool value) { fForceStrut = value; }
getForceStrut()501*c8dee2aaSAndroid Build Coastguard Worker     bool getForceStrut() const { return fForceStrut; }
502*c8dee2aaSAndroid Build Coastguard Worker 
503*c8dee2aaSAndroid Build Coastguard Worker private:
504*c8dee2aaSAndroid Build Coastguard Worker 
505*c8dee2aaSAndroid Build Coastguard Worker     friend class ParagraphImpl;
506*c8dee2aaSAndroid Build Coastguard Worker     friend class TextWrapper;
507*c8dee2aaSAndroid Build Coastguard Worker     friend class TextLine;
508*c8dee2aaSAndroid Build Coastguard Worker 
509*c8dee2aaSAndroid Build Coastguard Worker     SkScalar fAscent;
510*c8dee2aaSAndroid Build Coastguard Worker     SkScalar fDescent;
511*c8dee2aaSAndroid Build Coastguard Worker     SkScalar fLeading;
512*c8dee2aaSAndroid Build Coastguard Worker 
513*c8dee2aaSAndroid Build Coastguard Worker     SkScalar fRawAscent;
514*c8dee2aaSAndroid Build Coastguard Worker     SkScalar fRawDescent;
515*c8dee2aaSAndroid Build Coastguard Worker     SkScalar fRawLeading;
516*c8dee2aaSAndroid Build Coastguard Worker 
517*c8dee2aaSAndroid Build Coastguard Worker     bool fForceStrut;
518*c8dee2aaSAndroid Build Coastguard Worker };
519*c8dee2aaSAndroid Build Coastguard Worker }  // namespace textlayout
520*c8dee2aaSAndroid Build Coastguard Worker }  // namespace skia
521*c8dee2aaSAndroid Build Coastguard Worker 
522*c8dee2aaSAndroid Build Coastguard Worker #endif  // Run_DEFINED
523