/*
 * 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/core/SkCanvas.h"
#include "include/core/SkData.h"
#include "include/core/SkFontMetrics.h"
#include "include/utils/SkCustomTypeface.h"
#include "src/core/SkAdvancedTypefaceMetrics.h"

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;

    SkUserTypeface() : SkTypeface(SkFontStyle()) {}

    std::vector<SkPath> fPaths;
    std::vector<float>  fAdvances;
    SkFontMetrics       fMetrics;

    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;
    SkTypeface::LocalizedStrings* onCreateFamilyNameIterator() const override;

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

    // trivial

    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 {}
    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 {
        SkASSERT(fPaths.size() == fAdvances.size());
        return SkToInt(fPaths.size());
    }
};

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

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

void SkCustomTypefaceBuilder::setGlyph(SkGlyphID index, float advance, const SkPath& path) {
    SkASSERT(fPaths.size() == fAdvances.size());
    if (index >= fPaths.size()) {
           fPaths.resize(SkToSizeT(index) + 1);
        fAdvances.resize(SkToSizeT(index) + 1);
    }
    fAdvances[index] = advance;
    fPaths[index]    = path;
}

sk_sp<SkTypeface> SkCustomTypefaceBuilder::detach() {
    SkASSERT(fPaths.size() == fAdvances.size());
    if (fPaths.empty()) return nullptr;

    sk_sp<SkUserTypeface> tf(new SkUserTypeface());
    tf->fAdvances = std::move(fAdvances);
    tf->fPaths    = std::move(fPaths);
    tf->fMetrics  = fMetrics;

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

    for (const auto& path : tf->fPaths) {
        if (!path.isEmpty()) {
            bounds.join(path.getBounds());
        }
    }
    tf->fMetrics.fTop    = bounds.top();
    tf->fMetrics.fBottom = bounds.bottom();
    tf->fMetrics.fXMin   = bounds.left();
    tf->fMetrics.fXMax   = bounds.right();

    return std::move(tf);
}

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

#include "src/core/SkScalerContext.h"

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

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

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

#include "src/core/SkScalerContext.h"

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:
    unsigned generateGlyphCount() override {
        return this->userTF()->glyphCount();
    }

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

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

    void generateMetrics(SkGlyph* glyph) override {
        glyph->zeroMetrics();
        this->generateAdvance(glyph);
        // Always generates from paths, so SkScalerContext::getMetrics will figure the bounds.
    }

    void generateImage(const SkGlyph&) override { SK_ABORT("Should have generated from path."); }

    bool generatePath(SkGlyphID glyph, SkPath* path) override {
        this->userTF()->fPaths[glyph].transform(fMatrix, path);
        return true;
    }

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

private:
    SkMatrix fMatrix;
};

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

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

#include "include/private/SkFloatingPoint.h"
#include "src/core/SkAutoMalloc.h"
#include "src/core/SkPathPriv.h"

static void write_scaled_float_to_16(SkWStream* stream, float x, float scale) {
    stream->write16(SkToS16(sk_float_round2int(x * scale)) & 0xFFFF);
}

enum PVerb {
    kMove,
    kLine,
    kCurve,
    kClose,
};

static void compress_write(SkWStream* stream, const SkPath& path, int upem) {
    int pCount = 0;
    std::vector<PVerb> verbs;
    for (auto [v, p, w] : SkPathPriv::Iterate(path)) {
        switch (v) {
            default: break;
            case SkPathVerb::kMove: verbs.push_back(kMove); pCount += 1; break;
            case SkPathVerb::kQuad: verbs.push_back(kCurve); pCount += 2; break;
            case SkPathVerb::kLine: verbs.push_back(kLine); pCount += 1; break;
            case SkPathVerb::kClose: verbs.push_back(kClose); break;
        }
    }

    int vCount = verbs.size();

    stream->write16(upem);      // share w/ other paths?
    stream->write16(vCount);
    stream->write16(pCount);
    for (int i = 0; i < (vCount & ~3); i += 4) {
        stream->write8((verbs[i+0]<<6) | (verbs[i+1]<<4) | (verbs[i+2]<<2) | verbs[i+3]);
    }
    if (vCount & 3) {
        uint8_t b = 0;
        int shift = 6;
        for (int i = vCount & ~3; i < vCount; ++i) {
            b |= verbs[i] << shift;
            shift >>= 2;
        }
        stream->write8(b);
    }
    if (vCount & 1) {
        stream->write8(0);
    }

    const float scale = (float)upem;
    auto write_pts = [&](const SkPoint pts[], int count) {
        for (int i = 0; i < count; ++i) {
            write_scaled_float_to_16(stream, pts[i].fX, scale);
            write_scaled_float_to_16(stream, pts[i].fY, scale);
        }
    };

    for (auto [v, p, w] : SkPathPriv::Iterate(path)) {
        switch (v) {
            default: break;
            case SkPathVerb::kMove: write_pts(&p[0], 1); break;
            case SkPathVerb::kQuad: write_pts(&p[1], 2); break;
            case SkPathVerb::kLine: write_pts(&p[1], 1); break;
            case SkPathVerb::kClose:                     break;
        }
    }
}

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

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

    wstream.write(gHeaderString, kHeaderSize);

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

    // just hacking around -- this makes the serialized font 1/2 size
    const bool use_compression = false;

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

    if (use_compression) {
        for (float a : fAdvances) {
            write_scaled_float_to_16(&wstream, a, 2048);
        }
    } else {
        wstream.write(fAdvances.data(), this->glyphCount() * sizeof(float));
    }

    for (const auto& p : fPaths) {
        if (use_compression) {
            compress_write(&wstream, p, 2048);
        } else {
            auto data = p.serialize();
            SkASSERT(SkIsAlign4(data->size()));
            wstream.write(data->data(), data->size());
        }
    }
//    SkDebugf("%d glyphs, %d bytes\n", fGlyphCount, wstream.bytesWritten());
    *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 ||
        memcmp(header, gHeaderString, kHeaderSize) != 0)
    {
        return nullptr;
    }

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

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

    SkCustomTypefaceBuilder builder;

    builder.setMetrics(metrics);

    std::vector<float> advances(glyphCount);
    if (stream->read(advances.data(), glyphCount * sizeof(float)) != glyphCount * sizeof(float)) {
        return nullptr;
    }

    // SkPath can read from a stream, so we have to page the rest into ram
    const size_t offset = stream->getPosition();
    const size_t length = stream->getLength() - offset;
    SkAutoMalloc ram(length);
    char* buffer = (char*)ram.get();

    if (stream->read(buffer, length) != length) {
        return nullptr;
    }

    size_t totalUsed = 0;
    for (int i = 0; i < glyphCount; ++i) {
        SkPath path;
        size_t used = path.readFromMemory(buffer + totalUsed, length - totalUsed);
        if (used == 0) {
            return nullptr;
        }
        builder.setGlyph(i, advances[i], path);
        totalUsed += used;
        SkASSERT(length >= totalUsed);
    }

    // all done, update the stream to only reflect the bytes we needed
    stream->seek(offset + totalUsed);

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