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

#ifndef SkSVGTextPriv_DEFINED
#define SkSVGTextPriv_DEFINED

#include "modules/skshaper/include/SkShaper.h"
#include "modules/svg/include/SkSVGRenderContext.h"
#include "modules/svg/include/SkSVGText.h"
#include "src/core/SkTLazy.h"

#include <functional>
#include <tuple>

class SkContourMeasure;
struct SkRSXform;

// SkSVGTextContext is responsible for sequencing input text chars into "chunks".
// A single text chunk can span multiple structural elements (<text>, <tspan>, etc),
// and per [1] new chunks are emitted
//
//   a) for each top level text element (<text>, <textPath>)
//   b) whenever a character with an explicit absolute position is encountered
//
// The implementation queues shaped run data until a full text chunk is resolved, at which
// point we have enough information to perform final alignment and rendering.
//
// [1] https://www.w3.org/TR/SVG11/text.html#TextLayoutIntroduction
class SkSVGTextContext final : SkShaper::RunHandler {
public:
    using ShapedTextCallback = std::function<void(const SkSVGRenderContext&,
                                                  const sk_sp<SkTextBlob>&,
                                                  const SkPaint*,
                                                  const SkPaint*)>;

    // Helper for encoding optional positional attributes.
    class PosAttrs {
    public:
        // TODO: rotate
        enum Attr : size_t {
            kX      = 0,
            kY      = 1,
            kDx     = 2,
            kDy     = 3,
            kRotate = 4,
        };

        float  operator[](Attr a) const { return fStorage[a]; }
        float& operator[](Attr a)       { return fStorage[a]; }

        bool has(Attr a) const { return fStorage[a] != kNone; }
        bool hasAny()    const {
            return this->has(kX)
                || this->has(kY)
                || this->has(kDx)
                || this->has(kDy)
                || this->has(kRotate);
        }

        void setImplicitRotate(bool imp) { fImplicitRotate = imp; }
        bool isImplicitRotate() const { return fImplicitRotate; }

    private:
        inline static constexpr auto kNone = std::numeric_limits<float>::infinity();

        float fStorage[5]     = { kNone, kNone, kNone, kNone, kNone };
        bool  fImplicitRotate = false;
    };

    // Helper for cascading position attribute resolution (x, y, dx, dy, rotate) [1]:
    //   - each text position element can specify an arbitrary-length attribute array
    //   - for each character, we look up a given attribute first in its local attribute array,
    //     then in the ancestor chain (cascading/fallback) - and return the first value encountered.
    //   - the lookup is based on character index relative to the text content subtree
    //     (i.e. the index crosses chunk boundaries)
    //
    // [1] https://www.w3.org/TR/SVG11/text.html#TSpanElementXAttribute
    class ScopedPosResolver {
    public:
        ScopedPosResolver(const SkSVGTextContainer&, const SkSVGLengthContext&, SkSVGTextContext*,
                          size_t);

        ScopedPosResolver(const SkSVGTextContainer&, const SkSVGLengthContext&, SkSVGTextContext*);

        ~ScopedPosResolver();

        PosAttrs resolve(size_t charIndex) const;

    private:
        SkSVGTextContext*         fTextContext;
        const ScopedPosResolver*  fParent;          // parent resolver (fallback)
        const size_t              fCharIndexOffset; // start index for the current resolver
        const std::vector<float>  fX,
                                  fY,
                                  fDx,
                                  fDy;
        const std::vector<float>& fRotate;

        // cache for the last known index with explicit positioning
        mutable size_t           fLastPosIndex = std::numeric_limits<size_t>::max();

    };

    SkSVGTextContext(const SkSVGRenderContext&,
                     const ShapedTextCallback&,
                     const SkSVGTextPath* = nullptr);
    ~SkSVGTextContext() override;

    // Shape and queue codepoints for final alignment.
    void shapeFragment(const SkString&, const SkSVGRenderContext&, SkSVGXmlSpace);

    // Perform final adjustments and push shaped blobs to the callback.
    void flushChunk(const SkSVGRenderContext& ctx);

    const ShapedTextCallback& getCallback() const { return fCallback; }

private:
    struct PositionAdjustment {
        SkVector offset;
        float    rotation;
    };

    struct ShapeBuffer {
        SkSTArray<128, char              , true> fUtf8;
        // per-utf8-char cumulative pos adjustments
        SkSTArray<128, PositionAdjustment, true> fUtf8PosAdjust;

        void reserve(size_t size) {
            fUtf8.reserve_back(SkToInt(size));
            fUtf8PosAdjust.reserve_back(SkToInt(size));
        }

        void reset() {
            fUtf8.reset();
            fUtf8PosAdjust.reset();
        }

        void append(SkUnichar, PositionAdjustment);
    };

    struct RunRec {
        SkFont                                font;
        std::unique_ptr<SkPaint>              fillPaint,
                                              strokePaint;
        std::unique_ptr<SkGlyphID[]>          glyphs;        // filled by SkShaper
        std::unique_ptr<SkPoint[]>            glyphPos;      // filled by SkShaper
        std::unique_ptr<PositionAdjustment[]> glyhPosAdjust; // deferred positioning adjustments
        size_t                                glyphCount;
        SkVector                              advance;
    };

    // Caches path information to accelerate position lookups.
    class PathData {
    public:
        PathData(const SkSVGRenderContext&, const SkSVGTextPath&);

        SkMatrix getMatrixAt(float offset) const;

        float length() const { return fLength; }

    private:
        std::vector<sk_sp<SkContourMeasure>> fContours;
        float                                fLength = 0; // total path length
    };

    void shapePendingBuffer(const SkFont&);

    SkRSXform computeGlyphXform(SkGlyphID, const SkFont&, const SkPoint& glyph_pos,
                                const PositionAdjustment&) const;

    // SkShaper callbacks
    void beginLine() override {}
    void runInfo(const RunInfo&) override {}
    void commitRunInfo() override {}
    Buffer runBuffer(const RunInfo& ri) override;
    void commitRunBuffer(const RunInfo& ri) override;
    void commitLine() override {}

    // http://www.w3.org/TR/SVG11/text.html#TextLayout
    const SkSVGRenderContext&       fRenderContext; // original render context
    const ShapedTextCallback&       fCallback;
    const std::unique_ptr<SkShaper> fShaper;
    std::vector<RunRec>             fRuns;
    const ScopedPosResolver*        fPosResolver  = nullptr;
    std::unique_ptr<PathData>       fPathData;

    // shaper state
    ShapeBuffer                     fShapeBuffer;
    std::vector<uint32_t>           fShapeClusterBuffer;

    // chunk state
    SkPoint                         fChunkPos     = {0,0}; // current text chunk position
    SkVector                        fChunkAdvance = {0,0}; // cumulative advance
    float                           fChunkAlignmentFactor; // current chunk alignment

    // tracks the global text subtree char index (cross chunks).  Used for position resolution.
    size_t                          fCurrentCharIndex = 0;

    // cached for access from SkShaper callbacks.
    SkTLazy<SkPaint>                fCurrentFill;
    SkTLazy<SkPaint>                fCurrentStroke;

    bool                            fPrevCharSpace = true; // WS filter state
};

#endif // SkSVGTextPriv_DEFINED
