Home | History | Annotate | Download | only in core
      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 
     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 };
     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 
     73 size_t pad(size_t size, size_t alignment) { return (size + (alignment - 1)) & ~(alignment - 1); }
     74 
     75 class Serializer {
     76 public:
     77     Serializer(std::vector<uint8_t>* buffer) : fBuffer{buffer} { }
     78 
     79     template <typename T, typename... 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>
     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>
     92     T* allocate() {
     93         T* result = (T*)allocate(sizeof(T), alignof(T));
     94         return result;
     95     }
     96 
     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 
    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:
    117     Deserializer(const volatile char* memory, size_t memorySize)
    118             : fMemory(memory), fMemorySize(memorySize) {}
    119 
    120     template <typename T>
    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 
    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 
    141     const volatile void* read(size_t size, size_t alignment) {
    142       return this->ensureAtLeast(size, alignment);
    143     }
    144 
    145 private:
    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 
    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 
    178 size_t SkDescriptorMapOperators::operator()(const SkDescriptor* key) const {
    179     return key->getChecksum();
    180 }
    181 
    182 bool SkDescriptorMapOperators::operator()(const SkDescriptor* lhs, const SkDescriptor* rhs) const {
    183     return *lhs == *rhs;
    184 }
    185 
    186 struct StrikeSpec {
    187     StrikeSpec() {}
    188     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 -----------------------------------------------------------------------------
    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 
    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 
    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 
    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 
    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 
    239 SkCanvas::SaveLayerStrategy SkTextBlobCacheDiffCanvas::getSaveLayerStrategy(
    240         const SaveLayerRec& rec) {
    241     return kFullLayer_SaveLayerStrategy;
    242 }
    243 
    244 bool SkTextBlobCacheDiffCanvas::onDoSaveBehind(const SkRect*) {
    245     return false;
    246 }
    247 
    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;
    255     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 
    266 SkStrikeServer::SkStrikeServer(DiscardableHandleManager* discardableHandleManager)
    267         : fDiscardableHandleManager(discardableHandleManager) {
    268     SkASSERT(fDiscardableHandleManager);
    269 }
    270 
    271 SkStrikeServer::~SkStrikeServer() = default;
    272 
    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 
    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 
    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 
    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 ----------------------------------------------------------------------------
    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 
    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 
    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 
    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 
    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 
    513 void SkStrikeServer::SkGlyphCacheState::ensureScalerContext() {
    514     if (fContext == nullptr) {
    515         auto tf = fFont->getTypefaceOrDefault();
    516         fContext = tf->createScalerContext(fEffects, fDeviceDescriptor.getDesc());
    517     }
    518 }
    519 
    520 void SkStrikeServer::SkGlyphCacheState::resetScalerContext() {
    521     fContext.reset();
    522     fFont = nullptr;
    523 }
    524 
    525 void SkStrikeServer::SkGlyphCacheState::setFontAndEffects(
    526         const SkFont& font, SkScalerContextEffects effects) {
    527     fFont = &font;
    528     fEffects = effects;
    529 }
    530 
    531 SkVector SkStrikeServer::SkGlyphCacheState::rounding() const {
    532     return SkStrikeCommon::PixelRounding(fIsSubpixel, fAxisAlignmentForHText);
    533 }
    534 
    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 
    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 
    549 bool SkStrikeServer::SkGlyphCacheState::hasPath(const SkGlyph& glyph) {
    550     return const_cast<SkGlyph&>(glyph).addPath(fContext.get(), &fAlloc) != nullptr;
    551 }
    552 
    553 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:
    569     DiscardableStrikePinner(SkDiscardableHandleId discardableHandleId,
    570                             sk_sp<DiscardableHandleManager> manager)
    571             : fDiscardableHandleId(discardableHandleId), fManager(std::move(manager)) {}
    572 
    573     ~DiscardableStrikePinner() override = default;
    574     bool canDelete() override { return fManager->deleteHandle(fDiscardableHandleId); }
    575 
    576 private:
    577     const SkDiscardableHandleId fDiscardableHandleId;
    578     sk_sp<DiscardableHandleManager> fManager;
    579 };
    580 
    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 
    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 
    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 
    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 
    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