Flutter Engine
The Flutter Engine
Classes | Functions
TextBlobTest.cpp File Reference
#include "include/core/SkCanvas.h"
#include "include/core/SkColor.h"
#include "include/core/SkData.h"
#include "include/core/SkFont.h"
#include "include/core/SkFontStyle.h"
#include "include/core/SkFontTypes.h"
#include "include/core/SkImage.h"
#include "include/core/SkImageInfo.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPoint.h"
#include "include/core/SkRect.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkScalar.h"
#include "include/core/SkSerialProcs.h"
#include "include/core/SkSurface.h"
#include "include/core/SkTextBlob.h"
#include "include/core/SkTypeface.h"
#include "include/core/SkTypes.h"
#include "include/private/base/SkTArray.h"
#include "include/private/base/SkTemplates.h"
#include "include/private/base/SkTo.h"
#include "src/core/SkFontPriv.h"
#include "src/core/SkTextBlobPriv.h"
#include "tests/Test.h"
#include "tools/ToolUtils.h"
#include "tools/fonts/FontToolUtils.h"
#include <algorithm>
#include <cstdint>
#include <cstring>
#include <string>

Go to the source code of this file.

Classes

class  TextBlobTester
 

Functions

 DEF_TEST (TextBlob_builder, reporter)
 
 DEF_TEST (TextBlob_paint, reporter)
 
 DEF_TEST (TextBlob_extended, reporter)
 
static void add_run (SkTextBlobBuilder *builder, const char text[], SkScalar x, SkScalar y, sk_sp< SkTypeface > tf)
 
static sk_sp< SkImagerender (const SkTextBlob *blob)
 
static sk_sp< SkDataSerializeTypeface (SkTypeface *tf, void *ctx)
 
static sk_sp< SkTypefaceDeserializeTypeface (const void *data, size_t length, void *ctx)
 
 DEF_TEST (TextBlob_serialize, reporter)
 
 DEF_TEST (TextBlob_MakeAsDrawText, reporter)
 
 DEF_TEST (TextBlob_iter, reporter)
 
 DEF_TEST (TextBlob_getIntercepts, reporter)
 

Function Documentation

◆ add_run()

static void add_run ( SkTextBlobBuilder builder,
const char  text[],
SkScalar  x,
SkScalar  y,
sk_sp< SkTypeface tf 
)
static

Definition at line 370 of file TextBlobTest.cpp.

371 {
372 SkFont font;
374 font.setSubpixel(true);
375 font.setSize(16);
376 font.setTypeface(tf);
377
378 int glyphCount = font.countText(text, strlen(text), SkTextEncoding::kUTF8);
379
380 SkTextBlobBuilder::RunBuffer buffer = builder->allocRun(font, glyphCount, x, y);
381
382 (void)font.textToGlyphs(text, strlen(text), SkTextEncoding::kUTF8, buffer.glyphs, glyphCount);
383}
@ kUTF8
uses bytes to represent UTF-8 or ASCII
Definition: SkFont.h:35
@ kAntiAlias
may have transparent pixels on glyph edges
std::u16string text
double y
double x
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not defaults to or::depending on whether ipv6 is specified vm service A custom Dart VM Service port The default is to pick a randomly available open port disable vm Disable the Dart VM Service The Dart VM Service is never available in release mode disable vm service Disable mDNS Dart VM Service publication Bind to the IPv6 localhost address for the Dart VM Service Ignored if vm service host is set endless trace buffer
Definition: switches.h:126
font
Font Metadata and Metrics.

◆ DEF_TEST() [1/7]

DEF_TEST ( TextBlob_builder  ,
reporter   
)

Definition at line 325 of file TextBlobTest.cpp.

325 {
328}
reporter
Definition: FontMgrTest.cpp:39
static void TestBounds(skiatest::Reporter *reporter)
static void TestBuilder(skiatest::Reporter *reporter)

◆ DEF_TEST() [2/7]

DEF_TEST ( TextBlob_extended  ,
reporter   
)

Definition at line 334 of file TextBlobTest.cpp.

334 {
335 SkTextBlobBuilder textBlobBuilder;
337 const char text1[] = "Foo";
338 const char text2[] = "Bar";
339
340 int glyphCount = font.countText(text1, strlen(text1), SkTextEncoding::kUTF8);
341 AutoTMalloc<uint16_t> glyphs(glyphCount);
342 (void)font.textToGlyphs(text1, strlen(text1), SkTextEncoding::kUTF8, glyphs.get(), glyphCount);
343
344 auto run = textBlobBuilder.allocRunText(font, glyphCount, 0, 0, SkToInt(strlen(text2)));
345 memcpy(run.glyphs, glyphs.get(), sizeof(uint16_t) * glyphCount);
346 memcpy(run.utf8text, text2, strlen(text2));
347 for (int i = 0; i < glyphCount; ++i) {
348 run.clusters[i] = std::min(SkToU32(i), SkToU32(strlen(text2)));
349 }
350 sk_sp<SkTextBlob> blob(textBlobBuilder.make());
352
353 for (SkTextBlobRunIterator it(blob.get()); !it.done(); it.next()) {
354 REPORTER_ASSERT(reporter, it.glyphCount() == (uint32_t)glyphCount);
355 for (uint32_t i = 0; i < it.glyphCount(); ++i) {
356 REPORTER_ASSERT(reporter, it.glyphs()[i] == glyphs[i]);
357 }
359 REPORTER_ASSERT(reporter, (SkPoint{0.0f, 0.0f}) == it.offset());
360 REPORTER_ASSERT(reporter, it.textSize() > 0);
361 REPORTER_ASSERT(reporter, it.clusters());
362 for (uint32_t i = 0; i < it.glyphCount(); ++i) {
363 REPORTER_ASSERT(reporter, i == it.clusters()[i]);
364 }
365 REPORTER_ASSERT(reporter, 0 == strncmp(text2, it.text(), it.textSize()));
366 }
367}
uint16_t glyphs[5]
Definition: FontMgrTest.cpp:46
constexpr int SkToInt(S x)
Definition: SkTo.h:29
constexpr uint32_t SkToU32(S x)
Definition: SkTo.h:26
#define REPORTER_ASSERT(r, cond,...)
Definition: Test.h:286
const RunBuffer & allocRunText(const SkFont &font, int count, SkScalar x, SkScalar y, int textByteCount, const SkRect *bounds=nullptr)
Definition: SkTextBlob.cpp:565
sk_sp< SkTextBlob > make()
Definition: SkTextBlob.cpp:617
static float min(float r, float g, float b)
Definition: hsl.cpp:48
SkFont DefaultFont()
Definition: run.py:1

◆ DEF_TEST() [3/7]

DEF_TEST ( TextBlob_getIntercepts  ,
reporter   
)

Definition at line 513 of file TextBlobTest.cpp.

513 {
515 font.setSize(16);
516
517 SkPoint lowPos[1] = { SkPoint::Make(0, 5) };
518 SkPoint highPos[1] = { SkPoint::Make(0, -8) };
519 SkPoint zeroPos[1] = { SkPoint::Make(0, 0) };
520
521 // 'x' sitting on baseline
522 auto blobZeroX = SkTextBlob::MakeFromPosText("x", 1, zeroPos, font);
523 // 'x' lowered to intersect baseline
524 auto blobLowX = SkTextBlob::MakeFromPosText("x", 1, lowPos, font);
525 // 'y' sitting on baseline
526 auto blobZeroY = SkTextBlob::MakeFromPosText("y", 1, zeroPos, font);
527 // 'y' raised to not intersect baseline
528 auto blobHighY = SkTextBlob::MakeFromPosText("y", 1, highPos, font);
529
530 // bounds right below baseline
531 SkScalar bounds[2] = { 1, 2 };
532
533 // 'x' on baseline should not intersect
534 REPORTER_ASSERT(reporter, blobZeroX->getIntercepts(bounds, nullptr) == 0);
535 // lowered 'x' should intersect
536 REPORTER_ASSERT(reporter, blobLowX->getIntercepts(bounds, nullptr) == 2);
537 // 'y' on baseline should intersect
538 REPORTER_ASSERT(reporter, blobZeroY->getIntercepts(bounds, nullptr) == 2);
539 // raised 'y' should not intersect
540 REPORTER_ASSERT(reporter, blobHighY->getIntercepts(bounds, nullptr) == 0);
541}
static sk_sp< SkTextBlob > MakeFromPosText(const void *text, size_t byteLength, const SkPoint pos[], const SkFont &font, SkTextEncoding encoding=SkTextEncoding::kUTF8)
Definition: SkTextBlob.cpp:803
float SkScalar
Definition: extension.cpp:12
Optional< SkRect > bounds
Definition: SkRecords.h:189
static constexpr SkPoint Make(float x, float y)
Definition: SkPoint_impl.h:173

◆ DEF_TEST() [4/7]

DEF_TEST ( TextBlob_iter  ,
reporter   
)

Definition at line 481 of file TextBlobTest.cpp.

481 {
483
485 add_run(&builder, "Hello", 10, 20, tf);
486 add_run(&builder, "World!", 10, 40, tf);
487 auto blob = builder.make();
488
489 SkTextBlob::Iter::Run expected[] = {
490 { tf.get(), 5, nullptr },
491 { tf.get(), 6, nullptr },
492 };
493
494 SkTextBlob::Iter iter(*blob);
496 for (auto exp : expected) {
497 REPORTER_ASSERT(reporter, iter.next(&run));
498 REPORTER_ASSERT(reporter, run.fTypeface == exp.fTypeface);
499 REPORTER_ASSERT(reporter, run.fGlyphCount == exp.fGlyphCount);
500 for (int i = 0; i < run.fGlyphCount; ++i) {
501 REPORTER_ASSERT(reporter, run.fGlyphIndices[i] != 0,
502 "Glyph Index %d is unexpectedly 0", i);
503 }
504 }
505 REPORTER_ASSERT(reporter, !iter.next(&run)); // we're done
506
507 SkTextBlob::Iter iter2(*blob);
508 REPORTER_ASSERT(reporter, iter2.next(&run));
509 // Hello should have the same glyph repeated for the 'l'
510 REPORTER_ASSERT(reporter, run.fGlyphIndices[2] == run.fGlyphIndices[3]);
511}
static void add_run(SkTextBlobBuilder *builder, const char text[], SkScalar x, SkScalar y, sk_sp< SkTypeface > tf)
static constexpr SkFontStyle BoldItalic()
Definition: SkFontStyle.h:75
T * get() const
Definition: SkRefCnt.h:303
sk_sp< SkTypeface > CreateTestTypeface(const char *name, SkFontStyle style)
def run(cmd)
Definition: run.py:14

◆ DEF_TEST() [5/7]

DEF_TEST ( TextBlob_MakeAsDrawText  ,
reporter   
)

Definition at line 467 of file TextBlobTest.cpp.

467 {
468 const char text[] = "Hello";
470
471 int runs = 0;
472 for(SkTextBlobRunIterator it(blob.get()); !it.done(); it.next()) {
473 REPORTER_ASSERT(reporter, it.glyphCount() == strlen(text));
475 runs += 1;
476 }
477 REPORTER_ASSERT(reporter, runs == 1);
478
479}
static sk_sp< SkTextBlob > MakeFromString(const char *string, const SkFont &font, SkTextEncoding encoding=SkTextEncoding::kUTF8)
Definition: SkTextBlob.h:115

◆ DEF_TEST() [6/7]

DEF_TEST ( TextBlob_paint  ,
reporter   
)

Definition at line 330 of file TextBlobTest.cpp.

330 {
332}
static void TestPaintProps(skiatest::Reporter *reporter)

◆ DEF_TEST() [7/7]

DEF_TEST ( TextBlob_serialize  ,
reporter   
)

Definition at line 434 of file TextBlobTest.cpp.

434 {
435 sk_sp<SkTextBlob> blob0 = [reporter]() {
437 REPORTER_ASSERT(reporter, tf, "Test typeface was nullptr");
438 REPORTER_ASSERT(reporter, tf->countGlyphs() > 0, "Test typeface had no glyphs");
439
441 add_run(&builder, "Hello", 10, 20, nullptr); // don't flatten a typeface
442 add_run(&builder, "World", 10, 40, tf); // do flatten this typeface
443 return builder.make();
444 }();
445
447 SkSerialProcs serializeProcs;
448 serializeProcs.fTypefaceProc = &SerializeTypeface;
449 serializeProcs.fTypefaceCtx = (void*) &array;
450 sk_sp<SkData> data = blob0->serialize(serializeProcs);
451 REPORTER_ASSERT(reporter, array.size() == 1,
452 "Did not serialize exactly one non-empty font, instead %d", array.size());
453 REPORTER_ASSERT(reporter, array[0]->countGlyphs() > 0, "Serialized typeface had no glyphs");
454 SkDeserialProcs deserializeProcs;
455 deserializeProcs.fTypefaceProc = &DeserializeTypeface;
456 deserializeProcs.fTypefaceCtx = (void*) &array;
457 sk_sp<SkTextBlob> blob1 = SkTextBlob::Deserialize(data->data(), data->size(), deserializeProcs);
459
460 sk_sp<SkImage> img0 = render(blob0.get());
461 sk_sp<SkImage> img1 = render(blob1.get());
462 if (img0 && img1) {
464 }
465}
static sk_sp< SkTypeface > DeserializeTypeface(const void *data, size_t length, void *ctx)
static sk_sp< SkImage > render(const SkTextBlob *blob)
static sk_sp< SkData > SerializeTypeface(SkTypeface *tf, void *ctx)
static sk_sp< SkTextBlob > Deserialize(const void *data, size_t size, const SkDeserialProcs &procs)
Definition: SkTextBlob.cpp:855
size_t serialize(const SkSerialProcs &procs, void *memory, size_t memory_size) const
Definition: SkTextBlob.cpp:864
int countGlyphs() const
Definition: SkTypeface.cpp:432
int size() const
Definition: SkTArray.h:421
bool equal_pixels(const SkPixmap &a, const SkPixmap &b)
Definition: ToolUtils.cpp:456
SkDeserialTypefaceProc fTypefaceProc
void * fTypefaceCtx
Definition: SkSerialProcs.h:94
SkSerialTypefaceProc fTypefaceProc
Definition: SkSerialProcs.h:93
std::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:63

◆ DeserializeTypeface()

static sk_sp< SkTypeface > DeserializeTypeface ( const void *  data,
size_t  length,
void *  ctx 
)
static

Definition at line 410 of file TextBlobTest.cpp.

410 {
411 auto array = (TArray<sk_sp<SkTypeface>>*)ctx;
412 if (length != sizeof(size_t)) {
413 SkDEBUGFAIL("Did not serialize an index");
414 return nullptr;
415 }
416 if (!data) {
417 return nullptr;
418 }
419 size_t idx = 0;
420 std::memcpy(&idx, data, sizeof(size_t));
421 if (idx >= SkToSizeT(array->size())) {
422 SkDEBUGFAIL("Index too big");
423 return nullptr;
424 }
425 return (*array)[idx];
426}
#define SkDEBUGFAIL(message)
Definition: SkAssert.h:118
constexpr size_t SkToSizeT(S x)
Definition: SkTo.h:31
size_t length

◆ render()

static sk_sp< SkImage > render ( const SkTextBlob blob)
static

Definition at line 385 of file TextBlobTest.cpp.

385 {
386 SkASSERT(blob);
387 auto surf = SkSurfaces::Raster(
389 SkScalarRoundToInt(blob->bounds().height())));
390 if (!surf) {
391 return nullptr; // bounds are empty?
392 }
393 surf->getCanvas()->clear(SK_ColorWHITE);
394 surf->getCanvas()->drawTextBlob(blob, -blob->bounds().left(), -blob->bounds().top(), SkPaint());
395 return surf->makeImageSnapshot();
396}
#define SkASSERT(cond)
Definition: SkAssert.h:116
constexpr SkColor SK_ColorWHITE
Definition: SkColor.h:122
#define SkScalarRoundToInt(x)
Definition: SkScalar.h:37
const SkRect & bounds() const
Definition: SkTextBlob.h:53
SK_API sk_sp< SkSurface > Raster(const SkImageInfo &imageInfo, size_t rowBytes, const SkSurfaceProps *surfaceProps)
static SkImageInfo MakeN32Premul(int width, int height)
constexpr float left() const
Definition: SkRect.h:734
constexpr float top() const
Definition: SkRect.h:741
constexpr float height() const
Definition: SkRect.h:769
constexpr float width() const
Definition: SkRect.h:762

◆ SerializeTypeface()

static sk_sp< SkData > SerializeTypeface ( SkTypeface tf,
void *  ctx 
)
static

Definition at line 398 of file TextBlobTest.cpp.

398 {
399 // Do not serialize the empty font.
400 if (!tf || (tf->countGlyphs() == 0 && tf->getBounds().isEmpty())) {
401 return nullptr;
402 }
403 auto array = (TArray<sk_sp<SkTypeface>>*)ctx;
404 const size_t idx = array->size();
405 array->emplace_back(sk_ref_sp(tf));
406 // In this test, we are deserializing on the same machine, so we don't worry about endianness.
407 return SkData::MakeWithCopy(&idx, sizeof(idx));
408}
sk_sp< T > sk_ref_sp(T *obj)
Definition: SkRefCnt.h:381
static sk_sp< SkData > MakeWithCopy(const void *data, size_t length)
Definition: SkData.cpp:111
SkRect getBounds() const
Definition: SkTypeface.cpp:507
bool isEmpty() const
Definition: SkRect.h:693