1 /*
2 * Copyright 2006 The Android Open Source Project
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 "SkXfermode_proccoeff.h"
9 #include "SkColorPriv.h"
10 #include "SkMathPriv.h"
11 #include "SkOnce.h"
12 #include "SkOpts.h"
13 #include "SkRasterPipeline.h"
14 #include "SkReadBuffer.h"
15 #include "SkString.h"
16 #include "SkWriteBuffer.h"
17 #include "SkPM4f.h"
18
19 #if SK_SUPPORT_GPU
20 #include "GrFragmentProcessor.h"
21 #include "effects/GrCustomXfermode.h"
22 #include "effects/GrPorterDuffXferProcessor.h"
23 #include "effects/GrXfermodeFragmentProcessor.h"
24 #endif
25
26 #define SkAlphaMulAlpha(a, b) SkMulDiv255Round(a, b)
27
saturated_add(unsigned a,unsigned b)28 static inline unsigned saturated_add(unsigned a, unsigned b) {
29 SkASSERT(a <= 255);
30 SkASSERT(b <= 255);
31 unsigned sum = a + b;
32 if (sum > 255) {
33 sum = 255;
34 }
35 return sum;
36 }
37
clamp_signed_byte(int n)38 static inline int clamp_signed_byte(int n) {
39 if (n < 0) {
40 n = 0;
41 } else if (n > 255) {
42 n = 255;
43 }
44 return n;
45 }
46
clamp_div255round(int prod)47 static inline int clamp_div255round(int prod) {
48 if (prod <= 0) {
49 return 0;
50 } else if (prod >= 255*255) {
51 return 255;
52 } else {
53 return SkDiv255Round(prod);
54 }
55 }
56
57 ///////////////////////////////////////////////////////////////////////////////
58 #include "SkNx.h"
59
alpha(const Sk4f & color)60 static Sk4f alpha(const Sk4f& color) { return Sk4f(color[3]); }
inv_alpha(const Sk4f & color)61 static Sk4f inv_alpha(const Sk4f& color) { return Sk4f(1 - color[3]); }
pin_1(const Sk4f & value)62 static Sk4f pin_1(const Sk4f& value) { return Sk4f::Min(value, Sk4f(1)); }
63
color_alpha(const Sk4f & color,float newAlpha)64 static Sk4f color_alpha(const Sk4f& color, float newAlpha) {
65 return Sk4f(color[0], color[1], color[2], newAlpha);
66 }
color_alpha(const Sk4f & color,const Sk4f & newAlpha)67 static Sk4f color_alpha(const Sk4f& color, const Sk4f& newAlpha) {
68 return color_alpha(color, newAlpha[3]);
69 }
70
set_argb(float a,float r,float g,float b)71 static Sk4f set_argb(float a, float r, float g, float b) {
72 if (0 == SkPM4f::R) {
73 return Sk4f(r, g, b, a);
74 } else {
75 return Sk4f(b, g, r, a);
76 }
77 }
78
clear_4f(const Sk4f & s,const Sk4f & d)79 static Sk4f clear_4f(const Sk4f& s, const Sk4f& d) { return Sk4f(0); }
src_4f(const Sk4f & s,const Sk4f & d)80 static Sk4f src_4f(const Sk4f& s, const Sk4f& d) { return s; }
dst_4f(const Sk4f & s,const Sk4f & d)81 static Sk4f dst_4f(const Sk4f& s, const Sk4f& d) { return d; }
srcover_4f(const Sk4f & s,const Sk4f & d)82 static Sk4f srcover_4f(const Sk4f& s, const Sk4f& d) { return s + inv_alpha(s) * d; }
dstover_4f(const Sk4f & s,const Sk4f & d)83 static Sk4f dstover_4f(const Sk4f& s, const Sk4f& d) { return d + inv_alpha(d) * s; }
srcin_4f(const Sk4f & s,const Sk4f & d)84 static Sk4f srcin_4f(const Sk4f& s, const Sk4f& d) { return s * alpha(d); }
dstin_4f(const Sk4f & s,const Sk4f & d)85 static Sk4f dstin_4f(const Sk4f& s, const Sk4f& d) { return d * alpha(s); }
srcout_4f(const Sk4f & s,const Sk4f & d)86 static Sk4f srcout_4f(const Sk4f& s, const Sk4f& d) { return s * inv_alpha(d); }
dstout_4f(const Sk4f & s,const Sk4f & d)87 static Sk4f dstout_4f(const Sk4f& s, const Sk4f& d) { return d * inv_alpha(s); }
srcatop_4f(const Sk4f & s,const Sk4f & d)88 static Sk4f srcatop_4f(const Sk4f& s, const Sk4f& d) { return s * alpha(d) + d * inv_alpha(s); }
dstatop_4f(const Sk4f & s,const Sk4f & d)89 static Sk4f dstatop_4f(const Sk4f& s, const Sk4f& d) { return d * alpha(s) + s * inv_alpha(d); }
xor_4f(const Sk4f & s,const Sk4f & d)90 static Sk4f xor_4f(const Sk4f& s, const Sk4f& d) { return s * inv_alpha(d) + d * inv_alpha(s);}
plus_4f(const Sk4f & s,const Sk4f & d)91 static Sk4f plus_4f(const Sk4f& s, const Sk4f& d) { return pin_1(s + d); }
modulate_4f(const Sk4f & s,const Sk4f & d)92 static Sk4f modulate_4f(const Sk4f& s, const Sk4f& d) { return s * d; }
screen_4f(const Sk4f & s,const Sk4f & d)93 static Sk4f screen_4f(const Sk4f& s, const Sk4f& d) { return s + d - s * d; }
94
multiply_4f(const Sk4f & s,const Sk4f & d)95 static Sk4f multiply_4f(const Sk4f& s, const Sk4f& d) {
96 return s * inv_alpha(d) + d * inv_alpha(s) + s * d;
97 }
98
overlay_4f(const Sk4f & s,const Sk4f & d)99 static Sk4f overlay_4f(const Sk4f& s, const Sk4f& d) {
100 Sk4f sa = alpha(s);
101 Sk4f da = alpha(d);
102 Sk4f two = Sk4f(2);
103 Sk4f rc = (two * d <= da).thenElse(two * s * d,
104 sa * da - two * (da - d) * (sa - s));
105 return pin_1(s + d - s * da + color_alpha(rc - d * sa, 0));
106 }
107
hardlight_4f(const Sk4f & s,const Sk4f & d)108 static Sk4f hardlight_4f(const Sk4f& s, const Sk4f& d) {
109 return overlay_4f(d, s);
110 }
111
darken_4f(const Sk4f & s,const Sk4f & d)112 static Sk4f darken_4f(const Sk4f& s, const Sk4f& d) {
113 Sk4f sa = alpha(s);
114 Sk4f da = alpha(d);
115 return s + d - Sk4f::Max(s * da, d * sa);
116 }
117
lighten_4f(const Sk4f & s,const Sk4f & d)118 static Sk4f lighten_4f(const Sk4f& s, const Sk4f& d) {
119 Sk4f sa = alpha(s);
120 Sk4f da = alpha(d);
121 return s + d - Sk4f::Min(s * da, d * sa);
122 }
123
colordodge_4f(const Sk4f & s,const Sk4f & d)124 static Sk4f colordodge_4f(const Sk4f& s, const Sk4f& d) {
125 Sk4f sa = alpha(s);
126 Sk4f da = alpha(d);
127 Sk4f isa = Sk4f(1) - sa;
128 Sk4f ida = Sk4f(1) - da;
129
130 Sk4f srcover = s + d * isa;
131 Sk4f dstover = d + s * ida;
132 Sk4f otherwise = sa * Sk4f::Min(da, (d * sa) / (sa - s)) + s * ida + d * isa;
133
134 // Order matters here, preferring d==0 over s==sa.
135 auto colors = (d == Sk4f(0)).thenElse(dstover,
136 (s == sa).thenElse(srcover,
137 otherwise));
138 return color_alpha(colors, srcover);
139 }
140
colorburn_4f(const Sk4f & s,const Sk4f & d)141 static Sk4f colorburn_4f(const Sk4f& s, const Sk4f& d) {
142 Sk4f sa = alpha(s);
143 Sk4f da = alpha(d);
144 Sk4f isa = Sk4f(1) - sa;
145 Sk4f ida = Sk4f(1) - da;
146
147 Sk4f srcover = s + d * isa;
148 Sk4f dstover = d + s * ida;
149 Sk4f otherwise = sa * (da - Sk4f::Min(da, (da - d) * sa / s)) + s * ida + d * isa;
150
151 // Order matters here, preferring d==da over s==0.
152 auto colors = (d == da).thenElse(dstover,
153 (s == Sk4f(0)).thenElse(srcover,
154 otherwise));
155 return color_alpha(colors, srcover);
156 }
157
softlight_4f(const Sk4f & s,const Sk4f & d)158 static Sk4f softlight_4f(const Sk4f& s, const Sk4f& d) {
159 Sk4f sa = alpha(s);
160 Sk4f da = alpha(d);
161 Sk4f isa = Sk4f(1) - sa;
162 Sk4f ida = Sk4f(1) - da;
163
164 // Some common terms.
165 Sk4f m = (da > Sk4f(0)).thenElse(d / da, Sk4f(0));
166 Sk4f s2 = Sk4f(2) * s;
167 Sk4f m4 = Sk4f(4) * m;
168
169 // The logic forks three ways:
170 // 1. dark src?
171 // 2. light src, dark dst?
172 // 3. light src, light dst?
173 Sk4f darkSrc = d * (sa + (s2 - sa) * (Sk4f(1) - m)); // Used in case 1.
174 Sk4f darkDst = (m4 * m4 + m4) * (m - Sk4f(1)) + Sk4f(7) * m; // Used in case 2.
175 Sk4f liteDst = m.sqrt() - m; // Used in case 3.
176 Sk4f liteSrc = d * sa + da * (s2 - sa) * (Sk4f(4) * d <= da).thenElse(darkDst,
177 liteDst); // Case 2 or 3?
178
179 return color_alpha(s * ida + d * isa + (s2 <= sa).thenElse(darkSrc, liteSrc), // Case 1 or 2/3?
180 s + d * isa);
181 }
182
difference_4f(const Sk4f & s,const Sk4f & d)183 static Sk4f difference_4f(const Sk4f& s, const Sk4f& d) {
184 Sk4f min = Sk4f::Min(s * alpha(d), d * alpha(s));
185 return s + d - min - color_alpha(min, 0);
186 }
187
exclusion_4f(const Sk4f & s,const Sk4f & d)188 static Sk4f exclusion_4f(const Sk4f& s, const Sk4f& d) {
189 Sk4f product = s * d;
190 return s + d - product - color_alpha(product, 0);
191 }
192
193 ////////////////////////////////////////////////////
194
195 // The CSS compositing spec introduces the following formulas:
196 // (See https://dvcs.w3.org/hg/FXTF/rawfile/tip/compositing/index.html#blendingnonseparable)
197 // SkComputeLuminance is similar to this formula but it uses the new definition from Rec. 709
198 // while PDF and CG uses the one from Rec. Rec. 601
199 // See http://www.glennchan.info/articles/technical/hd-versus-sd-color-space/hd-versus-sd-color-space.htm
Lum(float r,float g,float b)200 static inline float Lum(float r, float g, float b) {
201 return r * 0.2126f + g * 0.7152f + b * 0.0722f;
202 }
203
max(float a,float b,float c)204 static inline float max(float a, float b, float c) {
205 return SkTMax(a, SkTMax(b, c));
206 }
207
min(float a,float b,float c)208 static inline float min(float a, float b, float c) {
209 return SkTMin(a, SkTMin(b, c));
210 }
211
Sat(float r,float g,float b)212 static inline float Sat(float r, float g, float b) {
213 return max(r, g, b) - min(r, g, b);
214 }
215
setSaturationComponents(float * Cmin,float * Cmid,float * Cmax,float s)216 static inline void setSaturationComponents(float* Cmin, float* Cmid, float* Cmax, float s) {
217 if(*Cmax > *Cmin) {
218 *Cmid = (*Cmid - *Cmin) * s / (*Cmax - *Cmin);
219 *Cmax = s;
220 } else {
221 *Cmax = 0;
222 *Cmid = 0;
223 }
224 *Cmin = 0;
225 }
226
SetSat(float * r,float * g,float * b,float s)227 static inline void SetSat(float* r, float* g, float* b, float s) {
228 if(*r <= *g) {
229 if(*g <= *b) {
230 setSaturationComponents(r, g, b, s);
231 } else if(*r <= *b) {
232 setSaturationComponents(r, b, g, s);
233 } else {
234 setSaturationComponents(b, r, g, s);
235 }
236 } else if(*r <= *b) {
237 setSaturationComponents(g, r, b, s);
238 } else if(*g <= *b) {
239 setSaturationComponents(g, b, r, s);
240 } else {
241 setSaturationComponents(b, g, r, s);
242 }
243 }
244
clipColor(float * r,float * g,float * b,float a)245 static inline void clipColor(float* r, float* g, float* b, float a) {
246 float L = Lum(*r, *g, *b);
247 float n = min(*r, *g, *b);
248 float x = max(*r, *g, *b);
249 float denom;
250 if ((n < 0) && (denom = L - n)) { // Compute denom and make sure it's non zero
251 float scale = L / denom;
252 *r = L + (*r - L) * scale;
253 *g = L + (*g - L) * scale;
254 *b = L + (*b - L) * scale;
255 }
256
257 if ((x > a) && (denom = x - L)) { // Compute denom and make sure it's non zero
258 float scale = (a - L) / denom;
259 *r = L + (*r - L) * scale;
260 *g = L + (*g - L) * scale;
261 *b = L + (*b - L) * scale;
262 }
263 }
264
SetLum(float * r,float * g,float * b,float a,float l)265 static inline void SetLum(float* r, float* g, float* b, float a, float l) {
266 float d = l - Lum(*r, *g, *b);
267 *r += d;
268 *g += d;
269 *b += d;
270 clipColor(r, g, b, a);
271 }
272
hue_4f(const Sk4f & s,const Sk4f & d)273 static Sk4f hue_4f(const Sk4f& s, const Sk4f& d) {
274 float sa = s[SkPM4f::A];
275 float sr = s[SkPM4f::R];
276 float sg = s[SkPM4f::G];
277 float sb = s[SkPM4f::B];
278
279 float da = d[SkPM4f::A];
280 float dr = d[SkPM4f::R];
281 float dg = d[SkPM4f::G];
282 float db = d[SkPM4f::B];
283
284 float Sr = sr;
285 float Sg = sg;
286 float Sb = sb;
287 SetSat(&Sr, &Sg, &Sb, Sat(dr, dg, db) * sa);
288 SetLum(&Sr, &Sg, &Sb, sa * da, Lum(dr, dg, db) * sa);
289
290 return color_alpha(s * inv_alpha(d) + d * inv_alpha(s) + set_argb(0, Sr, Sg, Sb),
291 sa + da - sa * da);
292 }
293
saturation_4f(const Sk4f & s,const Sk4f & d)294 static Sk4f saturation_4f(const Sk4f& s, const Sk4f& d) {
295 float sa = s[SkPM4f::A];
296 float sr = s[SkPM4f::R];
297 float sg = s[SkPM4f::G];
298 float sb = s[SkPM4f::B];
299
300 float da = d[SkPM4f::A];
301 float dr = d[SkPM4f::R];
302 float dg = d[SkPM4f::G];
303 float db = d[SkPM4f::B];
304
305 float Dr = dr;
306 float Dg = dg;
307 float Db = db;
308 SetSat(&Dr, &Dg, &Db, Sat(sr, sg, sb) * da);
309 SetLum(&Dr, &Dg, &Db, sa * da, Lum(dr, dg, db) * sa);
310
311 return color_alpha(s * inv_alpha(d) + d * inv_alpha(s) + set_argb(0, Dr, Dg, Db),
312 sa + da - sa * da);
313 }
314
color_4f(const Sk4f & s,const Sk4f & d)315 static Sk4f color_4f(const Sk4f& s, const Sk4f& d) {
316 float sa = s[SkPM4f::A];
317 float sr = s[SkPM4f::R];
318 float sg = s[SkPM4f::G];
319 float sb = s[SkPM4f::B];
320
321 float da = d[SkPM4f::A];
322 float dr = d[SkPM4f::R];
323 float dg = d[SkPM4f::G];
324 float db = d[SkPM4f::B];
325
326 float Sr = sr;
327 float Sg = sg;
328 float Sb = sb;
329 SetLum(&Sr, &Sg, &Sb, sa * da, Lum(dr, dg, db) * sa);
330
331 Sk4f res = color_alpha(s * inv_alpha(d) + d * inv_alpha(s) + set_argb(0, Sr, Sg, Sb),
332 sa + da - sa * da);
333 // Can return tiny negative values ...
334 return Sk4f::Max(res, Sk4f(0));
335 }
336
luminosity_4f(const Sk4f & s,const Sk4f & d)337 static Sk4f luminosity_4f(const Sk4f& s, const Sk4f& d) {
338 float sa = s[SkPM4f::A];
339 float sr = s[SkPM4f::R];
340 float sg = s[SkPM4f::G];
341 float sb = s[SkPM4f::B];
342
343 float da = d[SkPM4f::A];
344 float dr = d[SkPM4f::R];
345 float dg = d[SkPM4f::G];
346 float db = d[SkPM4f::B];
347
348 float Dr = dr;
349 float Dg = dg;
350 float Db = db;
351 SetLum(&Dr, &Dg, &Db, sa * da, Lum(sr, sg, sb) * da);
352
353 Sk4f res = color_alpha(s * inv_alpha(d) + d * inv_alpha(s) + set_argb(0, Dr, Dg, Db),
354 sa + da - sa * da);
355 // Can return tiny negative values ...
356 return Sk4f::Max(res, Sk4f(0));
357 }
358
359 ///////////////////////////////////////////////////////////////////////////////
360
361 // kClear_Mode, //!< [0, 0]
clear_modeproc(SkPMColor src,SkPMColor dst)362 static SkPMColor clear_modeproc(SkPMColor src, SkPMColor dst) {
363 return 0;
364 }
365
366 // kSrc_Mode, //!< [Sa, Sc]
src_modeproc(SkPMColor src,SkPMColor dst)367 static SkPMColor src_modeproc(SkPMColor src, SkPMColor dst) {
368 return src;
369 }
370
371 // kDst_Mode, //!< [Da, Dc]
dst_modeproc(SkPMColor src,SkPMColor dst)372 static SkPMColor dst_modeproc(SkPMColor src, SkPMColor dst) {
373 return dst;
374 }
375
376 // kSrcOver_Mode, //!< [Sa + Da - Sa*Da, Sc + (1 - Sa)*Dc]
srcover_modeproc(SkPMColor src,SkPMColor dst)377 static SkPMColor srcover_modeproc(SkPMColor src, SkPMColor dst) {
378 #if 0
379 // this is the old, more-correct way, but it doesn't guarantee that dst==255
380 // will always stay opaque
381 return src + SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src)));
382 #else
383 // this is slightly faster, but more importantly guarantees that dst==255
384 // will always stay opaque
385 return src + SkAlphaMulQ(dst, 256 - SkGetPackedA32(src));
386 #endif
387 }
388
389 // kDstOver_Mode, //!< [Sa + Da - Sa*Da, Dc + (1 - Da)*Sc]
dstover_modeproc(SkPMColor src,SkPMColor dst)390 static SkPMColor dstover_modeproc(SkPMColor src, SkPMColor dst) {
391 // this is the reverse of srcover, just flipping src and dst
392 // see srcover's comment about the 256 for opaqueness guarantees
393 return dst + SkAlphaMulQ(src, 256 - SkGetPackedA32(dst));
394 }
395
396 // kSrcIn_Mode, //!< [Sa * Da, Sc * Da]
srcin_modeproc(SkPMColor src,SkPMColor dst)397 static SkPMColor srcin_modeproc(SkPMColor src, SkPMColor dst) {
398 return SkAlphaMulQ(src, SkAlpha255To256(SkGetPackedA32(dst)));
399 }
400
401 // kDstIn_Mode, //!< [Sa * Da, Sa * Dc]
dstin_modeproc(SkPMColor src,SkPMColor dst)402 static SkPMColor dstin_modeproc(SkPMColor src, SkPMColor dst) {
403 return SkAlphaMulQ(dst, SkAlpha255To256(SkGetPackedA32(src)));
404 }
405
406 // kSrcOut_Mode, //!< [Sa * (1 - Da), Sc * (1 - Da)]
srcout_modeproc(SkPMColor src,SkPMColor dst)407 static SkPMColor srcout_modeproc(SkPMColor src, SkPMColor dst) {
408 return SkAlphaMulQ(src, SkAlpha255To256(255 - SkGetPackedA32(dst)));
409 }
410
411 // kDstOut_Mode, //!< [Da * (1 - Sa), Dc * (1 - Sa)]
dstout_modeproc(SkPMColor src,SkPMColor dst)412 static SkPMColor dstout_modeproc(SkPMColor src, SkPMColor dst) {
413 return SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src)));
414 }
415
416 // kSrcATop_Mode, //!< [Da, Sc * Da + (1 - Sa) * Dc]
srcatop_modeproc(SkPMColor src,SkPMColor dst)417 static SkPMColor srcatop_modeproc(SkPMColor src, SkPMColor dst) {
418 unsigned sa = SkGetPackedA32(src);
419 unsigned da = SkGetPackedA32(dst);
420 unsigned isa = 255 - sa;
421
422 return SkPackARGB32(da,
423 SkAlphaMulAlpha(da, SkGetPackedR32(src)) +
424 SkAlphaMulAlpha(isa, SkGetPackedR32(dst)),
425 SkAlphaMulAlpha(da, SkGetPackedG32(src)) +
426 SkAlphaMulAlpha(isa, SkGetPackedG32(dst)),
427 SkAlphaMulAlpha(da, SkGetPackedB32(src)) +
428 SkAlphaMulAlpha(isa, SkGetPackedB32(dst)));
429 }
430
431 // kDstATop_Mode, //!< [Sa, Sa * Dc + Sc * (1 - Da)]
dstatop_modeproc(SkPMColor src,SkPMColor dst)432 static SkPMColor dstatop_modeproc(SkPMColor src, SkPMColor dst) {
433 unsigned sa = SkGetPackedA32(src);
434 unsigned da = SkGetPackedA32(dst);
435 unsigned ida = 255 - da;
436
437 return SkPackARGB32(sa,
438 SkAlphaMulAlpha(ida, SkGetPackedR32(src)) +
439 SkAlphaMulAlpha(sa, SkGetPackedR32(dst)),
440 SkAlphaMulAlpha(ida, SkGetPackedG32(src)) +
441 SkAlphaMulAlpha(sa, SkGetPackedG32(dst)),
442 SkAlphaMulAlpha(ida, SkGetPackedB32(src)) +
443 SkAlphaMulAlpha(sa, SkGetPackedB32(dst)));
444 }
445
446 // kXor_Mode [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc]
xor_modeproc(SkPMColor src,SkPMColor dst)447 static SkPMColor xor_modeproc(SkPMColor src, SkPMColor dst) {
448 unsigned sa = SkGetPackedA32(src);
449 unsigned da = SkGetPackedA32(dst);
450 unsigned isa = 255 - sa;
451 unsigned ida = 255 - da;
452
453 return SkPackARGB32(sa + da - (SkAlphaMulAlpha(sa, da) << 1),
454 SkAlphaMulAlpha(ida, SkGetPackedR32(src)) +
455 SkAlphaMulAlpha(isa, SkGetPackedR32(dst)),
456 SkAlphaMulAlpha(ida, SkGetPackedG32(src)) +
457 SkAlphaMulAlpha(isa, SkGetPackedG32(dst)),
458 SkAlphaMulAlpha(ida, SkGetPackedB32(src)) +
459 SkAlphaMulAlpha(isa, SkGetPackedB32(dst)));
460 }
461
462 ///////////////////////////////////////////////////////////////////////////////
463
464 // kPlus_Mode
plus_modeproc(SkPMColor src,SkPMColor dst)465 static SkPMColor plus_modeproc(SkPMColor src, SkPMColor dst) {
466 unsigned b = saturated_add(SkGetPackedB32(src), SkGetPackedB32(dst));
467 unsigned g = saturated_add(SkGetPackedG32(src), SkGetPackedG32(dst));
468 unsigned r = saturated_add(SkGetPackedR32(src), SkGetPackedR32(dst));
469 unsigned a = saturated_add(SkGetPackedA32(src), SkGetPackedA32(dst));
470 return SkPackARGB32(a, r, g, b);
471 }
472
473 // kModulate_Mode
modulate_modeproc(SkPMColor src,SkPMColor dst)474 static SkPMColor modulate_modeproc(SkPMColor src, SkPMColor dst) {
475 int a = SkAlphaMulAlpha(SkGetPackedA32(src), SkGetPackedA32(dst));
476 int r = SkAlphaMulAlpha(SkGetPackedR32(src), SkGetPackedR32(dst));
477 int g = SkAlphaMulAlpha(SkGetPackedG32(src), SkGetPackedG32(dst));
478 int b = SkAlphaMulAlpha(SkGetPackedB32(src), SkGetPackedB32(dst));
479 return SkPackARGB32(a, r, g, b);
480 }
481
srcover_byte(int a,int b)482 static inline int srcover_byte(int a, int b) {
483 return a + b - SkAlphaMulAlpha(a, b);
484 }
485
486 // kMultiply_Mode
487 // B(Cb, Cs) = Cb x Cs
488 // multiply uses its own version of blendfunc_byte because sa and da are not needed
blendfunc_multiply_byte(int sc,int dc,int sa,int da)489 static int blendfunc_multiply_byte(int sc, int dc, int sa, int da) {
490 return clamp_div255round(sc * (255 - da) + dc * (255 - sa) + sc * dc);
491 }
492
multiply_modeproc(SkPMColor src,SkPMColor dst)493 static SkPMColor multiply_modeproc(SkPMColor src, SkPMColor dst) {
494 int sa = SkGetPackedA32(src);
495 int da = SkGetPackedA32(dst);
496 int a = srcover_byte(sa, da);
497 int r = blendfunc_multiply_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
498 int g = blendfunc_multiply_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
499 int b = blendfunc_multiply_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
500 return SkPackARGB32(a, r, g, b);
501 }
502
503 // kScreen_Mode
screen_modeproc(SkPMColor src,SkPMColor dst)504 static SkPMColor screen_modeproc(SkPMColor src, SkPMColor dst) {
505 int a = srcover_byte(SkGetPackedA32(src), SkGetPackedA32(dst));
506 int r = srcover_byte(SkGetPackedR32(src), SkGetPackedR32(dst));
507 int g = srcover_byte(SkGetPackedG32(src), SkGetPackedG32(dst));
508 int b = srcover_byte(SkGetPackedB32(src), SkGetPackedB32(dst));
509 return SkPackARGB32(a, r, g, b);
510 }
511
512 // kOverlay_Mode
overlay_byte(int sc,int dc,int sa,int da)513 static inline int overlay_byte(int sc, int dc, int sa, int da) {
514 int tmp = sc * (255 - da) + dc * (255 - sa);
515 int rc;
516 if (2 * dc <= da) {
517 rc = 2 * sc * dc;
518 } else {
519 rc = sa * da - 2 * (da - dc) * (sa - sc);
520 }
521 return clamp_div255round(rc + tmp);
522 }
overlay_modeproc(SkPMColor src,SkPMColor dst)523 static SkPMColor overlay_modeproc(SkPMColor src, SkPMColor dst) {
524 int sa = SkGetPackedA32(src);
525 int da = SkGetPackedA32(dst);
526 int a = srcover_byte(sa, da);
527 int r = overlay_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
528 int g = overlay_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
529 int b = overlay_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
530 return SkPackARGB32(a, r, g, b);
531 }
532
533 // kDarken_Mode
darken_byte(int sc,int dc,int sa,int da)534 static inline int darken_byte(int sc, int dc, int sa, int da) {
535 int sd = sc * da;
536 int ds = dc * sa;
537 if (sd < ds) {
538 // srcover
539 return sc + dc - SkDiv255Round(ds);
540 } else {
541 // dstover
542 return dc + sc - SkDiv255Round(sd);
543 }
544 }
darken_modeproc(SkPMColor src,SkPMColor dst)545 static SkPMColor darken_modeproc(SkPMColor src, SkPMColor dst) {
546 int sa = SkGetPackedA32(src);
547 int da = SkGetPackedA32(dst);
548 int a = srcover_byte(sa, da);
549 int r = darken_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
550 int g = darken_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
551 int b = darken_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
552 return SkPackARGB32(a, r, g, b);
553 }
554
555 // kLighten_Mode
lighten_byte(int sc,int dc,int sa,int da)556 static inline int lighten_byte(int sc, int dc, int sa, int da) {
557 int sd = sc * da;
558 int ds = dc * sa;
559 if (sd > ds) {
560 // srcover
561 return sc + dc - SkDiv255Round(ds);
562 } else {
563 // dstover
564 return dc + sc - SkDiv255Round(sd);
565 }
566 }
lighten_modeproc(SkPMColor src,SkPMColor dst)567 static SkPMColor lighten_modeproc(SkPMColor src, SkPMColor dst) {
568 int sa = SkGetPackedA32(src);
569 int da = SkGetPackedA32(dst);
570 int a = srcover_byte(sa, da);
571 int r = lighten_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
572 int g = lighten_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
573 int b = lighten_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
574 return SkPackARGB32(a, r, g, b);
575 }
576
577 // kColorDodge_Mode
colordodge_byte(int sc,int dc,int sa,int da)578 static inline int colordodge_byte(int sc, int dc, int sa, int da) {
579 int diff = sa - sc;
580 int rc;
581 if (0 == dc) {
582 return SkAlphaMulAlpha(sc, 255 - da);
583 } else if (0 == diff) {
584 rc = sa * da + sc * (255 - da) + dc * (255 - sa);
585 } else {
586 diff = dc * sa / diff;
587 rc = sa * ((da < diff) ? da : diff) + sc * (255 - da) + dc * (255 - sa);
588 }
589 return clamp_div255round(rc);
590 }
colordodge_modeproc(SkPMColor src,SkPMColor dst)591 static SkPMColor colordodge_modeproc(SkPMColor src, SkPMColor dst) {
592 int sa = SkGetPackedA32(src);
593 int da = SkGetPackedA32(dst);
594 int a = srcover_byte(sa, da);
595 int r = colordodge_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
596 int g = colordodge_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
597 int b = colordodge_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
598 return SkPackARGB32(a, r, g, b);
599 }
600
601 // kColorBurn_Mode
colorburn_byte(int sc,int dc,int sa,int da)602 static inline int colorburn_byte(int sc, int dc, int sa, int da) {
603 int rc;
604 if (dc == da) {
605 rc = sa * da + sc * (255 - da) + dc * (255 - sa);
606 } else if (0 == sc) {
607 return SkAlphaMulAlpha(dc, 255 - sa);
608 } else {
609 int tmp = (da - dc) * sa / sc;
610 rc = sa * (da - ((da < tmp) ? da : tmp))
611 + sc * (255 - da) + dc * (255 - sa);
612 }
613 return clamp_div255round(rc);
614 }
colorburn_modeproc(SkPMColor src,SkPMColor dst)615 static SkPMColor colorburn_modeproc(SkPMColor src, SkPMColor dst) {
616 int sa = SkGetPackedA32(src);
617 int da = SkGetPackedA32(dst);
618 int a = srcover_byte(sa, da);
619 int r = colorburn_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
620 int g = colorburn_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
621 int b = colorburn_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
622 return SkPackARGB32(a, r, g, b);
623 }
624
625 // kHardLight_Mode
hardlight_byte(int sc,int dc,int sa,int da)626 static inline int hardlight_byte(int sc, int dc, int sa, int da) {
627 int rc;
628 if (2 * sc <= sa) {
629 rc = 2 * sc * dc;
630 } else {
631 rc = sa * da - 2 * (da - dc) * (sa - sc);
632 }
633 return clamp_div255round(rc + sc * (255 - da) + dc * (255 - sa));
634 }
hardlight_modeproc(SkPMColor src,SkPMColor dst)635 static SkPMColor hardlight_modeproc(SkPMColor src, SkPMColor dst) {
636 int sa = SkGetPackedA32(src);
637 int da = SkGetPackedA32(dst);
638 int a = srcover_byte(sa, da);
639 int r = hardlight_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
640 int g = hardlight_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
641 int b = hardlight_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
642 return SkPackARGB32(a, r, g, b);
643 }
644
645 // returns 255 * sqrt(n/255)
sqrt_unit_byte(U8CPU n)646 static U8CPU sqrt_unit_byte(U8CPU n) {
647 return SkSqrtBits(n, 15+4);
648 }
649
650 // kSoftLight_Mode
softlight_byte(int sc,int dc,int sa,int da)651 static inline int softlight_byte(int sc, int dc, int sa, int da) {
652 int m = da ? dc * 256 / da : 0;
653 int rc;
654 if (2 * sc <= sa) {
655 rc = dc * (sa + ((2 * sc - sa) * (256 - m) >> 8));
656 } else if (4 * dc <= da) {
657 int tmp = (4 * m * (4 * m + 256) * (m - 256) >> 16) + 7 * m;
658 rc = dc * sa + (da * (2 * sc - sa) * tmp >> 8);
659 } else {
660 int tmp = sqrt_unit_byte(m) - m;
661 rc = dc * sa + (da * (2 * sc - sa) * tmp >> 8);
662 }
663 return clamp_div255round(rc + sc * (255 - da) + dc * (255 - sa));
664 }
softlight_modeproc(SkPMColor src,SkPMColor dst)665 static SkPMColor softlight_modeproc(SkPMColor src, SkPMColor dst) {
666 int sa = SkGetPackedA32(src);
667 int da = SkGetPackedA32(dst);
668 int a = srcover_byte(sa, da);
669 int r = softlight_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
670 int g = softlight_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
671 int b = softlight_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
672 return SkPackARGB32(a, r, g, b);
673 }
674
675 // kDifference_Mode
difference_byte(int sc,int dc,int sa,int da)676 static inline int difference_byte(int sc, int dc, int sa, int da) {
677 int tmp = SkMin32(sc * da, dc * sa);
678 return clamp_signed_byte(sc + dc - 2 * SkDiv255Round(tmp));
679 }
difference_modeproc(SkPMColor src,SkPMColor dst)680 static SkPMColor difference_modeproc(SkPMColor src, SkPMColor dst) {
681 int sa = SkGetPackedA32(src);
682 int da = SkGetPackedA32(dst);
683 int a = srcover_byte(sa, da);
684 int r = difference_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
685 int g = difference_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
686 int b = difference_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
687 return SkPackARGB32(a, r, g, b);
688 }
689
690 // kExclusion_Mode
exclusion_byte(int sc,int dc,int,int)691 static inline int exclusion_byte(int sc, int dc, int, int) {
692 // this equations is wacky, wait for SVG to confirm it
693 //int r = sc * da + dc * sa - 2 * sc * dc + sc * (255 - da) + dc * (255 - sa);
694
695 // The above equation can be simplified as follows
696 int r = 255*(sc + dc) - 2 * sc * dc;
697 return clamp_div255round(r);
698 }
exclusion_modeproc(SkPMColor src,SkPMColor dst)699 static SkPMColor exclusion_modeproc(SkPMColor src, SkPMColor dst) {
700 int sa = SkGetPackedA32(src);
701 int da = SkGetPackedA32(dst);
702 int a = srcover_byte(sa, da);
703 int r = exclusion_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
704 int g = exclusion_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
705 int b = exclusion_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
706 return SkPackARGB32(a, r, g, b);
707 }
708
709 // The CSS compositing spec introduces the following formulas:
710 // (See https://dvcs.w3.org/hg/FXTF/rawfile/tip/compositing/index.html#blendingnonseparable)
711 // SkComputeLuminance is similar to this formula but it uses the new definition from Rec. 709
712 // while PDF and CG uses the one from Rec. Rec. 601
713 // See http://www.glennchan.info/articles/technical/hd-versus-sd-color-space/hd-versus-sd-color-space.htm
Lum(int r,int g,int b)714 static inline int Lum(int r, int g, int b)
715 {
716 return SkDiv255Round(r * 77 + g * 150 + b * 28);
717 }
718
min2(int a,int b)719 static inline int min2(int a, int b) { return a < b ? a : b; }
max2(int a,int b)720 static inline int max2(int a, int b) { return a > b ? a : b; }
721 #define minimum(a, b, c) min2(min2(a, b), c)
722 #define maximum(a, b, c) max2(max2(a, b), c)
723
Sat(int r,int g,int b)724 static inline int Sat(int r, int g, int b) {
725 return maximum(r, g, b) - minimum(r, g, b);
726 }
727
setSaturationComponents(int * Cmin,int * Cmid,int * Cmax,int s)728 static inline void setSaturationComponents(int* Cmin, int* Cmid, int* Cmax, int s) {
729 if(*Cmax > *Cmin) {
730 *Cmid = SkMulDiv(*Cmid - *Cmin, s, *Cmax - *Cmin);
731 *Cmax = s;
732 } else {
733 *Cmax = 0;
734 *Cmid = 0;
735 }
736
737 *Cmin = 0;
738 }
739
SetSat(int * r,int * g,int * b,int s)740 static inline void SetSat(int* r, int* g, int* b, int s) {
741 if(*r <= *g) {
742 if(*g <= *b) {
743 setSaturationComponents(r, g, b, s);
744 } else if(*r <= *b) {
745 setSaturationComponents(r, b, g, s);
746 } else {
747 setSaturationComponents(b, r, g, s);
748 }
749 } else if(*r <= *b) {
750 setSaturationComponents(g, r, b, s);
751 } else if(*g <= *b) {
752 setSaturationComponents(g, b, r, s);
753 } else {
754 setSaturationComponents(b, g, r, s);
755 }
756 }
757
clipColor(int * r,int * g,int * b,int a)758 static inline void clipColor(int* r, int* g, int* b, int a) {
759 int L = Lum(*r, *g, *b);
760 int n = minimum(*r, *g, *b);
761 int x = maximum(*r, *g, *b);
762 int denom;
763 if ((n < 0) && (denom = L - n)) { // Compute denom and make sure it's non zero
764 *r = L + SkMulDiv(*r - L, L, denom);
765 *g = L + SkMulDiv(*g - L, L, denom);
766 *b = L + SkMulDiv(*b - L, L, denom);
767 }
768
769 if ((x > a) && (denom = x - L)) { // Compute denom and make sure it's non zero
770 int numer = a - L;
771 *r = L + SkMulDiv(*r - L, numer, denom);
772 *g = L + SkMulDiv(*g - L, numer, denom);
773 *b = L + SkMulDiv(*b - L, numer, denom);
774 }
775 }
776
SetLum(int * r,int * g,int * b,int a,int l)777 static inline void SetLum(int* r, int* g, int* b, int a, int l) {
778 int d = l - Lum(*r, *g, *b);
779 *r += d;
780 *g += d;
781 *b += d;
782
783 clipColor(r, g, b, a);
784 }
785
786 // non-separable blend modes are done in non-premultiplied alpha
787 #define blendfunc_nonsep_byte(sc, dc, sa, da, blendval) \
788 clamp_div255round(sc * (255 - da) + dc * (255 - sa) + blendval)
789
790 // kHue_Mode
791 // B(Cb, Cs) = SetLum(SetSat(Cs, Sat(Cb)), Lum(Cb))
792 // Create a color with the hue of the source color and the saturation and luminosity of the backdrop color.
hue_modeproc(SkPMColor src,SkPMColor dst)793 static SkPMColor hue_modeproc(SkPMColor src, SkPMColor dst) {
794 int sr = SkGetPackedR32(src);
795 int sg = SkGetPackedG32(src);
796 int sb = SkGetPackedB32(src);
797 int sa = SkGetPackedA32(src);
798
799 int dr = SkGetPackedR32(dst);
800 int dg = SkGetPackedG32(dst);
801 int db = SkGetPackedB32(dst);
802 int da = SkGetPackedA32(dst);
803 int Sr, Sg, Sb;
804
805 if(sa && da) {
806 Sr = sr * sa;
807 Sg = sg * sa;
808 Sb = sb * sa;
809 SetSat(&Sr, &Sg, &Sb, Sat(dr, dg, db) * sa);
810 SetLum(&Sr, &Sg, &Sb, sa * da, Lum(dr, dg, db) * sa);
811 } else {
812 Sr = 0;
813 Sg = 0;
814 Sb = 0;
815 }
816
817 int a = srcover_byte(sa, da);
818 int r = blendfunc_nonsep_byte(sr, dr, sa, da, Sr);
819 int g = blendfunc_nonsep_byte(sg, dg, sa, da, Sg);
820 int b = blendfunc_nonsep_byte(sb, db, sa, da, Sb);
821 return SkPackARGB32(a, r, g, b);
822 }
823
824 // kSaturation_Mode
825 // B(Cb, Cs) = SetLum(SetSat(Cb, Sat(Cs)), Lum(Cb))
826 // Create a color with the saturation of the source color and the hue and luminosity of the backdrop color.
saturation_modeproc(SkPMColor src,SkPMColor dst)827 static SkPMColor saturation_modeproc(SkPMColor src, SkPMColor dst) {
828 int sr = SkGetPackedR32(src);
829 int sg = SkGetPackedG32(src);
830 int sb = SkGetPackedB32(src);
831 int sa = SkGetPackedA32(src);
832
833 int dr = SkGetPackedR32(dst);
834 int dg = SkGetPackedG32(dst);
835 int db = SkGetPackedB32(dst);
836 int da = SkGetPackedA32(dst);
837 int Dr, Dg, Db;
838
839 if(sa && da) {
840 Dr = dr * sa;
841 Dg = dg * sa;
842 Db = db * sa;
843 SetSat(&Dr, &Dg, &Db, Sat(sr, sg, sb) * da);
844 SetLum(&Dr, &Dg, &Db, sa * da, Lum(dr, dg, db) * sa);
845 } else {
846 Dr = 0;
847 Dg = 0;
848 Db = 0;
849 }
850
851 int a = srcover_byte(sa, da);
852 int r = blendfunc_nonsep_byte(sr, dr, sa, da, Dr);
853 int g = blendfunc_nonsep_byte(sg, dg, sa, da, Dg);
854 int b = blendfunc_nonsep_byte(sb, db, sa, da, Db);
855 return SkPackARGB32(a, r, g, b);
856 }
857
858 // kColor_Mode
859 // B(Cb, Cs) = SetLum(Cs, Lum(Cb))
860 // Create a color with the hue and saturation of the source color and the luminosity of the backdrop color.
color_modeproc(SkPMColor src,SkPMColor dst)861 static SkPMColor color_modeproc(SkPMColor src, SkPMColor dst) {
862 int sr = SkGetPackedR32(src);
863 int sg = SkGetPackedG32(src);
864 int sb = SkGetPackedB32(src);
865 int sa = SkGetPackedA32(src);
866
867 int dr = SkGetPackedR32(dst);
868 int dg = SkGetPackedG32(dst);
869 int db = SkGetPackedB32(dst);
870 int da = SkGetPackedA32(dst);
871 int Sr, Sg, Sb;
872
873 if(sa && da) {
874 Sr = sr * da;
875 Sg = sg * da;
876 Sb = sb * da;
877 SetLum(&Sr, &Sg, &Sb, sa * da, Lum(dr, dg, db) * sa);
878 } else {
879 Sr = 0;
880 Sg = 0;
881 Sb = 0;
882 }
883
884 int a = srcover_byte(sa, da);
885 int r = blendfunc_nonsep_byte(sr, dr, sa, da, Sr);
886 int g = blendfunc_nonsep_byte(sg, dg, sa, da, Sg);
887 int b = blendfunc_nonsep_byte(sb, db, sa, da, Sb);
888 return SkPackARGB32(a, r, g, b);
889 }
890
891 // kLuminosity_Mode
892 // B(Cb, Cs) = SetLum(Cb, Lum(Cs))
893 // Create a color with the luminosity of the source color and the hue and saturation of the backdrop color.
luminosity_modeproc(SkPMColor src,SkPMColor dst)894 static SkPMColor luminosity_modeproc(SkPMColor src, SkPMColor dst) {
895 int sr = SkGetPackedR32(src);
896 int sg = SkGetPackedG32(src);
897 int sb = SkGetPackedB32(src);
898 int sa = SkGetPackedA32(src);
899
900 int dr = SkGetPackedR32(dst);
901 int dg = SkGetPackedG32(dst);
902 int db = SkGetPackedB32(dst);
903 int da = SkGetPackedA32(dst);
904 int Dr, Dg, Db;
905
906 if(sa && da) {
907 Dr = dr * sa;
908 Dg = dg * sa;
909 Db = db * sa;
910 SetLum(&Dr, &Dg, &Db, sa * da, Lum(sr, sg, sb) * da);
911 } else {
912 Dr = 0;
913 Dg = 0;
914 Db = 0;
915 }
916
917 int a = srcover_byte(sa, da);
918 int r = blendfunc_nonsep_byte(sr, dr, sa, da, Dr);
919 int g = blendfunc_nonsep_byte(sg, dg, sa, da, Dg);
920 int b = blendfunc_nonsep_byte(sb, db, sa, da, Db);
921 return SkPackARGB32(a, r, g, b);
922 }
923
924 ///////////////////////////////////////////////////////////////////////////////////////////////////
925
as_pm4f(const Sk4f & x)926 static SkPM4f as_pm4f(const Sk4f& x) {
927 SkPM4f pm4;
928 x.store(pm4.fVec);
929 return pm4;
930 }
931
as_4f(const SkPM4f & pm4)932 static Sk4f as_4f(const SkPM4f& pm4) {
933 return Sk4f::Load(pm4.fVec);
934 }
935
assert_unit(const SkPM4f & r)936 static void assert_unit(const SkPM4f& r) {
937 #ifdef SK_DEBUG
938 const float eps = 0.00001f;
939 const float min = 0 - eps;
940 const float max = 1 + eps;
941 for (int i = 0; i < 4; ++i) {
942 SkASSERT(r.fVec[i] >= min && r.fVec[i] <= max);
943 }
944 #endif
945 }
946
proc_4f(const SkPM4f & s,const SkPM4f & d)947 template <Sk4f (blend)(const Sk4f&, const Sk4f&)> SkPM4f proc_4f(const SkPM4f& s, const SkPM4f& d) {
948 assert_unit(s);
949 assert_unit(d);
950 SkPM4f r = as_pm4f(blend(as_4f(s), as_4f(d)));
951 // Turn this assert off for now because srgb conversions may end up in rgb > a
952 // assert_unit(r);
953 return r;
954 }
955
956 const ProcCoeff gProcCoeffs[] = {
957 { clear_modeproc, proc_4f<clear_4f>, SkXfermode::kZero_Coeff, SkXfermode::kZero_Coeff },
958 { src_modeproc, proc_4f<src_4f>, SkXfermode::kOne_Coeff, SkXfermode::kZero_Coeff },
959 { dst_modeproc, proc_4f<dst_4f>, SkXfermode::kZero_Coeff, SkXfermode::kOne_Coeff },
960 { srcover_modeproc, proc_4f<srcover_4f>, SkXfermode::kOne_Coeff, SkXfermode::kISA_Coeff },
961 { dstover_modeproc, proc_4f<dstover_4f>, SkXfermode::kIDA_Coeff, SkXfermode::kOne_Coeff },
962 { srcin_modeproc, proc_4f<srcin_4f>, SkXfermode::kDA_Coeff, SkXfermode::kZero_Coeff },
963 { dstin_modeproc, proc_4f<dstin_4f>, SkXfermode::kZero_Coeff, SkXfermode::kSA_Coeff },
964 { srcout_modeproc, proc_4f<srcout_4f>, SkXfermode::kIDA_Coeff, SkXfermode::kZero_Coeff },
965 { dstout_modeproc, proc_4f<dstout_4f>, SkXfermode::kZero_Coeff, SkXfermode::kISA_Coeff },
966 { srcatop_modeproc, proc_4f<srcatop_4f>, SkXfermode::kDA_Coeff, SkXfermode::kISA_Coeff },
967 { dstatop_modeproc, proc_4f<dstatop_4f>, SkXfermode::kIDA_Coeff, SkXfermode::kSA_Coeff },
968 { xor_modeproc, proc_4f<xor_4f>, SkXfermode::kIDA_Coeff, SkXfermode::kISA_Coeff },
969
970 { plus_modeproc, proc_4f<plus_4f>, SkXfermode::kOne_Coeff, SkXfermode::kOne_Coeff },
971 { modulate_modeproc, proc_4f<modulate_4f>, SkXfermode::kZero_Coeff, SkXfermode::kSC_Coeff },
972 { screen_modeproc, proc_4f<screen_4f>, SkXfermode::kOne_Coeff, SkXfermode::kISC_Coeff },
973 { overlay_modeproc, proc_4f<overlay_4f>, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
974 { darken_modeproc, proc_4f<darken_4f>, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
975 { lighten_modeproc, proc_4f<lighten_4f>, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
976 { colordodge_modeproc, proc_4f<colordodge_4f>, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
977 { colorburn_modeproc, proc_4f<colorburn_4f>, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
978 { hardlight_modeproc, proc_4f<hardlight_4f>, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
979 { softlight_modeproc, proc_4f<softlight_4f>, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
980 { difference_modeproc, proc_4f<difference_4f>, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
981 { exclusion_modeproc, proc_4f<exclusion_4f>, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
982 { multiply_modeproc, proc_4f<multiply_4f>, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
983 { hue_modeproc, proc_4f<hue_4f>, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
984 { saturation_modeproc, proc_4f<saturation_4f>, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
985 { color_modeproc, proc_4f<color_4f>, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
986 { luminosity_modeproc, proc_4f<luminosity_4f>, CANNOT_USE_COEFF, CANNOT_USE_COEFF },
987 };
988
989 ///////////////////////////////////////////////////////////////////////////////
990
asMode(Mode * mode) const991 bool SkXfermode::asMode(Mode* mode) const {
992 return false;
993 }
994
995 #if SK_SUPPORT_GPU
makeFragmentProcessorForImageFilter(sk_sp<GrFragmentProcessor>) const996 sk_sp<GrFragmentProcessor> SkXfermode::makeFragmentProcessorForImageFilter(
997 sk_sp<GrFragmentProcessor>) const {
998 // This should never be called.
999 // TODO: make pure virtual in SkXfermode once Android update lands
1000 SkASSERT(0);
1001 return nullptr;
1002 }
1003
asXPFactory() const1004 const GrXPFactory* SkXfermode::asXPFactory() const {
1005 // This should never be called.
1006 // TODO: make pure virtual in SkXfermode once Android update lands
1007 SkASSERT(0);
1008 return nullptr;
1009 }
1010 #endif
1011
xferColor(SkPMColor src,SkPMColor dst) const1012 SkPMColor SkXfermode::xferColor(SkPMColor src, SkPMColor dst) const{
1013 // no-op. subclasses should override this
1014 return dst;
1015 }
1016
xfer32(SkPMColor * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,const SkAlpha * SK_RESTRICT aa) const1017 void SkXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
1018 const SkPMColor* SK_RESTRICT src, int count,
1019 const SkAlpha* SK_RESTRICT aa) const {
1020 SkASSERT(dst && src && count >= 0);
1021
1022 if (nullptr == aa) {
1023 for (int i = count - 1; i >= 0; --i) {
1024 dst[i] = this->xferColor(src[i], dst[i]);
1025 }
1026 } else {
1027 for (int i = count - 1; i >= 0; --i) {
1028 unsigned a = aa[i];
1029 if (0 != a) {
1030 SkPMColor dstC = dst[i];
1031 SkPMColor C = this->xferColor(src[i], dstC);
1032 if (0xFF != a) {
1033 C = SkFourByteInterp(C, dstC, a);
1034 }
1035 dst[i] = C;
1036 }
1037 }
1038 }
1039 }
1040
xfer16(uint16_t * dst,const SkPMColor * SK_RESTRICT src,int count,const SkAlpha * SK_RESTRICT aa) const1041 void SkXfermode::xfer16(uint16_t* dst,
1042 const SkPMColor* SK_RESTRICT src, int count,
1043 const SkAlpha* SK_RESTRICT aa) const {
1044 SkASSERT(dst && src && count >= 0);
1045
1046 if (nullptr == aa) {
1047 for (int i = count - 1; i >= 0; --i) {
1048 SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
1049 dst[i] = SkPixel32ToPixel16_ToU16(this->xferColor(src[i], dstC));
1050 }
1051 } else {
1052 for (int i = count - 1; i >= 0; --i) {
1053 unsigned a = aa[i];
1054 if (0 != a) {
1055 SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
1056 SkPMColor C = this->xferColor(src[i], dstC);
1057 if (0xFF != a) {
1058 C = SkFourByteInterp(C, dstC, a);
1059 }
1060 dst[i] = SkPixel32ToPixel16_ToU16(C);
1061 }
1062 }
1063 }
1064 }
1065
xferA8(SkAlpha * SK_RESTRICT dst,const SkPMColor src[],int count,const SkAlpha * SK_RESTRICT aa) const1066 void SkXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
1067 const SkPMColor src[], int count,
1068 const SkAlpha* SK_RESTRICT aa) const {
1069 SkASSERT(dst && src && count >= 0);
1070
1071 if (nullptr == aa) {
1072 for (int i = count - 1; i >= 0; --i) {
1073 SkPMColor res = this->xferColor(src[i], (dst[i] << SK_A32_SHIFT));
1074 dst[i] = SkToU8(SkGetPackedA32(res));
1075 }
1076 } else {
1077 for (int i = count - 1; i >= 0; --i) {
1078 unsigned a = aa[i];
1079 if (0 != a) {
1080 SkAlpha dstA = dst[i];
1081 unsigned A = SkGetPackedA32(this->xferColor(src[i],
1082 (SkPMColor)(dstA << SK_A32_SHIFT)));
1083 if (0xFF != a) {
1084 A = SkAlphaBlend(A, dstA, SkAlpha255To256(a));
1085 }
1086 dst[i] = SkToU8(A);
1087 }
1088 }
1089 }
1090 }
1091
supportsCoverageAsAlpha() const1092 bool SkXfermode::supportsCoverageAsAlpha() const {
1093 return false;
1094 }
1095
isOpaque(SkXfermode::SrcColorOpacity opacityType) const1096 bool SkXfermode::isOpaque(SkXfermode::SrcColorOpacity opacityType) const {
1097 return false;
1098 }
1099
1100 ///////////////////////////////////////////////////////////////////////////////
1101 ///////////////////////////////////////////////////////////////////////////////
1102
CreateProc(SkReadBuffer & buffer)1103 sk_sp<SkFlattenable> SkProcCoeffXfermode::CreateProc(SkReadBuffer& buffer) {
1104 uint32_t mode32 = buffer.read32();
1105 if (!buffer.validate(mode32 < SK_ARRAY_COUNT(gProcCoeffs))) {
1106 return nullptr;
1107 }
1108 return SkXfermode::Make((SkXfermode::Mode)mode32);
1109 }
1110
flatten(SkWriteBuffer & buffer) const1111 void SkProcCoeffXfermode::flatten(SkWriteBuffer& buffer) const {
1112 buffer.write32((int)fMode);
1113 }
1114
asMode(Mode * mode) const1115 bool SkProcCoeffXfermode::asMode(Mode* mode) const {
1116 if (mode) {
1117 *mode = (Mode)fMode;
1118 }
1119 return true;
1120 }
1121
supportsCoverageAsAlpha() const1122 bool SkProcCoeffXfermode::supportsCoverageAsAlpha() const {
1123 if (CANNOT_USE_COEFF == fSrcCoeff) {
1124 return false;
1125 }
1126
1127 switch (fDstCoeff) {
1128 case SkXfermode::kOne_Coeff:
1129 case SkXfermode::kISA_Coeff:
1130 case SkXfermode::kISC_Coeff:
1131 return true;
1132 default:
1133 return false;
1134 }
1135 }
1136
isOpaque(SkXfermode::SrcColorOpacity opacityType) const1137 bool SkProcCoeffXfermode::isOpaque(SkXfermode::SrcColorOpacity opacityType) const {
1138 if (CANNOT_USE_COEFF == fSrcCoeff) {
1139 return false;
1140 }
1141
1142 if (SkXfermode::kDA_Coeff == fSrcCoeff || SkXfermode::kDC_Coeff == fSrcCoeff ||
1143 SkXfermode::kIDA_Coeff == fSrcCoeff || SkXfermode::kIDC_Coeff == fSrcCoeff) {
1144 return false;
1145 }
1146
1147 switch (fDstCoeff) {
1148 case SkXfermode::kZero_Coeff:
1149 return true;
1150 case SkXfermode::kISA_Coeff:
1151 return SkXfermode::kOpaque_SrcColorOpacity == opacityType;
1152 case SkXfermode::kSA_Coeff:
1153 return SkXfermode::kTransparentBlack_SrcColorOpacity == opacityType ||
1154 SkXfermode::kTransparentAlpha_SrcColorOpacity == opacityType;
1155 case SkXfermode::kSC_Coeff:
1156 return SkXfermode::kTransparentBlack_SrcColorOpacity == opacityType;
1157 default:
1158 return false;
1159 }
1160
1161 }
1162
xfer32(SkPMColor * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,const SkAlpha * SK_RESTRICT aa) const1163 void SkProcCoeffXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
1164 const SkPMColor* SK_RESTRICT src, int count,
1165 const SkAlpha* SK_RESTRICT aa) const {
1166 SkASSERT(dst && src && count >= 0);
1167
1168 SkXfermodeProc proc = fProc;
1169
1170 if (proc) {
1171 if (nullptr == aa) {
1172 for (int i = count - 1; i >= 0; --i) {
1173 dst[i] = proc(src[i], dst[i]);
1174 }
1175 } else {
1176 for (int i = count - 1; i >= 0; --i) {
1177 unsigned a = aa[i];
1178 if (0 != a) {
1179 SkPMColor dstC = dst[i];
1180 SkPMColor C = proc(src[i], dstC);
1181 if (a != 0xFF) {
1182 C = SkFourByteInterp(C, dstC, a);
1183 }
1184 dst[i] = C;
1185 }
1186 }
1187 }
1188 }
1189 }
1190
xfer16(uint16_t * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,const SkAlpha * SK_RESTRICT aa) const1191 void SkProcCoeffXfermode::xfer16(uint16_t* SK_RESTRICT dst,
1192 const SkPMColor* SK_RESTRICT src, int count,
1193 const SkAlpha* SK_RESTRICT aa) const {
1194 SkASSERT(dst && src && count >= 0);
1195
1196 SkXfermodeProc proc = fProc;
1197
1198 if (proc) {
1199 if (nullptr == aa) {
1200 for (int i = count - 1; i >= 0; --i) {
1201 SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
1202 dst[i] = SkPixel32ToPixel16_ToU16(proc(src[i], dstC));
1203 }
1204 } else {
1205 for (int i = count - 1; i >= 0; --i) {
1206 unsigned a = aa[i];
1207 if (0 != a) {
1208 SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
1209 SkPMColor C = proc(src[i], dstC);
1210 if (0xFF != a) {
1211 C = SkFourByteInterp(C, dstC, a);
1212 }
1213 dst[i] = SkPixel32ToPixel16_ToU16(C);
1214 }
1215 }
1216 }
1217 }
1218 }
1219
xferA8(SkAlpha * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,const SkAlpha * SK_RESTRICT aa) const1220 void SkProcCoeffXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
1221 const SkPMColor* SK_RESTRICT src, int count,
1222 const SkAlpha* SK_RESTRICT aa) const {
1223 SkASSERT(dst && src && count >= 0);
1224
1225 SkXfermodeProc proc = fProc;
1226
1227 if (proc) {
1228 if (nullptr == aa) {
1229 for (int i = count - 1; i >= 0; --i) {
1230 SkPMColor res = proc(src[i], dst[i] << SK_A32_SHIFT);
1231 dst[i] = SkToU8(SkGetPackedA32(res));
1232 }
1233 } else {
1234 for (int i = count - 1; i >= 0; --i) {
1235 unsigned a = aa[i];
1236 if (0 != a) {
1237 SkAlpha dstA = dst[i];
1238 SkPMColor res = proc(src[i], dstA << SK_A32_SHIFT);
1239 unsigned A = SkGetPackedA32(res);
1240 if (0xFF != a) {
1241 A = SkAlphaBlend(A, dstA, SkAlpha255To256(a));
1242 }
1243 dst[i] = SkToU8(A);
1244 }
1245 }
1246 }
1247 }
1248 }
1249
1250 #if SK_SUPPORT_GPU
makeFragmentProcessorForImageFilter(sk_sp<GrFragmentProcessor> dst) const1251 sk_sp<GrFragmentProcessor> SkProcCoeffXfermode::makeFragmentProcessorForImageFilter(
1252 sk_sp<GrFragmentProcessor> dst) const {
1253 SkASSERT(dst);
1254 return GrXfermodeFragmentProcessor::MakeFromDstProcessor(std::move(dst), fMode);
1255 }
1256
asXPFactory() const1257 const GrXPFactory* SkProcCoeffXfermode::asXPFactory() const {
1258 if (CANNOT_USE_COEFF != fSrcCoeff) {
1259 const GrXPFactory* result(GrPorterDuffXPFactory::Get(fMode));
1260 SkASSERT(result);
1261 return result;
1262 }
1263
1264 SkASSERT(GrCustomXfermode::IsSupportedMode(fMode));
1265 return GrCustomXfermode::Get(fMode);
1266 }
1267 #endif
1268
ModeName(Mode mode)1269 const char* SkXfermode::ModeName(Mode mode) {
1270 SkASSERT((unsigned) mode <= (unsigned)kLastMode);
1271 const char* gModeStrings[] = {
1272 "Clear", "Src", "Dst", "SrcOver", "DstOver", "SrcIn", "DstIn",
1273 "SrcOut", "DstOut", "SrcATop", "DstATop", "Xor", "Plus",
1274 "Modulate", "Screen", "Overlay", "Darken", "Lighten", "ColorDodge",
1275 "ColorBurn", "HardLight", "SoftLight", "Difference", "Exclusion",
1276 "Multiply", "Hue", "Saturation", "Color", "Luminosity"
1277 };
1278 return gModeStrings[mode];
1279 static_assert(SK_ARRAY_COUNT(gModeStrings) == kLastMode + 1, "mode_count");
1280 }
1281
SkBlendMode_Name(SkBlendMode mode)1282 const char* SkBlendMode_Name(SkBlendMode mode) {
1283 return SkXfermode::ModeName((SkXfermode::Mode)mode);
1284 }
1285
1286 #ifndef SK_IGNORE_TO_STRING
toString(SkString * str) const1287 void SkProcCoeffXfermode::toString(SkString* str) const {
1288 str->append("SkProcCoeffXfermode: ");
1289
1290 str->append("mode: ");
1291 str->append(ModeName(fMode));
1292
1293 static const char* gCoeffStrings[kCoeffCount] = {
1294 "Zero", "One", "SC", "ISC", "DC", "IDC", "SA", "ISA", "DA", "IDA"
1295 };
1296
1297 str->append(" src: ");
1298 if (CANNOT_USE_COEFF == fSrcCoeff) {
1299 str->append("can't use");
1300 } else {
1301 str->append(gCoeffStrings[fSrcCoeff]);
1302 }
1303
1304 str->append(" dst: ");
1305 if (CANNOT_USE_COEFF == fDstCoeff) {
1306 str->append("can't use");
1307 } else {
1308 str->append(gCoeffStrings[fDstCoeff]);
1309 }
1310 }
1311 #endif
1312
1313
Make(SkBlendMode mode)1314 sk_sp<SkXfermode> SkXfermode::Make(SkBlendMode mode) {
1315 if ((unsigned)mode > (unsigned)SkBlendMode::kLastMode) {
1316 // report error
1317 return nullptr;
1318 }
1319
1320 // Skia's "default" mode is srcover. nullptr in SkPaint is interpreted as srcover
1321 // so we can just return nullptr from the factory.
1322 if (SkBlendMode::kSrcOver == mode) {
1323 return nullptr;
1324 }
1325
1326 const int COUNT_BLENDMODES = (int)SkBlendMode::kLastMode + 1;
1327 SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == COUNT_BLENDMODES);
1328
1329 static SkOnce once[COUNT_BLENDMODES];
1330 static SkXfermode* cached[COUNT_BLENDMODES];
1331
1332 once[(int)mode]([mode] {
1333 ProcCoeff rec = gProcCoeffs[(int)mode];
1334 if (auto xfermode = SkOpts::create_xfermode(rec, mode)) {
1335 cached[(int)mode] = xfermode;
1336 } else {
1337 cached[(int)mode] = new SkProcCoeffXfermode(rec, mode);
1338 }
1339 });
1340 return sk_ref_sp(cached[(int)mode]);
1341 }
1342
GetProc(SkBlendMode mode)1343 SkXfermodeProc SkXfermode::GetProc(SkBlendMode mode) {
1344 SkXfermodeProc proc = nullptr;
1345 if ((unsigned)mode < kModeCount) {
1346 proc = gProcCoeffs[(unsigned)mode].fProc;
1347 }
1348 return proc;
1349 }
1350
GetProc4f(SkBlendMode mode)1351 SkXfermodeProc4f SkXfermode::GetProc4f(SkBlendMode mode) {
1352 SkXfermodeProc4f proc = nullptr;
1353 if ((unsigned)mode < kModeCount) {
1354 proc = gProcCoeffs[(unsigned)mode].fProc4f;
1355 }
1356 return proc;
1357 }
1358
ModeAsCoeff(Mode mode,Coeff * src,Coeff * dst)1359 bool SkXfermode::ModeAsCoeff(Mode mode, Coeff* src, Coeff* dst) {
1360 SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount);
1361
1362 if ((unsigned)mode >= (unsigned)kModeCount) {
1363 // illegal mode parameter
1364 return false;
1365 }
1366
1367 const ProcCoeff& rec = gProcCoeffs[mode];
1368
1369 if (CANNOT_USE_COEFF == rec.fSC) {
1370 return false;
1371 }
1372
1373 SkASSERT(CANNOT_USE_COEFF != rec.fDC);
1374 if (src) {
1375 *src = rec.fSC;
1376 }
1377 if (dst) {
1378 *dst = rec.fDC;
1379 }
1380 return true;
1381 }
1382
AsMode(const SkXfermode * xfer,Mode * mode)1383 bool SkXfermode::AsMode(const SkXfermode* xfer, Mode* mode) {
1384 if (nullptr == xfer) {
1385 if (mode) {
1386 *mode = kSrcOver_Mode;
1387 }
1388 return true;
1389 }
1390 return xfer->asMode(mode);
1391 }
1392
IsMode(const SkXfermode * xfer,Mode mode)1393 bool SkXfermode::IsMode(const SkXfermode* xfer, Mode mode) {
1394 // if xfer==null then the mode is srcover
1395 Mode m = kSrcOver_Mode;
1396 if (xfer && !xfer->asMode(&m)) {
1397 return false;
1398 }
1399 return mode == m;
1400 }
1401
SupportsCoverageAsAlpha(const SkXfermode * xfer)1402 bool SkXfermode::SupportsCoverageAsAlpha(const SkXfermode* xfer) {
1403 // if xfer is nullptr we treat it as srcOver which always supports coverageAsAlpha
1404 if (!xfer) {
1405 return true;
1406 }
1407
1408 return xfer->supportsCoverageAsAlpha();
1409 }
1410
IsOpaque(const SkXfermode * xfer,SrcColorOpacity opacityType)1411 bool SkXfermode::IsOpaque(const SkXfermode* xfer, SrcColorOpacity opacityType) {
1412 // if xfer is nullptr we treat it as srcOver which is opaque if our src is opaque
1413 if (!xfer) {
1414 return SkXfermode::kOpaque_SrcColorOpacity == opacityType;
1415 }
1416
1417 return xfer->isOpaque(opacityType);
1418 }
1419
1420 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkXfermode)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkProcCoeffXfermode)1421 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkProcCoeffXfermode)
1422 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
1423
1424 ///////////////////////////////////////////////////////////////////////////////////////////////////
1425
1426 bool SkBlendMode_SupportsCoverageAsAlpha(SkBlendMode mode) {
1427 switch (mode) {
1428 case SkBlendMode::kDst:
1429 case SkBlendMode::kSrcOver:
1430 case SkBlendMode::kDstOver:
1431 case SkBlendMode::kDstOut:
1432 case SkBlendMode::kSrcATop:
1433 case SkBlendMode::kXor:
1434 case SkBlendMode::kPlus:
1435 return true;
1436 default:
1437 break;
1438 }
1439 return false;
1440 }
1441
IsOpaque(SkBlendMode mode,SrcColorOpacity opacityType)1442 bool SkXfermode::IsOpaque(SkBlendMode mode, SrcColorOpacity opacityType) {
1443 const ProcCoeff rec = gProcCoeffs[(int)mode];
1444
1445 switch (rec.fSC) {
1446 case kDA_Coeff:
1447 case kDC_Coeff:
1448 case kIDA_Coeff:
1449 case kIDC_Coeff:
1450 return false;
1451 default:
1452 break;
1453 }
1454
1455 switch (rec.fDC) {
1456 case kZero_Coeff:
1457 return true;
1458 case kISA_Coeff:
1459 return kOpaque_SrcColorOpacity == opacityType;
1460 case kSA_Coeff:
1461 return kTransparentBlack_SrcColorOpacity == opacityType ||
1462 kTransparentAlpha_SrcColorOpacity == opacityType;
1463 case kSC_Coeff:
1464 return kTransparentBlack_SrcColorOpacity == opacityType;
1465 default:
1466 return false;
1467 }
1468 return false;
1469 }
1470
1471 #if SK_SUPPORT_GPU
SkBlendMode_AsXPFactory(SkBlendMode mode)1472 const GrXPFactory* SkBlendMode_AsXPFactory(SkBlendMode mode) {
1473 const ProcCoeff rec = gProcCoeffs[(int)mode];
1474 if (CANNOT_USE_COEFF != rec.fSC) {
1475 const GrXPFactory* result = GrPorterDuffXPFactory::Get(mode);
1476 SkASSERT(result);
1477 return result;
1478 }
1479
1480 SkASSERT(GrCustomXfermode::IsSupportedMode(mode));
1481 return GrCustomXfermode::Get(mode);
1482 }
1483 #endif
1484
SkBlendMode_CanOverflow(SkBlendMode mode)1485 bool SkBlendMode_CanOverflow(SkBlendMode mode) { return mode == SkBlendMode::kPlus; }
1486
SkBlendMode_AppendStages(SkBlendMode mode,SkRasterPipeline * p)1487 bool SkBlendMode_AppendStages(SkBlendMode mode, SkRasterPipeline* p) {
1488 auto stage = SkRasterPipeline::srcover;
1489 switch (mode) {
1490 case SkBlendMode::kClear: stage = SkRasterPipeline::clear; break;
1491 case SkBlendMode::kSrc: return true; // This stage is a no-op.
1492 case SkBlendMode::kDst: stage = SkRasterPipeline::move_dst_src; break;
1493 case SkBlendMode::kSrcOver: stage = SkRasterPipeline::srcover; break;
1494 case SkBlendMode::kDstOver: stage = SkRasterPipeline::dstover; break;
1495 case SkBlendMode::kSrcIn: stage = SkRasterPipeline::srcin; break;
1496 case SkBlendMode::kDstIn: stage = SkRasterPipeline::dstin; break;
1497 case SkBlendMode::kSrcOut: stage = SkRasterPipeline::srcout; break;
1498 case SkBlendMode::kDstOut: stage = SkRasterPipeline::dstout; break;
1499 case SkBlendMode::kSrcATop: stage = SkRasterPipeline::srcatop; break;
1500 case SkBlendMode::kDstATop: stage = SkRasterPipeline::dstatop; break;
1501 case SkBlendMode::kXor: stage = SkRasterPipeline::xor_; break;
1502 case SkBlendMode::kPlus: stage = SkRasterPipeline::plus_; break;
1503 case SkBlendMode::kModulate: stage = SkRasterPipeline::modulate; break;
1504
1505 case SkBlendMode::kScreen: stage = SkRasterPipeline::screen; break;
1506 case SkBlendMode::kOverlay: stage = SkRasterPipeline::overlay; break;
1507 case SkBlendMode::kDarken: stage = SkRasterPipeline::darken; break;
1508 case SkBlendMode::kLighten: stage = SkRasterPipeline::lighten; break;
1509 case SkBlendMode::kColorDodge: stage = SkRasterPipeline::colordodge; break;
1510 case SkBlendMode::kColorBurn: stage = SkRasterPipeline::colorburn; break;
1511 case SkBlendMode::kHardLight: stage = SkRasterPipeline::hardlight; break;
1512 case SkBlendMode::kSoftLight: stage = SkRasterPipeline::softlight; break;
1513 case SkBlendMode::kDifference: stage = SkRasterPipeline::difference; break;
1514 case SkBlendMode::kExclusion: stage = SkRasterPipeline::exclusion; break;
1515 case SkBlendMode::kMultiply: stage = SkRasterPipeline::multiply; break;
1516
1517 case SkBlendMode::kHue:
1518 case SkBlendMode::kSaturation:
1519 case SkBlendMode::kColor:
1520 case SkBlendMode::kLuminosity: return false; // TODO
1521 }
1522 if (p) {
1523 p->append(stage);
1524 }
1525 return true;
1526 }
1527