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