/*
 * 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 SkPictureShader_DEFINED
#define SkPictureShader_DEFINED

#include "include/core/SkFlattenable.h"
#include "include/core/SkImageInfo.h"
#include "include/core/SkMatrix.h"
#include "include/core/SkPicture.h"
#include "include/core/SkRect.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkSize.h"
#include "include/core/SkSurfaceProps.h"
#include "include/core/SkTypes.h"
#include "src/shaders/SkShaderBase.h"

class SkArenaAlloc;
class SkColorSpace;
class SkImage;
class SkReadBuffer;
class SkShader;
class SkSurface;
class SkWriteBuffer;
enum SkColorType : int;
enum class SkFilterMode;
enum class SkTileMode;
struct SkStageRec;

/*
 * An SkPictureShader can be used to draw SkPicture-based patterns.
 *
 * The SkPicture is first rendered into a tile, which is then used to shade the area according
 * to specified tiling rules.
 */
class SkPictureShader : public SkShaderBase {
public:
    static sk_sp<SkShader> Make(sk_sp<SkPicture>, SkTileMode, SkTileMode, SkFilterMode,
                                const SkMatrix*, const SkRect*);

    SkPictureShader(sk_sp<SkPicture>, SkTileMode, SkTileMode, SkFilterMode, const SkRect*);

    ShaderType type() const override { return ShaderType::kPicture; }

    sk_sp<SkPicture> picture() const { return fPicture; }
    SkRect tile() const { return fTile; }
    SkTileMode tileModeX() const { return fTmx; }
    SkTileMode tileModeY() const { return fTmy; }
    SkFilterMode filter() const { return fFilter; }

    struct CachedImageInfo {
        bool success;
        SkSize tileScale;        // Additional scale factors to apply when sampling image.
        SkMatrix matrixForDraw;  // Matrix used to produce an image from the picture
        SkImageInfo imageInfo;
        SkSurfaceProps props;

        static CachedImageInfo Make(const SkRect& bounds,
                                    const SkMatrix& totalM,
                                    SkColorType dstColorType,
                                    SkColorSpace* dstColorSpace,
                                    const int maxTextureSize,
                                    const SkSurfaceProps& propsIn);

        // Returns a temporary image created from the surface
        sk_sp<SkImage> makeImage(sk_sp<SkSurface> surf, const SkPicture* pict) const;
    };

protected:
    SkPictureShader(SkReadBuffer&);
    void flatten(SkWriteBuffer&) const override;
    bool appendStages(const SkStageRec&, const SkShaders::MatrixRec&) const override;
#ifdef SK_ENABLE_LEGACY_SHADERCONTEXT
    Context* onMakeContext(const ContextRec&, SkArenaAlloc*) const override;
#endif

private:
    SK_FLATTENABLE_HOOKS(SkPictureShader)

    sk_sp<SkShader> rasterShader(const SkMatrix&,
                                 SkColorType dstColorType,
                                 SkColorSpace* dstColorSpace,
                                 const SkSurfaceProps& props) const;

    sk_sp<SkPicture>    fPicture;
    SkRect              fTile;
    SkTileMode          fTmx, fTmy;
    SkFilterMode fFilter;
};

#endif // SkPictureShader_DEFINED
