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