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
8 #include "include/private/chromium/SkChromeRemoteGlyphCache.h"
9
10 #include "include/core/SkDrawable.h"
11 #include "include/core/SkSpan.h"
12 #include "include/core/SkTypeface.h"
13 #include "include/private/SkChecksum.h"
14 #include "src/base/SkTLazy.h"
15 #include "src/core/SkDevice.h"
16 #include "src/core/SkDistanceFieldGen.h"
17 #include "src/core/SkDraw.h"
18 #include "src/core/SkEnumerate.h"
19 #include "src/core/SkGlyph.h"
20 #include "src/core/SkReadBuffer.h"
21 #include "src/core/SkStrike.h"
22 #include "src/core/SkStrikeCache.h"
23 #include "src/core/SkTHash.h"
24 #include "src/core/SkTraceEvent.h"
25 #include "src/core/SkTypeface_remote.h"
26 #include "src/text/GlyphRun.h"
27 #include "src/text/StrikeForGPU.h"
28
29 #include <algorithm>
30 #include <bitset>
31 #include <iterator>
32 #include <memory>
33 #include <new>
34 #include <string>
35 #include <tuple>
36 #include <unordered_map>
37
38 #if defined(SK_GANESH)
39 #include "include/gpu/GrContextOptions.h"
40 #include "src/gpu/ganesh/GrDrawOpAtlas.h"
41 #include "src/text/gpu/SDFTControl.h"
42 #include "src/text/gpu/SubRunAllocator.h"
43 #include "src/text/gpu/SubRunContainer.h"
44 #include "src/text/gpu/TextBlob.h"
45 #endif
46
47 using namespace sktext;
48 using namespace sktext::gpu;
49 using namespace skglyph;
50
51 namespace {
52 // -- Serializer -----------------------------------------------------------------------------------
pad(size_t size,size_t alignment)53 size_t pad(size_t size, size_t alignment) { return (size + (alignment - 1)) & ~(alignment - 1); }
54
55 // Alignment between x86 and x64 differs for some types, in particular
56 // int64_t and doubles have 4 and 8-byte alignment, respectively.
57 // Be consistent even when writing and reading across different architectures.
58 template<typename T>
serialization_alignment()59 size_t serialization_alignment() {
60 return sizeof(T) == 8 ? 8 : alignof(T);
61 }
62
63 class Serializer {
64 public:
Serializer(std::vector<uint8_t> * buffer)65 explicit Serializer(std::vector<uint8_t>* buffer) : fBuffer{buffer} {}
66
67 template <typename T, typename... Args>
emplace(Args &&...args)68 T* emplace(Args&&... args) {
69 auto result = this->allocate(sizeof(T), serialization_alignment<T>());
70 return new (result) T{std::forward<Args>(args)...};
71 }
72
73 template <typename T>
write(const T & data)74 void write(const T& data) {
75 T* result = (T*)this->allocate(sizeof(T), serialization_alignment<T>());
76 memcpy(result, &data, sizeof(T));
77 }
78
writeDescriptor(const SkDescriptor & desc)79 void writeDescriptor(const SkDescriptor& desc) {
80 write(desc.getLength());
81 auto result = this->allocate(desc.getLength(), alignof(SkDescriptor));
82 memcpy(result, &desc, desc.getLength());
83 }
84
allocate(size_t size,size_t alignment)85 void* allocate(size_t size, size_t alignment) {
86 size_t aligned = pad(fBuffer->size(), alignment);
87 fBuffer->resize(aligned + size);
88 return &(*fBuffer)[aligned];
89 }
90
91 private:
92 std::vector<uint8_t>* fBuffer;
93 };
94
95 // -- Deserializer -------------------------------------------------------------------------------
96 // Note that the Deserializer is reading untrusted data, we need to guard against invalid data.
97 class Deserializer {
98 public:
Deserializer(const volatile char * memory,size_t memorySize)99 Deserializer(const volatile char* memory, size_t memorySize)
100 : fMemory(memory), fMemorySize(memorySize) {}
101
102 template <typename T>
read(T * val)103 bool read(T* val) {
104 auto* result = this->ensureAtLeast(sizeof(T), serialization_alignment<T>());
105 if (!result) return false;
106
107 memcpy(val, const_cast<const char*>(result), sizeof(T));
108 return true;
109 }
110
readDescriptor(SkAutoDescriptor * ad)111 bool readDescriptor(SkAutoDescriptor* ad) {
112 uint32_t descLength = 0u;
113 if (!this->read<uint32_t>(&descLength)) return false;
114
115 auto* underlyingBuffer = this->ensureAtLeast(descLength, alignof(SkDescriptor));
116 if (!underlyingBuffer) return false;
117 SkReadBuffer buffer((void*)underlyingBuffer, descLength);
118 auto autoDescriptor = SkAutoDescriptor::MakeFromBuffer(buffer);
119 if (!autoDescriptor.has_value()) { return false; }
120
121 *ad = std::move(*autoDescriptor);
122 return true;
123 }
124
read(size_t size,size_t alignment)125 const volatile void* read(size_t size, size_t alignment) {
126 return this->ensureAtLeast(size, alignment);
127 }
128
bytesRead() const129 size_t bytesRead() const { return fBytesRead; }
130
131 private:
ensureAtLeast(size_t size,size_t alignment)132 const volatile char* ensureAtLeast(size_t size, size_t alignment) {
133 size_t padded = pad(fBytesRead, alignment);
134
135 // Not enough data.
136 if (padded > fMemorySize) return nullptr;
137 if (size > fMemorySize - padded) return nullptr;
138
139 auto* result = fMemory + padded;
140 fBytesRead = padded + size;
141 return result;
142 }
143
144 // Note that we read each piece of memory only once to guard against TOCTOU violations.
145 const volatile char* fMemory;
146 size_t fMemorySize;
147 size_t fBytesRead = 0u;
148 };
149
150 // Paths use a SkWriter32 which requires 4 byte alignment.
151 static const size_t kPathAlignment = 4u;
152 static const size_t kDrawableAlignment = 8u;
153
154 // -- StrikeSpec -----------------------------------------------------------------------------------
155 struct StrikeSpec {
156 StrikeSpec() = default;
StrikeSpec__anon4624ab0d0111::StrikeSpec157 StrikeSpec(SkTypefaceID typefaceID, SkDiscardableHandleId discardableHandleId)
158 : fTypefaceID{typefaceID}, fDiscardableHandleId(discardableHandleId) {}
159 SkTypefaceID fTypefaceID = 0u;
160 SkDiscardableHandleId fDiscardableHandleId = 0u;
161 };
162
163 // -- RemoteStrike ----------------------------------------------------------------------------
164 class RemoteStrike final : public sktext::StrikeForGPU {
165 public:
166 // N.B. RemoteStrike is not valid until ensureScalerContext is called.
167 RemoteStrike(const SkStrikeSpec& strikeSpec,
168 std::unique_ptr<SkScalerContext> context,
169 SkDiscardableHandleId discardableHandleId);
170 ~RemoteStrike() override = default;
171
lock()172 void lock() override {}
unlock()173 void unlock() override {}
174 SkGlyphDigest digestFor(skglyph::ActionType, SkPackedGlyphID) override;
prepareForImage(SkGlyph * glyph)175 bool prepareForImage(SkGlyph* glyph) override {
176 this->ensureScalerContext();
177 glyph->setImage(&fAlloc, fContext.get());
178 return glyph->image() != nullptr;
179 }
prepareForPath(SkGlyph * glyph)180 bool prepareForPath(SkGlyph* glyph) override {
181 this->ensureScalerContext();
182 glyph->setPath(&fAlloc, fContext.get());
183 return glyph->path() != nullptr;
184 }
prepareForDrawable(SkGlyph * glyph)185 bool prepareForDrawable(SkGlyph* glyph) override {
186 this->ensureScalerContext();
187 glyph->setDrawable(&fAlloc, fContext.get());
188 return glyph->drawable() != nullptr;
189 }
190
191 void writePendingGlyphs(Serializer* serializer);
discardableHandleId() const192 SkDiscardableHandleId discardableHandleId() const { return fDiscardableHandleId; }
193
getDescriptor() const194 const SkDescriptor& getDescriptor() const override {
195 return *fDescriptor.getDesc();
196 }
197
198 void setStrikeSpec(const SkStrikeSpec& strikeSpec);
199
roundingSpec() const200 const SkGlyphPositionRoundingSpec& roundingSpec() const override {
201 return fRoundingSpec;
202 }
203
204 sktext::SkStrikePromise strikePromise() override;
205
hasPendingGlyphs() const206 bool hasPendingGlyphs() const {
207 return !fMasksToSend.empty() || !fPathsToSend.empty() || !fDrawablesToSend.empty();
208 }
209
210 void resetScalerContext();
211
212 private:
213 void writeGlyphPath(const SkGlyph& glyph, Serializer* serializer) const;
214 void writeGlyphDrawable(const SkGlyph& glyph, Serializer* serializer) const;
215 void ensureScalerContext();
216
217 const SkAutoDescriptor fDescriptor;
218 const SkDiscardableHandleId fDiscardableHandleId;
219
220 const SkGlyphPositionRoundingSpec fRoundingSpec;
221
222 // The context built using fDescriptor
223 std::unique_ptr<SkScalerContext> fContext;
224
225 // fStrikeSpec is set every time getOrCreateCache is called. This allows the code to maintain
226 // the fContext as lazy as possible.
227 const SkStrikeSpec* fStrikeSpec;
228
229 // Have the metrics been sent for this strike. Only send them once.
230 bool fHaveSentFontMetrics{false};
231
232 // The masks and paths that currently reside in the GPU process.
233 SkTHashMap<SkPackedGlyphID, SkGlyphDigest, SkPackedGlyphID::Hash> fSentGlyphs;
234
235 // The Masks, SDFT Mask, and Paths that need to be sent to the GPU task for the processed
236 // TextBlobs. Cleared after diffs are serialized.
237 std::vector<SkGlyph> fMasksToSend;
238 std::vector<SkGlyph> fPathsToSend;
239 std::vector<SkGlyph> fDrawablesToSend;
240
241 // Alloc for storing bits and pieces of paths and drawables, Cleared after diffs are serialized.
242 SkArenaAllocWithReset fAlloc{256};
243 };
244
RemoteStrike(const SkStrikeSpec & strikeSpec,std::unique_ptr<SkScalerContext> context,uint32_t discardableHandleId)245 RemoteStrike::RemoteStrike(
246 const SkStrikeSpec& strikeSpec,
247 std::unique_ptr<SkScalerContext> context,
248 uint32_t discardableHandleId)
249 : fDescriptor{strikeSpec.descriptor()}
250 , fDiscardableHandleId(discardableHandleId)
251 , fRoundingSpec{context->isSubpixel(), context->computeAxisAlignmentForHText()}
252 // N.B. context must come last because it is used above.
253 , fContext{std::move(context)} {
254 SkASSERT(fDescriptor.getDesc() != nullptr);
255 SkASSERT(fContext != nullptr);
256 }
257
258 // No need to write fScalerContextBits because any needed image is already generated.
write_glyph(const SkGlyph & glyph,Serializer * serializer)259 void write_glyph(const SkGlyph& glyph, Serializer* serializer) {
260 serializer->write<SkPackedGlyphID>(glyph.getPackedID());
261 serializer->write<float>(glyph.advanceX());
262 serializer->write<float>(glyph.advanceY());
263 serializer->write<uint16_t>(glyph.width());
264 serializer->write<uint16_t>(glyph.height());
265 serializer->write<int16_t>(glyph.top());
266 serializer->write<int16_t>(glyph.left());
267 serializer->write<uint8_t>(glyph.maskFormat());
268 }
269
writePendingGlyphs(Serializer * serializer)270 void RemoteStrike::writePendingGlyphs(Serializer* serializer) {
271 SkASSERT(this->hasPendingGlyphs());
272
273 // Write the desc.
274 serializer->emplace<StrikeSpec>(fContext->getTypeface()->uniqueID(), fDiscardableHandleId);
275 serializer->writeDescriptor(*fDescriptor.getDesc());
276
277 serializer->emplace<bool>(fHaveSentFontMetrics);
278 if (!fHaveSentFontMetrics) {
279 // Write FontMetrics if not sent before.
280 SkFontMetrics fontMetrics;
281 fContext->getFontMetrics(&fontMetrics);
282 serializer->write<SkFontMetrics>(fontMetrics);
283 fHaveSentFontMetrics = true;
284 }
285
286 // Write mask glyphs
287 serializer->emplace<uint64_t>(fMasksToSend.size());
288 for (SkGlyph& glyph : fMasksToSend) {
289 SkASSERT(SkMask::IsValidFormat(glyph.maskFormat()));
290
291 write_glyph(glyph, serializer);
292 auto imageSize = glyph.imageSize();
293 if (imageSize > 0 && SkGlyphDigest::FitsInAtlas(glyph)) {
294 glyph.setImage(serializer->allocate(imageSize, glyph.formatAlignment()));
295 fContext->getImage(glyph);
296 }
297 }
298 fMasksToSend.clear();
299
300 // Write glyphs paths.
301 serializer->emplace<uint64_t>(fPathsToSend.size());
302 for (SkGlyph& glyph : fPathsToSend) {
303 SkASSERT(SkMask::IsValidFormat(glyph.maskFormat()));
304
305 write_glyph(glyph, serializer);
306 this->writeGlyphPath(glyph, serializer);
307 }
308 fPathsToSend.clear();
309
310 // Write glyphs drawables.
311 serializer->emplace<uint64_t>(fDrawablesToSend.size());
312 for (SkGlyph& glyph : fDrawablesToSend) {
313 SkASSERT(SkMask::IsValidFormat(glyph.maskFormat()));
314
315 write_glyph(glyph, serializer);
316 writeGlyphDrawable(glyph, serializer);
317 }
318 fDrawablesToSend.clear();
319 fAlloc.reset();
320 }
321
ensureScalerContext()322 void RemoteStrike::ensureScalerContext() {
323 if (fContext == nullptr) {
324 fContext = fStrikeSpec->createScalerContext();
325 }
326 }
327
resetScalerContext()328 void RemoteStrike::resetScalerContext() {
329 fContext = nullptr;
330 fStrikeSpec = nullptr;
331 }
332
setStrikeSpec(const SkStrikeSpec & strikeSpec)333 void RemoteStrike::setStrikeSpec(const SkStrikeSpec& strikeSpec) {
334 fStrikeSpec = &strikeSpec;
335 }
336
writeGlyphPath(const SkGlyph & glyph,Serializer * serializer) const337 void RemoteStrike::writeGlyphPath(const SkGlyph& glyph, Serializer* serializer) const {
338 if (glyph.isEmpty()) {
339 serializer->write<uint64_t>(0u);
340 return;
341 }
342
343 const SkPath* path = glyph.path();
344
345 if (path == nullptr) {
346 serializer->write<uint64_t>(0u);
347 return;
348 }
349
350 size_t pathSize = path->writeToMemory(nullptr);
351 serializer->write<uint64_t>(pathSize);
352 path->writeToMemory(serializer->allocate(pathSize, kPathAlignment));
353
354 serializer->write<bool>(glyph.pathIsHairline());
355 }
356
writeGlyphDrawable(const SkGlyph & glyph,Serializer * serializer) const357 void RemoteStrike::writeGlyphDrawable(const SkGlyph& glyph, Serializer* serializer) const {
358 if (glyph.isEmpty()) {
359 serializer->write<uint64_t>(0u);
360 return;
361 }
362
363 SkDrawable* drawable = glyph.drawable();
364
365 if (drawable == nullptr) {
366 serializer->write<uint64_t>(0u);
367 return;
368 }
369
370 sk_sp<SkPicture> picture(drawable->newPictureSnapshot());
371 sk_sp<SkData> data = picture->serialize();
372 serializer->write<uint64_t>(data->size());
373 memcpy(serializer->allocate(data->size(), kDrawableAlignment), data->data(), data->size());
374 }
375
digestFor(ActionType actionType,SkPackedGlyphID packedGlyphID)376 SkGlyphDigest RemoteStrike::digestFor(ActionType actionType, SkPackedGlyphID packedGlyphID) {
377 SkGlyphDigest* digestPtr = fSentGlyphs.find(packedGlyphID);
378 if (digestPtr != nullptr && digestPtr->actionFor(actionType) != GlyphAction::kUnset) {
379 return *digestPtr;
380 }
381
382 SkGlyph* glyph;
383 this->ensureScalerContext();
384 switch (actionType) {
385 case kPath: {
386 fPathsToSend.emplace_back(fContext->makeGlyph(packedGlyphID, &fAlloc));
387 glyph = &fPathsToSend.back();
388 break;
389 }
390 case kDrawable: {
391 fDrawablesToSend.emplace_back(fContext->makeGlyph(packedGlyphID, &fAlloc));
392 glyph = &fDrawablesToSend.back();
393 break;
394 }
395 default: {
396 fMasksToSend.emplace_back(fContext->makeGlyph(packedGlyphID, &fAlloc));
397 glyph = &fMasksToSend.back();
398 break;
399 }
400 }
401
402 if (digestPtr == nullptr) {
403 digestPtr = fSentGlyphs.set(packedGlyphID, SkGlyphDigest{0, *glyph});
404 }
405
406 digestPtr->setActionFor(actionType, glyph, this);
407
408 return *digestPtr;
409 }
410
strikePromise()411 sktext::SkStrikePromise RemoteStrike::strikePromise() {
412 return sktext::SkStrikePromise{*this->fStrikeSpec};
413 }
414
415 // -- WireTypeface ---------------------------------------------------------------------------------
416 struct WireTypeface {
417 WireTypeface() = default;
WireTypeface__anon4624ab0d0111::WireTypeface418 WireTypeface(SkTypefaceID typefaceId, int glyphCount, SkFontStyle style,
419 bool isFixed, bool needsCurrentColor)
420 : fTypefaceID(typefaceId), fGlyphCount(glyphCount), fStyle(style),
421 fIsFixed(isFixed), fGlyphMaskNeedsCurrentColor(needsCurrentColor) {}
422
423 SkTypefaceID fTypefaceID{0};
424 int fGlyphCount{0};
425 SkFontStyle fStyle;
426 bool fIsFixed{false};
427 // Used for COLRv0 or COLRv1 fonts that may need the 0xFFFF special palette
428 // index to represent foreground color. This information needs to be on here
429 // to determine how this typeface can be cached.
430 bool fGlyphMaskNeedsCurrentColor{false};
431 };
432 } // namespace
433
434 // -- SkStrikeServerImpl ---------------------------------------------------------------------------
435 class SkStrikeServerImpl final : public sktext::StrikeForGPUCacheInterface {
436 public:
437 explicit SkStrikeServerImpl(
438 SkStrikeServer::DiscardableHandleManager* discardableHandleManager);
439
440 // SkStrikeServer API methods
441 sk_sp<SkData> serializeTypeface(SkTypeface*);
442 void writeStrikeData(std::vector<uint8_t>* memory);
443
444 sk_sp<sktext::StrikeForGPU> findOrCreateScopedStrike(const SkStrikeSpec& strikeSpec) override;
445
446 // Methods for testing
447 void setMaxEntriesInDescriptorMapForTesting(size_t count);
448 size_t remoteStrikeMapSizeForTesting() const;
449
450 private:
451 inline static constexpr size_t kMaxEntriesInDescriptorMap = 2000u;
452
453 void checkForDeletedEntries();
454
455 sk_sp<RemoteStrike> getOrCreateCache(const SkStrikeSpec& strikeSpec);
456
457 struct MapOps {
operator ()SkStrikeServerImpl::MapOps458 size_t operator()(const SkDescriptor* key) const {
459 return key->getChecksum();
460 }
operator ()SkStrikeServerImpl::MapOps461 bool operator()(const SkDescriptor* lhs, const SkDescriptor* rhs) const {
462 return *lhs == *rhs;
463 }
464 };
465
466 using DescToRemoteStrike =
467 std::unordered_map<const SkDescriptor*, sk_sp<RemoteStrike>, MapOps, MapOps>;
468 DescToRemoteStrike fDescToRemoteStrike;
469
470 SkStrikeServer::DiscardableHandleManager* const fDiscardableHandleManager;
471 SkTHashSet<SkTypefaceID> fCachedTypefaces;
472 size_t fMaxEntriesInDescriptorMap = kMaxEntriesInDescriptorMap;
473
474 // Cached serialized typefaces.
475 SkTHashMap<SkTypefaceID, sk_sp<SkData>> fSerializedTypefaces;
476
477 // State cached until the next serialization.
478 SkTHashSet<RemoteStrike*> fRemoteStrikesToSend;
479 std::vector<WireTypeface> fTypefacesToSend;
480 };
481
SkStrikeServerImpl(SkStrikeServer::DiscardableHandleManager * dhm)482 SkStrikeServerImpl::SkStrikeServerImpl(SkStrikeServer::DiscardableHandleManager* dhm)
483 : fDiscardableHandleManager(dhm) {
484 SkASSERT(fDiscardableHandleManager);
485 }
486
setMaxEntriesInDescriptorMapForTesting(size_t count)487 void SkStrikeServerImpl::setMaxEntriesInDescriptorMapForTesting(size_t count) {
488 fMaxEntriesInDescriptorMap = count;
489 }
remoteStrikeMapSizeForTesting() const490 size_t SkStrikeServerImpl::remoteStrikeMapSizeForTesting() const {
491 return fDescToRemoteStrike.size();
492 }
493
serializeTypeface(SkTypeface * tf)494 sk_sp<SkData> SkStrikeServerImpl::serializeTypeface(SkTypeface* tf) {
495 auto* data = fSerializedTypefaces.find(SkTypeface::UniqueID(tf));
496 if (data) {
497 return *data;
498 }
499
500 WireTypeface wire(SkTypeface::UniqueID(tf), tf->countGlyphs(), tf->fontStyle(),
501 tf->isFixedPitch(), tf->glyphMaskNeedsCurrentColor());
502 data = fSerializedTypefaces.set(SkTypeface::UniqueID(tf),
503 SkData::MakeWithCopy(&wire, sizeof(wire)));
504 return *data;
505 }
506
writeStrikeData(std::vector<uint8_t> * memory)507 void SkStrikeServerImpl::writeStrikeData(std::vector<uint8_t>* memory) {
508 #if defined(SK_TRACE_GLYPH_RUN_PROCESS)
509 SkString msg;
510 msg.appendf("\nBegin send strike differences\n");
511 #endif
512 size_t strikesToSend = 0;
513 fRemoteStrikesToSend.foreach ([&](RemoteStrike* strike) {
514 if (strike->hasPendingGlyphs()) {
515 strikesToSend++;
516 } else {
517 strike->resetScalerContext();
518 }
519 });
520
521 if (strikesToSend == 0 && fTypefacesToSend.empty()) {
522 fRemoteStrikesToSend.reset();
523 return;
524 }
525
526 Serializer serializer(memory);
527 serializer.emplace<uint64_t>(fTypefacesToSend.size());
528 for (const auto& tf : fTypefacesToSend) {
529 serializer.write<WireTypeface>(tf);
530 }
531 fTypefacesToSend.clear();
532
533 serializer.emplace<uint64_t>(SkTo<uint64_t>(strikesToSend));
534 fRemoteStrikesToSend.foreach (
535 [&](RemoteStrike* strike) {
536 if (strike->hasPendingGlyphs()) {
537 strike->writePendingGlyphs(&serializer);
538 strike->resetScalerContext();
539 }
540 #ifdef SK_DEBUG
541 auto it = fDescToRemoteStrike.find(&strike->getDescriptor());
542 SkASSERT(it != fDescToRemoteStrike.end());
543 SkASSERT(it->second.get() == strike);
544 #endif
545 #if defined(SK_TRACE_GLYPH_RUN_PROCESS)
546 msg.append(strike->getDescriptor().dumpRec());
547 #endif
548 }
549 );
550 fRemoteStrikesToSend.reset();
551 #if defined(SK_TRACE_GLYPH_RUN_PROCESS)
552 msg.appendf("End send strike differences");
553 SkDebugf("%s\n", msg.c_str());
554 #endif
555 }
556
findOrCreateScopedStrike(const SkStrikeSpec & strikeSpec)557 sk_sp<StrikeForGPU> SkStrikeServerImpl::findOrCreateScopedStrike(
558 const SkStrikeSpec& strikeSpec) {
559 return this->getOrCreateCache(strikeSpec);
560 }
561
checkForDeletedEntries()562 void SkStrikeServerImpl::checkForDeletedEntries() {
563 auto it = fDescToRemoteStrike.begin();
564 while (fDescToRemoteStrike.size() > fMaxEntriesInDescriptorMap &&
565 it != fDescToRemoteStrike.end()) {
566 RemoteStrike* strike = it->second.get();
567 if (fDiscardableHandleManager->isHandleDeleted(strike->discardableHandleId())) {
568 // If we are trying to send the strike, then do not erase it.
569 if (!fRemoteStrikesToSend.contains(strike)) {
570 // Erase returns the iterator following the removed element.
571 it = fDescToRemoteStrike.erase(it);
572 continue;
573 }
574 }
575 ++it;
576 }
577 }
578
getOrCreateCache(const SkStrikeSpec & strikeSpec)579 sk_sp<RemoteStrike> SkStrikeServerImpl::getOrCreateCache(const SkStrikeSpec& strikeSpec) {
580 // In cases where tracing is turned off, make sure not to get an unused function warning.
581 // Lambdaize the function.
582 TRACE_EVENT1("skia", "RecForDesc", "rec",
583 TRACE_STR_COPY(
584 [&strikeSpec](){
585 auto ptr =
586 strikeSpec.descriptor().findEntry(kRec_SkDescriptorTag, nullptr);
587 SkScalerContextRec rec;
588 std::memcpy((void*)&rec, ptr, sizeof(rec));
589 return rec.dump();
590 }().c_str()
591 )
592 );
593
594 if (auto it = fDescToRemoteStrike.find(&strikeSpec.descriptor());
595 it != fDescToRemoteStrike.end())
596 {
597 // We have processed the RemoteStrike before. Reuse it.
598 sk_sp<RemoteStrike> strike = it->second;
599 strike->setStrikeSpec(strikeSpec);
600 if (fRemoteStrikesToSend.contains(strike.get())) {
601 // Already tracking
602 return strike;
603 }
604
605 // Strike is in unknown state on GPU. Start tracking strike on GPU by locking it.
606 bool locked = fDiscardableHandleManager->lockHandle(it->second->discardableHandleId());
607 if (locked) {
608 fRemoteStrikesToSend.add(strike.get());
609 return strike;
610 }
611
612 // If it wasn't locked, then forget this strike, and build it anew below.
613 fDescToRemoteStrike.erase(it);
614 }
615
616 const SkTypeface& typeface = strikeSpec.typeface();
617 // Create a new RemoteStrike. Start by processing the typeface.
618 const SkTypefaceID typefaceId = typeface.uniqueID();
619 if (!fCachedTypefaces.contains(typefaceId)) {
620 fCachedTypefaces.add(typefaceId);
621 fTypefacesToSend.emplace_back(typefaceId, typeface.countGlyphs(),
622 typeface.fontStyle(),
623 typeface.isFixedPitch(),
624 typeface.glyphMaskNeedsCurrentColor());
625 }
626
627 auto context = strikeSpec.createScalerContext();
628 auto newHandle = fDiscardableHandleManager->createHandle(); // Locked on creation
629 auto remoteStrike = sk_make_sp<RemoteStrike>(strikeSpec, std::move(context), newHandle);
630 remoteStrike->setStrikeSpec(strikeSpec);
631 fRemoteStrikesToSend.add(remoteStrike.get());
632 auto d = &remoteStrike->getDescriptor();
633 fDescToRemoteStrike[d] = remoteStrike;
634
635 checkForDeletedEntries();
636
637 return remoteStrike;
638 }
639
640 // -- GlyphTrackingDevice --------------------------------------------------------------------------
641 #if defined(SK_GANESH)
642 class GlyphTrackingDevice final : public SkNoPixelsDevice {
643 public:
GlyphTrackingDevice(const SkISize & dimensions,const SkSurfaceProps & props,SkStrikeServerImpl * server,sk_sp<SkColorSpace> colorSpace,sktext::gpu::SDFTControl SDFTControl)644 GlyphTrackingDevice(
645 const SkISize& dimensions, const SkSurfaceProps& props, SkStrikeServerImpl* server,
646 sk_sp<SkColorSpace> colorSpace, sktext::gpu::SDFTControl SDFTControl)
647 : SkNoPixelsDevice(SkIRect::MakeSize(dimensions), props, std::move(colorSpace))
648 , fStrikeServerImpl(server)
649 , fSDFTControl(SDFTControl) {
650 SkASSERT(fStrikeServerImpl != nullptr);
651 }
652
onCreateDevice(const CreateInfo & cinfo,const SkPaint *)653 SkBaseDevice* onCreateDevice(const CreateInfo& cinfo, const SkPaint*) override {
654 const SkSurfaceProps surfaceProps(this->surfaceProps().flags(), cinfo.fPixelGeometry);
655 return new GlyphTrackingDevice(cinfo.fInfo.dimensions(), surfaceProps, fStrikeServerImpl,
656 cinfo.fInfo.refColorSpace(), fSDFTControl);
657 }
658
strikeDeviceInfo() const659 SkStrikeDeviceInfo strikeDeviceInfo() const override {
660 return {this->surfaceProps(), this->scalerContextFlags(), &fSDFTControl};
661 }
662
663 protected:
onDrawGlyphRunList(SkCanvas *,const sktext::GlyphRunList & glyphRunList,const SkPaint & initialPaint,const SkPaint & drawingPaint)664 void onDrawGlyphRunList(SkCanvas*,
665 const sktext::GlyphRunList& glyphRunList,
666 const SkPaint& initialPaint,
667 const SkPaint& drawingPaint) override {
668 SkMatrix drawMatrix = this->localToDevice();
669 drawMatrix.preTranslate(glyphRunList.origin().x(), glyphRunList.origin().y());
670
671 // Just ignore the resulting SubRunContainer. Since we're passing in a null SubRunAllocator
672 // no SubRuns will be produced.
673 STSubRunAllocator<sizeof(SubRunContainer), alignof(SubRunContainer)> tempAlloc;
674 auto container = SubRunContainer::MakeInAlloc(glyphRunList,
675 drawMatrix,
676 drawingPaint,
677 this->strikeDeviceInfo(),
678 fStrikeServerImpl,
679 &tempAlloc,
680 SubRunContainer::kStrikeCalculationsOnly,
681 "Cache Diff");
682 // Calculations only. No SubRuns.
683 SkASSERT(container->isEmpty());
684 }
685
convertGlyphRunListToSlug(const sktext::GlyphRunList & glyphRunList,const SkPaint & initialPaint,const SkPaint & drawingPaint)686 sk_sp<sktext::gpu::Slug> convertGlyphRunListToSlug(const sktext::GlyphRunList& glyphRunList,
687 const SkPaint& initialPaint,
688 const SkPaint& drawingPaint) override {
689 // Full matrix for placing glyphs.
690 SkMatrix positionMatrix = this->localToDevice();
691 positionMatrix.preTranslate(glyphRunList.origin().x(), glyphRunList.origin().y());
692
693 #ifdef SK_SUPPORT_LEGACY_SLUG_CONVERT
694 // TODO these two passes can be converted into one when the SkRemoteGlyphCache's strike
695 // cache is fortified with enough information for supporting slug creation.
696
697 // Use the lightweight strike cache provided by SkRemoteGlyphCache through fPainter to do
698 // the analysis. Just ignore the resulting SubRunContainer. Since we're passing in a null
699 // SubRunAllocator no SubRuns will be produced.
700 STSubRunAllocator<sizeof(SubRunContainer), alignof(SubRunContainer)> tempAlloc;
701 auto container = SubRunContainer::MakeInAlloc(glyphRunList,
702 positionMatrix,
703 drawingPaint,
704 this->strikeDeviceInfo(),
705 fStrikeServerImpl,
706 &tempAlloc,
707 SubRunContainer::kStrikeCalculationsOnly,
708 "Convert Slug Analysis");
709 // Calculations only. No SubRuns.
710 SkASSERT(container->isEmpty());
711
712 // Use the glyph strike cache to get actual glyph information.
713 return skgpu::v1::MakeSlug(this->localToDevice(),
714 glyphRunList,
715 initialPaint,
716 drawingPaint,
717 this->strikeDeviceInfo(),
718 SkStrikeCache::GlobalStrikeCache());
719 #else
720 // Use the SkStrikeServer's strike cache to generate the Slug.
721 return skgpu::v1::MakeSlug(this->localToDevice(),
722 glyphRunList,
723 initialPaint,
724 drawingPaint,
725 this->strikeDeviceInfo(),
726 fStrikeServerImpl);
727 #endif
728 }
729
730 private:
731 SkStrikeServerImpl* const fStrikeServerImpl;
732 const sktext::gpu::SDFTControl fSDFTControl;
733 };
734 #endif // defined(SK_GANESH)
735
736 // -- SkStrikeServer -------------------------------------------------------------------------------
SkStrikeServer(DiscardableHandleManager * dhm)737 SkStrikeServer::SkStrikeServer(DiscardableHandleManager* dhm)
738 : fImpl(new SkStrikeServerImpl{dhm}) { }
739
740 SkStrikeServer::~SkStrikeServer() = default;
741
makeAnalysisCanvas(int width,int height,const SkSurfaceProps & props,sk_sp<SkColorSpace> colorSpace,bool DFTSupport,bool DFTPerspSupport)742 std::unique_ptr<SkCanvas> SkStrikeServer::makeAnalysisCanvas(int width, int height,
743 const SkSurfaceProps& props,
744 sk_sp<SkColorSpace> colorSpace,
745 bool DFTSupport,
746 bool DFTPerspSupport) {
747 #if defined(SK_GANESH)
748 GrContextOptions ctxOptions;
749 #if !defined(SK_DISABLE_SDF_TEXT)
750 auto control = sktext::gpu::SDFTControl{DFTSupport,
751 props.isUseDeviceIndependentFonts(),
752 DFTPerspSupport,
753 ctxOptions.fMinDistanceFieldFontSize,
754 ctxOptions.fGlyphsAsPathsFontSize};
755 #else
756 auto control = sktext::gpu::SDFTControl{};
757 #endif
758
759 sk_sp<SkBaseDevice> trackingDevice(new GlyphTrackingDevice(
760 SkISize::Make(width, height),
761 props, this->impl(),
762 std::move(colorSpace),
763 control));
764 #else
765 sk_sp<SkBaseDevice> trackingDevice(new SkNoPixelsDevice(
766 SkIRect::MakeWH(width, height), props, std::move(colorSpace)));
767 #endif
768 return std::make_unique<SkCanvas>(std::move(trackingDevice));
769 }
770
serializeTypeface(SkTypeface * tf)771 sk_sp<SkData> SkStrikeServer::serializeTypeface(SkTypeface* tf) {
772 return fImpl->serializeTypeface(tf);
773 }
774
writeStrikeData(std::vector<uint8_t> * memory)775 void SkStrikeServer::writeStrikeData(std::vector<uint8_t>* memory) {
776 fImpl->writeStrikeData(memory);
777 }
778
impl()779 SkStrikeServerImpl* SkStrikeServer::impl() { return fImpl.get(); }
780
setMaxEntriesInDescriptorMapForTesting(size_t count)781 void SkStrikeServer::setMaxEntriesInDescriptorMapForTesting(size_t count) {
782 fImpl->setMaxEntriesInDescriptorMapForTesting(count);
783 }
remoteStrikeMapSizeForTesting() const784 size_t SkStrikeServer::remoteStrikeMapSizeForTesting() const {
785 return fImpl->remoteStrikeMapSizeForTesting();
786 }
787
788 // -- DiscardableStrikePinner ----------------------------------------------------------------------
789 class DiscardableStrikePinner : public SkStrikePinner {
790 public:
DiscardableStrikePinner(SkDiscardableHandleId discardableHandleId,sk_sp<SkStrikeClient::DiscardableHandleManager> manager)791 DiscardableStrikePinner(SkDiscardableHandleId discardableHandleId,
792 sk_sp<SkStrikeClient::DiscardableHandleManager> manager)
793 : fDiscardableHandleId(discardableHandleId), fManager(std::move(manager)) {}
794
795 ~DiscardableStrikePinner() override = default;
canDelete()796 bool canDelete() override { return fManager->deleteHandle(fDiscardableHandleId); }
assertValid()797 void assertValid() override { fManager->assertHandleValid(fDiscardableHandleId); }
798
799 private:
800 const SkDiscardableHandleId fDiscardableHandleId;
801 sk_sp<SkStrikeClient::DiscardableHandleManager> fManager;
802 };
803
804 // -- SkStrikeClientImpl ---------------------------------------------------------------------------
805 class SkStrikeClientImpl {
806 public:
807 explicit SkStrikeClientImpl(sk_sp<SkStrikeClient::DiscardableHandleManager>,
808 bool isLogging = true,
809 SkStrikeCache* strikeCache = nullptr);
810
811 sk_sp<SkTypeface> deserializeTypeface(const void* data, size_t length);
812
813 bool readStrikeData(const volatile void* memory, size_t memorySize);
814 bool translateTypefaceID(SkAutoDescriptor* descriptor) const;
815
816 private:
817 class PictureBackedGlyphDrawable final : public SkDrawable {
818 public:
PictureBackedGlyphDrawable(sk_sp<SkPicture> self)819 PictureBackedGlyphDrawable(sk_sp<SkPicture> self) : fSelf(std::move(self)) {}
820 private:
821 sk_sp<SkPicture> fSelf;
onGetBounds()822 SkRect onGetBounds() override { return fSelf->cullRect(); }
onApproximateBytesUsed()823 size_t onApproximateBytesUsed() override {
824 return sizeof(PictureBackedGlyphDrawable) + fSelf->approximateBytesUsed();
825 }
onDraw(SkCanvas * canvas)826 void onDraw(SkCanvas* canvas) override { canvas->drawPicture(fSelf); }
827 };
828
829 static bool ReadGlyph(SkTLazy<SkGlyph>& glyph, Deserializer* deserializer);
830 sk_sp<SkTypeface> addTypeface(const WireTypeface& wire);
831
832 SkTHashMap<SkTypefaceID, sk_sp<SkTypeface>> fRemoteTypefaceIdToTypeface;
833 sk_sp<SkStrikeClient::DiscardableHandleManager> fDiscardableHandleManager;
834 SkStrikeCache* const fStrikeCache;
835 const bool fIsLogging;
836 };
837
SkStrikeClientImpl(sk_sp<SkStrikeClient::DiscardableHandleManager> discardableManager,bool isLogging,SkStrikeCache * strikeCache)838 SkStrikeClientImpl::SkStrikeClientImpl(
839 sk_sp<SkStrikeClient::DiscardableHandleManager>
840 discardableManager,
841 bool isLogging,
842 SkStrikeCache* strikeCache)
843 : fDiscardableHandleManager(std::move(discardableManager)),
844 fStrikeCache{strikeCache ? strikeCache : SkStrikeCache::GlobalStrikeCache()},
845 fIsLogging{isLogging} {}
846
847 // No need to write fScalerContextBits because any needed image is already generated.
ReadGlyph(SkTLazy<SkGlyph> & glyph,Deserializer * deserializer)848 bool SkStrikeClientImpl::ReadGlyph(SkTLazy<SkGlyph>& glyph, Deserializer* deserializer) {
849 SkPackedGlyphID glyphID;
850 if (!deserializer->read<SkPackedGlyphID>(&glyphID)) return false;
851 glyph.init(glyphID);
852 if (!deserializer->read<float>(&glyph->fAdvanceX)) return false;
853 if (!deserializer->read<float>(&glyph->fAdvanceY)) return false;
854 if (!deserializer->read<uint16_t>(&glyph->fWidth)) return false;
855 if (!deserializer->read<uint16_t>(&glyph->fHeight)) return false;
856 if (!deserializer->read<int16_t>(&glyph->fTop)) return false;
857 if (!deserializer->read<int16_t>(&glyph->fLeft)) return false;
858 uint8_t maskFormat;
859 if (!deserializer->read<uint8_t>(&maskFormat)) return false;
860 if (!SkMask::IsValidFormat(maskFormat)) return false;
861 glyph->fMaskFormat = static_cast<SkMask::Format>(maskFormat);
862 SkDEBUGCODE(glyph->fAdvancesBoundsFormatAndInitialPathDone = true;)
863
864 return true;
865 }
866 // Change the path count to track the line number of the failing read.
867 // TODO: change __LINE__ back to glyphPathsCount when bug chromium:1287356 is closed.
868 #define READ_FAILURE \
869 { \
870 SkDebugf("Bad font data serialization line: %d", __LINE__); \
871 SkStrikeClient::DiscardableHandleManager::ReadFailureData data = { \
872 memorySize, deserializer.bytesRead(), typefaceSize, \
873 strikeCount, glyphImagesCount, __LINE__}; \
874 fDiscardableHandleManager->notifyReadFailure(data); \
875 return false; \
876 }
877
readStrikeData(const volatile void * memory,size_t memorySize)878 bool SkStrikeClientImpl::readStrikeData(const volatile void* memory, size_t memorySize) {
879 SkASSERT(memorySize != 0u);
880 Deserializer deserializer(static_cast<const volatile char*>(memory), memorySize);
881
882 uint64_t typefaceSize = 0;
883 uint64_t strikeCount = 0;
884 uint64_t glyphImagesCount = 0;
885 uint64_t glyphPathsCount = 0;
886 uint64_t glyphDrawablesCount = 0;
887
888 if (!deserializer.read<uint64_t>(&typefaceSize)) READ_FAILURE
889 for (size_t i = 0; i < typefaceSize; ++i) {
890 WireTypeface wire;
891 if (!deserializer.read<WireTypeface>(&wire)) READ_FAILURE
892
893 this->addTypeface(wire);
894 }
895
896 #if defined(SK_TRACE_GLYPH_RUN_PROCESS)
897 SkString msg;
898 msg.appendf("\nBegin receive strike differences\n");
899 #endif
900
901 if (!deserializer.read<uint64_t>(&strikeCount)) READ_FAILURE
902
903 for (size_t i = 0; i < strikeCount; ++i) {
904 StrikeSpec spec;
905 if (!deserializer.read<StrikeSpec>(&spec)) READ_FAILURE
906
907 SkAutoDescriptor ad;
908 if (!deserializer.readDescriptor(&ad)) READ_FAILURE
909 #if defined(SK_TRACE_GLYPH_RUN_PROCESS)
910 msg.appendf(" Received descriptor:\n%s", ad.getDesc()->dumpRec().c_str());
911 #endif
912
913 bool fontMetricsInitialized;
914 if (!deserializer.read(&fontMetricsInitialized)) READ_FAILURE
915
916 SkFontMetrics fontMetrics{};
917 if (!fontMetricsInitialized) {
918 if (!deserializer.read<SkFontMetrics>(&fontMetrics)) READ_FAILURE
919 }
920
921 // Preflight the TypefaceID before doing the Descriptor translation.
922 auto* tfPtr = fRemoteTypefaceIdToTypeface.find(spec.fTypefaceID);
923 // Received a TypefaceID for a typeface we don't know about.
924 if (!tfPtr) READ_FAILURE
925
926 // Replace the ContextRec in the desc from the server to create the client
927 // side descriptor.
928 if (!this->translateTypefaceID(&ad)) READ_FAILURE
929 SkDescriptor* clientDesc = ad.getDesc();
930
931 #if defined(SK_TRACE_GLYPH_RUN_PROCESS)
932 msg.appendf(" Mapped descriptor:\n%s", clientDesc->dumpRec().c_str());
933 #endif
934 auto strike = fStrikeCache->findStrike(*clientDesc);
935
936 // Make sure strike is pinned
937 if (strike) {
938 strike->verifyPinnedStrike();
939 }
940
941 // Metrics are only sent the first time. If the metrics are not initialized, there must
942 // be an existing strike.
943 if (fontMetricsInitialized && strike == nullptr) READ_FAILURE
944 if (strike == nullptr) {
945 // Note that we don't need to deserialize the effects since we won't be generating any
946 // glyphs here anyway, and the desc is still correct since it includes the serialized
947 // effects.
948 SkStrikeSpec strikeSpec{*clientDesc, *tfPtr};
949 strike = fStrikeCache->createStrike(
950 strikeSpec, &fontMetrics,
951 std::make_unique<DiscardableStrikePinner>(
952 spec.fDiscardableHandleId, fDiscardableHandleManager));
953 }
954
955 if (!deserializer.read<uint64_t>(&glyphImagesCount)) READ_FAILURE
956 for (size_t j = 0; j < glyphImagesCount; j++) {
957 SkTLazy<SkGlyph> glyph;
958 if (!ReadGlyph(glyph, &deserializer)) READ_FAILURE
959
960 if (!glyph->isEmpty() && SkGlyphDigest::FitsInAtlas(*glyph)) {
961 const volatile void* image =
962 deserializer.read(glyph->imageSize(), glyph->formatAlignment());
963 if (!image) READ_FAILURE
964 glyph->fImage = (void*)image;
965 }
966
967 strike->mergeGlyphAndImage(glyph->getPackedID(), *glyph);
968 }
969
970 if (!deserializer.read<uint64_t>(&glyphPathsCount)) READ_FAILURE
971 for (size_t j = 0; j < glyphPathsCount; j++) {
972 SkTLazy<SkGlyph> glyph;
973 if (!ReadGlyph(glyph, &deserializer)) READ_FAILURE
974
975 SkGlyph* allocatedGlyph = strike->mergeGlyphAndImage(glyph->getPackedID(), *glyph);
976
977 SkPath* pathPtr = nullptr;
978 SkPath path;
979 uint64_t pathSize = 0u;
980 bool hairline = false;
981 if (!deserializer.read<uint64_t>(&pathSize)) READ_FAILURE
982
983 if (pathSize > 0) {
984 auto* pathData = deserializer.read(pathSize, kPathAlignment);
985 if (!pathData) READ_FAILURE
986 if (!path.readFromMemory(const_cast<const void*>(pathData), pathSize)) READ_FAILURE
987 pathPtr = &path;
988 if (!deserializer.read<bool>(&hairline)) READ_FAILURE
989 }
990
991 strike->mergePath(allocatedGlyph, pathPtr, hairline);
992 }
993
994 if (!deserializer.read<uint64_t>(&glyphDrawablesCount)) READ_FAILURE
995 for (size_t j = 0; j < glyphDrawablesCount; j++) {
996 SkTLazy<SkGlyph> glyph;
997 if (!ReadGlyph(glyph, &deserializer)) READ_FAILURE
998
999 SkGlyph* allocatedGlyph = strike->mergeGlyphAndImage(glyph->getPackedID(), *glyph);
1000
1001 sk_sp<SkDrawable> drawable;
1002 uint64_t drawableSize = 0u;
1003 if (!deserializer.read<uint64_t>(&drawableSize)) READ_FAILURE
1004
1005 if (drawableSize > 0) {
1006 auto* drawableData = deserializer.read(drawableSize, kDrawableAlignment);
1007 if (!drawableData) READ_FAILURE
1008 sk_sp<SkPicture> picture(SkPicture::MakeFromData(
1009 const_cast<const void*>(drawableData), drawableSize));
1010 if (!picture) READ_FAILURE
1011
1012 drawable = sk_make_sp<PictureBackedGlyphDrawable>(std::move(picture));
1013 }
1014
1015 strike->mergeDrawable(allocatedGlyph, std::move(drawable));
1016 }
1017 }
1018
1019 #if defined(SK_TRACE_GLYPH_RUN_PROCESS)
1020 msg.appendf("End receive strike differences");
1021 SkDebugf("%s\n", msg.c_str());
1022 #endif
1023
1024 return true;
1025 }
1026
translateTypefaceID(SkAutoDescriptor * toChange) const1027 bool SkStrikeClientImpl::translateTypefaceID(SkAutoDescriptor* toChange) const {
1028 SkDescriptor& descriptor = *toChange->getDesc();
1029
1030 // Rewrite the typefaceID in the rec.
1031 {
1032 uint32_t size;
1033 // findEntry returns a const void*, remove the const in order to update in place.
1034 void* ptr = const_cast<void *>(descriptor.findEntry(kRec_SkDescriptorTag, &size));
1035 SkScalerContextRec rec;
1036 std::memcpy((void*)&rec, ptr, size);
1037 // Get the local typeface from remote typefaceID.
1038 auto* tfPtr = fRemoteTypefaceIdToTypeface.find(rec.fTypefaceID);
1039 // Received a strike for a typeface which doesn't exist.
1040 if (!tfPtr) { return false; }
1041 // Update the typeface id to work with the client side.
1042 rec.fTypefaceID = tfPtr->get()->uniqueID();
1043 std::memcpy(ptr, &rec, size);
1044 }
1045
1046 descriptor.computeChecksum();
1047
1048 return true;
1049 }
1050
deserializeTypeface(const void * buf,size_t len)1051 sk_sp<SkTypeface> SkStrikeClientImpl::deserializeTypeface(const void* buf, size_t len) {
1052 WireTypeface wire;
1053 if (len != sizeof(wire)) return nullptr;
1054 memcpy(&wire, buf, sizeof(wire));
1055 return this->addTypeface(wire);
1056 }
1057
addTypeface(const WireTypeface & wire)1058 sk_sp<SkTypeface> SkStrikeClientImpl::addTypeface(const WireTypeface& wire) {
1059 auto* typeface = fRemoteTypefaceIdToTypeface.find(wire.fTypefaceID);
1060 if (typeface) return *typeface;
1061
1062 auto newTypeface = sk_make_sp<SkTypefaceProxy>(
1063 wire.fTypefaceID, wire.fGlyphCount, wire.fStyle, wire.fIsFixed,
1064 wire.fGlyphMaskNeedsCurrentColor, fDiscardableHandleManager, fIsLogging);
1065 fRemoteTypefaceIdToTypeface.set(wire.fTypefaceID, newTypeface);
1066 return std::move(newTypeface);
1067 }
1068
1069 // SkStrikeClient ----------------------------------------------------------------------------------
SkStrikeClient(sk_sp<DiscardableHandleManager> discardableManager,bool isLogging,SkStrikeCache * strikeCache)1070 SkStrikeClient::SkStrikeClient(sk_sp<DiscardableHandleManager> discardableManager,
1071 bool isLogging,
1072 SkStrikeCache* strikeCache)
1073 : fImpl{new SkStrikeClientImpl{std::move(discardableManager), isLogging, strikeCache}} {}
1074
1075 SkStrikeClient::~SkStrikeClient() = default;
1076
readStrikeData(const volatile void * memory,size_t memorySize)1077 bool SkStrikeClient::readStrikeData(const volatile void* memory, size_t memorySize) {
1078 return fImpl->readStrikeData(memory, memorySize);
1079 }
1080
deserializeTypeface(const void * buf,size_t len)1081 sk_sp<SkTypeface> SkStrikeClient::deserializeTypeface(const void* buf, size_t len) {
1082 return fImpl->deserializeTypeface(buf, len);
1083 }
1084
translateTypefaceID(SkAutoDescriptor * descriptor) const1085 bool SkStrikeClient::translateTypefaceID(SkAutoDescriptor* descriptor) const {
1086 return fImpl->translateTypefaceID(descriptor);
1087 }
1088
1089 #if defined(SK_GANESH)
deserializeSlug(const void * data,size_t size) const1090 sk_sp<sktext::gpu::Slug> SkStrikeClient::deserializeSlug(const void* data, size_t size) const {
1091 return sktext::gpu::Slug::Deserialize(data, size, this);
1092 }
1093 #endif // defined(SK_GANESH)
1094