Line data Source code
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 :
16 0 : SkColorShader::SkColorShader(SkColor c) : fColor(c) {}
17 :
18 0 : bool SkColorShader::isOpaque() const {
19 0 : return SkColorGetA(fColor) == 255;
20 : }
21 :
22 0 : sk_sp<SkFlattenable> SkColorShader::CreateProc(SkReadBuffer& buffer) {
23 0 : return sk_make_sp<SkColorShader>(buffer.readColor());
24 : }
25 :
26 0 : void SkColorShader::flatten(SkWriteBuffer& buffer) const {
27 0 : buffer.writeColor(fColor);
28 0 : }
29 :
30 0 : uint32_t SkColorShader::ColorShaderContext::getFlags() const {
31 0 : return fFlags;
32 : }
33 :
34 0 : SkShader::Context* SkColorShader::onMakeContext(const ContextRec& rec, SkArenaAlloc* alloc) const {
35 0 : return alloc->make<ColorShaderContext>(*this, rec);
36 : }
37 :
38 0 : SkColorShader::ColorShaderContext::ColorShaderContext(const SkColorShader& shader,
39 0 : const ContextRec& rec)
40 0 : : INHERITED(shader, rec)
41 : {
42 0 : SkColor color = shader.fColor;
43 0 : unsigned a = SkAlphaMul(SkColorGetA(color), SkAlpha255To256(rec.fPaint->getAlpha()));
44 :
45 0 : unsigned r = SkColorGetR(color);
46 0 : unsigned g = SkColorGetG(color);
47 0 : unsigned b = SkColorGetB(color);
48 :
49 0 : if (a != 255) {
50 0 : r = SkMulDiv255Round(r, a);
51 0 : g = SkMulDiv255Round(g, a);
52 0 : b = SkMulDiv255Round(b, a);
53 : }
54 0 : fPMColor = SkPackARGB32(a, r, g, b);
55 :
56 0 : SkColor4f c4 = SkColor4f::FromColor(shader.fColor);
57 0 : c4.fA *= rec.fPaint->getAlpha() / 255.0f;
58 0 : fPM4f = c4.premul();
59 :
60 0 : fFlags = kConstInY32_Flag;
61 0 : if (255 == a) {
62 0 : fFlags |= kOpaqueAlpha_Flag;
63 : }
64 0 : }
65 :
66 0 : void SkColorShader::ColorShaderContext::shadeSpan(int x, int y, SkPMColor span[], int count) {
67 0 : sk_memset32(span, fPMColor, count);
68 0 : }
69 :
70 0 : void SkColorShader::ColorShaderContext::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) {
71 0 : memset(alpha, SkGetPackedA32(fPMColor), count);
72 0 : }
73 :
74 0 : void SkColorShader::ColorShaderContext::shadeSpan4f(int x, int y, SkPM4f span[], int count) {
75 0 : for (int i = 0; i < count; ++i) {
76 0 : span[i] = fPM4f;
77 : }
78 0 : }
79 :
80 0 : SkShader::GradientType SkColorShader::asAGradient(GradientInfo* info) const {
81 0 : if (info) {
82 0 : if (info->fColors && info->fColorCount >= 1) {
83 0 : info->fColors[0] = fColor;
84 : }
85 0 : info->fColorCount = 1;
86 0 : info->fTileMode = SkShader::kRepeat_TileMode;
87 : }
88 0 : return kColor_GradientType;
89 : }
90 :
91 : #if SK_SUPPORT_GPU
92 :
93 : #include "SkGr.h"
94 : #include "effects/GrConstColorProcessor.h"
95 0 : sk_sp<GrFragmentProcessor> SkColorShader::asFragmentProcessor(const AsFPArgs& args) const {
96 0 : GrColor4f color = SkColorToPremulGrColor4f(fColor, args.fDstColorSpace);
97 0 : return GrConstColorProcessor::Make(color, GrConstColorProcessor::kModulateA_InputMode);
98 : }
99 :
100 : #endif
101 :
102 : #ifndef SK_IGNORE_TO_STRING
103 0 : void SkColorShader::toString(SkString* str) const {
104 0 : str->append("SkColorShader: (");
105 :
106 0 : str->append("Color: ");
107 0 : str->appendHex(fColor);
108 :
109 0 : this->INHERITED::toString(str);
110 :
111 0 : str->append(")");
112 0 : }
113 : #endif
114 :
115 : ///////////////////////////////////////////////////////////////////////////////////////////////////
116 : ///////////////////////////////////////////////////////////////////////////////////////////////////
117 :
118 0 : static unsigned unit_to_byte(float unit) {
119 0 : SkASSERT(unit >= 0 && unit <= 1);
120 0 : return (unsigned)(unit * 255 + 0.5);
121 : }
122 :
123 0 : static SkColor unit_to_skcolor(const SkColor4f& unit, SkColorSpace* cs) {
124 0 : 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 :
128 0 : SkColor4Shader::SkColor4Shader(const SkColor4f& color, sk_sp<SkColorSpace> space)
129 0 : : fColorSpace(std::move(space))
130 : , fColor4(color)
131 0 : , fCachedByteColor(unit_to_skcolor(color.pin(), space.get()))
132 0 : {}
133 :
134 0 : sk_sp<SkFlattenable> SkColor4Shader::CreateProc(SkReadBuffer& buffer) {
135 : SkColor4f color;
136 0 : buffer.readColor4f(&color);
137 0 : if (buffer.readBool()) {
138 : // TODO how do we unflatten colorspaces
139 : }
140 0 : return SkShader::MakeColorShader(color, nullptr);
141 : }
142 :
143 0 : void SkColor4Shader::flatten(SkWriteBuffer& buffer) const {
144 0 : buffer.writeColor4f(fColor4);
145 0 : buffer.writeBool(false); // TODO how do we flatten colorspaces?
146 0 : }
147 :
148 0 : uint32_t SkColor4Shader::Color4Context::getFlags() const {
149 0 : return fFlags;
150 : }
151 :
152 0 : SkShader::Context* SkColor4Shader::onMakeContext(const ContextRec& rec, SkArenaAlloc* alloc) const {
153 0 : return alloc->make<Color4Context>(*this, rec);
154 : }
155 :
156 0 : SkColor4Shader::Color4Context::Color4Context(const SkColor4Shader& shader,
157 0 : const ContextRec& rec)
158 0 : : INHERITED(shader, rec)
159 : {
160 0 : SkColor color = shader.fCachedByteColor;
161 0 : unsigned a = SkAlphaMul(SkColorGetA(color), SkAlpha255To256(rec.fPaint->getAlpha()));
162 :
163 0 : unsigned r = SkColorGetR(color);
164 0 : unsigned g = SkColorGetG(color);
165 0 : unsigned b = SkColorGetB(color);
166 :
167 0 : if (a != 255) {
168 0 : r = SkMulDiv255Round(r, a);
169 0 : g = SkMulDiv255Round(g, a);
170 0 : b = SkMulDiv255Round(b, a);
171 : }
172 0 : fPMColor = SkPackARGB32(a, r, g, b);
173 :
174 0 : SkColor4f c4 = shader.fColor4;
175 0 : c4.fA *= rec.fPaint->getAlpha() * (1 / 255.0f);
176 0 : fPM4f = c4.premul();
177 :
178 0 : fFlags = kConstInY32_Flag;
179 0 : if (255 == a) {
180 0 : fFlags |= kOpaqueAlpha_Flag;
181 : }
182 0 : }
183 :
184 0 : void SkColor4Shader::Color4Context::shadeSpan(int x, int y, SkPMColor span[], int count) {
185 0 : sk_memset32(span, fPMColor, count);
186 0 : }
187 :
188 0 : void SkColor4Shader::Color4Context::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) {
189 0 : memset(alpha, SkGetPackedA32(fPMColor), count);
190 0 : }
191 :
192 0 : void SkColor4Shader::Color4Context::shadeSpan4f(int x, int y, SkPM4f span[], int count) {
193 0 : for (int i = 0; i < count; ++i) {
194 0 : span[i] = fPM4f;
195 : }
196 0 : }
197 :
198 : // TODO: do we need an updated version of this method for color4+colorspace?
199 0 : SkShader::GradientType SkColor4Shader::asAGradient(GradientInfo* info) const {
200 0 : if (info) {
201 0 : if (info->fColors && info->fColorCount >= 1) {
202 0 : info->fColors[0] = fCachedByteColor;
203 : }
204 0 : info->fColorCount = 1;
205 0 : info->fTileMode = SkShader::kRepeat_TileMode;
206 : }
207 0 : return kColor_GradientType;
208 : }
209 :
210 : #if SK_SUPPORT_GPU
211 :
212 : #include "SkGr.h"
213 : #include "effects/GrConstColorProcessor.h"
214 : #include "GrColorSpaceXform.h"
215 0 : sk_sp<GrFragmentProcessor> SkColor4Shader::asFragmentProcessor(const AsFPArgs& args) const {
216 0 : sk_sp<GrColorSpaceXform> colorSpaceXform = GrColorSpaceXform::Make(fColorSpace.get(),
217 0 : args.fDstColorSpace);
218 0 : GrColor4f color = GrColor4f::FromSkColor4f(fColor4);
219 0 : if (colorSpaceXform) {
220 0 : color = colorSpaceXform->apply(color);
221 : }
222 0 : return GrConstColorProcessor::Make(color.premul(), GrConstColorProcessor::kModulateA_InputMode);
223 : }
224 :
225 : #endif
226 :
227 : #ifndef SK_IGNORE_TO_STRING
228 0 : void SkColor4Shader::toString(SkString* str) const {
229 0 : str->append("SkColor4Shader: (");
230 :
231 0 : str->append("RGBA:");
232 0 : for (int i = 0; i < 4; ++i) {
233 0 : str->appendf(" %g", fColor4.vec()[i]);
234 : }
235 0 : str->append(" )");
236 0 : }
237 : #endif
238 :
239 0 : sk_sp<SkShader> SkShader::MakeColorShader(const SkColor4f& color, sk_sp<SkColorSpace> space) {
240 0 : if (!SkScalarsAreFinite(color.vec(), 4)) {
241 0 : return nullptr;
242 : }
243 0 : return sk_make_sp<SkColor4Shader>(color, std::move(space));
244 : }
245 :
246 : ///////////////////////////////////////////////////////////////////////////////////////////////////
247 : ///////////////////////////////////////////////////////////////////////////////////////////////////
248 :
249 0 : static void D32_BlitBW(SkShader::Context::BlitState* state, int x, int y, const SkPixmap& dst,
250 : int count) {
251 0 : SkXfermode::D32Proc proc = (SkXfermode::D32Proc)state->fStorage[0];
252 0 : const SkPM4f* src = (const SkPM4f*)state->fStorage[1];
253 0 : proc(state->fMode, dst.writable_addr32(x, y), src, count, nullptr);
254 0 : }
255 :
256 0 : static void D32_BlitAA(SkShader::Context::BlitState* state, int x, int y, const SkPixmap& dst,
257 : int count, const SkAlpha aa[]) {
258 0 : SkXfermode::D32Proc proc = (SkXfermode::D32Proc)state->fStorage[0];
259 0 : const SkPM4f* src = (const SkPM4f*)state->fStorage[1];
260 0 : proc(state->fMode, dst.writable_addr32(x, y), src, count, aa);
261 0 : }
262 :
263 0 : static void F16_BlitBW(SkShader::Context::BlitState* state, int x, int y, const SkPixmap& dst,
264 : int count) {
265 0 : SkXfermode::F16Proc proc = (SkXfermode::F16Proc)state->fStorage[0];
266 0 : const SkPM4f* src = (const SkPM4f*)state->fStorage[1];
267 0 : proc(state->fMode, dst.writable_addr64(x, y), src, count, nullptr);
268 0 : }
269 :
270 0 : static void F16_BlitAA(SkShader::Context::BlitState* state, int x, int y, const SkPixmap& dst,
271 : int count, const SkAlpha aa[]) {
272 0 : SkXfermode::F16Proc proc = (SkXfermode::F16Proc)state->fStorage[0];
273 0 : const SkPM4f* src = (const SkPM4f*)state->fStorage[1];
274 0 : proc(state->fMode, dst.writable_addr64(x, y), src, count, aa);
275 0 : }
276 :
277 0 : static bool choose_blitprocs(const SkPM4f* pm4, const SkImageInfo& info,
278 : SkShader::Context::BlitState* state) {
279 0 : uint32_t flags = SkXfermode::kSrcIsSingle_D32Flag;
280 0 : if (pm4->a() == 1) {
281 0 : flags |= SkXfermode::kSrcIsOpaque_D32Flag;
282 : }
283 0 : switch (info.colorType()) {
284 : case kN32_SkColorType:
285 0 : if (info.gammaCloseToSRGB()) {
286 0 : flags |= SkXfermode::kDstIsSRGB_D32Flag;
287 : }
288 0 : state->fStorage[0] = (void*)SkXfermode::GetD32Proc(state->fMode, flags);
289 0 : state->fStorage[1] = (void*)pm4;
290 0 : state->fBlitBW = D32_BlitBW;
291 0 : state->fBlitAA = D32_BlitAA;
292 0 : return true;
293 : case kRGBA_F16_SkColorType:
294 0 : state->fStorage[0] = (void*)SkXfermode::GetF16Proc(state->fMode, flags);
295 0 : state->fStorage[1] = (void*)pm4;
296 0 : state->fBlitBW = F16_BlitBW;
297 0 : state->fBlitAA = F16_BlitAA;
298 0 : return true;
299 : default:
300 0 : return false;
301 : }
302 : }
303 :
304 0 : bool SkColorShader::ColorShaderContext::onChooseBlitProcs(const SkImageInfo& info,
305 : BlitState* state) {
306 0 : return choose_blitprocs(&fPM4f, info, state);
307 : }
308 :
309 0 : bool SkColor4Shader::Color4Context::onChooseBlitProcs(const SkImageInfo& info, BlitState* state) {
310 0 : return choose_blitprocs(&fPM4f, info, state);
311 : }
312 :
313 0 : bool SkColorShader::onAppendStages(SkRasterPipeline* p,
314 : SkColorSpace* dst,
315 : SkArenaAlloc* scratch,
316 : const SkMatrix&,
317 : const SkPaint&,
318 : const SkMatrix*) const {
319 0 : auto color = scratch->make<SkPM4f>(SkPM4f_from_SkColor(fColor, dst));
320 0 : p->append(SkRasterPipeline::constant_color, color);
321 0 : return append_gamut_transform(p, scratch,
322 0 : SkColorSpace::MakeSRGB().get(), dst);
323 : }
324 :
325 0 : bool SkColor4Shader::onAppendStages(SkRasterPipeline* p,
326 : SkColorSpace* dst,
327 : SkArenaAlloc* scratch,
328 : const SkMatrix&,
329 : const SkPaint&,
330 : const SkMatrix*) const {
331 0 : auto color = scratch->make<SkPM4f>(fColor4.premul());
332 0 : p->append(SkRasterPipeline::constant_color, color);
333 0 : return append_gamut_transform(p, scratch, fColorSpace.get(), dst);
334 : }
|