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

#ifndef SkGradientShaderPriv_DEFINED
#define SkGradientShaderPriv_DEFINED

#include "include/core/SkBitmap.h"
#include "include/core/SkColor.h"
#include "include/core/SkColorSpace.h"
#include "include/core/SkMatrix.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkScalar.h"
#include "include/effects/SkGradientShader.h"
#include "include/private/base/SkAssert.h"
#include "include/private/base/SkTArray.h"
#include "include/private/base/SkTemplates.h"
#include "src/core/SkColorData.h"
#include "src/shaders/SkShaderBase.h"

#include <cstddef>
#include <cstdint>

class SkArenaAlloc;
class SkRasterPipeline;
class SkReadBuffer;
class SkShader;
class SkWriteBuffer;
enum class SkTileMode;
struct SkStageRec;

class SkGradientBaseShader : public SkShaderBase {
public:
    using Interpolation = SkGradientShader::Interpolation;

    struct Descriptor {
        Descriptor();
        ~Descriptor();

        Descriptor(const SkColor4f colors[],
                   sk_sp<SkColorSpace> colorSpace,
                   const SkScalar positions[],
                   int colorCount,
                   SkTileMode mode,
                   const Interpolation& interpolation);

        const SkColor4f* fColors;
        sk_sp<SkColorSpace> fColorSpace;
        const SkScalar* fPositions;
        int fColorCount;  // length of fColors (and fPositions, if not nullptr)
        SkTileMode fTileMode;
        Interpolation fInterpolation;
    };

    class DescriptorScope : public Descriptor {
    public:
        DescriptorScope() {}

        bool unflatten(SkReadBuffer&, SkMatrix* legacyLocalMatrix);

    private:
        skia_private::STArray<16, SkColor4f> fColorStorage;
        skia_private::STArray<16, SkScalar> fPositionStorage;
    };

    SkGradientBaseShader(const Descriptor& desc, const SkMatrix& ptsToUnit);
    ~SkGradientBaseShader() override;

    ShaderType type() const final { return ShaderType::kGradientBase; }

    bool isOpaque() const override;

    bool interpolateInPremul() const {
        return fInterpolation.fInPremul == SkGradientShader::Interpolation::InPremul::kYes;
    }

    const SkMatrix& getGradientMatrix() const { return fPtsToUnit; }
    int getColorCount() const { return fColorCount; }
    const float* getPositions() const { return fPositions; }
    const Interpolation& getInterpolation() const { return fInterpolation; }

    static bool ValidGradient(const SkColor4f colors[],
                              int count,
                              SkTileMode tileMode,
                              const Interpolation& interpolation);

    static sk_sp<SkShader> MakeDegenerateGradient(const SkColor4f colors[],
                                                  const SkScalar pos[],
                                                  int colorCount,
                                                  sk_sp<SkColorSpace> colorSpace,
                                                  SkTileMode mode);

    // The default SkScalarNearlyZero threshold of .0024 is too big and causes regressions for svg
    // gradients defined in the wild.
    static constexpr SkScalar kDegenerateThreshold = SK_Scalar1 / (1 << 15);

protected:
    void flatten(SkWriteBuffer&) const override;

    void commonAsAGradient(GradientInfo*) const;

    bool onAsLuminanceColor(SkColor4f*) const override;

    bool appendStages(const SkStageRec&, const SkShaders::MatrixRec&) const override;

    virtual void appendGradientStages(SkArenaAlloc* alloc,
                                      SkRasterPipeline* tPipeline,
                                      SkRasterPipeline* postPipeline) const = 0;

    const SkMatrix fPtsToUnit;
    SkTileMode fTileMode;

public:
    static void AppendGradientFillStages(SkRasterPipeline* p,
                                         SkArenaAlloc* alloc,
                                         const SkPMColor4f* colors,
                                         const SkScalar* positions,
                                         int count);

    static void AppendInterpolatedToDstStages(SkRasterPipeline* p,
                                              SkArenaAlloc* alloc,
                                              bool colorsAreOpaque,
                                              const Interpolation& interpolation,
                                              const SkColorSpace* intermediateColorSpace,
                                              const SkColorSpace* dstColorSpace);

    SkScalar getPos(int i) const {
        SkASSERT(i < fColorCount);
        return fPositions ? fPositions[i] : SkIntToScalar(i) / (fColorCount - 1);
    }

    SkColor getLegacyColor(int i) const {
        SkASSERT(i < fColorCount);
        return fColors[i].toSkColor();
    }

    SkColor4f* fColors;               // points into fStorage
    SkScalar* fPositions;             // points into fStorage, or nullptr
    sk_sp<SkColorSpace> fColorSpace;  // color space of gradient stops
    Interpolation fInterpolation;

    int fColorCount;                  // length of fColors (and fPositions, if not nullptr)
    bool fFirstStopIsImplicit;
    bool fLastStopIsImplicit;

    bool colorsAreOpaque() const { return fColorsAreOpaque; }

    SkTileMode getTileMode() const { return fTileMode; }

    const SkBitmap& cachedBitmap() const { return fColorsAndOffsetsBitmap; }
    void setCachedBitmap(SkBitmap b) const { fColorsAndOffsetsBitmap = b; }

private:
    // When the number of stops exceeds Graphite's uniform-based limit the colors and offsets
    // are stored in this bitmap. It is stored in the shader so it can be cached with a stable
    // id and easily regenerated if purged.
    // TODO(b/293160919) remove this field when we can store bitmaps in the cache by id.
    mutable SkBitmap fColorsAndOffsetsBitmap;

    // Reserve inline space for up to 4 stops.
    inline static constexpr size_t kInlineStopCount = 4;
    inline static constexpr size_t kInlineStorageSize =
            (sizeof(SkColor4f) + sizeof(SkScalar)) * kInlineStopCount;
    skia_private::AutoSTMalloc<kInlineStorageSize, uint8_t> fStorage;

    bool fColorsAreOpaque;
};

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

struct SkColor4fXformer {
    SkColor4fXformer(const SkGradientBaseShader* shader,
                     SkColorSpace* dst,
                     bool forceExplicitPositions = false);

    using ColorStorage = skia_private::STArray<4, SkPMColor4f>;
    using PositionStorage = skia_private::STArray<4, float>;

    ColorStorage fColors;
    PositionStorage fPositionStorage;
    float* fPositions;
    sk_sp<SkColorSpace> fIntermediateColorSpace;
};

struct SkColorConverter {
    SkColorConverter(const SkColor* colors, int count);

    skia_private::STArray<2, SkColor4f> fColors4f;
};

void SkRegisterConicalGradientShaderFlattenable();
void SkRegisterLinearGradientShaderFlattenable();
void SkRegisterRadialGradientShaderFlattenable();
void SkRegisterSweepGradientShaderFlattenable();

#endif
