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

#ifndef TestTypeface_DEFINED
#define TestTypeface_DEFINED

#include "include/core/SkFontArguments.h"
#include "include/core/SkFontMetrics.h"
#include "include/core/SkFontStyle.h"
#include "include/core/SkPaint.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkScalar.h"
#include "include/core/SkStream.h"
#include "include/core/SkTypeface.h"
#include "include/core/SkTypes.h"
#include "include/private/base/SkFixed.h"

#include <memory>

class SkDescriptor;
class SkFontDescriptor;
class SkGlyph;
class SkPath;
class SkScalerContext;
class SkStreamAsset;
class SkString;
class SkTestFont;
struct SkAdvancedTypefaceMetrics;
struct SkScalerContextEffects;
struct SkScalerContextRec;

struct SkTestFontData {
    const SkScalar*      fPoints;
    const unsigned char* fVerbs;
    const SkUnichar*     fCharCodes;
    const size_t         fCharCodesCount;
    const SkFixed*       fWidths;
    const SkFontMetrics& fMetrics;
    const char*          fName;
    SkFontStyle          fStyle;
};

class SkTestFont : public SkRefCnt {
public:
    SkTestFont(const SkTestFontData&);
    ~SkTestFont() override;
    SkGlyphID glyphForUnichar(SkUnichar charCode) const;
    void      init(const SkScalar* pts, const unsigned char* verbs);

private:
    const SkUnichar*     fCharCodes;
    const size_t         fCharCodesCount;
    const SkFixed*       fWidths;
    const SkFontMetrics& fMetrics;
    const char*          fName;
    SkPath*              fPaths;
    friend class TestTypeface;
    using INHERITED = SkRefCnt;
};

class TestTypeface : public SkTypeface {
public:
    struct List {
        struct Family {
            struct Face {
                sk_sp<SkTypeface> typeface;
                const char* name;
                bool isDefault;
            };
            std::vector<Face> faces;
            const char* name;
        };
        std::vector<Family> families;
    };
    static const List& Typefaces();

    SkVector getAdvance(SkGlyphID) const;
    void getFontMetrics(SkFontMetrics* metrics);
    SkPath getPath(SkGlyphID glyph);

    struct Register { Register(); };
protected:
    std::unique_ptr<SkScalerContext> onCreateScalerContext(const SkScalerContextEffects&,
                                                           const SkDescriptor* desc) const override;
    void onFilterRec(SkScalerContextRec* rec) const override;
    void getGlyphToUnicodeMap(SkSpan<SkUnichar>) const override;
    std::unique_ptr<SkAdvancedTypefaceMetrics> onGetAdvancedMetrics() const override;

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

    sk_sp<SkTypeface> onMakeClone(const SkFontArguments& args) const override {
        return sk_ref_sp(this);
    }

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

    void onCharsToGlyphs(SkSpan<const SkUnichar>, SkSpan<SkGlyphID>) const override;

    int onCountGlyphs() const override { return (int)fTestFont->fCharCodesCount; }

    void getPostScriptGlyphNames(SkString*) const override {}

    int onGetUPEM() const override { return 2048; }

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

    bool onGlyphMaskNeedsCurrentColor() const override { return false; }

    int onGetVariationDesignPosition(
                         SkSpan<SkFontArguments::VariationPosition::Coordinate>) const override {
        return 0;
    }

    int onGetVariationDesignParameters(SkSpan<SkFontParameters::Variation::Axis>) const override {
        return 0;
    }

    int onGetTableTags(SkSpan<SkFontTableTag>) const override { return 0; }

    size_t onGetTableData(SkFontTableTag tag,
                          size_t         offset,
                          size_t         length,
                          void*          data) const override {
        return 0;
    }

private:
    static constexpr SkTypeface::FactoryId FactoryId = SkSetFourByteTag('t','e','s','t');
    static sk_sp<SkTypeface> MakeFromStream(std::unique_ptr<SkStreamAsset>, const SkFontArguments&);
    TestTypeface(sk_sp<SkTestFont>, const SkFontStyle& style);
    sk_sp<SkTestFont> fTestFont;
    friend class SkTestScalerContext;
};

#endif
