• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2021 Google LLC.
2 #ifndef TextLine_DEFINED
3 #define TextLine_DEFINED
4 
5 #include "experimental/sktext/include/Types.h"
6 #include "include/core/SkFont.h"
7 #include "include/core/SkFontMetrics.h"
8 
9 namespace skia {
10 namespace text {
11 
12 class Processor;
13 
14 class TextMetrics {
15 
16 public:
TextMetrics()17   TextMetrics() {
18       clean();
19   }
20 
TextMetrics(const SkFont & font)21   TextMetrics(const SkFont& font) {
22 
23       SkFontMetrics metrics;
24       font.getMetrics(&metrics);
25       fAscent = metrics.fAscent;
26       fDescent = metrics.fDescent;
27       fLeading = metrics.fLeading;
28   }
29 
30   TextMetrics(const TextMetrics&) = default;
31 
merge(TextMetrics tail)32   void merge(TextMetrics tail) {
33       this->fAscent = std::min(this->fAscent, tail.fAscent);
34       this->fDescent = std::max(this->fDescent, tail.fDescent);
35       this->fLeading = std::max(this->fLeading, tail.fLeading);
36   }
37 
clean()38   void clean() {
39       this->fAscent = 0;
40       this->fDescent = 0;
41       this->fLeading = 0;
42   }
43 
height()44   SkScalar height() const {
45       return this->fDescent - this->fAscent + this->fLeading;
46   }
47 
baseline()48 SkScalar baseline() const {
49       return - this->fAscent + this->fLeading / 2;
50   }
51 
52 private:
53     SkScalar fAscent;
54     SkScalar fDescent;
55     SkScalar fLeading;
56 };
57 
58 class GlyphPos {
59 public:
60 
GlyphPos()61     GlyphPos() : fRunIndex(EMPTY_INDEX), fGlyphIndex(EMPTY_INDEX) { }
GlyphPos(size_t runIndex,size_t glyphIndex)62     GlyphPos(size_t runIndex, size_t glyphIndex) : fRunIndex(runIndex), fGlyphIndex(glyphIndex) { }
63 
64     bool operator==(const GlyphPos& other) const {
65         return this->fRunIndex == other.fRunIndex && this->fGlyphIndex == other.fGlyphIndex;
66     }
67 
runIndex()68     size_t runIndex() const { return fRunIndex; }
glyphIndex()69     size_t glyphIndex() const { return fGlyphIndex; }
setGlyphIndex(size_t index)70     void setGlyphIndex(size_t index) { fGlyphIndex = index; }
71 
isEmpty()72     bool isEmpty() const { return fRunIndex == EMPTY_INDEX; }
73 
74 private:
75     size_t fRunIndex;
76     size_t fGlyphIndex;
77 };
78 
79 class Stretch {
80 public:
81 
Stretch()82     Stretch() : fGlyphStart(), fGlyphEnd(), fWidth(0), fTextRange(0, 0), fTextMetrics() { }
83 
Stretch(GlyphPos glyphStart,size_t textIndex,const TextMetrics & metrics)84     Stretch(GlyphPos glyphStart, size_t textIndex, const TextMetrics& metrics)
85         : fGlyphStart(glyphStart)
86         , fGlyphEnd(glyphStart)
87         , fWidth(0.0)
88         , fTextRange(textIndex, textIndex)
89         , fTextMetrics(metrics) { }
90 
91     Stretch(const Stretch&) = default;
92     Stretch(Stretch&&) = default;
93     Stretch& operator=(Stretch&&) = default;
94     Stretch& operator=(const Stretch&) = default;
95 
isEmpty()96     bool isEmpty() const {
97         if (this->fGlyphStart.isEmpty()) {
98             SkASSERT(this->fGlyphEnd.isEmpty());
99             return true;
100         } else {
101             SkASSERT(!this->fGlyphEnd.isEmpty());
102             return false;
103             //return (this->fGlyphStart.runIndex() == this->fGlyphEnd.runIndex() &&
104             //        this->fGlyphStart.glyphIndex() == this->fGlyphEnd.glyphIndex());
105         }
106     }
107 
clean()108     void clean() {
109         fGlyphStart = fGlyphEnd;
110         fTextRange.fStart = fTextRange.fEnd;
111         fWidth = 0.0f;
112         fTextMetrics.clean();
113     }
114 
moveTo(Stretch & tail)115     void moveTo(Stretch& tail) {
116 
117         if (tail.isEmpty()) {
118             return;
119         }
120 
121         if (this->isEmpty()) {
122             if (!tail.isEmpty()) {
123                 this->fGlyphStart = tail.fGlyphStart;
124                 this->fGlyphEnd = tail.fGlyphEnd;
125                 this->fWidth = tail.fWidth;
126                 this->fTextRange = tail.fTextRange;
127                 this->fTextMetrics = tail.fTextMetrics;
128             }
129             tail.clean();
130             return;
131         }
132 
133         SkASSERT(this->fGlyphEnd.runIndex() != tail.fGlyphStart.runIndex() ||
134                        this->fGlyphEnd.glyphIndex() == tail.fGlyphStart.glyphIndex());
135         this->fGlyphEnd = tail.fGlyphEnd;
136         this->fWidth += tail.fWidth;
137         this->fTextRange.merge(tail.fTextRange);
138         this->fTextMetrics.merge(tail.fTextMetrics);
139         tail.clean();
140     }
141 
finish(size_t glyphIndex,size_t textIndex,SkScalar width)142     void finish(size_t glyphIndex, size_t textIndex, SkScalar width) {
143         this->fTextRange.fEnd = textIndex;
144         this->fGlyphEnd.setGlyphIndex(glyphIndex);
145         this->fWidth = width;
146     }
147 
width()148     SkScalar width() const { return fWidth; }
textRange()149     TextRange textRange() const { return fTextRange; }
setTextRange(TextRange range)150     void setTextRange(TextRange range) { fTextRange = range; }
151 
textMetrics()152     const TextMetrics& textMetrics() const { return fTextMetrics; }
glyphStart()153     GlyphPos glyphStart() const { return fGlyphStart; }
glyphEnd()154     GlyphPos glyphEnd() const { return fGlyphEnd; }
glyphStartIndex()155     size_t glyphStartIndex() const { return fGlyphStart.glyphIndex(); }
textStart()156     size_t textStart() const { return fTextRange.fStart; }
157 
158 private:
159     GlyphPos fGlyphStart;
160     GlyphPos fGlyphEnd;
161     SkScalar fWidth;
162     TextRange fTextRange;
163     TextMetrics fTextMetrics;
164 };
165 
166 class Line {
167 public:
168     Line(Processor* processor, const Stretch& stretch, const Stretch& spaces);
169     ~Line() = default;
170 
171 private:
172     friend class Processor;
173 
174     GlyphPos fTextStart;
175     GlyphPos fTextEnd;
176     GlyphPos fWhitespacesEnd;
177     TextRange fText;
178     TextRange fWhitespaces;
179     SkScalar fTextWidth;
180     SkScalar fSpacesWidth;
181     TextMetrics fTextMetrics;
182     SkSTArray<1, size_t, true> fRunsInVisualOrder;
183     Processor* fProcessor;
184 };
185 
186 } // namespace text
187 } // namespace skia
188 #endif
189