Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
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);
167 font.setEdging(SkFont::Edging::kAntiAlias);
168 font.setSubpixel(true);
169
170 SkTextBlobBuilder builder;
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
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
716 SkTextBlobBuilder builder;
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.
838 SkMatrix matrix = SkMatrix::Scale(16, 16);
840 direct->priv().asRecordingContext()->priv().getSDFTControl(true);
841 SkScalar approximateDeviceTextSize = SkFontPriv::ApproximateTransformedTextSize(font, matrix,
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.
904 SkMatrix matrix = SkMatrix::I();
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
reporter
@ 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
static void sk_bzero(void *buffer, size_t size)
Definition SkMalloc.h:105
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)
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)
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)
sk_sp< SkSurface > MakeSurface(int width, int height, GrRecordingContext *rContext)
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 DEF_TEST(name, reporter)
Definition Test.h:312
#define REPORTER_ASSERT(r, cond,...)
Definition Test.h:286
#define DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(name, reporter, context_info, ctsEnforcement)
Definition Test.h:434
#define DEF_GANESH_TEST_FOR_CONTEXTS( name, context_filter, reporter, context_info, options_filter, ctsEnforcement)
Definition Test.h:426
~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
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)
static void PurgeFontCache()
static int GetTypefaceCacheCountLimit()
static SkMatrix Scale(SkScalar sx, SkScalar sy)
Definition SkMatrix.h:75
static const SkMatrix & I()
@ 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)
static sk_sp< SkTextBlob > Deserialize(const void *data, size_t size, const SkDeserialProcs &procs)
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:573
bool isSDFT(SkScalar approximateDeviceTextSize, const SkPaint &paint, const SkMatrix &matrix) const
static sk_sp< Slug > ConvertBlob(SkCanvas *canvas, const SkTextBlob &blob, SkPoint origin, const SkPaint &paint)
Definition Slug.cpp:20
const Paint & paint
VkSurfaceKHR surface
Definition main.cc:49
float SkScalar
Definition extension.cpp:12
struct MyStruct s
size_t length
std::u16string text
double x
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)
bool IsRenderingContext(skgpu::ContextType type)
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
sk_sp< SkTypeface > typeface