/src/skia/include/core/SkTextBlob.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright 2014 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 SkTextBlob_DEFINED |
9 | | #define SkTextBlob_DEFINED |
10 | | |
11 | | #include "include/core/SkFont.h" |
12 | | #include "include/core/SkFontTypes.h" |
13 | | #include "include/core/SkPoint.h" |
14 | | #include "include/core/SkRSXform.h" |
15 | | #include "include/core/SkRect.h" |
16 | | #include "include/core/SkRefCnt.h" |
17 | | #include "include/core/SkScalar.h" |
18 | | #include "include/core/SkSpan.h" |
19 | | #include "include/core/SkTypes.h" |
20 | | #include "include/private/base/SkDebug.h" |
21 | | #include "include/private/base/SkTemplates.h" |
22 | | |
23 | | #include <atomic> |
24 | | #include <cstdint> |
25 | | #include <cstring> |
26 | | |
27 | | class SkData; |
28 | | class SkPaint; |
29 | | class SkTypeface; |
30 | | struct SkDeserialProcs; |
31 | | struct SkSerialProcs; |
32 | | |
33 | | namespace sktext { |
34 | | class GlyphRunList; |
35 | | } |
36 | | |
37 | | /** \class SkTextBlob |
38 | | SkTextBlob combines multiple text runs into an immutable container. Each text |
39 | | run consists of glyphs, SkPaint, and position. Only parts of SkPaint related to |
40 | | fonts and text rendering are used by run. |
41 | | */ |
42 | | class SK_API SkTextBlob final : public SkNVRefCnt<SkTextBlob> { |
43 | | private: |
44 | | class RunRecord; |
45 | | |
46 | | public: |
47 | | |
48 | | /** Returns conservative bounding box. Uses SkPaint associated with each glyph to |
49 | | determine glyph bounds, and unions all bounds. Returned bounds may be |
50 | | larger than the bounds of all glyphs in runs. |
51 | | |
52 | | @return conservative bounding box |
53 | | */ |
54 | 748k | const SkRect& bounds() const { return fBounds; } |
55 | | |
56 | | /** Returns a non-zero value unique among all text blobs. |
57 | | |
58 | | @return identifier for SkTextBlob |
59 | | */ |
60 | 7.49k | uint32_t uniqueID() const { return fUniqueID; } |
61 | | |
62 | | /** Returns the number of intervals that intersect bounds. |
63 | | bounds describes a pair of lines parallel to the text advance. |
64 | | The return count is zero or a multiple of two, and is at most twice the number of glyphs in |
65 | | the the blob. |
66 | | |
67 | | Pass nullptr for intervals to determine the size of the interval array. |
68 | | |
69 | | Runs within the blob that contain SkRSXform are ignored when computing intercepts. |
70 | | |
71 | | @param bounds lower and upper line parallel to the advance |
72 | | @param intervals returned intersections; may be nullptr |
73 | | @param paint specifies stroking, SkPathEffect that affects the result; may be nullptr |
74 | | @return number of intersections; may be zero |
75 | | */ |
76 | | int getIntercepts(const SkScalar bounds[2], SkScalar intervals[], |
77 | | const SkPaint* paint = nullptr) const; |
78 | | |
79 | | /** Creates SkTextBlob with a single run. |
80 | | |
81 | | font contains attributes used to define the run text. |
82 | | |
83 | | When encoding is SkTextEncoding::kUTF8, SkTextEncoding::kUTF16, or |
84 | | SkTextEncoding::kUTF32, this function uses the default |
85 | | character-to-glyph mapping from the SkTypeface in font. It does not |
86 | | perform typeface fallback for characters not found in the SkTypeface. |
87 | | It does not perform kerning or other complex shaping; glyphs are |
88 | | positioned based on their default advances. |
89 | | |
90 | | @param text character code points or glyphs drawn |
91 | | @param byteLength byte length of text array |
92 | | @param font text size, typeface, text scale, and so on, used to draw |
93 | | @param encoding text encoding used in the text array |
94 | | @return SkTextBlob constructed from one run |
95 | | */ |
96 | | static sk_sp<SkTextBlob> MakeFromText(const void* text, size_t byteLength, const SkFont& font, |
97 | | SkTextEncoding encoding = SkTextEncoding::kUTF8); |
98 | | |
99 | | /** Creates SkTextBlob with a single run. string meaning depends on SkTextEncoding; |
100 | | by default, string is encoded as UTF-8. |
101 | | |
102 | | font contains attributes used to define the run text. |
103 | | |
104 | | When encoding is SkTextEncoding::kUTF8, SkTextEncoding::kUTF16, or |
105 | | SkTextEncoding::kUTF32, this function uses the default |
106 | | character-to-glyph mapping from the SkTypeface in font. It does not |
107 | | perform typeface fallback for characters not found in the SkTypeface. |
108 | | It does not perform kerning or other complex shaping; glyphs are |
109 | | positioned based on their default advances. |
110 | | |
111 | | @param string character code points or glyphs drawn |
112 | | @param font text size, typeface, text scale, and so on, used to draw |
113 | | @param encoding text encoding used in the text array |
114 | | @return SkTextBlob constructed from one run |
115 | | */ |
116 | | static sk_sp<SkTextBlob> MakeFromString(const char* string, const SkFont& font, |
117 | 0 | SkTextEncoding encoding = SkTextEncoding::kUTF8) { |
118 | 0 | if (!string) { |
119 | 0 | return nullptr; |
120 | 0 | } |
121 | 0 | return MakeFromText(string, strlen(string), font, encoding); |
122 | 0 | } |
123 | | |
124 | | /** Returns a textblob built from a single run of text with x-positions and a single y value. |
125 | | This is equivalent to using SkTextBlobBuilder and calling allocRunPosH(). |
126 | | Returns nullptr if byteLength is zero. |
127 | | |
128 | | @param text character code points or glyphs drawn (based on encoding) |
129 | | @param byteLength byte length of text array |
130 | | @param xpos array of x-positions, must contain values for all of the character points. |
131 | | @param constY shared y-position for each character point, to be paired with each xpos. |
132 | | @param font SkFont used for this run |
133 | | @param encoding specifies the encoding of the text array. |
134 | | @return new textblob or nullptr |
135 | | */ |
136 | | static sk_sp<SkTextBlob> MakeFromPosTextH(const void* text, size_t byteLength, |
137 | | SkSpan<const SkScalar> xpos, SkScalar constY, |
138 | | const SkFont& font, |
139 | | SkTextEncoding encoding = SkTextEncoding::kUTF8); |
140 | | |
141 | | /** Returns a textblob built from a single run of text with positions. |
142 | | This is equivalent to using SkTextBlobBuilder and calling allocRunPos(). |
143 | | Returns nullptr if byteLength is zero. |
144 | | |
145 | | @param text character code points or glyphs drawn (based on encoding) |
146 | | @param byteLength byte length of text array |
147 | | @param pos array of positions, must contain values for all of the character points. |
148 | | @param font SkFont used for this run |
149 | | @param encoding specifies the encoding of the text array. |
150 | | @return new textblob or nullptr |
151 | | */ |
152 | | static sk_sp<SkTextBlob> MakeFromPosText(const void* text, size_t byteLength, |
153 | | SkSpan<const SkPoint> pos, const SkFont& font, |
154 | | SkTextEncoding encoding = SkTextEncoding::kUTF8); |
155 | | |
156 | | static sk_sp<SkTextBlob> MakeFromRSXform(const void* text, size_t byteLength, |
157 | | SkSpan<const SkRSXform> xform, const SkFont& font, |
158 | | SkTextEncoding encoding = SkTextEncoding::kUTF8); |
159 | | |
160 | | // Helpers for glyphs |
161 | | |
162 | | static sk_sp<SkTextBlob> MakeFromPosHGlyphs(SkSpan<const SkGlyphID> glyphs, |
163 | | SkSpan<const SkScalar> xpos, SkScalar constY, |
164 | 0 | const SkFont& font) { |
165 | 0 | return MakeFromPosTextH(glyphs.data(), glyphs.size() * sizeof(SkGlyphID), xpos, constY, |
166 | 0 | font, SkTextEncoding::kGlyphID); |
167 | 0 | } |
168 | | static sk_sp<SkTextBlob> MakeFromPosGlyphs(SkSpan<const SkGlyphID> glyphs, |
169 | 0 | SkSpan<const SkPoint> pos, const SkFont& font) { |
170 | 0 | return MakeFromPosText(glyphs.data(), glyphs.size() * sizeof(SkGlyphID), pos, font, |
171 | 0 | SkTextEncoding::kGlyphID); |
172 | 0 | } |
173 | | static sk_sp<SkTextBlob> MakeFromRSXformGlyphs(SkSpan<const SkGlyphID> glyphs, |
174 | | SkSpan<const SkRSXform> xform, |
175 | 0 | const SkFont& font) { |
176 | 0 | return MakeFromRSXform(glyphs.data(), glyphs.size() * sizeof(SkGlyphID), xform, font, |
177 | 0 | SkTextEncoding::kGlyphID); |
178 | 0 | } |
179 | | |
180 | | /** Writes data to allow later reconstruction of SkTextBlob. memory points to storage |
181 | | to receive the encoded data, and memory_size describes the size of storage. |
182 | | Returns bytes used if provided storage is large enough to hold all data; |
183 | | otherwise, returns zero. |
184 | | |
185 | | procs.fTypefaceProc permits supplying a custom function to encode SkTypeface. |
186 | | If procs.fTypefaceProc is nullptr, default encoding is used. procs.fTypefaceCtx |
187 | | may be used to provide user context to procs.fTypefaceProc; procs.fTypefaceProc |
188 | | is called with a pointer to SkTypeface and user context. |
189 | | |
190 | | @param procs custom serial data encoders; may be nullptr |
191 | | @param memory storage for data |
192 | | @param memory_size size of storage |
193 | | @return bytes written, or zero if required storage is larger than memory_size |
194 | | |
195 | | example: https://fiddle.skia.org/c/@TextBlob_serialize |
196 | | */ |
197 | | size_t serialize(const SkSerialProcs& procs, void* memory, size_t memory_size) const; |
198 | | |
199 | | /** Returns storage containing SkData describing SkTextBlob, using optional custom |
200 | | encoders. |
201 | | |
202 | | procs.fTypefaceProc permits supplying a custom function to encode SkTypeface. |
203 | | If procs.fTypefaceProc is nullptr, default encoding is used. procs.fTypefaceCtx |
204 | | may be used to provide user context to procs.fTypefaceProc; procs.fTypefaceProc |
205 | | is called with a pointer to SkTypeface and user context. |
206 | | |
207 | | @param procs custom serial data encoders; may be nullptr |
208 | | @return storage containing serialized SkTextBlob |
209 | | |
210 | | example: https://fiddle.skia.org/c/@TextBlob_serialize_2 |
211 | | */ |
212 | | sk_sp<SkData> serialize(const SkSerialProcs& procs) const; |
213 | | |
214 | | /** Recreates SkTextBlob that was serialized into data. Returns constructed SkTextBlob |
215 | | if successful; otherwise, returns nullptr. Fails if size is smaller than |
216 | | required data length, or if data does not permit constructing valid SkTextBlob. |
217 | | |
218 | | procs.fTypefaceProc permits supplying a custom function to decode SkTypeface. |
219 | | If procs.fTypefaceProc is nullptr, default decoding is used. procs.fTypefaceCtx |
220 | | may be used to provide user context to procs.fTypefaceProc; procs.fTypefaceProc |
221 | | is called with a pointer to SkTypeface data, data byte length, and user context. |
222 | | |
223 | | @param data pointer for serial data |
224 | | @param size size of data |
225 | | @param procs custom serial data decoders; may be nullptr |
226 | | @return SkTextBlob constructed from data in memory |
227 | | */ |
228 | | static sk_sp<SkTextBlob> Deserialize(const void* data, size_t size, |
229 | | const SkDeserialProcs& procs); |
230 | | |
231 | | class SK_API Iter { |
232 | | public: |
233 | | struct Run { |
234 | | SkTypeface* fTypeface; |
235 | | int fGlyphCount; |
236 | | const SkGlyphID* fGlyphIndices; |
237 | | #ifdef SK_UNTIL_CRBUG_1187654_IS_FIXED |
238 | | const uint32_t* fClusterIndex_forTest; |
239 | | int fUtf8Size_forTest; |
240 | | const char* fUtf8_forTest; |
241 | | #endif |
242 | | }; |
243 | | |
244 | | Iter(const SkTextBlob&); |
245 | | |
246 | | /** |
247 | | * Returns true for each "run" inside the textblob, setting the Run fields (if not null). |
248 | | * If this returns false, there are no more runs, and the Run parameter will be ignored. |
249 | | */ |
250 | | bool next(Run*); |
251 | | |
252 | | // Experimental, DO NO USE, will change/go-away |
253 | | struct ExperimentalRun { |
254 | | SkFont font; |
255 | | int count; |
256 | | const SkGlyphID* glyphs; |
257 | | const SkPoint* positions; |
258 | | }; |
259 | | bool experimentalNext(ExperimentalRun*); |
260 | | |
261 | | private: |
262 | | const RunRecord* fRunRecord; |
263 | | }; |
264 | | |
265 | | #ifdef SK_SUPPORT_UNSPANNED_APIS |
266 | | static sk_sp<SkTextBlob> MakeFromPosTextH(const void* text, size_t byteLength, |
267 | | const SkScalar xpos[], SkScalar constY, |
268 | | const SkFont& font, |
269 | | SkTextEncoding encoding = SkTextEncoding::kUTF8) { |
270 | | const size_t worstCaseCount = byteLength; |
271 | | return MakeFromPosTextH(text, byteLength, {xpos, worstCaseCount}, constY, font, encoding); |
272 | | } |
273 | | static sk_sp<SkTextBlob> MakeFromPosText(const void* text, size_t byteLength, |
274 | | const SkPoint pos[], const SkFont& font, |
275 | | SkTextEncoding encoding = SkTextEncoding::kUTF8) { |
276 | | const size_t worstCaseCount = byteLength; |
277 | | return MakeFromPosText(text, byteLength, {pos, worstCaseCount}, font, encoding); |
278 | | } |
279 | | static sk_sp<SkTextBlob> MakeFromRSXform(const void* text, size_t byteLength, |
280 | | const SkRSXform xform[], const SkFont& font, |
281 | | SkTextEncoding encoding = SkTextEncoding::kUTF8) { |
282 | | const size_t worstCaseCount = byteLength; |
283 | | return MakeFromRSXform(text, byteLength, {xform, worstCaseCount}, font, encoding); |
284 | | } |
285 | | #endif |
286 | | |
287 | | private: |
288 | | friend class SkNVRefCnt<SkTextBlob>; |
289 | | |
290 | | enum GlyphPositioning : uint8_t; |
291 | | |
292 | | explicit SkTextBlob(const SkRect& bounds); |
293 | | |
294 | | ~SkTextBlob(); |
295 | | |
296 | | // Memory for objects of this class is created with sk_malloc rather than operator new and must |
297 | | // be freed with sk_free. |
298 | | void operator delete(void* p); |
299 | | void* operator new(size_t); |
300 | | void* operator new(size_t, void* p); |
301 | | |
302 | | static unsigned ScalarsPerGlyph(GlyphPositioning pos); |
303 | | |
304 | | using PurgeDelegate = void (*)(uint32_t blobID, uint32_t cacheID); |
305 | | |
306 | | // Call when this blob is part of the key to a cache entry. This allows the cache |
307 | | // to know automatically those entries can be purged when this SkTextBlob is deleted. |
308 | 2.90k | void notifyAddedToCache(uint32_t cacheID, PurgeDelegate purgeDelegate) const { |
309 | 2.90k | fCacheID.store(cacheID); |
310 | 2.90k | fPurgeDelegate.store(purgeDelegate); |
311 | 2.90k | } |
312 | | |
313 | | friend class sktext::GlyphRunList; |
314 | | friend class SkTextBlobBuilder; |
315 | | friend class SkTextBlobPriv; |
316 | | friend class SkTextBlobRunIterator; |
317 | | |
318 | | const SkRect fBounds; |
319 | | const uint32_t fUniqueID; |
320 | | mutable std::atomic<uint32_t> fCacheID; |
321 | | mutable std::atomic<PurgeDelegate> fPurgeDelegate; |
322 | | |
323 | | SkDEBUGCODE(size_t fStorageSize;) |
324 | | |
325 | | // The actual payload resides in externally-managed storage, following the object. |
326 | | // (see the .cpp for more details) |
327 | | |
328 | | using INHERITED = SkRefCnt; |
329 | | }; |
330 | | |
331 | | /** \class SkTextBlobBuilder |
332 | | Helper class for constructing SkTextBlob. |
333 | | */ |
334 | | class SK_API SkTextBlobBuilder { |
335 | | public: |
336 | | |
337 | | /** Constructs empty SkTextBlobBuilder. By default, SkTextBlobBuilder has no runs. |
338 | | |
339 | | @return empty SkTextBlobBuilder |
340 | | |
341 | | example: https://fiddle.skia.org/c/@TextBlobBuilder_empty_constructor |
342 | | */ |
343 | | SkTextBlobBuilder(); |
344 | | |
345 | | /** Deletes data allocated internally by SkTextBlobBuilder. |
346 | | */ |
347 | | ~SkTextBlobBuilder(); |
348 | | |
349 | | /** Returns SkTextBlob built from runs of glyphs added by builder. Returned |
350 | | SkTextBlob is immutable; it may be copied, but its contents may not be altered. |
351 | | Returns nullptr if no runs of glyphs were added by builder. |
352 | | |
353 | | Resets SkTextBlobBuilder to its initial empty state, allowing it to be |
354 | | reused to build a new set of runs. |
355 | | |
356 | | @return SkTextBlob or nullptr |
357 | | |
358 | | example: https://fiddle.skia.org/c/@TextBlobBuilder_make |
359 | | */ |
360 | | sk_sp<SkTextBlob> make(); |
361 | | |
362 | | /** \struct SkTextBlobBuilder::RunBuffer |
363 | | RunBuffer supplies storage for glyphs and positions within a run. |
364 | | |
365 | | A run is a sequence of glyphs sharing font metrics and positioning. |
366 | | Each run may position its glyphs in one of three ways: |
367 | | by specifying where the first glyph is drawn, and allowing font metrics to |
368 | | determine the advance to subsequent glyphs; by specifying a baseline, and |
369 | | the position on that baseline for each glyph in run; or by providing SkPoint |
370 | | array, one per glyph. |
371 | | */ |
372 | | struct RunBuffer { |
373 | | SkGlyphID* glyphs; //!< storage for glyph indexes in run |
374 | | SkScalar* pos; //!< storage for glyph positions in run |
375 | | char* utf8text; //!< storage for text UTF-8 code units in run |
376 | | uint32_t* clusters; //!< storage for glyph clusters (index of UTF-8 code unit) |
377 | | |
378 | | // Helpers, since the "pos" field can be different types (always some number of floats). |
379 | 9.00k | SkPoint* points() const { return reinterpret_cast<SkPoint*>(pos); } |
380 | 4.40M | SkRSXform* xforms() const { return reinterpret_cast<SkRSXform*>(pos); } |
381 | | }; |
382 | | |
383 | | /** Returns run with storage for glyphs. Caller must write count glyphs to |
384 | | RunBuffer::glyphs before next call to SkTextBlobBuilder. |
385 | | |
386 | | RunBuffer::pos, RunBuffer::utf8text, and RunBuffer::clusters should be ignored. |
387 | | |
388 | | Glyphs share metrics in font. |
389 | | |
390 | | Glyphs are positioned on a baseline at (x, y), using font metrics to |
391 | | determine their relative placement. |
392 | | |
393 | | bounds defines an optional bounding box, used to suppress drawing when SkTextBlob |
394 | | bounds does not intersect SkSurface bounds. If bounds is nullptr, SkTextBlob bounds |
395 | | is computed from (x, y) and RunBuffer::glyphs metrics. |
396 | | |
397 | | @param font SkFont used for this run |
398 | | @param count number of glyphs |
399 | | @param x horizontal offset within the blob |
400 | | @param y vertical offset within the blob |
401 | | @param bounds optional run bounding box |
402 | | @return writable glyph buffer |
403 | | */ |
404 | | const RunBuffer& allocRun(const SkFont& font, int count, SkScalar x, SkScalar y, |
405 | | const SkRect* bounds = nullptr); |
406 | | |
407 | | /** Returns run with storage for glyphs and positions along baseline. Caller must |
408 | | write count glyphs to RunBuffer::glyphs and count scalars to RunBuffer::pos |
409 | | before next call to SkTextBlobBuilder. |
410 | | |
411 | | RunBuffer::utf8text and RunBuffer::clusters should be ignored. |
412 | | |
413 | | Glyphs share metrics in font. |
414 | | |
415 | | Glyphs are positioned on a baseline at y, using x-axis positions written by |
416 | | caller to RunBuffer::pos. |
417 | | |
418 | | bounds defines an optional bounding box, used to suppress drawing when SkTextBlob |
419 | | bounds does not intersect SkSurface bounds. If bounds is nullptr, SkTextBlob bounds |
420 | | is computed from y, RunBuffer::pos, and RunBuffer::glyphs metrics. |
421 | | |
422 | | @param font SkFont used for this run |
423 | | @param count number of glyphs |
424 | | @param y vertical offset within the blob |
425 | | @param bounds optional run bounding box |
426 | | @return writable glyph buffer and x-axis position buffer |
427 | | */ |
428 | | const RunBuffer& allocRunPosH(const SkFont& font, int count, SkScalar y, |
429 | | const SkRect* bounds = nullptr); |
430 | | |
431 | | /** Returns run with storage for glyphs and SkPoint positions. Caller must |
432 | | write count glyphs to RunBuffer::glyphs and count SkPoint to RunBuffer::pos |
433 | | before next call to SkTextBlobBuilder. |
434 | | |
435 | | RunBuffer::utf8text and RunBuffer::clusters should be ignored. |
436 | | |
437 | | Glyphs share metrics in font. |
438 | | |
439 | | Glyphs are positioned using SkPoint written by caller to RunBuffer::pos, using |
440 | | two scalar values for each SkPoint. |
441 | | |
442 | | bounds defines an optional bounding box, used to suppress drawing when SkTextBlob |
443 | | bounds does not intersect SkSurface bounds. If bounds is nullptr, SkTextBlob bounds |
444 | | is computed from RunBuffer::pos, and RunBuffer::glyphs metrics. |
445 | | |
446 | | @param font SkFont used for this run |
447 | | @param count number of glyphs |
448 | | @param bounds optional run bounding box |
449 | | @return writable glyph buffer and SkPoint buffer |
450 | | */ |
451 | | const RunBuffer& allocRunPos(const SkFont& font, int count, |
452 | | const SkRect* bounds = nullptr); |
453 | | |
454 | | // RunBuffer.pos points to SkRSXform array |
455 | | const RunBuffer& allocRunRSXform(const SkFont& font, int count); |
456 | | |
457 | | /** Returns run with storage for glyphs, text, and clusters. Caller must |
458 | | write count glyphs to RunBuffer::glyphs, textByteCount UTF-8 code units |
459 | | into RunBuffer::utf8text, and count monotonic indexes into utf8text |
460 | | into RunBuffer::clusters before next call to SkTextBlobBuilder. |
461 | | |
462 | | RunBuffer::pos should be ignored. |
463 | | |
464 | | Glyphs share metrics in font. |
465 | | |
466 | | Glyphs are positioned on a baseline at (x, y), using font metrics to |
467 | | determine their relative placement. |
468 | | |
469 | | bounds defines an optional bounding box, used to suppress drawing when SkTextBlob |
470 | | bounds does not intersect SkSurface bounds. If bounds is nullptr, SkTextBlob bounds |
471 | | is computed from (x, y) and RunBuffer::glyphs metrics. |
472 | | |
473 | | @param font SkFont used for this run |
474 | | @param count number of glyphs |
475 | | @param x horizontal offset within the blob |
476 | | @param y vertical offset within the blob |
477 | | @param textByteCount number of UTF-8 code units |
478 | | @param bounds optional run bounding box |
479 | | @return writable glyph buffer, text buffer, and cluster buffer |
480 | | */ |
481 | | const RunBuffer& allocRunText(const SkFont& font, int count, SkScalar x, SkScalar y, |
482 | | int textByteCount, const SkRect* bounds = nullptr); |
483 | | |
484 | | /** Returns run with storage for glyphs, positions along baseline, text, |
485 | | and clusters. Caller must write count glyphs to RunBuffer::glyphs, |
486 | | count scalars to RunBuffer::pos, textByteCount UTF-8 code units into |
487 | | RunBuffer::utf8text, and count monotonic indexes into utf8text into |
488 | | RunBuffer::clusters before next call to SkTextBlobBuilder. |
489 | | |
490 | | Glyphs share metrics in font. |
491 | | |
492 | | Glyphs are positioned on a baseline at y, using x-axis positions written by |
493 | | caller to RunBuffer::pos. |
494 | | |
495 | | bounds defines an optional bounding box, used to suppress drawing when SkTextBlob |
496 | | bounds does not intersect SkSurface bounds. If bounds is nullptr, SkTextBlob bounds |
497 | | is computed from y, RunBuffer::pos, and RunBuffer::glyphs metrics. |
498 | | |
499 | | @param font SkFont used for this run |
500 | | @param count number of glyphs |
501 | | @param y vertical offset within the blob |
502 | | @param textByteCount number of UTF-8 code units |
503 | | @param bounds optional run bounding box |
504 | | @return writable glyph buffer, x-axis position buffer, text buffer, and cluster buffer |
505 | | */ |
506 | | const RunBuffer& allocRunTextPosH(const SkFont& font, int count, SkScalar y, int textByteCount, |
507 | | const SkRect* bounds = nullptr); |
508 | | |
509 | | /** Returns run with storage for glyphs, SkPoint positions, text, and |
510 | | clusters. Caller must write count glyphs to RunBuffer::glyphs, count |
511 | | SkPoint to RunBuffer::pos, textByteCount UTF-8 code units into |
512 | | RunBuffer::utf8text, and count monotonic indexes into utf8text into |
513 | | RunBuffer::clusters before next call to SkTextBlobBuilder. |
514 | | |
515 | | Glyphs share metrics in font. |
516 | | |
517 | | Glyphs are positioned using SkPoint written by caller to RunBuffer::pos, using |
518 | | two scalar values for each SkPoint. |
519 | | |
520 | | bounds defines an optional bounding box, used to suppress drawing when SkTextBlob |
521 | | bounds does not intersect SkSurface bounds. If bounds is nullptr, SkTextBlob bounds |
522 | | is computed from RunBuffer::pos, and RunBuffer::glyphs metrics. |
523 | | |
524 | | @param font SkFont used for this run |
525 | | @param count number of glyphs |
526 | | @param textByteCount number of UTF-8 code units |
527 | | @param bounds optional run bounding box |
528 | | @return writable glyph buffer, SkPoint buffer, text buffer, and cluster buffer |
529 | | */ |
530 | | const RunBuffer& allocRunTextPos(const SkFont& font, int count, int textByteCount, |
531 | | const SkRect* bounds = nullptr); |
532 | | |
533 | | // RunBuffer.pos points to SkRSXform array |
534 | | const RunBuffer& allocRunTextRSXform(const SkFont& font, int count, int textByteCount, |
535 | | const SkRect* bounds = nullptr); |
536 | | |
537 | | private: |
538 | | void reserve(size_t size); |
539 | | void allocInternal(const SkFont& font, SkTextBlob::GlyphPositioning positioning, |
540 | | int count, int textBytes, SkPoint offset, const SkRect* bounds); |
541 | | bool mergeRun(const SkFont& font, SkTextBlob::GlyphPositioning positioning, |
542 | | uint32_t count, SkPoint offset); |
543 | | void updateDeferredBounds(); |
544 | | |
545 | | static SkRect ConservativeRunBounds(const SkTextBlob::RunRecord&); |
546 | | static SkRect TightRunBounds(const SkTextBlob::RunRecord&); |
547 | | |
548 | | friend class SkTextBlobPriv; |
549 | | friend class SkTextBlobBuilderPriv; |
550 | | |
551 | | skia_private::AutoTMalloc<uint8_t> fStorage; |
552 | | size_t fStorageSize; |
553 | | size_t fStorageUsed; |
554 | | |
555 | | SkRect fBounds; |
556 | | int fRunCount; |
557 | | bool fDeferredBounds; |
558 | | size_t fLastRun; // index into fStorage |
559 | | |
560 | | RunBuffer fCurrentRunBuffer; |
561 | | }; |
562 | | |
563 | | #endif // SkTextBlob_DEFINED |