1#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]; 27 SkFont font; 28 font.textToGlyphs(bunny, len, SkTextEncoding::kUTF8, glyphs, sizeof(glyphs)); 29 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); 34 const SkTextBlobBuilder::RunBuffer& run = 35 textBlobBuilder.allocRun(font, runLen, textPos.fX, textPos.fY); 36 memcpy(run.glyphs, &glyphs[glyphIndex], sizeof(glyphs[0]) * runLen); 37 textPos.fX += font.measureText(&glyphs[glyphIndex], sizeof(glyphs[0]) * runLen, 38 SkTextEncoding::kGlyphID); 39 glyphIndex += runLen; 40 } 41 sk_sp<const SkTextBlob> blob = textBlobBuilder.make(); 42 SkPaint paint; 43 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]; 65 SkFont font; 66 font.textToGlyphs(bunny, len, SkTextEncoding::kUTF8, glyphs, sizeof(glyphs)); 67 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); 73 const SkTextBlobBuilder::RunBuffer& run = 74 textBlobBuilder.allocRun(font, runLen, textPos.fX, textPos.fY); 75 memcpy(run.glyphs, &glyphs[glyphIndex], sizeof(glyphs[0]) * runLen); 76 textPos.fX += font.measureText(&glyphs[glyphIndex], sizeof(glyphs[0]) * runLen, 77 SkTextEncoding::kGlyphID); 78 glyphIndex += runLen; 79 } 80 sk_sp<const SkTextBlob> blob = textBlobBuilder.make(); 81 SkPaint paint; 82 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 102#Method int getIntercepts(const SkScalar bounds[2], SkScalar intervals[], 103 const SkPaint* paint = nullptr) const; 104#In Text_Intercepts 105#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## 138 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 ## 306