• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2016 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 #include "SkArenaAlloc.h"
9 #include "SkColorShader.h"
10 #include "SkColorSpace.h"
11 #include "SkPM4fPriv.h"
12 #include "SkRasterPipeline.h"
13 #include "SkReadBuffer.h"
14 #include "SkUtils.h"
15 
SkColorShader(SkColor c)16 SkColorShader::SkColorShader(SkColor c) : fColor(c) {}
17 
isOpaque() const18 bool SkColorShader::isOpaque() const {
19     return SkColorGetA(fColor) == 255;
20 }
21 
CreateProc(SkReadBuffer & buffer)22 sk_sp<SkFlattenable> SkColorShader::CreateProc(SkReadBuffer& buffer) {
23     return sk_make_sp<SkColorShader>(buffer.readColor());
24 }
25 
flatten(SkWriteBuffer & buffer) const26 void SkColorShader::flatten(SkWriteBuffer& buffer) const {
27     buffer.writeColor(fColor);
28 }
29 
getFlags() const30 uint32_t SkColorShader::ColorShaderContext::getFlags() const {
31     return fFlags;
32 }
33 
onMakeContext(const ContextRec & rec,SkArenaAlloc * alloc) const34 SkShaderBase::Context* SkColorShader::onMakeContext(const ContextRec& rec,
35                                                     SkArenaAlloc* alloc) const {
36     return alloc->make<ColorShaderContext>(*this, rec);
37 }
38 
ColorShaderContext(const SkColorShader & shader,const ContextRec & rec)39 SkColorShader::ColorShaderContext::ColorShaderContext(const SkColorShader& shader,
40                                                       const ContextRec& rec)
41     : INHERITED(shader, rec)
42 {
43     SkColor color = shader.fColor;
44     unsigned a = SkAlphaMul(SkColorGetA(color), SkAlpha255To256(rec.fPaint->getAlpha()));
45 
46     unsigned r = SkColorGetR(color);
47     unsigned g = SkColorGetG(color);
48     unsigned b = SkColorGetB(color);
49 
50     if (a != 255) {
51         r = SkMulDiv255Round(r, a);
52         g = SkMulDiv255Round(g, a);
53         b = SkMulDiv255Round(b, a);
54     }
55     fPMColor = SkPackARGB32(a, r, g, b);
56 
57     SkColor4f c4 = SkColor4f::FromColor(shader.fColor);
58     c4.fA *= rec.fPaint->getAlpha() / 255.0f;
59     fPM4f = c4.premul();
60 
61     fFlags = kConstInY32_Flag;
62     if (255 == a) {
63         fFlags |= kOpaqueAlpha_Flag;
64     }
65 }
66 
shadeSpan(int x,int y,SkPMColor span[],int count)67 void SkColorShader::ColorShaderContext::shadeSpan(int x, int y, SkPMColor span[], int count) {
68     sk_memset32(span, fPMColor, count);
69 }
70 
shadeSpanAlpha(int x,int y,uint8_t alpha[],int count)71 void SkColorShader::ColorShaderContext::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) {
72     memset(alpha, SkGetPackedA32(fPMColor), count);
73 }
74 
shadeSpan4f(int x,int y,SkPM4f span[],int count)75 void SkColorShader::ColorShaderContext::shadeSpan4f(int x, int y, SkPM4f span[], int count) {
76     for (int i = 0; i < count; ++i) {
77         span[i] = fPM4f;
78     }
79 }
80 
asAGradient(GradientInfo * info) const81 SkShader::GradientType SkColorShader::asAGradient(GradientInfo* info) const {
82     if (info) {
83         if (info->fColors && info->fColorCount >= 1) {
84             info->fColors[0] = fColor;
85         }
86         info->fColorCount = 1;
87         info->fTileMode = SkShader::kRepeat_TileMode;
88     }
89     return kColor_GradientType;
90 }
91 
92 #if SK_SUPPORT_GPU
93 
94 #include "SkGr.h"
95 #include "effects/GrConstColorProcessor.h"
asFragmentProcessor(const AsFPArgs & args) const96 sk_sp<GrFragmentProcessor> SkColorShader::asFragmentProcessor(const AsFPArgs& args) const {
97     GrColor4f color = SkColorToPremulGrColor4f(fColor, args.fDstColorSpace);
98     return GrConstColorProcessor::Make(color, GrConstColorProcessor::kModulateA_InputMode);
99 }
100 
101 #endif
102 
103 #ifndef SK_IGNORE_TO_STRING
toString(SkString * str) const104 void SkColorShader::toString(SkString* str) const {
105     str->append("SkColorShader: (");
106 
107     str->append("Color: ");
108     str->appendHex(fColor);
109 
110     this->INHERITED::toString(str);
111 
112     str->append(")");
113 }
114 #endif
115 
116 ///////////////////////////////////////////////////////////////////////////////////////////////////
117 ///////////////////////////////////////////////////////////////////////////////////////////////////
118 
unit_to_byte(float unit)119 static unsigned unit_to_byte(float unit) {
120     SkASSERT(unit >= 0 && unit <= 1);
121     return (unsigned)(unit * 255 + 0.5);
122 }
123 
unit_to_skcolor(const SkColor4f & unit,SkColorSpace * cs)124 static SkColor unit_to_skcolor(const SkColor4f& unit, SkColorSpace* cs) {
125     return SkColorSetARGB(unit_to_byte(unit.fA), unit_to_byte(unit.fR),
126                           unit_to_byte(unit.fG), unit_to_byte(unit.fB));
127 }
128 
SkColor4Shader(const SkColor4f & color,sk_sp<SkColorSpace> space)129 SkColor4Shader::SkColor4Shader(const SkColor4f& color, sk_sp<SkColorSpace> space)
130     : fColorSpace(std::move(space))
131     , fColor4(color)
132     , fCachedByteColor(unit_to_skcolor(color.pin(), space.get()))
133 {}
134 
CreateProc(SkReadBuffer & buffer)135 sk_sp<SkFlattenable> SkColor4Shader::CreateProc(SkReadBuffer& buffer) {
136     SkColor4f color;
137     buffer.readColor4f(&color);
138     if (buffer.readBool()) {
139         // TODO how do we unflatten colorspaces
140     }
141     return SkShader::MakeColorShader(color, nullptr);
142 }
143 
flatten(SkWriteBuffer & buffer) const144 void SkColor4Shader::flatten(SkWriteBuffer& buffer) const {
145     buffer.writeColor4f(fColor4);
146     buffer.writeBool(false);    // TODO how do we flatten colorspaces?
147 }
148 
getFlags() const149 uint32_t SkColor4Shader::Color4Context::getFlags() const {
150     return fFlags;
151 }
152 
onMakeContext(const ContextRec & rec,SkArenaAlloc * alloc) const153 SkShaderBase::Context* SkColor4Shader::onMakeContext(const ContextRec& rec,
154                                                      SkArenaAlloc* alloc) const {
155     return alloc->make<Color4Context>(*this, rec);
156 }
157 
Color4Context(const SkColor4Shader & shader,const ContextRec & rec)158 SkColor4Shader::Color4Context::Color4Context(const SkColor4Shader& shader,
159                                                       const ContextRec& rec)
160 : INHERITED(shader, rec)
161 {
162     SkColor color = shader.fCachedByteColor;
163     unsigned a = SkAlphaMul(SkColorGetA(color), SkAlpha255To256(rec.fPaint->getAlpha()));
164 
165     unsigned r = SkColorGetR(color);
166     unsigned g = SkColorGetG(color);
167     unsigned b = SkColorGetB(color);
168 
169     if (a != 255) {
170         r = SkMulDiv255Round(r, a);
171         g = SkMulDiv255Round(g, a);
172         b = SkMulDiv255Round(b, a);
173     }
174     fPMColor = SkPackARGB32(a, r, g, b);
175 
176     SkColor4f c4 = shader.fColor4;
177     c4.fA *= rec.fPaint->getAlpha() * (1 / 255.0f);
178     fPM4f = c4.premul();
179 
180     fFlags = kConstInY32_Flag;
181     if (255 == a) {
182         fFlags |= kOpaqueAlpha_Flag;
183     }
184 }
185 
shadeSpan(int x,int y,SkPMColor span[],int count)186 void SkColor4Shader::Color4Context::shadeSpan(int x, int y, SkPMColor span[], int count) {
187     sk_memset32(span, fPMColor, count);
188 }
189 
shadeSpanAlpha(int x,int y,uint8_t alpha[],int count)190 void SkColor4Shader::Color4Context::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) {
191     memset(alpha, SkGetPackedA32(fPMColor), count);
192 }
193 
shadeSpan4f(int x,int y,SkPM4f span[],int count)194 void SkColor4Shader::Color4Context::shadeSpan4f(int x, int y, SkPM4f span[], int count) {
195     for (int i = 0; i < count; ++i) {
196         span[i] = fPM4f;
197     }
198 }
199 
200 // TODO: do we need an updated version of this method for color4+colorspace?
asAGradient(GradientInfo * info) const201 SkShader::GradientType SkColor4Shader::asAGradient(GradientInfo* info) const {
202     if (info) {
203         if (info->fColors && info->fColorCount >= 1) {
204             info->fColors[0] = fCachedByteColor;
205         }
206         info->fColorCount = 1;
207         info->fTileMode = SkShader::kRepeat_TileMode;
208     }
209     return kColor_GradientType;
210 }
211 
212 #if SK_SUPPORT_GPU
213 
214 #include "SkGr.h"
215 #include "effects/GrConstColorProcessor.h"
216 #include "GrColorSpaceXform.h"
asFragmentProcessor(const AsFPArgs & args) const217 sk_sp<GrFragmentProcessor> SkColor4Shader::asFragmentProcessor(const AsFPArgs& args) const {
218     sk_sp<GrColorSpaceXform> colorSpaceXform = GrColorSpaceXform::Make(fColorSpace.get(),
219                                                                        args.fDstColorSpace);
220     GrColor4f color = GrColor4f::FromSkColor4f(fColor4);
221     if (colorSpaceXform) {
222         color = colorSpaceXform->apply(color);
223     }
224     return GrConstColorProcessor::Make(color.premul(), GrConstColorProcessor::kModulateA_InputMode);
225 }
226 
227 #endif
228 
229 #ifndef SK_IGNORE_TO_STRING
toString(SkString * str) const230 void SkColor4Shader::toString(SkString* str) const {
231     str->append("SkColor4Shader: (");
232 
233     str->append("RGBA:");
234     for (int i = 0; i < 4; ++i) {
235         str->appendf(" %g", fColor4.vec()[i]);
236     }
237     str->append(" )");
238 }
239 #endif
240 
onMakeColorSpace(SkColorSpaceXformer * xformer) const241 sk_sp<SkShader> SkColor4Shader::onMakeColorSpace(SkColorSpaceXformer* xformer) const {
242     return SkShader::MakeColorShader(xformer->apply(fCachedByteColor));
243 }
244 
MakeColorShader(const SkColor4f & color,sk_sp<SkColorSpace> space)245 sk_sp<SkShader> SkShader::MakeColorShader(const SkColor4f& color, sk_sp<SkColorSpace> space) {
246     if (!SkScalarsAreFinite(color.vec(), 4)) {
247         return nullptr;
248     }
249     return sk_make_sp<SkColor4Shader>(color, std::move(space));
250 }
251 
252 ///////////////////////////////////////////////////////////////////////////////////////////////////
253 
onAppendStages(SkRasterPipeline * p,SkColorSpace * dst,SkArenaAlloc * scratch,const SkMatrix &,const SkPaint &,const SkMatrix *) const254 bool SkColorShader::onAppendStages(SkRasterPipeline* p,
255                                    SkColorSpace* dst,
256                                    SkArenaAlloc* scratch,
257                                    const SkMatrix&,
258                                    const SkPaint&,
259                                    const SkMatrix*) const {
260     p->append_uniform_color(scratch, SkPM4f_from_SkColor(fColor, dst));
261     return true;
262 }
263 
onAppendStages(SkRasterPipeline * p,SkColorSpace * dst,SkArenaAlloc * scratch,const SkMatrix &,const SkPaint &,const SkMatrix *) const264 bool SkColor4Shader::onAppendStages(SkRasterPipeline* p,
265                                     SkColorSpace* dst,
266                                     SkArenaAlloc* scratch,
267                                     const SkMatrix&,
268                                     const SkPaint&,
269                                     const SkMatrix*) const {
270     p->append_uniform_color(scratch, to_colorspace(fColor4, fColorSpace.get(), dst).premul());
271     return true;
272 }
273