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