blob: 250a367822a2ecbe88e34fac23e592f4e283f3b0 [file] [log] [blame]
reed0ccc62d2016-05-04 13:09:39 -07001/*
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 "SkColorShader.h"
9#include "SkColorSpace.h"
10#include "SkReadBuffer.h"
11#include "SkUtils.h"
12
13SkColorShader::SkColorShader(SkColor c) : fColor(c) {}
14
15bool SkColorShader::isOpaque() const {
16 return SkColorGetA(fColor) == 255;
17}
18
19sk_sp<SkFlattenable> SkColorShader::CreateProc(SkReadBuffer& buffer) {
20 return sk_make_sp<SkColorShader>(buffer.readColor());
21}
22
23void SkColorShader::flatten(SkWriteBuffer& buffer) const {
24 buffer.writeColor(fColor);
25}
26
27uint32_t SkColorShader::ColorShaderContext::getFlags() const {
28 return fFlags;
29}
30
31SkShader::Context* SkColorShader::onCreateContext(const ContextRec& rec, void* storage) const {
32 return new (storage) ColorShaderContext(*this, rec);
33}
34
35SkColorShader::ColorShaderContext::ColorShaderContext(const SkColorShader& shader,
36 const ContextRec& rec)
37 : INHERITED(shader, rec)
38{
39 SkColor color = shader.fColor;
40 unsigned a = SkAlphaMul(SkColorGetA(color), SkAlpha255To256(rec.fPaint->getAlpha()));
41
42 unsigned r = SkColorGetR(color);
43 unsigned g = SkColorGetG(color);
44 unsigned b = SkColorGetB(color);
45
46 if (a != 255) {
47 r = SkMulDiv255Round(r, a);
48 g = SkMulDiv255Round(g, a);
49 b = SkMulDiv255Round(b, a);
50 }
51 fPMColor = SkPackARGB32(a, r, g, b);
52
53 SkColor4f c4 = SkColor4f::FromColor(shader.fColor);
54 c4.fA *= rec.fPaint->getAlpha() / 255.0f;
55 fPM4f = c4.premul();
56
57 fFlags = kConstInY32_Flag;
58 if (255 == a) {
59 fFlags |= kOpaqueAlpha_Flag;
60 }
61}
62
63void SkColorShader::ColorShaderContext::shadeSpan(int x, int y, SkPMColor span[], int count) {
64 sk_memset32(span, fPMColor, count);
65}
66
67void SkColorShader::ColorShaderContext::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) {
68 memset(alpha, SkGetPackedA32(fPMColor), count);
69}
70
71void SkColorShader::ColorShaderContext::shadeSpan4f(int x, int y, SkPM4f span[], int count) {
72 for (int i = 0; i < count; ++i) {
73 span[i] = fPM4f;
74 }
75}
76
77SkShader::GradientType SkColorShader::asAGradient(GradientInfo* info) const {
78 if (info) {
79 if (info->fColors && info->fColorCount >= 1) {
80 info->fColors[0] = fColor;
81 }
82 info->fColorCount = 1;
83 info->fTileMode = SkShader::kRepeat_TileMode;
84 }
85 return kColor_GradientType;
86}
87
88#if SK_SUPPORT_GPU
89
90#include "SkGr.h"
91#include "effects/GrConstColorProcessor.h"
bungeman06ca8ec2016-06-09 08:01:03 -070092sk_sp<GrFragmentProcessor> SkColorShader::asFragmentProcessor(GrContext*, const SkMatrix&,
reed0ccc62d2016-05-04 13:09:39 -070093 const SkMatrix*,
brianosman982eb7f2016-06-06 13:10:58 -070094 SkFilterQuality,
95 SkSourceGammaTreatment) const {
reed0ccc62d2016-05-04 13:09:39 -070096 GrColor color = SkColorToPremulGrColor(fColor);
bungeman06ca8ec2016-06-09 08:01:03 -070097 return GrConstColorProcessor::Make(color, GrConstColorProcessor::kModulateA_InputMode);
reed0ccc62d2016-05-04 13:09:39 -070098}
99
100#endif
101
102#ifndef SK_IGNORE_TO_STRING
103void SkColorShader::toString(SkString* str) const {
104 str->append("SkColorShader: (");
105
106 str->append("Color: ");
107 str->appendHex(fColor);
108
109 this->INHERITED::toString(str);
110
111 str->append(")");
112}
113#endif
114
115///////////////////////////////////////////////////////////////////////////////////////////////////
116///////////////////////////////////////////////////////////////////////////////////////////////////
117
118static unsigned unit_to_byte(float unit) {
119 SkASSERT(unit >= 0 && unit <= 1);
120 return (unsigned)(unit * 255 + 0.5);
121}
122
123static SkColor unit_to_skcolor(const SkColor4f& unit, SkColorSpace* cs) {
124 return SkColorSetARGB(unit_to_byte(unit.fA), unit_to_byte(unit.fR),
125 unit_to_byte(unit.fG), unit_to_byte(unit.fB));
126}
127
128SkColor4Shader::SkColor4Shader(const SkColor4f& color, sk_sp<SkColorSpace> space)
129 : fColorSpace(std::move(space))
130 , fColor4(color)
131 , fCachedByteColor(unit_to_skcolor(color.pin(), space.get()))
132{}
133
134sk_sp<SkFlattenable> SkColor4Shader::CreateProc(SkReadBuffer& buffer) {
135 SkColor4f color;
136 color.fA = buffer.readScalar(); // readFloat()
137 color.fR = buffer.readScalar();
138 color.fG = buffer.readScalar();
139 color.fB = buffer.readScalar();
140 if (buffer.readBool()) {
141 // TODO how do we unflatten colorspaces
142 }
143 return SkShader::MakeColorShader(color, nullptr);
144}
145
146void SkColor4Shader::flatten(SkWriteBuffer& buffer) const {
147 buffer.writeScalar(fColor4.fA); // writeFloat()
148 buffer.writeScalar(fColor4.fR);
149 buffer.writeScalar(fColor4.fG);
150 buffer.writeScalar(fColor4.fB);
151 buffer.writeBool(false); // TODO how do we flatten colorspaces?
152}
153
154uint32_t SkColor4Shader::Color4Context::getFlags() const {
155 return fFlags;
156}
157
158SkShader::Context* SkColor4Shader::onCreateContext(const ContextRec& rec, void* storage) const {
159 return new (storage) Color4Context(*this, rec);
160}
161
162SkColor4Shader::Color4Context::Color4Context(const SkColor4Shader& shader,
163 const ContextRec& rec)
164: INHERITED(shader, rec)
165{
166 SkColor color = shader.fCachedByteColor;
167 unsigned a = SkAlphaMul(SkColorGetA(color), SkAlpha255To256(rec.fPaint->getAlpha()));
168
169 unsigned r = SkColorGetR(color);
170 unsigned g = SkColorGetG(color);
171 unsigned b = SkColorGetB(color);
172
173 if (a != 255) {
174 r = SkMulDiv255Round(r, a);
175 g = SkMulDiv255Round(g, a);
176 b = SkMulDiv255Round(b, a);
177 }
178 fPMColor = SkPackARGB32(a, r, g, b);
179
180 SkColor4f c4 = shader.fColor4;
181 c4.fA *= rec.fPaint->getAlpha() * (1 / 255.0f);
182 fPM4f = c4.premul();
183
184 fFlags = kConstInY32_Flag;
185 if (255 == a) {
186 fFlags |= kOpaqueAlpha_Flag;
187 }
188}
189
190void SkColor4Shader::Color4Context::shadeSpan(int x, int y, SkPMColor span[], int count) {
191 sk_memset32(span, fPMColor, count);
192}
193
194void SkColor4Shader::Color4Context::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) {
195 memset(alpha, SkGetPackedA32(fPMColor), count);
196}
197
198void SkColor4Shader::Color4Context::shadeSpan4f(int x, int y, SkPM4f span[], int count) {
199 for (int i = 0; i < count; ++i) {
200 span[i] = fPM4f;
201 }
202}
203
204// TODO: do we need an updated version of this method for color4+colorspace?
205SkShader::GradientType SkColor4Shader::asAGradient(GradientInfo* info) const {
206 if (info) {
207 if (info->fColors && info->fColorCount >= 1) {
208 info->fColors[0] = fCachedByteColor;
209 }
210 info->fColorCount = 1;
211 info->fTileMode = SkShader::kRepeat_TileMode;
212 }
213 return kColor_GradientType;
214}
215
216#if SK_SUPPORT_GPU
217
218#include "SkGr.h"
219#include "effects/GrConstColorProcessor.h"
bungeman06ca8ec2016-06-09 08:01:03 -0700220sk_sp<GrFragmentProcessor> SkColor4Shader::asFragmentProcessor(GrContext*, const SkMatrix&,
reed0ccc62d2016-05-04 13:09:39 -0700221 const SkMatrix*,
brianosman982eb7f2016-06-06 13:10:58 -0700222 SkFilterQuality,
223 SkSourceGammaTreatment) const {
reed0ccc62d2016-05-04 13:09:39 -0700224 // TODO: how to communicate color4f to Gr
225 GrColor color = SkColorToPremulGrColor(fCachedByteColor);
bungeman06ca8ec2016-06-09 08:01:03 -0700226 return GrConstColorProcessor::Make(color, GrConstColorProcessor::kModulateA_InputMode);
reed0ccc62d2016-05-04 13:09:39 -0700227}
228
229#endif
230
231#ifndef SK_IGNORE_TO_STRING
232void SkColor4Shader::toString(SkString* str) const {
233 str->append("SkColor4Shader: (");
234
235 str->append("ARGB:");
236 for (int i = 0; i < 4; ++i) {
237 str->appendf(" %g", fColor4.vec()[i]);
238 }
239 str->append(" )");
240}
241#endif
242
243sk_sp<SkShader> SkShader::MakeColorShader(const SkColor4f& color, sk_sp<SkColorSpace> space) {
244 if (!SkScalarsAreFinite(color.vec(), 4)) {
245 return nullptr;
246 }
247 return sk_make_sp<SkColor4Shader>(color, std::move(space));
248}
249
250///////////////////////////////////////////////////////////////////////////////////////////////////
251///////////////////////////////////////////////////////////////////////////////////////////////////
252
253static void D32_BlitBW(SkShader::Context::BlitState* state, int x, int y, const SkPixmap& dst,
254 int count) {
255 SkXfermode::D32Proc proc = (SkXfermode::D32Proc)state->fStorage[0];
256 const SkPM4f* src = (const SkPM4f*)state->fStorage[1];
257 proc(state->fXfer, dst.writable_addr32(x, y), src, count, nullptr);
258}
259
260static void D32_BlitAA(SkShader::Context::BlitState* state, int x, int y, const SkPixmap& dst,
261 int count, const SkAlpha aa[]) {
262 SkXfermode::D32Proc proc = (SkXfermode::D32Proc)state->fStorage[0];
263 const SkPM4f* src = (const SkPM4f*)state->fStorage[1];
264 proc(state->fXfer, dst.writable_addr32(x, y), src, count, aa);
265}
266
267static void F16_BlitBW(SkShader::Context::BlitState* state, int x, int y, const SkPixmap& dst,
268 int count) {
269 SkXfermode::F16Proc proc = (SkXfermode::F16Proc)state->fStorage[0];
270 const SkPM4f* src = (const SkPM4f*)state->fStorage[1];
271 proc(state->fXfer, dst.writable_addr64(x, y), src, count, nullptr);
272}
273
274static void F16_BlitAA(SkShader::Context::BlitState* state, int x, int y, const SkPixmap& dst,
275 int count, const SkAlpha aa[]) {
276 SkXfermode::F16Proc proc = (SkXfermode::F16Proc)state->fStorage[0];
277 const SkPM4f* src = (const SkPM4f*)state->fStorage[1];
278 proc(state->fXfer, dst.writable_addr64(x, y), src, count, aa);
279}
280
281static bool choose_blitprocs(const SkPM4f* pm4, const SkImageInfo& info,
282 SkShader::Context::BlitState* state) {
283 uint32_t flags = SkXfermode::kSrcIsSingle_D32Flag;
284 if (pm4->a() == 1) {
285 flags |= SkXfermode::kSrcIsOpaque_D32Flag;
286 }
287 switch (info.colorType()) {
288 case kN32_SkColorType:
reeddabe5d32016-06-21 10:28:14 -0700289 if (info.gammaCloseToSRGB()) {
reed0ccc62d2016-05-04 13:09:39 -0700290 flags |= SkXfermode::kDstIsSRGB_D32Flag;
291 }
292 state->fStorage[0] = (void*)SkXfermode::GetD32Proc(state->fXfer, flags);
293 state->fStorage[1] = (void*)pm4;
294 state->fBlitBW = D32_BlitBW;
295 state->fBlitAA = D32_BlitAA;
296 return true;
297 case kRGBA_F16_SkColorType:
298 state->fStorage[0] = (void*)SkXfermode::GetF16Proc(state->fXfer, flags);
299 state->fStorage[1] = (void*)pm4;
300 state->fBlitBW = F16_BlitBW;
301 state->fBlitAA = F16_BlitAA;
302 return true;
303 default:
304 return false;
305 }
306}
307
308bool SkColorShader::ColorShaderContext::onChooseBlitProcs(const SkImageInfo& info,
309 BlitState* state) {
310 return choose_blitprocs(&fPM4f, info, state);
311}
312
313bool SkColor4Shader::Color4Context::onChooseBlitProcs(const SkImageInfo& info, BlitState* state) {
314 return choose_blitprocs(&fPM4f, info, state);
315}