blob: fc01ab1a8e6acae2cd1515c6ae6ca565f42b0578 [file] [log] [blame]
Cary Clark05c1dcf2018-12-12 13:32:56 -05001#Topic Text_Blob
2#Alias Text_Blob_Reference ##
3
4#Class SkTextBlob
5
6#Code
7#Populate
8##
9
10SkTextBlob combines multiple text runs into an immutable container. Each text
11run consists of Glyphs, Paint, and position. Only parts of Paint related to
12fonts and text rendering are used by run.
13
14# ------------------------------------------------------------------------------
15
16#Method const SkRect& bounds() const
17#In Property
18#Line # returns conservative bounding box ##
19#Populate
20
21#Example
22#Height 70
23 SkTextBlobBuilder textBlobBuilder;
24 const char bunny[] = "/(^x^)\\";
25 const int len = sizeof(bunny) - 1;
26 uint16_t glyphs[len];
Cary Clark05c1dcf2018-12-12 13:32:56 -050027 SkFont font;
Cary Clark26d173f2019-01-07 15:16:56 -050028 font.textToGlyphs(bunny, len, SkTextEncoding::kUTF8, glyphs, sizeof(glyphs));
Cary Clark05c1dcf2018-12-12 13:32:56 -050029 int runs[] = { 3, 1, 3 };
30 SkPoint textPos = { 20, 50 };
31 int glyphIndex = 0;
32 for (auto runLen : runs) {
33 font.setSize(1 == runLen ? 20 : 50);
Cary Clark05c1dcf2018-12-12 13:32:56 -050034 const SkTextBlobBuilder::RunBuffer& run =
35 textBlobBuilder.allocRun(font, runLen, textPos.fX, textPos.fY);
36 memcpy(run.glyphs, &glyphs[glyphIndex], sizeof(glyphs[0]) * runLen);
Cary Clark26d173f2019-01-07 15:16:56 -050037 textPos.fX += font.measureText(&glyphs[glyphIndex], sizeof(glyphs[0]) * runLen,
38 SkTextEncoding::kGlyphID);
Cary Clark05c1dcf2018-12-12 13:32:56 -050039 glyphIndex += runLen;
40 }
41 sk_sp<const SkTextBlob> blob = textBlobBuilder.make();
Cary Clark26d173f2019-01-07 15:16:56 -050042 SkPaint paint;
Cary Clark05c1dcf2018-12-12 13:32:56 -050043 canvas->drawTextBlob(blob.get(), 0, 0, paint);
44 paint.setStyle(SkPaint::kStroke_Style);
45 canvas->drawRect(blob->bounds(), paint);
46##
47
48#SeeAlso SkPath::getBounds
49
50#Method ##
51
52# ------------------------------------------------------------------------------
53
54#Method uint32_t uniqueID() const
55#In Property
56#Line # returns identifier for Text_Blob ##
57#Populate
58
59#Example
60for (int index = 0; index < 2; ++index) {
61 SkTextBlobBuilder textBlobBuilder;
62 const char bunny[] = "/(^x^)\\";
63 const int len = sizeof(bunny) - 1;
64 uint16_t glyphs[len];
Cary Clark05c1dcf2018-12-12 13:32:56 -050065 SkFont font;
Cary Clark26d173f2019-01-07 15:16:56 -050066 font.textToGlyphs(bunny, len, SkTextEncoding::kUTF8, glyphs, sizeof(glyphs));
Cary Clark05c1dcf2018-12-12 13:32:56 -050067 font.setScaleX(0.5);
68 int runs[] = { 3, 1, 3 };
69 SkPoint textPos = { 20, 50 };
70 int glyphIndex = 0;
71 for (auto runLen : runs) {
72 font.setSize(1 == runLen ? 20 : 50);
Cary Clark05c1dcf2018-12-12 13:32:56 -050073 const SkTextBlobBuilder::RunBuffer& run =
74 textBlobBuilder.allocRun(font, runLen, textPos.fX, textPos.fY);
75 memcpy(run.glyphs, &glyphs[glyphIndex], sizeof(glyphs[0]) * runLen);
Cary Clark26d173f2019-01-07 15:16:56 -050076 textPos.fX += font.measureText(&glyphs[glyphIndex], sizeof(glyphs[0]) * runLen,
77 SkTextEncoding::kGlyphID);
Cary Clark05c1dcf2018-12-12 13:32:56 -050078 glyphIndex += runLen;
79 }
80 sk_sp<const SkTextBlob> blob = textBlobBuilder.make();
Cary Clark26d173f2019-01-07 15:16:56 -050081 SkPaint paint;
Cary Clark05c1dcf2018-12-12 13:32:56 -050082 canvas->drawTextBlob(blob.get(), 0, 0, paint);
83 std::string id = "unique ID:" + std::to_string(blob->uniqueID());
84 canvas->drawString(id.c_str(), 30, blob->bounds().fBottom + 15, paint);
85 canvas->translate(blob->bounds().fRight + 10, 0);
86}
87##
88
89#SeeAlso SkRefCnt
90
91#Method ##
92
93# ------------------------------------------------------------------------------
94
95#Subtopic Text_Intercepts
96#Line # advanced underline, strike through ##
97
98Text_Intercepts describe the intersection of drawn text Glyphs with a pair
99of lines parallel to the text advance. Text_Intercepts permits creating a
100underline that skips Descenders.
101
Cary Clark4f738832018-12-11 08:41:11 -0500102#Method int getIntercepts(const SkScalar bounds[2], SkScalar intervals[],
103 const SkPaint* paint = nullptr) const;
Cary Clark05c1dcf2018-12-12 13:32:56 -0500104#In Text_Intercepts
Cary Clark4f738832018-12-11 08:41:11 -0500105#Line # returns where lines intersect Text_Blob; underlines ##
106#Populate
107
108#Example
109#Height 143
110 void draw(SkCanvas* canvas) {
111 SkFont font;
112 font.setSize(120);
113 SkPoint textPos = { 20, 110 };
114 int len = 3;
115 SkTextBlobBuilder textBlobBuilder;
116 const SkTextBlobBuilder::RunBuffer& run =
117 textBlobBuilder.allocRun(font, len, textPos.fX, textPos.fY);
118 run.glyphs[0] = 10;
119 run.glyphs[1] = 20;
120 run.glyphs[2] = 30;
121 sk_sp<const SkTextBlob> blob = textBlobBuilder.make();
122 SkPaint paint;
123 SkScalar bounds[] = { 116, 134 };
124 int count = blob->getIntercepts(bounds, nullptr);
125 std::vector<SkScalar> intervals;
126 intervals.resize(count);
127 (void) paint.getTextBlobIntercepts(blob.get(), bounds, &intervals.front());
128 canvas->drawTextBlob(blob.get(), 0, 0, paint);
129 paint.setColor(0xFFFF7777);
130 SkScalar x = textPos.fX;
131 for (int i = 0; i < count; i+= 2) {
132 canvas->drawRect({x, bounds[0], intervals[i], bounds[1]}, paint);
133 x = intervals[i + 1];
134 }
135 canvas->drawRect({intervals[count - 1], bounds[0], 180, bounds[1]}, paint);
136 }
137##
Cary Clark05c1dcf2018-12-12 13:32:56 -0500138
139#Method ##
140
141#Subtopic Text_Intercepts ##
142
143# ------------------------------------------------------------------------------
144
145#Method static sk_sp<SkTextBlob> MakeFromText(const void* text, size_t byteLength, const SkFont& font,
146 SkTextEncoding encoding = kUTF8_SkTextEncoding)
147#In Constructors
148#Line # constructs Text_Blob with one run ##
149
150Creates Text_Blob with a single run. text meaning depends on Text_Encoding;
151by default, text is encoded as UTF-8.
152
153font contains attributes used to define the run text: #font_metrics#.
154
155#Param text character code points or Glyphs drawn ##
156#Param byteLength byte length of text array ##
157#Param font text size, typeface, text scale, and so on, used to draw ##
158#Param encoding one of: kUTF8_SkTextEncoding, kUTF16_SkTextEncoding,
159 kUTF32_SkTextEncoding, kGlyphID_SkTextEncoding
160##
161
162#Return Text_Blob constructed from one run ##
163
164#Example
165#Height 24
166 SkFont font;
167 font.setSize(24);
168 SkPaint canvasPaint;
169 canvasPaint.setColor(SK_ColorBLUE); // respected
170 canvasPaint.setTextSize(2); // ignored
171 sk_sp<SkTextBlob> blob = SkTextBlob::MakeFromText("Hello World", 11, font);
172 canvas->drawTextBlob(blob, 20, 20, canvasPaint);
173##
174
175#SeeAlso MakeFromString SkTextBlobBuilder
176
177##
178
179# ------------------------------------------------------------------------------
180
181#Method static sk_sp<SkTextBlob> MakeFromString(const char* string, const SkFont& font,
182 SkTextEncoding encoding = kUTF8_SkTextEncoding)
183#In Constructors
184#Line # constructs Text_Blob with one run ##
185
186Creates Text_Blob with a single run. string meaning depends on Text_Encoding;
187by default, string is encoded as UTF-8.
188
189font contains Font_Metrics used to define the run text: #font_metrics#.
190
191#Param string character code points or Glyphs drawn ##
192#Param font text size, typeface, text scale, and so on, used to draw ##
193#Param encoding one of: kUTF8_SkTextEncoding, kUTF16_SkTextEncoding,
194 kUTF32_SkTextEncoding, kGlyphID_SkTextEncoding
195##
196
197#Return Text_Blob constructed from one run ##
198
199#Example
200#Height 24
201 SkFont font;
202 font.setSize(24);
203 SkPaint canvasPaint;
204 canvasPaint.setColor(SK_ColorBLUE); // respected
205 canvasPaint.setTextSize(2); // ignored
206 sk_sp<SkTextBlob> blob = SkTextBlob::MakeFromString("Hello World", font);
207 canvas->drawTextBlob(blob, 20, 20, canvasPaint);
208##
209
210#SeeAlso MakeFromText SkTextBlobBuilder
211
212##
213
214# ------------------------------------------------------------------------------
215
216#Method size_t serialize(const SkSerialProcs& procs, void* memory, size_t memory_size) const
217#In Utility
218#Line # writes Text_Blob to memory ##
219#Populate
220
221#Example
222#Height 64
223###$
224$Function
225#include "SkSerialProcs.h"
226$$
227$$$#
228 SkFont blobFont;
229 blobFont.setSize(24);
230 sk_sp<SkTextBlob> blob = SkTextBlob::MakeFromText("Hello World", 11, blobFont);
231 char storage[2048];
232 size_t used = blob->serialize(SkSerialProcs(), storage, sizeof(storage));
233 sk_sp<SkTextBlob> copy = SkTextBlob::Deserialize(storage, used, SkDeserialProcs());
234 canvas->drawTextBlob(copy, 20, 20, SkPaint());
235 std::string usage = "size=" + std::to_string(sizeof(storage)) + " used=" + std::to_string(used);
236 canvas->drawString(usage.c_str(), 20, 40, SkPaint());
237##
238
239#SeeAlso Deserialize SkSerialProcs
240
241#Method ##
242
243# ------------------------------------------------------------------------------
244
245#Method sk_sp<SkData> serialize(const SkSerialProcs& procs) const
246#In Utility
247#Line # writes Text_Blob to Data ##
248#Populate
249
250#Example
251#Height 24
252###$
253$Function
254#include "SkSerialProcs.h"
255$$
256$$$#
257 SkFont blobFont;
258 blobFont.setSize(24);
259 sk_sp<SkTextBlob> blob = SkTextBlob::MakeFromText("Hello World", 11, blobFont);
260 sk_sp<SkData> data = blob->serialize(SkSerialProcs());
261 sk_sp<SkTextBlob> copy = SkTextBlob::Deserialize(data->data(), data->size(), SkDeserialProcs());
262 canvas->drawTextBlob(copy, 20, 20, SkPaint());
263##
264
265#SeeAlso Deserialize SkData SkSerialProcs
266
267#Method ##
268
269# ------------------------------------------------------------------------------
270
271#Method static sk_sp<SkTextBlob> Deserialize(const void* data, size_t size, const SkDeserialProcs& procs)
272#In Constructors
273#Line # constructs Text_Blob from memory ##
274#Populate
275
276#Example
277#Height 24
278#Description
279Text "Hacker" replaces "World!", but does not update its metrics.
280When drawn, "Hacker" uses the spacing computed for "World!".
281##
282###$
283$Function
284#include "SkSerialProcs.h"
285$$
286$$$#
287 SkFont blobFont;
288 blobFont.setSize(24);
289 sk_sp<SkTextBlob> blob = SkTextBlob::MakeFromText("Hello World!", 12, blobFont);
290 sk_sp<SkData> data = blob->serialize(SkSerialProcs());
291 uint16_t glyphs[6];
292 SkPaint blobPaint;
293 blobPaint.textToGlyphs("Hacker", 6, glyphs);
294 memcpy((char*)data->writable_data() + 0x54, glyphs, sizeof(glyphs));
295 sk_sp<SkTextBlob> copy = SkTextBlob::Deserialize(data->data(), data->size(), SkDeserialProcs());
296 canvas->drawTextBlob(copy, 20, 20, SkPaint());
297##
298
299#SeeAlso serialize SkDeserialProcs
300
301#Method ##
302
303#Class SkTextBlob ##
304
305#Topic Text_Blob ##