Flutter Engine
The Flutter Engine
SkRemoteGlyphCacheTest.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2018 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
14#include "include/core/SkData.h"
15#include "include/core/SkFont.h"
22#include "include/core/SkRect.h"
40#include "src/core/SkFontPriv.h"
41#include "src/core/SkGlyph.h"
44#include "src/core/SkTHash.h"
53#include "tests/Test.h"
54#include "tools/Resources.h"
55#include "tools/ToolUtils.h"
58
59#include <cmath>
60#include <cstdint>
61#include <cstring>
62#include <initializer_list>
63#include <memory>
64#include <optional>
65#include <vector>
66
67using namespace skia_private;
69
72public:
73 DiscardableManager() { sk_bzero(&fCacheMissCount, sizeof(fCacheMissCount)); }
74 ~DiscardableManager() override = default;
75
76 // Server implementation.
78 SkAutoMutexExclusive l(fMutex);
79
80 // Handles starts as locked.
81 fLockedHandles.add(++fNextHandleId);
82 return fNextHandleId;
83 }
85 SkAutoMutexExclusive l(fMutex);
86
87 if (id <= fLastDeletedHandleId) return false;
88 fLockedHandles.add(id);
89 return true;
90 }
91
92 // Client implementation.
94 SkAutoMutexExclusive l(fMutex);
95
96 return id <= fLastDeletedHandleId;
97 }
98
99 void notifyCacheMiss(SkStrikeClient::CacheMissType type, int fontSize) override {
100 SkAutoMutexExclusive l(fMutex);
101
102 fCacheMissCount[type]++;
103 }
105 SkAutoMutexExclusive l(fMutex);
106
107 return id <= fLastDeletedHandleId;
108 }
109
110 void unlockAll() {
111 SkAutoMutexExclusive l(fMutex);
112
113 fLockedHandles.reset();
114 }
116 SkAutoMutexExclusive l(fMutex);
117
118 fLockedHandles.reset();
119 fLastDeletedHandleId = fNextHandleId;
120 }
122 SkAutoMutexExclusive l(fMutex);
123
124 return fLockedHandles;
125 }
127 SkAutoMutexExclusive l(fMutex);
128
129 return fNextHandleId;
130 }
131 int cacheMissCount(uint32_t type) {
132 SkAutoMutexExclusive l(fMutex);
133
134 return fCacheMissCount[type];
135 }
136 bool hasCacheMiss() const {
137 SkAutoMutexExclusive l(fMutex);
138
139 for (uint32_t i = 0; i <= SkStrikeClient::CacheMissType::kLast; ++i) {
140 if (fCacheMissCount[i] > 0) { return true; }
141 }
142 return false;
143 }
145 SkAutoMutexExclusive l(fMutex);
146 sk_bzero(&fCacheMissCount, sizeof(fCacheMissCount));
147 }
148
149private:
150 // The tests below run in parallel on multiple threads and use the same
151 // process global SkStrikeCache. So the implementation needs to be
152 // thread-safe.
153 mutable SkMutex fMutex;
154
155 SkDiscardableHandleId fNextHandleId = 0u;
156 SkDiscardableHandleId fLastDeletedHandleId = 0u;
157 THashSet<SkDiscardableHandleId> fLockedHandles;
158 int fCacheMissCount[SkStrikeClient::CacheMissType::kLast + 1u];
159};
160
161sk_sp<SkTextBlob> buildTextBlob(sk_sp<SkTypeface> tf, int glyphCount, int textSize = 1) {
162 SkFont font;
163 SkASSERT(tf);
164 font.setTypeface(tf);
165 font.setHinting(SkFontHinting::kNormal);
166 font.setSize(textSize);
168 font.setSubpixel(true);
169
171 SkRect bounds = SkRect::MakeWH(10, 10);
172 const auto& runBuffer = builder.allocRunPosH(font, glyphCount, 0, &bounds);
173 SkASSERT(runBuffer.utf8text == nullptr);
174 SkASSERT(runBuffer.clusters == nullptr);
175
176 for (int i = 0; i < glyphCount; i++) {
177 runBuffer.glyphs[i] = static_cast<SkGlyphID>(i);
178 runBuffer.pos[i] = SkIntToScalar(i);
179 }
180 return builder.make();
181}
182
183static void compare_blobs(const SkBitmap& expected, const SkBitmap& actual,
184 skiatest::Reporter* reporter, int tolerance = 0) {
185 SkASSERT(expected.width() == actual.width());
186 SkASSERT(expected.height() == actual.height());
187 for (int i = 0; i < expected.width(); ++i) {
188 for (int j = 0; j < expected.height(); ++j) {
189 SkColor expectedColor = expected.getColor(i, j);
190 SkColor actualColor = actual.getColor(i, j);
191 if (0 == tolerance) {
192 REPORTER_ASSERT(reporter, expectedColor == actualColor);
193 } else {
194 for (int k = 0; k < 4; ++k) {
195 int expectedChannel = (expectedColor >> (k*8)) & 0xff;
196 int actualChannel = (actualColor >> (k*8)) & 0xff;
197 REPORTER_ASSERT(reporter, abs(expectedChannel - actualChannel) <= tolerance);
198 }
199 }
200 }
201 }
202}
203
205 const SkImageInfo info =
208}
209
211 auto surface = MakeSurface(1, 1, rContext);
212 return surface->props();
213}
214
216 GrRecordingContext* rContext, const SkMatrix* matrix = nullptr,
217 SkScalar x = 0) {
218 auto surface = MakeSurface(width, height, rContext);
219 if (matrix) {
220 surface->getCanvas()->concat(*matrix);
221 }
222 surface->getCanvas()->drawTextBlob(blob.get(), x, height/2, paint);
224 bitmap.allocN32Pixels(width, height);
225 surface->readPixels(bitmap, 0, 0);
226 return bitmap;
227}
228
230 GrRecordingContext* rContext, const SkMatrix* matrix = nullptr,
231 SkScalar x = 0) {
232 auto surface = MakeSurface(width, height, rContext);
233 if (matrix) {
234 surface->getCanvas()->concat(*matrix);
235 }
236 auto canvas = surface->getCanvas();
237 auto slug = Slug::ConvertBlob(canvas, *blob, {x, height/2.0f}, paint);
238 slug->draw(canvas, paint);
240 bitmap.allocN32Pixels(width, height);
241 surface->readPixels(bitmap, 0, 0);
242 return bitmap;
243}
244
246 GrRecordingContext* rContext, const SkMatrix* matrix = nullptr,
247 SkScalar x = 0) {
248 auto surface = MakeSurface(width, height, rContext);
249 auto canvas = surface->getCanvas();
250 if (matrix) {
251 canvas->concat(*matrix);
252 }
253 slug->draw(canvas, paint);
255 bitmap.allocN32Pixels(width, height);
256 surface->readPixels(bitmap, 0, 0);
257 return bitmap;
258}
259
260DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(SkRemoteGlyphCache_StrikeSerialization,
261 reporter,
262 ctxInfo,
264 auto dContext = ctxInfo.directContext();
265 sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>();
266 SkStrikeServer server(discardableManager.get());
267 SkStrikeClient client(discardableManager, false);
268 const SkPaint paint;
269
270 // Server.
271 auto serverTypeface = ToolUtils::CreateTestTypeface("monospace", SkFontStyle());
272 const SkTypefaceID serverTypefaceID = serverTypeface->uniqueID();
273
274 int glyphCount = 10;
275 auto serverBlob = buildTextBlob(serverTypeface, glyphCount);
276 auto props = FindSurfaceProps(dContext);
277 std::unique_ptr<SkCanvas> analysisCanvas = server.makeAnalysisCanvas(
278 10, 10, props, nullptr, dContext->supportsDistanceFieldText(),
279 !dContext->priv().caps()->disablePerspectiveSDFText());
280 analysisCanvas->drawTextBlob(serverBlob.get(), 0, 0, paint);
281
282 std::vector<uint8_t> serverStrikeData;
283 server.writeStrikeData(&serverStrikeData);
284
285 // Client.
287 client.readStrikeData(serverStrikeData.data(), serverStrikeData.size()));
288 auto clientTypeface = client.retrieveTypefaceUsingServerIDForTest(serverTypefaceID);
289
290 // Ensure typeface serialization/deserialization worked.
292 static_cast<SkTypefaceProxy*>(clientTypeface.get())->remoteTypefaceID() ==
293 serverTypefaceID);
294
295 auto clientBlob = buildTextBlob(clientTypeface, glyphCount);
296
297 SkBitmap expected = RasterBlob(serverBlob, 10, 10, paint, dContext);
298 SkBitmap actual = RasterBlob(clientBlob, 10, 10, paint, dContext);
299 compare_blobs(expected, actual, reporter);
300 REPORTER_ASSERT(reporter, !discardableManager->hasCacheMiss());
301
302 // Must unlock everything on termination, otherwise valgrind complains about memory leaks.
303 discardableManager->unlockAndDeleteAll();
304}
305
307 options->fSupportBilerpFromGlyphAtlas = true;
308}
309
310DEF_GANESH_TEST_FOR_CONTEXTS(SkRemoteGlyphCache_StrikeSerializationSlug,
312 reporter,
313 ctxInfo,
316 auto dContext = ctxInfo.directContext();
317 sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>();
318 SkStrikeServer server(discardableManager.get());
319 SkStrikeClient client(discardableManager, false);
320 const SkPaint paint;
321
322 // Server.
323 auto serverTypeface = ToolUtils::CreateTestTypeface("monospace", SkFontStyle());
324 const SkTypefaceID serverTypefaceID = serverTypeface->uniqueID();
325
326 int glyphCount = 10;
327 auto serverBlob = buildTextBlob(serverTypeface, glyphCount);
328 auto props = FindSurfaceProps(dContext);
329 std::unique_ptr<SkCanvas> analysisCanvas = server.makeAnalysisCanvas(
330 10, 10, props, nullptr, dContext->supportsDistanceFieldText(),
331 !dContext->priv().caps()->disablePerspectiveSDFText());
332
333 // Generate strike updates.
334 (void)Slug::ConvertBlob(analysisCanvas.get(), *serverBlob, {0, 0}, paint);
335
336 std::vector<uint8_t> serverStrikeData;
337 server.writeStrikeData(&serverStrikeData);
338
339 // Client.
341 client.readStrikeData(serverStrikeData.data(), serverStrikeData.size()));
342 auto clientTypeface = client.retrieveTypefaceUsingServerIDForTest(serverTypefaceID);
343 auto clientBlob = buildTextBlob(clientTypeface, glyphCount);
344
345 SkBitmap expected = RasterBlobThroughSlug(serverBlob, 10, 10, paint, dContext);
346 SkBitmap actual = RasterBlobThroughSlug(clientBlob, 10, 10, paint, dContext);
347 compare_blobs(expected, actual, reporter);
348 REPORTER_ASSERT(reporter, !discardableManager->hasCacheMiss());
349
350 // Must unlock everything on termination, otherwise valgrind complains about memory leaks.
351 discardableManager->unlockAndDeleteAll();
352}
353
354DEF_GANESH_TEST_FOR_CONTEXTS(SkRemoteGlyphCache_StrikeSerializationSlugForcePath,
356 reporter,
357 ctxInfo,
360 auto dContext = ctxInfo.directContext();
361 sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>();
362 SkStrikeServer server(discardableManager.get());
363 SkStrikeClient client(discardableManager, false);
364 const SkPaint paint;
365
366 // Server.
367 auto serverTypeface = ToolUtils::CreateTestTypeface("monospace", SkFontStyle());
368 const SkTypefaceID serverTypefaceID = serverTypeface->uniqueID();
369
370 int glyphCount = 10;
371 auto serverBlob = buildTextBlob(serverTypeface, glyphCount, 360);
372 auto props = FindSurfaceProps(dContext);
373 std::unique_ptr<SkCanvas> analysisCanvas = server.makeAnalysisCanvas(
374 10, 10, props, nullptr, dContext->supportsDistanceFieldText(),
375 !dContext->priv().caps()->disablePerspectiveSDFText());
376
377 // Generate strike updates.
378 (void)Slug::ConvertBlob(analysisCanvas.get(), *serverBlob, {0, 0}, paint);
379
380 std::vector<uint8_t> serverStrikeData;
381 server.writeStrikeData(&serverStrikeData);
382
383 // Client.
385 client.readStrikeData(serverStrikeData.data(), serverStrikeData.size()));
386 auto clientTypeface = client.retrieveTypefaceUsingServerIDForTest(serverTypefaceID);
387 auto clientBlob = buildTextBlob(clientTypeface, glyphCount, 360);
388
389 SkBitmap expected = RasterBlobThroughSlug(serverBlob, 10, 10, paint, dContext);
390 SkBitmap actual = RasterBlobThroughSlug(clientBlob, 10, 10, paint, dContext);
391 compare_blobs(expected, actual, reporter);
392 REPORTER_ASSERT(reporter, !discardableManager->hasCacheMiss());
393
394 // Must unlock everything on termination, otherwise valgrind complains about memory leaks.
395 discardableManager->unlockAndDeleteAll();
396}
397
398DEF_GANESH_TEST_FOR_CONTEXTS(SkRemoteGlyphCache_SlugSerialization,
400 reporter,
401 ctxInfo,
404 auto dContext = ctxInfo.directContext();
405 sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>();
406 SkStrikeServer server(discardableManager.get());
407 SkStrikeClient client(discardableManager, false);
408 const SkPaint paint;
409
410 // Server.
411 auto serverTypeface = ToolUtils::CreateTestTypeface("monospace", SkFontStyle());
412
413 int glyphCount = 10;
414 auto serverBlob = buildTextBlob(serverTypeface, glyphCount);
415 auto props = FindSurfaceProps(dContext);
416 std::unique_ptr<SkCanvas> analysisCanvas = server.makeAnalysisCanvas(
417 10, 10, props, nullptr, dContext->supportsDistanceFieldText(),
418 !dContext->priv().caps()->disablePerspectiveSDFText());
419
420 // Generate strike updates.
421 auto srcSlug = Slug::ConvertBlob(analysisCanvas.get(), *serverBlob, {0.3f, 0}, paint);
422 auto dstSlugData = srcSlug->serialize();
423
424 std::vector<uint8_t> serverStrikeData;
425 server.writeStrikeData(&serverStrikeData);
426
427 // Client.
429 client.readStrikeData(serverStrikeData.data(), serverStrikeData.size()));
430
431 SkBitmap expected = RasterSlug(srcSlug, 10, 10, paint, dContext);
432 auto dstSlug = client.deserializeSlugForTest(dstSlugData->data(), dstSlugData->size());
433 REPORTER_ASSERT(reporter, dstSlug != nullptr);
434 SkBitmap actual = RasterSlug(dstSlug, 10, 10, paint, dContext);
435 compare_blobs(expected, actual, reporter);
436 REPORTER_ASSERT(reporter, !discardableManager->hasCacheMiss());
437
438 // Must unlock everything on termination, otherwise valgrind complains about memory leaks.
439 discardableManager->unlockAndDeleteAll();
440}
441
442DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(SkRemoteGlyphCache_ReleaseTypeFace,
443 reporter,
444 ctxInfo,
446 sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>();
447 SkStrikeServer server(discardableManager.get());
448 SkStrikeClient client(discardableManager, false);
449
450 // Server.
451 auto serverTypeface = TestEmptyTypeface::Make();
452 REPORTER_ASSERT(reporter, serverTypeface->unique());
453
454 {
455 const SkPaint paint;
456 int glyphCount = 10;
457 auto serverBlob = buildTextBlob(serverTypeface, glyphCount);
458 const SkSurfaceProps props;
459 std::unique_ptr<SkCanvas> cache_diff_canvas = server.makeAnalysisCanvas(
460 10, 10, props, nullptr, ctxInfo.directContext()->supportsDistanceFieldText(),
461 !ctxInfo.directContext()->priv().caps()->disablePerspectiveSDFText());
462 cache_diff_canvas->drawTextBlob(serverBlob.get(), 0, 0, paint);
463 REPORTER_ASSERT(reporter, !serverTypeface->unique());
464
465 std::vector<uint8_t> serverStrikeData;
466 server.writeStrikeData(&serverStrikeData);
467 }
468 REPORTER_ASSERT(reporter, serverTypeface->unique());
469
470 // Must unlock everything on termination, otherwise valgrind complains about memory leaks.
471 discardableManager->unlockAndDeleteAll();
472}
473
474DEF_TEST(SkRemoteGlyphCache_StrikeLockingServer, reporter) {
475 sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>();
476 SkStrikeServer server(discardableManager.get());
477 SkStrikeClient client(discardableManager, false);
478
479 auto serverTypeface = ToolUtils::CreateTestTypeface("monospace", SkFontStyle());
480 int glyphCount = 10;
481 auto serverBlob = buildTextBlob(serverTypeface, glyphCount);
482
483 const SkSurfaceProps props;
484 std::unique_ptr<SkCanvas> cache_diff_canvas =
485 server.makeAnalysisCanvas(10, 10, props, nullptr, true, true);
487 cache_diff_canvas->drawTextBlob(serverBlob.get(), 0, 0, paint);
488
489 // The strike from the blob should be locked after it has been drawn on the canvas.
490 REPORTER_ASSERT(reporter, discardableManager->handleCount() == 1u);
491 REPORTER_ASSERT(reporter, discardableManager->lockedHandles().count() == 1u);
492
493 // Write the strike data and unlock everything. Re-analyzing the blob should lock the handle
494 // again.
495 std::vector<uint8_t> fontData;
496 server.writeStrikeData(&fontData);
497 discardableManager->unlockAll();
498 REPORTER_ASSERT(reporter, discardableManager->lockedHandles().count() == 0u);
499
500 cache_diff_canvas->drawTextBlob(serverBlob.get(), 0, 0, paint);
501 REPORTER_ASSERT(reporter, discardableManager->handleCount() == 1u);
502 REPORTER_ASSERT(reporter, discardableManager->lockedHandles().count() == 1u);
503
504 // Must unlock everything on termination, otherwise valgrind complains about memory leaks.
505 discardableManager->unlockAndDeleteAll();
506}
507
508DEF_TEST(SkRemoteGlyphCache_StrikeDeletionServer, reporter) {
509 sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>();
510 SkStrikeServer server(discardableManager.get());
511 SkStrikeClient client(discardableManager, false);
512
513 auto serverTypeface = ToolUtils::CreateTestTypeface("monospace", SkFontStyle());
514 int glyphCount = 10;
515 auto serverBlob = buildTextBlob(serverTypeface, glyphCount);
516
517 const SkSurfaceProps props;
518 std::unique_ptr<SkCanvas> cache_diff_canvas =
519 server.makeAnalysisCanvas(10, 10, props, nullptr, true, true);
521 cache_diff_canvas->drawTextBlob(serverBlob.get(), 0, 0, paint);
522 REPORTER_ASSERT(reporter, discardableManager->handleCount() == 1u);
523
524 // Write the strike data and delete all the handles. Re-analyzing the blob should create new
525 // handles.
526 std::vector<uint8_t> fontData;
527 server.writeStrikeData(&fontData);
528
529 // Another analysis pass, to ensure that deleting handles after a complete cache hit still
530 // works. This is a regression test for crbug.com/999682.
531 cache_diff_canvas->drawTextBlob(serverBlob.get(), 0, 0, paint);
532 server.writeStrikeData(&fontData);
533 REPORTER_ASSERT(reporter, discardableManager->handleCount() == 1u);
534
535 discardableManager->unlockAndDeleteAll();
536 cache_diff_canvas->drawTextBlob(serverBlob.get(), 0, 0, paint);
537 REPORTER_ASSERT(reporter, discardableManager->handleCount() == 2u);
538
539 // Must unlock everything on termination, otherwise valgrind complains about memory leaks.
540 discardableManager->unlockAndDeleteAll();
541}
542
543DEF_TEST(SkRemoteGlyphCache_StrikePinningClient, reporter) {
544 sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>();
545 SkStrikeServer server(discardableManager.get());
546 SkStrikeClient client(discardableManager, false);
547
548 // Server.
549 auto serverTypeface = ToolUtils::CreateTestTypeface("monospace", SkFontStyle());
550 const SkTypefaceID serverTypefaceID = serverTypeface->uniqueID();
551
552 int glyphCount = 10;
553 auto serverBlob = buildTextBlob(serverTypeface, glyphCount);
554
555 const SkSurfaceProps props;
556 std::unique_ptr<SkCanvas> cache_diff_canvas =
557 server.makeAnalysisCanvas(10, 10, props, nullptr, true, true);
559 cache_diff_canvas->drawTextBlob(serverBlob.get(), 0, 0, paint);
560
561 std::vector<uint8_t> serverStrikeData;
562 server.writeStrikeData(&serverStrikeData);
563
564 // Client.
566 client.readStrikeData(serverStrikeData.data(), serverStrikeData.size()));
567 auto* clientTypeface = client.retrieveTypefaceUsingServerIDForTest(serverTypefaceID).get();
568
569 // The cache remains alive until it is pinned in the discardable manager.
571 REPORTER_ASSERT(reporter, !clientTypeface->unique());
572
573 // Once the strike is unpinned and purged, SkStrikeClient should be the only owner of the
574 // clientTf.
575 discardableManager->unlockAndDeleteAll();
577 REPORTER_ASSERT(reporter, clientTypeface->unique());
578
579 // Must unlock everything on termination, otherwise valgrind complains about memory leaks.
580 discardableManager->unlockAndDeleteAll();
581}
582
583DEF_TEST(SkRemoteGlyphCache_ClientMemoryAccounting, reporter) {
584 sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>();
585 SkStrikeServer server(discardableManager.get());
586 SkStrikeClient client(discardableManager, false);
587
588 // Server.
589 auto serverTypeface = ToolUtils::CreateTestTypeface("monospace", SkFontStyle());
590
591 int glyphCount = 10;
592 auto serverBlob = buildTextBlob(serverTypeface, glyphCount);
593
594 const SkSurfaceProps props;
595 std::unique_ptr<SkCanvas> cache_diff_canvas =
596 server.makeAnalysisCanvas(10, 10, props, nullptr, true, true);
598 cache_diff_canvas->drawTextBlob(serverBlob.get(), 0, 0, paint);
599
600 std::vector<uint8_t> serverStrikeData;
601 server.writeStrikeData(&serverStrikeData);
602
603 // Client.
605 client.readStrikeData(serverStrikeData.data(), serverStrikeData.size()));
606
607 // Must unlock everything on termination, otherwise valgrind complains about memory leaks.
608 discardableManager->unlockAndDeleteAll();
609}
610
611DEF_TEST(SkRemoteGlyphCache_PurgesServerEntries, reporter) {
612 sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>();
613 SkStrikeServer server(discardableManager.get());
615 SkStrikeClient client(discardableManager, false);
616
617 {
618 auto serverTypeface = ToolUtils::CreateTestTypeface("monospace", SkFontStyle());
619 int glyphCount = 10;
620 auto serverBlob = buildTextBlob(serverTypeface, glyphCount);
621
622 const SkSurfaceProps props;
623 std::unique_ptr<SkCanvas> cache_diff_canvas =
624 server.makeAnalysisCanvas(10, 10, props, nullptr, true, true);
627 cache_diff_canvas->drawTextBlob(serverBlob.get(), 0, 0, paint);
629 }
630
631 // Serialize to release the lock from the strike server and delete all current
632 // handles.
633 std::vector<uint8_t> fontData;
634 server.writeStrikeData(&fontData);
635 discardableManager->unlockAndDeleteAll();
636
637 // Use a different typeface. Creating a new strike should evict the previous
638 // one.
639 {
640 auto serverTypeface = ToolUtils::CreateTestTypeface("Georgia", SkFontStyle());
641 int glyphCount = 10;
642 auto serverBlob = buildTextBlob(serverTypeface, glyphCount);
643
644 const SkSurfaceProps props;
645 std::unique_ptr<SkCanvas> cache_diff_canvas =
646 server.makeAnalysisCanvas(10, 10, props, nullptr, true, true);
649 cache_diff_canvas->drawTextBlob(serverBlob.get(), 0, 0, paint);
651 }
652
653 // Must unlock everything on termination, otherwise valgrind complains about memory leaks.
654 discardableManager->unlockAndDeleteAll();
655}
656
657DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(SkRemoteGlyphCache_DrawTextAsPath,
658 reporter,
659 ctxInfo,
661 auto direct = ctxInfo.directContext();
662 sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>();
663 SkStrikeServer server(discardableManager.get());
664 SkStrikeClient client(discardableManager, false);
667 paint.setStrokeWidth(0);
671
672 // Server.
673 auto serverTypeface = ToolUtils::CreateTestTypeface("monospace", SkFontStyle());
674 const SkTypefaceID serverTypefaceID = serverTypeface->uniqueID();
675
676 int glyphCount = 10;
677 auto serverBlob = buildTextBlob(serverTypeface, glyphCount);
678 auto props = FindSurfaceProps(direct);
679 std::unique_ptr<SkCanvas> cache_diff_canvas = server.makeAnalysisCanvas(
680 10, 10, props, nullptr, direct->supportsDistanceFieldText(),
681 !direct->priv().caps()->disablePerspectiveSDFText());
682 cache_diff_canvas->drawTextBlob(serverBlob.get(), 0, 0, paint);
683
684 std::vector<uint8_t> serverStrikeData;
685 server.writeStrikeData(&serverStrikeData);
686
687 // Client.
689 client.readStrikeData(serverStrikeData.data(), serverStrikeData.size()));
690 auto clientTypeface = client.retrieveTypefaceUsingServerIDForTest(serverTypefaceID);
691 auto clientBlob = buildTextBlob(clientTypeface, glyphCount);
692
693 SkBitmap expected = RasterBlob(serverBlob, 10, 10, paint, direct);
694 SkBitmap actual = RasterBlob(clientBlob, 10, 10, paint, direct);
695 compare_blobs(expected, actual, reporter, 1);
696 REPORTER_ASSERT(reporter, !discardableManager->hasCacheMiss());
697
698 // Must unlock everything on termination, otherwise valgrind complains about memory leaks.
699 discardableManager->unlockAndDeleteAll();
700}
701
703 sk_sp<SkTypeface> targetTf, const SkTypeface* glyphTf, skiatest::Reporter* reporter) {
705 font.setSubpixel(true);
706 font.setSize(96);
707 font.setHinting(SkFontHinting::kNormal);
708 font.setTypeface(targetTf);
709
712
713 char s[] = "Skia";
714 int runSize = strlen(s);
715
717 SkRect bounds = SkRect::MakeIWH(100, 100);
718 const auto& runBuffer = builder.allocRunPosH(font, runSize, 10, &bounds);
719 SkASSERT(runBuffer.utf8text == nullptr);
720 SkASSERT(runBuffer.clusters == nullptr);
721
723 runBuffer.glyphs, runSize);
724
725 SkRect glyphBounds;
726 font.getWidths(runBuffer.glyphs, 1, nullptr, &glyphBounds);
727
729
730 for (int i = 0; i < runSize; i++) {
731 runBuffer.pos[i] = i * 10;
732 }
733
734 return builder.make();
735}
736
737DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(SkRemoteGlyphCache_DrawTextAsMaskWithPathFallback,
738 reporter,
739 ctxInfo,
741 auto direct = ctxInfo.directContext();
742 sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>();
743 SkStrikeServer server(discardableManager.get());
744 SkStrikeClient client(discardableManager, false);
745
747
748 auto serverTypeface = ToolUtils::CreateTypefaceFromResource("fonts/HangingS.ttf");
749 // TODO: when the cq bots can handle this font remove the check.
750 if (serverTypeface == nullptr) {
751 return;
752 }
753 const SkTypefaceID serverTypefaceID = serverTypeface->uniqueID();
754
755 auto serverBlob = make_blob_causing_fallback(serverTypeface, serverTypeface.get(), reporter);
756
757 auto props = FindSurfaceProps(direct);
758 std::unique_ptr<SkCanvas> cache_diff_canvas = server.makeAnalysisCanvas(
759 10, 10, props, nullptr, direct->supportsDistanceFieldText(),
760 !direct->priv().caps()->disablePerspectiveSDFText());
761 cache_diff_canvas->drawTextBlob(serverBlob.get(), 0, 0, paint);
762
763 std::vector<uint8_t> serverStrikeData;
764 server.writeStrikeData(&serverStrikeData);
765
766 // Client.
768 client.readStrikeData(serverStrikeData.data(), serverStrikeData.size()));
769 auto clientTypeface = client.retrieveTypefaceUsingServerIDForTest(serverTypefaceID);
770 auto clientBlob = make_blob_causing_fallback(clientTypeface, serverTypeface.get(), reporter);
771
772 SkBitmap expected = RasterBlob(serverBlob, 10, 10, paint, direct);
773 SkBitmap actual = RasterBlob(clientBlob, 10, 10, paint, direct);
774 compare_blobs(expected, actual, reporter);
775 REPORTER_ASSERT(reporter, !discardableManager->hasCacheMiss());
776
777 // Must unlock everything on termination, otherwise valgrind complains about memory leaks.
778 discardableManager->unlockAndDeleteAll();
779}
780
781DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(SkRemoteGlyphCache_DrawTextXY,
782 reporter,
783 ctxInfo,
785 auto direct = ctxInfo.directContext();
786 sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>();
787 SkStrikeServer server(discardableManager.get());
788 SkStrikeClient client(discardableManager, false);
790 paint.setAntiAlias(true);
791
792 // Server.
793 auto serverTypeface = ToolUtils::CreateTestTypeface("monospace", SkFontStyle());
794 const SkTypefaceID serverTypefaceID = serverTypeface->uniqueID();
795
796 int glyphCount = 10;
797 auto serverBlob = buildTextBlob(serverTypeface, glyphCount);
798 auto props = FindSurfaceProps(direct);
799 std::unique_ptr<SkCanvas> cache_diff_canvas = server.makeAnalysisCanvas(
800 10, 10, props, nullptr, direct->supportsDistanceFieldText(),
801 !direct->priv().caps()->disablePerspectiveSDFText());
802 cache_diff_canvas->drawTextBlob(serverBlob.get(), 0.5, 0, paint);
803
804 std::vector<uint8_t> serverStrikeData;
805 server.writeStrikeData(&serverStrikeData);
806
807 // Client.
809 client.readStrikeData(serverStrikeData.data(), serverStrikeData.size()));
810 auto clientTypeface = client.retrieveTypefaceUsingServerIDForTest(serverTypefaceID);
811 auto clientBlob = buildTextBlob(clientTypeface, glyphCount);
812
813 SkBitmap expected = RasterBlob(serverBlob, 10, 10, paint, direct, nullptr, 0.5);
814 SkBitmap actual = RasterBlob(clientBlob, 10, 10, paint, direct, nullptr, 0.5);
815 compare_blobs(expected, actual, reporter);
816 REPORTER_ASSERT(reporter, !discardableManager->hasCacheMiss());
817
818 // Must unlock everything on termination, otherwise valgrind complains about memory leaks.
819 discardableManager->unlockAndDeleteAll();
820}
821
822#if !defined(SK_DISABLE_SDF_TEXT)
823DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(SkRemoteGlyphCache_DrawTextAsDFT,
824 reporter,
825 ctxInfo,
827 auto direct = ctxInfo.directContext();
828 if (!direct->priv().caps()->shaderCaps()->supportsDistanceFieldText()) {
829 return;
830 }
831 sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>();
832 SkStrikeServer server(discardableManager.get());
833 SkStrikeClient client(discardableManager, false);
836
837 // A scale transform forces fallback to dft.
840 direct->priv().asRecordingContext()->priv().getSDFTControl(true);
842 {0, 0});
843 REPORTER_ASSERT(reporter, control.isSDFT(approximateDeviceTextSize, paint, matrix));
844
845 // Server.
846 auto serverTypeface = ToolUtils::CreateTestTypeface("monospace", SkFontStyle());
847 const SkTypefaceID serverTypefaceID = serverTypeface->uniqueID();
848
849 int glyphCount = 10;
850 auto serverBlob = buildTextBlob(serverTypeface, glyphCount);
851 const SkSurfaceProps props;
852 std::unique_ptr<SkCanvas> cache_diff_canvas = server.makeAnalysisCanvas(
853 10, 10, props, nullptr, direct->supportsDistanceFieldText(),
854 !direct->priv().caps()->disablePerspectiveSDFText());
855 cache_diff_canvas->concat(matrix);
856 cache_diff_canvas->drawTextBlob(serverBlob.get(), 0, 0, paint);
857
858 std::vector<uint8_t> serverStrikeData;
859 server.writeStrikeData(&serverStrikeData);
860
861 // Client.
863 client.readStrikeData(serverStrikeData.data(), serverStrikeData.size()));
864 auto clientTypeface = client.retrieveTypefaceUsingServerIDForTest(serverTypefaceID);
865 auto clientBlob = buildTextBlob(clientTypeface, glyphCount);
866
867 SkBitmap expected = RasterBlob(serverBlob, 10, 10, paint, direct, &matrix);
868 SkBitmap actual = RasterBlob(clientBlob, 10, 10, paint, direct, &matrix);
869 compare_blobs(expected, actual, reporter);
870 REPORTER_ASSERT(reporter, !discardableManager->hasCacheMiss());
871
872 // Must unlock everything on termination, otherwise valgrind complains about memory leaks.
873 discardableManager->unlockAndDeleteAll();
874}
875#endif // !defined(SK_DISABLE_SDF_TEXT)
876
877DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(SkRemoteGlyphCache_CacheMissReporting,
878 reporter,
879 ctxInfo,
881 sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>();
882 SkStrikeServer server(discardableManager.get());
883 SkStrikeClient client(discardableManager, false);
884
885 auto serverTypeface = ToolUtils::CreateTestTypeface("monospace", SkFontStyle());
886 REPORTER_ASSERT(reporter, serverTypeface);
887
888 // Create the clientTypeface proxy directly from the serverTypeface.
889 auto clientTypeface = sk_make_sp<SkTypefaceProxy>(
890 serverTypeface->uniqueID(),
891 serverTypeface->countGlyphs(),
892 serverTypeface->fontStyle(),
893 serverTypeface->isFixedPitch(),
894 /*glyphMaskNeedsCurrentColor=*/ false,
895 discardableManager,
896 /*isLogging=*/ false);
897
898 REPORTER_ASSERT(reporter, clientTypeface);
899 int glyphCount = 10;
900 auto clientBlob = buildTextBlob(clientTypeface, glyphCount);
901
902 // Raster the client-side blob without the glyph data, we should get cache miss notifications.
905 RasterBlob(clientBlob, 10, 10, paint, ctxInfo.directContext(), &matrix);
907 discardableManager->cacheMissCount(SkStrikeClient::kFontMetrics) == 1);
909 discardableManager->cacheMissCount(SkStrikeClient::kGlyphMetrics) == 10);
910
911 // There shouldn't be any image or path requests, since we mark the glyph as empty on a cache
912 // miss.
913 REPORTER_ASSERT(reporter, discardableManager->cacheMissCount(SkStrikeClient::kGlyphImage) == 0);
914 REPORTER_ASSERT(reporter, discardableManager->cacheMissCount(SkStrikeClient::kGlyphPath) == 0);
915
916 // Must unlock everything on termination, otherwise valgrind complains about memory leaks.
917 discardableManager->unlockAndDeleteAll();
918}
919
921 sk_sp<SkTypeface> clientTf = nullptr) {
923 font.setTypeface(serverTf);
924 font.setSize(textSize);
925
926 const char* text = ToolUtils::EmojiSample().sampleText;
927 auto blob = SkTextBlob::MakeFromText(text, strlen(text), font);
928 if (clientTf == nullptr) return blob;
929
930 SkSerialProcs s_procs;
931 s_procs.fTypefaceProc = [](SkTypeface*, void* ctx) -> sk_sp<SkData> {
932 return SkData::MakeUninitialized(1u);
933 };
934 auto serialized = blob->serialize(s_procs);
935
936 SkDeserialProcs d_procs;
937 d_procs.fTypefaceCtx = &clientTf;
938 d_procs.fTypefaceProc = [](const void* data, size_t length, void* ctx) -> sk_sp<SkTypeface> {
939 return *(static_cast<sk_sp<SkTypeface>*>(ctx));
940 };
941 return SkTextBlob::Deserialize(serialized->data(), serialized->size(), d_procs);
942}
943
944DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(SkRemoteGlyphCache_TypefaceWithNoPaths,
945 reporter,
946 ctxInfo,
948 auto direct = ctxInfo.directContext();
949 sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>();
950 SkStrikeServer server(discardableManager.get());
951 SkStrikeClient client(discardableManager, false);
952
953 auto serverTypeface = ToolUtils::EmojiSample().typeface;
954 const SkTypefaceID serverTypefaceID = serverTypeface->uniqueID();
955
956 auto props = FindSurfaceProps(direct);
957 std::unique_ptr<SkCanvas> cache_diff_canvas = server.makeAnalysisCanvas(
958 500, 500, props, nullptr, direct->supportsDistanceFieldText(),
959 !direct->priv().caps()->disablePerspectiveSDFText());
960 for (SkScalar textSize : { 70, 180, 270, 340}) {
961 auto serverBlob = MakeEmojiBlob(serverTypeface, textSize);
962
964 cache_diff_canvas->drawTextBlob(serverBlob.get(), 100, 100, paint);
965
966 std::vector<uint8_t> serverStrikeData;
967 server.writeStrikeData(&serverStrikeData);
968 if (!serverStrikeData.empty()) {
970 client.readStrikeData(serverStrikeData.data(),
971 serverStrikeData.size()));
972 }
973 auto clientTypeface = client.retrieveTypefaceUsingServerIDForTest(serverTypefaceID);
974 auto clientBlob = MakeEmojiBlob(serverTypeface, textSize, clientTypeface);
975 REPORTER_ASSERT(reporter, clientBlob);
976
977 RasterBlob(clientBlob, 500, 500, paint, direct);
978 REPORTER_ASSERT(reporter, !discardableManager->hasCacheMiss());
979 discardableManager->resetCacheMissCounts();
980 }
981
982 // Must unlock everything on termination, otherwise valgrind complains about memory leaks.
983 discardableManager->unlockAndDeleteAll();
984}
985
987 public:
989 sk_sp<SkTypeface> serverTf, bool asPaths, SkScalar textSize,
990 sk_sp<SkTypeface> clientTf = nullptr) {
992 font.setTypeface(serverTf);
993 font.setSize(textSize);
994
995 const char* text = "Hel lo";
996 if (asPaths) {
997 font.setupForAsPaths(paint);
998 } else {
999 SkFont font2(font);
1000 font2.setupForAsPaths(paint);
1001 }
1002 auto blob = SkTextBlob::MakeFromText(text, strlen(text), font);
1003 if (clientTf == nullptr) return blob;
1004
1005 SkSerialProcs s_procs;
1006 s_procs.fTypefaceProc = [](SkTypeface*, void* ctx) -> sk_sp<SkData> {
1007 return SkData::MakeUninitialized(1u);
1008 };
1009 auto serialized = blob->serialize(s_procs);
1010
1011 SkDeserialProcs d_procs;
1012 d_procs.fTypefaceCtx = &clientTf;
1013 d_procs.fTypefaceProc = [](const void* data, size_t length, void* ctx) -> sk_sp<SkTypeface> {
1014 return *(static_cast<sk_sp<SkTypeface>*>(ctx));
1015 };
1016 return SkTextBlob::Deserialize(serialized->data(), serialized->size(), d_procs);
1017 }
1018};
1019DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(SkRemoteGlyphCache_TypefaceWithPaths_MaskThenPath,
1020 reporter,
1021 ctxInfo,
1023 auto direct = ctxInfo.directContext();
1024 sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>();
1025 SkStrikeServer server(discardableManager.get());
1026 SkStrikeClient client(discardableManager, true);
1027
1028 auto serverTypeface = ToolUtils::DefaultPortableTypeface();
1029 const SkTypefaceID serverTypefaceID = serverTypeface->uniqueID();
1030
1031 auto props = FindSurfaceProps(direct);
1032 std::unique_ptr<SkCanvas> cache_diff_canvas = server.makeAnalysisCanvas(
1033 500, 500, props, nullptr, direct->supportsDistanceFieldText(),
1034 !direct->priv().caps()->disablePerspectiveSDFText());
1035 SkPaint paint;
1036 using Rgct = SkRemoteGlyphCacheTest;
1037
1038 // Draw from mask out of the strike which provides paths.
1039 {
1040 auto serverBlob = Rgct::MakeNormalBlob(&paint, serverTypeface, true, 64);
1041 cache_diff_canvas->drawTextBlob(serverBlob.get(), 100, 100, paint);
1042 }
1043 // Draw from path out of the strike which provides paths.
1044 {
1045 auto serverBlob = Rgct::MakeNormalBlob(&paint, serverTypeface, false, 440);
1046 cache_diff_canvas->drawTextBlob(serverBlob.get(), 100, 100, paint);
1047 }
1048 std::vector<uint8_t> serverStrikeData;
1049 server.writeStrikeData(&serverStrikeData);
1050 if (!serverStrikeData.empty()) {
1052 client.readStrikeData(serverStrikeData.data(),
1053 serverStrikeData.size()));
1054 }
1055
1056 auto clientTypeface = client.retrieveTypefaceUsingServerIDForTest(serverTypefaceID);
1057
1058 {
1059 auto clientBlob = Rgct::MakeNormalBlob(&paint, serverTypeface, true, 64, clientTypeface);
1060 REPORTER_ASSERT(reporter, clientBlob);
1061
1062 RasterBlob(clientBlob, 100, 100, paint, direct);
1063 REPORTER_ASSERT(reporter, !discardableManager->hasCacheMiss());
1064 discardableManager->resetCacheMissCounts();
1065 }
1066 {
1067 auto clientBlob = Rgct::MakeNormalBlob(&paint, serverTypeface, false, 440, clientTypeface);
1068 REPORTER_ASSERT(reporter, clientBlob);
1069
1070 RasterBlob(clientBlob, 100, 100, paint, direct);
1071 REPORTER_ASSERT(reporter, !discardableManager->hasCacheMiss());
1072 discardableManager->resetCacheMissCounts();
1073 }
1074 // Must unlock everything on termination, otherwise valgrind complains about memory leaks.
1075 discardableManager->unlockAndDeleteAll();
1076}
1077
1078DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(SkRemoteGlyphCache_TypefaceWithPaths_PathThenMask,
1079 reporter,
1080 ctxInfo,
1082 auto direct = ctxInfo.directContext();
1083 sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>();
1084 SkStrikeServer server(discardableManager.get());
1085 SkStrikeClient client(discardableManager, true);
1086
1087 auto serverTypeface = ToolUtils::DefaultPortableTypeface();
1088 const SkTypefaceID serverTypefaceID = serverTypeface->uniqueID();
1089
1090 auto props = FindSurfaceProps(direct);
1091 std::unique_ptr<SkCanvas> cache_diff_canvas = server.makeAnalysisCanvas(
1092 500, 500, props, nullptr, direct->supportsDistanceFieldText(),
1093 !direct->priv().caps()->disablePerspectiveSDFText());
1094 SkPaint paint;
1095 using Rgct = SkRemoteGlyphCacheTest;
1096
1097 // Draw from path out of the strike which provides paths.
1098 {
1099 auto serverBlob = Rgct::MakeNormalBlob(&paint, serverTypeface, false, 440);
1100 cache_diff_canvas->drawTextBlob(serverBlob.get(), 100, 100, paint);
1101 }
1102 // Draw from mask out of the strike which provides paths.
1103 {
1104 auto serverBlob = Rgct::MakeNormalBlob(&paint, serverTypeface, true, 64);
1105 cache_diff_canvas->drawTextBlob(serverBlob.get(), 100, 100, paint);
1106 }
1107 std::vector<uint8_t> serverStrikeData;
1108 server.writeStrikeData(&serverStrikeData);
1109 if (!serverStrikeData.empty()) {
1111 client.readStrikeData(serverStrikeData.data(),
1112 serverStrikeData.size()));
1113 }
1114
1115 auto clientTypeface = client.retrieveTypefaceUsingServerIDForTest(serverTypefaceID);
1116
1117 {
1118 auto clientBlob = Rgct::MakeNormalBlob(&paint, serverTypeface, true, 64, clientTypeface);
1119 REPORTER_ASSERT(reporter, clientBlob);
1120
1121 RasterBlob(clientBlob, 100, 100, paint, direct);
1122 REPORTER_ASSERT(reporter, !discardableManager->hasCacheMiss());
1123 discardableManager->resetCacheMissCounts();
1124 }
1125 {
1126 auto clientBlob = Rgct::MakeNormalBlob(&paint, serverTypeface, false, 440, clientTypeface);
1127 REPORTER_ASSERT(reporter, clientBlob);
1128
1129 RasterBlob(clientBlob, 100, 100, paint, direct);
1130 REPORTER_ASSERT(reporter, !discardableManager->hasCacheMiss());
1131 discardableManager->resetCacheMissCounts();
1132 }
1133 // Must unlock everything on termination, otherwise valgrind complains about memory leaks.
1134 discardableManager->unlockAndDeleteAll();
1135}
1136
1137DEF_TEST(SkTypefaceProxy_Basic_Serial, reporter) {
1138 auto typeface = ToolUtils::CreateTestTypeface("monospace", SkFontStyle());
1139 sk_sp<DiscardableManager> discardableManager = sk_make_sp<DiscardableManager>();
1140 SkTypefaceProxyPrototype srcProto{*typeface};
1141
1142 SkBinaryWriteBuffer writeBuffer({});
1143 srcProto.flatten(writeBuffer);
1144
1145 auto data = writeBuffer.snapshotAsData();
1146 SkReadBuffer readBuffer{data->data(), data->size()};
1147 std::optional<SkTypefaceProxyPrototype> dstProto =
1149 REPORTER_ASSERT(reporter, dstProto.has_value());
1150 auto proxy = sk_make_sp<SkTypefaceProxy>(dstProto.value(), discardableManager, false);
1151 REPORTER_ASSERT(reporter, typeface->uniqueID() == proxy->remoteTypefaceID());
1152 REPORTER_ASSERT(reporter, typeface->uniqueID() != proxy->uniqueID());
1153 REPORTER_ASSERT(reporter, typeface->countGlyphs() == proxy->countGlyphs());
1154 REPORTER_ASSERT(reporter, typeface->fontStyle() == proxy->fontStyle());
1155 REPORTER_ASSERT(reporter, typeface->isFixedPitch() == proxy->isFixedPitch());
1156
1157 // Must be multiple of 4 bytes or the buffer will be invalid.
1158 uint8_t brokenBytes[] = {1, 2, 3, 4, 5, 6, 7, 8};
1159 SkReadBuffer brokenBuffer{std::data(brokenBytes), std::size(brokenBytes)};
1160 std::optional<SkTypefaceProxyPrototype> brokenProto =
1162 REPORTER_ASSERT(reporter, !brokenProto.has_value());
1163}
1164
1165DEF_TEST(SkGraphics_Limits, reporter) {
1166 const auto prev1 = SkGraphics::GetTypefaceCacheCountLimit();
1167
1168 auto prev2 = SkGraphics::SetTypefaceCacheCountLimit(prev1 + 1);
1169 REPORTER_ASSERT(reporter, prev1 == prev2);
1171 REPORTER_ASSERT(reporter, prev2 == prev1 + 1);
1172
1173 SkGraphics::SetTypefaceCacheCountLimit(prev1); // restore orig
1174}
const char * options
static void info(const char *fmt,...) SK_PRINTF_LIKE(1
Definition: DM.cpp:213
sk_bzero(glyphs, sizeof(glyphs))
reporter
Definition: FontMgrTest.cpp:39
@ kPremul_SkAlphaType
pixel components are premultiplied by alpha
Definition: SkAlphaType.h:29
#define SkASSERT(cond)
Definition: SkAssert.h:116
uint32_t SkDiscardableHandleId
uint32_t SkColor
Definition: SkColor.h:37
@ kNormal
glyph outlines modified to improve constrast
@ kUTF8
uses bytes to represent UTF-8 or ASCII
sk_sp< T > sk_ref_sp(T *obj)
Definition: SkRefCnt.h:381
SkBitmap RasterBlobThroughSlug(sk_sp< SkTextBlob > blob, int width, int height, const SkPaint &paint, GrRecordingContext *rContext, const SkMatrix *matrix=nullptr, SkScalar x=0)
DEF_TEST(SkRemoteGlyphCache_StrikeLockingServer, reporter)
SkSurfaceProps FindSurfaceProps(GrRecordingContext *rContext)
sk_sp< SkTextBlob > make_blob_causing_fallback(sk_sp< SkTypeface > targetTf, const SkTypeface *glyphTf, skiatest::Reporter *reporter)
SkBitmap RasterSlug(sk_sp< Slug > slug, int width, int height, const SkPaint &paint, GrRecordingContext *rContext, const SkMatrix *matrix=nullptr, SkScalar x=0)
sktext::gpu::Slug Slug
static void use_padding_options(GrContextOptions *options)
static void compare_blobs(const SkBitmap &expected, const SkBitmap &actual, skiatest::Reporter *reporter, int tolerance=0)
sk_sp< SkTextBlob > MakeEmojiBlob(sk_sp< SkTypeface > serverTf, SkScalar textSize, sk_sp< SkTypeface > clientTf=nullptr)
sk_sp< SkTextBlob > buildTextBlob(sk_sp< SkTypeface > tf, int glyphCount, int textSize=1)
DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(SkRemoteGlyphCache_StrikeSerialization, reporter, ctxInfo, CtsEnforcement::kNever)
sk_sp< SkSurface > MakeSurface(int width, int height, GrRecordingContext *rContext)
DEF_GANESH_TEST_FOR_CONTEXTS(SkRemoteGlyphCache_StrikeSerializationSlug, skgpu::IsRenderingContext, reporter, ctxInfo, use_padding_options, CtsEnforcement::kNever)
SkBitmap RasterBlob(sk_sp< SkTextBlob > blob, int width, int height, const SkPaint &paint, GrRecordingContext *rContext, const SkMatrix *matrix=nullptr, SkScalar x=0)
#define SkIntToScalar(x)
Definition: SkScalar.h:57
uint32_t SkTypefaceID
Definition: SkTypeface.h:38
uint16_t SkGlyphID
Definition: SkTypes.h:179
#define REPORTER_ASSERT(r, cond,...)
Definition: Test.h:286
GLenum type
~DiscardableManager() override=default
const THashSet< SkDiscardableHandleId > & lockedHandles() const
bool isHandleDeleted(SkDiscardableHandleId id) override
bool deleteHandle(SkDiscardableHandleId id) override
void notifyCacheMiss(SkStrikeClient::CacheMissType type, int fontSize) override
int cacheMissCount(uint32_t type)
bool lockHandle(SkDiscardableHandleId id) override
SkDiscardableHandleId handleCount()
SkDiscardableHandleId createHandle() override
SkColor getColor(int x, int y) const
Definition: SkBitmap.h:874
int width() const
Definition: SkBitmap.h:149
int height() const
Definition: SkBitmap.h:158
static sk_sp< SkData > MakeUninitialized(size_t length)
Definition: SkData.cpp:116
static SkScalar ApproximateTransformedTextSize(const SkFont &font, const SkMatrix &matrix, const SkPoint &textLocation)
Definition: SkFont.cpp:366
Definition: SkFont.h:35
int textToGlyphs(const void *text, size_t byteLength, SkTextEncoding encoding, SkGlyphID glyphs[], int maxGlyphCount) const
Definition: SkFont.cpp:181
@ kAntiAlias
may have transparent pixels on glyph edges
static constexpr uint16_t kSkSideTooBigForAtlas
Definition: SkGlyph.h:333
static int SetTypefaceCacheCountLimit(int count)
Definition: SkGraphics.cpp:87
static void PurgeFontCache()
Definition: SkGraphics.cpp:72
static int GetTypefaceCacheCountLimit()
Definition: SkGraphics.cpp:83
static SkMatrix Scale(SkScalar sx, SkScalar sy)
Definition: SkMatrix.h:75
static const SkMatrix & I()
Definition: SkMatrix.cpp:1544
@ kStroke_Style
set to stroke geometry
Definition: SkPaint.h:194
static sk_sp< SkTextBlob > MakeNormalBlob(SkPaint *paint, sk_sp< SkTypeface > serverTf, bool asPaths, SkScalar textSize, sk_sp< SkTypeface > clientTf=nullptr)
SK_SPI bool readStrikeData(const volatile void *memory, size_t memorySize)
sk_sp< SkTypeface > retrieveTypefaceUsingServerIDForTest(SkTypefaceID) const
sk_sp< sktext::gpu::Slug > deserializeSlugForTest(const void *data, size_t size) const
void setMaxEntriesInDescriptorMapForTesting(size_t count)
SK_SPI void writeStrikeData(std::vector< uint8_t > *memory)
SK_API std::unique_ptr< SkCanvas > makeAnalysisCanvas(int width, int height, const SkSurfaceProps &props, sk_sp< SkColorSpace > colorSpace, bool DFTSupport, bool DFTPerspSupport=true)
size_t remoteStrikeMapSizeForTesting() const
static bool ShouldDrawAsPath(const SkPaint &paint, const SkFont &font, const SkMatrix &matrix)
static sk_sp< SkTextBlob > MakeFromText(const void *text, size_t byteLength, const SkFont &font, SkTextEncoding encoding=SkTextEncoding::kUTF8)
Definition: SkTextBlob.cpp:788
static sk_sp< SkTextBlob > Deserialize(const void *data, size_t size, const SkDeserialProcs &procs)
Definition: SkTextBlob.cpp:855
static std::optional< SkTypefaceProxyPrototype > MakeFromBuffer(SkReadBuffer &buffer)
SkTypefaceID remoteTypefaceID() const
SkTypefaceID uniqueID() const
Definition: SkTypeface.h:101
static sk_sp< SkTypeface > Make()
T * get() const
Definition: SkRefCnt.h:303
void add(T item)
Definition: SkTHash.h:592
bool isSDFT(SkScalar approximateDeviceTextSize, const SkPaint &paint, const SkMatrix &matrix) const
Definition: SDFTControl.cpp:69
static sk_sp< Slug > ConvertBlob(SkCanvas *canvas, const SkTextBlob &blob, SkPoint origin, const SkPaint &paint)
Definition: Slug.cpp:20
const Paint & paint
Definition: color_source.cc:38
VkSurfaceKHR surface
Definition: main.cc:49
float SkScalar
Definition: extension.cpp:12
struct MyStruct s
size_t length
std::u16string text
double x
unsigned useCenter Optional< SkMatrix > matrix
Definition: SkRecords.h:258
Optional< SkRect > bounds
Definition: SkRecords.h:189
SK_API sk_sp< SkSurface > RenderTarget(GrRecordingContext *context, skgpu::Budgeted budgeted, const SkImageInfo &imageInfo, int sampleCount, GrSurfaceOrigin surfaceOrigin, const SkSurfaceProps *surfaceProps, bool shouldCreateWithMips=false, bool isProtected=false)
sk_sp< SkTypeface > DefaultPortableTypeface()
SkFont DefaultFont()
sk_sp< SkTypeface > CreateTypefaceFromResource(const char *resource, int ttcIndex)
EmojiTestSample EmojiSample()
sk_sp< SkTypeface > CreateTestTypeface(const char *name, SkFontStyle style)
Definition: bitmap.py:1
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.
bool IsRenderingContext(skgpu::ContextType type)
Definition: ContextType.cpp:88
SIN Vec< N, float > abs(const Vec< N, float > &x)
Definition: SkVx.h:707
int32_t height
int32_t width
SkDeserialTypefaceProc fTypefaceProc
static SkImageInfo Make(int width, int height, SkColorType ct, SkAlphaType at)
static SkRect MakeIWH(int w, int h)
Definition: SkRect.h:623
constexpr float width() const
Definition: SkRect.h:762
static constexpr SkRect MakeWH(float w, float h)
Definition: SkRect.h:609
SkSerialTypefaceProc fTypefaceProc
Definition: SkSerialProcs.h:93
sk_sp< SkTypeface > typeface
Definition: FontToolUtils.h:48
std::shared_ptr< const fml::Mapping > data
Definition: texture_gles.cc:63