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.h"
9 #include "SkXfermode_proccoeff.h"
10 #include "SkColorPriv.h"
11 #include "SkMathPriv.h"
12 #include "SkOnce.h"
13 #include "SkOpts.h"
14 #include "SkRasterPipeline.h"
15 #include "SkReadBuffer.h"
16 #include "SkString.h"
17 #include "SkWriteBuffer.h"
18 #include "SkPM4f.h"
19
20 #if SK_SUPPORT_GPU
21 #include "GrFragmentProcessor.h"
22 #include "effects/GrCustomXfermode.h"
23 #include "effects/GrPorterDuffXferProcessor.h"
24 #include "effects/GrXfermodeFragmentProcessor.h"
25 #endif
26
27 #define SkAlphaMulAlpha(a, b) SkMulDiv255Round(a, b)
28
saturated_add(unsigned a,unsigned b)29 static inline unsigned saturated_add(unsigned a, unsigned b) {
30 SkASSERT(a <= 255);
31 SkASSERT(b <= 255);
32 unsigned sum = a + b;
33 if (sum > 255) {
34 sum = 255;
35 }
36 return sum;
37 }
38
clamp_signed_byte(int n)39 static inline int clamp_signed_byte(int n) {
40 if (n < 0) {
41 n = 0;
42 } else if (n > 255) {
43 n = 255;
44 }
45 return n;
46 }
47
clamp_div255round(int prod)48 static inline int clamp_div255round(int prod) {
49 if (prod <= 0) {
50 return 0;
51 } else if (prod >= 255*255) {
52 return 255;
53 } else {
54 return SkDiv255Round(prod);
55 }
56 }
57
58 ///////////////////////////////////////////////////////////////////////////////
59 #include "SkNx.h"
60
alpha(const Sk4f & color)61 static Sk4f alpha(const Sk4f& color) { return Sk4f(color[3]); }
inv_alpha(const Sk4f & color)62 static Sk4f inv_alpha(const Sk4f& color) { return Sk4f(1 - color[3]); }
pin_1(const Sk4f & value)63 static Sk4f pin_1(const Sk4f& value) { return Sk4f::Min(value, Sk4f(1)); }
64
color_alpha(const Sk4f & color,float newAlpha)65 static Sk4f color_alpha(const Sk4f& color, float newAlpha) {
66 return Sk4f(color[0], color[1], color[2], newAlpha);
67 }
color_alpha(const Sk4f & color,const Sk4f & newAlpha)68 static Sk4f color_alpha(const Sk4f& color, const Sk4f& newAlpha) {
69 return color_alpha(color, newAlpha[3]);
70 }
71
set_argb(float a,float r,float g,float b)72 static Sk4f set_argb(float a, float r, float g, float b) {
73 if (0 == SkPM4f::R) {
74 return Sk4f(r, g, b, a);
75 } else {
76 return Sk4f(b, g, r, a);
77 }
78 }
79
clear_4f(const Sk4f & s,const Sk4f & d)80 static Sk4f clear_4f(const Sk4f& s, const Sk4f& d) { return Sk4f(0); }
src_4f(const Sk4f & s,const Sk4f & d)81 static Sk4f src_4f(const Sk4f& s, const Sk4f& d) { return s; }
dst_4f(const Sk4f & s,const Sk4f & d)82 static Sk4f dst_4f(const Sk4f& s, const Sk4f& d) { return d; }
srcover_4f(const Sk4f & s,const Sk4f & d)83 static Sk4f srcover_4f(const Sk4f& s, const Sk4f& d) { return s + inv_alpha(s) * d; }
dstover_4f(const Sk4f & s,const Sk4f & d)84 static Sk4f dstover_4f(const Sk4f& s, const Sk4f& d) { return d + inv_alpha(d) * s; }
srcin_4f(const Sk4f & s,const Sk4f & d)85 static Sk4f srcin_4f(const Sk4f& s, const Sk4f& d) { return s * alpha(d); }
dstin_4f(const Sk4f & s,const Sk4f & d)86 static Sk4f dstin_4f(const Sk4f& s, const Sk4f& d) { return d * alpha(s); }
srcout_4f(const Sk4f & s,const Sk4f & d)87 static Sk4f srcout_4f(const Sk4f& s, const Sk4f& d) { return s * inv_alpha(d); }
dstout_4f(const Sk4f & s,const Sk4f & d)88 static Sk4f dstout_4f(const Sk4f& s, const Sk4f& d) { return d * inv_alpha(s); }
srcatop_4f(const Sk4f & s,const Sk4f & d)89 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)90 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)91 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)92 static Sk4f plus_4f(const Sk4f& s, const Sk4f& d) { return pin_1(s + d); }
modulate_4f(const Sk4f & s,const Sk4f & d)93 static Sk4f modulate_4f(const Sk4f& s, const Sk4f& d) { return s * d; }
screen_4f(const Sk4f & s,const Sk4f & d)94 static Sk4f screen_4f(const Sk4f& s, const Sk4f& d) { return s + d - s * d; }
95
multiply_4f(const Sk4f & s,const Sk4f & d)96 static Sk4f multiply_4f(const Sk4f& s, const Sk4f& d) {
97 return s * inv_alpha(d) + d * inv_alpha(s) + s * d;
98 }
99
overlay_4f(const Sk4f & s,const Sk4f & d)100 static Sk4f overlay_4f(const Sk4f& s, const Sk4f& d) {
101 Sk4f sa = alpha(s);
102 Sk4f da = alpha(d);
103 Sk4f two = Sk4f(2);
104 Sk4f rc = (two * d <= da).thenElse(two * s * d,
105 sa * da - two * (da - d) * (sa - s));
106 return pin_1(s + d - s * da + color_alpha(rc - d * sa, 0));
107 }
108
hardlight_4f(const Sk4f & s,const Sk4f & d)109 static Sk4f hardlight_4f(const Sk4f& s, const Sk4f& d) {
110 return overlay_4f(d, s);
111 }
112
darken_4f(const Sk4f & s,const Sk4f & d)113 static Sk4f darken_4f(const Sk4f& s, const Sk4f& d) {
114 Sk4f sa = alpha(s);
115 Sk4f da = alpha(d);
116 return s + d - Sk4f::Max(s * da, d * sa);
117 }
118
lighten_4f(const Sk4f & s,const Sk4f & d)119 static Sk4f lighten_4f(const Sk4f& s, const Sk4f& d) {
120 Sk4f sa = alpha(s);
121 Sk4f da = alpha(d);
122 return s + d - Sk4f::Min(s * da, d * sa);
123 }
124
colordodge_4f(const Sk4f & s,const Sk4f & d)125 static Sk4f colordodge_4f(const Sk4f& s, const Sk4f& d) {
126 Sk4f sa = alpha(s);
127 Sk4f da = alpha(d);
128 Sk4f isa = Sk4f(1) - sa;
129 Sk4f ida = Sk4f(1) - da;
130
131 Sk4f srcover = s + d * isa;
132 Sk4f dstover = d + s * ida;
133 Sk4f otherwise = sa * Sk4f::Min(da, (d * sa) / (sa - s)) + s * ida + d * isa;
134
135 // Order matters here, preferring d==0 over s==sa.
136 auto colors = (d == Sk4f(0)).thenElse(dstover,
137 (s == sa).thenElse(srcover,
138 otherwise));
139 return color_alpha(colors, srcover);
140 }
141
colorburn_4f(const Sk4f & s,const Sk4f & d)142 static Sk4f colorburn_4f(const Sk4f& s, const Sk4f& d) {
143 Sk4f sa = alpha(s);
144 Sk4f da = alpha(d);
145 Sk4f isa = Sk4f(1) - sa;
146 Sk4f ida = Sk4f(1) - da;
147
148 Sk4f srcover = s + d * isa;
149 Sk4f dstover = d + s * ida;
150 Sk4f otherwise = sa * (da - Sk4f::Min(da, (da - d) * sa / s)) + s * ida + d * isa;
151
152 // Order matters here, preferring d==da over s==0.
153 auto colors = (d == da).thenElse(dstover,
154 (s == Sk4f(0)).thenElse(srcover,
155 otherwise));
156 return color_alpha(colors, srcover);
157 }
158
softlight_4f(const Sk4f & s,const Sk4f & d)159 static Sk4f softlight_4f(const Sk4f& s, const Sk4f& d) {
160 Sk4f sa = alpha(s);
161 Sk4f da = alpha(d);
162 Sk4f isa = Sk4f(1) - sa;
163 Sk4f ida = Sk4f(1) - da;
164
165 // Some common terms.
166 Sk4f m = (da > Sk4f(0)).thenElse(d / da, Sk4f(0));
167 Sk4f s2 = Sk4f(2) * s;
168 Sk4f m4 = Sk4f(4) * m;
169
170 // The logic forks three ways:
171 // 1. dark src?
172 // 2. light src, dark dst?
173 // 3. light src, light dst?
174 Sk4f darkSrc = d * (sa + (s2 - sa) * (Sk4f(1) - m)); // Used in case 1.
175 Sk4f darkDst = (m4 * m4 + m4) * (m - Sk4f(1)) + Sk4f(7) * m; // Used in case 2.
176 Sk4f liteDst = m.sqrt() - m; // Used in case 3.
177 Sk4f liteSrc = d * sa + da * (s2 - sa) * (Sk4f(4) * d <= da).thenElse(darkDst,
178 liteDst); // Case 2 or 3?
179
180 return color_alpha(s * ida + d * isa + (s2 <= sa).thenElse(darkSrc, liteSrc), // Case 1 or 2/3?
181 s + d * isa);
182 }
183
difference_4f(const Sk4f & s,const Sk4f & d)184 static Sk4f difference_4f(const Sk4f& s, const Sk4f& d) {
185 Sk4f min = Sk4f::Min(s * alpha(d), d * alpha(s));
186 return s + d - min - color_alpha(min, 0);
187 }
188
exclusion_4f(const Sk4f & s,const Sk4f & d)189 static Sk4f exclusion_4f(const Sk4f& s, const Sk4f& d) {
190 Sk4f product = s * d;
191 return s + d - product - color_alpha(product, 0);
192 }
193
194 ////////////////////////////////////////////////////
195
196 // The CSS compositing spec introduces the following formulas:
197 // (See https://dvcs.w3.org/hg/FXTF/rawfile/tip/compositing/index.html#blendingnonseparable)
198 // SkComputeLuminance is similar to this formula but it uses the new definition from Rec. 709
199 // while PDF and CG uses the one from Rec. Rec. 601
200 // 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)201 static inline float Lum(float r, float g, float b) {
202 return r * 0.2126f + g * 0.7152f + b * 0.0722f;
203 }
204
max(float a,float b,float c)205 static inline float max(float a, float b, float c) {
206 return SkTMax(a, SkTMax(b, c));
207 }
208
min(float a,float b,float c)209 static inline float min(float a, float b, float c) {
210 return SkTMin(a, SkTMin(b, c));
211 }
212
Sat(float r,float g,float b)213 static inline float Sat(float r, float g, float b) {
214 return max(r, g, b) - min(r, g, b);
215 }
216
setSaturationComponents(float * Cmin,float * Cmid,float * Cmax,float s)217 static inline void setSaturationComponents(float* Cmin, float* Cmid, float* Cmax, float s) {
218 if(*Cmax > *Cmin) {
219 *Cmid = (*Cmid - *Cmin) * s / (*Cmax - *Cmin);
220 *Cmax = s;
221 } else {
222 *Cmax = 0;
223 *Cmid = 0;
224 }
225 *Cmin = 0;
226 }
227
SetSat(float * r,float * g,float * b,float s)228 static inline void SetSat(float* r, float* g, float* b, float s) {
229 if(*r <= *g) {
230 if(*g <= *b) {
231 setSaturationComponents(r, g, b, s);
232 } else if(*r <= *b) {
233 setSaturationComponents(r, b, g, s);
234 } else {
235 setSaturationComponents(b, r, g, s);
236 }
237 } else if(*r <= *b) {
238 setSaturationComponents(g, r, b, s);
239 } else if(*g <= *b) {
240 setSaturationComponents(g, b, r, s);
241 } else {
242 setSaturationComponents(b, g, r, s);
243 }
244 }
245
clipColor(float * r,float * g,float * b,float a)246 static inline void clipColor(float* r, float* g, float* b, float a) {
247 float L = Lum(*r, *g, *b);
248 float n = min(*r, *g, *b);
249 float x = max(*r, *g, *b);
250 float denom;
251 if ((n < 0) && (denom = L - n)) { // Compute denom and make sure it's non zero
252 float scale = L / denom;
253 *r = L + (*r - L) * scale;
254 *g = L + (*g - L) * scale;
255 *b = L + (*b - L) * scale;
256 }
257
258 if ((x > a) && (denom = x - L)) { // Compute denom and make sure it's non zero
259 float scale = (a - L) / denom;
260 *r = L + (*r - L) * scale;
261 *g = L + (*g - L) * scale;
262 *b = L + (*b - L) * scale;
263 }
264 }
265
SetLum(float * r,float * g,float * b,float a,float l)266 static inline void SetLum(float* r, float* g, float* b, float a, float l) {
267 float d = l - Lum(*r, *g, *b);
268 *r += d;
269 *g += d;
270 *b += d;
271 clipColor(r, g, b, a);
272 }
273
hue_4f(const Sk4f & s,const Sk4f & d)274 static Sk4f hue_4f(const Sk4f& s, const Sk4f& d) {
275 float sa = s[SkPM4f::A];
276 float sr = s[SkPM4f::R];
277 float sg = s[SkPM4f::G];
278 float sb = s[SkPM4f::B];
279
280 float da = d[SkPM4f::A];
281 float dr = d[SkPM4f::R];
282 float dg = d[SkPM4f::G];
283 float db = d[SkPM4f::B];
284
285 float Sr = sr;
286 float Sg = sg;
287 float Sb = sb;
288 SetSat(&Sr, &Sg, &Sb, Sat(dr, dg, db) * sa);
289 SetLum(&Sr, &Sg, &Sb, sa * da, Lum(dr, dg, db) * sa);
290
291 return color_alpha(s * inv_alpha(d) + d * inv_alpha(s) + set_argb(0, Sr, Sg, Sb),
292 sa + da - sa * da);
293 }
294
saturation_4f(const Sk4f & s,const Sk4f & d)295 static Sk4f saturation_4f(const Sk4f& s, const Sk4f& d) {
296 float sa = s[SkPM4f::A];
297 float sr = s[SkPM4f::R];
298 float sg = s[SkPM4f::G];
299 float sb = s[SkPM4f::B];
300
301 float da = d[SkPM4f::A];
302 float dr = d[SkPM4f::R];
303 float dg = d[SkPM4f::G];
304 float db = d[SkPM4f::B];
305
306 float Dr = dr;
307 float Dg = dg;
308 float Db = db;
309 SetSat(&Dr, &Dg, &Db, Sat(sr, sg, sb) * da);
310 SetLum(&Dr, &Dg, &Db, sa * da, Lum(dr, dg, db) * sa);
311
312 return color_alpha(s * inv_alpha(d) + d * inv_alpha(s) + set_argb(0, Dr, Dg, Db),
313 sa + da - sa * da);
314 }
315
color_4f(const Sk4f & s,const Sk4f & d)316 static Sk4f color_4f(const Sk4f& s, const Sk4f& d) {
317 float sa = s[SkPM4f::A];
318 float sr = s[SkPM4f::R];
319 float sg = s[SkPM4f::G];
320 float sb = s[SkPM4f::B];
321
322 float da = d[SkPM4f::A];
323 float dr = d[SkPM4f::R];
324 float dg = d[SkPM4f::G];
325 float db = d[SkPM4f::B];
326
327 float Sr = sr;
328 float Sg = sg;
329 float Sb = sb;
330 SetLum(&Sr, &Sg, &Sb, sa * da, Lum(dr, dg, db) * sa);
331
332 Sk4f res = color_alpha(s * inv_alpha(d) + d * inv_alpha(s) + set_argb(0, Sr, Sg, Sb),
333 sa + da - sa * da);
334 // Can return tiny negative values ...
335 return Sk4f::Max(res, Sk4f(0));
336 }
337
luminosity_4f(const Sk4f & s,const Sk4f & d)338 static Sk4f luminosity_4f(const Sk4f& s, const Sk4f& d) {
339 float sa = s[SkPM4f::A];
340 float sr = s[SkPM4f::R];
341 float sg = s[SkPM4f::G];
342 float sb = s[SkPM4f::B];
343
344 float da = d[SkPM4f::A];
345 float dr = d[SkPM4f::R];
346 float dg = d[SkPM4f::G];
347 float db = d[SkPM4f::B];
348
349 float Dr = dr;
350 float Dg = dg;
351 float Db = db;
352 SetLum(&Dr, &Dg, &Db, sa * da, Lum(sr, sg, sb) * da);
353
354 Sk4f res = color_alpha(s * inv_alpha(d) + d * inv_alpha(s) + set_argb(0, Dr, Dg, Db),
355 sa + da - sa * da);
356 // Can return tiny negative values ...
357 return Sk4f::Max(res, Sk4f(0));
358 }
359
360 ///////////////////////////////////////////////////////////////////////////////
361
362 // kClear_Mode, //!< [0, 0]
clear_modeproc(SkPMColor src,SkPMColor dst)363 static SkPMColor clear_modeproc(SkPMColor src, SkPMColor dst) {
364 return 0;
365 }
366
367 // kSrc_Mode, //!< [Sa, Sc]
src_modeproc(SkPMColor src,SkPMColor dst)368 static SkPMColor src_modeproc(SkPMColor src, SkPMColor dst) {
369 return src;
370 }
371
372 // kDst_Mode, //!< [Da, Dc]
dst_modeproc(SkPMColor src,SkPMColor dst)373 static SkPMColor dst_modeproc(SkPMColor src, SkPMColor dst) {
374 return dst;
375 }
376
377 // kSrcOver_Mode, //!< [Sa + Da - Sa*Da, Sc + (1 - Sa)*Dc]
srcover_modeproc(SkPMColor src,SkPMColor dst)378 static SkPMColor srcover_modeproc(SkPMColor src, SkPMColor dst) {
379 #if 0
380 // this is the old, more-correct way, but it doesn't guarantee that dst==255
381 // will always stay opaque
382 return src + SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src)));
383 #else
384 // this is slightly faster, but more importantly guarantees that dst==255
385 // will always stay opaque
386 return src + SkAlphaMulQ(dst, 256 - SkGetPackedA32(src));
387 #endif
388 }
389
390 // kDstOver_Mode, //!< [Sa + Da - Sa*Da, Dc + (1 - Da)*Sc]
dstover_modeproc(SkPMColor src,SkPMColor dst)391 static SkPMColor dstover_modeproc(SkPMColor src, SkPMColor dst) {
392 // this is the reverse of srcover, just flipping src and dst
393 // see srcover's comment about the 256 for opaqueness guarantees
394 return dst + SkAlphaMulQ(src, 256 - SkGetPackedA32(dst));
395 }
396
397 // kSrcIn_Mode, //!< [Sa * Da, Sc * Da]
srcin_modeproc(SkPMColor src,SkPMColor dst)398 static SkPMColor srcin_modeproc(SkPMColor src, SkPMColor dst) {
399 return SkAlphaMulQ(src, SkAlpha255To256(SkGetPackedA32(dst)));
400 }
401
402 // kDstIn_Mode, //!< [Sa * Da, Sa * Dc]
dstin_modeproc(SkPMColor src,SkPMColor dst)403 static SkPMColor dstin_modeproc(SkPMColor src, SkPMColor dst) {
404 return SkAlphaMulQ(dst, SkAlpha255To256(SkGetPackedA32(src)));
405 }
406
407 // kSrcOut_Mode, //!< [Sa * (1 - Da), Sc * (1 - Da)]
srcout_modeproc(SkPMColor src,SkPMColor dst)408 static SkPMColor srcout_modeproc(SkPMColor src, SkPMColor dst) {
409 return SkAlphaMulQ(src, SkAlpha255To256(255 - SkGetPackedA32(dst)));
410 }
411
412 // kDstOut_Mode, //!< [Da * (1 - Sa), Dc * (1 - Sa)]
dstout_modeproc(SkPMColor src,SkPMColor dst)413 static SkPMColor dstout_modeproc(SkPMColor src, SkPMColor dst) {
414 return SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src)));
415 }
416
417 // kSrcATop_Mode, //!< [Da, Sc * Da + (1 - Sa) * Dc]
srcatop_modeproc(SkPMColor src,SkPMColor dst)418 static SkPMColor srcatop_modeproc(SkPMColor src, SkPMColor dst) {
419 unsigned sa = SkGetPackedA32(src);
420 unsigned da = SkGetPackedA32(dst);
421 unsigned isa = 255 - sa;
422
423 return SkPackARGB32(da,
424 SkAlphaMulAlpha(da, SkGetPackedR32(src)) +
425 SkAlphaMulAlpha(isa, SkGetPackedR32(dst)),
426 SkAlphaMulAlpha(da, SkGetPackedG32(src)) +
427 SkAlphaMulAlpha(isa, SkGetPackedG32(dst)),
428 SkAlphaMulAlpha(da, SkGetPackedB32(src)) +
429 SkAlphaMulAlpha(isa, SkGetPackedB32(dst)));
430 }
431
432 // kDstATop_Mode, //!< [Sa, Sa * Dc + Sc * (1 - Da)]
dstatop_modeproc(SkPMColor src,SkPMColor dst)433 static SkPMColor dstatop_modeproc(SkPMColor src, SkPMColor dst) {
434 unsigned sa = SkGetPackedA32(src);
435 unsigned da = SkGetPackedA32(dst);
436 unsigned ida = 255 - da;
437
438 return SkPackARGB32(sa,
439 SkAlphaMulAlpha(ida, SkGetPackedR32(src)) +
440 SkAlphaMulAlpha(sa, SkGetPackedR32(dst)),
441 SkAlphaMulAlpha(ida, SkGetPackedG32(src)) +
442 SkAlphaMulAlpha(sa, SkGetPackedG32(dst)),
443 SkAlphaMulAlpha(ida, SkGetPackedB32(src)) +
444 SkAlphaMulAlpha(sa, SkGetPackedB32(dst)));
445 }
446
447 // kXor_Mode [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc]
xor_modeproc(SkPMColor src,SkPMColor dst)448 static SkPMColor xor_modeproc(SkPMColor src, SkPMColor dst) {
449 unsigned sa = SkGetPackedA32(src);
450 unsigned da = SkGetPackedA32(dst);
451 unsigned isa = 255 - sa;
452 unsigned ida = 255 - da;
453
454 return SkPackARGB32(sa + da - (SkAlphaMulAlpha(sa, da) << 1),
455 SkAlphaMulAlpha(ida, SkGetPackedR32(src)) +
456 SkAlphaMulAlpha(isa, SkGetPackedR32(dst)),
457 SkAlphaMulAlpha(ida, SkGetPackedG32(src)) +
458 SkAlphaMulAlpha(isa, SkGetPackedG32(dst)),
459 SkAlphaMulAlpha(ida, SkGetPackedB32(src)) +
460 SkAlphaMulAlpha(isa, SkGetPackedB32(dst)));
461 }
462
463 ///////////////////////////////////////////////////////////////////////////////
464
465 // kPlus_Mode
plus_modeproc(SkPMColor src,SkPMColor dst)466 static SkPMColor plus_modeproc(SkPMColor src, SkPMColor dst) {
467 unsigned b = saturated_add(SkGetPackedB32(src), SkGetPackedB32(dst));
468 unsigned g = saturated_add(SkGetPackedG32(src), SkGetPackedG32(dst));
469 unsigned r = saturated_add(SkGetPackedR32(src), SkGetPackedR32(dst));
470 unsigned a = saturated_add(SkGetPackedA32(src), SkGetPackedA32(dst));
471 return SkPackARGB32(a, r, g, b);
472 }
473
474 // kModulate_Mode
modulate_modeproc(SkPMColor src,SkPMColor dst)475 static SkPMColor modulate_modeproc(SkPMColor src, SkPMColor dst) {
476 int a = SkAlphaMulAlpha(SkGetPackedA32(src), SkGetPackedA32(dst));
477 int r = SkAlphaMulAlpha(SkGetPackedR32(src), SkGetPackedR32(dst));
478 int g = SkAlphaMulAlpha(SkGetPackedG32(src), SkGetPackedG32(dst));
479 int b = SkAlphaMulAlpha(SkGetPackedB32(src), SkGetPackedB32(dst));
480 return SkPackARGB32(a, r, g, b);
481 }
482
srcover_byte(int a,int b)483 static inline int srcover_byte(int a, int b) {
484 return a + b - SkAlphaMulAlpha(a, b);
485 }
486
487 // kMultiply_Mode
488 // B(Cb, Cs) = Cb x Cs
489 // 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)490 static int blendfunc_multiply_byte(int sc, int dc, int sa, int da) {
491 return clamp_div255round(sc * (255 - da) + dc * (255 - sa) + sc * dc);
492 }
493
multiply_modeproc(SkPMColor src,SkPMColor dst)494 static SkPMColor multiply_modeproc(SkPMColor src, SkPMColor dst) {
495 int sa = SkGetPackedA32(src);
496 int da = SkGetPackedA32(dst);
497 int a = srcover_byte(sa, da);
498 int r = blendfunc_multiply_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
499 int g = blendfunc_multiply_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
500 int b = blendfunc_multiply_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
501 return SkPackARGB32(a, r, g, b);
502 }
503
504 // kScreen_Mode
screen_modeproc(SkPMColor src,SkPMColor dst)505 static SkPMColor screen_modeproc(SkPMColor src, SkPMColor dst) {
506 int a = srcover_byte(SkGetPackedA32(src), SkGetPackedA32(dst));
507 int r = srcover_byte(SkGetPackedR32(src), SkGetPackedR32(dst));
508 int g = srcover_byte(SkGetPackedG32(src), SkGetPackedG32(dst));
509 int b = srcover_byte(SkGetPackedB32(src), SkGetPackedB32(dst));
510 return SkPackARGB32(a, r, g, b);
511 }
512
513 // kOverlay_Mode
overlay_byte(int sc,int dc,int sa,int da)514 static inline int overlay_byte(int sc, int dc, int sa, int da) {
515 int tmp = sc * (255 - da) + dc * (255 - sa);
516 int rc;
517 if (2 * dc <= da) {
518 rc = 2 * sc * dc;
519 } else {
520 rc = sa * da - 2 * (da - dc) * (sa - sc);
521 }
522 return clamp_div255round(rc + tmp);
523 }
overlay_modeproc(SkPMColor src,SkPMColor dst)524 static SkPMColor overlay_modeproc(SkPMColor src, SkPMColor dst) {
525 int sa = SkGetPackedA32(src);
526 int da = SkGetPackedA32(dst);
527 int a = srcover_byte(sa, da);
528 int r = overlay_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
529 int g = overlay_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
530 int b = overlay_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
531 return SkPackARGB32(a, r, g, b);
532 }
533
534 // kDarken_Mode
darken_byte(int sc,int dc,int sa,int da)535 static inline int darken_byte(int sc, int dc, int sa, int da) {
536 int sd = sc * da;
537 int ds = dc * sa;
538 if (sd < ds) {
539 // srcover
540 return sc + dc - SkDiv255Round(ds);
541 } else {
542 // dstover
543 return dc + sc - SkDiv255Round(sd);
544 }
545 }
darken_modeproc(SkPMColor src,SkPMColor dst)546 static SkPMColor darken_modeproc(SkPMColor src, SkPMColor dst) {
547 int sa = SkGetPackedA32(src);
548 int da = SkGetPackedA32(dst);
549 int a = srcover_byte(sa, da);
550 int r = darken_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
551 int g = darken_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
552 int b = darken_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
553 return SkPackARGB32(a, r, g, b);
554 }
555
556 // kLighten_Mode
lighten_byte(int sc,int dc,int sa,int da)557 static inline int lighten_byte(int sc, int dc, int sa, int da) {
558 int sd = sc * da;
559 int ds = dc * sa;
560 if (sd > ds) {
561 // srcover
562 return sc + dc - SkDiv255Round(ds);
563 } else {
564 // dstover
565 return dc + sc - SkDiv255Round(sd);
566 }
567 }
lighten_modeproc(SkPMColor src,SkPMColor dst)568 static SkPMColor lighten_modeproc(SkPMColor src, SkPMColor dst) {
569 int sa = SkGetPackedA32(src);
570 int da = SkGetPackedA32(dst);
571 int a = srcover_byte(sa, da);
572 int r = lighten_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
573 int g = lighten_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
574 int b = lighten_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
575 return SkPackARGB32(a, r, g, b);
576 }
577
578 // kColorDodge_Mode
colordodge_byte(int sc,int dc,int sa,int da)579 static inline int colordodge_byte(int sc, int dc, int sa, int da) {
580 int diff = sa - sc;
581 int rc;
582 if (0 == dc) {
583 return SkAlphaMulAlpha(sc, 255 - da);
584 } else if (0 == diff) {
585 rc = sa * da + sc * (255 - da) + dc * (255 - sa);
586 } else {
587 diff = dc * sa / diff;
588 rc = sa * ((da < diff) ? da : diff) + sc * (255 - da) + dc * (255 - sa);
589 }
590 return clamp_div255round(rc);
591 }
colordodge_modeproc(SkPMColor src,SkPMColor dst)592 static SkPMColor colordodge_modeproc(SkPMColor src, SkPMColor dst) {
593 int sa = SkGetPackedA32(src);
594 int da = SkGetPackedA32(dst);
595 int a = srcover_byte(sa, da);
596 int r = colordodge_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
597 int g = colordodge_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
598 int b = colordodge_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
599 return SkPackARGB32(a, r, g, b);
600 }
601
602 // kColorBurn_Mode
colorburn_byte(int sc,int dc,int sa,int da)603 static inline int colorburn_byte(int sc, int dc, int sa, int da) {
604 int rc;
605 if (dc == da) {
606 rc = sa * da + sc * (255 - da) + dc * (255 - sa);
607 } else if (0 == sc) {
608 return SkAlphaMulAlpha(dc, 255 - sa);
609 } else {
610 int tmp = (da - dc) * sa / sc;
611 rc = sa * (da - ((da < tmp) ? da : tmp))
612 + sc * (255 - da) + dc * (255 - sa);
613 }
614 return clamp_div255round(rc);
615 }
colorburn_modeproc(SkPMColor src,SkPMColor dst)616 static SkPMColor colorburn_modeproc(SkPMColor src, SkPMColor dst) {
617 int sa = SkGetPackedA32(src);
618 int da = SkGetPackedA32(dst);
619 int a = srcover_byte(sa, da);
620 int r = colorburn_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
621 int g = colorburn_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
622 int b = colorburn_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
623 return SkPackARGB32(a, r, g, b);
624 }
625
626 // kHardLight_Mode
hardlight_byte(int sc,int dc,int sa,int da)627 static inline int hardlight_byte(int sc, int dc, int sa, int da) {
628 int rc;
629 if (2 * sc <= sa) {
630 rc = 2 * sc * dc;
631 } else {
632 rc = sa * da - 2 * (da - dc) * (sa - sc);
633 }
634 return clamp_div255round(rc + sc * (255 - da) + dc * (255 - sa));
635 }
hardlight_modeproc(SkPMColor src,SkPMColor dst)636 static SkPMColor hardlight_modeproc(SkPMColor src, SkPMColor dst) {
637 int sa = SkGetPackedA32(src);
638 int da = SkGetPackedA32(dst);
639 int a = srcover_byte(sa, da);
640 int r = hardlight_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
641 int g = hardlight_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
642 int b = hardlight_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
643 return SkPackARGB32(a, r, g, b);
644 }
645
646 // returns 255 * sqrt(n/255)
sqrt_unit_byte(U8CPU n)647 static U8CPU sqrt_unit_byte(U8CPU n) {
648 return SkSqrtBits(n, 15+4);
649 }
650
651 // kSoftLight_Mode
softlight_byte(int sc,int dc,int sa,int da)652 static inline int softlight_byte(int sc, int dc, int sa, int da) {
653 int m = da ? dc * 256 / da : 0;
654 int rc;
655 if (2 * sc <= sa) {
656 rc = dc * (sa + ((2 * sc - sa) * (256 - m) >> 8));
657 } else if (4 * dc <= da) {
658 int tmp = (4 * m * (4 * m + 256) * (m - 256) >> 16) + 7 * m;
659 rc = dc * sa + (da * (2 * sc - sa) * tmp >> 8);
660 } else {
661 int tmp = sqrt_unit_byte(m) - m;
662 rc = dc * sa + (da * (2 * sc - sa) * tmp >> 8);
663 }
664 return clamp_div255round(rc + sc * (255 - da) + dc * (255 - sa));
665 }
softlight_modeproc(SkPMColor src,SkPMColor dst)666 static SkPMColor softlight_modeproc(SkPMColor src, SkPMColor dst) {
667 int sa = SkGetPackedA32(src);
668 int da = SkGetPackedA32(dst);
669 int a = srcover_byte(sa, da);
670 int r = softlight_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
671 int g = softlight_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
672 int b = softlight_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
673 return SkPackARGB32(a, r, g, b);
674 }
675
676 // kDifference_Mode
difference_byte(int sc,int dc,int sa,int da)677 static inline int difference_byte(int sc, int dc, int sa, int da) {
678 int tmp = SkMin32(sc * da, dc * sa);
679 return clamp_signed_byte(sc + dc - 2 * SkDiv255Round(tmp));
680 }
difference_modeproc(SkPMColor src,SkPMColor dst)681 static SkPMColor difference_modeproc(SkPMColor src, SkPMColor dst) {
682 int sa = SkGetPackedA32(src);
683 int da = SkGetPackedA32(dst);
684 int a = srcover_byte(sa, da);
685 int r = difference_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
686 int g = difference_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
687 int b = difference_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
688 return SkPackARGB32(a, r, g, b);
689 }
690
691 // kExclusion_Mode
exclusion_byte(int sc,int dc,int,int)692 static inline int exclusion_byte(int sc, int dc, int, int) {
693 // this equations is wacky, wait for SVG to confirm it
694 //int r = sc * da + dc * sa - 2 * sc * dc + sc * (255 - da) + dc * (255 - sa);
695
696 // The above equation can be simplified as follows
697 int r = 255*(sc + dc) - 2 * sc * dc;
698 return clamp_div255round(r);
699 }
exclusion_modeproc(SkPMColor src,SkPMColor dst)700 static SkPMColor exclusion_modeproc(SkPMColor src, SkPMColor dst) {
701 int sa = SkGetPackedA32(src);
702 int da = SkGetPackedA32(dst);
703 int a = srcover_byte(sa, da);
704 int r = exclusion_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
705 int g = exclusion_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
706 int b = exclusion_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
707 return SkPackARGB32(a, r, g, b);
708 }
709
710 // The CSS compositing spec introduces the following formulas:
711 // (See https://dvcs.w3.org/hg/FXTF/rawfile/tip/compositing/index.html#blendingnonseparable)
712 // SkComputeLuminance is similar to this formula but it uses the new definition from Rec. 709
713 // while PDF and CG uses the one from Rec. Rec. 601
714 // 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)715 static inline int Lum(int r, int g, int b)
716 {
717 return SkDiv255Round(r * 77 + g * 150 + b * 28);
718 }
719
min2(int a,int b)720 static inline int min2(int a, int b) { return a < b ? a : b; }
max2(int a,int b)721 static inline int max2(int a, int b) { return a > b ? a : b; }
722 #define minimum(a, b, c) min2(min2(a, b), c)
723 #define maximum(a, b, c) max2(max2(a, b), c)
724
Sat(int r,int g,int b)725 static inline int Sat(int r, int g, int b) {
726 return maximum(r, g, b) - minimum(r, g, b);
727 }
728
setSaturationComponents(int * Cmin,int * Cmid,int * Cmax,int s)729 static inline void setSaturationComponents(int* Cmin, int* Cmid, int* Cmax, int s) {
730 if(*Cmax > *Cmin) {
731 *Cmid = SkMulDiv(*Cmid - *Cmin, s, *Cmax - *Cmin);
732 *Cmax = s;
733 } else {
734 *Cmax = 0;
735 *Cmid = 0;
736 }
737
738 *Cmin = 0;
739 }
740
SetSat(int * r,int * g,int * b,int s)741 static inline void SetSat(int* r, int* g, int* b, int s) {
742 if(*r <= *g) {
743 if(*g <= *b) {
744 setSaturationComponents(r, g, b, s);
745 } else if(*r <= *b) {
746 setSaturationComponents(r, b, g, s);
747 } else {
748 setSaturationComponents(b, r, g, s);
749 }
750 } else if(*r <= *b) {
751 setSaturationComponents(g, r, b, s);
752 } else if(*g <= *b) {
753 setSaturationComponents(g, b, r, s);
754 } else {
755 setSaturationComponents(b, g, r, s);
756 }
757 }
758
clipColor(int * r,int * g,int * b,int a)759 static inline void clipColor(int* r, int* g, int* b, int a) {
760 int L = Lum(*r, *g, *b);
761 int n = minimum(*r, *g, *b);
762 int x = maximum(*r, *g, *b);
763 int denom;
764 if ((n < 0) && (denom = L - n)) { // Compute denom and make sure it's non zero
765 *r = L + SkMulDiv(*r - L, L, denom);
766 *g = L + SkMulDiv(*g - L, L, denom);
767 *b = L + SkMulDiv(*b - L, L, denom);
768 }
769
770 if ((x > a) && (denom = x - L)) { // Compute denom and make sure it's non zero
771 int numer = a - L;
772 *r = L + SkMulDiv(*r - L, numer, denom);
773 *g = L + SkMulDiv(*g - L, numer, denom);
774 *b = L + SkMulDiv(*b - L, numer, denom);
775 }
776 }
777
SetLum(int * r,int * g,int * b,int a,int l)778 static inline void SetLum(int* r, int* g, int* b, int a, int l) {
779 int d = l - Lum(*r, *g, *b);
780 *r += d;
781 *g += d;
782 *b += d;
783
784 clipColor(r, g, b, a);
785 }
786
787 // non-separable blend modes are done in non-premultiplied alpha
788 #define blendfunc_nonsep_byte(sc, dc, sa, da, blendval) \
789 clamp_div255round(sc * (255 - da) + dc * (255 - sa) + blendval)
790
791 // kHue_Mode
792 // B(Cb, Cs) = SetLum(SetSat(Cs, Sat(Cb)), Lum(Cb))
793 // 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)794 static SkPMColor hue_modeproc(SkPMColor src, SkPMColor dst) {
795 int sr = SkGetPackedR32(src);
796 int sg = SkGetPackedG32(src);
797 int sb = SkGetPackedB32(src);
798 int sa = SkGetPackedA32(src);
799
800 int dr = SkGetPackedR32(dst);
801 int dg = SkGetPackedG32(dst);
802 int db = SkGetPackedB32(dst);
803 int da = SkGetPackedA32(dst);
804 int Sr, Sg, Sb;
805
806 if(sa && da) {
807 Sr = sr * sa;
808 Sg = sg * sa;
809 Sb = sb * sa;
810 SetSat(&Sr, &Sg, &Sb, Sat(dr, dg, db) * sa);
811 SetLum(&Sr, &Sg, &Sb, sa * da, Lum(dr, dg, db) * sa);
812 } else {
813 Sr = 0;
814 Sg = 0;
815 Sb = 0;
816 }
817
818 int a = srcover_byte(sa, da);
819 int r = blendfunc_nonsep_byte(sr, dr, sa, da, Sr);
820 int g = blendfunc_nonsep_byte(sg, dg, sa, da, Sg);
821 int b = blendfunc_nonsep_byte(sb, db, sa, da, Sb);
822 return SkPackARGB32(a, r, g, b);
823 }
824
825 // kSaturation_Mode
826 // B(Cb, Cs) = SetLum(SetSat(Cb, Sat(Cs)), Lum(Cb))
827 // 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)828 static SkPMColor saturation_modeproc(SkPMColor src, SkPMColor dst) {
829 int sr = SkGetPackedR32(src);
830 int sg = SkGetPackedG32(src);
831 int sb = SkGetPackedB32(src);
832 int sa = SkGetPackedA32(src);
833
834 int dr = SkGetPackedR32(dst);
835 int dg = SkGetPackedG32(dst);
836 int db = SkGetPackedB32(dst);
837 int da = SkGetPackedA32(dst);
838 int Dr, Dg, Db;
839
840 if(sa && da) {
841 Dr = dr * sa;
842 Dg = dg * sa;
843 Db = db * sa;
844 SetSat(&Dr, &Dg, &Db, Sat(sr, sg, sb) * da);
845 SetLum(&Dr, &Dg, &Db, sa * da, Lum(dr, dg, db) * sa);
846 } else {
847 Dr = 0;
848 Dg = 0;
849 Db = 0;
850 }
851
852 int a = srcover_byte(sa, da);
853 int r = blendfunc_nonsep_byte(sr, dr, sa, da, Dr);
854 int g = blendfunc_nonsep_byte(sg, dg, sa, da, Dg);
855 int b = blendfunc_nonsep_byte(sb, db, sa, da, Db);
856 return SkPackARGB32(a, r, g, b);
857 }
858
859 // kColor_Mode
860 // B(Cb, Cs) = SetLum(Cs, Lum(Cb))
861 // 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)862 static SkPMColor color_modeproc(SkPMColor src, SkPMColor dst) {
863 int sr = SkGetPackedR32(src);
864 int sg = SkGetPackedG32(src);
865 int sb = SkGetPackedB32(src);
866 int sa = SkGetPackedA32(src);
867
868 int dr = SkGetPackedR32(dst);
869 int dg = SkGetPackedG32(dst);
870 int db = SkGetPackedB32(dst);
871 int da = SkGetPackedA32(dst);
872 int Sr, Sg, Sb;
873
874 if(sa && da) {
875 Sr = sr * da;
876 Sg = sg * da;
877 Sb = sb * da;
878 SetLum(&Sr, &Sg, &Sb, sa * da, Lum(dr, dg, db) * sa);
879 } else {
880 Sr = 0;
881 Sg = 0;
882 Sb = 0;
883 }
884
885 int a = srcover_byte(sa, da);
886 int r = blendfunc_nonsep_byte(sr, dr, sa, da, Sr);
887 int g = blendfunc_nonsep_byte(sg, dg, sa, da, Sg);
888 int b = blendfunc_nonsep_byte(sb, db, sa, da, Sb);
889 return SkPackARGB32(a, r, g, b);
890 }
891
892 // kLuminosity_Mode
893 // B(Cb, Cs) = SetLum(Cb, Lum(Cs))
894 // 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)895 static SkPMColor luminosity_modeproc(SkPMColor src, SkPMColor dst) {
896 int sr = SkGetPackedR32(src);
897 int sg = SkGetPackedG32(src);
898 int sb = SkGetPackedB32(src);
899 int sa = SkGetPackedA32(src);
900
901 int dr = SkGetPackedR32(dst);
902 int dg = SkGetPackedG32(dst);
903 int db = SkGetPackedB32(dst);
904 int da = SkGetPackedA32(dst);
905 int Dr, Dg, Db;
906
907 if(sa && da) {
908 Dr = dr * sa;
909 Dg = dg * sa;
910 Db = db * sa;
911 SetLum(&Dr, &Dg, &Db, sa * da, Lum(sr, sg, sb) * da);
912 } else {
913 Dr = 0;
914 Dg = 0;
915 Db = 0;
916 }
917
918 int a = srcover_byte(sa, da);
919 int r = blendfunc_nonsep_byte(sr, dr, sa, da, Dr);
920 int g = blendfunc_nonsep_byte(sg, dg, sa, da, Dg);
921 int b = blendfunc_nonsep_byte(sb, db, sa, da, Db);
922 return SkPackARGB32(a, r, g, b);
923 }
924
925 ///////////////////////////////////////////////////////////////////////////////////////////////////
926
as_pm4f(const Sk4f & x)927 static SkPM4f as_pm4f(const Sk4f& x) {
928 SkPM4f pm4;
929 x.store(pm4.fVec);
930 return pm4;
931 }
932
as_4f(const SkPM4f & pm4)933 static Sk4f as_4f(const SkPM4f& pm4) {
934 return Sk4f::Load(pm4.fVec);
935 }
936
assert_unit(const SkPM4f & r)937 static void assert_unit(const SkPM4f& r) {
938 #ifdef SK_DEBUG
939 const float eps = 0.00001f;
940 const float min = 0 - eps;
941 const float max = 1 + eps;
942 for (int i = 0; i < 4; ++i) {
943 SkASSERT(r.fVec[i] >= min && r.fVec[i] <= max);
944 }
945 #endif
946 }
947
proc_4f(const SkPM4f & s,const SkPM4f & d)948 template <Sk4f (blend)(const Sk4f&, const Sk4f&)> SkPM4f proc_4f(const SkPM4f& s, const SkPM4f& d) {
949 assert_unit(s);
950 assert_unit(d);
951 SkPM4f r = as_pm4f(blend(as_4f(s), as_4f(d)));
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 sk_sp<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(fMode);
1113 }
1114
asMode(Mode * mode) const1115 bool SkProcCoeffXfermode::asMode(Mode* mode) const {
1116 if (mode) {
1117 *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 sk_sp<GrXPFactory> SkProcCoeffXfermode::asXPFactory() const {
1258 if (CANNOT_USE_COEFF != fSrcCoeff) {
1259 sk_sp<GrXPFactory> result(GrPorterDuffXPFactory::Make(fMode));
1260 SkASSERT(result);
1261 return result;
1262 }
1263
1264 SkASSERT(GrCustomXfermode::IsSupportedMode(fMode));
1265 return GrCustomXfermode::MakeXPFactory(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
1282 #ifndef SK_IGNORE_TO_STRING
toString(SkString * str) const1283 void SkProcCoeffXfermode::toString(SkString* str) const {
1284 str->append("SkProcCoeffXfermode: ");
1285
1286 str->append("mode: ");
1287 str->append(ModeName(fMode));
1288
1289 static const char* gCoeffStrings[kCoeffCount] = {
1290 "Zero", "One", "SC", "ISC", "DC", "IDC", "SA", "ISA", "DA", "IDA"
1291 };
1292
1293 str->append(" src: ");
1294 if (CANNOT_USE_COEFF == fSrcCoeff) {
1295 str->append("can't use");
1296 } else {
1297 str->append(gCoeffStrings[fSrcCoeff]);
1298 }
1299
1300 str->append(" dst: ");
1301 if (CANNOT_USE_COEFF == fDstCoeff) {
1302 str->append("can't use");
1303 } else {
1304 str->append(gCoeffStrings[fDstCoeff]);
1305 }
1306 }
1307 #endif
1308
1309
Make(Mode mode)1310 sk_sp<SkXfermode> SkXfermode::Make(Mode mode) {
1311 if ((unsigned)mode >= kModeCount) {
1312 // report error
1313 return nullptr;
1314 }
1315
1316 // Skia's "default" mode is srcover. nullptr in SkPaint is interpreted as srcover
1317 // so we can just return nullptr from the factory.
1318 if (kSrcOver_Mode == mode) {
1319 return nullptr;
1320 }
1321
1322 SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount);
1323
1324 static SkOnce once[SkXfermode::kLastMode+1];
1325 static SkXfermode* cached[SkXfermode::kLastMode+1];
1326
1327 once[mode]([mode] {
1328 ProcCoeff rec = gProcCoeffs[mode];
1329 if (auto xfermode = SkOpts::create_xfermode(rec, mode)) {
1330 cached[mode] = xfermode;
1331 } else {
1332 cached[mode] = new SkProcCoeffXfermode(rec, mode);
1333 }
1334 });
1335 return sk_ref_sp(cached[mode]);
1336 }
1337
GetProc(Mode mode)1338 SkXfermodeProc SkXfermode::GetProc(Mode mode) {
1339 SkXfermodeProc proc = nullptr;
1340 if ((unsigned)mode < kModeCount) {
1341 proc = gProcCoeffs[mode].fProc;
1342 }
1343 return proc;
1344 }
1345
GetProc4f(Mode mode)1346 SkXfermodeProc4f SkXfermode::GetProc4f(Mode mode) {
1347 SkXfermodeProc4f proc = nullptr;
1348 if ((unsigned)mode < kModeCount) {
1349 proc = gProcCoeffs[mode].fProc4f;
1350 }
1351 return proc;
1352 }
1353
missing_proc4f(const SkPM4f & src,const SkPM4f & dst)1354 static SkPM4f missing_proc4f(const SkPM4f& src, const SkPM4f& dst) {
1355 return src;
1356 }
1357
getProc4f() const1358 SkXfermodeProc4f SkXfermode::getProc4f() const {
1359 Mode mode;
1360 return this->asMode(&mode) ? GetProc4f(mode) : missing_proc4f;
1361 }
1362
ModeAsCoeff(Mode mode,Coeff * src,Coeff * dst)1363 bool SkXfermode::ModeAsCoeff(Mode mode, Coeff* src, Coeff* dst) {
1364 SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount);
1365
1366 if ((unsigned)mode >= (unsigned)kModeCount) {
1367 // illegal mode parameter
1368 return false;
1369 }
1370
1371 const ProcCoeff& rec = gProcCoeffs[mode];
1372
1373 if (CANNOT_USE_COEFF == rec.fSC) {
1374 return false;
1375 }
1376
1377 SkASSERT(CANNOT_USE_COEFF != rec.fDC);
1378 if (src) {
1379 *src = rec.fSC;
1380 }
1381 if (dst) {
1382 *dst = rec.fDC;
1383 }
1384 return true;
1385 }
1386
AsMode(const SkXfermode * xfer,Mode * mode)1387 bool SkXfermode::AsMode(const SkXfermode* xfer, Mode* mode) {
1388 if (nullptr == xfer) {
1389 if (mode) {
1390 *mode = kSrcOver_Mode;
1391 }
1392 return true;
1393 }
1394 return xfer->asMode(mode);
1395 }
1396
IsMode(const SkXfermode * xfer,Mode mode)1397 bool SkXfermode::IsMode(const SkXfermode* xfer, Mode mode) {
1398 // if xfer==null then the mode is srcover
1399 Mode m = kSrcOver_Mode;
1400 if (xfer && !xfer->asMode(&m)) {
1401 return false;
1402 }
1403 return mode == m;
1404 }
1405
SupportsCoverageAsAlpha(const SkXfermode * xfer)1406 bool SkXfermode::SupportsCoverageAsAlpha(const SkXfermode* xfer) {
1407 // if xfer is nullptr we treat it as srcOver which always supports coverageAsAlpha
1408 if (!xfer) {
1409 return true;
1410 }
1411
1412 return xfer->supportsCoverageAsAlpha();
1413 }
1414
IsOpaque(const SkXfermode * xfer,SrcColorOpacity opacityType)1415 bool SkXfermode::IsOpaque(const SkXfermode* xfer, SrcColorOpacity opacityType) {
1416 // if xfer is nullptr we treat it as srcOver which is opaque if our src is opaque
1417 if (!xfer) {
1418 return SkXfermode::kOpaque_SrcColorOpacity == opacityType;
1419 }
1420
1421 return xfer->isOpaque(opacityType);
1422 }
1423
appendStages(SkRasterPipeline * pipeline) const1424 bool SkXfermode::appendStages(SkRasterPipeline* pipeline) const {
1425 return this->onAppendStages(pipeline);
1426 }
1427
onAppendStages(SkRasterPipeline *) const1428 bool SkXfermode::onAppendStages(SkRasterPipeline*) const {
1429 return false;
1430 }
1431
1432 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkXfermode)
SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkProcCoeffXfermode)1433 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkProcCoeffXfermode)
1434 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
1435
1436
1437 bool SkProcCoeffXfermode::onAppendStages(SkRasterPipeline* p) const {
1438 switch (fMode) {
1439 case kSrc_Mode: /*This stage is a no-op.*/ return true;
1440 case kDst_Mode: p->append(SkRasterPipeline::dst); return true;
1441 case kSrcATop_Mode: p->append(SkRasterPipeline::srcatop); return true;
1442 case kDstATop_Mode: p->append(SkRasterPipeline::dstatop); return true;
1443 case kSrcIn_Mode: p->append(SkRasterPipeline::srcin); return true;
1444 case kDstIn_Mode: p->append(SkRasterPipeline::dstin); return true;
1445 case kSrcOut_Mode: p->append(SkRasterPipeline::srcout); return true;
1446 case kDstOut_Mode: p->append(SkRasterPipeline::dstout); return true;
1447 case kSrcOver_Mode: p->append(SkRasterPipeline::srcover); return true;
1448 case kDstOver_Mode: p->append(SkRasterPipeline::dstover); return true;
1449
1450 case kClear_Mode: p->append(SkRasterPipeline::clear); return true;
1451 case kModulate_Mode: p->append(SkRasterPipeline::modulate); return true;
1452 case kMultiply_Mode: p->append(SkRasterPipeline::multiply); return true;
1453 case kPlus_Mode: p->append(SkRasterPipeline::plus_); return true;
1454 case kScreen_Mode: p->append(SkRasterPipeline::screen); return true;
1455 case kXor_Mode: p->append(SkRasterPipeline::xor_); return true;
1456
1457 case kColorBurn_Mode: p->append(SkRasterPipeline::colorburn); return true;
1458 case kColorDodge_Mode: p->append(SkRasterPipeline::colordodge); return true;
1459 case kDarken_Mode: p->append(SkRasterPipeline::darken); return true;
1460 case kDifference_Mode: p->append(SkRasterPipeline::difference); return true;
1461 case kExclusion_Mode: p->append(SkRasterPipeline::exclusion); return true;
1462 case kHardLight_Mode: p->append(SkRasterPipeline::hardlight); return true;
1463 case kLighten_Mode: p->append(SkRasterPipeline::lighten); return true;
1464 case kOverlay_Mode: p->append(SkRasterPipeline::overlay); return true;
1465 case kSoftLight_Mode: p->append(SkRasterPipeline::softlight); return true;
1466
1467 // TODO
1468 case kColor_Mode: return false;
1469 case kHue_Mode: return false;
1470 case kLuminosity_Mode: return false;
1471 case kSaturation_Mode: return false;
1472 }
1473 return false;
1474 }
1475
1476 ///////////////////////////////////////////////////////////////////////////////////////////////////
1477
SkBlendMode_SupportsCoverageAsAlpha(SkBlendMode mode)1478 bool SkBlendMode_SupportsCoverageAsAlpha(SkBlendMode mode) {
1479 switch (mode) {
1480 case SkBlendMode::kDst:
1481 case SkBlendMode::kSrcOver:
1482 case SkBlendMode::kDstOver:
1483 case SkBlendMode::kDstOut:
1484 case SkBlendMode::kSrcATop:
1485 case SkBlendMode::kXor:
1486 case SkBlendMode::kPlus:
1487 return true;
1488 default:
1489 break;
1490 }
1491 return false;
1492 }
1493
IsOpaque(SkBlendMode mode,SrcColorOpacity opacityType)1494 bool SkXfermode::IsOpaque(SkBlendMode mode, SrcColorOpacity opacityType) {
1495 const ProcCoeff rec = gProcCoeffs[(int)mode];
1496
1497 switch (rec.fSC) {
1498 case kDA_Coeff:
1499 case kDC_Coeff:
1500 case kIDA_Coeff:
1501 case kIDC_Coeff:
1502 return false;
1503 default:
1504 break;
1505 }
1506
1507 switch (rec.fDC) {
1508 case kZero_Coeff:
1509 return true;
1510 case kISA_Coeff:
1511 return kOpaque_SrcColorOpacity == opacityType;
1512 case kSA_Coeff:
1513 return kTransparentBlack_SrcColorOpacity == opacityType ||
1514 kTransparentAlpha_SrcColorOpacity == opacityType;
1515 case kSC_Coeff:
1516 return kTransparentBlack_SrcColorOpacity == opacityType;
1517 default:
1518 return false;
1519 }
1520 return false;
1521 }
1522
1523 #if SK_SUPPORT_GPU
SkBlendMode_AsXPFactory(SkBlendMode mode)1524 sk_sp<GrXPFactory> SkBlendMode_AsXPFactory(SkBlendMode mode) {
1525 const ProcCoeff rec = gProcCoeffs[(int)mode];
1526 if (CANNOT_USE_COEFF != rec.fSC) {
1527 sk_sp<GrXPFactory> result(GrPorterDuffXPFactory::Make(mode));
1528 SkASSERT(result);
1529 return result;
1530 }
1531
1532 SkASSERT(GrCustomXfermode::IsSupportedMode((SkXfermode::Mode)mode));
1533 return GrCustomXfermode::MakeXPFactory((SkXfermode::Mode)mode);
1534 }
1535 #endif
1536