#Topic Text_Blob #Alias Text_Blob_Reference ## #Class SkTextBlob #Code #Populate ## SkTextBlob combines multiple text runs into an immutable container. Each text run consists of Glyphs, Paint, and position. Only parts of Paint related to fonts and text rendering are used by run. # ------------------------------------------------------------------------------ #Method const SkRect& bounds() const #In Property #Line # returns conservative bounding box ## #Populate #Example #Height 70 SkTextBlobBuilder textBlobBuilder; const char bunny[] = "/(^x^)\\"; const int len = sizeof(bunny) - 1; uint16_t glyphs[len]; SkFont font; font.textToGlyphs(bunny, len, SkTextEncoding::kUTF8, glyphs, sizeof(glyphs)); int runs[] = { 3, 1, 3 }; SkPoint textPos = { 20, 50 }; int glyphIndex = 0; for (auto runLen : runs) { font.setSize(1 == runLen ? 20 : 50); const SkTextBlobBuilder::RunBuffer& run = textBlobBuilder.allocRun(font, runLen, textPos.fX, textPos.fY); memcpy(run.glyphs, &glyphs[glyphIndex], sizeof(glyphs[0]) * runLen); textPos.fX += font.measureText(&glyphs[glyphIndex], sizeof(glyphs[0]) * runLen, SkTextEncoding::kGlyphID); glyphIndex += runLen; } sk_sp<const SkTextBlob> blob = textBlobBuilder.make(); SkPaint paint; canvas->drawTextBlob(blob.get(), 0, 0, paint); paint.setStyle(SkPaint::kStroke_Style); canvas->drawRect(blob->bounds(), paint); ## #SeeAlso SkPath::getBounds #Method ## # ------------------------------------------------------------------------------ #Method uint32_t uniqueID() const #In Property #Line # returns identifier for Text_Blob ## #Populate #Example for (int index = 0; index < 2; ++index) { SkTextBlobBuilder textBlobBuilder; const char bunny[] = "/(^x^)\\"; const int len = sizeof(bunny) - 1; uint16_t glyphs[len]; SkFont font; font.textToGlyphs(bunny, len, SkTextEncoding::kUTF8, glyphs, sizeof(glyphs)); font.setScaleX(0.5); int runs[] = { 3, 1, 3 }; SkPoint textPos = { 20, 50 }; int glyphIndex = 0; for (auto runLen : runs) { font.setSize(1 == runLen ? 20 : 50); const SkTextBlobBuilder::RunBuffer& run = textBlobBuilder.allocRun(font, runLen, textPos.fX, textPos.fY); memcpy(run.glyphs, &glyphs[glyphIndex], sizeof(glyphs[0]) * runLen); textPos.fX += font.measureText(&glyphs[glyphIndex], sizeof(glyphs[0]) * runLen, SkTextEncoding::kGlyphID); glyphIndex += runLen; } sk_sp<const SkTextBlob> blob = textBlobBuilder.make(); SkPaint paint; canvas->drawTextBlob(blob.get(), 0, 0, paint); std::string id = "unique ID:" + std::to_string(blob->uniqueID()); canvas->drawString(id.c_str(), 30, blob->bounds().fBottom + 15, paint); canvas->translate(blob->bounds().fRight + 10, 0); } ## #SeeAlso SkRefCnt #Method ## # ------------------------------------------------------------------------------ #Subtopic Text_Intercepts #Line # advanced underline, strike through ## Text_Intercepts describe the intersection of drawn text Glyphs with a pair of lines parallel to the text advance. Text_Intercepts permits creating a underline that skips Descenders. #Method int getIntercepts(const SkScalar bounds[2], SkScalar intervals[], const SkPaint* paint = nullptr) const; #In Text_Intercepts #Line # returns where lines intersect Text_Blob; underlines ## #Populate #Example #Height 143 void draw(SkCanvas* canvas) { SkFont font; font.setSize(120); SkPoint textPos = { 20, 110 }; int len = 3; SkTextBlobBuilder textBlobBuilder; const SkTextBlobBuilder::RunBuffer& run = textBlobBuilder.allocRun(font, len, textPos.fX, textPos.fY); run.glyphs[0] = 10; run.glyphs[1] = 20; run.glyphs[2] = 30; sk_sp<const SkTextBlob> blob = textBlobBuilder.make(); SkPaint paint; SkScalar bounds[] = { 116, 134 }; int count = blob->getIntercepts(bounds, nullptr); std::vector<SkScalar> intervals; intervals.resize(count); (void) paint.getTextBlobIntercepts(blob.get(), bounds, &intervals.front()); canvas->drawTextBlob(blob.get(), 0, 0, paint); paint.setColor(0xFFFF7777); SkScalar x = textPos.fX; for (int i = 0; i < count; i+= 2) { canvas->drawRect({x, bounds[0], intervals[i], bounds[1]}, paint); x = intervals[i + 1]; } canvas->drawRect({intervals[count - 1], bounds[0], 180, bounds[1]}, paint); } ## #Method ## #Subtopic Text_Intercepts ## # ------------------------------------------------------------------------------ #Method static sk_sp<SkTextBlob> MakeFromText(const void* text, size_t byteLength, const SkFont& font, SkTextEncoding encoding = kUTF8_SkTextEncoding) #In Constructors #Line # constructs Text_Blob with one run ## Creates Text_Blob with a single run. text meaning depends on Text_Encoding; by default, text is encoded as UTF-8. font contains attributes used to define the run text: #font_metrics#. #Param text character code points or Glyphs drawn ## #Param byteLength byte length of text array ## #Param font text size, typeface, text scale, and so on, used to draw ## #Param encoding one of: kUTF8_SkTextEncoding, kUTF16_SkTextEncoding, kUTF32_SkTextEncoding, kGlyphID_SkTextEncoding ## #Return Text_Blob constructed from one run ## #Example #Height 24 SkFont font; font.setSize(24); SkPaint canvasPaint; canvasPaint.setColor(SK_ColorBLUE); // respected canvasPaint.setTextSize(2); // ignored sk_sp<SkTextBlob> blob = SkTextBlob::MakeFromText("Hello World", 11, font); canvas->drawTextBlob(blob, 20, 20, canvasPaint); ## #SeeAlso MakeFromString SkTextBlobBuilder ## # ------------------------------------------------------------------------------ #Method static sk_sp<SkTextBlob> MakeFromString(const char* string, const SkFont& font, SkTextEncoding encoding = kUTF8_SkTextEncoding) #In Constructors #Line # constructs Text_Blob with one run ## Creates Text_Blob with a single run. string meaning depends on Text_Encoding; by default, string is encoded as UTF-8. font contains Font_Metrics used to define the run text: #font_metrics#. #Param string character code points or Glyphs drawn ## #Param font text size, typeface, text scale, and so on, used to draw ## #Param encoding one of: kUTF8_SkTextEncoding, kUTF16_SkTextEncoding, kUTF32_SkTextEncoding, kGlyphID_SkTextEncoding ## #Return Text_Blob constructed from one run ## #Example #Height 24 SkFont font; font.setSize(24); SkPaint canvasPaint; canvasPaint.setColor(SK_ColorBLUE); // respected canvasPaint.setTextSize(2); // ignored sk_sp<SkTextBlob> blob = SkTextBlob::MakeFromString("Hello World", font); canvas->drawTextBlob(blob, 20, 20, canvasPaint); ## #SeeAlso MakeFromText SkTextBlobBuilder ## # ------------------------------------------------------------------------------ #Method size_t serialize(const SkSerialProcs& procs, void* memory, size_t memory_size) const #In Utility #Line # writes Text_Blob to memory ## #Populate #Example #Height 64 ###$ $Function #include "SkSerialProcs.h" $$ $$$# SkFont blobFont; blobFont.setSize(24); sk_sp<SkTextBlob> blob = SkTextBlob::MakeFromText("Hello World", 11, blobFont); char storage[2048]; size_t used = blob->serialize(SkSerialProcs(), storage, sizeof(storage)); sk_sp<SkTextBlob> copy = SkTextBlob::Deserialize(storage, used, SkDeserialProcs()); canvas->drawTextBlob(copy, 20, 20, SkPaint()); std::string usage = "size=" + std::to_string(sizeof(storage)) + " used=" + std::to_string(used); canvas->drawString(usage.c_str(), 20, 40, SkPaint()); ## #SeeAlso Deserialize SkSerialProcs #Method ## # ------------------------------------------------------------------------------ #Method sk_sp<SkData> serialize(const SkSerialProcs& procs) const #In Utility #Line # writes Text_Blob to Data ## #Populate #Example #Height 24 ###$ $Function #include "SkSerialProcs.h" $$ $$$# SkFont blobFont; blobFont.setSize(24); sk_sp<SkTextBlob> blob = SkTextBlob::MakeFromText("Hello World", 11, blobFont); sk_sp<SkData> data = blob->serialize(SkSerialProcs()); sk_sp<SkTextBlob> copy = SkTextBlob::Deserialize(data->data(), data->size(), SkDeserialProcs()); canvas->drawTextBlob(copy, 20, 20, SkPaint()); ## #SeeAlso Deserialize SkData SkSerialProcs #Method ## # ------------------------------------------------------------------------------ #Method static sk_sp<SkTextBlob> Deserialize(const void* data, size_t size, const SkDeserialProcs& procs) #In Constructors #Line # constructs Text_Blob from memory ## #Populate #Example #Height 24 #Description Text "Hacker" replaces "World!", but does not update its metrics. When drawn, "Hacker" uses the spacing computed for "World!". ## ###$ $Function #include "SkSerialProcs.h" $$ $$$# SkFont blobFont; blobFont.setSize(24); sk_sp<SkTextBlob> blob = SkTextBlob::MakeFromText("Hello World!", 12, blobFont); sk_sp<SkData> data = blob->serialize(SkSerialProcs()); uint16_t glyphs[6]; SkPaint blobPaint; blobPaint.textToGlyphs("Hacker", 6, glyphs); memcpy((char*)data->writable_data() + 0x54, glyphs, sizeof(glyphs)); sk_sp<SkTextBlob> copy = SkTextBlob::Deserialize(data->data(), data->size(), SkDeserialProcs()); canvas->drawTextBlob(copy, 20, 20, SkPaint()); ## #SeeAlso serialize SkDeserialProcs #Method ## #Class SkTextBlob ## #Topic Text_Blob ##