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