Cary Clark | d2ca79c | 2018-08-10 13:09:13 -0400 | [diff] [blame] | 1 | #Topic Text_Blob |
| 2 | #Alias Text_Blob_Reference ## |
| 3 | |
| 4 | #PhraseDef paint_font_metrics |
| 5 | Typeface, Paint_Text_Size, Paint_Text_Scale_X, |
| 6 | Paint_Text_Skew_X, Paint_Text_Align, Paint_Hinting, Anti_Alias, Paint_Fake_Bold, |
| 7 | Font_Embedded_Bitmaps, Full_Hinting_Spacing, LCD_Text, Linear_Text, |
| 8 | and Subpixel_Text |
| 9 | ## |
| 10 | |
| 11 | Text_Blob holds one or more runs of text. Each run associates a string of Glyphs |
| 12 | with a position and Paint. Each Paint contains attributes used |
| 13 | to define the run text: #paint_font_metrics#. |
| 14 | |
| 15 | Text_Blob runs of text use Glyph_ID encoding; each run Paint must set |
| 16 | Paint_Text_Encoding to SkPaint::kGlyphID_TextEncoding. |
| 17 | |
| 18 | Text_Blob is constructed with SkTextBlob::MakeFromText or Text_Blob_Builder. |
| 19 | Once created, Text_Blob can not be modified. |
| 20 | |
| 21 | #Subtopic Overview |
| 22 | #Populate |
| 23 | ## |
| 24 | |
| 25 | #Subtopic Constructor |
| 26 | #Populate |
| 27 | ## |
| 28 | |
| 29 | #Subtopic Member_Function |
| 30 | #Populate |
| 31 | ## |
| 32 | |
| 33 | # ------------------------------------------------------------------------------ |
| 34 | |
| 35 | #Class SkTextBlob |
| 36 | |
| 37 | SkTextBlob combines multiple text runs into an immutable container. Each text |
| 38 | run consists of Glyphs, Paint, and position. Only parts of Paint related to |
| 39 | fonts and text rendering are used by run. |
| 40 | |
| 41 | # ------------------------------------------------------------------------------ |
| 42 | |
| 43 | #Method const SkRect& bounds() const |
| 44 | #In Property |
| 45 | #Line # returns conservative bounding box ## |
| 46 | |
| 47 | Returns conservative bounding box. Uses Paint 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 | #Example |
| 54 | #Height 70 |
| 55 | SkTextBlobBuilder textBlobBuilder;
|
| 56 | const char bunny[] = "/(^x^)\\";
|
| 57 | const int len = sizeof(bunny) - 1;
|
| 58 | uint16_t glyphs[len];
|
| 59 | SkPaint paint;
|
| 60 | paint.textToGlyphs(bunny, len, glyphs);
|
| 61 | paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
|
| 62 | int runs[] = { 3, 1, 3 };
|
| 63 | SkPoint textPos = { 20, 50 };
|
| 64 | int glyphIndex = 0;
|
| 65 | for (auto runLen : runs) {
|
| 66 | paint.setTextSize(1 == runLen ? 20 : 50);
|
| 67 | const SkTextBlobBuilder::RunBuffer& run =
|
| 68 | textBlobBuilder.allocRun(paint, runLen, textPos.fX, textPos.fY);
|
| 69 | memcpy(run.glyphs, &glyphs[glyphIndex], sizeof(glyphs[0]) * runLen);
|
| 70 | textPos.fX += paint.measureText(&glyphs[glyphIndex], sizeof(glyphs[0]) * runLen, nullptr);
|
| 71 | glyphIndex += runLen;
|
| 72 | }
|
| 73 | sk_sp<const SkTextBlob> blob = textBlobBuilder.make();
|
| 74 | paint.reset();
|
| 75 | canvas->drawTextBlob(blob.get(), 0, 0, paint);
|
| 76 | paint.setStyle(SkPaint::kStroke_Style);
|
| 77 | canvas->drawRect(blob->bounds(), paint); |
| 78 | ## |
| 79 | |
| 80 | #SeeAlso SkPath::getBounds |
| 81 | |
| 82 | #Method ## |
| 83 | |
| 84 | # ------------------------------------------------------------------------------ |
| 85 | |
| 86 | #Method uint32_t uniqueID() const |
| 87 | #In Property |
| 88 | #Line # returns identifier for Text_Blob ## |
| 89 | |
| 90 | Returns a non-zero value unique among all text blobs. |
| 91 | |
| 92 | #Return identifier for Text_Blob ## |
| 93 | |
| 94 | #Example |
| 95 | for (int index = 0; index < 2; ++index) {
|
| 96 | SkTextBlobBuilder textBlobBuilder;
|
| 97 | const char bunny[] = "/(^x^)\\";
|
| 98 | const int len = sizeof(bunny) - 1;
|
| 99 | uint16_t glyphs[len];
|
| 100 | SkPaint paint;
|
| 101 | paint.textToGlyphs(bunny, len, glyphs);
|
| 102 | paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
|
| 103 | paint.setTextScaleX(0.5);
|
| 104 | int runs[] = { 3, 1, 3 };
|
| 105 | SkPoint textPos = { 20, 50 };
|
| 106 | int glyphIndex = 0;
|
| 107 | for (auto runLen : runs) {
|
| 108 | paint.setTextSize(1 == runLen ? 20 : 50);
|
| 109 | const SkTextBlobBuilder::RunBuffer& run =
|
| 110 | textBlobBuilder.allocRun(paint, runLen, textPos.fX, textPos.fY);
|
| 111 | memcpy(run.glyphs, &glyphs[glyphIndex], sizeof(glyphs[0]) * runLen);
|
| 112 | textPos.fX += paint.measureText(&glyphs[glyphIndex], sizeof(glyphs[0]) * runLen, nullptr);
|
| 113 | glyphIndex += runLen;
|
| 114 | }
|
| 115 | sk_sp<const SkTextBlob> blob = textBlobBuilder.make();
|
| 116 | paint.reset();
|
| 117 | canvas->drawTextBlob(blob.get(), 0, 0, paint);
|
| 118 | std::string id = "unique ID:" + std::to_string(blob->uniqueID());
|
| 119 | canvas->drawString(id.c_str(), 30, blob->bounds().fBottom + 15, paint);
|
| 120 | canvas->translate(blob->bounds().fRight + 10, 0);
|
| 121 | } |
| 122 | ## |
| 123 | |
| 124 | #SeeAlso SkRefCnt |
| 125 | |
| 126 | #Method ## |
| 127 | |
| 128 | # ------------------------------------------------------------------------------ |
| 129 | |
| 130 | #Method static sk_sp<SkTextBlob> MakeFromText( |
| 131 | const void* text, size_t byteLength, const SkPaint& paint) |
| 132 | #In Constructor |
| 133 | #Line # constructs Text_Blob with one run ## |
| 134 | |
| 135 | Creates Text_Blob with a single run. text meaning depends on Paint_Text_Encoding; |
| 136 | by default, text is encoded as UTF-8. |
| 137 | |
| 138 | paint contains attributes used to define the run text: #paint_font_metrics#. |
| 139 | |
| 140 | #Param text character code points or Glyphs drawn ## |
| 141 | #Param byteLength byte length of text array ## |
| 142 | #Param paint text size, typeface, text scale, and so on, used to draw ## |
| 143 | |
| 144 | #Return Text_Blob constructed from one run ## |
| 145 | |
| 146 | #Example |
| 147 | #Height 24 |
| 148 | SkPaint blobPaint; |
| 149 | blobPaint.setColor(SK_ColorRED); // ignored |
| 150 | blobPaint.setTextSize(24); // respected |
| 151 | blobPaint.setAntiAlias(true); // ignored |
| 152 | SkPaint canvasPaint = blobPaint; |
| 153 | canvasPaint.setColor(SK_ColorBLUE); // respected |
| 154 | canvasPaint.setTextSize(2); // ignored |
| 155 | sk_sp<SkTextBlob> blob = SkTextBlob::MakeFromText("Hello World", 11, blobPaint); |
| 156 | canvas->drawTextBlob(blob, 20, 20, canvasPaint); |
| 157 | ## |
| 158 | |
| 159 | #SeeAlso MakeFromString TextBlobBuilder |
| 160 | |
| 161 | ## |
| 162 | |
| 163 | # ------------------------------------------------------------------------------ |
| 164 | |
| 165 | #Method static sk_sp<SkTextBlob> MakeFromString(const char* string, const SkPaint& paint) |
| 166 | #In Constructor |
| 167 | #Line # constructs Text_Blob with one run ## |
| 168 | |
| 169 | Creates Text_Blob with a single run. string meaning depends on Paint_Text_Encoding; |
| 170 | by default, string is encoded as UTF-8. |
| 171 | |
| 172 | paint contains Paint_Font_Metrics used to define the run text: #paint_font_metrics#. |
| 173 | |
| 174 | #Param string character code points or Glyphs drawn ## |
| 175 | #Param paint text size, typeface, text scale, and so on, used to draw ## |
| 176 | |
| 177 | #Return Text_Blob constructed from one run ## |
| 178 | |
| 179 | #Example |
| 180 | #Height 24 |
| 181 | SkPaint blobPaint; |
| 182 | blobPaint.setColor(SK_ColorRED); // ignored |
| 183 | blobPaint.setTextSize(24); // respected |
| 184 | blobPaint.setAntiAlias(true); // ignored |
| 185 | SkPaint canvasPaint = blobPaint; |
| 186 | canvasPaint.setColor(SK_ColorBLUE); // respected |
| 187 | canvasPaint.setTextSize(2); // ignored |
| 188 | sk_sp<SkTextBlob> blob = SkTextBlob::MakeFromString("Hello World", blobPaint); |
| 189 | canvas->drawTextBlob(blob, 20, 20, canvasPaint); |
| 190 | ## |
| 191 | |
| 192 | #SeeAlso MakeFromText TextBlobBuilder |
| 193 | |
| 194 | ## |
| 195 | |
| 196 | # ------------------------------------------------------------------------------ |
| 197 | |
| 198 | #Method size_t serialize(const SkSerialProcs& procs, void* memory, size_t memory_size) const |
| 199 | #In Utility |
| 200 | #Line # writes Text_Blob to memory ## |
| 201 | |
| 202 | Writes data to allow later reconstruction of Text_Blob. memory points to storage |
| 203 | to receive the encoded data, and memory_size describes the size of storage. |
| 204 | Returns bytes used if provided storage is large enough to hold all data; |
| 205 | otherwise, returns zero. |
| 206 | |
| 207 | procs.fTypefaceProc permits supplying a custom function to encode Typeface. |
| 208 | If procs.fTypefaceProc is nullptr, default encoding is used. procs.fTypefaceCtx |
| 209 | may be used to provide user context to procs.fTypefaceProc; procs.fTypefaceProc |
| 210 | is called with a pointer to Typeface and user context. |
| 211 | |
| 212 | #Param procs custom serial data encoders; may be nullptr ## |
| 213 | #Param memory storage for data ## |
| 214 | #Param size size of storage ## |
| 215 | |
| 216 | #Return bytes written, or zero if required storage is larger than memory_size ## |
| 217 | |
| 218 | #Example |
| 219 | #Height 64 |
| 220 | ###$ |
| 221 | $Function |
| 222 | #include "SkSerialProcs.h" |
| 223 | $$ |
| 224 | $$$# |
| 225 | SkPaint blobPaint;
|
| 226 | blobPaint.setTextSize(24);
|
Cary Clark | 57ca297 | 2018-08-10 15:49:01 -0400 | [diff] [blame] | 227 | sk_sp<SkTextBlob> blob = SkTextBlob::MakeFromText("Hello World", 11, blobPaint);
|
Cary Clark | d2ca79c | 2018-08-10 13:09:13 -0400 | [diff] [blame] | 228 | char storage[2048];
|
| 229 | size_t used = blob->serialize(SkSerialProcs(), storage, sizeof(storage));
|
| 230 | sk_sp<SkTextBlob> copy = SkTextBlob::Deserialize(storage, used, SkDeserialProcs());
|
| 231 | canvas->drawTextBlob(copy, 20, 20, SkPaint());
|
| 232 | std::string usage = "size=" + std::to_string(sizeof(storage)) + " used=" + std::to_string(used);
|
| 233 | canvas->drawString(usage.c_str(), 20, 40, SkPaint()); |
| 234 | ## |
| 235 | |
| 236 | #SeeAlso Deserialize SkSerialProcs |
| 237 | |
| 238 | #Method ## |
| 239 | |
| 240 | # ------------------------------------------------------------------------------ |
| 241 | |
| 242 | #Method sk_sp<SkData> serialize(const SkSerialProcs& procs) const |
| 243 | #In Utility |
| 244 | #Line # writes Text_Blob to Data ## |
| 245 | Returns storage containing Data describing Text_Blob, using optional custom |
| 246 | encoders. |
| 247 | |
| 248 | procs.fTypefaceProc permits supplying a custom function to encode Typeface. |
| 249 | If procs.fTypefaceProc is nullptr, default encoding is used. procs.fTypefaceCtx |
| 250 | may be used to provide user context to procs.fTypefaceProc; procs.fTypefaceProc |
| 251 | is called with a pointer to Typeface and user context. |
| 252 | |
| 253 | #Param procs custom serial data encoders; may be nullptr ## |
| 254 | |
| 255 | #Return storage containing serialized Text_Blob ## |
| 256 | |
| 257 | #Example |
| 258 | #Height 24 |
| 259 | ###$ |
| 260 | $Function |
| 261 | #include "SkSerialProcs.h" |
| 262 | $$ |
| 263 | $$$# |
| 264 | SkPaint blobPaint;
|
| 265 | blobPaint.setTextSize(24);
|
Cary Clark | 57ca297 | 2018-08-10 15:49:01 -0400 | [diff] [blame] | 266 | sk_sp<SkTextBlob> blob = SkTextBlob::MakeFromText("Hello World", 11, blobPaint);
|
Cary Clark | d2ca79c | 2018-08-10 13:09:13 -0400 | [diff] [blame] | 267 | sk_sp<SkData> data = blob->serialize(SkSerialProcs());
|
| 268 | sk_sp<SkTextBlob> copy = SkTextBlob::Deserialize(data->data(), data->size(), SkDeserialProcs());
|
| 269 | canvas->drawTextBlob(copy, 20, 20, SkPaint()); |
| 270 | ## |
| 271 | |
| 272 | #SeeAlso Deserialize SkData SkSerialProcs |
| 273 | |
| 274 | #Method ## |
| 275 | |
| 276 | # ------------------------------------------------------------------------------ |
| 277 | |
| 278 | #Method static sk_sp<SkTextBlob> Deserialize(const void* data, size_t size, const SkDeserialProcs& procs) |
| 279 | #In Constructor |
| 280 | #Line # constructs Text_Blob from memory ## |
| 281 | |
| 282 | Recreates Text_Blob that was serialized into data. Returns constructed Text_Blob |
| 283 | if successful; otherwise, returns nullptr. Fails if size is smaller than |
| 284 | required data length, or if data does not permit constructing valid Text_Blob. |
| 285 | |
| 286 | procs.fTypefaceProc permits supplying a custom function to decode Typeface. |
| 287 | If procs.fTypefaceProc is nullptr, default decoding is used. procs.fTypefaceCtx |
| 288 | may be used to provide user context to procs.fTypefaceProc; procs.fTypefaceProc |
| 289 | is called with a pointer to Typeface data, data byte length, and user context. |
| 290 | |
| 291 | #Param data pointer for serial data ## |
| 292 | #Param size size of data ## |
| 293 | #Param procs custom serial data decoders; may be nullptr ## |
| 294 | |
| 295 | #Return Text_Blob constructed from data in memory ## |
| 296 | |
| 297 | #Example |
| 298 | #Height 24 |
| 299 | #Description |
| 300 | Text "Hacker" replaces "World!", but does not update its metrics. |
| 301 | When drawn, "Hacker" uses the spacing computed for "World!". |
| 302 | ## |
| 303 | ###$ |
| 304 | $Function |
| 305 | #include "SkSerialProcs.h" |
| 306 | $$ |
| 307 | $$$# |
| 308 | SkPaint blobPaint;
|
| 309 | blobPaint.setTextSize(24);
|
Cary Clark | 57ca297 | 2018-08-10 15:49:01 -0400 | [diff] [blame] | 310 | sk_sp<SkTextBlob> blob = SkTextBlob::MakeFromText("Hello World!", 12, blobPaint);
|
Cary Clark | d2ca79c | 2018-08-10 13:09:13 -0400 | [diff] [blame] | 311 | sk_sp<SkData> data = blob->serialize(SkSerialProcs());
|
| 312 | uint16_t glyphs[6];
|
| 313 | blobPaint.textToGlyphs("Hacker", 6, glyphs);
|
| 314 | memcpy((char*)data->writable_data() + 0x54, glyphs, sizeof(glyphs));
|
| 315 | sk_sp<SkTextBlob> copy = SkTextBlob::Deserialize(data->data(), data->size(), SkDeserialProcs());
|
| 316 | canvas->drawTextBlob(copy, 20, 20, SkPaint()); |
| 317 | ## |
| 318 | |
| 319 | #SeeAlso serialize SkDeserialProcs |
| 320 | |
| 321 | #Method ## |
| 322 | |
| 323 | #Class SkTextBlob ## |
| 324 | |
| 325 | #Topic Text_Blob ## |