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

#include "include/utils/SkCustomTypeface.h"

#include "include/core/SkCanvas.h"
#include "include/core/SkColor.h"
#include "include/core/SkData.h"
#include "include/core/SkDrawable.h"
#include "include/core/SkFontArguments.h"
#include "include/core/SkFontMetrics.h"
#include "include/core/SkFontParameters.h"
#include "include/core/SkFontStyle.h"
#include "include/core/SkFontTypes.h"
#include "include/core/SkMatrix.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPath.h"
#include "include/core/SkPoint.h"
#include "include/core/SkRect.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkScalar.h"
#include "include/core/SkStream.h"
#include "include/core/SkString.h"
#include "include/core/SkTypeface.h"
#include "include/core/SkTypes.h"
#include "include/private/SkFixed.h"
#include "include/private/SkMalloc.h"
#include "include/private/SkTo.h"
#include "src/core/SkAdvancedTypefaceMetrics.h" // IWYU pragma: keep
#include "src/core/SkGlyph.h"
#include "src/core/SkMask.h"
#include "src/core/SkScalerContext.h"

#include <cstddef>
#include <cstdint>
#include <memory>
#include <string>
#include <utility>
#include <vector>

class SkArenaAlloc;
class SkDescriptor;
class SkFontDescriptor;

namespace {
static inline const constexpr bool kSkShowTextBlitCoverage = false;
}

static SkFontMetrics scale_fontmetrics(const SkFontMetrics& src, float sx, float sy) {
    SkFontMetrics dst = src;

    #define SCALE_X(field)  dst.field *= sx
    #define SCALE_Y(field)  dst.field *= sy

    SCALE_X(fAvgCharWidth);
    SCALE_X(fMaxCharWidth);
    SCALE_X(fXMin);
    SCALE_X(fXMax);

    SCALE_Y(fTop);
    SCALE_Y(fAscent);
    SCALE_Y(fDescent);
    SCALE_Y(fBottom);
    SCALE_Y(fLeading);
    SCALE_Y(fXHeight);
    SCALE_Y(fCapHeight);
    SCALE_Y(fUnderlineThickness);
    SCALE_Y(fUnderlinePosition);
    SCALE_Y(fStrikeoutThickness);
    SCALE_Y(fStrikeoutPosition);

    #undef SCALE_X
    #undef SCALE_Y

    return dst;
}

class SkUserTypeface final : public SkTypeface {
private:
    friend class SkCustomTypefaceBuilder;
    friend class SkUserScalerContext;

    explicit SkUserTypeface(SkFontStyle style, const SkFontMetrics& metrics,
                            std::vector<SkCustomTypefaceBuilder::GlyphRec>&& recs)
        : SkTypeface(style)
        , fGlyphRecs(std::move(recs))
        , fMetrics(metrics)
    {}

    const std::vector<SkCustomTypefaceBuilder::GlyphRec> fGlyphRecs;
    const SkFontMetrics                                  fMetrics;

    std::unique_ptr<SkScalerContext> onCreateScalerContext(const SkScalerContextEffects&,
                                                           const SkDescriptor* desc) const override;
    void onFilterRec(SkScalerContextRec* rec) const override;
    void getGlyphToUnicodeMap(SkUnichar* glyphToUnicode) const override;
    std::unique_ptr<SkAdvancedTypefaceMetrics> onGetAdvancedMetrics() const override;

    void onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocal) const override;

    void onCharsToGlyphs(const SkUnichar* chars, int count, SkGlyphID glyphs[]) const override;

    void onGetFamilyName(SkString* familyName) const override;
    bool onGetPostScriptName(SkString*) const override;
    SkTypeface::LocalizedStrings* onCreateFamilyNameIterator() const override;

    std::unique_ptr<SkStreamAsset> onOpenStream(int*) const override;

    // trivial

    std::unique_ptr<SkStreamAsset> onOpenExistingStream(int*) const override { return nullptr; }

    sk_sp<SkTypeface> onMakeClone(const SkFontArguments& args) const override {
        return sk_ref_sp(this);
    }
    int onCountGlyphs() const override { return this->glyphCount(); }
    int onGetUPEM() const override { return 2048; /* ?? */ }
    bool onComputeBounds(SkRect* bounds) const override {
        bounds->setLTRB(fMetrics.fXMin, fMetrics.fTop, fMetrics.fXMax, fMetrics.fBottom);
        return true;
    }

    // noops

    void getPostScriptGlyphNames(SkString*) const override {}
    bool onGlyphMaskNeedsCurrentColor() const override { return false; }
    int onGetVariationDesignPosition(SkFontArguments::VariationPosition::Coordinate[],
                                     int) const override { return 0; }
    int onGetVariationDesignParameters(SkFontParameters::Variation::Axis[],
                                       int) const override { return 0; }
    int onGetTableTags(SkFontTableTag tags[]) const override { return 0; }
    size_t onGetTableData(SkFontTableTag, size_t, size_t, void*) const override { return 0; }

    int glyphCount() const {
        return SkToInt(fGlyphRecs.size());
    }
};

SkCustomTypefaceBuilder::SkCustomTypefaceBuilder() {
    sk_bzero(&fMetrics, sizeof(fMetrics));
}

void SkCustomTypefaceBuilder::setMetrics(const SkFontMetrics& fm, float scale) {
    fMetrics = scale_fontmetrics(fm, scale, scale);
}

void SkCustomTypefaceBuilder::setFontStyle(SkFontStyle style) {
    fStyle = style;
}

SkCustomTypefaceBuilder::GlyphRec& SkCustomTypefaceBuilder::ensureStorage(SkGlyphID index) {
    if (index >= fGlyphRecs.size()) {
           fGlyphRecs.resize(SkToSizeT(index) + 1);
    }

    return fGlyphRecs[index];
}

void SkCustomTypefaceBuilder::setGlyph(SkGlyphID index, float advance, const SkPath& path) {
    auto& rec = this->ensureStorage(index);
    rec.fAdvance  = advance;
    rec.fPath     = path;
    rec.fDrawable = nullptr;
}

void SkCustomTypefaceBuilder::setGlyph(SkGlyphID index, float advance,
                                       sk_sp<SkDrawable> drawable, const SkRect& bounds) {
    auto& rec = this->ensureStorage(index);
    rec.fAdvance  = advance;
    rec.fDrawable = std::move(drawable);
    rec.fBounds   = bounds;
    rec.fPath.reset();
}

sk_sp<SkTypeface> SkCustomTypefaceBuilder::detach() {
    if (fGlyphRecs.empty()) return nullptr;

    // initially inverted, so that any "union" will overwrite the first time
    SkRect bounds = {SK_ScalarMax, SK_ScalarMax, -SK_ScalarMax, -SK_ScalarMax};

    for (const auto& rec : fGlyphRecs) {
        bounds.join(rec.isDrawable()
                        ? rec.fBounds
                        : rec.fPath.getBounds());
    }

    fMetrics.fTop    = bounds.top();
    fMetrics.fBottom = bounds.bottom();
    fMetrics.fXMin   = bounds.left();
    fMetrics.fXMax   = bounds.right();

    return sk_sp<SkUserTypeface>(new SkUserTypeface(fStyle, fMetrics, std::move(fGlyphRecs)));
}

/////////////

void SkUserTypeface::onFilterRec(SkScalerContextRec* rec) const {
    rec->setHinting(SkFontHinting::kNone);
}

void SkUserTypeface::getGlyphToUnicodeMap(SkUnichar* glyphToUnicode) const {
    for (int gid = 0; gid < this->glyphCount(); ++gid) {
        glyphToUnicode[gid] = SkTo<SkUnichar>(gid);
    }
}

std::unique_ptr<SkAdvancedTypefaceMetrics> SkUserTypeface::onGetAdvancedMetrics() const {
    return nullptr;
}

void SkUserTypeface::onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocal) const {
    *isLocal = true;
}

void SkUserTypeface::onCharsToGlyphs(const SkUnichar uni[], int count, SkGlyphID glyphs[]) const {
    for (int i = 0; i < count; ++i) {
        glyphs[i] = uni[i] < this->glyphCount() ? SkTo<SkGlyphID>(uni[i]) : 0;
    }
}

void SkUserTypeface::onGetFamilyName(SkString* familyName) const {
    *familyName = "";
}

bool SkUserTypeface::onGetPostScriptName(SkString*) const {
    return false;
}

SkTypeface::LocalizedStrings* SkUserTypeface::onCreateFamilyNameIterator() const {
    return nullptr;
}

//////////////

class SkUserScalerContext : public SkScalerContext {
public:
    SkUserScalerContext(sk_sp<SkUserTypeface>           face,
                        const SkScalerContextEffects& effects,
                        const SkDescriptor*           desc)
            : SkScalerContext(std::move(face), effects, desc) {
        fRec.getSingleMatrix(&fMatrix);
        this->forceGenerateImageFromPath();
    }

    const SkUserTypeface* userTF() const {
        return static_cast<SkUserTypeface*>(this->getTypeface());
    }

protected:
    bool generateAdvance(SkGlyph* glyph) override {
        const SkUserTypeface* tf = this->userTF();
        auto advance = fMatrix.mapXY(tf->fGlyphRecs[glyph->getGlyphID()].fAdvance, 0);

        glyph->fAdvanceX = advance.fX;
        glyph->fAdvanceY = advance.fY;
        return true;
    }

    void generateMetrics(SkGlyph* glyph, SkArenaAlloc* alloc) override {
        glyph->zeroMetrics();
        this->generateAdvance(glyph);

        const auto& rec = this->userTF()->fGlyphRecs[glyph->getGlyphID()];
        if (rec.isDrawable()) {
            glyph->fMaskFormat = SkMask::kARGB32_Format;

            SkRect bounds = fMatrix.mapRect(rec.fBounds);
            bounds.offset(SkFixedToScalar(glyph->getSubXFixed()),
                          SkFixedToScalar(glyph->getSubYFixed()));

            SkIRect ibounds;
            bounds.roundOut(&ibounds);
            glyph->fLeft   = ibounds.fLeft;
            glyph->fTop    = ibounds.fTop;
            glyph->fWidth  = ibounds.width();
            glyph->fHeight = ibounds.height();

            // These do not have an outline path.
            glyph->setPath(alloc, nullptr, false);
        }
    }

    void generateImage(const SkGlyph& glyph) override {
        const auto& rec = this->userTF()->fGlyphRecs[glyph.getGlyphID()];
        SkASSERTF(rec.isDrawable(), "Only drawable-backed glyphs should reach generateImage.");

        auto canvas = SkCanvas::MakeRasterDirectN32(glyph.fWidth, glyph.fHeight,
                                                    static_cast<SkPMColor*>(glyph.fImage),
                                                    glyph.rowBytes());
        if constexpr (kSkShowTextBlitCoverage) {
            canvas->clear(0x33FF0000);
        } else {
            canvas->clear(SK_ColorTRANSPARENT);
        }

        canvas->translate(-glyph.fLeft, -glyph.fTop);
        canvas->translate(SkFixedToScalar(glyph.getSubXFixed()),
                          SkFixedToScalar(glyph.getSubYFixed()));
        canvas->drawDrawable(rec.fDrawable.get(), &fMatrix);
    }

    bool generatePath(const SkGlyph& glyph, SkPath* path) override {
        const auto& rec = this->userTF()->fGlyphRecs[glyph.getGlyphID()];

        SkASSERT(!rec.isDrawable());

        rec.fPath.transform(fMatrix, path);

        return true;
    }

    sk_sp<SkDrawable> generateDrawable(const SkGlyph& glyph) override {
        class DrawableMatrixWrapper final : public SkDrawable {
        public:
            DrawableMatrixWrapper(sk_sp<SkDrawable> drawable, const SkMatrix& m)
                : fDrawable(std::move(drawable))
                , fMatrix(m)
            {}

            SkRect onGetBounds() override {
                return fMatrix.mapRect(fDrawable->getBounds());
            }

            size_t onApproximateBytesUsed() override {
                return fDrawable->approximateBytesUsed() + sizeof(DrawableMatrixWrapper);
            }

            void onDraw(SkCanvas* canvas) override {
                if constexpr (kSkShowTextBlitCoverage) {
                    SkPaint paint;
                    paint.setColor(0x3300FF00);
                    paint.setStyle(SkPaint::kFill_Style);
                    canvas->drawRect(this->onGetBounds(), paint);
                }
                canvas->drawDrawable(fDrawable.get(), &fMatrix);
            }
        private:
            const sk_sp<SkDrawable> fDrawable;
            const SkMatrix          fMatrix;
        };

        const auto& rec = this->userTF()->fGlyphRecs[glyph.getGlyphID()];

        return rec.fDrawable
            ? sk_make_sp<DrawableMatrixWrapper>(rec.fDrawable, fMatrix)
            : nullptr;
    }

    void generateFontMetrics(SkFontMetrics* metrics) override {
        auto [sx, sy] = fMatrix.mapXY(1, 1);
        *metrics = scale_fontmetrics(this->userTF()->fMetrics, sx, sy);
    }

private:
    SkMatrix fMatrix;
};

std::unique_ptr<SkScalerContext> SkUserTypeface::onCreateScalerContext(
    const SkScalerContextEffects& effects, const SkDescriptor* desc) const
{
    return std::make_unique<SkUserScalerContext>(
            sk_ref_sp(const_cast<SkUserTypeface*>(this)), effects, desc);
}

///////////////////////////////////////////////////////////////////////////////////////////////////

static constexpr int kMaxGlyphCount = 65536;
static constexpr size_t kHeaderSize = 16;
static const char gHeaderString[] = "SkUserTypeface01";
static_assert(sizeof(gHeaderString) == 1 + kHeaderSize, "need header to be 16 bytes");

enum GlyphType : uint32_t { kPath, kDrawable };

std::unique_ptr<SkStreamAsset> SkUserTypeface::onOpenStream(int* ttcIndex) const {
    SkDynamicMemoryWStream wstream;

    wstream.write(gHeaderString, kHeaderSize);

    wstream.write(&fMetrics, sizeof(fMetrics));

    SkFontStyle style = this->fontStyle();
    wstream.write(&style, sizeof(style));

    wstream.write32(this->glyphCount());

    for (const auto& rec : fGlyphRecs) {
        wstream.write32(rec.isDrawable() ? GlyphType::kDrawable : GlyphType::kPath);

        wstream.writeScalar(rec.fAdvance);

        wstream.write(&rec.fBounds, sizeof(rec.fBounds));

        auto data = rec.isDrawable()
                ? rec.fDrawable->serialize()
                : rec.fPath.serialize();

        const size_t sz = data->size();
        SkASSERT(SkIsAlign4(sz));
        wstream.write(&sz, sizeof(sz));
        wstream.write(data->data(), sz);
    }

    *ttcIndex = 0;
    return wstream.detachAsStream();
}

class AutoRestorePosition {
    SkStream* fStream;
    size_t fPosition;
public:
    AutoRestorePosition(SkStream* stream) : fStream(stream) {
        fPosition = stream->getPosition();
    }

    ~AutoRestorePosition() {
        if (fStream) {
            fStream->seek(fPosition);
        }
    }

    // So we don't restore the position
    void markDone() { fStream = nullptr; }
};

sk_sp<SkTypeface> SkCustomTypefaceBuilder::Deserialize(SkStream* stream) {
    AutoRestorePosition arp(stream);

    char header[kHeaderSize];
    if (stream->read(header, kHeaderSize) != kHeaderSize ||
        0 != memcmp(header, gHeaderString, kHeaderSize))
    {
        return nullptr;
    }

    SkFontMetrics metrics;
    if (stream->read(&metrics, sizeof(metrics)) != sizeof(metrics)) {
        return nullptr;
    }

    SkFontStyle style;
    if (stream->read(&style, sizeof(style)) != sizeof(style)) {
        return nullptr;
    }

    int glyphCount;
    if (!stream->readS32(&glyphCount) || glyphCount < 0 || glyphCount > kMaxGlyphCount) {
        return nullptr;
    }

    SkCustomTypefaceBuilder builder;

    builder.setMetrics(metrics);
    builder.setFontStyle(style);

    for (int i = 0; i < glyphCount; ++i) {
        uint32_t gtype;
        if (!stream->readU32(&gtype)) {
            return nullptr;
        }

        float advance;
        if (!stream->readScalar(&advance)) {
            return nullptr;
        }

        SkRect bounds;
        if (stream->read(&bounds, sizeof(bounds)) != sizeof(bounds)) {
            return nullptr;
        }

        // SkPath and SkDrawable cannot read from a stream, so we have to page them into ram
        size_t sz;
        if (stream->read(&sz, sizeof(sz)) != sizeof(sz)) {
            return nullptr;
        }
        auto data = SkData::MakeUninitialized(sz);
        if (stream->read(data->writable_data(), sz) != sz) {
            return nullptr;
        }

        switch (gtype) {
        case GlyphType::kDrawable: {
            auto drawable = SkDrawable::Deserialize(data->data(), data->size());
            if (!drawable) {
                return nullptr;
            }
            builder.setGlyph(i, advance, std::move(drawable), bounds);
        } break;
        case GlyphType::kPath: {
            SkPath path;
            if (path.readFromMemory(data->data(), data->size()) != data->size()) {
                return nullptr;
            }

            builder.setGlyph(i, advance, path);
        } break;
        default:
            return nullptr;
        }
    }

    arp.markDone();
    return builder.detach();
}
