Flutter Engine
The Flutter Engine
TextBlobTest.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2014 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
10#include "include/core/SkData.h"
11#include "include/core/SkFont.h"
18#include "include/core/SkRect.h"
29#include "src/core/SkFontPriv.h"
31#include "tests/Test.h"
32#include "tools/ToolUtils.h"
34
35#include <algorithm>
36#include <cstdint>
37#include <cstring>
38#include <string>
39
40using namespace skia_private;
41
43public:
44 // This unit test feeds an SkTextBlobBuilder various runs then checks to see if
45 // the result contains the provided data and merges runs when appropriate.
48
49 // empty run set
50 RunBuilderTest(reporter, builder, nullptr, 0, nullptr, 0);
51
52 RunDef set1[] = {
54 };
55 RunBuilderTest(reporter, builder, set1, std::size(set1), set1, std::size(set1));
56
57 RunDef set2[] = {
59 };
60 RunBuilderTest(reporter, builder, set2, std::size(set2), set2, std::size(set2));
61
62 RunDef set3[] = {
64 };
65 RunBuilderTest(reporter, builder, set3, std::size(set3), set3, std::size(set3));
66
67 RunDef set4[] = {
71 };
72 RunBuilderTest(reporter, builder, set4, std::size(set4), set4, std::size(set4));
73
74 RunDef set5[] = {
78 };
79 RunDef mergedSet5[] = {
82 };
83 RunBuilderTest(reporter, builder, set5, std::size(set5), mergedSet5,
84 std::size(mergedSet5));
85
86 RunDef set6[] = {
90 };
91 RunDef mergedSet6[] = {
93 };
94 RunBuilderTest(reporter, builder, set6, std::size(set6), mergedSet6,
95 std::size(mergedSet6));
96
97 RunDef set7[] = {
110 };
111 RunDef mergedSet7[] = {
121 };
122 RunBuilderTest(reporter, builder, set7, std::size(set7), mergedSet7,
123 std::size(mergedSet7));
124 }
125
126 // This unit test verifies blob bounds computation.
130
131 // Explicit bounds.
132 {
133 sk_sp<SkTextBlob> blob(builder.make());
135 }
136
137 {
138 SkRect r1 = SkRect::MakeXYWH(10, 10, 20, 20);
139 builder.allocRun(font, 16, 0, 0, &r1);
140 sk_sp<SkTextBlob> blob(builder.make());
141 REPORTER_ASSERT(reporter, blob->bounds() == r1);
142 }
143
144 {
145 SkRect r1 = SkRect::MakeXYWH(10, 10, 20, 20);
146 builder.allocRunPosH(font, 16, 0, &r1);
147 sk_sp<SkTextBlob> blob(builder.make());
148 REPORTER_ASSERT(reporter, blob->bounds() == r1);
149 }
150
151 {
152 SkRect r1 = SkRect::MakeXYWH(10, 10, 20, 20);
153 builder.allocRunPos(font, 16, &r1);
154 sk_sp<SkTextBlob> blob(builder.make());
155 REPORTER_ASSERT(reporter, blob->bounds() == r1);
156 }
157
158 {
159 SkRect r1 = SkRect::MakeXYWH(10, 10, 20, 20);
160 SkRect r2 = SkRect::MakeXYWH(15, 20, 50, 50);
161 SkRect r3 = SkRect::MakeXYWH(0, 5, 10, 5);
162
163 builder.allocRun(font, 16, 0, 0, &r1);
164 builder.allocRunPosH(font, 16, 0, &r2);
165 builder.allocRunPos(font, 16, &r3);
166
167 sk_sp<SkTextBlob> blob(builder.make());
168 REPORTER_ASSERT(reporter, blob->bounds() == SkRect::MakeXYWH(0, 5, 65, 65));
169 }
170
171 {
172 sk_sp<SkTextBlob> blob(builder.make());
174 }
175
176 // Implicit bounds
177
178 {
179 // Exercise the empty bounds path, and ensure that RunRecord-aligned pos buffers
180 // don't trigger asserts (http://crbug.com/542643).
181 font.setSize(0);
182
183 const char* txt = "BOOO";
184 const size_t txtLen = strlen(txt);
185 const int glyphCount = font.countText(txt, txtLen, SkTextEncoding::kUTF8);
186 const SkTextBlobBuilder::RunBuffer& buffer = builder.allocRunPos(font, glyphCount);
187
188 font.textToGlyphs(txt, txtLen, SkTextEncoding::kUTF8, buffer.glyphs, glyphCount);
189
190 memset(buffer.pos, 0, sizeof(SkScalar) * glyphCount * 2);
191 sk_sp<SkTextBlob> blob(builder.make());
193 }
194 }
195
196 // Verify that text-related properties are captured in run paints.
198 SkFont font;
199 // Kitchen sink font.
200 font.setSize(42);
201 font.setScaleX(4.2f);
203 font.setSkewX(0.42f);
204 font.setHinting(SkFontHinting::kFull);
206 font.setEmbolden(true);
207 font.setLinearMetrics(true);
208 font.setSubpixel(true);
209 font.setEmbeddedBitmaps(true);
210 font.setForceAutoHinting(true);
211
212 // Ensure we didn't pick default values by mistake.
213 SkFont defaultFont = ToolUtils::DefaultFont();
214 REPORTER_ASSERT(reporter, defaultFont.getSize() != font.getSize());
215 REPORTER_ASSERT(reporter, defaultFont.getScaleX() != font.getScaleX());
216 REPORTER_ASSERT(reporter, defaultFont.getTypeface() != font.getTypeface());
217 REPORTER_ASSERT(reporter, defaultFont.getSkewX() != font.getSkewX());
218 REPORTER_ASSERT(reporter, defaultFont.getHinting() != font.getHinting());
219 REPORTER_ASSERT(reporter, defaultFont.getEdging() != font.getEdging());
220 REPORTER_ASSERT(reporter, defaultFont.isEmbolden() != font.isEmbolden());
221 REPORTER_ASSERT(reporter, defaultFont.isLinearMetrics() != font.isLinearMetrics());
222 REPORTER_ASSERT(reporter, defaultFont.isSubpixel() != font.isSubpixel());
224 defaultFont.isEmbeddedBitmaps() != font.isEmbeddedBitmaps());
225 REPORTER_ASSERT(reporter, defaultFont.isForceAutoHinting() != font.isForceAutoHinting());
226
230 builder);
232 sk_sp<SkTextBlob> blob(builder.make());
233
234 SkTextBlobRunIterator it(blob.get());
235 while (!it.done()) {
237 it.next();
238 }
239
240 }
241
242private:
243 struct RunDef {
244 unsigned count;
246 SkScalar x, y;
247 };
248
249 static void RunBuilderTest(skiatest::Reporter* reporter, SkTextBlobBuilder& builder,
250 const RunDef in[], unsigned inCount,
251 const RunDef out[], unsigned outCount) {
253
254 for (unsigned i = 0; i < inCount; ++i) {
255 AddRun(font, in[i].count, in[i].pos, SkPoint::Make(in[i].x, in[i].y), builder);
256 }
257
258 sk_sp<SkTextBlob> blob(builder.make());
259 REPORTER_ASSERT(reporter, (inCount > 0) == SkToBool(blob));
260 if (!blob) {
261 return;
262 }
263
264 SkTextBlobRunIterator it(blob.get());
265 for (unsigned i = 0; i < outCount; ++i) {
266 REPORTER_ASSERT(reporter, !it.done());
267 REPORTER_ASSERT(reporter, out[i].pos == it.positioning());
268 REPORTER_ASSERT(reporter, out[i].count == it.glyphCount());
270 REPORTER_ASSERT(reporter, out[i].x == it.offset().x());
271 REPORTER_ASSERT(reporter, out[i].y == it.offset().y());
273 REPORTER_ASSERT(reporter, out[i].y == it.offset().y());
274 }
275
276 for (unsigned k = 0; k < it.glyphCount(); ++k) {
277 REPORTER_ASSERT(reporter, k % 128 == it.glyphs()[k]);
278 if (SkTextBlobRunIterator::kHorizontal_Positioning == it.positioning()) {
279 REPORTER_ASSERT(reporter, SkIntToScalar(k % 128) == it.pos()[k]);
280 } else if (SkTextBlobRunIterator::kFull_Positioning == it.positioning()) {
281 REPORTER_ASSERT(reporter, SkIntToScalar(k % 128) == it.pos()[k * 2]);
282 REPORTER_ASSERT(reporter, -SkIntToScalar(k % 128) == it.pos()[k * 2 + 1]);
283 }
284 }
285
286 it.next();
287 }
288
289 REPORTER_ASSERT(reporter, it.done());
290 }
291
292 static void AddRun(const SkFont& font, int count, SkTextBlobRunIterator::GlyphPositioning pos,
294 const SkRect* bounds = nullptr) {
295 switch (pos) {
297 const SkTextBlobBuilder::RunBuffer& rb = builder.allocRun(font, count, offset.x(),
298 offset.y(), bounds);
299 for (int i = 0; i < count; ++i) {
300 rb.glyphs[i] = i;
301 }
302 } break;
304 const SkTextBlobBuilder::RunBuffer& rb = builder.allocRunPosH(font, count, offset.y(),
305 bounds);
306 for (int i = 0; i < count; ++i) {
307 rb.glyphs[i] = i;
308 rb.pos[i] = SkIntToScalar(i);
309 }
310 } break;
312 const SkTextBlobBuilder::RunBuffer& rb = builder.allocRunPos(font, count, bounds);
313 for (int i = 0; i < count; ++i) {
314 rb.glyphs[i] = i;
315 rb.pos[i * 2] = SkIntToScalar(i);
316 rb.pos[i * 2 + 1] = -SkIntToScalar(i);
317 }
318 } break;
319 default:
320 SK_ABORT("unhandled positioning value");
321 }
322 }
323};
324
325DEF_TEST(TextBlob_builder, reporter) {
328}
329
330DEF_TEST(TextBlob_paint, reporter) {
332}
333
334DEF_TEST(TextBlob_extended, reporter) {
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}
368
369///////////////////////////////////////////////////////////////////////////////////////////////////
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}
384
385static sk_sp<SkImage> render(const SkTextBlob* blob) {
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}
397
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}
409
410static sk_sp<SkTypeface> DeserializeTypeface(const void* data, size_t length, void* ctx) {
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}
427
428/*
429 * Build a blob with more than one typeface.
430 * Draw it into an offscreen,
431 * then serialize and deserialize,
432 * Then draw the new instance and assert it draws the same as the original.
433 */
434DEF_TEST(TextBlob_serialize, reporter) {
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}
466
467DEF_TEST(TextBlob_MakeAsDrawText, reporter) {
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}
480
481DEF_TEST(TextBlob_iter, reporter) {
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) {
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);
509 // Hello should have the same glyph repeated for the 'l'
510 REPORTER_ASSERT(reporter, run.fGlyphIndices[2] == run.fGlyphIndices[3]);
511}
512
513DEF_TEST(TextBlob_getIntercepts, reporter) {
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}
reporter
Definition: FontMgrTest.cpp:39
uint16_t glyphs[5]
Definition: FontMgrTest.cpp:46
int count
Definition: FontMgrTest.cpp:50
SkPoint pos
#define SkDEBUGFAIL(message)
Definition: SkAssert.h:118
#define SK_ABORT(message,...)
Definition: SkAssert.h:70
#define SkASSERT(cond)
Definition: SkAssert.h:116
constexpr SkColor SK_ColorWHITE
Definition: SkColor.h:122
@ kFull
modifies glyph outlines for maximum constrast
@ kUTF8
uses bytes to represent UTF-8 or ASCII
sk_sp< T > sk_ref_sp(T *obj)
Definition: SkRefCnt.h:381
#define SkScalarRoundToInt(x)
Definition: SkScalar.h:37
#define SkIntToScalar(x)
Definition: SkScalar.h:57
constexpr size_t SkToSizeT(S x)
Definition: SkTo.h:31
constexpr int SkToInt(S x)
Definition: SkTo.h:29
static constexpr bool SkToBool(const T &x)
Definition: SkTo.h:35
constexpr uint32_t SkToU32(S x)
Definition: SkTo.h:26
#define REPORTER_ASSERT(r, cond,...)
Definition: Test.h:286
static sk_sp< SkTypeface > DeserializeTypeface(const void *data, size_t length, void *ctx)
DEF_TEST(TextBlob_builder, reporter)
static sk_sp< SkImage > render(const SkTextBlob *blob)
static sk_sp< SkData > SerializeTypeface(SkTypeface *tf, void *ctx)
static void add_run(SkTextBlobBuilder *builder, const char text[], SkScalar x, SkScalar y, sk_sp< SkTypeface > tf)
static sk_sp< SkData > MakeWithCopy(const void *data, size_t length)
Definition: SkData.cpp:111
size_t size() const
Definition: SkData.h:30
static constexpr SkFontStyle BoldItalic()
Definition: SkFontStyle.h:75
static constexpr SkFontStyle Bold()
Definition: SkFontStyle.h:69
Definition: SkFont.h:35
bool isEmbolden() const
Definition: SkFont.h:126
Edging getEdging() const
Definition: SkFont.h:180
SkTypeface * getTypeface() const
Definition: SkFont.h:208
SkScalar getSize() const
Definition: SkFont.h:217
SkFontHinting getHinting() const
Definition: SkFont.h:194
bool isForceAutoHinting() const
Definition: SkFont.h:101
bool isLinearMetrics() const
Definition: SkFont.h:119
bool isEmbeddedBitmaps() const
Definition: SkFont.h:107
SkScalar getScaleX() const
Definition: SkFont.h:224
SkScalar getSkewX() const
Definition: SkFont.h:231
bool isSubpixel() const
Definition: SkFont.h:113
@ kAntiAlias
may have transparent pixels on glyph edges
@ kSubpixelAntiAlias
glyph positioned in pixel using transparency
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
const SkFont & font() const
bool next(Run *)
Definition: SkTextBlob.cpp:978
const SkRect & bounds() const
Definition: SkTextBlob.h:53
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
static sk_sp< SkTextBlob > Deserialize(const void *data, size_t size, const SkDeserialProcs &procs)
Definition: SkTextBlob.cpp:855
static sk_sp< SkTextBlob > MakeFromString(const char *string, const SkFont &font, SkTextEncoding encoding=SkTextEncoding::kUTF8)
Definition: SkTextBlob.h:115
size_t serialize(const SkSerialProcs &procs, void *memory, size_t memory_size) const
Definition: SkTextBlob.cpp:864
int countGlyphs() const
Definition: SkTypeface.cpp:432
SkRect getBounds() const
Definition: SkTypeface.cpp:507
static void TestPaintProps(skiatest::Reporter *reporter)
static void TestBounds(skiatest::Reporter *reporter)
static void TestBuilder(skiatest::Reporter *reporter)
T * get() const
Definition: SkRefCnt.h:303
int size() const
Definition: SkTArray.h:421
float SkScalar
Definition: extension.cpp:12
static float min(float r, float g, float b)
Definition: hsl.cpp:48
size_t length
std::u16string text
double y
double x
Optional< SkRect > bounds
Definition: SkRecords.h:189
SK_API sk_sp< SkSurface > Raster(const SkImageInfo &imageInfo, size_t rowBytes, const SkSurfaceProps *surfaceProps)
sk_sp< SkTypeface > CreatePortableTypeface(const char *name, SkFontStyle style)
SkFont DefaultFont()
bool equal_pixels(const SkPixmap &a, const SkPixmap &b)
Definition: ToolUtils.cpp:456
sk_sp< SkTypeface > CreateTestTypeface(const char *name, SkFontStyle style)
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
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
font
Font Metadata and Metrics.
Definition: run.py:1
def run(cmd)
Definition: run.py:14
SeparatedVector2 offset
SkDeserialTypefaceProc fTypefaceProc
static SkImageInfo MakeN32Premul(int width, int height)
static constexpr SkPoint Make(float x, float y)
Definition: SkPoint_impl.h:173
constexpr float left() const
Definition: SkRect.h:734
constexpr float top() const
Definition: SkRect.h:741
static constexpr SkRect MakeXYWH(float x, float y, float w, float h)
Definition: SkRect.h:659
constexpr float height() const
Definition: SkRect.h:769
constexpr float width() const
Definition: SkRect.h:762
bool isEmpty() const
Definition: SkRect.h:693
void * fTypefaceCtx
Definition: SkSerialProcs.h:94
SkSerialTypefaceProc fTypefaceProc
Definition: SkSerialProcs.h:93
SkScalar * pos
storage for glyph positions in run
Definition: SkTextBlob.h:330
SkGlyphID * glyphs
storage for glyph indexes in run
Definition: SkTextBlob.h:329
std::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:63