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

#ifndef SkAtlasTextTarget_DEFINED
#define SkAtlasTextTarget_DEFINED

#include <memory>
#include "SkDeque.h"
#include "SkRefCnt.h"
#include "SkScalar.h"

class SkAtlasTextContext;
class SkAtlasTextFont;
class SkMatrix;
struct SkPoint;

/** Represents a client-created renderable surface and is used to draw text into the surface. */
class SK_API SkAtlasTextTarget {
public:
    virtual ~SkAtlasTextTarget();

    /**
     * Creates a text drawing target. ‘handle’ is used to identify this rendering surface when
     * draws are flushed to the SkAtlasTextContext's SkAtlasTextRenderer.
     */
    static std::unique_ptr<SkAtlasTextTarget> Make(sk_sp<SkAtlasTextContext>,
                                                   int width,
                                                   int height,
                                                   void* handle);

    /**
     * Enqueues a text draw in the target. The caller provides an array of glyphs and their
     * positions. The meaning of 'color' here is interpreted by the client's SkAtlasTextRenderer
     * when it actually renders the text.
     */
    virtual void drawText(const SkGlyphID[], const SkPoint[], int glyphCnt, uint32_t color,
                          const SkAtlasTextFont&) = 0;

    /** Issues all queued text draws to SkAtlasTextRenderer. */
    virtual void flush() = 0;

    int width() const { return fWidth; }
    int height() const { return fHeight; }

    void* handle() const { return fHandle; }

    SkAtlasTextContext* context() const { return fContext.get(); }

    /** Saves the current matrix in a stack. Returns the prior depth of the saved matrix stack. */
    int save();
    /** Pops the top matrix on the stack if the stack is not empty. */
    void restore();
    /**
     * Pops the matrix stack until the stack depth is count. Does nothing if the depth is already
     * less than count.
     */
    void restoreToCount(int count);

    /** Pre-translates the current CTM. */
    void translate(SkScalar dx, SkScalar dy);
    /** Pre-scales the current CTM. */
    void scale(SkScalar sx, SkScalar sy);
    /** Pre-rotates the current CTM about the origin. */
    void rotate(SkScalar degrees);
    /** Pre-rotates the current CTM about the (px, py). */
    void rotate(SkScalar degrees, SkScalar px, SkScalar py);
    /** Pre-skews the current CTM. */
    void skew(SkScalar sx, SkScalar sy);
    /** Pre-concats the current CTM. */
    void concat(const SkMatrix& matrix);

protected:
    SkAtlasTextTarget(sk_sp<SkAtlasTextContext>, int width, int height, void* handle);

    const SkMatrix& ctm() const { return *static_cast<const SkMatrix*>(fMatrixStack.back()); }

    void* const fHandle;
    const sk_sp<SkAtlasTextContext> fContext;
    const int fWidth;
    const int fHeight;

private:
    SkDeque fMatrixStack;
    int fSaveCnt;

    SkMatrix* accessCTM() const {
        return static_cast<SkMatrix*>(const_cast<void*>(fMatrixStack.back()));
    }

    SkAtlasTextTarget() = delete;
    SkAtlasTextTarget(const SkAtlasTextContext&) = delete;
    SkAtlasTextTarget& operator=(const SkAtlasTextContext&) = delete;
};

#endif
