/*
 * 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 "include/private/chromium/SkChromeRemoteGlyphCache.h"

#include "include/core/SkCanvas.h"
#include "include/core/SkColorSpace.h"
#include "include/core/SkData.h"
#include "include/core/SkDrawable.h"
#include "include/core/SkFontMetrics.h"
#include "include/core/SkImageInfo.h"
#include "include/core/SkMatrix.h"
#include "include/core/SkPicture.h"
#include "include/core/SkRect.h"
#include "include/core/SkSize.h"
#include "include/core/SkString.h"
#include "include/core/SkSurfaceProps.h"
#include "include/core/SkTypeface.h"
#include "include/private/base/SkAssert.h"
#include "include/private/base/SkDebug.h"
#include "include/private/base/SkPoint_impl.h"
#include "include/private/base/SkTFitsIn.h"
#include "include/private/base/SkTo.h"
#include "include/private/chromium/Slug.h"
#include "src/base/SkArenaAlloc.h"
#include "src/core/SkDescriptor.h"
#include "src/core/SkDevice.h"
#include "src/core/SkFontMetricsPriv.h"
#include "src/core/SkGlyph.h"
#include "src/core/SkReadBuffer.h"
#include "src/core/SkScalerContext.h"
#include "src/core/SkStrike.h"
#include "src/core/SkStrikeCache.h"
#include "src/core/SkStrikeSpec.h"
#include "src/core/SkTHash.h"
#include "src/core/SkTraceEvent.h"
#include "src/core/SkTypeface_remote.h"
#include "src/core/SkWriteBuffer.h"
#include "src/text/GlyphRun.h"
#include "src/text/StrikeForGPU.h"
#include "src/text/gpu/SDFTControl.h"
#include "src/text/gpu/SubRunAllocator.h"
#include "src/text/gpu/SubRunContainer.h"
#include "src/text/gpu/TextBlob.h"

#include <cstring>
#include <memory>
#include <optional>
#include <unordered_map>
#include <utility>

class SkPaint;

using namespace skia_private;
using namespace sktext;
using namespace sktext::gpu;
using namespace skglyph;

namespace {

// -- StrikeSpec -----------------------------------------------------------------------------------
struct StrikeSpec {
    StrikeSpec() = default;
    StrikeSpec(SkTypefaceID typefaceID, SkDiscardableHandleId discardableHandleId)
            : fTypefaceID{typefaceID}, fDiscardableHandleId(discardableHandleId) {}
    SkTypefaceID fTypefaceID = 0u;
    SkDiscardableHandleId fDiscardableHandleId = 0u;
};

// -- RemoteStrike ----------------------------------------------------------------------------
class RemoteStrike final : public sktext::StrikeForGPU {
public:
    // N.B. RemoteStrike is not valid until ensureScalerContext is called.
    RemoteStrike(const SkStrikeSpec& strikeSpec,
                 std::unique_ptr<SkScalerContext> context,
                 SkDiscardableHandleId discardableHandleId);
    ~RemoteStrike() override = default;

    void lock() override {}
    void unlock() override {}
    SkGlyphDigest digestFor(skglyph::ActionType, SkPackedGlyphID) override;
    bool prepareForImage(SkGlyph* glyph) override {
        this->ensureScalerContext();
        glyph->setImage(&fAlloc, fContext.get());
        return glyph->image() != nullptr;
    }
    bool prepareForPath(SkGlyph* glyph) override {
        this->ensureScalerContext();
        glyph->setPath(&fAlloc, fContext.get());
        return glyph->path() != nullptr;
    }
    bool prepareForDrawable(SkGlyph* glyph) override {
        this->ensureScalerContext();
        glyph->setDrawable(&fAlloc, fContext.get());
        return glyph->drawable() != nullptr;
    }

    void writePendingGlyphs(SkWriteBuffer& buffer);

    SkDiscardableHandleId discardableHandleId() const { return fDiscardableHandleId; }

    const SkDescriptor& getDescriptor() const override {
        return *fDescriptor.getDesc();
    }

    void setStrikeSpec(const SkStrikeSpec& strikeSpec);

    const SkGlyphPositionRoundingSpec& roundingSpec() const override {
        return fRoundingSpec;
    }

    sktext::SkStrikePromise strikePromise() override;

    bool hasPendingGlyphs() const {
        return !fMasksToSend.empty() || !fPathsToSend.empty() || !fDrawablesToSend.empty();
    }

    void resetScalerContext();

private:
    void ensureScalerContext();

    const SkAutoDescriptor fDescriptor;
    const SkDiscardableHandleId fDiscardableHandleId;

    const SkGlyphPositionRoundingSpec fRoundingSpec;

    // The context built using fDescriptor
    std::unique_ptr<SkScalerContext> fContext;

    // fStrikeSpec is set every time getOrCreateCache is called. This allows the code to maintain
    // the fContext as lazy as possible.
    const SkStrikeSpec* fStrikeSpec;

    // Have the metrics been sent for this strike. Only send them once.
    bool fHaveSentFontMetrics{false};

    // The masks and paths that currently reside in the GPU process.
    THashTable<SkGlyphDigest, SkPackedGlyphID, SkGlyphDigest> fSentGlyphs;

    // The Masks, SDFT Mask, and Paths that need to be sent to the GPU task for the processed
    // TextBlobs. Cleared after diffs are serialized.
    std::vector<SkGlyph> fMasksToSend;
    std::vector<SkGlyph> fPathsToSend;
    std::vector<SkGlyph> fDrawablesToSend;

    // Alloc for storing bits and pieces of paths and drawables, Cleared after diffs are serialized.
    SkArenaAllocWithReset fAlloc{256};
};

RemoteStrike::RemoteStrike(
        const SkStrikeSpec& strikeSpec,
        std::unique_ptr<SkScalerContext> context,
        uint32_t discardableHandleId)
        : fDescriptor{strikeSpec.descriptor()}
        , fDiscardableHandleId(discardableHandleId)
        , fRoundingSpec{context->isSubpixel(), context->computeAxisAlignmentForHText()}
        // N.B. context must come last because it is used above.
        , fContext{std::move(context)} {
    SkASSERT(fDescriptor.getDesc() != nullptr);
    SkASSERT(fContext != nullptr);
}

void RemoteStrike::writePendingGlyphs(SkWriteBuffer& buffer) {
    SkASSERT(this->hasPendingGlyphs());

    buffer.writeUInt(fContext->getTypeface()->uniqueID());
    buffer.writeUInt(fDiscardableHandleId);
    fDescriptor.getDesc()->flatten(buffer);

    buffer.writeBool(fHaveSentFontMetrics);
    if (!fHaveSentFontMetrics) {
        // Write FontMetrics if not sent before.
        SkFontMetrics fontMetrics;
        fContext->getFontMetrics(&fontMetrics);
        SkFontMetricsPriv::Flatten(buffer, fontMetrics);
        fHaveSentFontMetrics = true;
    }

    // Make sure to install all the mask data into the glyphs before sending.
    for (SkGlyph& glyph: fMasksToSend) {
        this->prepareForImage(&glyph);
    }

    // Make sure to install all the path data into the glyphs before sending.
    for (SkGlyph& glyph: fPathsToSend) {
        this->prepareForPath(&glyph);
    }

    // Make sure to install all the drawable data into the glyphs before sending.
    for (SkGlyph& glyph: fDrawablesToSend) {
        this->prepareForDrawable(&glyph);
    }

    // Send all the pending glyph information.
    SkStrike::FlattenGlyphsByType(buffer, fMasksToSend, fPathsToSend, fDrawablesToSend);

    // Reset all the sending data.
    fMasksToSend.clear();
    fPathsToSend.clear();
    fDrawablesToSend.clear();
    fAlloc.reset();
}

void RemoteStrike::ensureScalerContext() {
    if (fContext == nullptr) {
        fContext = fStrikeSpec->createScalerContext();
    }
}

void RemoteStrike::resetScalerContext() {
    fContext = nullptr;
    fStrikeSpec = nullptr;
}

void RemoteStrike::setStrikeSpec(const SkStrikeSpec& strikeSpec) {
    fStrikeSpec = &strikeSpec;
}

SkGlyphDigest RemoteStrike::digestFor(ActionType actionType, SkPackedGlyphID packedGlyphID) {
    SkGlyphDigest* digestPtr = fSentGlyphs.find(packedGlyphID);
    if (digestPtr != nullptr && digestPtr->actionFor(actionType) != GlyphAction::kUnset) {
        return *digestPtr;
    }

    SkGlyph* glyph;
    this->ensureScalerContext();
    switch (actionType) {
        case skglyph::kPath: {
            fPathsToSend.emplace_back(fContext->makeGlyph(packedGlyphID, &fAlloc));
            glyph = &fPathsToSend.back();
            break;
        }
        case skglyph::kDrawable: {
            fDrawablesToSend.emplace_back(fContext->makeGlyph(packedGlyphID, &fAlloc));
            glyph = &fDrawablesToSend.back();
            break;
        }
        default: {
            fMasksToSend.emplace_back(fContext->makeGlyph(packedGlyphID, &fAlloc));
            glyph = &fMasksToSend.back();
            break;
        }
    }

    if (digestPtr == nullptr) {
        digestPtr = fSentGlyphs.set(SkGlyphDigest{0, *glyph});
    }

    digestPtr->setActionFor(actionType, glyph, this);

    return *digestPtr;
}

sktext::SkStrikePromise RemoteStrike::strikePromise() {
    return sktext::SkStrikePromise{*this->fStrikeSpec};
}
}  // namespace

// -- SkStrikeServerImpl ---------------------------------------------------------------------------
class SkStrikeServerImpl final : public sktext::StrikeForGPUCacheInterface {
public:
    explicit SkStrikeServerImpl(
            SkStrikeServer::DiscardableHandleManager* discardableHandleManager);

    // SkStrikeServer API methods
    void writeStrikeData(std::vector<uint8_t>* memory);

    sk_sp<sktext::StrikeForGPU> findOrCreateScopedStrike(const SkStrikeSpec& strikeSpec) override;

    // Methods for testing
    void setMaxEntriesInDescriptorMapForTesting(size_t count);
    size_t remoteStrikeMapSizeForTesting() const;

private:
    inline static constexpr size_t kMaxEntriesInDescriptorMap = 2000u;

    void checkForDeletedEntries();

    sk_sp<RemoteStrike> getOrCreateCache(const SkStrikeSpec& strikeSpec);

    struct MapOps {
        size_t operator()(const SkDescriptor* key) const {
            return key->getChecksum();
        }
        bool operator()(const SkDescriptor* lhs, const SkDescriptor* rhs) const {
            return *lhs == *rhs;
        }
    };

    using DescToRemoteStrike =
        std::unordered_map<const SkDescriptor*, sk_sp<RemoteStrike>, MapOps, MapOps>;
    DescToRemoteStrike fDescToRemoteStrike;

    SkStrikeServer::DiscardableHandleManager* const fDiscardableHandleManager;
    THashSet<SkTypefaceID> fCachedTypefaces;
    size_t fMaxEntriesInDescriptorMap = kMaxEntriesInDescriptorMap;

    // State cached until the next serialization.
    THashSet<RemoteStrike*> fRemoteStrikesToSend;
    std::vector<SkTypefaceProxyPrototype> fTypefacesToSend;
};

SkStrikeServerImpl::SkStrikeServerImpl(SkStrikeServer::DiscardableHandleManager* dhm)
        : fDiscardableHandleManager(dhm) {
    SkASSERT(fDiscardableHandleManager);
}

void SkStrikeServerImpl::setMaxEntriesInDescriptorMapForTesting(size_t count) {
    fMaxEntriesInDescriptorMap = count;
}
size_t SkStrikeServerImpl::remoteStrikeMapSizeForTesting() const {
    return fDescToRemoteStrike.size();
}

void SkStrikeServerImpl::writeStrikeData(std::vector<uint8_t>* memory) {
    // We can use the default SkSerialProcs because we do not currently need to encode any SkImages.
    SkBinaryWriteBuffer buffer{nullptr, 0, {}};

    // Gather statistics about what needs to be sent.
    size_t strikesToSend = 0;
    fRemoteStrikesToSend.foreach([&](RemoteStrike* strike) {
        if (strike->hasPendingGlyphs()) {
            strikesToSend++;
        } else {
            // This strike has nothing to send, so drop its scaler context to reduce memory.
            strike->resetScalerContext();
        }
    });

    // If there are no strikes or typefaces to send, then cleanup and return.
    if (strikesToSend == 0 && fTypefacesToSend.empty()) {
        fRemoteStrikesToSend.reset();
        return;
    }

    // Send newly seen typefaces.
    SkASSERT_RELEASE(SkTFitsIn<int>(fTypefacesToSend.size()));
    buffer.writeInt(fTypefacesToSend.size());
    for (const auto& typeface: fTypefacesToSend) {
        SkTypefaceProxyPrototype proto{typeface};
        proto.flatten(buffer);
    }
    fTypefacesToSend.clear();

    buffer.writeInt(strikesToSend);
    fRemoteStrikesToSend.foreach(
            [&](RemoteStrike* strike) {
                if (strike->hasPendingGlyphs()) {
                    strike->writePendingGlyphs(buffer);
                    strike->resetScalerContext();
                }
            }
    );
    fRemoteStrikesToSend.reset();

    // Copy data into the vector.
    auto data = buffer.snapshotAsData();
    memory->assign(data->bytes(), data->bytes() + data->size());
}

sk_sp<StrikeForGPU> SkStrikeServerImpl::findOrCreateScopedStrike(
        const SkStrikeSpec& strikeSpec) {
    return this->getOrCreateCache(strikeSpec);
}

void SkStrikeServerImpl::checkForDeletedEntries() {
    auto it = fDescToRemoteStrike.begin();
    while (fDescToRemoteStrike.size() > fMaxEntriesInDescriptorMap &&
           it != fDescToRemoteStrike.end()) {
        RemoteStrike* strike = it->second.get();
        if (fDiscardableHandleManager->isHandleDeleted(strike->discardableHandleId())) {
            // If we are trying to send the strike, then do not erase it.
            if (!fRemoteStrikesToSend.contains(strike)) {
                // Erase returns the iterator following the removed element.
                it = fDescToRemoteStrike.erase(it);
                continue;
            }
        }
        ++it;
    }
}

sk_sp<RemoteStrike> SkStrikeServerImpl::getOrCreateCache(const SkStrikeSpec& strikeSpec) {
    // In cases where tracing is turned off, make sure not to get an unused function warning.
    // Lambdaize the function.
    TRACE_EVENT1("skia", "RecForDesc", "rec",
                 TRACE_STR_COPY(
                         [&strikeSpec](){
                             auto ptr =
                                 strikeSpec.descriptor().findEntry(kRec_SkDescriptorTag, nullptr);
                             SkScalerContextRec rec;
                             std::memcpy((void*)&rec, ptr, sizeof(rec));
                             return rec.dump();
                         }().c_str()
                 )
    );

    if (auto it = fDescToRemoteStrike.find(&strikeSpec.descriptor());
        it != fDescToRemoteStrike.end())
    {
        // We have processed the RemoteStrike before. Reuse it.
        sk_sp<RemoteStrike> strike = it->second;
        strike->setStrikeSpec(strikeSpec);
        if (fRemoteStrikesToSend.contains(strike.get())) {
            // Already tracking
            return strike;
        }

        // Strike is in unknown state on GPU. Start tracking strike on GPU by locking it.
        bool locked = fDiscardableHandleManager->lockHandle(it->second->discardableHandleId());
        if (locked) {
            fRemoteStrikesToSend.add(strike.get());
            return strike;
        }

        // If it wasn't locked, then forget this strike, and build it anew below.
        fDescToRemoteStrike.erase(it);
    }

    const SkTypeface& typeface = strikeSpec.typeface();
    // Create a new RemoteStrike. Start by processing the typeface.
    const SkTypefaceID typefaceId = typeface.uniqueID();
    if (!fCachedTypefaces.contains(typefaceId)) {
        fCachedTypefaces.add(typefaceId);
        fTypefacesToSend.emplace_back(typeface);
    }

    auto context = strikeSpec.createScalerContext();
    auto newHandle = fDiscardableHandleManager->createHandle();  // Locked on creation
    auto remoteStrike = sk_make_sp<RemoteStrike>(strikeSpec, std::move(context), newHandle);
    remoteStrike->setStrikeSpec(strikeSpec);
    fRemoteStrikesToSend.add(remoteStrike.get());
    auto d = &remoteStrike->getDescriptor();
    fDescToRemoteStrike[d] = remoteStrike;

    checkForDeletedEntries();

    return remoteStrike;
}

// -- GlyphTrackingDevice --------------------------------------------------------------------------
class GlyphTrackingDevice final : public SkNoPixelsDevice {
public:
    GlyphTrackingDevice(
            const SkISize& dimensions, const SkSurfaceProps& props, SkStrikeServerImpl* server,
            sk_sp<SkColorSpace> colorSpace, sktext::gpu::SDFTControl SDFTControl)
            : SkNoPixelsDevice(SkIRect::MakeSize(dimensions), props, std::move(colorSpace))
            , fStrikeServerImpl(server)
            , fSDFTControl(SDFTControl) {
        SkASSERT(fStrikeServerImpl != nullptr);
    }

    sk_sp<SkDevice> createDevice(const CreateInfo& cinfo, const SkPaint*) override {
        const SkSurfaceProps surfaceProps =
            this->surfaceProps().cloneWithPixelGeometry(cinfo.fPixelGeometry);

        return sk_make_sp<GlyphTrackingDevice>(cinfo.fInfo.dimensions(),
                                               surfaceProps,
                                               fStrikeServerImpl,
                                               cinfo.fInfo.refColorSpace(),
                                               fSDFTControl);
    }

    SkStrikeDeviceInfo strikeDeviceInfo() const override {
        return {this->surfaceProps(), this->scalerContextFlags(), &fSDFTControl};
    }

protected:
    void onDrawGlyphRunList(SkCanvas*,
                            const sktext::GlyphRunList& glyphRunList,
                            const SkPaint& paint) override {
        SkMatrix drawMatrix = this->localToDevice();
        drawMatrix.preTranslate(glyphRunList.origin().x(), glyphRunList.origin().y());

        // Just ignore the resulting SubRunContainer. Since we're passing in a null SubRunAllocator
        // no SubRuns will be produced.
        STSubRunAllocator<sizeof(SubRunContainer), alignof(SubRunContainer)> tempAlloc;
        auto container = SubRunContainer::MakeInAlloc(glyphRunList,
                                                      drawMatrix,
                                                      paint,
                                                      this->strikeDeviceInfo(),
                                                      fStrikeServerImpl,
                                                      &tempAlloc,
                                                      SubRunContainer::kStrikeCalculationsOnly,
                                                      "Cache Diff");
        // Calculations only. No SubRuns.
        SkASSERT(container->isEmpty());
    }

    sk_sp<sktext::gpu::Slug> convertGlyphRunListToSlug(const sktext::GlyphRunList& glyphRunList,
                                                       const SkPaint& paint) override {
        // Full matrix for placing glyphs.
        SkMatrix positionMatrix = this->localToDevice();
        positionMatrix.preTranslate(glyphRunList.origin().x(), glyphRunList.origin().y());

        // Use the SkStrikeServer's strike cache to generate the Slug.
        return sktext::gpu::MakeSlug(this->localToDevice(),
                                     glyphRunList,
                                     paint,
                                     this->strikeDeviceInfo(),
                                     fStrikeServerImpl);
    }

private:
    SkStrikeServerImpl* const fStrikeServerImpl;
    const sktext::gpu::SDFTControl fSDFTControl;
};

// -- SkStrikeServer -------------------------------------------------------------------------------
SkStrikeServer::SkStrikeServer(DiscardableHandleManager* dhm)
        : fImpl(new SkStrikeServerImpl{dhm}) { }

SkStrikeServer::~SkStrikeServer() = default;

std::unique_ptr<SkCanvas> SkStrikeServer::makeAnalysisCanvas(int width, int height,
                                                             const SkSurfaceProps& props,
                                                             sk_sp<SkColorSpace> colorSpace,
                                                             bool DFTSupport,
                                                             bool DFTPerspSupport) {
#if !defined(SK_DISABLE_SDF_TEXT)
    // These are copied from the defaults in GrContextOptions for historical reasons.
    // TODO(herb, jvanverth) pipe in parameters that can be used for both Ganesh and Graphite
    // backends instead of just using the defaults.
    constexpr float kMinDistanceFieldFontSize = 18.f;

#if defined(SK_BUILD_FOR_ANDROID)
    constexpr float kGlyphsAsPathsFontSize = 384.f;
#elif defined(SK_BUILD_FOR_MAC)
    constexpr float kGlyphsAsPathsFontSize = 256.f;
#else
    constexpr float kGlyphsAsPathsFontSize = 324.f;
#endif
    auto control = sktext::gpu::SDFTControl{DFTSupport,
                                            props.isUseDeviceIndependentFonts(),
                                            DFTPerspSupport,
                                            kMinDistanceFieldFontSize,
                                            kGlyphsAsPathsFontSize};
#else
    auto control = sktext::gpu::SDFTControl{};
#endif

    sk_sp<SkDevice> trackingDevice = sk_make_sp<GlyphTrackingDevice>(
            SkISize::Make(width, height),
            props, this->impl(),
            std::move(colorSpace),
            control);
    return std::make_unique<SkCanvas>(std::move(trackingDevice));
}

void SkStrikeServer::writeStrikeData(std::vector<uint8_t>* memory) {
    fImpl->writeStrikeData(memory);
}

SkStrikeServerImpl* SkStrikeServer::impl() { return fImpl.get(); }

void SkStrikeServer::setMaxEntriesInDescriptorMapForTesting(size_t count) {
    fImpl->setMaxEntriesInDescriptorMapForTesting(count);
}
size_t SkStrikeServer::remoteStrikeMapSizeForTesting() const {
    return fImpl->remoteStrikeMapSizeForTesting();
}

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

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

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

// -- SkStrikeClientImpl ---------------------------------------------------------------------------
class SkStrikeClientImpl {
public:
    explicit SkStrikeClientImpl(sk_sp<SkStrikeClient::DiscardableHandleManager>,
                                bool isLogging = true,
                                SkStrikeCache* strikeCache = nullptr);

    bool readStrikeData(const volatile void* memory, size_t memorySize);
    bool translateTypefaceID(SkAutoDescriptor* descriptor) const;
    sk_sp<SkTypeface> retrieveTypefaceUsingServerID(SkTypefaceID) const;

private:
    class PictureBackedGlyphDrawable final : public SkDrawable {
    public:
        PictureBackedGlyphDrawable(sk_sp<SkPicture> self) : fSelf(std::move(self)) {}
    private:
        sk_sp<SkPicture> fSelf;
        SkRect onGetBounds() override { return fSelf->cullRect();  }
        size_t onApproximateBytesUsed() override {
            return sizeof(PictureBackedGlyphDrawable) + fSelf->approximateBytesUsed();
        }
        void onDraw(SkCanvas* canvas) override { canvas->drawPicture(fSelf); }
    };

    sk_sp<SkTypeface> addTypeface(const SkTypefaceProxyPrototype& typefaceProto);

    THashMap<SkTypefaceID, sk_sp<SkTypeface>> fServerTypefaceIdToTypeface;
    sk_sp<SkStrikeClient::DiscardableHandleManager> fDiscardableHandleManager;
    SkStrikeCache* const fStrikeCache;
    const bool fIsLogging;
};

SkStrikeClientImpl::SkStrikeClientImpl(
        sk_sp<SkStrikeClient::DiscardableHandleManager>
        discardableManager,
        bool isLogging,
        SkStrikeCache* strikeCache)
    : fDiscardableHandleManager(std::move(discardableManager)),
      fStrikeCache{strikeCache ? strikeCache : SkStrikeCache::GlobalStrikeCache()},
      fIsLogging{isLogging} {}

// Change the path count to track the line number of the failing read.
// TODO: change __LINE__ back to glyphPathsCount when bug chromium:1287356 is closed.
#define READ_FAILURE                                                        \
    {                                                                       \
        SkDebugf("Bad font data serialization line: %d", __LINE__);         \
        SkStrikeClient::DiscardableHandleManager::ReadFailureData data = {  \
                memorySize,  deserializer.bytesRead(), typefaceSize,        \
                strikeCount, glyphImagesCount, __LINE__};                   \
        fDiscardableHandleManager->notifyReadFailure(data);                 \
        return false;                                                       \
    }

bool SkStrikeClientImpl::readStrikeData(const volatile void* memory, size_t memorySize) {
    SkASSERT(memorySize != 0);
    SkASSERT(memory != nullptr);

    // We do not need to set any SkDeserialProcs here because SkStrikeServerImpl::writeStrikeData
    // did not encode any SkImages.
    SkReadBuffer buffer{const_cast<const void*>(memory), memorySize};
    // Limit the kinds of effects that appear in a glyph's drawable (crbug.com/1442140):
    buffer.setAllowSkSL(false);

    int curTypeface = 0,
        curStrike = 0;

    auto postError = [&](int line) {
        SkDebugf("Read Error Posted %s : %d", __FILE__, line);
        SkStrikeClient::DiscardableHandleManager::ReadFailureData data{
                memorySize,
                buffer.offset(),
                SkTo<uint64_t>(curTypeface),
                SkTo<uint64_t>(curStrike),
                SkTo<uint64_t>(0),
                SkTo<uint64_t>(0)};
        fDiscardableHandleManager->notifyReadFailure(data);
    };

    // Read the number of typefaces sent.
    const int typefaceCount = buffer.readInt();
    for (curTypeface = 0; curTypeface < typefaceCount; ++curTypeface) {
        auto proto = SkTypefaceProxyPrototype::MakeFromBuffer(buffer);
        if (proto) {
            this->addTypeface(proto.value());
        } else {
            postError(__LINE__);
            return false;
        }
    }

    // Read the number of strikes sent.
    const int stirkeCount = buffer.readInt();
    for (curStrike = 0; curStrike < stirkeCount; ++curStrike) {

        const SkTypefaceID serverTypefaceID = buffer.readUInt();
        if (serverTypefaceID == 0 && !buffer.isValid()) {
            postError(__LINE__);
            return false;
        }

        const SkDiscardableHandleId discardableHandleID = buffer.readUInt();
        if (discardableHandleID == 0 && !buffer.isValid()) {
            postError(__LINE__);
            return false;
        }

        std::optional<SkAutoDescriptor> serverDescriptor = SkAutoDescriptor::MakeFromBuffer(buffer);
        if (!buffer.validate(serverDescriptor.has_value())) {
            postError(__LINE__);
            return false;
        }

        const bool fontMetricsInitialized = buffer.readBool();
        if (!fontMetricsInitialized && !buffer.isValid()) {
            postError(__LINE__);
            return false;
        }

        std::optional<SkFontMetrics> fontMetrics;
        if (!fontMetricsInitialized) {
            fontMetrics = SkFontMetricsPriv::MakeFromBuffer(buffer);
            if (!fontMetrics || !buffer.isValid()) {
                postError(__LINE__);
                return false;
            }
        }

        auto* clientTypeface = fServerTypefaceIdToTypeface.find(serverTypefaceID);
        if (clientTypeface == nullptr) {
            postError(__LINE__);
            return false;
        }

        if (!this->translateTypefaceID(&serverDescriptor.value())) {
            postError(__LINE__);
            return false;
        }

        SkDescriptor* clientDescriptor = serverDescriptor->getDesc();
        auto strike = fStrikeCache->findStrike(*clientDescriptor);

        if (strike == nullptr) {
            // Metrics are only sent the first time. If creating a new strike, then the metrics
            // are not initialized.
            if (fontMetricsInitialized) {
                postError(__LINE__);
                return false;
            }
            SkStrikeSpec strikeSpec{*clientDescriptor, *clientTypeface};
            strike = fStrikeCache->createStrike(
                    strikeSpec, &fontMetrics.value(),
                    std::make_unique<DiscardableStrikePinner>(
                            discardableHandleID, fDiscardableHandleManager));
        }

        // Make sure this strike is pinned on the GPU side.
        strike->verifyPinnedStrike();

        if (!strike->mergeFromBuffer(buffer)) {
            postError(__LINE__);
            return false;
        }
    }

    return true;
}

bool SkStrikeClientImpl::translateTypefaceID(SkAutoDescriptor* toChange) const {
    SkDescriptor& descriptor = *toChange->getDesc();

    // Rewrite the typefaceID in the rec.
    {
        uint32_t size;
        // findEntry returns a const void*, remove the const in order to update in place.
        void* ptr = const_cast<void *>(descriptor.findEntry(kRec_SkDescriptorTag, &size));
        SkScalerContextRec rec;
        if (!ptr || size != sizeof(rec)) { return false; }
        std::memcpy((void*)&rec, ptr, size);
        // Get the local typeface from remote typefaceID.
        auto* tfPtr = fServerTypefaceIdToTypeface.find(rec.fTypefaceID);
        // Received a strike for a typeface which doesn't exist.
        if (!tfPtr) { return false; }
        // Update the typeface id to work with the client side.
        rec.fTypefaceID = tfPtr->get()->uniqueID();
        std::memcpy(ptr, &rec, size);
    }

    descriptor.computeChecksum();

    return true;
}

sk_sp<SkTypeface> SkStrikeClientImpl::retrieveTypefaceUsingServerID(SkTypefaceID typefaceID) const {
    auto* tfPtr = fServerTypefaceIdToTypeface.find(typefaceID);
    return tfPtr != nullptr ? *tfPtr : nullptr;
}

sk_sp<SkTypeface> SkStrikeClientImpl::addTypeface(const SkTypefaceProxyPrototype& typefaceProto) {
    sk_sp<SkTypeface>* typeface =
            fServerTypefaceIdToTypeface.find(typefaceProto.serverTypefaceID());

    // We already have the typeface.
    if (typeface != nullptr)  {
        return *typeface;
    }

    auto newTypeface = sk_make_sp<SkTypefaceProxy>(
            typefaceProto, fDiscardableHandleManager, fIsLogging);
    fServerTypefaceIdToTypeface.set(typefaceProto.serverTypefaceID(), newTypeface);
    return newTypeface;
}

// SkStrikeClient ----------------------------------------------------------------------------------
SkStrikeClient::SkStrikeClient(sk_sp<DiscardableHandleManager> discardableManager,
                               bool isLogging,
                               SkStrikeCache* strikeCache)
       : fImpl{new SkStrikeClientImpl{std::move(discardableManager), isLogging, strikeCache}} {}

SkStrikeClient::~SkStrikeClient() = default;

bool SkStrikeClient::readStrikeData(const volatile void* memory, size_t memorySize) {
    return fImpl->readStrikeData(memory, memorySize);
}

sk_sp<SkTypeface> SkStrikeClient::retrieveTypefaceUsingServerIDForTest(
        SkTypefaceID typefaceID) const {
    return fImpl->retrieveTypefaceUsingServerID(typefaceID);
}

bool SkStrikeClient::translateTypefaceID(SkAutoDescriptor* descriptor) const {
    return fImpl->translateTypefaceID(descriptor);
}

sk_sp<sktext::gpu::Slug> SkStrikeClient::deserializeSlugForTest(const void* data,
                                                                size_t size) const {
    return sktext::gpu::Slug::Deserialize(data, size, this);
}
