/*
 * Copyright 2018 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkRemoteGlyphCache.h"

#include <iterator>
#include <memory>
#include <string>
#include <tuple>

#include "SkDevice.h"
#include "SkDraw.h"
#include "SkFindAndPlaceGlyph.h"
#include "SkPathEffect.h"
#include "SkStrikeCache.h"
#include "SkTextBlobRunIterator.h"
#include "SkTraceEvent.h"
#include "SkTypeface_remote.h"

#if SK_SUPPORT_GPU
#include "GrDrawOpAtlas.h"
#include "text/GrTextContext.h"
#endif

static SkDescriptor* auto_descriptor_from_desc(const SkDescriptor* source_desc,
                                               SkFontID font_id,
                                               SkAutoDescriptor* ad) {
    ad->reset(source_desc->getLength());
    auto* desc = ad->getDesc();
    desc->init();

    // Rec.
    {
        uint32_t size;
        auto ptr = source_desc->findEntry(kRec_SkDescriptorTag, &size);
        SkScalerContextRec rec;
        std::memcpy(&rec, ptr, size);
        rec.fFontID = font_id;
        desc->addEntry(kRec_SkDescriptorTag, sizeof(rec), &rec);
    }

    // Path effect.
    {
        uint32_t size;
        auto ptr = source_desc->findEntry(kPathEffect_SkDescriptorTag, &size);
        if (ptr) desc->addEntry(kPathEffect_SkDescriptorTag, size, ptr);
    }

    // Mask filter.
    {
        uint32_t size;
        auto ptr = source_desc->findEntry(kMaskFilter_SkDescriptorTag, &size);
        if (ptr) desc->addEntry(kMaskFilter_SkDescriptorTag, size, ptr);
    }

    desc->computeChecksum();
    return desc;
}

// -- Serializer ----------------------------------------------------------------------------------

size_t pad(size_t size, size_t alignment) { return (size + (alignment - 1)) & ~(alignment - 1); }

class Serializer {
public:
    Serializer(std::vector<uint8_t>* buffer) : fBuffer{buffer} { }

    template <typename T, typename... Args>
    T* emplace(Args&&... args) {
        auto result = allocate(sizeof(T), alignof(T));
        return new (result) T{std::forward<Args>(args)...};
    }

    template <typename T>
    void write(const T& data) {
        T* result = (T*)allocate(sizeof(T), alignof(T));
        memcpy(result, &data, sizeof(T));
    }

    template <typename T>
    T* allocate() {
        T* result = (T*)allocate(sizeof(T), alignof(T));
        return result;
    }

    void writeDescriptor(const SkDescriptor& desc) {
        write(desc.getLength());
        auto result = allocate(desc.getLength(), alignof(SkDescriptor));
        memcpy(result, &desc, desc.getLength());
    }

    void* allocate(size_t size, size_t alignment) {
        size_t aligned = pad(fBuffer->size(), alignment);
        fBuffer->resize(aligned + size);
        return &(*fBuffer)[aligned];
    }

private:
    std::vector<uint8_t>* fBuffer;
};

// -- Deserializer -------------------------------------------------------------------------------
// Note that the Deserializer is reading untrusted data, we need to guard against invalid data.
class Deserializer {
public:
    Deserializer(const volatile char* memory, size_t memorySize)
            : fMemory(memory), fMemorySize(memorySize) {}

    template <typename T>
    bool read(T* val) {
        auto* result = this->ensureAtLeast(sizeof(T), alignof(T));
        if (!result) return false;

        memcpy(val, const_cast<const char*>(result), sizeof(T));
        return true;
    }

    bool readDescriptor(SkAutoDescriptor* ad) {
        uint32_t desc_length = 0u;
        if (!read<uint32_t>(&desc_length)) return false;

        auto* result = this->ensureAtLeast(desc_length, alignof(SkDescriptor));
        if (!result) return false;

        ad->reset(desc_length);
        memcpy(ad->getDesc(), const_cast<const char*>(result), desc_length);
        return true;
    }

    const volatile void* read(size_t size, size_t alignment) {
      return this->ensureAtLeast(size, alignment);
    }

private:
    const volatile char* ensureAtLeast(size_t size, size_t alignment) {
        size_t padded = pad(fBytesRead, alignment);

        // Not enough data
        if (padded + size > fMemorySize) return nullptr;

        auto* result = fMemory + padded;
        fBytesRead = padded + size;
        return result;
    }

    // Note that we read each piece of memory only once to guard against TOCTOU violations.
    const volatile char* fMemory;
    size_t fMemorySize;
    size_t fBytesRead = 0u;
};

// Paths use a SkWriter32 which requires 4 byte alignment.
static const size_t kPathAlignment  = 4u;

bool read_path(Deserializer* deserializer, SkGlyph* glyph, SkGlyphCache* cache) {
    size_t pathSize = 0u;
    if (!deserializer->read<size_t>(&pathSize)) return false;

    if (pathSize == 0u) return true;

    auto* path = deserializer->read(pathSize, kPathAlignment);
    if (!path) return false;

    return cache->initializePath(glyph, path, pathSize);
}

size_t SkDescriptorMapOperators::operator()(const SkDescriptor* key) const {
    return key->getChecksum();
    }

    bool SkDescriptorMapOperators::operator()(const SkDescriptor* lhs,
                                              const SkDescriptor* rhs) const {
        return *lhs == *rhs;
    }

// -- TrackLayerDevice -----------------------------------------------------------------------------
class TrackLayerDevice : public SkNoPixelsDevice {
public:
    TrackLayerDevice(const SkIRect& bounds, const SkSurfaceProps& props)
            : SkNoPixelsDevice(bounds, props) { }
    SkBaseDevice* onCreateDevice(const CreateInfo& cinfo, const SkPaint*) override {
        const SkSurfaceProps surfaceProps(this->surfaceProps().flags(), cinfo.fPixelGeometry);
        return new TrackLayerDevice(this->getGlobalBounds(), surfaceProps);
    }
};

// -- SkTextBlobCacheDiffCanvas -------------------------------------------------------------------
SkTextBlobCacheDiffCanvas::Settings::Settings() = default;
SkTextBlobCacheDiffCanvas::Settings::~Settings() = default;

SkTextBlobCacheDiffCanvas::SkTextBlobCacheDiffCanvas(int width, int height,
                                                     const SkMatrix& deviceMatrix,
                                                     const SkSurfaceProps& props,
                                                     SkStrikeServer* strikeSever, Settings settings)
        : SkNoDrawCanvas{sk_make_sp<TrackLayerDevice>(SkIRect::MakeWH(width, height), props)}
        , fDeviceMatrix{deviceMatrix}
        , fStrikeServer{strikeSever}
        , fSettings{settings} {
    SkASSERT(fStrikeServer);
}

SkTextBlobCacheDiffCanvas::~SkTextBlobCacheDiffCanvas() = default;

SkCanvas::SaveLayerStrategy SkTextBlobCacheDiffCanvas::getSaveLayerStrategy(
    const SaveLayerRec&rec)
{
    return kFullLayer_SaveLayerStrategy;
}

void SkTextBlobCacheDiffCanvas::onDrawTextBlob(
        const SkTextBlob* blob, SkScalar x, SkScalar y, const SkPaint& paint) {
    SkPoint position{x, y};

    SkPaint runPaint{paint};
    SkTextBlobRunIterator it(blob);
        for (;!it.done(); it.next()) {
        // applyFontToPaint() always overwrites the exact same attributes,
        // so it is safe to not re-seed the paint for this reason.
        it.applyFontToPaint(&runPaint);
        if (auto looper = runPaint.getLooper()) {
            this->processLooper(position, it, runPaint, looper);
        } else {
            this->processGlyphRun(position, it, runPaint);
        }
    }
}

void SkTextBlobCacheDiffCanvas::processLooper(
        const SkPoint& position,
        const SkTextBlobRunIterator& it,
        const SkPaint& origPaint,
        SkDrawLooper* looper)
{
    SkSTArenaAlloc<48> alloc;
    auto context = looper->makeContext(this, &alloc);
    SkPaint runPaint = origPaint;
    while (context->next(this, &runPaint)) {
        this->save();
        this->processGlyphRun(position, it, runPaint);
        this->restore();
        runPaint = origPaint;
    }
}

#define FAIL_AND_RETURN                         \
    SkDEBUGFAIL("Failed to process glyph run"); \
    return;

void SkTextBlobCacheDiffCanvas::processGlyphRun(
        const SkPoint& position,
        const SkTextBlobRunIterator& it,
        const SkPaint& runPaint)
{

    if (runPaint.getTextEncoding() != SkPaint::TextEncoding::kGlyphID_TextEncoding) {
        TRACE_EVENT0("skia", "kGlyphID_TextEncoding");
        FAIL_AND_RETURN
    }

    // All other alignment modes need the glyph advances. Use the slow drawing mode.
    if (runPaint.getTextAlign() != SkPaint::kLeft_Align) {
        TRACE_EVENT0("skia", "kLeft_Align");
        FAIL_AND_RETURN
    }

    if (it.positioning() == SkTextBlob::kDefault_Positioning) {
        // Default positioning needs advances. Can't do that.
        TRACE_EVENT0("skia", "kDefault_Positioning");
        FAIL_AND_RETURN
    }

    SkMatrix runMatrix{fDeviceMatrix};
    runMatrix.preConcat(this->getTotalMatrix());

#if SK_SUPPORT_GPU
    GrTextContext::Options options;
    options.fMinDistanceFieldFontSize = fSettings.fMinDistanceFieldFontSize;
    options.fMaxDistanceFieldFontSize = fSettings.fMaxDistanceFieldFontSize;
    GrTextContext::SanitizeOptions(&options);
    if (GrTextContext::CanDrawAsDistanceFields(runPaint, runMatrix, this->surfaceProps(),
                                               fSettings.fContextSupportsDistanceFieldText,
                                               options)) {
        SkScalar textRatio;
        SkPaint dfPaint(runPaint);
        SkScalerContextFlags flags;
        GrTextContext::InitDistanceFieldPaint(nullptr, &dfPaint, runMatrix, options,
                                                   &textRatio, &flags);
        this->processGlyphRunForDFT(it, dfPaint, flags);
    }
#endif

    // If the matrix has perspective, we fall back to using distance field text or paths.
    // TODO: Add distance field text support, and FallbackTextHelper logic from GrTextContext.
    if (SkDraw::ShouldDrawTextAsPaths(runPaint, runMatrix)) {
        this->processGlyphRunForPaths(it, runPaint);
        return;
    }

    using PosFn = SkPoint(*)(int index, const SkScalar* pos);
    PosFn posFn;
    SkSTArenaAlloc<120> arena;
    SkFindAndPlaceGlyph::MapperInterface* mapper = nullptr;
    switch (it.positioning()) {
        case SkTextBlob::kHorizontal_Positioning:
            posFn = [](int index, const SkScalar* pos) {
                return SkPoint{pos[index], 0};
            };
            mapper = SkFindAndPlaceGlyph::CreateMapper(
                    runMatrix, SkPoint::Make(position.x(), position.y() + it.offset().y()), 1,
                    &arena);
            break;
        case SkTextBlob::kFull_Positioning:
            posFn = [](int index, const SkScalar* pos) {
                return SkPoint{pos[2 * index], pos[2 * index + 1]};
            };
            mapper = SkFindAndPlaceGlyph::CreateMapper(runMatrix, position, 2, &arena);
            break;
        default:
            posFn = nullptr;
            SK_ABORT("unhandled positioning mode");
    }

    SkScalerContextRec deviceSpecificRec;
    SkScalerContextEffects effects;
    auto* glyphCacheState =
            static_cast<SkStrikeServer*>(fStrikeServer)
                    ->getOrCreateCache(runPaint, &this->surfaceProps(), &runMatrix,
                                       SkScalerContextFlags::kFakeGammaAndBoostContrast,
                                       &deviceSpecificRec, &effects);
    SkASSERT(glyphCacheState);

    const bool asPath = false;
    bool isSubpixel =
            SkToBool(deviceSpecificRec.fFlags & SkScalerContext::kSubpixelPositioning_Flag);
    SkAxisAlignment axisAlignment = deviceSpecificRec.computeAxisAlignmentForHText();
    auto pos = it.pos();
    const uint16_t* glyphs = it.glyphs();
    for (uint32_t index = 0; index < it.glyphCount(); index++) {
        SkIPoint subPixelPos{0, 0};
        if (isSubpixel) {
            SkPoint glyphPos = mapper->map(posFn(index, pos));
            subPixelPos = SkFindAndPlaceGlyph::SubpixelAlignment(axisAlignment, glyphPos);
        }

        glyphCacheState->addGlyph(runPaint.getTypeface(),
                                  effects,
                                  SkPackedGlyphID(glyphs[index], subPixelPos.x(), subPixelPos.y()),
                                  asPath);
    }
}

void SkTextBlobCacheDiffCanvas::processGlyphRunForPaths(const SkTextBlobRunIterator& it,
                                                        const SkPaint& runPaint) {
    TRACE_EVENT0("skia", "SkTextBlobCacheDiffCanvas::processGlyphRunForPaths");

    // The code below borrowed from GrTextContext::DrawBmpPosTextAsPaths.
    SkPaint pathPaint(runPaint);
    pathPaint.setupForAsPaths();
    pathPaint.setStyle(SkPaint::kFill_Style);
    pathPaint.setPathEffect(nullptr);

    SkScalerContextRec deviceSpecificRec;
    SkScalerContextEffects effects;
    auto* glyphCacheState =
            static_cast<SkStrikeServer*>(fStrikeServer)
                    ->getOrCreateCache(pathPaint, &this->surfaceProps(), nullptr,
                                       SkScalerContextFlags::kFakeGammaAndBoostContrast,
                                       &deviceSpecificRec, &effects);

    const bool asPath = true;
    const SkIPoint subPixelPos{0, 0};
    const uint16_t* glyphs = it.glyphs();
    for (uint32_t index = 0; index < it.glyphCount(); index++) {
        glyphCacheState->addGlyph(runPaint.getTypeface(),
                                  effects,
                                  SkPackedGlyphID(glyphs[index], subPixelPos.x(), subPixelPos.y()),
                                  asPath);
    }
}

void SkTextBlobCacheDiffCanvas::processGlyphRunForDFT(const SkTextBlobRunIterator& it,
                                                      const SkPaint& runPaint,
                                                      SkScalerContextFlags flags) {
    SkScalerContextRec deviceSpecificRec;
    SkScalerContextEffects effects;
    auto* glyphCacheState = static_cast<SkStrikeServer*>(fStrikeServer)
                                    ->getOrCreateCache(runPaint, &this->surfaceProps(), nullptr,
                                                       flags, &deviceSpecificRec, &effects);

    const bool asPath = false;
    const SkIPoint subPixelPos{0, 0};
    const uint16_t* glyphs = it.glyphs();
    for (uint32_t index = 0; index < it.glyphCount(); index++) {
        glyphCacheState->addGlyph(runPaint.getTypeface(),
                                  effects,
                                  SkPackedGlyphID(glyphs[index], subPixelPos.x(), subPixelPos.y()),
                                  asPath);
    }
}

const SkSurfaceProps& SkTextBlobCacheDiffCanvas::surfaceProps() const {
    // SaveLayers can change the SurfaceProps used, and we ensure that the props used by the top
    // device for the layer is correct. This is done by ensuring that TrackLayerDevice used by this
    // canvas propagates them correctly when a new device is created for a layer.
    const auto* device = this->getTopDevice();
    SkASSERT(device);
    return device->surfaceProps();
}

struct StrikeSpec {
    StrikeSpec() {}
    StrikeSpec(SkFontID typefaceID_, SkDiscardableHandleId discardableHandleId_)
            : typefaceID{typefaceID_}, discardableHandleId(discardableHandleId_) {}
    SkFontID typefaceID = 0u;
    SkDiscardableHandleId discardableHandleId = 0u;
    /* desc */
    /* n X (glyphs ids) */
};

struct WireTypeface {
    WireTypeface() = default;
    WireTypeface(SkFontID typeface_id, int glyph_count, SkFontStyle style, bool is_fixed)
            : typefaceID(typeface_id), glyphCount(glyph_count), style(style), isFixed(is_fixed) {}

    // std::thread::id thread_id;  // TODO:need to figure a good solution
    SkFontID        typefaceID;
    int             glyphCount;
    SkFontStyle     style;
    bool            isFixed;
};

// SkStrikeServer -----------------------------------------

SkStrikeServer::SkStrikeServer(DiscardableHandleManager* discardableHandleManager)
        : fDiscardableHandleManager(discardableHandleManager) {
    SkASSERT(fDiscardableHandleManager);
}

SkStrikeServer::~SkStrikeServer() = default;

sk_sp<SkData> SkStrikeServer::serializeTypeface(SkTypeface* tf) {
    WireTypeface wire(SkTypeface::UniqueID(tf), tf->countGlyphs(), tf->fontStyle(),
                      tf->isFixedPitch());
    return SkData::MakeWithCopy(&wire, sizeof(wire));
}

void SkStrikeServer::writeStrikeData(std::vector<uint8_t>* memory) {
    if (fLockedDescs.empty() && fTypefacesToSend.empty()) return;

    Serializer serializer(memory);
    serializer.emplace<size_t>(fTypefacesToSend.size());
    for (const auto& tf : fTypefacesToSend) serializer.write<WireTypeface>(tf);
    fTypefacesToSend.clear();

    serializer.emplace<size_t>(fLockedDescs.size());
    for (const auto* desc : fLockedDescs) {
        auto it = fRemoteGlyphStateMap.find(desc);
        SkASSERT(it != fRemoteGlyphStateMap.end());

        // TODO: This is unnecessary, write only the descs which has any glyphs
        // to send. It was getting awkward to write the size after writing the
        // descs because the vector reallocs.
        serializer.emplace<bool>(it->second->has_pending_glyphs());
        if (!it->second->has_pending_glyphs()) continue;

        it->second->writePendingGlyphs(&serializer);
    }
    fLockedDescs.clear();
}

SkStrikeServer::SkGlyphCacheState* SkStrikeServer::getOrCreateCache(
        const SkPaint& paint,
        const SkSurfaceProps* props,
        const SkMatrix* matrix,
        SkScalerContextFlags flags,
        SkScalerContextRec* deviceRec,
        SkScalerContextEffects* effects) {
    SkScalerContextRec keyRec;
    SkScalerContext::MakeRecAndEffects(paint, props, matrix, flags, deviceRec, effects, true);
    SkScalerContext::MakeRecAndEffects(paint, props, matrix, flags, &keyRec, effects, false);
    TRACE_EVENT1("skia", "RecForDesc", "rec", TRACE_STR_COPY(keyRec.dump().c_str()));

    // TODO: possible perf improvement - don't recompute the device desc on cache hit.
    auto deviceDesc = SkScalerContext::DescriptorGivenRecAndEffects(*deviceRec, *effects);
    auto keyDesc = SkScalerContext::DescriptorGivenRecAndEffects(keyRec, *effects);

    // Already locked.
    if (fLockedDescs.find(keyDesc.get()) != fLockedDescs.end()) {
        auto it = fRemoteGlyphStateMap.find(keyDesc.get());
        SkASSERT(it != fRemoteGlyphStateMap.end());
        return it->second.get();
    }

    // Try to lock.
    auto it = fRemoteGlyphStateMap.find(keyDesc.get());
    if (it != fRemoteGlyphStateMap.end()) {
        SkASSERT(it->second->getDeviceDescriptor() == *deviceDesc);
        bool locked = fDiscardableHandleManager->lockHandle(it->second->discardable_handle_id());
        if (locked) {
            fLockedDescs.insert(it->first);
            return it->second.get();
        }

        // If the lock failed, the entry was deleted on the client. Remove our
        // tracking.
        fRemoteGlyphStateMap.erase(it);
    }

    auto* tf = paint.getTypeface();
    const SkFontID typefaceId = tf->uniqueID();
    if (!fCachedTypefaces.contains(typefaceId)) {
        fCachedTypefaces.add(typefaceId);
        fTypefacesToSend.emplace_back(typefaceId, tf->countGlyphs(), tf->fontStyle(),
                                      tf->isFixedPitch());
    }

    auto* keyDescPtr = keyDesc.get();
    auto newHandle = fDiscardableHandleManager->createHandle();
    auto cacheState = skstd::make_unique<SkGlyphCacheState>(std::move(deviceDesc),
                                                            std::move(keyDesc), newHandle);
    auto* cacheStatePtr = cacheState.get();

    fLockedDescs.insert(keyDescPtr);
    fRemoteGlyphStateMap[keyDescPtr] = std::move(cacheState);
    return cacheStatePtr;
}

SkStrikeServer::SkGlyphCacheState::SkGlyphCacheState(std::unique_ptr<SkDescriptor> deviceDescriptor,
                                                     std::unique_ptr<SkDescriptor>
                                                             keyDescriptor,
                                                     uint32_t discardable_handle_id)
        : fDeviceDescriptor(std::move(deviceDescriptor))
        , fKeyDescriptor(std::move(keyDescriptor))
        , fDiscardableHandleId(discardable_handle_id) {
    SkASSERT(fDeviceDescriptor);
    SkASSERT(fKeyDescriptor);
}

SkStrikeServer::SkGlyphCacheState::~SkGlyphCacheState() = default;

void SkStrikeServer::SkGlyphCacheState::addGlyph(SkTypeface* typeface,
                                                 const SkScalerContextEffects& effects,
                                                 SkPackedGlyphID glyph,
                                                 bool asPath) {
    auto* cache = asPath ? &fCachedGlyphPaths : &fCachedGlyphImages;
    auto* pending = asPath ? &fPendingGlyphPaths : &fPendingGlyphImages;

    // Already cached.
    if (cache->contains(glyph)) return;

    // Serialize and cache. Also create the scalar context to use when serializing
    // this glyph.
    cache->add(glyph);
    pending->push_back(glyph);
    if (!fContext) {
        fContext = typeface->createScalerContext(effects, fDeviceDescriptor.get(), false);
    }
}

void SkStrikeServer::SkGlyphCacheState::writePendingGlyphs(Serializer* serializer) {
    // Write the desc.
    serializer->emplace<StrikeSpec>(fContext->getTypeface()->uniqueID(), fDiscardableHandleId);
    serializer->writeDescriptor(*fKeyDescriptor.get());

    // Write FontMetrics.
    // TODO(khushalsagar): Do we need to re-send each time?
    SkPaint::FontMetrics fontMetrics;
    fContext->getFontMetrics(&fontMetrics);
    serializer->write<SkPaint::FontMetrics>(fontMetrics);

    // Write glyphs images.
    serializer->emplace<size_t>(fPendingGlyphImages.size());
    for (const auto& glyphID : fPendingGlyphImages) {
        auto glyph = serializer->emplace<SkGlyph>();
        glyph->initWithGlyphID(glyphID);
        fContext->getMetrics(glyph);
        glyph->fPathData = nullptr;
        glyph->fImage = nullptr;

        // Glyphs which are too large for the atlas still request images when computing the bounds
        // for the glyph, which is why its necessary to send both. See related code in
        // get_packed_glyph_bounds in GrGlyphCache.cpp and crbug.com/510931.
        bool tooLargeForAtlas = false;
#if SK_SUPPORT_GPU
        tooLargeForAtlas = GrDrawOpAtlas::GlyphTooLargeForAtlas(glyph->fWidth, glyph->fHeight);
#endif
        if (tooLargeForAtlas) {
            // Add this to the path cache, since we will always fall back to using paths
            // for this glyph.
            fCachedGlyphPaths.add(glyphID);
            writeGlyphPath(glyphID, serializer);
        }

        auto imageSize = glyph->computeImageSize();
        if (imageSize == 0u) continue;

        // Since the allocate can move glyph, make one that stays in one place.
        SkGlyph stationaryGlyph = *glyph;
        stationaryGlyph.fImage = serializer->allocate(imageSize, stationaryGlyph.formatAlignment());
        fContext->getImage(stationaryGlyph);
    }
    fPendingGlyphImages.clear();

    // Write glyphs paths.
    serializer->emplace<size_t>(fPendingGlyphPaths.size());
    for (const auto& glyphID : fPendingGlyphPaths) {
        auto glyph = serializer->emplace<SkGlyph>();
        glyph->initWithGlyphID(glyphID);
        fContext->getMetrics(glyph);
        glyph->fPathData = nullptr;
        glyph->fImage = nullptr;
        writeGlyphPath(glyphID, serializer);
    }
    fPendingGlyphPaths.clear();

    // Note that we reset the context after serializing pending glyphs since we
    // don't want to extend the lifetime of the typeface.
    fContext.reset();
}

void SkStrikeServer::SkGlyphCacheState::writeGlyphPath(const SkPackedGlyphID& glyphID,
                                                       Serializer* serializer) const {
    SkPath path;
    if (!fContext->getPath(glyphID, &path)) {
        serializer->write<size_t>(0u);
        return;
    }

    size_t pathSize = path.writeToMemory(nullptr);
    serializer->write<size_t>(pathSize);
    path.writeToMemory(serializer->allocate(pathSize, kPathAlignment));
}

// SkStrikeClient -----------------------------------------

class SkStrikeClient::DiscardableStrikePinner : public SkStrikePinner {
public:
    DiscardableStrikePinner(SkDiscardableHandleId discardableHandleId,
                            sk_sp<DiscardableHandleManager> manager)
            : fDiscardableHandleId(discardableHandleId), fManager(std::move(manager)) {}

    ~DiscardableStrikePinner() override = default;
    bool canDelete() override { return fManager->deleteHandle(fDiscardableHandleId); }

private:
    const SkDiscardableHandleId fDiscardableHandleId;
    sk_sp<DiscardableHandleManager> fManager;
};

SkStrikeClient::SkStrikeClient(sk_sp<DiscardableHandleManager> discardableManager, bool isLogging)
        : fDiscardableHandleManager(std::move(discardableManager))
        , fIsLogging{isLogging} {}

SkStrikeClient::~SkStrikeClient() = default;

#define READ_FAILURE                      \
    {                                     \
        SkDEBUGFAIL("Bad serialization"); \
        return false;                     \
    }

bool SkStrikeClient::readStrikeData(const volatile void* memory, size_t memorySize) {
    SkASSERT(memorySize != 0u);
    Deserializer deserializer(static_cast<const volatile char*>(memory), memorySize);

    size_t typefaceSize = 0u;
    if (!deserializer.read<size_t>(&typefaceSize)) READ_FAILURE

    for (size_t i = 0; i < typefaceSize; ++i) {
        WireTypeface wire;
        if (!deserializer.read<WireTypeface>(&wire)) READ_FAILURE

        // TODO(khushalsagar): The typeface no longer needs a reference to the
        // SkStrikeClient, since all needed glyphs must have been pushed before
        // raster.
        addTypeface(wire);
    }

    size_t strikeCount = 0u;
    if (!deserializer.read<size_t>(&strikeCount)) READ_FAILURE

    for (size_t i = 0; i < strikeCount; ++i) {
        bool has_glyphs = false;
        if (!deserializer.read<bool>(&has_glyphs)) READ_FAILURE

        if (!has_glyphs) continue;

        StrikeSpec spec;
        if (!deserializer.read<StrikeSpec>(&spec)) READ_FAILURE

        SkAutoDescriptor sourceAd;
        if (!deserializer.readDescriptor(&sourceAd)) READ_FAILURE

        SkPaint::FontMetrics fontMetrics;
        if (!deserializer.read<SkPaint::FontMetrics>(&fontMetrics)) READ_FAILURE

        // Get the local typeface from remote fontID.
        auto* tf = fRemoteFontIdToTypeface.find(spec.typefaceID)->get();
        // Received strikes for a typeface which doesn't exist.
        if (!tf) READ_FAILURE

        // Replace the ContextRec in the desc from the server to create the client
        // side descriptor.
        // TODO: Can we do this in-place and re-compute checksum? Instead of a complete copy.
        SkAutoDescriptor ad;
        auto* client_desc = auto_descriptor_from_desc(sourceAd.getDesc(), tf->uniqueID(), &ad);

        auto strike = SkStrikeCache::FindStrikeExclusive(*client_desc);
        if (strike == nullptr) {
            // Note that we don't need to deserialize the effects since we won't be generating any
            // glyphs here anyway, and the desc is still correct since it includes the serialized
            // effects.
            SkScalerContextEffects effects;
            auto scaler = SkStrikeCache::CreateScalerContext(*client_desc, effects, *tf);
            strike = SkStrikeCache::CreateStrikeExclusive(
                    *client_desc, std::move(scaler), &fontMetrics,
                    skstd::make_unique<DiscardableStrikePinner>(spec.discardableHandleId,
                                                                fDiscardableHandleManager));
        }

        size_t glyphImagesCount = 0u;
        if (!deserializer.read<size_t>(&glyphImagesCount)) READ_FAILURE
        for (size_t j = 0; j < glyphImagesCount; j++) {
            SkGlyph glyph;
            if (!deserializer.read<SkGlyph>(&glyph)) READ_FAILURE

            SkGlyph* allocatedGlyph = strike->getRawGlyphByID(glyph.getPackedID());
            // Don't override the path, if the glyph has one.
            auto* glyphPath = allocatedGlyph->fPathData;
            *allocatedGlyph = glyph;
            allocatedGlyph->fPathData = glyphPath;

            bool tooLargeForAtlas = false;
#if SK_SUPPORT_GPU
            tooLargeForAtlas = GrDrawOpAtlas::GlyphTooLargeForAtlas(glyph.fWidth, glyph.fHeight);
#endif
            if (tooLargeForAtlas) {
                if (!read_path(&deserializer, allocatedGlyph, strike.get())) READ_FAILURE
            }

            auto imageSize = glyph.computeImageSize();
            if (imageSize == 0u) continue;

            auto* image = deserializer.read(imageSize, allocatedGlyph->formatAlignment());
            if (!image ||
                !strike->initializeImage(image, imageSize, allocatedGlyph))
                READ_FAILURE
        }

        size_t glyphPathsCount = 0u;
        if (!deserializer.read<size_t>(&glyphPathsCount)) READ_FAILURE
        for (size_t j = 0; j < glyphPathsCount; j++) {
            SkGlyph glyph;
            if (!deserializer.read<SkGlyph>(&glyph)) READ_FAILURE

            SkGlyph* allocatedGlyph = strike->getRawGlyphByID(glyph.getPackedID());
            // Don't override the image, if the glyph has one.
            auto* glyphImage = allocatedGlyph->fImage;
            *allocatedGlyph = glyph;
            allocatedGlyph->fImage = glyphImage;

            if (!read_path(&deserializer, allocatedGlyph, strike.get())) READ_FAILURE
        }
    }

    return true;
}

sk_sp<SkTypeface> SkStrikeClient::deserializeTypeface(const void* buf, size_t len) {
    WireTypeface wire;
    if (len != sizeof(wire)) return nullptr;
    memcpy(&wire, buf, sizeof(wire));
    return addTypeface(wire);
}

sk_sp<SkTypeface> SkStrikeClient::addTypeface(const WireTypeface& wire) {
    auto* typeface = fRemoteFontIdToTypeface.find(wire.typefaceID);
    if (typeface) return *typeface;

    auto newTypeface = sk_make_sp<SkTypefaceProxy>(
            wire.typefaceID, wire.glyphCount, wire.style, wire.isFixed,
            fDiscardableHandleManager, fIsLogging);
    fRemoteFontIdToTypeface.set(wire.typefaceID, newTypeface);
    return std::move(newTypeface);
}
