• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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