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