/*
 * 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 "src/core/SkStreamPriv.h"

#include <cstdint>
#include <cstring>
#include <memory>
#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) ||
            (gtype != GlyphType::kDrawable && gtype != GlyphType::kPath)) {
            return nullptr;
        }

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

        SkRect bounds;
        if (stream->read(&bounds, sizeof(bounds)) != sizeof(bounds) || !bounds.isFinite()) {
            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;
        }

        // The amount of bytes in the stream must be at least as big as sz, otherwise
        // sz is invalid.
        if (StreamRemainingLengthIsBelow(stream, 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();
}
