• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2019 Google LLC.
2 #ifndef Run_DEFINED
3 #define Run_DEFINED
4 
5 #include "include/core/SkFontMetrics.h"
6 #include "include/core/SkPoint.h"
7 #include "include/core/SkTextBlob.h"
8 #include "modules/skparagraph/include/DartTypes.h"
9 #include "modules/skparagraph/include/TextStyle.h"
10 #include "modules/skshaper/include/SkShaper.h"
11 #include "src/core/SkSpan.h"
12 #include "src/core/SkTraceEvent.h"
13 
14 namespace skia {
15 namespace textlayout {
16 
17 class ParagraphImpl;
18 class Cluster;
19 class Run;
20 
21 typedef size_t RunIndex;
22 const size_t EMPTY_RUN = EMPTY_INDEX;
23 
24 typedef size_t ClusterIndex;
25 typedef SkRange<size_t> ClusterRange;
26 const size_t EMPTY_CLUSTER = EMPTY_INDEX;
27 const SkRange<size_t> EMPTY_CLUSTERS = EMPTY_RANGE;
28 
29 typedef size_t GraphemeIndex;
30 typedef SkRange<GraphemeIndex> GraphemeRange;
31 
32 typedef size_t CodepointIndex;
33 typedef SkRange<CodepointIndex> CodepointRange;
34 
35 typedef size_t BlockIndex;
36 typedef SkRange<size_t> BlockRange;
37 const size_t EMPTY_BLOCK = EMPTY_INDEX;
38 const SkRange<size_t> EMPTY_BLOCKS = EMPTY_RANGE;
39 
40 struct RunShifts {
RunShiftsRunShifts41     RunShifts() { }
RunShiftsRunShifts42     RunShifts(size_t count) { fShifts.push_back_n(count, 0.0); }
43     SkSTArray<128, SkScalar, true> fShifts;
44 };
45 
46 class Run {
47 public:
48     Run() = default;
49     Run(ParagraphImpl* master,
50         const SkShaper::RunHandler::RunInfo& info,
51         SkScalar lineHeight,
52         size_t index,
53         SkScalar shiftX);
~Run()54     ~Run() {}
55 
setMaster(ParagraphImpl * master)56     void setMaster(ParagraphImpl* master) { fMaster = master; }
57 
58     SkShaper::RunHandler::Buffer newRunBuffer();
59 
size()60     size_t size() const { return fGlyphs.size(); }
setWidth(SkScalar width)61     void setWidth(SkScalar width) { fAdvance.fX = width; }
setHeight(SkScalar height)62     void setHeight(SkScalar height) { fAdvance.fY = height; }
shift(SkScalar shiftX,SkScalar shiftY)63     void shift(SkScalar shiftX, SkScalar shiftY) {
64         fOffset.fX += shiftX;
65         fOffset.fY += shiftY;
66     }
advance()67     SkVector advance() const {
68         return SkVector::Make(fAdvance.fX, fFontMetrics.fDescent - fFontMetrics.fAscent);
69     }
offset()70     SkVector offset() const { return fOffset; }
ascent()71     SkScalar ascent() const { return fFontMetrics.fAscent; }
72     //SkScalar descent() const { return fFontMetrics.fDescent; }
73     //SkScalar leading() const { return fFontMetrics.fLeading; }
correctAscent()74     SkScalar correctAscent() const {
75 
76         if (fHeightMultiplier == 0 || fHeightMultiplier == 1) {
77             return fFontMetrics.fAscent - fFontMetrics.fLeading / 2;
78         }
79         return fFontMetrics.fAscent * fHeightMultiplier * fFont.getSize() /
80                 (fFontMetrics.fDescent - fFontMetrics.fAscent + fFontMetrics.fLeading / 2);
81     }
correctDescent()82     SkScalar correctDescent() const {
83 
84         if (fHeightMultiplier == 0 || fHeightMultiplier == 1) {
85             return fFontMetrics.fDescent + fFontMetrics.fLeading / 2;
86         }
87         return fFontMetrics.fDescent * fHeightMultiplier * fFont.getSize() /
88                 (fFontMetrics.fDescent - fFontMetrics.fAscent + fFontMetrics.fLeading / 2);
89     }
correctLeading()90     SkScalar correctLeading() const {
91 
92         if (fHeightMultiplier == 0 || fHeightMultiplier == 1) {
93             return fFontMetrics.fAscent;
94         }
95         return fFontMetrics.fLeading * fHeightMultiplier * fFont.getSize() /
96                 (fFontMetrics.fDescent - fFontMetrics.fAscent + fFontMetrics.fLeading);
97     }
font()98     const SkFont& font() const { return fFont; }
leftToRight()99     bool leftToRight() const { return fBidiLevel % 2 == 0; }
index()100     size_t index() const { return fIndex; }
lineHeight()101     SkScalar lineHeight() const { return fHeightMultiplier; }
clusterIndex(size_t pos)102     size_t clusterIndex(size_t pos) const { return fClusterIndexes[pos]; }
103     SkScalar positionX(size_t pos) const;
104 
textRange()105     TextRange textRange() { return fTextRange; }
clusterRange()106     ClusterRange clusterRange() { return fClusterRange; }
107 
setClusterRange(size_t from,size_t to)108     void setClusterRange(size_t from, size_t to) { fClusterRange = ClusterRange(from, to); }
clip()109     SkRect clip() const {
110         return SkRect::MakeXYWH(fOffset.fX, fOffset.fY, fAdvance.fX, fAdvance.fY);
111     }
112 
113     SkScalar addSpacesAtTheEnd(SkScalar space, Cluster* cluster);
114     SkScalar addSpacesEvenly(SkScalar space, Cluster* cluster);
115     void shift(const Cluster* cluster, SkScalar offset);
116 
calculateHeight()117     SkScalar calculateHeight() const {
118         if (fHeightMultiplier == 0 || fHeightMultiplier == 1) {
119             return fFontMetrics.fDescent - fFontMetrics.fAscent;
120         }
121         return fHeightMultiplier * fFont.getSize();
122     }
123     SkScalar calculateWidth(size_t start, size_t end, bool clip) const;
124 
125     void copyTo(SkTextBlobBuilder& builder, size_t pos, size_t size, SkVector offset) const;
126 
127     using ClusterVisitor = std::function<void(size_t glyphStart,
128                                               size_t glyphEnd,
129                                               size_t charStart,
130                                               size_t charEnd,
131                                               SkScalar width,
132                                               SkScalar height)>;
133     void iterateThroughClustersInTextOrder(const ClusterVisitor& visitor);
134 
135     std::tuple<bool, ClusterIndex, ClusterIndex> findLimitingClusters(TextRange);
glyphs()136     SkSpan<const SkGlyphID> glyphs() const {
137         return SkSpan<const SkGlyphID>(fGlyphs.begin(), fGlyphs.size());
138     }
positions()139     SkSpan<const SkPoint> positions() const {
140         return SkSpan<const SkPoint>(fPositions.begin(), fPositions.size());
141     }
clusterIndexes()142     SkSpan<const uint32_t> clusterIndexes() const {
143         return SkSpan<const uint32_t>(fClusterIndexes.begin(), fClusterIndexes.size());
144     }
offsets()145     SkSpan<const SkScalar> offsets() const { return SkSpan<const SkScalar>(fOffsets.begin(), fOffsets.size()); }
146 
147 private:
148     friend class ParagraphImpl;
149     friend class TextLine;
150     friend class LineMetrics;
151     friend class ParagraphCache;
152 
153     ParagraphImpl* fMaster;
154     TextRange fTextRange;
155     ClusterRange fClusterRange;
156 
157     SkFont fFont;
158     SkFontMetrics fFontMetrics;
159     SkScalar fHeightMultiplier;
160     size_t fIndex;
161     uint8_t fBidiLevel;
162     SkVector fAdvance;
163     SkVector fOffset;
164     SkShaper::RunHandler::Range fUtf8Range;
165     SkSTArray<128, SkGlyphID, false> fGlyphs;
166     SkSTArray<128, SkPoint, true> fPositions;
167     SkSTArray<128, uint32_t, true> fClusterIndexes;
168     SkSTArray<128, SkScalar, true> fOffsets;  // For formatting (letter/word spacing, justification)
169     bool fSpaced;
170 };
171 
172 struct Codepoint {
173 
CodepointCodepoint174   Codepoint(GraphemeIndex graphemeIndex, TextIndex textIndex)
175     : fGrapeme(graphemeIndex), fTextIndex(textIndex) { }
176 
177   GraphemeIndex fGrapeme;
178   TextIndex fTextIndex;             // Used for getGlyphPositionAtCoordinate
179 };
180 
181 struct Grapheme {
GraphemeGrapheme182     Grapheme(CodepointRange codepoints, TextRange textRange)
183         : fCodepointRange(codepoints), fTextRange(textRange) { }
184     CodepointRange fCodepointRange;
185     TextRange fTextRange;           // Used for getRectsForRange
186 };
187 
188 class Cluster {
189 public:
190     enum BreakType {
191         None,
192         CharacterBoundary,       // not yet in use (UBRK_CHARACTER)
193         WordBoundary,            // calculated for all clusters (UBRK_WORD)
194         WordBreakWithoutHyphen,  // calculated only for hyphenated words
195         WordBreakWithHyphen,
196         SoftLineBreak,  // calculated for all clusters (UBRK_LINE)
197         HardLineBreak,  // calculated for all clusters (UBRK_LINE)
198     };
199 
Cluster()200     Cluster()
201             : fMaster(nullptr)
202             , fRunIndex(EMPTY_RUN)
203             , fTextRange(EMPTY_TEXT)
204             , fGraphemeRange(EMPTY_RANGE)
205             , fStart(0)
206             , fEnd()
207             , fWidth()
208             , fSpacing(0)
209             , fHeight()
210             , fWhiteSpaces(false)
211             , fBreakType(None) {}
212 
213     Cluster(ParagraphImpl* master,
214             RunIndex runIndex,
215             size_t start,
216             size_t end,
217             SkSpan<const char> text,
218             SkScalar width,
219             SkScalar height);
220 
Cluster(TextRange textRange)221     Cluster(TextRange textRange) : fTextRange(textRange), fGraphemeRange(EMPTY_RANGE) { }
222 
223     ~Cluster() = default;
224 
setMaster(ParagraphImpl * master)225     void setMaster(ParagraphImpl* master) { fMaster = master; }
226     SkScalar sizeToChar(TextIndex ch) const;
227     SkScalar sizeFromChar(TextIndex ch) const;
228 
229     size_t roundPos(SkScalar s) const;
230 
space(SkScalar shift,SkScalar space)231     void space(SkScalar shift, SkScalar space) {
232         fSpacing += space;
233         fWidth += shift;
234     }
235 
setBreakType(BreakType type)236     void setBreakType(BreakType type) { fBreakType = type; }
isWhitespaces()237     bool isWhitespaces() const { return fWhiteSpaces; }
canBreakLineAfter()238     bool canBreakLineAfter() const {
239         return fBreakType == SoftLineBreak || fBreakType == HardLineBreak;
240     }
isHardBreak()241     bool isHardBreak() const { return fBreakType == HardLineBreak; }
isSoftBreak()242     bool isSoftBreak() const { return fBreakType == SoftLineBreak; }
startPos()243     size_t startPos() const { return fStart; }
endPos()244     size_t endPos() const { return fEnd; }
width()245     SkScalar width() const { return fWidth; }
trimmedWidth()246     SkScalar trimmedWidth() const { return fWidth - fSpacing; }
lastSpacing()247     SkScalar lastSpacing() const { return fSpacing; }
height()248     SkScalar height() const { return fHeight; }
size()249     size_t size() const { return fEnd - fStart; }
250 
textRange()251     TextRange textRange() const { return fTextRange; }
252 
runIndex()253     RunIndex runIndex() const { return fRunIndex; }
254     Run* run() const;
255     SkFont font() const;
256 
257     SkScalar trimmedWidth(size_t pos) const;
258 
259     void setIsWhiteSpaces();
260 
contains(TextIndex ch)261     bool contains(TextIndex ch) const { return ch >= fTextRange.start && ch < fTextRange.end; }
262 
belongs(TextRange text)263     bool belongs(TextRange text) const {
264         return fTextRange.start >= text.start && fTextRange.end <= text.end;
265     }
266 
startsIn(TextRange text)267     bool startsIn(TextRange text) const {
268         return fTextRange.start >= text.start && fTextRange.start < text.end;
269     }
270 
271 private:
272 
273     friend ParagraphImpl;
274 
275     ParagraphImpl* fMaster;
276     RunIndex fRunIndex;
277     TextRange fTextRange;
278     GraphemeRange fGraphemeRange;
279 
280     size_t fStart;
281     size_t fEnd;
282     SkScalar fWidth;
283     SkScalar fSpacing;
284     SkScalar fHeight;
285     bool fWhiteSpaces;
286     BreakType fBreakType;
287 };
288 
289 class LineMetrics {
290 public:
291 
LineMetrics()292     LineMetrics() { clean(); }
LineMetrics(bool forceStrut)293     LineMetrics(bool forceStrut) : fForceStrut(forceStrut) { clean(); }
294 
LineMetrics(SkScalar a,SkScalar d,SkScalar l)295     LineMetrics(SkScalar a, SkScalar d, SkScalar l) : fForceStrut(false) {
296         fAscent = a;
297         fDescent = d;
298         fLeading = l;
299     }
300 
LineMetrics(const SkFont & font,bool forceStrut)301     LineMetrics(const SkFont& font, bool forceStrut) : fForceStrut(forceStrut) {
302         SkFontMetrics metrics;
303         font.getMetrics(&metrics);
304         fAscent = metrics.fAscent;
305         fDescent = metrics.fDescent;
306         fLeading = metrics.fLeading;
307     }
308 
add(Run * run)309     void add(Run* run) {
310 
311         if (fForceStrut) {
312             return;
313         }
314 
315         fAscent = SkTMin(fAscent, run->correctAscent());
316         fDescent = SkTMax(fDescent, run->correctDescent());
317         fLeading = SkTMax(fLeading, run->correctLeading());
318 
319     }
320 
add(LineMetrics other)321     void add(LineMetrics other) {
322         fAscent = SkTMin(fAscent, other.fAscent);
323         fDescent = SkTMax(fDescent, other.fDescent);
324         fLeading = SkTMax(fLeading, other.fLeading);
325     }
clean()326     void clean() {
327         fAscent = 0;
328         fDescent = 0;
329         fLeading = 0;
330     }
331 
delta()332     SkScalar delta() const { return height() - ideographicBaseline(); }
333 
updateLineMetrics(LineMetrics & metrics)334     void updateLineMetrics(LineMetrics& metrics) {
335         metrics.fAscent = SkTMin(metrics.fAscent, fAscent);
336         metrics.fDescent = SkTMax(metrics.fDescent, fDescent);
337         metrics.fLeading = SkTMax(metrics.fLeading, fLeading);
338     }
339 
runTop(Run * run)340     SkScalar runTop(Run* run) const {
341         return fLeading / 2 - fAscent + run->ascent() + delta();
342     }
height()343     SkScalar height() const { return SkScalarRoundToInt(fDescent - fAscent + fLeading); }
alphabeticBaseline()344     SkScalar alphabeticBaseline() const { return fLeading / 2 - fAscent; }
ideographicBaseline()345     SkScalar ideographicBaseline() const { return fDescent - fAscent + fLeading; }
baseline()346     SkScalar baseline() const { return fLeading / 2 - fAscent; }
ascent()347     SkScalar ascent() const { return fAscent; }
descent()348     SkScalar descent() const { return fDescent; }
leading()349     SkScalar leading() const { return fLeading; }
350 
351 private:
352     SkScalar fAscent;
353     SkScalar fDescent;
354     SkScalar fLeading;
355     bool fForceStrut;
356 };
357 }  // namespace textlayout
358 }  // namespace skia
359 
360 #endif  // Run_DEFINED
361