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