• 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 "src/core/SkRemoteGlyphCache.h"
9 
10 #include <bitset>
11 #include <iterator>
12 #include <memory>
13 #include <new>
14 #include <string>
15 #include <tuple>
16 
17 #include "include/core/SkSerialProcs.h"
18 #include "include/core/SkSpan.h"
19 #include "include/core/SkTypeface.h"
20 #include "include/private/SkChecksum.h"
21 #include "include/private/SkTHash.h"
22 #include "src/core/SkDevice.h"
23 #include "src/core/SkDraw.h"
24 #include "src/core/SkEnumerate.h"
25 #include "src/core/SkGlyphRun.h"
26 #include "src/core/SkScalerCache.h"
27 #include "src/core/SkStrikeCache.h"
28 #include "src/core/SkStrikeForGPU.h"
29 #include "src/core/SkTLazy.h"
30 #include "src/core/SkTraceEvent.h"
31 #include "src/core/SkTypeface_remote.h"
32 
33 #if SK_SUPPORT_GPU
34 #include "include/gpu/GrContextOptions.h"
35 #include "src/gpu/GrDrawOpAtlas.h"
36 #include "src/gpu/text/GrSDFTControl.h"
37 #endif
38 
39 // This essentially replaces the font_id used on the RendererSide with the font_id on the GPU side.
auto_descriptor_from_desc(const SkDescriptor * source_desc,SkFontID font_id,SkAutoDescriptor * ad)40 static SkDescriptor* auto_descriptor_from_desc(const SkDescriptor* source_desc,
41                                                SkFontID font_id,
42                                                SkAutoDescriptor* ad) {
43     ad->reset(source_desc->getLength());
44     auto* desc = ad->getDesc();
45 
46     // Rec.
47     {
48         uint32_t size;
49         auto ptr = source_desc->findEntry(kRec_SkDescriptorTag, &size);
50         SkScalerContextRec rec;
51         std::memcpy((void*)&rec, ptr, size);
52         rec.fFontID = font_id;
53         desc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
54     }
55 
56     // Effects.
57     {
58         uint32_t size;
59         auto ptr = source_desc->findEntry(kEffects_SkDescriptorTag, &size);
60         if (ptr) { desc->addEntry(kEffects_SkDescriptorTag, size, ptr); }
61     }
62 
63     desc->computeChecksum();
64     return desc;
65 }
66 
67 // -- Serializer -----------------------------------------------------------------------------------
pad(size_t size,size_t alignment)68 size_t pad(size_t size, size_t alignment) { return (size + (alignment - 1)) & ~(alignment - 1); }
69 
70 // Alignment between x86 and x64 differs for some types, in particular
71 // int64_t and doubles have 4 and 8-byte alignment, respectively.
72 // Be consistent even when writing and reading across different architectures.
73 template<typename T>
serialization_alignment()74 size_t serialization_alignment() {
75   return sizeof(T) == 8 ? 8 : alignof(T);
76 }
77 
78 class Serializer {
79 public:
Serializer(std::vector<uint8_t> * buffer)80     explicit Serializer(std::vector<uint8_t>* buffer) : fBuffer{buffer} {}
81 
82     template <typename T, typename... Args>
emplace(Args &&...args)83     T* emplace(Args&&... args) {
84         auto result = allocate(sizeof(T), serialization_alignment<T>());
85         return new (result) T{std::forward<Args>(args)...};
86     }
87 
88     template <typename T>
write(const T & data)89     void write(const T& data) {
90         T* result = (T*)allocate(sizeof(T), serialization_alignment<T>());
91         memcpy(result, &data, sizeof(T));
92     }
93 
94     template <typename T>
allocate()95     T* allocate() {
96         T* result = (T*)allocate(sizeof(T), serialization_alignment<T>());
97         return result;
98     }
99 
writeDescriptor(const SkDescriptor & desc)100     void writeDescriptor(const SkDescriptor& desc) {
101         write(desc.getLength());
102         auto result = allocate(desc.getLength(), alignof(SkDescriptor));
103         memcpy(result, &desc, desc.getLength());
104     }
105 
allocate(size_t size,size_t alignment)106     void* allocate(size_t size, size_t alignment) {
107         size_t aligned = pad(fBuffer->size(), alignment);
108         fBuffer->resize(aligned + size);
109         return &(*fBuffer)[aligned];
110     }
111 
112 private:
113     std::vector<uint8_t>* fBuffer;
114 };
115 
116 // -- Deserializer -------------------------------------------------------------------------------
117 // Note that the Deserializer is reading untrusted data, we need to guard against invalid data.
118 class Deserializer {
119 public:
Deserializer(const volatile char * memory,size_t memorySize)120     Deserializer(const volatile char* memory, size_t memorySize)
121             : fMemory(memory), fMemorySize(memorySize) {}
122 
123     template <typename T>
read(T * val)124     bool read(T* val) {
125         auto* result = this->ensureAtLeast(sizeof(T), serialization_alignment<T>());
126         if (!result) return false;
127 
128         memcpy(val, const_cast<const char*>(result), sizeof(T));
129         return true;
130     }
131 
readDescriptor(SkAutoDescriptor * ad)132     bool readDescriptor(SkAutoDescriptor* ad) {
133         uint32_t descLength = 0u;
134         if (!read<uint32_t>(&descLength)) return false;
135         if (descLength < sizeof(SkDescriptor)) return false;
136         if (descLength != SkAlign4(descLength)) return false;
137 
138         auto* result = this->ensureAtLeast(descLength, alignof(SkDescriptor));
139         if (!result) return false;
140 
141         ad->reset(descLength);
142         memcpy(ad->getDesc(), const_cast<const char*>(result), descLength);
143 
144         if (ad->getDesc()->getLength() > descLength) return false;
145         return ad->getDesc()->isValid();
146     }
147 
read(size_t size,size_t alignment)148     const volatile void* read(size_t size, size_t alignment) {
149       return this->ensureAtLeast(size, alignment);
150     }
151 
bytesRead() const152     size_t bytesRead() const { return fBytesRead; }
153 
154 private:
ensureAtLeast(size_t size,size_t alignment)155     const volatile char* ensureAtLeast(size_t size, size_t alignment) {
156         size_t padded = pad(fBytesRead, alignment);
157 
158         // Not enough data.
159         if (padded > fMemorySize) return nullptr;
160         if (size > fMemorySize - padded) return nullptr;
161 
162         auto* result = fMemory + padded;
163         fBytesRead = padded + size;
164         return result;
165     }
166 
167     // Note that we read each piece of memory only once to guard against TOCTOU violations.
168     const volatile char* fMemory;
169     size_t fMemorySize;
170     size_t fBytesRead = 0u;
171 };
172 
SkFuzzDeserializeSkDescriptor(sk_sp<SkData> bytes,SkAutoDescriptor * ad)173 bool SkFuzzDeserializeSkDescriptor(sk_sp<SkData> bytes, SkAutoDescriptor* ad) {
174     auto d = Deserializer(reinterpret_cast<const volatile char*>(bytes->data()), bytes->size());
175     return d.readDescriptor(ad);
176 }
177 
178 // Paths use a SkWriter32 which requires 4 byte alignment.
179 static const size_t kPathAlignment  = 4u;
180 
181 // -- StrikeSpec -----------------------------------------------------------------------------------
182 struct StrikeSpec {
183     StrikeSpec() = default;
StrikeSpecStrikeSpec184     StrikeSpec(SkFontID typefaceID_, SkDiscardableHandleId discardableHandleId_)
185             : typefaceID{typefaceID_}, discardableHandleId(discardableHandleId_) {}
186     SkFontID typefaceID = 0u;
187     SkDiscardableHandleId discardableHandleId = 0u;
188     /* desc */
189     /* n X (glyphs ids) */
190 };
191 
192 // Represent a set of x sub-pixel-position glyphs with a glyph id < kMaxGlyphID and
193 // y sub-pxiel-position must be 0. Most sub-pixel-positioned glyphs have been x-axis aligned
194 // forcing the y sub-pixel position to be zero. We can organize the SkPackedGlyphID to check that
195 // the glyph id and the y position == 0 with a single compare in the following way:
196 //    <y-sub-pixel-position>:2 | <glyphid:16> | <x-sub-pixel-position>:2
197 // This organization allows a single check of a packed-id to be:
198 //    packed-id < kMaxGlyphID * possible-x-sub-pixel-positions
199 // where possible-x-sub-pixel-positions == 4.
200 class LowerRangeBitVector {
201 public:
test(SkPackedGlyphID packedID) const202     bool test(SkPackedGlyphID packedID) const {
203         uint32_t bit = packedID.value();
204         return bit < kMaxIndex && fBits.test(bit);
205     }
setIfLower(SkPackedGlyphID packedID)206     void setIfLower(SkPackedGlyphID packedID) {
207         uint32_t bit = packedID.value();
208         if (bit < kMaxIndex) {
209             fBits.set(bit);
210         }
211     }
212 
213 private:
214     using GID = SkPackedGlyphID;
215     static_assert(GID::kSubPixelX < GID::kGlyphID && GID::kGlyphID < GID::kSubPixelY,
216             "SkPackedGlyphID must be organized: sub-y | glyph id | sub-x");
217     inline static constexpr int kMaxGlyphID = 128;
218     inline static constexpr int kMaxIndex = kMaxGlyphID * (1u << GID::kSubPixelPosLen);
219     std::bitset<kMaxIndex> fBits;
220 };
221 
222 // -- MapOps ---------------------------------------------------------------------------------------
223 struct MapOps {
224     size_t operator()(const SkDescriptor* key) const;
225     bool operator()(const SkDescriptor* lhs, const SkDescriptor* rhs) const;
226 };
operator ()(const SkDescriptor * key) const227 size_t MapOps::operator()(const SkDescriptor* key) const {
228     return key->getChecksum();
229 }
230 
operator ()(const SkDescriptor * lhs,const SkDescriptor * rhs) const231 bool MapOps::operator()(const SkDescriptor* lhs, const SkDescriptor* rhs) const {
232     return *lhs == *rhs;
233 }
234 
235 // -- RemoteStrike ----------------------------------------------------------------------------
236 class RemoteStrike final : public SkStrikeForGPU {
237 public:
238     // N.B. RemoteStrike is not valid until ensureScalerContext is called.
239     RemoteStrike(const SkStrikeSpec& strikeSpec,
240                  std::unique_ptr<SkScalerContext> context,
241                  SkDiscardableHandleId discardableHandleId);
242     ~RemoteStrike() override = default;
243 
244     void writePendingGlyphs(Serializer* serializer);
discardableHandleId() const245     SkDiscardableHandleId discardableHandleId() const { return fDiscardableHandleId; }
246 
getDescriptor() const247     const SkDescriptor& getDescriptor() const override {
248         return *fDescriptor.getDesc();
249     }
250 
251     void setStrikeSpec(const SkStrikeSpec& strikeSpec);
252 
roundingSpec() const253     const SkGlyphPositionRoundingSpec& roundingSpec() const override {
254         return fRoundingSpec;
255     }
256 
257     void prepareForMaskDrawing(
258             SkDrawableGlyphBuffer* drawables, SkSourceGlyphBuffer* rejects) override;
259 
260     void prepareForSDFTDrawing(
261             SkDrawableGlyphBuffer* drawables, SkSourceGlyphBuffer* rejects) override;
262 
263     void prepareForPathDrawing(
264             SkDrawableGlyphBuffer* drawables, SkSourceGlyphBuffer* rejects) override;
265 
onAboutToExitScope()266     void onAboutToExitScope() override {}
267 
getUnderlyingStrike() const268     sk_sp<SkStrike> getUnderlyingStrike() const override { return nullptr; }
269 
hasPendingGlyphs() const270     bool hasPendingGlyphs() const {
271         return !fMasksToSend.empty() || !fPathsToSend.empty();
272     }
273 
274     void resetScalerContext();
275 
276 private:
277     template <typename Rejector>
278     void commonMaskLoop(
279             SkDrawableGlyphBuffer* drawables, SkSourceGlyphBuffer* rejects, Rejector&& reject);
280 
281     // Keep track of if the glyph draw has been totally satisfied. It could be that this
282     // strike can not draw the glyph, and it must be rejected to be handled by fallback.
283     // For example, if a glyph has canDrawAsMask sent, then that data is on the GPU, and this
284     // strike totally satisfies this result. If canDrawAsMask is false, then this glyph must be
285     // rejected, and handled by a later stage using a latter strike.
286     struct MaskSummary {
287         static_assert(SkPackedGlyphID::kMaskAll < (1u << 30), "SkPackedGlyphID is too big.");
288         uint32_t packedID:30;
289         uint32_t canDrawAsMask:1;
290         uint32_t canDrawAsSDFT:1;
291     };
292 
293     struct MaskSummaryTraits {
GetKeyRemoteStrike::MaskSummaryTraits294         static SkPackedGlyphID GetKey(MaskSummary summary) {
295             return SkPackedGlyphID{summary.packedID};
296         }
297 
HashRemoteStrike::MaskSummaryTraits298         static uint32_t Hash(SkPackedGlyphID packedID) {
299             return packedID.hash();
300         }
301     };
302 
303     // Same thing as MaskSummary, but for paths.
304     struct PathSummary {
305         constexpr static uint16_t kIsPath = 0;
306         SkGlyphID glyphID;
307         // If drawing glyphID can be done with a path, this is 0, otherwise it is the max
308         // dimension of the glyph.
309         uint16_t maxDimensionOrPath;
310     };
311 
312     struct PathSummaryTraits {
GetKeyRemoteStrike::PathSummaryTraits313         static SkGlyphID GetKey(PathSummary summary) {
314             return summary.glyphID;
315         }
316 
HashRemoteStrike::PathSummaryTraits317         static uint32_t Hash(SkGlyphID packedID) {
318             return SkChecksum::CheapMix(packedID);
319         }
320     };
321 
322     void writeGlyphPath(const SkGlyph& glyph, Serializer* serializer) const;
323     void ensureScalerContext();
324 
325     const SkAutoDescriptor fDescriptor;
326     const SkDiscardableHandleId fDiscardableHandleId;
327 
328     const SkGlyphPositionRoundingSpec fRoundingSpec;
329 
330     // The context built using fDescriptor
331     std::unique_ptr<SkScalerContext> fContext;
332 
333     // fStrikeSpec is set every time getOrCreateCache is called. This allows the code to maintain
334     // the fContext as lazy as possible.
335     const SkStrikeSpec* fStrikeSpec;
336 
337     // Have the metrics been sent for this strike. Only send them once.
338     bool fHaveSentFontMetrics{false};
339 
340     LowerRangeBitVector fSentLowGlyphIDs;
341 
342     // The masks and paths that currently reside in the GPU process.
343     SkTHashTable<MaskSummary, SkPackedGlyphID, MaskSummaryTraits> fSentGlyphs;
344     SkTHashTable<PathSummary, SkGlyphID, PathSummaryTraits> fSentPaths;
345 
346     // The Masks, SDFT Mask, and Paths that need to be sent to the GPU task for the processed
347     // TextBlobs. Cleared after diffs are serialized.
348     std::vector<SkGlyph> fMasksToSend;
349     std::vector<SkGlyph> fPathsToSend;
350 
351     // Alloc for storing bits and pieces of paths, Cleared after diffs are serialized.
352     SkArenaAllocWithReset fPathAlloc{256};
353 };
354 
RemoteStrike(const SkStrikeSpec & strikeSpec,std::unique_ptr<SkScalerContext> context,uint32_t discardableHandleId)355 RemoteStrike::RemoteStrike(
356         const SkStrikeSpec& strikeSpec,
357         std::unique_ptr<SkScalerContext> context,
358         uint32_t discardableHandleId)
359         : fDescriptor{strikeSpec.descriptor()}
360         , fDiscardableHandleId(discardableHandleId)
361         , fRoundingSpec{context->isSubpixel(), context->computeAxisAlignmentForHText()}
362         // N.B. context must come last because it is used above.
363         , fContext{std::move(context)}
364         , fSentLowGlyphIDs{} {
365     SkASSERT(fDescriptor.getDesc() != nullptr);
366     SkASSERT(fContext != nullptr);
367 }
368 
369 // No need to write fForceBW because it is a flag private to SkScalerContext_DW, which will never
370 // be called on the GPU side.
writeGlyph(const SkGlyph & glyph,Serializer * serializer)371 static void writeGlyph(const SkGlyph& glyph, Serializer* serializer) {
372     serializer->write<SkPackedGlyphID>(glyph.getPackedID());
373     serializer->write<float>(glyph.advanceX());
374     serializer->write<float>(glyph.advanceY());
375     serializer->write<uint16_t>(glyph.width());
376     serializer->write<uint16_t>(glyph.height());
377     serializer->write<int16_t>(glyph.top());
378     serializer->write<int16_t>(glyph.left());
379     serializer->write<uint8_t>(glyph.maskFormat());
380 }
381 
writePendingGlyphs(Serializer * serializer)382 void RemoteStrike::writePendingGlyphs(Serializer* serializer) {
383     SkASSERT(this->hasPendingGlyphs());
384 
385     // Write the desc.
386     serializer->emplace<StrikeSpec>(fContext->getTypeface()->uniqueID(), fDiscardableHandleId);
387     serializer->writeDescriptor(*fDescriptor.getDesc());
388 
389     serializer->emplace<bool>(fHaveSentFontMetrics);
390     if (!fHaveSentFontMetrics) {
391         // Write FontMetrics if not sent before.
392         SkFontMetrics fontMetrics;
393         fContext->getFontMetrics(&fontMetrics);
394         serializer->write<SkFontMetrics>(fontMetrics);
395         fHaveSentFontMetrics = true;
396     }
397 
398     // Write mask glyphs
399     serializer->emplace<uint64_t>(fMasksToSend.size());
400     for (SkGlyph& glyph : fMasksToSend) {
401         SkASSERT(SkMask::IsValidFormat(glyph.fMaskFormat));
402 
403         writeGlyph(glyph, serializer);
404         auto imageSize = glyph.imageSize();
405         if (imageSize > 0 && FitsInAtlas(glyph)) {
406             glyph.fImage = serializer->allocate(imageSize, glyph.formatAlignment());
407             fContext->getImage(glyph);
408         }
409     }
410     fMasksToSend.clear();
411 
412     // Write glyphs paths.
413     serializer->emplace<uint64_t>(fPathsToSend.size());
414     for (SkGlyph& glyph : fPathsToSend) {
415         SkASSERT(SkMask::IsValidFormat(glyph.fMaskFormat));
416 
417         writeGlyph(glyph, serializer);
418         writeGlyphPath(glyph, serializer);
419     }
420     fPathsToSend.clear();
421     fPathAlloc.reset();
422 }
423 
ensureScalerContext()424 void RemoteStrike::ensureScalerContext() {
425     if (fContext == nullptr) {
426         fContext = fStrikeSpec->createScalerContext();
427     }
428 }
429 
resetScalerContext()430 void RemoteStrike::resetScalerContext() {
431     fContext = nullptr;
432     fStrikeSpec = nullptr;
433 }
434 
setStrikeSpec(const SkStrikeSpec & strikeSpec)435 void RemoteStrike::setStrikeSpec(const SkStrikeSpec& strikeSpec) {
436     fStrikeSpec = &strikeSpec;
437 }
438 
writeGlyphPath(const SkGlyph & glyph,Serializer * serializer) const439 void RemoteStrike::writeGlyphPath(
440         const SkGlyph& glyph, Serializer* serializer) const {
441     if (glyph.isColor() || glyph.isEmpty()) {
442         serializer->write<uint64_t>(0u);
443         return;
444     }
445 
446     const SkPath* path = glyph.path();
447 
448     if (path == nullptr) {
449         serializer->write<uint64_t>(0u);
450         return;
451     }
452 
453     size_t pathSize = path->writeToMemory(nullptr);
454     serializer->write<uint64_t>(pathSize);
455     path->writeToMemory(serializer->allocate(pathSize, kPathAlignment));
456 }
457 
458 template <typename Rejector>
commonMaskLoop(SkDrawableGlyphBuffer * drawables,SkSourceGlyphBuffer * rejects,Rejector && reject)459 void RemoteStrike::commonMaskLoop(
460         SkDrawableGlyphBuffer* drawables, SkSourceGlyphBuffer* rejects, Rejector&& reject) {
461     drawables->forEachGlyphID(
462             [&](size_t i, SkPackedGlyphID packedID, SkPoint position) {
463                 MaskSummary* summary = fSentGlyphs.find(packedID);
464                 if (summary == nullptr) {
465                     // Put the new SkGlyph in the glyphs to send.
466                     this->ensureScalerContext();
467                     fMasksToSend.emplace_back(fContext->makeGlyph(packedID));
468                     SkGlyph* glyph = &fMasksToSend.back();
469 
470                     MaskSummary newSummary =
471                             {packedID.value(), CanDrawAsMask(*glyph), CanDrawAsSDFT(*glyph)};
472                     summary = fSentGlyphs.set(newSummary);
473                 }
474 
475                 // Reject things that are too big.
476                 if (reject(*summary)) {
477                     rejects->reject(i);
478                 }
479             });
480 }
481 
prepareForMaskDrawing(SkDrawableGlyphBuffer * drawables,SkSourceGlyphBuffer * rejects)482 void RemoteStrike::prepareForMaskDrawing(
483         SkDrawableGlyphBuffer* drawables, SkSourceGlyphBuffer* rejects) {
484     for (auto [i, variant, _] : SkMakeEnumerate(drawables->input())) {
485         SkPackedGlyphID packedID = variant.packedID();
486         if (fSentLowGlyphIDs.test(packedID)) {
487             #ifdef SK_DEBUG
488             MaskSummary* summary = fSentGlyphs.find(packedID);
489             SkASSERT(summary != nullptr);
490             SkASSERT(summary->canDrawAsMask && summary->canDrawAsSDFT);
491             #endif
492             continue;
493         }
494 
495         MaskSummary* summary = fSentGlyphs.find(packedID);
496         if (summary == nullptr) {
497 
498             // Put the new SkGlyph in the glyphs to send.
499             this->ensureScalerContext();
500             fMasksToSend.emplace_back(fContext->makeGlyph(packedID));
501             SkGlyph* glyph = &fMasksToSend.back();
502 
503             MaskSummary newSummary =
504                     {packedID.value(), CanDrawAsMask(*glyph), CanDrawAsSDFT(*glyph)};
505 
506             summary = fSentGlyphs.set(newSummary);
507 
508             if (summary->canDrawAsMask && summary->canDrawAsSDFT) {
509                 fSentLowGlyphIDs.setIfLower(packedID);
510             }
511         }
512 
513         // Reject things that are too big.
514         if (!summary->canDrawAsMask) {
515             rejects->reject(i);
516         }
517     }
518 }
519 
prepareForSDFTDrawing(SkDrawableGlyphBuffer * drawables,SkSourceGlyphBuffer * rejects)520 void RemoteStrike::prepareForSDFTDrawing(
521         SkDrawableGlyphBuffer* drawables, SkSourceGlyphBuffer* rejects) {
522     this->commonMaskLoop(drawables, rejects,
523                          [](MaskSummary summary){return !summary.canDrawAsSDFT;});
524 }
525 
prepareForPathDrawing(SkDrawableGlyphBuffer * drawables,SkSourceGlyphBuffer * rejects)526 void RemoteStrike::prepareForPathDrawing(
527         SkDrawableGlyphBuffer* drawables, SkSourceGlyphBuffer* rejects) {
528     drawables->forEachGlyphID(
529             [&](size_t i, SkPackedGlyphID packedID, SkPoint position) {
530                 SkGlyphID glyphID = packedID.glyphID();
531                 PathSummary* summary = fSentPaths.find(glyphID);
532                 if (summary == nullptr) {
533 
534                     // Put the new SkGlyph in the glyphs to send.
535                     this->ensureScalerContext();
536                     fPathsToSend.emplace_back(fContext->makeGlyph(SkPackedGlyphID{glyphID}));
537                     SkGlyph* glyph = &fPathsToSend.back();
538 
539                     uint16_t maxDimensionOrPath = glyph->maxDimension();
540                     // Only try to get the path if the glyphs is not color.
541                     if (!glyph->isColor() && !glyph->isEmpty()) {
542                         glyph->setPath(&fPathAlloc, fContext.get());
543                         if (glyph->path() != nullptr) {
544                             maxDimensionOrPath = PathSummary::kIsPath;
545                         }
546                     }
547 
548                     PathSummary newSummary = {glyph->getGlyphID(), maxDimensionOrPath};
549                     summary = fSentPaths.set(newSummary);
550                 }
551 
552                 if (summary->maxDimensionOrPath != PathSummary::kIsPath) {
553                     rejects->reject(i, (int)summary->maxDimensionOrPath);
554                 }
555             });
556 }
557 
558 // -- WireTypeface ---------------------------------------------------------------------------------
559 struct WireTypeface {
560     WireTypeface() = default;
WireTypefaceWireTypeface561     WireTypeface(SkFontID typeface_id, int glyph_count, SkFontStyle style,
562                  bool is_fixed, bool needsCurrentColor)
563       : typefaceID(typeface_id), glyphCount(glyph_count), style(style),
564         isFixed(is_fixed), glyphMaskNeedsCurrentColor(needsCurrentColor) {}
565 
566     SkFontID        typefaceID{0};
567     int             glyphCount{0};
568     SkFontStyle     style;
569     bool            isFixed{false};
570     // Used for COLRv0 or COLRv1 fonts that may need the 0xFFFF special palette
571     // index to represent foreground color. This information needs to be on here
572     // to determine how this typeface can be cached.
573     bool            glyphMaskNeedsCurrentColor{false};
574 };
575 
576 // -- SkStrikeServerImpl ---------------------------------------------------------------------------
577 class SkStrikeServerImpl final : public SkStrikeForGPUCacheInterface {
578 public:
579     explicit SkStrikeServerImpl(
580             SkStrikeServer::DiscardableHandleManager* discardableHandleManager);
581 
582     // SkStrikeServer API methods
583     sk_sp<SkData> serializeTypeface(SkTypeface*);
584     void writeStrikeData(std::vector<uint8_t>* memory);
585 
586     SkScopedStrikeForGPU findOrCreateScopedStrike(const SkStrikeSpec& strikeSpec) override;
587 
588     // Methods for testing
589     void setMaxEntriesInDescriptorMapForTesting(size_t count);
590     size_t remoteStrikeMapSizeForTesting() const;
591 
592 private:
593     inline static constexpr size_t kMaxEntriesInDescriptorMap = 2000u;
594 
595     void checkForDeletedEntries();
596 
597     RemoteStrike* getOrCreateCache(const SkStrikeSpec& strikeSpec);
598 
599 
600     using DescToRemoteStrike =
601     std::unordered_map<const SkDescriptor*, std::unique_ptr<RemoteStrike>, MapOps, MapOps>;
602     DescToRemoteStrike fDescToRemoteStrike;
603 
604     SkStrikeServer::DiscardableHandleManager* const fDiscardableHandleManager;
605     SkTHashSet<SkFontID> fCachedTypefaces;
606     size_t fMaxEntriesInDescriptorMap = kMaxEntriesInDescriptorMap;
607 
608     // Cached serialized typefaces.
609     SkTHashMap<SkFontID, sk_sp<SkData>> fSerializedTypefaces;
610 
611     // State cached until the next serialization.
612     SkTHashSet<RemoteStrike*> fRemoteStrikesToSend;
613     std::vector<WireTypeface> fTypefacesToSend;
614 };
615 
SkStrikeServerImpl(SkStrikeServer::DiscardableHandleManager * dhm)616 SkStrikeServerImpl::SkStrikeServerImpl(SkStrikeServer::DiscardableHandleManager* dhm)
617         : fDiscardableHandleManager(dhm) {
618     SkASSERT(fDiscardableHandleManager);
619 }
620 
setMaxEntriesInDescriptorMapForTesting(size_t count)621 void SkStrikeServerImpl::setMaxEntriesInDescriptorMapForTesting(size_t count) {
622     fMaxEntriesInDescriptorMap = count;
623 }
remoteStrikeMapSizeForTesting() const624 size_t SkStrikeServerImpl::remoteStrikeMapSizeForTesting() const {
625     return fDescToRemoteStrike.size();
626 }
627 
serializeTypeface(SkTypeface * tf)628 sk_sp<SkData> SkStrikeServerImpl::serializeTypeface(SkTypeface* tf) {
629     auto* data = fSerializedTypefaces.find(SkTypeface::UniqueID(tf));
630     if (data) {
631         return *data;
632     }
633 
634     WireTypeface wire(SkTypeface::UniqueID(tf), tf->countGlyphs(), tf->fontStyle(),
635                       tf->isFixedPitch(), tf->glyphMaskNeedsCurrentColor());
636     data = fSerializedTypefaces.set(SkTypeface::UniqueID(tf),
637                                     SkData::MakeWithCopy(&wire, sizeof(wire)));
638     return *data;
639 }
640 
writeStrikeData(std::vector<uint8_t> * memory)641 void SkStrikeServerImpl::writeStrikeData(std::vector<uint8_t>* memory) {
642     #if defined(SK_TRACE_GLYPH_RUN_PROCESS)
643         SkString msg;
644         msg.appendf("\nBegin send strike differences\n");
645     #endif
646     size_t strikesToSend = 0;
647     fRemoteStrikesToSend.foreach ([&](RemoteStrike* strike) {
648         if (strike->hasPendingGlyphs()) {
649             strikesToSend++;
650         } else {
651             strike->resetScalerContext();
652         }
653     });
654 
655     if (strikesToSend == 0 && fTypefacesToSend.empty()) {
656         fRemoteStrikesToSend.reset();
657         return;
658     }
659 
660     Serializer serializer(memory);
661     serializer.emplace<uint64_t>(fTypefacesToSend.size());
662     for (const auto& tf : fTypefacesToSend) {
663         serializer.write<WireTypeface>(tf);
664     }
665     fTypefacesToSend.clear();
666 
667     serializer.emplace<uint64_t>(SkTo<uint64_t>(strikesToSend));
668     fRemoteStrikesToSend.foreach (
669 #ifdef SK_DEBUG
670             [&](RemoteStrike* strike) {
671                 if (strike->hasPendingGlyphs()) {
672                     strike->writePendingGlyphs(&serializer);
673                     strike->resetScalerContext();
674                 }
675                 auto it = fDescToRemoteStrike.find(&strike->getDescriptor());
676                 SkASSERT(it != fDescToRemoteStrike.end());
677                 SkASSERT(it->second.get() == strike);
678                 #if defined(SK_TRACE_GLYPH_RUN_PROCESS)
679                     msg.append(strike->getDescriptor().dumpRec());
680                 #endif
681             }
682 
683 #else
684             [&serializer](RemoteStrike* strike) {
685                 if (strike->hasPendingGlyphs()) {
686                     strike->writePendingGlyphs(&serializer);
687                     strike->resetScalerContext();
688                 }
689                 #if defined(SK_TRACE_GLYPH_RUN_PROCESS)
690                     msg.append(strike->getDescriptor().dumpRec());
691                 #endif
692             }
693 #endif
694     );
695     fRemoteStrikesToSend.reset();
696     #if defined(SK_TRACE_GLYPH_RUN_PROCESS)
697         msg.appendf("End send strike differences");
698         SkDebugf("%s\n", msg.c_str());
699     #endif
700 }
701 
findOrCreateScopedStrike(const SkStrikeSpec & strikeSpec)702 SkScopedStrikeForGPU SkStrikeServerImpl::findOrCreateScopedStrike(const SkStrikeSpec& strikeSpec) {
703     return SkScopedStrikeForGPU{this->getOrCreateCache(strikeSpec)};
704 }
705 
checkForDeletedEntries()706 void SkStrikeServerImpl::checkForDeletedEntries() {
707     auto it = fDescToRemoteStrike.begin();
708     while (fDescToRemoteStrike.size() > fMaxEntriesInDescriptorMap &&
709            it != fDescToRemoteStrike.end()) {
710         RemoteStrike* strike = it->second.get();
711         if (fDiscardableHandleManager->isHandleDeleted(strike->discardableHandleId())) {
712             // If we are removing the strike, we better not be trying to send it at the same time.
713             SkASSERT(!fRemoteStrikesToSend.contains(strike));
714             it = fDescToRemoteStrike.erase(it);
715         } else {
716             ++it;
717         }
718     }
719 }
720 
getOrCreateCache(const SkStrikeSpec & strikeSpec)721 RemoteStrike* SkStrikeServerImpl::getOrCreateCache(const SkStrikeSpec& strikeSpec) {
722 
723     // In cases where tracing is turned off, make sure not to get an unused function warning.
724     // Lambdaize the function.
725     TRACE_EVENT1("skia", "RecForDesc", "rec",
726                  TRACE_STR_COPY(
727                          [&strikeSpec](){
728                              auto ptr =
729                                  strikeSpec.descriptor().findEntry(kRec_SkDescriptorTag, nullptr);
730                              SkScalerContextRec rec;
731                              std::memcpy((void*)&rec, ptr, sizeof(rec));
732                              return rec.dump();
733                          }().c_str()
734                  )
735     );
736 
737     auto it = fDescToRemoteStrike.find(&strikeSpec.descriptor());
738     if (it != fDescToRemoteStrike.end()) {
739         // We have processed the RemoteStrike before. Reuse it.
740         RemoteStrike* strike = it->second.get();
741         strike->setStrikeSpec(strikeSpec);
742         if (fRemoteStrikesToSend.contains(strike)) {
743             // Already tracking
744             return strike;
745         }
746 
747         // Strike is in unknown state on GPU. Start tracking strike on GPU by locking it.
748         bool locked = fDiscardableHandleManager->lockHandle(it->second->discardableHandleId());
749         if (locked) {
750             fRemoteStrikesToSend.add(strike);
751             return strike;
752         }
753 
754         fDescToRemoteStrike.erase(it);
755     }
756 
757     const SkTypeface& typeface = strikeSpec.typeface();
758     // Create a new RemoteStrike. Start by processing the typeface.
759     const SkFontID typefaceId = typeface.uniqueID();
760     if (!fCachedTypefaces.contains(typefaceId)) {
761         fCachedTypefaces.add(typefaceId);
762         fTypefacesToSend.emplace_back(typefaceId, typeface.countGlyphs(),
763                                       typeface.fontStyle(),
764                                       typeface.isFixedPitch(),
765                                       typeface.glyphMaskNeedsCurrentColor());
766     }
767 
768     auto context = strikeSpec.createScalerContext();
769     auto newHandle = fDiscardableHandleManager->createHandle();  // Locked on creation
770     auto remoteStrike = std::make_unique<RemoteStrike>(strikeSpec, std::move(context), newHandle);
771     remoteStrike->setStrikeSpec(strikeSpec);
772     auto remoteStrikePtr = remoteStrike.get();
773     fRemoteStrikesToSend.add(remoteStrikePtr);
774     auto d = &remoteStrike->getDescriptor();
775     fDescToRemoteStrike[d] = std::move(remoteStrike);
776 
777     checkForDeletedEntries();
778 
779     return remoteStrikePtr;
780 }
781 
782 // -- GlyphTrackingDevice --------------------------------------------------------------------------
783 class GlyphTrackingDevice final : public SkNoPixelsDevice {
784 public:
GlyphTrackingDevice(const SkISize & dimensions,const SkSurfaceProps & props,SkStrikeServerImpl * server,sk_sp<SkColorSpace> colorSpace,bool DFTSupport)785     GlyphTrackingDevice(
786             const SkISize& dimensions, const SkSurfaceProps& props, SkStrikeServerImpl* server,
787             sk_sp<SkColorSpace> colorSpace, bool DFTSupport)
788             : SkNoPixelsDevice(SkIRect::MakeSize(dimensions), props, std::move(colorSpace))
789             , fStrikeServerImpl(server)
790             , fDFTSupport(DFTSupport)
791             , fPainter{props, kUnknown_SkColorType, imageInfo().colorSpace(), fStrikeServerImpl} {
792         SkASSERT(fStrikeServerImpl != nullptr);
793     }
794 
onCreateDevice(const CreateInfo & cinfo,const SkPaint *)795     SkBaseDevice* onCreateDevice(const CreateInfo& cinfo, const SkPaint*) override {
796         const SkSurfaceProps surfaceProps(this->surfaceProps().flags(), cinfo.fPixelGeometry);
797         return new GlyphTrackingDevice(cinfo.fInfo.dimensions(), surfaceProps, fStrikeServerImpl,
798                                        cinfo.fInfo.refColorSpace(), fDFTSupport);
799     }
800 
801 protected:
onDrawGlyphRunList(const SkGlyphRunList & glyphRunList,const SkPaint & paint)802     void onDrawGlyphRunList(const SkGlyphRunList& glyphRunList, const SkPaint& paint) override {
803         #if SK_SUPPORT_GPU
804         GrContextOptions ctxOptions;
805         GrSDFTControl control =
806                 GrSDFTControl{fDFTSupport,
807                               this->surfaceProps().isUseDeviceIndependentFonts(),
808                               ctxOptions.fMinDistanceFieldFontSize,
809                               ctxOptions.fGlyphsAsPathsFontSize};
810 
811         SkMatrix drawMatrix = this->localToDevice();
812         drawMatrix.preTranslate(glyphRunList.origin().x(), glyphRunList.origin().y());
813         for (auto& glyphRun : glyphRunList) {
814             fPainter.processGlyphRun(glyphRun,
815                                      drawMatrix,
816                                      paint,
817                                      control,
818                                      nullptr,
819                                      "Cache Diff");
820         }
821         #endif  // SK_SUPPORT_GPU
822     }
823 
824 private:
825     SkStrikeServerImpl* const fStrikeServerImpl;
826     const bool fDFTSupport{false};
827     SkGlyphRunListPainter fPainter;
828 };
829 
830 // -- SkStrikeServer -------------------------------------------------------------------------------
SkStrikeServer(DiscardableHandleManager * dhm)831 SkStrikeServer::SkStrikeServer(DiscardableHandleManager* dhm)
832         : fImpl(new SkStrikeServerImpl{dhm}) { }
833 
834 SkStrikeServer::~SkStrikeServer() = default;
835 
makeAnalysisCanvas(int width,int height,const SkSurfaceProps & props,sk_sp<SkColorSpace> colorSpace,bool DFTSupport)836 std::unique_ptr<SkCanvas> SkStrikeServer::makeAnalysisCanvas(int width, int height,
837                                                              const SkSurfaceProps& props,
838                                                              sk_sp<SkColorSpace> colorSpace,
839                                                              bool DFTSupport) {
840     sk_sp<SkBaseDevice> trackingDevice(new GlyphTrackingDevice(SkISize::Make(width, height),
841                                                                props, this->impl(),
842                                                                std::move(colorSpace),
843                                                                DFTSupport));
844     return std::make_unique<SkCanvas>(std::move(trackingDevice));
845 }
846 
serializeTypeface(SkTypeface * tf)847 sk_sp<SkData> SkStrikeServer::serializeTypeface(SkTypeface* tf) {
848     return fImpl->serializeTypeface(tf);
849 }
850 
writeStrikeData(std::vector<uint8_t> * memory)851 void SkStrikeServer::writeStrikeData(std::vector<uint8_t>* memory) {
852     fImpl->writeStrikeData(memory);
853 }
854 
impl()855 SkStrikeServerImpl* SkStrikeServer::impl() { return fImpl.get(); }
856 
setMaxEntriesInDescriptorMapForTesting(size_t count)857 void SkStrikeServer::setMaxEntriesInDescriptorMapForTesting(size_t count) {
858     fImpl->setMaxEntriesInDescriptorMapForTesting(count);
859 }
remoteStrikeMapSizeForTesting() const860 size_t SkStrikeServer::remoteStrikeMapSizeForTesting() const {
861     return fImpl->remoteStrikeMapSizeForTesting();
862 }
863 
864 // -- DiscardableStrikePinner ----------------------------------------------------------------------
865 class DiscardableStrikePinner : public SkStrikePinner {
866 public:
DiscardableStrikePinner(SkDiscardableHandleId discardableHandleId,sk_sp<SkStrikeClient::DiscardableHandleManager> manager)867     DiscardableStrikePinner(SkDiscardableHandleId discardableHandleId,
868                             sk_sp<SkStrikeClient::DiscardableHandleManager> manager)
869             : fDiscardableHandleId(discardableHandleId), fManager(std::move(manager)) {}
870 
871     ~DiscardableStrikePinner() override = default;
canDelete()872     bool canDelete() override { return fManager->deleteHandle(fDiscardableHandleId); }
873 
874 private:
875     const SkDiscardableHandleId fDiscardableHandleId;
876     sk_sp<SkStrikeClient::DiscardableHandleManager> fManager;
877 };
878 
879 // -- SkStrikeClientImpl ---------------------------------------------------------------------------
880 class SkStrikeClientImpl {
881 public:
882     explicit SkStrikeClientImpl(sk_sp<SkStrikeClient::DiscardableHandleManager>,
883                                 bool isLogging = true,
884                                 SkStrikeCache* strikeCache = nullptr);
885 
886     sk_sp<SkTypeface> deserializeTypeface(const void* data, size_t length);
887 
888     bool readStrikeData(const volatile void* memory, size_t memorySize);
889 
890 private:
891     static bool ReadGlyph(SkTLazy<SkGlyph>& glyph, Deserializer* deserializer);
892     sk_sp<SkTypeface> addTypeface(const WireTypeface& wire);
893 
894     SkTHashMap<SkFontID, sk_sp<SkTypeface>> fRemoteFontIdToTypeface;
895     sk_sp<SkStrikeClient::DiscardableHandleManager> fDiscardableHandleManager;
896     SkStrikeCache* const fStrikeCache;
897     const bool fIsLogging;
898 };
899 
SkStrikeClientImpl(sk_sp<SkStrikeClient::DiscardableHandleManager> discardableManager,bool isLogging,SkStrikeCache * strikeCache)900 SkStrikeClientImpl::SkStrikeClientImpl(
901         sk_sp<SkStrikeClient::DiscardableHandleManager>
902         discardableManager,
903         bool isLogging,
904         SkStrikeCache* strikeCache)
905     : fDiscardableHandleManager(std::move(discardableManager)),
906       fStrikeCache{strikeCache ? strikeCache : SkStrikeCache::GlobalStrikeCache()},
907       fIsLogging{isLogging} {}
908 
909 // No need to read fForceBW because it is a flag private to SkScalerContext_DW, which will never
910 // be called on the GPU side.
ReadGlyph(SkTLazy<SkGlyph> & glyph,Deserializer * deserializer)911 bool SkStrikeClientImpl::ReadGlyph(SkTLazy<SkGlyph>& glyph, Deserializer* deserializer) {
912     SkPackedGlyphID glyphID;
913     if (!deserializer->read<SkPackedGlyphID>(&glyphID)) return false;
914     glyph.init(glyphID);
915     if (!deserializer->read<float>(&glyph->fAdvanceX)) return false;
916     if (!deserializer->read<float>(&glyph->fAdvanceY)) return false;
917     if (!deserializer->read<uint16_t>(&glyph->fWidth)) return false;
918     if (!deserializer->read<uint16_t>(&glyph->fHeight)) return false;
919     if (!deserializer->read<int16_t>(&glyph->fTop)) return false;
920     if (!deserializer->read<int16_t>(&glyph->fLeft)) return false;
921     uint8_t maskFormat;
922     if (!deserializer->read<uint8_t>(&maskFormat)) return false;
923     if (!SkMask::IsValidFormat(maskFormat)) return false;
924     glyph->fMaskFormat = static_cast<SkMask::Format>(maskFormat);
925 
926     return true;
927 }
928 
929 #define READ_FAILURE                                                        \
930     {                                                                       \
931         SkDebugf("Bad font data serialization line: %d", __LINE__);         \
932         SkStrikeClient::DiscardableHandleManager::ReadFailureData data = {  \
933                 memorySize,  deserializer.bytesRead(), typefaceSize,        \
934                 strikeCount, glyphImagesCount,         glyphPathsCount};    \
935         fDiscardableHandleManager->notifyReadFailure(data);                 \
936         return false;                                                       \
937     }
938 
readStrikeData(const volatile void * memory,size_t memorySize)939 bool SkStrikeClientImpl::readStrikeData(const volatile void* memory, size_t memorySize) {
940     SkASSERT(memorySize != 0u);
941     Deserializer deserializer(static_cast<const volatile char*>(memory), memorySize);
942 
943     uint64_t typefaceSize = 0;
944     uint64_t strikeCount = 0;
945     uint64_t glyphImagesCount = 0;
946     uint64_t glyphPathsCount = 0;
947 
948     if (!deserializer.read<uint64_t>(&typefaceSize)) READ_FAILURE
949     for (size_t i = 0; i < typefaceSize; ++i) {
950         WireTypeface wire;
951         if (!deserializer.read<WireTypeface>(&wire)) READ_FAILURE
952 
953         // TODO(khushalsagar): The typeface no longer needs a reference to the
954         // SkStrikeClient, since all needed glyphs must have been pushed before
955         // raster.
956         addTypeface(wire);
957     }
958 
959     #if defined(SK_TRACE_GLYPH_RUN_PROCESS)
960         SkString msg;
961         msg.appendf("\nBegin receive strike differences\n");
962     #endif
963 
964     if (!deserializer.read<uint64_t>(&strikeCount)) READ_FAILURE
965 
966     for (size_t i = 0; i < strikeCount; ++i) {
967         StrikeSpec spec;
968         if (!deserializer.read<StrikeSpec>(&spec)) READ_FAILURE
969 
970         SkAutoDescriptor sourceAd;
971         if (!deserializer.readDescriptor(&sourceAd)) READ_FAILURE
972         #if defined(SK_TRACE_GLYPH_RUN_PROCESS)
973             msg.appendf("  Received descriptor:\n%s", sourceAd.getDesc()->dumpRec().c_str());
974         #endif
975 
976         bool fontMetricsInitialized;
977         if (!deserializer.read(&fontMetricsInitialized)) READ_FAILURE
978 
979         SkFontMetrics fontMetrics{};
980         if (!fontMetricsInitialized) {
981             if (!deserializer.read<SkFontMetrics>(&fontMetrics)) READ_FAILURE
982         }
983 
984         // Get the local typeface from remote fontID.
985         auto* tfPtr = fRemoteFontIdToTypeface.find(spec.typefaceID);
986         // Received strikes for a typeface which doesn't exist.
987         if (!tfPtr) READ_FAILURE
988         auto* tf = tfPtr->get();
989 
990         // Replace the ContextRec in the desc from the server to create the client
991         // side descriptor.
992         // TODO: Can we do this in-place and re-compute checksum? Instead of a complete copy.
993         SkAutoDescriptor ad;
994         auto* client_desc = auto_descriptor_from_desc(sourceAd.getDesc(), tf->uniqueID(), &ad);
995 
996         #if defined(SK_TRACE_GLYPH_RUN_PROCESS)
997             msg.appendf("  Mapped descriptor:\n%s", client_desc->dumpRec().c_str());
998         #endif
999         auto strike = fStrikeCache->findStrike(*client_desc);
1000         // Metrics are only sent the first time. If the metrics are not initialized, there must
1001         // be an existing strike.
1002         if (fontMetricsInitialized && strike == nullptr) READ_FAILURE
1003         if (strike == nullptr) {
1004             // Note that we don't need to deserialize the effects since we won't be generating any
1005             // glyphs here anyway, and the desc is still correct since it includes the serialized
1006             // effects.
1007             SkStrikeSpec strikeSpec{*client_desc, *tfPtr};
1008             strike = fStrikeCache->createStrike(
1009                     strikeSpec, &fontMetrics,
1010                     std::make_unique<DiscardableStrikePinner>(
1011                             spec.discardableHandleId, fDiscardableHandleManager));
1012         }
1013 
1014         if (!deserializer.read<uint64_t>(&glyphImagesCount)) READ_FAILURE
1015         for (size_t j = 0; j < glyphImagesCount; j++) {
1016             SkTLazy<SkGlyph> glyph;
1017             if (!ReadGlyph(glyph, &deserializer)) READ_FAILURE
1018 
1019             if (!glyph->isEmpty() && SkStrikeForGPU::FitsInAtlas(*glyph)) {
1020                 const volatile void* image =
1021                         deserializer.read(glyph->imageSize(), glyph->formatAlignment());
1022                 if (!image) READ_FAILURE
1023                 glyph->fImage = (void*)image;
1024             }
1025 
1026             strike->mergeGlyphAndImage(glyph->getPackedID(), *glyph);
1027         }
1028 
1029         if (!deserializer.read<uint64_t>(&glyphPathsCount)) READ_FAILURE
1030         for (size_t j = 0; j < glyphPathsCount; j++) {
1031             SkTLazy<SkGlyph> glyph;
1032             if (!ReadGlyph(glyph, &deserializer)) READ_FAILURE
1033 
1034             SkGlyph* allocatedGlyph = strike->mergeGlyphAndImage(glyph->getPackedID(), *glyph);
1035 
1036             SkPath* pathPtr = nullptr;
1037             SkPath path;
1038             uint64_t pathSize = 0u;
1039             if (!deserializer.read<uint64_t>(&pathSize)) READ_FAILURE
1040 
1041             if (pathSize > 0) {
1042                 auto* pathData = deserializer.read(pathSize, kPathAlignment);
1043                 if (!pathData) READ_FAILURE
1044                 if (!path.readFromMemory(const_cast<const void*>(pathData), pathSize)) READ_FAILURE
1045                 pathPtr = &path;
1046             }
1047 
1048             strike->mergePath(allocatedGlyph, pathPtr);
1049         }
1050     }
1051 
1052 #if defined(SK_TRACE_GLYPH_RUN_PROCESS)
1053     msg.appendf("End receive strike differences");
1054     SkDebugf("%s\n", msg.c_str());
1055 #endif
1056 
1057     return true;
1058 }
1059 
deserializeTypeface(const void * buf,size_t len)1060 sk_sp<SkTypeface> SkStrikeClientImpl::deserializeTypeface(const void* buf, size_t len) {
1061     WireTypeface wire;
1062     if (len != sizeof(wire)) return nullptr;
1063     memcpy(&wire, buf, sizeof(wire));
1064     return this->addTypeface(wire);
1065 }
1066 
addTypeface(const WireTypeface & wire)1067 sk_sp<SkTypeface> SkStrikeClientImpl::addTypeface(const WireTypeface& wire) {
1068     auto* typeface = fRemoteFontIdToTypeface.find(wire.typefaceID);
1069     if (typeface) return *typeface;
1070 
1071     auto newTypeface = sk_make_sp<SkTypefaceProxy>(
1072             wire.typefaceID, wire.glyphCount, wire.style, wire.isFixed,
1073             wire.glyphMaskNeedsCurrentColor, fDiscardableHandleManager, fIsLogging);
1074     fRemoteFontIdToTypeface.set(wire.typefaceID, newTypeface);
1075     return std::move(newTypeface);
1076 }
1077 
1078 // SkStrikeClient ----------------------------------------------------------------------------------
SkStrikeClient(sk_sp<DiscardableHandleManager> discardableManager,bool isLogging,SkStrikeCache * strikeCache)1079 SkStrikeClient::SkStrikeClient(sk_sp<DiscardableHandleManager> discardableManager,
1080                                bool isLogging,
1081                                SkStrikeCache* strikeCache)
1082        : fImpl{new SkStrikeClientImpl{std::move(discardableManager), isLogging, strikeCache}} {}
1083 
1084 SkStrikeClient::~SkStrikeClient() = default;
1085 
readStrikeData(const volatile void * memory,size_t memorySize)1086 bool SkStrikeClient::readStrikeData(const volatile void* memory, size_t memorySize) {
1087     return fImpl->readStrikeData(memory, memorySize);
1088 }
1089 
deserializeTypeface(const void * buf,size_t len)1090 sk_sp<SkTypeface> SkStrikeClient::deserializeTypeface(const void* buf, size_t len) {
1091     return fImpl->deserializeTypeface(buf, len);
1092 }
1093