Flutter Engine
The Flutter Engine
TextWrapper.h
Go to the documentation of this file.
1// Copyright 2019 Google LLC.
2#ifndef TextWrapper_DEFINED
3#define TextWrapper_DEFINED
4
5#include <string>
8
9namespace skia {
10namespace textlayout {
11
12class ParagraphImpl;
13
15 class ClusterPos {
16 public:
17 ClusterPos() : fCluster(nullptr), fPos(0) {}
18 ClusterPos(Cluster* cluster, size_t pos) : fCluster(cluster), fPos(pos) {}
19 inline Cluster* cluster() const { return fCluster; }
20 inline size_t position() const { return fPos; }
21 inline void setPosition(size_t pos) { fPos = pos; }
22 void clean() {
23 fCluster = nullptr;
24 fPos = 0;
25 }
26 void move(bool up) {
27 fCluster += up ? 1 : -1;
28 fPos = up ? 0 : fCluster->endPos();
29 }
30
31 private:
32 Cluster* fCluster;
33 size_t fPos;
34 };
35 class TextStretch {
36 public:
37 TextStretch() : fStart(), fEnd(), fWidth(0), fWidthWithGhostSpaces(0) {}
38 TextStretch(Cluster* s, Cluster* e, bool forceStrut)
39 : fStart(s, 0), fEnd(e, e->endPos()), fMetrics(forceStrut), fWidth(0), fWidthWithGhostSpaces(0) {
40 for (auto c = s; c <= e; ++c) {
41 if (auto r = c->runOrNull()) {
42 fMetrics.add(r);
43 }
44 if (c < e) {
45 fWidth += c->width();
46 }
47 }
48 fWidthWithGhostSpaces = fWidth;
49 }
50
51 inline SkScalar width() const { return fWidth; }
52 SkScalar widthWithGhostSpaces() const { return fWidthWithGhostSpaces; }
53 inline Cluster* startCluster() const { return fStart.cluster(); }
54 inline Cluster* endCluster() const { return fEnd.cluster(); }
55 inline Cluster* breakCluster() const { return fBreak.cluster(); }
56 inline InternalLineMetrics& metrics() { return fMetrics; }
57 inline size_t startPos() const { return fStart.position(); }
58 inline size_t endPos() const { return fEnd.position(); }
59 bool endOfCluster() { return fEnd.position() == fEnd.cluster()->endPos(); }
60 bool endOfWord() {
61 return endOfCluster() &&
62 (fEnd.cluster()->isHardBreak() || fEnd.cluster()->isSoftBreak());
63 }
64
65 void extend(TextStretch& stretch) {
66 fMetrics.add(stretch.fMetrics);
67 fEnd = stretch.fEnd;
68 fWidth += stretch.fWidth;
69 stretch.clean();
70 }
71
72 bool empty() { return fStart.cluster() == fEnd.cluster() &&
73 fStart.position() == fEnd.position(); }
74
75 void setMetrics(const InternalLineMetrics& metrics) { fMetrics = metrics; }
76
77 void extend(Cluster* cluster) {
78 if (fStart.cluster() == nullptr) {
79 fStart = ClusterPos(cluster, cluster->startPos());
80 }
81 fEnd = ClusterPos(cluster, cluster->endPos());
82 // TODO: Make sure all the checks are correct and there are no unnecessary checks
83 auto& r = cluster->run();
84 if (!cluster->isHardBreak() && !r.isPlaceholder()) {
85 // We ignore metrics for \n as the Flutter does
86 fMetrics.add(&r);
87 }
88 fWidth += cluster->width();
89 }
90
91 void extend(Cluster* cluster, size_t pos) {
92 fEnd = ClusterPos(cluster, pos);
93 if (auto r = cluster->runOrNull()) {
94 fMetrics.add(r);
95 }
96 }
97
98 void startFrom(Cluster* cluster, size_t pos) {
99 fStart = ClusterPos(cluster, pos);
100 fEnd = ClusterPos(cluster, pos);
101 if (auto r = cluster->runOrNull()) {
102 // In case of placeholder we should ignore the default text style -
103 // we will pick up the correct one from the placeholder
104 if (!r->isPlaceholder()) {
105 fMetrics.add(r);
106 }
107 }
108 fWidth = 0;
109 }
110
111 void saveBreak() {
112 fWidthWithGhostSpaces = fWidth;
113 fBreak = fEnd;
114 }
115
116 void restoreBreak() {
117 fWidth = fWidthWithGhostSpaces;
118 fEnd = fBreak;
119 }
120
121 void shiftBreak() {
122 fBreak.move(true);
123 }
124
125 void trim() {
126
127 if (fEnd.cluster() != nullptr &&
128 fEnd.cluster()->owner() != nullptr &&
129 fEnd.cluster()->runOrNull() != nullptr &&
130 fEnd.cluster()->run().placeholderStyle() == nullptr &&
131 fWidth > 0) {
132 fWidth -= (fEnd.cluster()->width() - fEnd.cluster()->trimmedWidth(fEnd.position()));
133 }
134 }
135
136 void trim(Cluster* cluster) {
137 SkASSERT(fEnd.cluster() == cluster);
138 if (fEnd.cluster() > fStart.cluster()) {
139 fEnd.move(false);
140 fWidth -= cluster->width();
141 } else {
142 fEnd.setPosition(fStart.position());
143 fWidth = 0;
144 }
145 }
146
147 void clean() {
148 fStart.clean();
149 fEnd.clean();
150 fWidth = 0;
151 fMetrics.clean();
152 }
153
154 private:
155 ClusterPos fStart;
156 ClusterPos fEnd;
157 ClusterPos fBreak;
158 InternalLineMetrics fMetrics;
159 SkScalar fWidth;
160 SkScalar fWidthWithGhostSpaces;
161 };
162
163public:
165 fLineNumber = 1;
166 fHardLineBreak = false;
167 fExceededMaxLines = false;
168 }
169
170 using AddLineToParagraph = std::function<void(TextRange textExcludingSpaces,
172 TextRange textIncludingNewlines,
173 ClusterRange clusters,
174 ClusterRange clustersWithGhosts,
176 size_t startClip,
177 size_t endClip,
179 SkVector advance,
180 InternalLineMetrics metrics,
181 bool addEllipsis)>;
183 SkScalar maxWidth,
184 const AddLineToParagraph& addLine);
185
186 SkScalar height() const { return fHeight; }
187 SkScalar minIntrinsicWidth() const { return fMinIntrinsicWidth; }
188 SkScalar maxIntrinsicWidth() const { return fMaxIntrinsicWidth; }
189 bool exceededMaxLines() const { return fExceededMaxLines; }
190
191private:
192 TextStretch fWords;
193 TextStretch fClusters;
194 TextStretch fClip;
195 TextStretch fEndLine;
196 size_t fLineNumber;
197 bool fTooLongWord;
198 bool fTooLongCluster;
199
200 bool fHardLineBreak;
201 bool fExceededMaxLines;
202
203 SkScalar fHeight;
204 SkScalar fMinIntrinsicWidth;
205 SkScalar fMaxIntrinsicWidth;
206
207 void reset() {
208 fWords.clean();
209 fClusters.clean();
210 fClip.clean();
211 fTooLongCluster = false;
212 fTooLongWord = false;
213 fHardLineBreak = false;
214 }
215
216 void lookAhead(SkScalar maxWidth, Cluster* endOfClusters, bool applyRoundingHack);
217 void moveForward(bool hasEllipsis);
218 void trimEndSpaces(TextAlign align);
219 std::tuple<Cluster*, size_t, SkScalar> trimStartSpaces(Cluster* endOfClusters);
220 SkScalar getClustersTrimmedWidth();
221};
222} // namespace textlayout
223} // namespace skia
224
225#endif // TextWrapper_DEFINED
SkPoint pos
#define SkASSERT(cond)
Definition: SkAssert.h:116
static SkCanvas * trim(SkCanvas *canvas, SkScalar width, SkScalar height, const SkRect *content)
Definition: SkDocument.cpp:19
size_t startPos() const
Definition: Run.h:316
Run * runOrNull() const
Definition: Run.cpp:329
size_t endPos() const
Definition: Run.h:317
bool isHardBreak() const
Definition: Run.h:310
SkScalar width() const
Definition: Run.h:318
Run & run() const
Definition: Run.cpp:336
std::function< void(TextRange textExcludingSpaces, TextRange text, TextRange textIncludingNewlines, ClusterRange clusters, ClusterRange clustersWithGhosts, SkScalar AddLineToParagraph, size_t startClip, size_t endClip, SkVector offset, SkVector advance, InternalLineMetrics metrics, bool addEllipsis)> AddLineToParagraph
Definition: TextWrapper.h:181
SkScalar minIntrinsicWidth() const
Definition: TextWrapper.h:187
void breakTextIntoLines(ParagraphImpl *parent, SkScalar maxWidth, const AddLineToParagraph &addLine)
SkScalar maxIntrinsicWidth() const
Definition: TextWrapper.h:188
float SkScalar
Definition: extension.cpp:12
struct MyStruct s
EMSCRIPTEN_KEEPALIVE void empty()
Dart_NativeFunction function
Definition: fuchsia.cc:51
std::u16string text
Definition: DartTypes.h:13
int32_t width
SeparatedVector2 offset