• 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 #include <functional>  // std::function
14 
15 namespace skia {
16 namespace textlayout {
17 
18 class ParagraphImpl;
19 class Cluster;
20 class Run;
21 
22 typedef size_t RunIndex;
23 const size_t EMPTY_RUN = EMPTY_INDEX;
24 
25 typedef size_t ClusterIndex;
26 typedef SkRange<size_t> ClusterRange;
27 const size_t EMPTY_CLUSTER = EMPTY_INDEX;
28 const SkRange<size_t> EMPTY_CLUSTERS = EMPTY_RANGE;
29 
30 typedef size_t GraphemeIndex;
31 typedef SkRange<GraphemeIndex> GraphemeRange;
32 
33 typedef size_t CodepointIndex;
34 typedef SkRange<CodepointIndex> CodepointRange;
35 
36 struct RunShifts {
RunShiftsRunShifts37     RunShifts() { }
RunShiftsRunShifts38     RunShifts(size_t count) { fShifts.push_back_n(count, 0.0); }
39     SkSTArray<128, SkScalar, true> fShifts;
40 };
41 
42 class InternalLineMetrics;
43 class Run {
44 public:
45     Run() = default;
46     Run(ParagraphImpl* master,
47         const SkShaper::RunHandler::RunInfo& info,
48         size_t firstChar,
49         SkScalar lineHeight,
50         size_t index,
51         SkScalar shiftX);
~Run()52     ~Run() {}
53 
setMaster(ParagraphImpl * master)54     void setMaster(ParagraphImpl* master) { fMaster = master; }
55 
56     SkShaper::RunHandler::Buffer newRunBuffer();
57 
posX(size_t index)58     SkScalar posX(size_t index) const {
59         return fPositions[index].fX + fOffsets[index].fX;
60     }
addX(size_t index,SkScalar shift)61     void addX(size_t index, SkScalar shift) {
62         fPositions[index].fX += shift;
63     }
posY(size_t index)64     SkScalar posY(size_t index) const {
65         return fPositions[index].fY + fOffsets[index].fY;
66     }
size()67     size_t size() const { return fGlyphs.size(); }
setWidth(SkScalar width)68     void setWidth(SkScalar width) { fAdvance.fX = width; }
setHeight(SkScalar height)69     void setHeight(SkScalar height) { fAdvance.fY = height; }
shift(SkScalar shiftX,SkScalar shiftY)70     void shift(SkScalar shiftX, SkScalar shiftY) {
71         fOffset.fX += shiftX;
72         fOffset.fY += shiftY;
73     }
advance()74     SkVector advance() const {
75         return SkVector::Make(fAdvance.fX, fFontMetrics.fDescent - fFontMetrics.fAscent);
76     }
offset()77     SkVector offset() const { return fOffset; }
ascent()78     SkScalar ascent() const { return fFontMetrics.fAscent; }
correctAscent()79     SkScalar correctAscent() const {
80 
81         if (fHeightMultiplier == 0) {
82             return fFontMetrics.fAscent - fFontMetrics.fLeading / 2;
83         }
84         return fFontMetrics.fAscent * fHeightMultiplier * fFont.getSize() /
85                 (fFontMetrics.fDescent - fFontMetrics.fAscent + fFontMetrics.fLeading / 2);
86     }
correctDescent()87     SkScalar correctDescent() const {
88 
89         if (fHeightMultiplier == 0) {
90             return fFontMetrics.fDescent + fFontMetrics.fLeading / 2;
91         }
92         return fFontMetrics.fDescent * fHeightMultiplier * fFont.getSize() /
93                 (fFontMetrics.fDescent - fFontMetrics.fAscent + fFontMetrics.fLeading / 2);
94     }
correctLeading()95     SkScalar correctLeading() const {
96 
97         if (fHeightMultiplier == 0) {
98             return fFontMetrics.fAscent;
99         }
100         return fFontMetrics.fLeading * fHeightMultiplier * fFont.getSize() /
101                 (fFontMetrics.fDescent - fFontMetrics.fAscent + fFontMetrics.fLeading);
102     }
font()103     const SkFont& font() const { return fFont; }
leftToRight()104     bool leftToRight() const { return fBidiLevel % 2 == 0; }
index()105     size_t index() const { return fIndex; }
lineHeight()106     SkScalar lineHeight() const { return fHeightMultiplier; }
107     PlaceholderStyle* placeholderStyle() const;
isPlaceholder()108     bool isPlaceholder() const { return fPlaceholderIndex != std::numeric_limits<size_t>::max(); }
clusterIndex(size_t pos)109     size_t clusterIndex(size_t pos) const { return fClusterIndexes[pos]; }
globalClusterIndex(size_t pos)110     size_t globalClusterIndex(size_t pos) const { return fClusterStart + fClusterIndexes[pos]; }
111     SkScalar positionX(size_t pos) const;
112 
textRange()113     TextRange textRange() const { return fTextRange; }
clusterRange()114     ClusterRange clusterRange() const { return fClusterRange; }
115 
master()116     ParagraphImpl* master() const { return fMaster; }
117 
isEllipsis()118     bool isEllipsis() const { return fEllipsis; }
119 
120     void updateMetrics(InternalLineMetrics* endlineMetrics);
121 
setClusterRange(size_t from,size_t to)122     void setClusterRange(size_t from, size_t to) { fClusterRange = ClusterRange(from, to); }
clip()123     SkRect clip() const {
124         return SkRect::MakeXYWH(fOffset.fX, fOffset.fY, fAdvance.fX, fAdvance.fY);
125     }
126 
127     SkScalar addSpacesAtTheEnd(SkScalar space, Cluster* cluster);
128     SkScalar addSpacesEvenly(SkScalar space, Cluster* cluster);
129     void shift(const Cluster* cluster, SkScalar offset);
130 
calculateHeight()131     SkScalar calculateHeight() const {
132         if (fHeightMultiplier == 0) {
133             return fFontMetrics.fDescent - fFontMetrics.fAscent;
134         }
135         return fHeightMultiplier * fFont.getSize();
136     }
137     SkScalar calculateWidth(size_t start, size_t end, bool clip) const;
138 
139     void copyTo(SkTextBlobBuilder& builder, size_t pos, size_t size, SkVector offset) const;
140 
141     using ClusterVisitor = std::function<void(size_t glyphStart,
142                                               size_t glyphEnd,
143                                               size_t charStart,
144                                               size_t charEnd,
145                                               SkScalar width,
146                                               SkScalar height)>;
147     void iterateThroughClustersInTextOrder(const ClusterVisitor& visitor);
148 
149     std::tuple<bool, ClusterIndex, ClusterIndex> findLimitingClusters(TextRange text, bool onlyInnerClusters) const;
glyphs()150     SkSpan<const SkGlyphID> glyphs() const {
151         return SkSpan<const SkGlyphID>(fGlyphs.begin(), fGlyphs.size());
152     }
positions()153     SkSpan<const SkPoint> positions() const {
154         return SkSpan<const SkPoint>(fPositions.begin(), fPositions.size());
155     }
offsets()156     SkSpan<const SkPoint> offsets() const {
157         return SkSpan<const SkPoint>(fOffsets.begin(), fOffsets.size());
158     }
clusterIndexes()159     SkSpan<const uint32_t> clusterIndexes() const {
160         return SkSpan<const uint32_t>(fClusterIndexes.begin(), fClusterIndexes.size());
161     }
shifts()162     SkSpan<const SkScalar> shifts() const { return SkSpan<const SkScalar>(fShifts.begin(), fShifts.size()); }
163 
164     void commit();
165 
getBounds(size_t pos)166     SkRect getBounds(size_t pos) const { return fBounds[pos]; }
167 
resetShifts()168     void resetShifts() {
169         for (auto& r: fShifts) { r = 0; }
170         fSpaced = false;
171     }
172 private:
173     friend class ParagraphImpl;
174     friend class TextLine;
175     friend class InternalLineMetrics;
176     friend class ParagraphCache;
177     friend class OneLineShaper;
178 
179     ParagraphImpl* fMaster;
180     TextRange fTextRange;
181     ClusterRange fClusterRange;
182 
183     SkFont fFont;
184     SkFontMetrics fFontMetrics;
185     SkScalar fHeightMultiplier;
186     size_t fPlaceholderIndex;
187     bool fEllipsis;
188     size_t fIndex;
189     uint8_t fBidiLevel;
190     SkVector fAdvance;
191     SkVector fOffset;
192     TextIndex fClusterStart;
193     SkShaper::RunHandler::Range fUtf8Range;
194     SkSTArray<128, SkGlyphID, true> fGlyphs;
195     SkSTArray<128, SkPoint, true> fPositions;
196     SkSTArray<128, SkPoint, true> fOffsets;
197     SkSTArray<128, uint32_t, true> fClusterIndexes;
198     SkSTArray<128, SkRect, true> fBounds;
199 
200     SkSTArray<128, SkScalar, true> fShifts;  // For formatting (letter/word spacing, justification)
201     bool fSpaced;
202 };
203 
204 struct Codepoint {
205 
CodepointCodepoint206   Codepoint(GraphemeIndex graphemeIndex, TextIndex textIndex, size_t index)
207     : fGrapheme(graphemeIndex), fTextIndex(textIndex), fIndex(index) { }
208 
209   GraphemeIndex fGrapheme;
210   TextIndex fTextIndex;             // Used for getGlyphPositionAtCoordinate
211   size_t fIndex;
212 };
213 
214 struct Grapheme {
GraphemeGrapheme215     Grapheme(CodepointRange codepoints, TextRange textRange)
216         : fCodepointRange(codepoints), fTextRange(textRange) { }
217     CodepointRange fCodepointRange;
218     TextRange fTextRange;           // Used for getRectsForRange
219 };
220 
221 class Cluster {
222 public:
223     enum BreakType {
224         None,
225         CharacterBoundary,       // not yet in use (UBRK_CHARACTER)
226         WordBoundary,            // calculated for all clusters (UBRK_WORD)
227         WordBreakWithoutHyphen,  // calculated only for hyphenated words
228         WordBreakWithHyphen,
229         SoftLineBreak,  // calculated for all clusters (UBRK_LINE)
230         HardLineBreak,  // calculated for all clusters (UBRK_LINE)
231     };
232 
Cluster()233     Cluster()
234             : fMaster(nullptr)
235             , fRunIndex(EMPTY_RUN)
236             , fTextRange(EMPTY_TEXT)
237             , fGraphemeRange(EMPTY_RANGE)
238             , fStart(0)
239             , fEnd()
240             , fWidth()
241             , fSpacing(0)
242             , fHeight()
243             , fHalfLetterSpacing(0.0)
244             , fWhiteSpaces(false)
245             , fBreakType(None) {}
246 
247     Cluster(ParagraphImpl* master,
248             RunIndex runIndex,
249             size_t start,
250             size_t end,
251             SkSpan<const char> text,
252             SkScalar width,
253             SkScalar height);
254 
Cluster(TextRange textRange)255     Cluster(TextRange textRange) : fTextRange(textRange), fGraphemeRange(EMPTY_RANGE) { }
256 
257     ~Cluster() = default;
258 
setMaster(ParagraphImpl * master)259     void setMaster(ParagraphImpl* master) { fMaster = master; }
260     SkScalar sizeToChar(TextIndex ch) const;
261     SkScalar sizeFromChar(TextIndex ch) const;
262 
263     size_t roundPos(SkScalar s) const;
264 
space(SkScalar shift,SkScalar space)265     void space(SkScalar shift, SkScalar space) {
266         fSpacing += space;
267         fWidth += shift;
268     }
269 
setBreakType(BreakType type)270     void setBreakType(BreakType type) { fBreakType = type; }
isWhitespaces()271     bool isWhitespaces() const { return fWhiteSpaces; }
canBreakLineAfter()272     bool canBreakLineAfter() const {
273         return fBreakType == SoftLineBreak || fBreakType == HardLineBreak;
274     }
isHardBreak()275     bool isHardBreak() const { return fBreakType == HardLineBreak; }
isSoftBreak()276     bool isSoftBreak() const { return fBreakType == SoftLineBreak; }
startPos()277     size_t startPos() const { return fStart; }
endPos()278     size_t endPos() const { return fEnd; }
width()279     SkScalar width() const { return fWidth; }
height()280     SkScalar height() const { return fHeight; }
size()281     size_t size() const { return fEnd - fStart; }
282 
setHalfLetterSpacing(SkScalar halfLetterSpacing)283     void setHalfLetterSpacing(SkScalar halfLetterSpacing) { fHalfLetterSpacing = halfLetterSpacing; }
getHalfLetterSpacing()284     SkScalar getHalfLetterSpacing() const { return fHalfLetterSpacing; }
285 
textRange()286     TextRange textRange() const { return fTextRange; }
287 
runIndex()288     RunIndex runIndex() const { return fRunIndex; }
master()289     ParagraphImpl* master() const { return fMaster; }
290 
291     Run* run() const;
292     SkFont font() const;
293 
294     SkScalar trimmedWidth(size_t pos) const;
295 
296     void setIsWhiteSpaces();
297 
contains(TextIndex ch)298     bool contains(TextIndex ch) const { return ch >= fTextRange.start && ch < fTextRange.end; }
299 
belongs(TextRange text)300     bool belongs(TextRange text) const {
301         return fTextRange.start >= text.start && fTextRange.end <= text.end;
302     }
303 
startsIn(TextRange text)304     bool startsIn(TextRange text) const {
305         return fTextRange.start >= text.start && fTextRange.start < text.end;
306     }
307 
308 private:
309 
310     friend ParagraphImpl;
311 
312     ParagraphImpl* fMaster;
313     RunIndex fRunIndex;
314     TextRange fTextRange;
315     GraphemeRange fGraphemeRange;
316 
317     size_t fStart;
318     size_t fEnd;
319     SkScalar fWidth;
320     SkScalar fSpacing;
321     SkScalar fHeight;
322     SkScalar fHalfLetterSpacing;
323     bool fWhiteSpaces;
324     BreakType fBreakType;
325 };
326 
327 class InternalLineMetrics {
328 public:
329 
InternalLineMetrics()330     InternalLineMetrics() {
331         clean();
332         fForceStrut = false;
333     }
334 
InternalLineMetrics(bool forceStrut)335     InternalLineMetrics(bool forceStrut) {
336         clean();
337         fForceStrut = forceStrut;
338     }
339 
InternalLineMetrics(SkScalar a,SkScalar d,SkScalar l)340     InternalLineMetrics(SkScalar a, SkScalar d, SkScalar l) {
341         fAscent = a;
342         fDescent = d;
343         fLeading = l;
344         fForceStrut = false;
345     }
346 
InternalLineMetrics(const SkFont & font,bool forceStrut)347     InternalLineMetrics(const SkFont& font, bool forceStrut) {
348         SkFontMetrics metrics;
349         font.getMetrics(&metrics);
350         fAscent = metrics.fAscent;
351         fDescent = metrics.fDescent;
352         fLeading = metrics.fLeading;
353         fForceStrut = forceStrut;
354     }
355 
add(Run * run)356     void add(Run* run) {
357 
358         if (fForceStrut) {
359             return;
360         }
361 
362         fAscent = std::min(fAscent, run->correctAscent());
363         fDescent = std::max(fDescent, run->correctDescent());
364         fLeading = std::max(fLeading, run->correctLeading());
365     }
366 
add(InternalLineMetrics other)367     void add(InternalLineMetrics other) {
368         fAscent = std::min(fAscent, other.fAscent);
369         fDescent = std::max(fDescent, other.fDescent);
370         fLeading = std::max(fLeading, other.fLeading);
371     }
clean()372     void clean() {
373         fAscent = 0;
374         fDescent = 0;
375         fLeading = 0;
376     }
377 
delta()378     SkScalar delta() const { return height() - ideographicBaseline(); }
379 
updateLineMetrics(InternalLineMetrics & metrics)380     void updateLineMetrics(InternalLineMetrics& metrics) {
381         if (metrics.fForceStrut) {
382             metrics.fAscent = fAscent;
383             metrics.fDescent = fDescent;
384             metrics.fLeading = fLeading;
385         } else {
386             // This is another of those flutter changes. To be removed...
387             metrics.fAscent = std::min(metrics.fAscent, fAscent - fLeading / 2.0f);
388             metrics.fDescent = std::max(metrics.fDescent, fDescent + fLeading / 2.0f);
389         }
390     }
391 
runTop(const Run * run)392     SkScalar runTop(const Run* run) const {
393         return fLeading / 2 - fAscent + run->ascent() + delta();
394     }
395 
height()396     SkScalar height() const {
397         return ::round((double)fDescent - fAscent + fLeading);
398     }
399 
alphabeticBaseline()400     SkScalar alphabeticBaseline() const { return fLeading / 2 - fAscent; }
ideographicBaseline()401     SkScalar ideographicBaseline() const { return fDescent - fAscent + fLeading; }
deltaBaselines()402     SkScalar deltaBaselines() const { return fLeading / 2 + fDescent; }
baseline()403     SkScalar baseline() const { return fLeading / 2 - fAscent; }
ascent()404     SkScalar ascent() const { return fAscent; }
descent()405     SkScalar descent() const { return fDescent; }
leading()406     SkScalar leading() const { return fLeading; }
setForceStrut(bool value)407     void setForceStrut(bool value) { fForceStrut = value; }
408 
409 private:
410 
411     friend class TextWrapper;
412 
413     SkScalar fAscent;
414     SkScalar fDescent;
415     SkScalar fLeading;
416     bool fForceStrut;
417 };
418 }  // namespace textlayout
419 }  // namespace skia
420 
421 #endif  // Run_DEFINED
422