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