/*
 * 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 "SkFindAndPlaceGlyph.h"
#include "SkStrikeCache.h"
#include "SkTextBlobRunIterator.h"
#include "SkTraceEvent.h"
#include "SkTypeface_remote.h"

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;
}

template <typename T>
class ArraySlice final : public std::tuple<const T*, size_t> {
public:
    // Additional constructors as needed.
    ArraySlice(const T* data, size_t size) : fData{data}, fSize{size} { }
    ArraySlice() : ArraySlice<T>(nullptr, 0) { }

    const T* begin() {
        return this->data();
    }
    const T* end() {
        return &this->data()[this->size()];
    }

    const T* data() const {
        return fData;
    }

    size_t size() const {
        return fSize;
    }

private:
    const T* fData;
    size_t   fSize;
};

// -- 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());
    }

    template <typename T>
    T* allocateArray(int count) {
        auto result = allocate(sizeof(T) * count, alignof(T));
        return new (result) T[count];
    }

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

    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;
    }

    template <typename T>
    ArraySlice<T> readArray(int count) {
        size_t size = count * sizeof(T);
        const T* base = (const T*)this->ensureAtLeast(size, alignof(T));
        if (!base) return ArraySlice<T>();

        ArraySlice<T> result = ArraySlice<T>{base, (uint32_t)count};
        return result;
    }

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;
};

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::SkTextBlobCacheDiffCanvas(int width, int height,
                                                     const SkMatrix& deviceMatrix,
                                                     const SkSurfaceProps& props,
                                                     SkStrikeServer* strikeSever)
        : SkNoDrawCanvas{sk_make_sp<TrackLayerDevice>(SkIRect::MakeWH(width, height), props)}
        , fDeviceMatrix{deviceMatrix}
        , fSurfaceProps{props}
        , fStrikeServer{strikeSever} {
    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
    }

    using PosFn = SkPoint(*)(int index, const SkScalar* pos);
    PosFn posFn;
    switch (it.positioning()) {
        case SkTextBlob::kDefault_Positioning: {
            // Default positioning needs advances. Can't do that.
            TRACE_EVENT0("skia", "kDefault_Positioning");
            FAIL_AND_RETURN
        }

        case SkTextBlob::kHorizontal_Positioning:
            posFn = [](int index, const SkScalar* pos) {
                return SkPoint{pos[index], 0};
            };

            break;

        case SkTextBlob::kFull_Positioning:
            posFn = [](int index, const SkScalar* pos) {
                return SkPoint{pos[2 * index], pos[2 * index + 1]};
            };
            break;

        default:
            posFn = nullptr;
            SK_ABORT("unhandled positioning mode");
    }

    SkMatrix blobMatrix{fDeviceMatrix};
    blobMatrix.preConcat(this->getTotalMatrix());
    if (blobMatrix.hasPerspective()) {
        TRACE_EVENT0("skia", "hasPerspective");
        FAIL_AND_RETURN
    }
    blobMatrix.preTranslate(position.x(), position.y());

    SkMatrix runMatrix{blobMatrix};
    runMatrix.preTranslate(it.offset().x(), it.offset().y());

    using MapFn = SkPoint(*)(const SkMatrix& m, SkPoint pt);
    MapFn mapFn;
    switch ((int)runMatrix.getType()) {
        case SkMatrix::kIdentity_Mask:
        case SkMatrix::kTranslate_Mask:
            mapFn = [](const SkMatrix& m, SkPoint pt) {
                pt.offset(m.getTranslateX(), m.getTranslateY());
                return pt;
            };
            break;
        case SkMatrix::kScale_Mask:
        case SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask:
            mapFn = [](const SkMatrix& m, SkPoint pt) {
                return SkPoint{pt.x() * m.getScaleX() + m.getTranslateX(),
                               pt.y() * m.getScaleY() + m.getTranslateY()};
            };
            break;
        case SkMatrix::kAffine_Mask | SkMatrix::kScale_Mask:
        case SkMatrix::kAffine_Mask | SkMatrix::kScale_Mask | SkMatrix::kTranslate_Mask:
            mapFn = [](const SkMatrix& m, SkPoint pt) {
                return SkPoint{
                        pt.x() * m.getScaleX() + pt.y() * m.getSkewX() + m.getTranslateX(),
                        pt.x() * m.getSkewY() + pt.y() * m.getScaleY() + m.getTranslateY()};
            };
            break;
        default:
            mapFn = nullptr;
            SK_ABORT("Bad matrix.");
    }

    SkScalerContextRec deviceSpecificRec;
    SkScalerContextRec keyRec;
    SkScalerContextEffects effects;

    SkScalerContext::MakeRecAndEffects(runPaint, &fSurfaceProps, &runMatrix,
                                       SkScalerContextFlags::kFakeGammaAndBoostContrast,
                                       &deviceSpecificRec,
                                       &effects, true);

    SkScalerContext::MakeRecAndEffects(runPaint, &fSurfaceProps, &runMatrix,
                                       SkScalerContextFlags::kFakeGammaAndBoostContrast,
                                       &keyRec,
                                       &effects, false);


    TRACE_EVENT1("skia", "RecForDesc", "rec", TRACE_STR_COPY(keyRec.dump().c_str()));

    // TODO: possible perf improvement - move descriptor calculation into getOrCreateCache.
    auto deviceDescriptor =
            SkScalerContext::DescriptorGivenRecAndEffects(deviceSpecificRec, effects);
    auto keyDescriptor =
            SkScalerContext::DescriptorGivenRecAndEffects(keyRec, effects);
    auto* glyphCacheState =
            static_cast<SkStrikeServer*>(fStrikeServer)
                    ->getOrCreateCache(
                            runPaint.getTypeface(),
                            std::move(deviceDescriptor),
                            std::move(keyDescriptor));
    SkASSERT(glyphCacheState);

    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 (runPaint.isAntiAlias() && isSubpixel) {
            SkPoint glyphPos = mapFn(runMatrix, posFn(index, pos));
            subPixelPos = SkFindAndPlaceGlyph::SubpixelAlignment(axisAlignment, glyphPos);
        }

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

struct StrikeSpec {
    StrikeSpec() {}
    StrikeSpec(SkFontID typefaceID_, size_t glyphCount_, SkDiscardableHandleId discardableHandleId_)
            : typefaceID{typefaceID_}
            , glyphCount{glyphCount_}
            , discardableHandleId(discardableHandleId_) {}
    SkFontID typefaceID = 0u;
    size_t glyphCount = 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(
        SkTypeface* tf,
        std::unique_ptr<SkDescriptor> deviceDesc,
        std::unique_ptr<SkDescriptor> keyDesc) {
    SkASSERT(deviceDesc);
    SkASSERT(keyDesc);

    // 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);
    }

    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) {
    // Already cached.
    if (fCachedGlyphs.contains(glyph)) return;

    // Serialize and cache. Also create the scalar context to use when serializing
    // this glyph.
    fCachedGlyphs.add(glyph);
    fPendingGlyphs.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(), fPendingGlyphs.size(),
                                    fDiscardableHandleId);
    serializer->writeDescriptor(*fKeyDescriptor.get());

    // Write FontMetrics.
    SkPaint::FontMetrics fontMetrics;
    fContext->getFontMetrics(&fontMetrics);
    serializer->write<SkPaint::FontMetrics>(fontMetrics);

    // Write Glyphs.
    for (const auto& glyphID : fPendingGlyphs) {
        auto glyph = serializer->emplace<SkGlyph>();
        glyph->initWithGlyphID(glyphID);
        fContext->getMetrics(glyph);
        auto imageSize = glyph->computeImageSize();
        glyph->fPathData = nullptr;
        glyph->fImage = nullptr;

        if (imageSize > 0) {
            // Since the allocateArray can move glyph, make one that stays in one place.
            SkGlyph stationaryGlyph = *glyph;
            stationaryGlyph.fImage = serializer->allocateArray<uint8_t>(imageSize);
            fContext->getImage(stationaryGlyph);
        }
    }

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

// 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)
        : fDiscardableHandleManager(std::move(discardableManager)) {}

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));
        }

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

            SkGlyph* allocatedGlyph = strike->getRawGlyphByID(glyph.getPackedID());
            *allocatedGlyph = glyph;

            ArraySlice<uint8_t> image;
            auto imageSize = glyph.computeImageSize();
            if (imageSize != 0) {
                image = deserializer.readArray<uint8_t>(imageSize);
                if (!image.data()) READ_FAILURE
                allocatedGlyph->allocImage(strike->getAlloc());
                memcpy(allocatedGlyph->fImage, image.data(), image.size());
            }
        }
    }

    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, this);
    fRemoteFontIdToTypeface.set(wire.typefaceID, newTypeface);
    return std::move(newTypeface);
}

void SkStrikeClient::generateFontMetrics(const SkTypefaceProxy& typefaceProxy,
                                         const SkScalerContextRec& rec,
                                         SkPaint::FontMetrics* metrics) {
    TRACE_EVENT1("skia", "generateFontMetrics", "rec", TRACE_STR_COPY(rec.dump().c_str()));
    SkDebugf("generateFontMetrics: %s\n", rec.dump().c_str());
    SkStrikeCache::Dump();
    SkDEBUGFAIL("GlyphCacheMiss");
}

void SkStrikeClient::generateMetricsAndImage(const SkTypefaceProxy& typefaceProxy,
                                             const SkScalerContextRec& rec,
                                             SkArenaAlloc* alloc,
                                             SkGlyph* glyph) {
    TRACE_EVENT1("skia", "generateMetricsAndImage", "rec", TRACE_STR_COPY(rec.dump().c_str()));
    SkDebugf("generateMetricsAndImage: %s\n", rec.dump().c_str());
    SkStrikeCache::Dump();
    SkDEBUGFAIL("GlyphCacheMiss");
}

void SkStrikeClient::generatePath(const SkTypefaceProxy& typefaceProxy,
                                  const SkScalerContextRec& rec,
                                  SkGlyphID glyphID,
                                  SkPath* path) {
    TRACE_EVENT1("skia", "generatePath", "rec", TRACE_STR_COPY(rec.dump().c_str()));
    SkDebugf("generatePath: %s\n", rec.dump().c_str());
    SkStrikeCache::Dump();
    SkDEBUGFAIL("GlyphCacheMiss");
}
