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 | |
20 | class SkColorSpace; |
21 | class SkRasterPipeline; |
22 | class SkReadBuffer; |
23 | class SkWriteBuffer; |
24 | |
25 | class SkGradientShaderBase : public SkShaderBase { |
26 | public: |
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 | |
70 | protected: |
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* p, skvm::F32 x, skvm::F32 y, skvm::Color paint, |
83 | const SkMatrix& ctm, 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::F32 x, skvm::F32 y, 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 | |
107 | public: |
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 | |
135 | private: |
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 | |
149 | struct 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 | |