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