1/*
2 * Copyright 2012 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#ifndef SkGradientShaderPriv_DEFINED
9#define SkGradientShaderPriv_DEFINED
10
11#include "include/effects/SkGradientShader.h"
12
13#include "include/core/SkMatrix.h"
14#include "include/private/SkTArray.h"
15#include "include/private/SkTemplates.h"
16#include "src/core/SkArenaAlloc.h"
17#include "src/core/SkVM.h"
18#include "src/shaders/SkShaderBase.h"
19
20class SkColorSpace;
21class SkRasterPipeline;
22class SkReadBuffer;
23class SkWriteBuffer;
24
25class SkGradientShaderBase : public SkShaderBase {
26public:
27 struct Descriptor {
28 Descriptor() {
29 sk_bzero(this, sizeof(*this));
30 fTileMode = SkTileMode::kClamp;
31 }
32
33 const SkMatrix* fLocalMatrix;
34 const SkColor4f* fColors;
35 sk_sp<SkColorSpace> fColorSpace;
36 const SkScalar* fPos;
37 int fCount;
38 SkTileMode fTileMode;
39 uint32_t fGradFlags;
40
41 void flatten(SkWriteBuffer&) const;
42 };
43
44 class DescriptorScope : public Descriptor {
45 public:
46 DescriptorScope() {}
47
48 bool unflatten(SkReadBuffer&);
49
50 // fColors and fPos always point into local memory, so they can be safely mutated
51 //
52 SkColor4f* mutableColors() { return const_cast<SkColor4f*>(fColors); }
53 SkScalar* mutablePos() { return const_cast<SkScalar*>(fPos); }
54
55 private:
56 SkSTArray<16, SkColor4f, true> fColorStorage;
57 SkSTArray<16, SkScalar , true> fPosStorage;
58 SkMatrix fLocalMatrixStorage;
59 };
60
61 SkGradientShaderBase(const Descriptor& desc, const SkMatrix& ptsToUnit);
62 ~SkGradientShaderBase() override;
63
64 bool isOpaque() const override;
65
66 uint32_t getGradFlags() const { return fGradFlags; }
67
68 const SkMatrix& getGradientMatrix() const { return fPtsToUnit; }
69
70protected:
71 class GradientShaderBase4fContext;
72
73 SkGradientShaderBase(SkReadBuffer& );
74 void flatten(SkWriteBuffer&) const override;
75
76 void commonAsAGradient(GradientInfo*) const;
77
78 bool onAsLuminanceColor(SkColor*) const override;
79
80 bool onAppendStages(const SkStageRec&) const override;
81
82 skvm::Color onProgram(skvm::Builder*, skvm::Coord device, skvm::Coord local, skvm::Color paint,
83 const SkMatrixProvider&, const SkMatrix* localM,
84 SkFilterQuality quality, const SkColorInfo& dstCS,
85 skvm::Uniforms* uniforms, SkArenaAlloc* alloc) const override;
86
87 virtual void appendGradientStages(SkArenaAlloc* alloc, SkRasterPipeline* tPipeline,
88 SkRasterPipeline* postPipeline) const = 0;
89
90 // Produce t from (x,y), modifying mask if it should be anything other than ~0.
91 virtual skvm::F32 transformT(skvm::Builder*, skvm::Uniforms*,
92 skvm::Coord coord, skvm::I32* mask) const = 0;
93
94 template <typename T, typename... Args>
95 static Context* CheckedMakeContext(SkArenaAlloc* alloc, Args&&... args) {
96 auto* ctx = alloc->make<T>(std::forward<Args>(args)...);
97 if (!ctx->isValid()) {
98 return nullptr;
99 }
100 return ctx;
101 }
102
103 const SkMatrix fPtsToUnit;
104 SkTileMode fTileMode;
105 uint8_t fGradFlags;
106
107public:
108 SkScalar getPos(int i) const {
109 SkASSERT(i < fColorCount);
110 return fOrigPos ? fOrigPos[i] : SkIntToScalar(i) / (fColorCount - 1);
111 }
112
113 SkColor getLegacyColor(int i) const {
114 SkASSERT(i < fColorCount);
115 return fOrigColors4f[i].toSkColor();
116 }
117
118 bool colorsCanConvertToSkColor() const {
119 bool canConvert = true;
120 for (int i = 0; i < fColorCount; ++i) {
121 canConvert &= fOrigColors4f[i].fitsInBytes();
122 }
123 return canConvert;
124 }
125
126 SkColor4f* fOrigColors4f; // original colors, as floats
127 SkScalar* fOrigPos; // original positions
128 int fColorCount;
129 sk_sp<SkColorSpace> fColorSpace; // color space of gradient stops
130
131 bool colorsAreOpaque() const { return fColorsAreOpaque; }
132
133 SkTileMode getTileMode() const { return fTileMode; }
134
135private:
136 // Reserve inline space for up to 4 stops.
137 static constexpr size_t kInlineStopCount = 4;
138 static constexpr size_t kInlineStorageSize = (sizeof(SkColor4f) + sizeof(SkScalar))
139 * kInlineStopCount;
140 SkAutoSTMalloc<kInlineStorageSize, uint8_t> fStorage;
141
142 bool fColorsAreOpaque;
143
144 typedef SkShaderBase INHERITED;
145};
146
147///////////////////////////////////////////////////////////////////////////////
148
149struct SkColor4fXformer {
150 SkColor4fXformer(const SkColor4f* colors, int colorCount, SkColorSpace* src, SkColorSpace* dst);
151
152 const SkColor4f* fColors;
153 SkSTArray<4, SkColor4f, true> fStorage;
154};
155
156#endif
157