DEF_TEST(TextBlob_extended, reporter) { SkTextBlobBuilder textBlobBuilder; SkFont font; const char text1[] = "Foo"; const char text2[] = "Bar"; int glyphCount = font.countText(text1, strlen(text1), SkTextEncoding::kUTF8); SkAutoTMalloc<uint16_t> glyphs(glyphCount); (void)font.textToGlyphs(text1, strlen(text1), SkTextEncoding::kUTF8, glyphs.get(), glyphCount); auto run = SkTextBlobBuilderPriv::AllocRunText(&textBlobBuilder, font, glyphCount, 0, 0, SkToInt(strlen(text2)), SkString(), nullptr); memcpy(run.glyphs, glyphs.get(), sizeof(uint16_t) * glyphCount); memcpy(run.utf8text, text2, strlen(text2)); for (int i = 0; i < glyphCount; ++i) { run.clusters[i] = SkTMin(SkToU32(i), SkToU32(strlen(text2))); } sk_sp<SkTextBlob> blob(textBlobBuilder.make()); REPORTER_ASSERT(reporter, blob); for (SkTextBlobRunIterator it(blob.get()); !it.done(); it.next()) { REPORTER_ASSERT(reporter, it.glyphCount() == (uint32_t)glyphCount); for (uint32_t i = 0; i < it.glyphCount(); ++i) { REPORTER_ASSERT(reporter, it.glyphs()[i] == glyphs[i]); } REPORTER_ASSERT(reporter, SkTextBlobRunIterator::kDefault_Positioning == it.positioning()); REPORTER_ASSERT(reporter, (SkPoint{0.0f, 0.0f}) == it.offset()); REPORTER_ASSERT(reporter, it.textSize() > 0); REPORTER_ASSERT(reporter, it.clusters()); for (uint32_t i = 0; i < it.glyphCount(); ++i) { REPORTER_ASSERT(reporter, i == it.clusters()[i]); } REPORTER_ASSERT(reporter, 0 == strncmp(text2, it.text(), it.textSize())); } }
static void add_run(SkTextBlobBuilder* builder, const char text[], SkScalar x, SkScalar y, sk_sp<SkTypeface> tf) { SkFont font; font.setEdging(SkFont::Edging::kAntiAlias); font.setSubpixel(true); font.setSize(16); font.setTypeface(tf); int glyphCount = font.countText(text, strlen(text), SkTextEncoding::kUTF8); SkTextBlobBuilder::RunBuffer buffer = builder->allocRun(font, glyphCount, x, y); (void)font.textToGlyphs(text, strlen(text), SkTextEncoding::kUTF8, buffer.glyphs, glyphCount); }
// This unit test verifies blob bounds computation. static void TestBounds(skiatest::Reporter* reporter) { SkTextBlobBuilder builder; SkFont font; // Explicit bounds. { sk_sp<SkTextBlob> blob(builder.make()); REPORTER_ASSERT(reporter, !blob); } { SkRect r1 = SkRect::MakeXYWH(10, 10, 20, 20); builder.allocRun(font, 16, 0, 0, &r1); sk_sp<SkTextBlob> blob(builder.make()); REPORTER_ASSERT(reporter, blob->bounds() == r1); } { SkRect r1 = SkRect::MakeXYWH(10, 10, 20, 20); builder.allocRunPosH(font, 16, 0, &r1); sk_sp<SkTextBlob> blob(builder.make()); REPORTER_ASSERT(reporter, blob->bounds() == r1); } { SkRect r1 = SkRect::MakeXYWH(10, 10, 20, 20); builder.allocRunPos(font, 16, &r1); sk_sp<SkTextBlob> blob(builder.make()); REPORTER_ASSERT(reporter, blob->bounds() == r1); } { SkRect r1 = SkRect::MakeXYWH(10, 10, 20, 20); SkRect r2 = SkRect::MakeXYWH(15, 20, 50, 50); SkRect r3 = SkRect::MakeXYWH(0, 5, 10, 5); builder.allocRun(font, 16, 0, 0, &r1); builder.allocRunPosH(font, 16, 0, &r2); builder.allocRunPos(font, 16, &r3); sk_sp<SkTextBlob> blob(builder.make()); REPORTER_ASSERT(reporter, blob->bounds() == SkRect::MakeXYWH(0, 5, 65, 65)); } { sk_sp<SkTextBlob> blob(builder.make()); REPORTER_ASSERT(reporter, !blob); } // Implicit bounds { // Exercise the empty bounds path, and ensure that RunRecord-aligned pos buffers // don't trigger asserts (http://crbug.com/542643). SkFont font; font.setSize(0); const char* txt = "BOOO"; const size_t txtLen = strlen(txt); const int glyphCount = font.countText(txt, txtLen, SkTextEncoding::kUTF8); const SkTextBlobBuilder::RunBuffer& buffer = builder.allocRunPos(font, glyphCount); font.textToGlyphs(txt, txtLen, SkTextEncoding::kUTF8, buffer.glyphs, glyphCount); memset(buffer.pos, 0, sizeof(SkScalar) * glyphCount * 2); sk_sp<SkTextBlob> blob(builder.make()); REPORTER_ASSERT(reporter, blob->bounds().isEmpty()); } }