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 "SkRemoteGlyphCache.h"
9 
10 #include <iterator>
11 #include <memory>
12 #include <new>
13 #include <string>
14 #include <tuple>
15 
16 #include "SkDevice.h"
17 #include "SkDraw.h"
18 #include "SkGlyphRun.h"
19 #include "SkRemoteGlyphCacheImpl.h"
20 #include "SkStrike.h"
21 #include "SkStrikeCache.h"
22 #include "SkTLazy.h"
23 #include "SkTraceEvent.h"
24 #include "SkTypeface_remote.h"
25 
26 #if SK_SUPPORT_GPU
27 #include "GrDrawOpAtlas.h"
28 #include "text/GrTextContext.h"
29 #endif
30 
auto_descriptor_from_desc(const SkDescriptor * source_desc,SkFontID font_id,SkAutoDescriptor * ad)31 static SkDescriptor* auto_descriptor_from_desc(const SkDescriptor* source_desc,
32                                                SkFontID font_id,
33                                                SkAutoDescriptor* ad) {
34     ad->reset(source_desc->getLength());
35     auto* desc = ad->getDesc();
36     desc->init();
37 
38     // Rec.
39     {
40         uint32_t size;
41         auto ptr = source_desc->findEntry(kRec_SkDescriptorTag, &size);
42         SkScalerContextRec rec;
43         std::memcpy(&rec, ptr, size);
44         rec.fFontID = font_id;
45         desc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
46     }
47 
48     // Effects.
49     {
50         uint32_t size;
51         auto ptr = source_desc->findEntry(kEffects_SkDescriptorTag, &size);
52         if (ptr) { desc->addEntry(kEffects_SkDescriptorTag, size, ptr); }
53     }
54 
55     desc->computeChecksum();
56     return desc;
57 }
58 
59 enum DescriptorType : bool { kKey = false, kDevice = true };
create_descriptor(DescriptorType type,const SkPaint & paint,const SkFont & font,const SkMatrix & m,const SkSurfaceProps & props,SkScalerContextFlags flags,SkAutoDescriptor * ad,SkScalerContextEffects * effects)60 static const SkDescriptor* create_descriptor(
61         DescriptorType type, const SkPaint& paint, const SkFont& font, const SkMatrix& m,
62         const SkSurfaceProps& props, SkScalerContextFlags flags,
63         SkAutoDescriptor* ad, SkScalerContextEffects* effects) {
64     SkScalerContextRec deviceRec;
65     bool enableTypefaceFiltering = (type == kDevice);
66     SkScalerContext::MakeRecAndEffects(
67             font, paint, props, flags, m, &deviceRec, effects, enableTypefaceFiltering);
68     return SkScalerContext::AutoDescriptorGivenRecAndEffects(deviceRec, *effects, ad);
69 }
70 
71 // -- Serializer ----------------------------------------------------------------------------------
72 
pad(size_t size,size_t alignment)73 size_t pad(size_t size, size_t alignment) { return (size + (alignment - 1)) & ~(alignment - 1); }
74 
75 class Serializer {
76 public:
Serializer(std::vector<uint8_t> * buffer)77     Serializer(std::vector<uint8_t>* buffer) : fBuffer{buffer} { }
78 
79     template <typename T, typename... Args>
emplace(Args &&...args)80     T* emplace(Args&&... args) {
81         auto result = allocate(sizeof(T), alignof(T));
82         return new (result) T{std::forward<Args>(args)...};
83     }
84 
85     template <typename T>
write(const T & data)86     void write(const T& data) {
87         T* result = (T*)allocate(sizeof(T), alignof(T));
88         memcpy(result, &data, sizeof(T));
89     }
90 
91     template <typename T>
allocate()92     T* allocate() {
93         T* result = (T*)allocate(sizeof(T), alignof(T));
94         return result;
95     }
96 
writeDescriptor(const SkDescriptor & desc)97     void writeDescriptor(const SkDescriptor& desc) {
98         write(desc.getLength());
99         auto result = allocate(desc.getLength(), alignof(SkDescriptor));
100         memcpy(result, &desc, desc.getLength());
101     }
102 
allocate(size_t size,size_t alignment)103     void* allocate(size_t size, size_t alignment) {
104         size_t aligned = pad(fBuffer->size(), alignment);
105         fBuffer->resize(aligned + size);
106         return &(*fBuffer)[aligned];
107     }
108 
109 private:
110     std::vector<uint8_t>* fBuffer;
111 };
112 
113 // -- Deserializer -------------------------------------------------------------------------------
114 // Note that the Deserializer is reading untrusted data, we need to guard against invalid data.
115 class Deserializer {
116 public:
Deserializer(const volatile char * memory,size_t memorySize)117     Deserializer(const volatile char* memory, size_t memorySize)
118             : fMemory(memory), fMemorySize(memorySize) {}
119 
120     template <typename T>
read(T * val)121     bool read(T* val) {
122         auto* result = this->ensureAtLeast(sizeof(T), alignof(T));
123         if (!result) return false;
124 
125         memcpy(val, const_cast<const char*>(result), sizeof(T));
126         return true;
127     }
128 
readDescriptor(SkAutoDescriptor * ad)129     bool readDescriptor(SkAutoDescriptor* ad) {
130         uint32_t desc_length = 0u;
131         if (!read<uint32_t>(&desc_length)) return false;
132 
133         auto* result = this->ensureAtLeast(desc_length, alignof(SkDescriptor));
134         if (!result) return false;
135 
136         ad->reset(desc_length);
137         memcpy(ad->getDesc(), const_cast<const char*>(result), desc_length);
138         return true;
139     }
140 
read(size_t size,size_t alignment)141     const volatile void* read(size_t size, size_t alignment) {
142       return this->ensureAtLeast(size, alignment);
143     }
144 
145 private:
ensureAtLeast(size_t size,size_t alignment)146     const volatile char* ensureAtLeast(size_t size, size_t alignment) {
147         size_t padded = pad(fBytesRead, alignment);
148 
149         // Not enough data
150         if (padded + size > fMemorySize) return nullptr;
151 
152         auto* result = fMemory + padded;
153         fBytesRead = padded + size;
154         return result;
155     }
156 
157     // Note that we read each piece of memory only once to guard against TOCTOU violations.
158     const volatile char* fMemory;
159     size_t fMemorySize;
160     size_t fBytesRead = 0u;
161 };
162 
163 // Paths use a SkWriter32 which requires 4 byte alignment.
164 static const size_t kPathAlignment  = 4u;
165 
read_path(Deserializer * deserializer,SkGlyph * glyph,SkStrike * cache)166 bool read_path(Deserializer* deserializer, SkGlyph* glyph, SkStrike* cache) {
167     uint64_t pathSize = 0u;
168     if (!deserializer->read<uint64_t>(&pathSize)) return false;
169 
170     if (pathSize == 0u) return true;
171 
172     auto* path = deserializer->read(pathSize, kPathAlignment);
173     if (!path) return false;
174 
175     return cache->initializePath(glyph, path, pathSize);
176 }
177 
operator ()(const SkDescriptor * key) const178 size_t SkDescriptorMapOperators::operator()(const SkDescriptor* key) const {
179     return key->getChecksum();
180 }
181 
operator ()(const SkDescriptor * lhs,const SkDescriptor * rhs) const182 bool SkDescriptorMapOperators::operator()(const SkDescriptor* lhs, const SkDescriptor* rhs) const {
183     return *lhs == *rhs;
184 }
185 
186 struct StrikeSpec {
StrikeSpecStrikeSpec187     StrikeSpec() {}
StrikeSpecStrikeSpec188     StrikeSpec(SkFontID typefaceID_, SkDiscardableHandleId discardableHandleId_)
189             : typefaceID{typefaceID_}, discardableHandleId(discardableHandleId_) {}
190     SkFontID typefaceID = 0u;
191     SkDiscardableHandleId discardableHandleId = 0u;
192     /* desc */
193     /* n X (glyphs ids) */
194 };
195 
196 // -- TrackLayerDevice -----------------------------------------------------------------------------
TrackLayerDevice(const SkIRect & bounds,const SkSurfaceProps & props,SkStrikeServer * server,const SkTextBlobCacheDiffCanvas::Settings & settings)197 SkTextBlobCacheDiffCanvas::TrackLayerDevice::TrackLayerDevice(
198         const SkIRect& bounds, const SkSurfaceProps& props, SkStrikeServer* server,
199         const SkTextBlobCacheDiffCanvas::Settings& settings)
200     : SkNoPixelsDevice(bounds, props)
201     , fStrikeServer(server)
202     , fSettings(settings)
203     , fPainter{props, kUnknown_SkColorType, SkScalerContextFlags::kFakeGammaAndBoostContrast} {
204     SkASSERT(fStrikeServer);
205 }
206 
onCreateDevice(const CreateInfo & cinfo,const SkPaint *)207 SkBaseDevice* SkTextBlobCacheDiffCanvas::TrackLayerDevice::onCreateDevice(
208         const CreateInfo& cinfo, const SkPaint*) {
209     const SkSurfaceProps surfaceProps(this->surfaceProps().flags(), cinfo.fPixelGeometry);
210     return new TrackLayerDevice(this->getGlobalBounds(), surfaceProps, fStrikeServer, fSettings);
211 }
212 
drawGlyphRunList(const SkGlyphRunList & glyphRunList)213 void SkTextBlobCacheDiffCanvas::TrackLayerDevice::drawGlyphRunList(
214         const SkGlyphRunList& glyphRunList) {
215     for (auto& glyphRun : glyphRunList) {
216         this->processGlyphRun(glyphRunList.origin(), glyphRun, glyphRunList.paint());
217     }
218 }
219 
220 // -- SkTextBlobCacheDiffCanvas -------------------------------------------------------------------
221 SkTextBlobCacheDiffCanvas::Settings::Settings() = default;
222 
SkTextBlobCacheDiffCanvas(int width,int height,const SkMatrix & deviceMatrix,const SkSurfaceProps & props,SkStrikeServer * strikeServer,Settings settings)223 SkTextBlobCacheDiffCanvas::SkTextBlobCacheDiffCanvas(int width, int height,
224                                                      const SkMatrix& deviceMatrix,
225                                                      const SkSurfaceProps& props,
226                                                      SkStrikeServer* strikeServer,
227                                                      Settings settings)
228         : SkNoDrawCanvas{sk_make_sp<TrackLayerDevice>(SkIRect::MakeWH(width, height), props,
229                                                       strikeServer, settings)} {}
230 
SkTextBlobCacheDiffCanvas(int width,int height,const SkSurfaceProps & props,SkStrikeServer * strikeServer,Settings settings)231 SkTextBlobCacheDiffCanvas::SkTextBlobCacheDiffCanvas(
232         int width, int height, const SkSurfaceProps& props,
233         SkStrikeServer* strikeServer, Settings settings)
234     : SkNoDrawCanvas{sk_make_sp<TrackLayerDevice>(
235             SkIRect::MakeWH(width, height), props, strikeServer, settings)} {}
236 
237 SkTextBlobCacheDiffCanvas::~SkTextBlobCacheDiffCanvas() = default;
238 
getSaveLayerStrategy(const SaveLayerRec & rec)239 SkCanvas::SaveLayerStrategy SkTextBlobCacheDiffCanvas::getSaveLayerStrategy(
240         const SaveLayerRec& rec) {
241     return kFullLayer_SaveLayerStrategy;
242 }
243 
onDoSaveBehind(const SkRect *)244 bool SkTextBlobCacheDiffCanvas::onDoSaveBehind(const SkRect*) {
245     return false;
246 }
247 
onDrawTextBlob(const SkTextBlob * blob,SkScalar x,SkScalar y,const SkPaint & paint)248 void SkTextBlobCacheDiffCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
249                                                const SkPaint& paint) {
250     SkCanvas::onDrawTextBlob(blob, x, y, paint);
251 }
252 
253 struct WireTypeface {
254     WireTypeface() = default;
WireTypefaceWireTypeface255     WireTypeface(SkFontID typeface_id, int glyph_count, SkFontStyle style, bool is_fixed)
256             : typefaceID(typeface_id), glyphCount(glyph_count), style(style), isFixed(is_fixed) {}
257 
258     SkFontID        typefaceID;
259     int             glyphCount;
260     SkFontStyle     style;
261     bool            isFixed;
262 };
263 
264 // SkStrikeServer -----------------------------------------
265 
SkStrikeServer(DiscardableHandleManager * discardableHandleManager)266 SkStrikeServer::SkStrikeServer(DiscardableHandleManager* discardableHandleManager)
267         : fDiscardableHandleManager(discardableHandleManager) {
268     SkASSERT(fDiscardableHandleManager);
269 }
270 
271 SkStrikeServer::~SkStrikeServer() = default;
272 
serializeTypeface(SkTypeface * tf)273 sk_sp<SkData> SkStrikeServer::serializeTypeface(SkTypeface* tf) {
274     auto* data = fSerializedTypefaces.find(SkTypeface::UniqueID(tf));
275     if (data) {
276         return *data;
277     }
278 
279     WireTypeface wire(SkTypeface::UniqueID(tf), tf->countGlyphs(), tf->fontStyle(),
280                       tf->isFixedPitch());
281     data = fSerializedTypefaces.set(SkTypeface::UniqueID(tf),
282                                     SkData::MakeWithCopy(&wire, sizeof(wire)));
283     return *data;
284 }
285 
writeStrikeData(std::vector<uint8_t> * memory)286 void SkStrikeServer::writeStrikeData(std::vector<uint8_t>* memory) {
287     if (fLockedDescs.empty() && fTypefacesToSend.empty()) {
288         return;
289     }
290 
291     Serializer serializer(memory);
292     serializer.emplace<uint64_t>(fTypefacesToSend.size());
293     for (const auto& tf : fTypefacesToSend) serializer.write<WireTypeface>(tf);
294     fTypefacesToSend.clear();
295 
296     serializer.emplace<uint64_t>(fLockedDescs.size());
297     for (const auto* desc : fLockedDescs) {
298         auto it = fRemoteGlyphStateMap.find(desc);
299         SkASSERT(it != fRemoteGlyphStateMap.end());
300         it->second->writePendingGlyphs(&serializer);
301     }
302     fLockedDescs.clear();
303 }
304 
getOrCreateCache(const SkPaint & paint,const SkFont & font,const SkSurfaceProps & props,const SkMatrix & matrix,SkScalerContextFlags flags,SkScalerContextEffects * effects)305 SkStrikeServer::SkGlyphCacheState* SkStrikeServer::getOrCreateCache(
306         const SkPaint& paint,
307         const SkFont& font,
308         const SkSurfaceProps& props,
309         const SkMatrix& matrix,
310         SkScalerContextFlags flags,
311         SkScalerContextEffects* effects) {
312     SkAutoDescriptor keyAutoDesc;
313     auto keyDesc = create_descriptor(
314             kKey, paint, font, matrix, props, flags, &keyAutoDesc, effects);
315 
316     // In cases where tracing is turned off, make sure not to get an unused function warning.
317     // Lambdaize the function.
318     TRACE_EVENT1("skia", "RecForDesc", "rec",
319             TRACE_STR_COPY(
320                     [keyDesc](){
321                         auto ptr = keyDesc->findEntry(kRec_SkDescriptorTag, nullptr);
322                         SkScalerContextRec rec;
323                         std::memcpy(&rec, ptr, sizeof(rec));
324                         return rec.dump();
325                     }().c_str()
326             )
327     );
328 
329     // Already locked.
330     if (fLockedDescs.find(keyDesc) != fLockedDescs.end()) {
331         auto it = fRemoteGlyphStateMap.find(keyDesc);
332         SkASSERT(it != fRemoteGlyphStateMap.end());
333         SkGlyphCacheState* cache = it->second.get();
334         cache->setFontAndEffects(font, SkScalerContextEffects{paint});
335         return cache;
336     }
337 
338     // Try to lock.
339     auto it = fRemoteGlyphStateMap.find(keyDesc);
340     if (it != fRemoteGlyphStateMap.end()) {
341         SkGlyphCacheState* cache = it->second.get();
342 #ifdef SK_DEBUG
343         SkScalerContextEffects deviceEffects;
344         SkAutoDescriptor deviceAutoDesc;
345         auto deviceDesc = create_descriptor(
346                 kDevice, paint, font, matrix, props, flags, &deviceAutoDesc, &deviceEffects);
347         SkASSERT(cache->getDeviceDescriptor() == *deviceDesc);
348 #endif
349         bool locked = fDiscardableHandleManager->lockHandle(it->second->discardableHandleId());
350         if (locked) {
351             fLockedDescs.insert(it->first);
352             cache->setFontAndEffects(font, SkScalerContextEffects{paint});
353             return cache;
354         }
355 
356         // If the lock failed, the entry was deleted on the client. Remove our
357         // tracking.
358         fRemoteGlyphStateMap.erase(it);
359     }
360 
361     auto* tf = font.getTypefaceOrDefault();
362     const SkFontID typefaceId = tf->uniqueID();
363     if (!fCachedTypefaces.contains(typefaceId)) {
364         fCachedTypefaces.add(typefaceId);
365         fTypefacesToSend.emplace_back(typefaceId, tf->countGlyphs(), tf->fontStyle(),
366                                       tf->isFixedPitch());
367     }
368 
369     SkScalerContextEffects deviceEffects;
370     SkAutoDescriptor deviceAutoDesc;
371     auto deviceDesc = create_descriptor(
372             kDevice, paint, font, matrix, props, flags, &deviceAutoDesc, &deviceEffects);
373 
374     auto context = tf->createScalerContext(deviceEffects, deviceDesc);
375 
376     // Create a new cache state and insert it into the map.
377     auto newHandle = fDiscardableHandleManager->createHandle();
378     auto cacheState = skstd::make_unique<SkGlyphCacheState>(
379             *keyDesc, *deviceDesc, std::move(context), newHandle);
380 
381     auto* cacheStatePtr = cacheState.get();
382 
383     fLockedDescs.insert(&cacheStatePtr->getKeyDescriptor());
384     fRemoteGlyphStateMap[&cacheStatePtr->getKeyDescriptor()] = std::move(cacheState);
385 
386     checkForDeletedEntries();
387 
388     cacheStatePtr->setFontAndEffects(font, SkScalerContextEffects{paint});
389     return cacheStatePtr;
390 }
391 
checkForDeletedEntries()392 void SkStrikeServer::checkForDeletedEntries() {
393     auto it = fRemoteGlyphStateMap.begin();
394     while (fRemoteGlyphStateMap.size() > fMaxEntriesInDescriptorMap &&
395            it != fRemoteGlyphStateMap.end()) {
396         if (fDiscardableHandleManager->isHandleDeleted(it->second->discardableHandleId())) {
397             it = fRemoteGlyphStateMap.erase(it);
398         } else {
399             ++it;
400         }
401     }
402 }
403 
404 // -- SkGlyphCacheState ----------------------------------------------------------------------------
SkGlyphCacheState(const SkDescriptor & keyDescriptor,const SkDescriptor & deviceDescriptor,std::unique_ptr<SkScalerContext> context,uint32_t discardableHandleId)405 SkStrikeServer::SkGlyphCacheState::SkGlyphCacheState(
406         const SkDescriptor& keyDescriptor,
407         const SkDescriptor& deviceDescriptor,
408         std::unique_ptr<SkScalerContext> context,
409         uint32_t discardableHandleId)
410         : fKeyDescriptor{keyDescriptor}
411         , fDeviceDescriptor{deviceDescriptor}
412         , fDiscardableHandleId(discardableHandleId)
413         , fIsSubpixel{context->isSubpixel()}
414         , fAxisAlignmentForHText{context->computeAxisAlignmentForHText()}
415         // N.B. context must come last because it is used above.
416         , fContext{std::move(context)} {
417     SkASSERT(fKeyDescriptor.getDesc() != nullptr);
418     SkASSERT(fDeviceDescriptor.getDesc() != nullptr);
419     SkASSERT(fContext != nullptr);
420 }
421 
422 SkStrikeServer::SkGlyphCacheState::~SkGlyphCacheState() = default;
423 
addGlyph(SkPackedGlyphID glyph,bool asPath)424 void SkStrikeServer::SkGlyphCacheState::addGlyph(SkPackedGlyphID glyph, bool asPath) {
425     auto* cache = asPath ? &fCachedGlyphPaths : &fCachedGlyphImages;
426     auto* pending = asPath ? &fPendingGlyphPaths : &fPendingGlyphImages;
427 
428     // Already cached.
429     if (cache->contains(glyph)) {
430         return;
431     }
432 
433     // A glyph is going to be sent. Make sure we have a scaler context to send it.
434     this->ensureScalerContext();
435 
436     // Serialize and cache. Also create the scalar context to use when serializing
437     // this glyph.
438     cache->add(glyph);
439     pending->push_back(glyph);
440 }
441 
writeGlyph(SkGlyph * glyph,Serializer * serializer)442 static void writeGlyph(SkGlyph* glyph, Serializer* serializer) {
443     serializer->write<SkPackedGlyphID>(glyph->getPackedID());
444     serializer->write<float>(glyph->fAdvanceX);
445     serializer->write<float>(glyph->fAdvanceY);
446     serializer->write<uint16_t>(glyph->fWidth);
447     serializer->write<uint16_t>(glyph->fHeight);
448     serializer->write<int16_t>(glyph->fTop);
449     serializer->write<int16_t>(glyph->fLeft);
450     serializer->write<int8_t>(glyph->fForceBW);
451     serializer->write<uint8_t>(glyph->fMaskFormat);
452 }
453 
writePendingGlyphs(Serializer * serializer)454 void SkStrikeServer::SkGlyphCacheState::writePendingGlyphs(Serializer* serializer) {
455     // TODO(khushalsagar): Write a strike only if it has any pending glyphs.
456     serializer->emplace<bool>(this->hasPendingGlyphs());
457     if (!this->hasPendingGlyphs()) {
458         this->resetScalerContext();
459         return;
460     }
461 
462     // Write the desc.
463     serializer->emplace<StrikeSpec>(fContext->getTypeface()->uniqueID(), fDiscardableHandleId);
464     serializer->writeDescriptor(*fKeyDescriptor.getDesc());
465 
466     // Write FontMetrics.
467     // TODO(khushalsagar): Do we need to re-send each time?
468     SkFontMetrics fontMetrics;
469     fContext->getFontMetrics(&fontMetrics);
470     serializer->write<SkFontMetrics>(fontMetrics);
471 
472     // Write glyphs images.
473     serializer->emplace<uint64_t>(fPendingGlyphImages.size());
474     for (const auto& glyphID : fPendingGlyphImages) {
475         SkGlyph glyph{glyphID};
476         fContext->getMetrics(&glyph);
477         writeGlyph(&glyph, serializer);
478 
479         auto imageSize = glyph.computeImageSize();
480         if (imageSize == 0u) continue;
481 
482         glyph.fImage = serializer->allocate(imageSize, glyph.formatAlignment());
483         fContext->getImage(glyph);
484         // TODO: Generating the image can change the mask format, do we need to update it in the
485         // serialized glyph?
486     }
487     fPendingGlyphImages.clear();
488 
489     // Write glyphs paths.
490     serializer->emplace<uint64_t>(fPendingGlyphPaths.size());
491     for (const auto& glyphID : fPendingGlyphPaths) {
492         SkGlyph glyph{glyphID};
493         fContext->getMetrics(&glyph);
494         writeGlyph(&glyph, serializer);
495         writeGlyphPath(glyphID, serializer);
496     }
497     fPendingGlyphPaths.clear();
498     this->resetScalerContext();
499 }
500 
findGlyph(SkPackedGlyphID glyphID)501 const SkGlyph& SkStrikeServer::SkGlyphCacheState::findGlyph(SkPackedGlyphID glyphID) {
502     SkGlyph* glyphPtr = fGlyphMap.findOrNull(glyphID);
503     if (glyphPtr == nullptr) {
504         glyphPtr = fAlloc.make<SkGlyph>(glyphID);
505         fGlyphMap.set(glyphPtr);
506         this->ensureScalerContext();
507         fContext->getMetrics(glyphPtr);
508     }
509 
510     return *glyphPtr;
511 }
512 
ensureScalerContext()513 void SkStrikeServer::SkGlyphCacheState::ensureScalerContext() {
514     if (fContext == nullptr) {
515         auto tf = fFont->getTypefaceOrDefault();
516         fContext = tf->createScalerContext(fEffects, fDeviceDescriptor.getDesc());
517     }
518 }
519 
resetScalerContext()520 void SkStrikeServer::SkGlyphCacheState::resetScalerContext() {
521     fContext.reset();
522     fFont = nullptr;
523 }
524 
setFontAndEffects(const SkFont & font,SkScalerContextEffects effects)525 void SkStrikeServer::SkGlyphCacheState::setFontAndEffects(
526         const SkFont& font, SkScalerContextEffects effects) {
527     fFont = &font;
528     fEffects = effects;
529 }
530 
rounding() const531 SkVector SkStrikeServer::SkGlyphCacheState::rounding() const {
532     return SkStrikeCommon::PixelRounding(fIsSubpixel, fAxisAlignmentForHText);
533 }
534 
getGlyphMetrics(SkGlyphID glyphID,SkPoint position)535 const SkGlyph& SkStrikeServer::SkGlyphCacheState::getGlyphMetrics(
536         SkGlyphID glyphID, SkPoint position) {
537     SkIPoint lookupPoint = SkStrikeCommon::SubpixelLookup(fAxisAlignmentForHText, position);
538     SkPackedGlyphID packedGlyphID = fIsSubpixel ? SkPackedGlyphID{glyphID, lookupPoint}
539                                                 : SkPackedGlyphID{glyphID};
540 
541     return this->findGlyph(packedGlyphID);
542 }
543 
hasImage(const SkGlyph & glyph)544 bool SkStrikeServer::SkGlyphCacheState::hasImage(const SkGlyph& glyph) {
545     // If a glyph has width and height, it must have an image available to it.
546     return !glyph.isEmpty();
547 }
548 
hasPath(const SkGlyph & glyph)549 bool SkStrikeServer::SkGlyphCacheState::hasPath(const SkGlyph& glyph) {
550     return const_cast<SkGlyph&>(glyph).addPath(fContext.get(), &fAlloc) != nullptr;
551 }
552 
writeGlyphPath(const SkPackedGlyphID & glyphID,Serializer * serializer) const553 void SkStrikeServer::SkGlyphCacheState::writeGlyphPath(const SkPackedGlyphID& glyphID,
554                                                        Serializer* serializer) const {
555     SkPath path;
556     if (!fContext->getPath(glyphID, &path)) {
557         serializer->write<uint64_t>(0u);
558         return;
559     }
560 
561     size_t pathSize = path.writeToMemory(nullptr);
562     serializer->write<uint64_t>(pathSize);
563     path.writeToMemory(serializer->allocate(pathSize, kPathAlignment));
564 }
565 
566 // SkStrikeClient -----------------------------------------
567 class SkStrikeClient::DiscardableStrikePinner : public SkStrikePinner {
568 public:
DiscardableStrikePinner(SkDiscardableHandleId discardableHandleId,sk_sp<DiscardableHandleManager> manager)569     DiscardableStrikePinner(SkDiscardableHandleId discardableHandleId,
570                             sk_sp<DiscardableHandleManager> manager)
571             : fDiscardableHandleId(discardableHandleId), fManager(std::move(manager)) {}
572 
573     ~DiscardableStrikePinner() override = default;
canDelete()574     bool canDelete() override { return fManager->deleteHandle(fDiscardableHandleId); }
575 
576 private:
577     const SkDiscardableHandleId fDiscardableHandleId;
578     sk_sp<DiscardableHandleManager> fManager;
579 };
580 
SkStrikeClient(sk_sp<DiscardableHandleManager> discardableManager,bool isLogging,SkStrikeCache * strikeCache)581 SkStrikeClient::SkStrikeClient(sk_sp<DiscardableHandleManager> discardableManager,
582                                bool isLogging,
583                                SkStrikeCache* strikeCache)
584         : fDiscardableHandleManager(std::move(discardableManager))
585         , fStrikeCache{strikeCache ? strikeCache : SkStrikeCache::GlobalStrikeCache()}
586         , fIsLogging{isLogging} {}
587 
588 SkStrikeClient::~SkStrikeClient() = default;
589 
590 #define READ_FAILURE                      \
591     {                                     \
592         SkDEBUGFAIL("Bad serialization"); \
593         return false;                     \
594     }
595 
readGlyph(SkTLazy<SkGlyph> & glyph,Deserializer * deserializer)596 static bool readGlyph(SkTLazy<SkGlyph>& glyph, Deserializer* deserializer) {
597     SkPackedGlyphID glyphID;
598     if (!deserializer->read<SkPackedGlyphID>(&glyphID)) return false;
599     glyph.init(glyphID);
600     if (!deserializer->read<float>(&glyph->fAdvanceX)) return false;
601     if (!deserializer->read<float>(&glyph->fAdvanceY)) return false;
602     if (!deserializer->read<uint16_t>(&glyph->fWidth)) return false;
603     if (!deserializer->read<uint16_t>(&glyph->fHeight)) return false;
604     if (!deserializer->read<int16_t>(&glyph->fTop)) return false;
605     if (!deserializer->read<int16_t>(&glyph->fLeft)) return false;
606     if (!deserializer->read<int8_t>(&glyph->fForceBW)) return false;
607     if (!deserializer->read<uint8_t>(&glyph->fMaskFormat)) return false;
608     return true;
609 }
610 
readStrikeData(const volatile void * memory,size_t memorySize)611 bool SkStrikeClient::readStrikeData(const volatile void* memory, size_t memorySize) {
612     SkASSERT(memorySize != 0u);
613     Deserializer deserializer(static_cast<const volatile char*>(memory), memorySize);
614 
615     uint64_t typefaceSize = 0u;
616     if (!deserializer.read<uint64_t>(&typefaceSize)) READ_FAILURE
617 
618     for (size_t i = 0; i < typefaceSize; ++i) {
619         WireTypeface wire;
620         if (!deserializer.read<WireTypeface>(&wire)) READ_FAILURE
621 
622         // TODO(khushalsagar): The typeface no longer needs a reference to the
623         // SkStrikeClient, since all needed glyphs must have been pushed before
624         // raster.
625         addTypeface(wire);
626     }
627 
628     uint64_t strikeCount = 0u;
629     if (!deserializer.read<uint64_t>(&strikeCount)) READ_FAILURE
630 
631     for (size_t i = 0; i < strikeCount; ++i) {
632         bool has_glyphs = false;
633         if (!deserializer.read<bool>(&has_glyphs)) READ_FAILURE
634 
635         if (!has_glyphs) continue;
636 
637         StrikeSpec spec;
638         if (!deserializer.read<StrikeSpec>(&spec)) READ_FAILURE
639 
640         SkAutoDescriptor sourceAd;
641         if (!deserializer.readDescriptor(&sourceAd)) READ_FAILURE
642 
643         SkFontMetrics fontMetrics;
644         if (!deserializer.read<SkFontMetrics>(&fontMetrics)) READ_FAILURE
645 
646         // Get the local typeface from remote fontID.
647         auto* tf = fRemoteFontIdToTypeface.find(spec.typefaceID)->get();
648         // Received strikes for a typeface which doesn't exist.
649         if (!tf) READ_FAILURE
650 
651         // Replace the ContextRec in the desc from the server to create the client
652         // side descriptor.
653         // TODO: Can we do this in-place and re-compute checksum? Instead of a complete copy.
654         SkAutoDescriptor ad;
655         auto* client_desc = auto_descriptor_from_desc(sourceAd.getDesc(), tf->uniqueID(), &ad);
656 
657         auto strike = fStrikeCache->findStrikeExclusive(*client_desc);
658         if (strike == nullptr) {
659             // Note that we don't need to deserialize the effects since we won't be generating any
660             // glyphs here anyway, and the desc is still correct since it includes the serialized
661             // effects.
662             SkScalerContextEffects effects;
663             auto scaler = SkStrikeCache::CreateScalerContext(*client_desc, effects, *tf);
664             strike = fStrikeCache->createStrikeExclusive(
665                     *client_desc, std::move(scaler), &fontMetrics,
666                     skstd::make_unique<DiscardableStrikePinner>(spec.discardableHandleId,
667                                                                 fDiscardableHandleManager));
668             auto proxyContext = static_cast<SkScalerContextProxy*>(strike->getScalerContext());
669             proxyContext->initCache(strike.get(), fStrikeCache);
670         }
671 
672         uint64_t glyphImagesCount = 0u;
673         if (!deserializer.read<uint64_t>(&glyphImagesCount)) READ_FAILURE
674         for (size_t j = 0; j < glyphImagesCount; j++) {
675             SkTLazy<SkGlyph> glyph;
676             if (!readGlyph(glyph, &deserializer)) READ_FAILURE
677 
678             SkGlyph* allocatedGlyph = strike->getRawGlyphByID(glyph->getPackedID());
679 
680             // Update the glyph unless it's already got an image (from fallback),
681             // preserving any path that might be present.
682             if (allocatedGlyph->fImage == nullptr) {
683                 auto* glyphPath = allocatedGlyph->fPathData;
684                 *allocatedGlyph = *glyph;
685                 allocatedGlyph->fPathData = glyphPath;
686             }
687 
688             auto imageSize = glyph->computeImageSize();
689             if (imageSize == 0u) continue;
690 
691             auto* image = deserializer.read(imageSize, allocatedGlyph->formatAlignment());
692             if (!image) READ_FAILURE
693             strike->initializeImage(image, imageSize, allocatedGlyph);
694         }
695 
696         uint64_t glyphPathsCount = 0u;
697         if (!deserializer.read<uint64_t>(&glyphPathsCount)) READ_FAILURE
698         for (size_t j = 0; j < glyphPathsCount; j++) {
699             SkTLazy<SkGlyph> glyph;
700             if (!readGlyph(glyph, &deserializer)) READ_FAILURE
701 
702             SkGlyph* allocatedGlyph = strike->getRawGlyphByID(glyph->getPackedID());
703 
704             // Update the glyph unless it's already got a path (from fallback),
705             // preserving any image that might be present.
706             if (allocatedGlyph->fPathData == nullptr) {
707                 auto* glyphImage = allocatedGlyph->fImage;
708                 *allocatedGlyph = *glyph;
709                 allocatedGlyph->fImage = glyphImage;
710             }
711 
712             if (!read_path(&deserializer, allocatedGlyph, strike.get())) READ_FAILURE
713         }
714     }
715 
716     return true;
717 }
718 
deserializeTypeface(const void * buf,size_t len)719 sk_sp<SkTypeface> SkStrikeClient::deserializeTypeface(const void* buf, size_t len) {
720     WireTypeface wire;
721     if (len != sizeof(wire)) return nullptr;
722     memcpy(&wire, buf, sizeof(wire));
723     return this->addTypeface(wire);
724 }
725 
addTypeface(const WireTypeface & wire)726 sk_sp<SkTypeface> SkStrikeClient::addTypeface(const WireTypeface& wire) {
727     auto* typeface = fRemoteFontIdToTypeface.find(wire.typefaceID);
728     if (typeface) return *typeface;
729 
730     auto newTypeface = sk_make_sp<SkTypefaceProxy>(
731             wire.typefaceID, wire.glyphCount, wire.style, wire.isFixed,
732             fDiscardableHandleManager, fIsLogging);
733     fRemoteFontIdToTypeface.set(wire.typefaceID, newTypeface);
734     return std::move(newTypeface);
735 }
736