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

#include "include/core/SkBitmap.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkPath.h"
#include "src/core/SkAdvancedTypefaceMetrics.h"
#include "src/core/SkGlyph.h"
#include "src/core/SkRectPriv.h"
#include "tools/fonts/RandomScalerContext.h"

class SkDescriptor;

class RandomScalerContext : public SkScalerContext {
public:
    RandomScalerContext(sk_sp<SkRandomTypeface>,
                        const SkScalerContextEffects&,
                        const SkDescriptor*,
                        bool fFakeIt);

protected:
    bool     generateAdvance(SkGlyph*) override;
    void     generateMetrics(SkGlyph*) override;
    void     generateImage(const SkGlyph&) override;
    bool     generatePath(SkGlyphID, SkPath*) override;
    void     generateFontMetrics(SkFontMetrics*) override;

private:
    SkRandomTypeface* getRandomTypeface() const {
        return static_cast<SkRandomTypeface*>(this->getTypeface());
    }
    std::unique_ptr<SkScalerContext> fProxy;
    bool                             fFakeIt;
};

RandomScalerContext::RandomScalerContext(sk_sp<SkRandomTypeface>       face,
                                         const SkScalerContextEffects& effects,
                                         const SkDescriptor*           desc,
                                         bool                          fakeIt)
        : SkScalerContext(std::move(face), effects, desc)
        , fProxy(getRandomTypeface()->proxy()->createScalerContext(SkScalerContextEffects(), desc))
        , fFakeIt(fakeIt) {
    fProxy->forceGenerateImageFromPath();
}

bool RandomScalerContext::generateAdvance(SkGlyph* glyph) { return fProxy->generateAdvance(glyph); }

void RandomScalerContext::generateMetrics(SkGlyph* glyph) {
    // Here we will change the mask format of the glyph
    // NOTE: this may be overridden by the base class (e.g. if a mask filter is applied).
    SkMask::Format format = SkMask::kA8_Format;
    switch (glyph->getGlyphID() % 4) {
        case 0: format = SkMask::kLCD16_Format; break;
        case 1: format = SkMask::kA8_Format; break;
        case 2: format = SkMask::kARGB32_Format; break;
        case 3: format = SkMask::kBW_Format; break;
    }

    *glyph = fProxy->internalMakeGlyph(glyph->getPackedID(), format);

    if (fFakeIt || (glyph->getGlyphID() % 4) != 2) {
        return;
    }

    SkPath path;
    if (!fProxy->getPath(glyph->getPackedID(), &path)) {
        return;
    }
    glyph->fMaskFormat = SkMask::kARGB32_Format;

    SkRect         storage;
    const SkPaint& paint = this->getRandomTypeface()->paint();
    const SkRect&  newBounds =
            paint.doComputeFastBounds(path.getBounds(), &storage, SkPaint::kFill_Style);
    SkIRect ibounds;
    newBounds.roundOut(&ibounds);
    glyph->fLeft   = ibounds.fLeft;
    glyph->fTop    = ibounds.fTop;
    glyph->fWidth  = ibounds.width();
    glyph->fHeight = ibounds.height();
}

void RandomScalerContext::generateImage(const SkGlyph& glyph) {
    // TODO: can force down but not up
    /*
    SkMask::Format format = (SkMask::Format)glyph.fMaskFormat;
    switch (glyph.getGlyphID() % 4) {
        case 0: format = SkMask::kLCD16_Format; break;
        case 1: format = SkMask::kA8_Format; break;
        case 2: format = SkMask::kARGB32_Format; break;
        case 3: format = SkMask::kBW_Format; break;
    }
    const_cast<SkGlyph&>(glyph).fMaskFormat = format;
    */

    if (fFakeIt) {
        sk_bzero(glyph.fImage, glyph.imageSize());
        return;
    }

    if (SkMask::kARGB32_Format != glyph.fMaskFormat) {
        fProxy->getImage(glyph);
        return;
    }

    // If the format is ARGB, just draw the glyph from path.
    SkPath path;
    if (!fProxy->getPath(glyph.getPackedID(), &path)) {
        fProxy->getImage(glyph);
        return;
    }

    SkBitmap bm;
    bm.installPixels(SkImageInfo::MakeN32Premul(glyph.fWidth, glyph.fHeight),
                     glyph.fImage,
                     glyph.rowBytes());
    bm.eraseColor(0);

    SkCanvas canvas(bm);
    canvas.translate(-SkIntToScalar(glyph.fLeft), -SkIntToScalar(glyph.fTop));
    canvas.drawPath(path, this->getRandomTypeface()->paint());
}

bool RandomScalerContext::generatePath(SkGlyphID glyph, SkPath* path) {
    return fProxy->generatePath(glyph, path);
}

void RandomScalerContext::generateFontMetrics(SkFontMetrics* metrics) {
    fProxy->getFontMetrics(metrics);
}

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

SkRandomTypeface::SkRandomTypeface(sk_sp<SkTypeface> proxy, const SkPaint& paint, bool fakeIt)
        : SkTypeface(proxy->fontStyle(), false)
        , fProxy(std::move(proxy))
        , fPaint(paint)
        , fFakeIt(fakeIt) {}

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

void SkRandomTypeface::onFilterRec(SkScalerContextRec* rec) const {
    fProxy->filterRec(rec);
    rec->setHinting(SkFontHinting::kNone);
    rec->fMaskFormat = SkMask::kARGB32_Format;
}

void SkRandomTypeface::getGlyphToUnicodeMap(SkUnichar* glyphToUnicode) const {
    fProxy->getGlyphToUnicodeMap(glyphToUnicode);
}

std::unique_ptr<SkAdvancedTypefaceMetrics> SkRandomTypeface::onGetAdvancedMetrics() const {
    return fProxy->getAdvancedMetrics();
}

std::unique_ptr<SkStreamAsset> SkRandomTypeface::onOpenStream(int* ttcIndex) const {
    return fProxy->openStream(ttcIndex);
}

sk_sp<SkTypeface> SkRandomTypeface::onMakeClone(const SkFontArguments& args) const {
    sk_sp<SkTypeface> proxy = fProxy->makeClone(args);
    if (!proxy) {
        return nullptr;
    }
    return sk_make_sp<SkRandomTypeface>(proxy, fPaint, fFakeIt);
}

void SkRandomTypeface::onGetFontDescriptor(SkFontDescriptor* desc, bool* isLocal) const {
    // TODO: anything that uses this typeface isn't correctly serializable, since this typeface
    // cannot be deserialized.
    fProxy->getFontDescriptor(desc, isLocal);
}

void SkRandomTypeface::onCharsToGlyphs(const SkUnichar* uni, int count, SkGlyphID glyphs[]) const {
    fProxy->unicharsToGlyphs(uni, count, glyphs);
}

int SkRandomTypeface::onCountGlyphs() const { return fProxy->countGlyphs(); }

int SkRandomTypeface::onGetUPEM() const { return fProxy->getUnitsPerEm(); }

void SkRandomTypeface::onGetFamilyName(SkString* familyName) const {
    fProxy->getFamilyName(familyName);
}

bool SkRandomTypeface::onGetPostScriptName(SkString* postScriptName) const {
    return fProxy->getPostScriptName(postScriptName);
}

SkTypeface::LocalizedStrings* SkRandomTypeface::onCreateFamilyNameIterator() const {
    return fProxy->createFamilyNameIterator();
}

void SkRandomTypeface::getPostScriptGlyphNames(SkString* names) const {
    return fProxy->getPostScriptGlyphNames(names);
}

int SkRandomTypeface::onGetVariationDesignPosition(
        SkFontArguments::VariationPosition::Coordinate coordinates[],
        int                                            coordinateCount) const {
    return fProxy->onGetVariationDesignPosition(coordinates, coordinateCount);
}

int SkRandomTypeface::onGetVariationDesignParameters(SkFontParameters::Variation::Axis parameters[],
                                                     int parameterCount) const {
    return fProxy->onGetVariationDesignParameters(parameters, parameterCount);
}

int SkRandomTypeface::onGetTableTags(SkFontTableTag tags[]) const {
    return fProxy->getTableTags(tags);
}

size_t SkRandomTypeface::onGetTableData(SkFontTableTag tag,
                                        size_t         offset,
                                        size_t         length,
                                        void*          data) const {
    return fProxy->getTableData(tag, offset, length, data);
}
