/*
* 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 "SkGradientShader.h"
#include "SkArenaAlloc.h"
#include "SkMatrix.h"
#include "SkShaderBase.h"
#include "SkTArray.h"
#include "SkTemplates.h"
class SkColorSpace;
class SkColorSpaceXformer;
class SkRasterPipeline;
class SkReadBuffer;
class SkWriteBuffer;
class SkGradientShaderBase : public SkShaderBase {
public:
struct Descriptor {
Descriptor() {
sk_bzero(this, sizeof(*this));
fTileMode = SkShader::kClamp_TileMode;
}
const SkMatrix* fLocalMatrix;
const SkColor4f* fColors;
sk_sp<SkColorSpace> fColorSpace;
const SkScalar* fPos;
int fCount;
SkShader::TileMode fTileMode;
uint32_t fGradFlags;
void flatten(SkWriteBuffer&) const;
};
class DescriptorScope : public Descriptor {
public:
DescriptorScope() {}
bool unflatten(SkReadBuffer&);
// fColors and fPos always point into local memory, so they can be safely mutated
//
SkColor4f* mutableColors() { return const_cast<SkColor4f*>(fColors); }
SkScalar* mutablePos() { return const_cast<SkScalar*>(fPos); }
private:
SkSTArray<16, SkColor4f, true> fColorStorage;
SkSTArray<16, SkScalar , true> fPosStorage;
SkMatrix fLocalMatrixStorage;
};
SkGradientShaderBase(const Descriptor& desc, const SkMatrix& ptsToUnit);
~SkGradientShaderBase() override;
bool isOpaque() const override;
uint32_t getGradFlags() const { return fGradFlags; }
const SkMatrix& getGradientMatrix() const { return fPtsToUnit; }
protected:
class GradientShaderBase4fContext;
SkGradientShaderBase(SkReadBuffer& );
void flatten(SkWriteBuffer&) const override;
void commonAsAGradient(GradientInfo*) const;
bool onAsLuminanceColor(SkColor*) const override;
bool onAppendStages(const StageRec&) const override;
virtual void appendGradientStages(SkArenaAlloc* alloc, SkRasterPipeline* tPipeline,
SkRasterPipeline* postPipeline) const = 0;
template <typename T, typename... Args>
static Context* CheckedMakeContext(SkArenaAlloc* alloc, Args&&... args) {
auto* ctx = alloc->make<T>(std::forward<Args>(args)...);
if (!ctx->isValid()) {
return nullptr;
}
return ctx;
}
struct AutoXformColors {
AutoXformColors(const SkGradientShaderBase&, SkColorSpaceXformer*);
SkAutoSTMalloc<8, SkColor> fColors;
};
const SkMatrix fPtsToUnit;
TileMode fTileMode;
uint8_t fGradFlags;
public:
SkScalar getPos(int i) const {
SkASSERT(i < fColorCount);
return fOrigPos ? fOrigPos[i] : SkIntToScalar(i) / (fColorCount - 1);
}
SkColor getLegacyColor(int i) const {
SkASSERT(i < fColorCount);
return fOrigColors4f[i].toSkColor();
}
SkColor4f* fOrigColors4f; // original colors, as linear floats
SkScalar* fOrigPos; // original positions
int fColorCount;
sk_sp<SkColorSpace> fColorSpace; // color space of gradient stops
bool colorsAreOpaque() const { return fColorsAreOpaque; }
TileMode getTileMode() const { return fTileMode; }
private:
// Reserve inline space for up to 4 stops.
static constexpr size_t kInlineStopCount = 4;
static constexpr size_t kInlineStorageSize = (sizeof(SkColor4f) + sizeof(SkScalar))
* kInlineStopCount;
SkAutoSTMalloc<kInlineStorageSize, uint8_t> fStorage;
bool fColorsAreOpaque;
typedef SkShaderBase INHERITED;
};
///////////////////////////////////////////////////////////////////////////////
struct SkColor4fXformer {
SkColor4fXformer(const SkColor4f* colors, int colorCount, SkColorSpace* src, SkColorSpace* dst);
const SkColor4f* fColors;
SkSTArray<4, SkColor4f, true> fStorage;
};
#endif