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