/src/skia/src/core/SkTextBlobPriv.h
Line | Count | Source |
1 | | /* |
2 | | * Copyright 2018 Google Inc. |
3 | | * |
4 | | * Use of this source code is governed by a BSD-style license that can be |
5 | | * found in the LICENSE file. |
6 | | */ |
7 | | |
8 | | #ifndef SkTextBlobPriv_DEFINED |
9 | | #define SkTextBlobPriv_DEFINED |
10 | | |
11 | | #include "include/core/SkColorFilter.h" |
12 | | #include "include/core/SkFont.h" |
13 | | #include "include/core/SkImageFilter.h" |
14 | | #include "include/core/SkMaskFilter.h" |
15 | | #include "include/core/SkPathEffect.h" |
16 | | #include "include/core/SkShader.h" |
17 | | #include "include/core/SkTextBlob.h" |
18 | | #include "include/core/SkTypeface.h" |
19 | | #include "src/core/SkPaintPriv.h" |
20 | | #include "src/core/SkSafeMath.h" |
21 | | |
22 | | class SkReadBuffer; |
23 | | class SkWriteBuffer; |
24 | | |
25 | | class SkTextBlobPriv { |
26 | | public: |
27 | | /** |
28 | | * Serialize to a buffer. |
29 | | */ |
30 | | static void Flatten(const SkTextBlob& , SkWriteBuffer&); |
31 | | |
32 | | /** |
33 | | * Recreate an SkTextBlob that was serialized into a buffer. |
34 | | * |
35 | | * @param SkReadBuffer Serialized blob data. |
36 | | * @return A new SkTextBlob representing the serialized data, or NULL if the buffer is |
37 | | * invalid. |
38 | | */ |
39 | | static sk_sp<SkTextBlob> MakeFromBuffer(SkReadBuffer&); |
40 | | }; |
41 | | |
42 | | // |
43 | | // Textblob data is laid out into externally-managed storage as follows: |
44 | | // |
45 | | // ----------------------------------------------------------------------------- |
46 | | // | SkTextBlob | RunRecord | Glyphs[] | Pos[] | RunRecord | Glyphs[] | Pos[] | ... |
47 | | // ----------------------------------------------------------------------------- |
48 | | // |
49 | | // Each run record describes a text blob run, and can be used to determine the (implicit) |
50 | | // location of the following record. |
51 | | // |
52 | | // Extended Textblob runs have more data after the Pos[] array: |
53 | | // |
54 | | // ------------------------------------------------------------------------- |
55 | | // ... | RunRecord | Glyphs[] | Pos[] | TextSize | Clusters[] | Text[] | ... |
56 | | // ------------------------------------------------------------------------- |
57 | | // |
58 | | // To determine the length of the extended run data, the TextSize must be read. |
59 | | // |
60 | | // Extended Textblob runs may be mixed with non-extended runs. |
61 | | |
62 | | SkDEBUGCODE(static const unsigned kRunRecordMagic = 0xb10bcafe;) |
63 | | |
64 | | class SkTextBlob::RunRecord { |
65 | | public: |
66 | | RunRecord(uint32_t count, uint32_t textSize, const SkPoint& offset, const SkFont& font, GlyphPositioning pos) |
67 | | : fFont(font) |
68 | | , fCount(count) |
69 | | , fOffset(offset) |
70 | 483k | , fFlags(pos) { |
71 | 483k | SkASSERT(static_cast<unsigned>(pos) <= Flags::kPositioning_Mask); |
72 | | |
73 | 483k | SkDEBUGCODE(fMagic = kRunRecordMagic); |
74 | 483k | if (textSize > 0) { |
75 | 156 | fFlags |= kExtended_Flag; |
76 | 156 | *this->textSizePtr() = textSize; |
77 | 156 | } |
78 | 483k | } |
79 | | |
80 | 8.03M | uint32_t glyphCount() const { |
81 | 8.03M | return fCount; |
82 | 8.03M | } |
83 | | |
84 | 995k | const SkPoint& offset() const { |
85 | 995k | return fOffset; |
86 | 995k | } |
87 | | |
88 | 2.22M | const SkFont& font() const { |
89 | 2.22M | return fFont; |
90 | 2.22M | } |
91 | | |
92 | 2.77M | GlyphPositioning positioning() const { |
93 | 2.77M | return static_cast<GlyphPositioning>(fFlags & kPositioning_Mask); |
94 | 2.77M | } |
95 | | |
96 | 3.22M | uint16_t* glyphBuffer() const { |
97 | 3.22M | static_assert(SkIsAlignPtr(sizeof(RunRecord)), ""); |
98 | | // Glyphs are stored immediately following the record. |
99 | 3.22M | return reinterpret_cast<uint16_t*>(const_cast<RunRecord*>(this) + 1); |
100 | 3.22M | } |
101 | | |
102 | | // can be aliased with pointBuffer() or xformBuffer() |
103 | 1.37M | SkScalar* posBuffer() const { |
104 | | // Position scalars follow the (aligned) glyph buffer. |
105 | 1.37M | return reinterpret_cast<SkScalar*>(reinterpret_cast<uint8_t*>(this->glyphBuffer()) + |
106 | 1.37M | SkAlign4(fCount * sizeof(uint16_t))); |
107 | 1.37M | } |
108 | | |
109 | | // alias for posBuffer() |
110 | 13.6k | SkPoint* pointBuffer() const { |
111 | 13.6k | SkASSERT(this->positioning() == (GlyphPositioning)2); |
112 | 13.6k | return reinterpret_cast<SkPoint*>(this->posBuffer()); |
113 | 13.6k | } |
114 | | |
115 | | // alias for posBuffer() |
116 | 854k | SkRSXform* xformBuffer() const { |
117 | 854k | SkASSERT(this->positioning() == (GlyphPositioning)3); |
118 | 854k | return reinterpret_cast<SkRSXform*>(this->posBuffer()); |
119 | 854k | } |
120 | | |
121 | 526k | uint32_t textSize() const { return isExtended() ? *this->textSizePtr() : 0; } |
122 | | |
123 | 888k | uint32_t* clusterBuffer() const { |
124 | | // clusters follow the textSize. |
125 | 887k | return isExtended() ? 1 + this->textSizePtr() : nullptr; |
126 | 888k | } |
127 | | |
128 | 888k | char* textBuffer() const { |
129 | 888k | return isExtended() |
130 | 226 | ? reinterpret_cast<char*>(this->clusterBuffer() + fCount) |
131 | 887k | : nullptr; |
132 | 888k | } |
133 | | |
134 | 430k | bool isLastRun() const { return SkToBool(fFlags & kLast_Flag); } |
135 | | |
136 | | static size_t StorageSize(uint32_t glyphCount, uint32_t textSize, |
137 | | SkTextBlob::GlyphPositioning positioning, |
138 | | SkSafeMath* safe); |
139 | | |
140 | | static const RunRecord* First(const SkTextBlob* blob); |
141 | | |
142 | | static const RunRecord* Next(const RunRecord* run); |
143 | | |
144 | | void validate(const uint8_t* storageTop) const; |
145 | | |
146 | | private: |
147 | | friend class SkTextBlobBuilder; |
148 | | |
149 | | enum Flags { |
150 | | kPositioning_Mask = 0x03, // bits 0-1 reserved for positioning |
151 | | kLast_Flag = 0x04, // set for the last blob run |
152 | | kExtended_Flag = 0x08, // set for runs with text/cluster info |
153 | | }; |
154 | | |
155 | | static const RunRecord* NextUnchecked(const RunRecord* run); |
156 | | |
157 | | static size_t PosCount(uint32_t glyphCount, |
158 | | SkTextBlob::GlyphPositioning positioning, |
159 | | SkSafeMath* safe); |
160 | | |
161 | | uint32_t* textSizePtr() const; |
162 | | |
163 | | void grow(uint32_t count); |
164 | | |
165 | 2.78M | bool isExtended() const { |
166 | 2.78M | return fFlags & kExtended_Flag; |
167 | 2.78M | } |
168 | | |
169 | | SkFont fFont; |
170 | | uint32_t fCount; |
171 | | SkPoint fOffset; |
172 | | uint32_t fFlags; |
173 | | |
174 | | SkDEBUGCODE(unsigned fMagic;) |
175 | | }; |
176 | | |
177 | | /** |
178 | | * Iterate through all of the text runs of the text blob. For example: |
179 | | * for (SkTextBlobRunIterator it(blob); !it.done(); it.next()) { |
180 | | * ..... |
181 | | * } |
182 | | */ |
183 | | class SkTextBlobRunIterator { |
184 | | public: |
185 | | SkTextBlobRunIterator(const SkTextBlob* blob); |
186 | | |
187 | | enum GlyphPositioning : uint8_t { |
188 | | kDefault_Positioning = 0, // Default glyph advances -- zero scalars per glyph. |
189 | | kHorizontal_Positioning = 1, // Horizontal positioning -- one scalar per glyph. |
190 | | kFull_Positioning = 2, // Point positioning -- two scalars per glyph. |
191 | | kRSXform_Positioning = 3, // RSXform positioning -- four scalars per glyph. |
192 | | }; |
193 | | |
194 | 2.55M | bool done() const { |
195 | 2.55M | return !fCurrentRun; |
196 | 2.55M | } |
197 | | void next(); |
198 | | |
199 | 1.24M | uint32_t glyphCount() const { |
200 | 1.24M | SkASSERT(!this->done()); |
201 | 1.24M | return fCurrentRun->glyphCount(); |
202 | 1.24M | } |
203 | 458k | const uint16_t* glyphs() const { |
204 | 458k | SkASSERT(!this->done()); |
205 | 458k | return fCurrentRun->glyphBuffer(); |
206 | 458k | } |
207 | 1.17k | const SkScalar* pos() const { |
208 | 1.17k | SkASSERT(!this->done()); |
209 | 1.17k | return fCurrentRun->posBuffer(); |
210 | 1.17k | } |
211 | | // alias for pos() |
212 | 6.73k | const SkPoint* points() const { |
213 | 6.73k | return fCurrentRun->pointBuffer(); |
214 | 6.73k | } |
215 | | // alias for pos() |
216 | 438k | const SkRSXform* xforms() const { |
217 | 438k | return fCurrentRun->xformBuffer(); |
218 | 438k | } |
219 | 47.4k | const SkPoint& offset() const { |
220 | 47.4k | SkASSERT(!this->done()); |
221 | 47.4k | return fCurrentRun->offset(); |
222 | 47.4k | } |
223 | 864k | const SkFont& font() const { |
224 | 864k | SkASSERT(!this->done()); |
225 | 864k | return fCurrentRun->font(); |
226 | 864k | } |
227 | | GlyphPositioning positioning() const; |
228 | | unsigned scalarsPerGlyph() const; |
229 | 404k | uint32_t* clusters() const { |
230 | 404k | SkASSERT(!this->done()); |
231 | 404k | return fCurrentRun->clusterBuffer(); |
232 | 404k | } |
233 | 404k | uint32_t textSize() const { |
234 | 404k | SkASSERT(!this->done()); |
235 | 404k | return fCurrentRun->textSize(); |
236 | 404k | } |
237 | 404k | char* text() const { |
238 | 404k | SkASSERT(!this->done()); |
239 | 404k | return fCurrentRun->textBuffer(); |
240 | 404k | } |
241 | | |
242 | | bool isLCD() const; |
243 | | |
244 | | private: |
245 | | const SkTextBlob::RunRecord* fCurrentRun; |
246 | | |
247 | | SkDEBUGCODE(uint8_t* fStorageTop;) |
248 | | }; |
249 | | |
250 | | #endif // SkTextBlobPriv_DEFINED |