1 
2 /*
3  * Copyright 2006 The Android Open Source Project
4  *
5  * Use of this source code is governed by a BSD-style license that can be
6  * found in the LICENSE file.
7  */
8 
9 #include "SkXfermode.h"
10 #include "SkXfermode_opts_SSE2.h"
11 #include "SkXfermode_proccoeff.h"
12 #include "Sk4px.h"
13 #include "SkColorPriv.h"
14 #include "SkLazyPtr.h"
15 #include "SkMathPriv.h"
16 #include "SkPMFloat.h"
17 #include "SkReadBuffer.h"
18 #include "SkString.h"
19 #include "SkUtilsArm.h"
20 #include "SkWriteBuffer.h"
21 
22 // When implemented, the Sk4f and Sk4px xfermodes beat src/opts/SkXfermodes_opts_SSE2's.
23 // When implemented, the Sk4px, but not Sk4f, xfermodes beat src/opts/SkXfermodes_arm_neon's.
24 #if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2
25     #define SK_4F_XFERMODES_ARE_FAST
26     #define SK_4PX_XFERMODES_ARE_FAST
27 #elif defined(SK_ARM_HAS_NEON)
28     #define SK_4PX_XFERMODES_ARE_FAST
29 #endif
30 
31 #if !SK_ARM_NEON_IS_NONE
32     #include "SkXfermode_opts_arm_neon.h"
33 #endif
34 
35 #define SkAlphaMulAlpha(a, b)   SkMulDiv255Round(a, b)
36 
saturated_add(unsigned a,unsigned b)37 static inline unsigned saturated_add(unsigned a, unsigned b) {
38     SkASSERT(a <= 255);
39     SkASSERT(b <= 255);
40     unsigned sum = a + b;
41     if (sum > 255) {
42         sum = 255;
43     }
44     return sum;
45 }
46 
clamp_signed_byte(int n)47 static inline int clamp_signed_byte(int n) {
48     if (n < 0) {
49         n = 0;
50     } else if (n > 255) {
51         n = 255;
52     }
53     return n;
54 }
55 
clamp_div255round(int prod)56 static inline int clamp_div255round(int prod) {
57     if (prod <= 0) {
58         return 0;
59     } else if (prod >= 255*255) {
60         return 255;
61     } else {
62         return SkDiv255Round(prod);
63     }
64 }
65 
66 ///////////////////////////////////////////////////////////////////////////////
67 
68 //  kClear_Mode,    //!< [0, 0]
clear_modeproc(SkPMColor src,SkPMColor dst)69 static SkPMColor clear_modeproc(SkPMColor src, SkPMColor dst) {
70     return 0;
71 }
72 
73 //  kSrc_Mode,      //!< [Sa, Sc]
src_modeproc(SkPMColor src,SkPMColor dst)74 static SkPMColor src_modeproc(SkPMColor src, SkPMColor dst) {
75     return src;
76 }
77 
78 //  kDst_Mode,      //!< [Da, Dc]
dst_modeproc(SkPMColor src,SkPMColor dst)79 static SkPMColor dst_modeproc(SkPMColor src, SkPMColor dst) {
80     return dst;
81 }
82 
83 //  kSrcOver_Mode,  //!< [Sa + Da - Sa*Da, Sc + (1 - Sa)*Dc]
srcover_modeproc(SkPMColor src,SkPMColor dst)84 static SkPMColor srcover_modeproc(SkPMColor src, SkPMColor dst) {
85 #if 0
86     // this is the old, more-correct way, but it doesn't guarantee that dst==255
87     // will always stay opaque
88     return src + SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src)));
89 #else
90     // this is slightly faster, but more importantly guarantees that dst==255
91     // will always stay opaque
92     return src + SkAlphaMulQ(dst, 256 - SkGetPackedA32(src));
93 #endif
94 }
95 
96 //  kDstOver_Mode,  //!< [Sa + Da - Sa*Da, Dc + (1 - Da)*Sc]
dstover_modeproc(SkPMColor src,SkPMColor dst)97 static SkPMColor dstover_modeproc(SkPMColor src, SkPMColor dst) {
98     // this is the reverse of srcover, just flipping src and dst
99     // see srcover's comment about the 256 for opaqueness guarantees
100     return dst + SkAlphaMulQ(src, 256 - SkGetPackedA32(dst));
101 }
102 
103 //  kSrcIn_Mode,    //!< [Sa * Da, Sc * Da]
srcin_modeproc(SkPMColor src,SkPMColor dst)104 static SkPMColor srcin_modeproc(SkPMColor src, SkPMColor dst) {
105     return SkAlphaMulQ(src, SkAlpha255To256(SkGetPackedA32(dst)));
106 }
107 
108 //  kDstIn_Mode,    //!< [Sa * Da, Sa * Dc]
dstin_modeproc(SkPMColor src,SkPMColor dst)109 static SkPMColor dstin_modeproc(SkPMColor src, SkPMColor dst) {
110     return SkAlphaMulQ(dst, SkAlpha255To256(SkGetPackedA32(src)));
111 }
112 
113 //  kSrcOut_Mode,   //!< [Sa * (1 - Da), Sc * (1 - Da)]
srcout_modeproc(SkPMColor src,SkPMColor dst)114 static SkPMColor srcout_modeproc(SkPMColor src, SkPMColor dst) {
115     return SkAlphaMulQ(src, SkAlpha255To256(255 - SkGetPackedA32(dst)));
116 }
117 
118 //  kDstOut_Mode,   //!< [Da * (1 - Sa), Dc * (1 - Sa)]
dstout_modeproc(SkPMColor src,SkPMColor dst)119 static SkPMColor dstout_modeproc(SkPMColor src, SkPMColor dst) {
120     return SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src)));
121 }
122 
123 //  kSrcATop_Mode,  //!< [Da, Sc * Da + (1 - Sa) * Dc]
srcatop_modeproc(SkPMColor src,SkPMColor dst)124 static SkPMColor srcatop_modeproc(SkPMColor src, SkPMColor dst) {
125     unsigned sa = SkGetPackedA32(src);
126     unsigned da = SkGetPackedA32(dst);
127     unsigned isa = 255 - sa;
128 
129     return SkPackARGB32(da,
130                         SkAlphaMulAlpha(da, SkGetPackedR32(src)) +
131                             SkAlphaMulAlpha(isa, SkGetPackedR32(dst)),
132                         SkAlphaMulAlpha(da, SkGetPackedG32(src)) +
133                             SkAlphaMulAlpha(isa, SkGetPackedG32(dst)),
134                         SkAlphaMulAlpha(da, SkGetPackedB32(src)) +
135                             SkAlphaMulAlpha(isa, SkGetPackedB32(dst)));
136 }
137 
138 //  kDstATop_Mode,  //!< [Sa, Sa * Dc + Sc * (1 - Da)]
dstatop_modeproc(SkPMColor src,SkPMColor dst)139 static SkPMColor dstatop_modeproc(SkPMColor src, SkPMColor dst) {
140     unsigned sa = SkGetPackedA32(src);
141     unsigned da = SkGetPackedA32(dst);
142     unsigned ida = 255 - da;
143 
144     return SkPackARGB32(sa,
145                         SkAlphaMulAlpha(ida, SkGetPackedR32(src)) +
146                             SkAlphaMulAlpha(sa, SkGetPackedR32(dst)),
147                         SkAlphaMulAlpha(ida, SkGetPackedG32(src)) +
148                             SkAlphaMulAlpha(sa, SkGetPackedG32(dst)),
149                         SkAlphaMulAlpha(ida, SkGetPackedB32(src)) +
150                             SkAlphaMulAlpha(sa, SkGetPackedB32(dst)));
151 }
152 
153 //  kXor_Mode   [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc]
xor_modeproc(SkPMColor src,SkPMColor dst)154 static SkPMColor xor_modeproc(SkPMColor src, SkPMColor dst) {
155     unsigned sa = SkGetPackedA32(src);
156     unsigned da = SkGetPackedA32(dst);
157     unsigned isa = 255 - sa;
158     unsigned ida = 255 - da;
159 
160     return SkPackARGB32(sa + da - (SkAlphaMulAlpha(sa, da) << 1),
161                         SkAlphaMulAlpha(ida, SkGetPackedR32(src)) +
162                             SkAlphaMulAlpha(isa, SkGetPackedR32(dst)),
163                         SkAlphaMulAlpha(ida, SkGetPackedG32(src)) +
164                             SkAlphaMulAlpha(isa, SkGetPackedG32(dst)),
165                         SkAlphaMulAlpha(ida, SkGetPackedB32(src)) +
166                             SkAlphaMulAlpha(isa, SkGetPackedB32(dst)));
167 }
168 
169 ///////////////////////////////////////////////////////////////////////////////
170 
171 // kPlus_Mode
plus_modeproc(SkPMColor src,SkPMColor dst)172 static SkPMColor plus_modeproc(SkPMColor src, SkPMColor dst) {
173     unsigned b = saturated_add(SkGetPackedB32(src), SkGetPackedB32(dst));
174     unsigned g = saturated_add(SkGetPackedG32(src), SkGetPackedG32(dst));
175     unsigned r = saturated_add(SkGetPackedR32(src), SkGetPackedR32(dst));
176     unsigned a = saturated_add(SkGetPackedA32(src), SkGetPackedA32(dst));
177     return SkPackARGB32(a, r, g, b);
178 }
179 
180 // kModulate_Mode
modulate_modeproc(SkPMColor src,SkPMColor dst)181 static SkPMColor modulate_modeproc(SkPMColor src, SkPMColor dst) {
182     int a = SkAlphaMulAlpha(SkGetPackedA32(src), SkGetPackedA32(dst));
183     int r = SkAlphaMulAlpha(SkGetPackedR32(src), SkGetPackedR32(dst));
184     int g = SkAlphaMulAlpha(SkGetPackedG32(src), SkGetPackedG32(dst));
185     int b = SkAlphaMulAlpha(SkGetPackedB32(src), SkGetPackedB32(dst));
186     return SkPackARGB32(a, r, g, b);
187 }
188 
srcover_byte(int a,int b)189 static inline int srcover_byte(int a, int b) {
190     return a + b - SkAlphaMulAlpha(a, b);
191 }
192 
193 // kMultiply_Mode
194 // B(Cb, Cs) = Cb x Cs
195 // 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)196 static int blendfunc_multiply_byte(int sc, int dc, int sa, int da) {
197     return clamp_div255round(sc * (255 - da)  + dc * (255 - sa)  + sc * dc);
198 }
199 
multiply_modeproc(SkPMColor src,SkPMColor dst)200 static SkPMColor multiply_modeproc(SkPMColor src, SkPMColor dst) {
201     int sa = SkGetPackedA32(src);
202     int da = SkGetPackedA32(dst);
203     int a = srcover_byte(sa, da);
204     int r = blendfunc_multiply_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
205     int g = blendfunc_multiply_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
206     int b = blendfunc_multiply_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
207     return SkPackARGB32(a, r, g, b);
208 }
209 
210 // kScreen_Mode
screen_modeproc(SkPMColor src,SkPMColor dst)211 static SkPMColor screen_modeproc(SkPMColor src, SkPMColor dst) {
212     int a = srcover_byte(SkGetPackedA32(src), SkGetPackedA32(dst));
213     int r = srcover_byte(SkGetPackedR32(src), SkGetPackedR32(dst));
214     int g = srcover_byte(SkGetPackedG32(src), SkGetPackedG32(dst));
215     int b = srcover_byte(SkGetPackedB32(src), SkGetPackedB32(dst));
216     return SkPackARGB32(a, r, g, b);
217 }
218 
219 // kOverlay_Mode
overlay_byte(int sc,int dc,int sa,int da)220 static inline int overlay_byte(int sc, int dc, int sa, int da) {
221     int tmp = sc * (255 - da) + dc * (255 - sa);
222     int rc;
223     if (2 * dc <= da) {
224         rc = 2 * sc * dc;
225     } else {
226         rc = sa * da - 2 * (da - dc) * (sa - sc);
227     }
228     return clamp_div255round(rc + tmp);
229 }
overlay_modeproc(SkPMColor src,SkPMColor dst)230 static SkPMColor overlay_modeproc(SkPMColor src, SkPMColor dst) {
231     int sa = SkGetPackedA32(src);
232     int da = SkGetPackedA32(dst);
233     int a = srcover_byte(sa, da);
234     int r = overlay_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
235     int g = overlay_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
236     int b = overlay_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
237     return SkPackARGB32(a, r, g, b);
238 }
239 
240 // kDarken_Mode
darken_byte(int sc,int dc,int sa,int da)241 static inline int darken_byte(int sc, int dc, int sa, int da) {
242     int sd = sc * da;
243     int ds = dc * sa;
244     if (sd < ds) {
245         // srcover
246         return sc + dc - SkDiv255Round(ds);
247     } else {
248         // dstover
249         return dc + sc - SkDiv255Round(sd);
250     }
251 }
darken_modeproc(SkPMColor src,SkPMColor dst)252 static SkPMColor darken_modeproc(SkPMColor src, SkPMColor dst) {
253     int sa = SkGetPackedA32(src);
254     int da = SkGetPackedA32(dst);
255     int a = srcover_byte(sa, da);
256     int r = darken_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
257     int g = darken_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
258     int b = darken_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
259     return SkPackARGB32(a, r, g, b);
260 }
261 
262 // kLighten_Mode
lighten_byte(int sc,int dc,int sa,int da)263 static inline int lighten_byte(int sc, int dc, int sa, int da) {
264     int sd = sc * da;
265     int ds = dc * sa;
266     if (sd > ds) {
267         // srcover
268         return sc + dc - SkDiv255Round(ds);
269     } else {
270         // dstover
271         return dc + sc - SkDiv255Round(sd);
272     }
273 }
lighten_modeproc(SkPMColor src,SkPMColor dst)274 static SkPMColor lighten_modeproc(SkPMColor src, SkPMColor dst) {
275     int sa = SkGetPackedA32(src);
276     int da = SkGetPackedA32(dst);
277     int a = srcover_byte(sa, da);
278     int r = lighten_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
279     int g = lighten_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
280     int b = lighten_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
281     return SkPackARGB32(a, r, g, b);
282 }
283 
284 // kColorDodge_Mode
colordodge_byte(int sc,int dc,int sa,int da)285 static inline int colordodge_byte(int sc, int dc, int sa, int da) {
286     int diff = sa - sc;
287     int rc;
288     if (0 == dc) {
289         return SkAlphaMulAlpha(sc, 255 - da);
290     } else if (0 == diff) {
291         rc = sa * da + sc * (255 - da) + dc * (255 - sa);
292     } else {
293         diff = dc * sa / diff;
294         rc = sa * ((da < diff) ? da : diff) + sc * (255 - da) + dc * (255 - sa);
295     }
296     return clamp_div255round(rc);
297 }
colordodge_modeproc(SkPMColor src,SkPMColor dst)298 static SkPMColor colordodge_modeproc(SkPMColor src, SkPMColor dst) {
299     int sa = SkGetPackedA32(src);
300     int da = SkGetPackedA32(dst);
301     int a = srcover_byte(sa, da);
302     int r = colordodge_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
303     int g = colordodge_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
304     int b = colordodge_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
305     return SkPackARGB32(a, r, g, b);
306 }
307 
308 // kColorBurn_Mode
colorburn_byte(int sc,int dc,int sa,int da)309 static inline int colorburn_byte(int sc, int dc, int sa, int da) {
310     int rc;
311     if (dc == da) {
312         rc = sa * da + sc * (255 - da) + dc * (255 - sa);
313     } else if (0 == sc) {
314         return SkAlphaMulAlpha(dc, 255 - sa);
315     } else {
316         int tmp = (da - dc) * sa / sc;
317         rc = sa * (da - ((da < tmp) ? da : tmp))
318             + sc * (255 - da) + dc * (255 - sa);
319     }
320     return clamp_div255round(rc);
321 }
colorburn_modeproc(SkPMColor src,SkPMColor dst)322 static SkPMColor colorburn_modeproc(SkPMColor src, SkPMColor dst) {
323     int sa = SkGetPackedA32(src);
324     int da = SkGetPackedA32(dst);
325     int a = srcover_byte(sa, da);
326     int r = colorburn_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
327     int g = colorburn_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
328     int b = colorburn_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
329     return SkPackARGB32(a, r, g, b);
330 }
331 
332 // kHardLight_Mode
hardlight_byte(int sc,int dc,int sa,int da)333 static inline int hardlight_byte(int sc, int dc, int sa, int da) {
334     int rc;
335     if (2 * sc <= sa) {
336         rc = 2 * sc * dc;
337     } else {
338         rc = sa * da - 2 * (da - dc) * (sa - sc);
339     }
340     return clamp_div255round(rc + sc * (255 - da) + dc * (255 - sa));
341 }
hardlight_modeproc(SkPMColor src,SkPMColor dst)342 static SkPMColor hardlight_modeproc(SkPMColor src, SkPMColor dst) {
343     int sa = SkGetPackedA32(src);
344     int da = SkGetPackedA32(dst);
345     int a = srcover_byte(sa, da);
346     int r = hardlight_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
347     int g = hardlight_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
348     int b = hardlight_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
349     return SkPackARGB32(a, r, g, b);
350 }
351 
352 // returns 255 * sqrt(n/255)
sqrt_unit_byte(U8CPU n)353 static U8CPU sqrt_unit_byte(U8CPU n) {
354     return SkSqrtBits(n, 15+4);
355 }
356 
357 // kSoftLight_Mode
softlight_byte(int sc,int dc,int sa,int da)358 static inline int softlight_byte(int sc, int dc, int sa, int da) {
359     int m = da ? dc * 256 / da : 0;
360     int rc;
361     if (2 * sc <= sa) {
362         rc = dc * (sa + ((2 * sc - sa) * (256 - m) >> 8));
363     } else if (4 * dc <= da) {
364         int tmp = (4 * m * (4 * m + 256) * (m - 256) >> 16) + 7 * m;
365         rc = dc * sa + (da * (2 * sc - sa) * tmp >> 8);
366     } else {
367         int tmp = sqrt_unit_byte(m) - m;
368         rc = dc * sa + (da * (2 * sc - sa) * tmp >> 8);
369     }
370     return clamp_div255round(rc + sc * (255 - da) + dc * (255 - sa));
371 }
softlight_modeproc(SkPMColor src,SkPMColor dst)372 static SkPMColor softlight_modeproc(SkPMColor src, SkPMColor dst) {
373     int sa = SkGetPackedA32(src);
374     int da = SkGetPackedA32(dst);
375     int a = srcover_byte(sa, da);
376     int r = softlight_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
377     int g = softlight_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
378     int b = softlight_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
379     return SkPackARGB32(a, r, g, b);
380 }
381 
382 // kDifference_Mode
difference_byte(int sc,int dc,int sa,int da)383 static inline int difference_byte(int sc, int dc, int sa, int da) {
384     int tmp = SkMin32(sc * da, dc * sa);
385     return clamp_signed_byte(sc + dc - 2 * SkDiv255Round(tmp));
386 }
difference_modeproc(SkPMColor src,SkPMColor dst)387 static SkPMColor difference_modeproc(SkPMColor src, SkPMColor dst) {
388     int sa = SkGetPackedA32(src);
389     int da = SkGetPackedA32(dst);
390     int a = srcover_byte(sa, da);
391     int r = difference_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
392     int g = difference_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
393     int b = difference_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
394     return SkPackARGB32(a, r, g, b);
395 }
396 
397 // kExclusion_Mode
exclusion_byte(int sc,int dc,int,int)398 static inline int exclusion_byte(int sc, int dc, int, int) {
399     // this equations is wacky, wait for SVG to confirm it
400     //int r = sc * da + dc * sa - 2 * sc * dc + sc * (255 - da) + dc * (255 - sa);
401 
402     // The above equation can be simplified as follows
403     int r = 255*(sc + dc) - 2 * sc * dc;
404     return clamp_div255round(r);
405 }
exclusion_modeproc(SkPMColor src,SkPMColor dst)406 static SkPMColor exclusion_modeproc(SkPMColor src, SkPMColor dst) {
407     int sa = SkGetPackedA32(src);
408     int da = SkGetPackedA32(dst);
409     int a = srcover_byte(sa, da);
410     int r = exclusion_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
411     int g = exclusion_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
412     int b = exclusion_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
413     return SkPackARGB32(a, r, g, b);
414 }
415 
416 // The CSS compositing spec introduces the following formulas:
417 // (See https://dvcs.w3.org/hg/FXTF/rawfile/tip/compositing/index.html#blendingnonseparable)
418 // SkComputeLuminance is similar to this formula but it uses the new definition from Rec. 709
419 // while PDF and CG uses the one from Rec. Rec. 601
420 // 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)421 static inline int Lum(int r, int g, int b)
422 {
423     return SkDiv255Round(r * 77 + g * 150 + b * 28);
424 }
425 
min2(int a,int b)426 static inline int min2(int a, int b) { return a < b ? a : b; }
max2(int a,int b)427 static inline int max2(int a, int b) { return a > b ? a : b; }
428 #define minimum(a, b, c) min2(min2(a, b), c)
429 #define maximum(a, b, c) max2(max2(a, b), c)
430 
Sat(int r,int g,int b)431 static inline int Sat(int r, int g, int b) {
432     return maximum(r, g, b) - minimum(r, g, b);
433 }
434 
setSaturationComponents(int * Cmin,int * Cmid,int * Cmax,int s)435 static inline void setSaturationComponents(int* Cmin, int* Cmid, int* Cmax, int s) {
436     if(*Cmax > *Cmin) {
437         *Cmid =  SkMulDiv(*Cmid - *Cmin, s, *Cmax - *Cmin);
438         *Cmax = s;
439     } else {
440         *Cmax = 0;
441         *Cmid = 0;
442     }
443 
444     *Cmin = 0;
445 }
446 
SetSat(int * r,int * g,int * b,int s)447 static inline void SetSat(int* r, int* g, int* b, int s) {
448     if(*r <= *g) {
449         if(*g <= *b) {
450             setSaturationComponents(r, g, b, s);
451         } else if(*r <= *b) {
452             setSaturationComponents(r, b, g, s);
453         } else {
454             setSaturationComponents(b, r, g, s);
455         }
456     } else if(*r <= *b) {
457         setSaturationComponents(g, r, b, s);
458     } else if(*g <= *b) {
459         setSaturationComponents(g, b, r, s);
460     } else {
461         setSaturationComponents(b, g, r, s);
462     }
463 }
464 
clipColor(int * r,int * g,int * b,int a)465 static inline void clipColor(int* r, int* g, int* b, int a) {
466     int L = Lum(*r, *g, *b);
467     int n = minimum(*r, *g, *b);
468     int x = maximum(*r, *g, *b);
469     int denom;
470     if ((n < 0) && (denom = L - n)) { // Compute denom and make sure it's non zero
471        *r = L + SkMulDiv(*r - L, L, denom);
472        *g = L + SkMulDiv(*g - L, L, denom);
473        *b = L + SkMulDiv(*b - L, L, denom);
474     }
475 
476     if ((x > a) && (denom = x - L)) { // Compute denom and make sure it's non zero
477        int numer = a - L;
478        *r = L + SkMulDiv(*r - L, numer, denom);
479        *g = L + SkMulDiv(*g - L, numer, denom);
480        *b = L + SkMulDiv(*b - L, numer, denom);
481     }
482 }
483 
SetLum(int * r,int * g,int * b,int a,int l)484 static inline void SetLum(int* r, int* g, int* b, int a, int l) {
485   int d = l - Lum(*r, *g, *b);
486   *r +=  d;
487   *g +=  d;
488   *b +=  d;
489 
490   clipColor(r, g, b, a);
491 }
492 
493 // non-separable blend modes are done in non-premultiplied alpha
494 #define  blendfunc_nonsep_byte(sc, dc, sa, da, blendval) \
495   clamp_div255round(sc * (255 - da) +  dc * (255 - sa) + blendval)
496 
497 // kHue_Mode
498 // B(Cb, Cs) = SetLum(SetSat(Cs, Sat(Cb)), Lum(Cb))
499 // 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)500 static SkPMColor hue_modeproc(SkPMColor src, SkPMColor dst) {
501     int sr = SkGetPackedR32(src);
502     int sg = SkGetPackedG32(src);
503     int sb = SkGetPackedB32(src);
504     int sa = SkGetPackedA32(src);
505 
506     int dr = SkGetPackedR32(dst);
507     int dg = SkGetPackedG32(dst);
508     int db = SkGetPackedB32(dst);
509     int da = SkGetPackedA32(dst);
510     int Sr, Sg, Sb;
511 
512     if(sa && da) {
513         Sr = sr * sa;
514         Sg = sg * sa;
515         Sb = sb * sa;
516         SetSat(&Sr, &Sg, &Sb, Sat(dr, dg, db) * sa);
517         SetLum(&Sr, &Sg, &Sb, sa * da, Lum(dr, dg, db) * sa);
518     } else {
519         Sr = 0;
520         Sg = 0;
521         Sb = 0;
522     }
523 
524     int a = srcover_byte(sa, da);
525     int r = blendfunc_nonsep_byte(sr, dr, sa, da, Sr);
526     int g = blendfunc_nonsep_byte(sg, dg, sa, da, Sg);
527     int b = blendfunc_nonsep_byte(sb, db, sa, da, Sb);
528     return SkPackARGB32(a, r, g, b);
529 }
530 
531 // kSaturation_Mode
532 // B(Cb, Cs) = SetLum(SetSat(Cb, Sat(Cs)), Lum(Cb))
533 // 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)534 static SkPMColor saturation_modeproc(SkPMColor src, SkPMColor dst) {
535     int sr = SkGetPackedR32(src);
536     int sg = SkGetPackedG32(src);
537     int sb = SkGetPackedB32(src);
538     int sa = SkGetPackedA32(src);
539 
540     int dr = SkGetPackedR32(dst);
541     int dg = SkGetPackedG32(dst);
542     int db = SkGetPackedB32(dst);
543     int da = SkGetPackedA32(dst);
544     int Dr, Dg, Db;
545 
546     if(sa && da) {
547         Dr = dr * sa;
548         Dg = dg * sa;
549         Db = db * sa;
550         SetSat(&Dr, &Dg, &Db, Sat(sr, sg, sb) * da);
551         SetLum(&Dr, &Dg, &Db, sa * da, Lum(dr, dg, db) * sa);
552     } else {
553         Dr = 0;
554         Dg = 0;
555         Db = 0;
556     }
557 
558     int a = srcover_byte(sa, da);
559     int r = blendfunc_nonsep_byte(sr, dr, sa, da, Dr);
560     int g = blendfunc_nonsep_byte(sg, dg, sa, da, Dg);
561     int b = blendfunc_nonsep_byte(sb, db, sa, da, Db);
562     return SkPackARGB32(a, r, g, b);
563 }
564 
565 // kColor_Mode
566 // B(Cb, Cs) = SetLum(Cs, Lum(Cb))
567 // 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)568 static SkPMColor color_modeproc(SkPMColor src, SkPMColor dst) {
569     int sr = SkGetPackedR32(src);
570     int sg = SkGetPackedG32(src);
571     int sb = SkGetPackedB32(src);
572     int sa = SkGetPackedA32(src);
573 
574     int dr = SkGetPackedR32(dst);
575     int dg = SkGetPackedG32(dst);
576     int db = SkGetPackedB32(dst);
577     int da = SkGetPackedA32(dst);
578     int Sr, Sg, Sb;
579 
580     if(sa && da) {
581         Sr = sr * da;
582         Sg = sg * da;
583         Sb = sb * da;
584         SetLum(&Sr, &Sg, &Sb, sa * da, Lum(dr, dg, db) * sa);
585     } else {
586         Sr = 0;
587         Sg = 0;
588         Sb = 0;
589     }
590 
591     int a = srcover_byte(sa, da);
592     int r = blendfunc_nonsep_byte(sr, dr, sa, da, Sr);
593     int g = blendfunc_nonsep_byte(sg, dg, sa, da, Sg);
594     int b = blendfunc_nonsep_byte(sb, db, sa, da, Sb);
595     return SkPackARGB32(a, r, g, b);
596 }
597 
598 // kLuminosity_Mode
599 // B(Cb, Cs) = SetLum(Cb, Lum(Cs))
600 // 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)601 static SkPMColor luminosity_modeproc(SkPMColor src, SkPMColor dst) {
602     int sr = SkGetPackedR32(src);
603     int sg = SkGetPackedG32(src);
604     int sb = SkGetPackedB32(src);
605     int sa = SkGetPackedA32(src);
606 
607     int dr = SkGetPackedR32(dst);
608     int dg = SkGetPackedG32(dst);
609     int db = SkGetPackedB32(dst);
610     int da = SkGetPackedA32(dst);
611     int Dr, Dg, Db;
612 
613     if(sa && da) {
614         Dr = dr * sa;
615         Dg = dg * sa;
616         Db = db * sa;
617         SetLum(&Dr, &Dg, &Db, sa * da, Lum(sr, sg, sb) * da);
618     } else {
619         Dr = 0;
620         Dg = 0;
621         Db = 0;
622     }
623 
624     int a = srcover_byte(sa, da);
625     int r = blendfunc_nonsep_byte(sr, dr, sa, da, Dr);
626     int g = blendfunc_nonsep_byte(sg, dg, sa, da, Dg);
627     int b = blendfunc_nonsep_byte(sb, db, sa, da, Db);
628     return SkPackARGB32(a, r, g, b);
629 }
630 
631 const ProcCoeff gProcCoeffs[] = {
632     { clear_modeproc,   SkXfermode::kZero_Coeff,    SkXfermode::kZero_Coeff },
633     { src_modeproc,     SkXfermode::kOne_Coeff,     SkXfermode::kZero_Coeff },
634     { dst_modeproc,     SkXfermode::kZero_Coeff,    SkXfermode::kOne_Coeff },
635     { srcover_modeproc, SkXfermode::kOne_Coeff,     SkXfermode::kISA_Coeff },
636     { dstover_modeproc, SkXfermode::kIDA_Coeff,     SkXfermode::kOne_Coeff },
637     { srcin_modeproc,   SkXfermode::kDA_Coeff,      SkXfermode::kZero_Coeff },
638     { dstin_modeproc,   SkXfermode::kZero_Coeff,    SkXfermode::kSA_Coeff },
639     { srcout_modeproc,  SkXfermode::kIDA_Coeff,     SkXfermode::kZero_Coeff },
640     { dstout_modeproc,  SkXfermode::kZero_Coeff,    SkXfermode::kISA_Coeff },
641     { srcatop_modeproc, SkXfermode::kDA_Coeff,      SkXfermode::kISA_Coeff },
642     { dstatop_modeproc, SkXfermode::kIDA_Coeff,     SkXfermode::kSA_Coeff },
643     { xor_modeproc,     SkXfermode::kIDA_Coeff,     SkXfermode::kISA_Coeff },
644 
645     { plus_modeproc,    SkXfermode::kOne_Coeff,     SkXfermode::kOne_Coeff },
646     { modulate_modeproc,SkXfermode::kZero_Coeff,    SkXfermode::kSC_Coeff },
647     { screen_modeproc,  SkXfermode::kOne_Coeff,     SkXfermode::kISC_Coeff },
648     { overlay_modeproc,     CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
649     { darken_modeproc,      CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
650     { lighten_modeproc,     CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
651     { colordodge_modeproc,  CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
652     { colorburn_modeproc,   CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
653     { hardlight_modeproc,   CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
654     { softlight_modeproc,   CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
655     { difference_modeproc,  CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
656     { exclusion_modeproc,   CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
657     { multiply_modeproc,    CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
658     { hue_modeproc,         CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
659     { saturation_modeproc,  CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
660     { color_modeproc,       CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
661     { luminosity_modeproc,  CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
662 };
663 
664 ///////////////////////////////////////////////////////////////////////////////
665 
asMode(Mode * mode) const666 bool SkXfermode::asMode(Mode* mode) const {
667     return false;
668 }
669 
asFragmentProcessor(GrFragmentProcessor **,GrTexture *) const670 bool SkXfermode::asFragmentProcessor(GrFragmentProcessor**, GrTexture*) const {
671     return false;
672 }
673 
asXPFactory(GrXPFactory **) const674 bool SkXfermode::asXPFactory(GrXPFactory**) const {
675     return false;
676 }
677 
678 
679 #if SK_SUPPORT_GPU
680 #include "effects/GrPorterDuffXferProcessor.h"
681 
AsXPFactory(SkXfermode * xfermode,GrXPFactory ** xpf)682 bool SkXfermode::AsXPFactory(SkXfermode* xfermode, GrXPFactory** xpf) {
683     if (NULL == xfermode) {
684         if (xpf) {
685             *xpf = GrPorterDuffXPFactory::Create(kSrcOver_Mode);
686         }
687         return true;
688     } else {
689         return xfermode->asXPFactory(xpf);
690     }
691 }
692 #else
AsXPFactory(SkXfermode * xfermode,GrXPFactory ** xpf)693 bool SkXfermode::AsXPFactory(SkXfermode* xfermode, GrXPFactory** xpf) {
694     return false;
695 }
696 #endif
697 
xferColor(SkPMColor src,SkPMColor dst) const698 SkPMColor SkXfermode::xferColor(SkPMColor src, SkPMColor dst) const{
699     // no-op. subclasses should override this
700     return dst;
701 }
702 
xfer32(SkPMColor * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,const SkAlpha * SK_RESTRICT aa) const703 void SkXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
704                         const SkPMColor* SK_RESTRICT src, int count,
705                         const SkAlpha* SK_RESTRICT aa) const {
706     SkASSERT(dst && src && count >= 0);
707 
708     if (NULL == aa) {
709         for (int i = count - 1; i >= 0; --i) {
710             dst[i] = this->xferColor(src[i], dst[i]);
711         }
712     } else {
713         for (int i = count - 1; i >= 0; --i) {
714             unsigned a = aa[i];
715             if (0 != a) {
716                 SkPMColor dstC = dst[i];
717                 SkPMColor C = this->xferColor(src[i], dstC);
718                 if (0xFF != a) {
719                     C = SkFourByteInterp(C, dstC, a);
720                 }
721                 dst[i] = C;
722             }
723         }
724     }
725 }
726 
xfer16(uint16_t * dst,const SkPMColor * SK_RESTRICT src,int count,const SkAlpha * SK_RESTRICT aa) const727 void SkXfermode::xfer16(uint16_t* dst,
728                         const SkPMColor* SK_RESTRICT src, int count,
729                         const SkAlpha* SK_RESTRICT aa) const {
730     SkASSERT(dst && src && count >= 0);
731 
732     if (NULL == aa) {
733         for (int i = count - 1; i >= 0; --i) {
734             SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
735             dst[i] = SkPixel32ToPixel16_ToU16(this->xferColor(src[i], dstC));
736         }
737     } else {
738         for (int i = count - 1; i >= 0; --i) {
739             unsigned a = aa[i];
740             if (0 != a) {
741                 SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
742                 SkPMColor C = this->xferColor(src[i], dstC);
743                 if (0xFF != a) {
744                     C = SkFourByteInterp(C, dstC, a);
745                 }
746                 dst[i] = SkPixel32ToPixel16_ToU16(C);
747             }
748         }
749     }
750 }
751 
xferA8(SkAlpha * SK_RESTRICT dst,const SkPMColor src[],int count,const SkAlpha * SK_RESTRICT aa) const752 void SkXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
753                         const SkPMColor src[], int count,
754                         const SkAlpha* SK_RESTRICT aa) const {
755     SkASSERT(dst && src && count >= 0);
756 
757     if (NULL == aa) {
758         for (int i = count - 1; i >= 0; --i) {
759             SkPMColor res = this->xferColor(src[i], (dst[i] << SK_A32_SHIFT));
760             dst[i] = SkToU8(SkGetPackedA32(res));
761         }
762     } else {
763         for (int i = count - 1; i >= 0; --i) {
764             unsigned a = aa[i];
765             if (0 != a) {
766                 SkAlpha dstA = dst[i];
767                 unsigned A = SkGetPackedA32(this->xferColor(src[i],
768                                             (SkPMColor)(dstA << SK_A32_SHIFT)));
769                 if (0xFF != a) {
770                     A = SkAlphaBlend(A, dstA, SkAlpha255To256(a));
771                 }
772                 dst[i] = SkToU8(A);
773             }
774         }
775     }
776 }
777 
supportsCoverageAsAlpha() const778 bool SkXfermode::supportsCoverageAsAlpha() const {
779     return false;
780 }
781 
isOpaque(SkXfermode::SrcColorOpacity opacityType) const782 bool SkXfermode::isOpaque(SkXfermode::SrcColorOpacity opacityType) const {
783     return false;
784 }
785 
786 ///////////////////////////////////////////////////////////////////////////////
787 ///////////////////////////////////////////////////////////////////////////////
788 
CreateProc(SkReadBuffer & buffer)789 SkFlattenable* SkProcCoeffXfermode::CreateProc(SkReadBuffer& buffer) {
790     uint32_t mode32 = buffer.read32();
791     if (!buffer.validate(mode32 < SK_ARRAY_COUNT(gProcCoeffs))) {
792         return NULL;
793     }
794     return SkXfermode::Create((SkXfermode::Mode)mode32);
795 }
796 
flatten(SkWriteBuffer & buffer) const797 void SkProcCoeffXfermode::flatten(SkWriteBuffer& buffer) const {
798     buffer.write32(fMode);
799 }
800 
asMode(Mode * mode) const801 bool SkProcCoeffXfermode::asMode(Mode* mode) const {
802     if (mode) {
803         *mode = fMode;
804     }
805     return true;
806 }
807 
supportsCoverageAsAlpha() const808 bool SkProcCoeffXfermode::supportsCoverageAsAlpha() const {
809     if (CANNOT_USE_COEFF == fSrcCoeff) {
810         return false;
811     }
812 
813     switch (fDstCoeff) {
814         case SkXfermode::kOne_Coeff:
815         case SkXfermode::kISA_Coeff:
816         case SkXfermode::kISC_Coeff:
817             return true;
818         default:
819             return false;
820     }
821 }
822 
isOpaque(SkXfermode::SrcColorOpacity opacityType) const823 bool SkProcCoeffXfermode::isOpaque(SkXfermode::SrcColorOpacity opacityType) const {
824     if (CANNOT_USE_COEFF == fSrcCoeff) {
825         return false;
826     }
827 
828     if (SkXfermode::kDA_Coeff == fSrcCoeff || SkXfermode::kDC_Coeff == fSrcCoeff ||
829         SkXfermode::kIDA_Coeff == fSrcCoeff || SkXfermode::kIDC_Coeff == fSrcCoeff) {
830         return false;
831     }
832 
833     switch (fDstCoeff) {
834         case SkXfermode::kZero_Coeff:
835             return true;
836         case SkXfermode::kISA_Coeff:
837             return SkXfermode::kOpaque_SrcColorOpacity == opacityType;
838         case SkXfermode::kSA_Coeff:
839             return SkXfermode::kTransparentBlack_SrcColorOpacity == opacityType ||
840                    SkXfermode::kTransparentAlpha_SrcColorOpacity == opacityType;
841         case SkXfermode::kSC_Coeff:
842             return SkXfermode::kTransparentBlack_SrcColorOpacity == opacityType;
843         default:
844             return false;
845     }
846 
847 }
848 
xfer32(SkPMColor * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,const SkAlpha * SK_RESTRICT aa) const849 void SkProcCoeffXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
850                                  const SkPMColor* SK_RESTRICT src, int count,
851                                  const SkAlpha* SK_RESTRICT aa) const {
852     SkASSERT(dst && src && count >= 0);
853 
854     SkXfermodeProc proc = fProc;
855 
856     if (proc) {
857         if (NULL == aa) {
858             for (int i = count - 1; i >= 0; --i) {
859                 dst[i] = proc(src[i], dst[i]);
860             }
861         } else {
862             for (int i = count - 1; i >= 0; --i) {
863                 unsigned a = aa[i];
864                 if (0 != a) {
865                     SkPMColor dstC = dst[i];
866                     SkPMColor C = proc(src[i], dstC);
867                     if (a != 0xFF) {
868                         C = SkFourByteInterp(C, dstC, a);
869                     }
870                     dst[i] = C;
871                 }
872             }
873         }
874     }
875 }
876 
xfer16(uint16_t * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,const SkAlpha * SK_RESTRICT aa) const877 void SkProcCoeffXfermode::xfer16(uint16_t* SK_RESTRICT dst,
878                                  const SkPMColor* SK_RESTRICT src, int count,
879                                  const SkAlpha* SK_RESTRICT aa) const {
880     SkASSERT(dst && src && count >= 0);
881 
882     SkXfermodeProc proc = fProc;
883 
884     if (proc) {
885         if (NULL == aa) {
886             for (int i = count - 1; i >= 0; --i) {
887                 SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
888                 dst[i] = SkPixel32ToPixel16_ToU16(proc(src[i], dstC));
889             }
890         } else {
891             for (int i = count - 1; i >= 0; --i) {
892                 unsigned a = aa[i];
893                 if (0 != a) {
894                     SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
895                     SkPMColor C = proc(src[i], dstC);
896                     if (0xFF != a) {
897                         C = SkFourByteInterp(C, dstC, a);
898                     }
899                     dst[i] = SkPixel32ToPixel16_ToU16(C);
900                 }
901             }
902         }
903     }
904 }
905 
xferA8(SkAlpha * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,const SkAlpha * SK_RESTRICT aa) const906 void SkProcCoeffXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
907                                  const SkPMColor* SK_RESTRICT src, int count,
908                                  const SkAlpha* SK_RESTRICT aa) const {
909     SkASSERT(dst && src && count >= 0);
910 
911     SkXfermodeProc proc = fProc;
912 
913     if (proc) {
914         if (NULL == aa) {
915             for (int i = count - 1; i >= 0; --i) {
916                 SkPMColor res = proc(src[i], dst[i] << SK_A32_SHIFT);
917                 dst[i] = SkToU8(SkGetPackedA32(res));
918             }
919         } else {
920             for (int i = count - 1; i >= 0; --i) {
921                 unsigned a = aa[i];
922                 if (0 != a) {
923                     SkAlpha dstA = dst[i];
924                     SkPMColor res = proc(src[i], dstA << SK_A32_SHIFT);
925                     unsigned A = SkGetPackedA32(res);
926                     if (0xFF != a) {
927                         A = SkAlphaBlend(A, dstA, SkAlpha255To256(a));
928                     }
929                     dst[i] = SkToU8(A);
930                 }
931             }
932         }
933     }
934 }
935 
936 #if SK_SUPPORT_GPU
937 #include "effects/GrCustomXfermode.h"
938 
asFragmentProcessor(GrFragmentProcessor ** fp,GrTexture * background) const939 bool SkProcCoeffXfermode::asFragmentProcessor(GrFragmentProcessor** fp,
940                                               GrTexture* background) const {
941     if (GrCustomXfermode::IsSupportedMode(fMode)) {
942         if (fp) {
943             *fp = GrCustomXfermode::CreateFP(fMode, background);
944             SkASSERT(*fp);
945         }
946         return true;
947     }
948     return false;
949 }
950 
asXPFactory(GrXPFactory ** xp) const951 bool SkProcCoeffXfermode::asXPFactory(GrXPFactory** xp) const {
952     if (CANNOT_USE_COEFF != fSrcCoeff) {
953         if (xp) {
954             *xp = GrPorterDuffXPFactory::Create(fMode);
955             SkASSERT(*xp);
956         }
957         return true;
958     }
959 
960     if (GrCustomXfermode::IsSupportedMode(fMode)) {
961         if (xp) {
962             *xp = GrCustomXfermode::CreateXPFactory(fMode);
963             SkASSERT(*xp);
964         }
965         return true;
966     }
967     return false;
968 }
969 #endif
970 
ModeName(Mode mode)971 const char* SkXfermode::ModeName(Mode mode) {
972     SkASSERT((unsigned) mode <= (unsigned)kLastMode);
973     const char* gModeStrings[] = {
974         "Clear", "Src", "Dst", "SrcOver", "DstOver", "SrcIn", "DstIn",
975         "SrcOut", "DstOut", "SrcATop", "DstATop", "Xor", "Plus",
976         "Modulate", "Screen", "Overlay", "Darken", "Lighten", "ColorDodge",
977         "ColorBurn", "HardLight", "SoftLight", "Difference", "Exclusion",
978         "Multiply", "Hue", "Saturation", "Color",  "Luminosity"
979     };
980     return gModeStrings[mode];
981     SK_COMPILE_ASSERT(SK_ARRAY_COUNT(gModeStrings) == kLastMode + 1, mode_count);
982 }
983 
984 #ifndef SK_IGNORE_TO_STRING
toString(SkString * str) const985 void SkProcCoeffXfermode::toString(SkString* str) const {
986     str->append("SkProcCoeffXfermode: ");
987 
988     str->append("mode: ");
989     str->append(ModeName(fMode));
990 
991     static const char* gCoeffStrings[kCoeffCount] = {
992         "Zero", "One", "SC", "ISC", "DC", "IDC", "SA", "ISA", "DA", "IDA"
993     };
994 
995     str->append(" src: ");
996     if (CANNOT_USE_COEFF == fSrcCoeff) {
997         str->append("can't use");
998     } else {
999         str->append(gCoeffStrings[fSrcCoeff]);
1000     }
1001 
1002     str->append(" dst: ");
1003     if (CANNOT_USE_COEFF == fDstCoeff) {
1004         str->append("can't use");
1005     } else {
1006         str->append(gCoeffStrings[fDstCoeff]);
1007     }
1008 }
1009 #endif
1010 
1011 ///////////////////////////////////////////////////////////////////////////////
1012 
1013 class SkClearXfermode : public SkProcCoeffXfermode {
1014 public:
Create(const ProcCoeff & rec)1015     static SkClearXfermode* Create(const ProcCoeff& rec) {
1016         return SkNEW_ARGS(SkClearXfermode, (rec));
1017     }
1018 
1019     void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const override;
1020     void xferA8(SkAlpha*, const SkPMColor*, int, const SkAlpha*) const override;
1021 
1022     SK_TO_STRING_OVERRIDE()
1023 
1024 private:
SkClearXfermode(const ProcCoeff & rec)1025     SkClearXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kClear_Mode) {}
1026 
1027     typedef SkProcCoeffXfermode INHERITED;
1028 };
1029 
xfer32(SkPMColor * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT,int count,const SkAlpha * SK_RESTRICT aa) const1030 void SkClearXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
1031                              const SkPMColor* SK_RESTRICT, int count,
1032                              const SkAlpha* SK_RESTRICT aa) const {
1033     SkASSERT(dst && count >= 0);
1034 
1035     if (NULL == aa) {
1036         memset(dst, 0, count << 2);
1037     } else {
1038         for (int i = count - 1; i >= 0; --i) {
1039             unsigned a = aa[i];
1040             if (0xFF == a) {
1041                 dst[i] = 0;
1042             } else if (a != 0) {
1043                 dst[i] = SkAlphaMulQ(dst[i], SkAlpha255To256(255 - a));
1044             }
1045         }
1046     }
1047 }
xferA8(SkAlpha * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT,int count,const SkAlpha * SK_RESTRICT aa) const1048 void SkClearXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
1049                              const SkPMColor* SK_RESTRICT, int count,
1050                              const SkAlpha* SK_RESTRICT aa) const {
1051     SkASSERT(dst && count >= 0);
1052 
1053     if (NULL == aa) {
1054         memset(dst, 0, count);
1055     } else {
1056         for (int i = count - 1; i >= 0; --i) {
1057             unsigned a = aa[i];
1058             if (0xFF == a) {
1059                 dst[i] = 0;
1060             } else if (0 != a) {
1061                 dst[i] = SkAlphaMulAlpha(dst[i], 255 - a);
1062             }
1063         }
1064     }
1065 }
1066 
1067 #ifndef SK_IGNORE_TO_STRING
toString(SkString * str) const1068 void SkClearXfermode::toString(SkString* str) const {
1069     this->INHERITED::toString(str);
1070 }
1071 #endif
1072 
1073 ///////////////////////////////////////////////////////////////////////////////
1074 
1075 class SkSrcXfermode : public SkProcCoeffXfermode {
1076 public:
Create(const ProcCoeff & rec)1077     static SkSrcXfermode* Create(const ProcCoeff& rec) {
1078         return SkNEW_ARGS(SkSrcXfermode, (rec));
1079     }
1080 
1081     void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const override;
1082     void xferA8(SkAlpha*, const SkPMColor*, int, const SkAlpha*) const override;
1083 
1084     SK_TO_STRING_OVERRIDE()
1085 
1086 private:
SkSrcXfermode(const ProcCoeff & rec)1087     SkSrcXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kSrc_Mode) {}
1088     typedef SkProcCoeffXfermode INHERITED;
1089 };
1090 
xfer32(SkPMColor * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,const SkAlpha * SK_RESTRICT aa) const1091 void SkSrcXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
1092                            const SkPMColor* SK_RESTRICT src, int count,
1093                            const SkAlpha* SK_RESTRICT aa) const {
1094     SkASSERT(dst && src && count >= 0);
1095 
1096     if (NULL == aa) {
1097         memcpy(dst, src, count << 2);
1098     } else {
1099         for (int i = count - 1; i >= 0; --i) {
1100             unsigned a = aa[i];
1101             if (a == 0xFF) {
1102                 dst[i] = src[i];
1103             } else if (a != 0) {
1104                 dst[i] = SkFourByteInterp(src[i], dst[i], a);
1105             }
1106         }
1107     }
1108 }
1109 
xferA8(SkAlpha * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,const SkAlpha * SK_RESTRICT aa) const1110 void SkSrcXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
1111                            const SkPMColor* SK_RESTRICT src, int count,
1112                            const SkAlpha* SK_RESTRICT aa) const {
1113     SkASSERT(dst && src && count >= 0);
1114 
1115     if (NULL == aa) {
1116         for (int i = count - 1; i >= 0; --i) {
1117             dst[i] = SkToU8(SkGetPackedA32(src[i]));
1118         }
1119     } else {
1120         for (int i = count - 1; i >= 0; --i) {
1121             unsigned a = aa[i];
1122             if (0 != a) {
1123                 unsigned srcA = SkGetPackedA32(src[i]);
1124                 if (a == 0xFF) {
1125                     dst[i] = SkToU8(srcA);
1126                 } else {
1127                     dst[i] = SkToU8(SkAlphaBlend(srcA, dst[i], a));
1128                 }
1129             }
1130         }
1131     }
1132 }
1133 #ifndef SK_IGNORE_TO_STRING
toString(SkString * str) const1134 void SkSrcXfermode::toString(SkString* str) const {
1135     this->INHERITED::toString(str);
1136 }
1137 #endif
1138 
1139 ///////////////////////////////////////////////////////////////////////////////
1140 
1141 class SkDstInXfermode : public SkProcCoeffXfermode {
1142 public:
Create(const ProcCoeff & rec)1143     static SkDstInXfermode* Create(const ProcCoeff& rec) {
1144         return SkNEW_ARGS(SkDstInXfermode, (rec));
1145     }
1146 
1147     void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const override;
1148 
1149     SK_TO_STRING_OVERRIDE()
1150 
1151 private:
SkDstInXfermode(const ProcCoeff & rec)1152     SkDstInXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstIn_Mode) {}
1153 
1154     typedef SkProcCoeffXfermode INHERITED;
1155 };
1156 
xfer32(SkPMColor * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,const SkAlpha * SK_RESTRICT aa) const1157 void SkDstInXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
1158                              const SkPMColor* SK_RESTRICT src, int count,
1159                              const SkAlpha* SK_RESTRICT aa) const {
1160     SkASSERT(dst && src);
1161 
1162     if (count <= 0) {
1163         return;
1164     }
1165     if (aa) {
1166         return this->INHERITED::xfer32(dst, src, count, aa);
1167     }
1168 
1169     do {
1170         unsigned a = SkGetPackedA32(*src);
1171         *dst = SkAlphaMulQ(*dst, SkAlpha255To256(a));
1172         dst++;
1173         src++;
1174     } while (--count != 0);
1175 }
1176 
1177 #ifndef SK_IGNORE_TO_STRING
toString(SkString * str) const1178 void SkDstInXfermode::toString(SkString* str) const {
1179     this->INHERITED::toString(str);
1180 }
1181 #endif
1182 
1183 ///////////////////////////////////////////////////////////////////////////////
1184 
1185 /* These modes can merge coverage into src-alpha
1186  *
1187 { dst_modeproc,     SkXfermode::kZero_Coeff,    SkXfermode::kOne_Coeff },
1188 { srcover_modeproc, SkXfermode::kOne_Coeff,     SkXfermode::kISA_Coeff },
1189 { dstover_modeproc, SkXfermode::kIDA_Coeff,     SkXfermode::kOne_Coeff },
1190 { dstout_modeproc,  SkXfermode::kZero_Coeff,    SkXfermode::kISA_Coeff },
1191 { srcatop_modeproc, SkXfermode::kDA_Coeff,      SkXfermode::kISA_Coeff },
1192 { xor_modeproc,     SkXfermode::kIDA_Coeff,     SkXfermode::kISA_Coeff },
1193 { plus_modeproc,    SkXfermode::kOne_Coeff,     SkXfermode::kOne_Coeff },
1194 { screen_modeproc,  SkXfermode::kOne_Coeff,     SkXfermode::kISC_Coeff },
1195 */
1196 
1197 static const float gInv255 = 0.0039215683f; //  (1.0f / 255) - ULP == SkBits2Float(0x3B808080)
1198 
ramp(const Sk4f & v0,const Sk4f & v1,const Sk4f & t)1199 static Sk4f ramp(const Sk4f& v0, const Sk4f& v1, const Sk4f& t) {
1200     return v0 + (v1 - v0) * t;
1201 }
1202 
clamp_255(const Sk4f & value)1203 static Sk4f clamp_255(const Sk4f& value) {
1204     return Sk4f::Min(Sk4f(255), value);
1205 }
1206 
clamp_0_255(const Sk4f & value)1207 static Sk4f clamp_0_255(const Sk4f& value) {
1208     return Sk4f::Max(Sk4f(0), Sk4f::Min(Sk4f(255), value));
1209 }
1210 
1211 /**
1212  *  Some modes can, due to very slight numerical error, generate "invalid" pmcolors...
1213  *
1214  *  e.g.
1215  *      alpha = 100.9999
1216  *      red   = 101
1217  *
1218  *  or
1219  *      alpha = 255.0001
1220  *
1221  *  If we know we're going to write-out the values as bytes, we can relax these somewhat,
1222  *  since we only really need to enforce that the bytes are valid premul...
1223  *
1224  *  To that end, this method asserts that the resulting pmcolor will be valid, but does not call
1225  *  SkPMFloat::isValid(), as that would fire sometimes, but not result in a bad pixel.
1226  */
check_as_pmfloat(const Sk4f & value)1227 static inline SkPMFloat check_as_pmfloat(const Sk4f& value) {
1228     SkPMFloat pm = value;
1229 #ifdef SK_DEBUG
1230     (void)pm.round();
1231 #endif
1232     return pm;
1233 }
1234 
1235 //  kSrcATop_Mode,  //!< [Da, Sc * Da + (1 - Sa) * Dc]
1236 struct SrcATop4f {
XferSrcATop4f1237     static SkPMFloat Xfer(const SkPMFloat& src, const SkPMFloat& dst) {
1238         const Sk4f inv255(gInv255);
1239         return check_as_pmfloat(dst + (src * Sk4f(dst.a()) - dst * Sk4f(src.a())) * inv255);
1240     }
XferSrcATop4f1241     static Sk4px Xfer(const Sk4px& src, const Sk4px& dst) {
1242         return Sk4px::Wide(src.mulWiden(dst.alphas()) + dst.mulWiden(src.alphas().inv()))
1243             .div255RoundNarrow();
1244     }
1245     static const bool kFoldCoverageIntoSrcAlpha = true;
1246     static const SkXfermode::Mode kMode = SkXfermode::kSrcATop_Mode;
1247 };
1248 
1249 //  kDstATop_Mode,  //!< [Sa, Sa * Dc + Sc * (1 - Da)]
1250 struct DstATop4f {
XferDstATop4f1251     static SkPMFloat Xfer(const SkPMFloat& src, const SkPMFloat& dst) {
1252         return SrcATop4f::Xfer(dst, src);
1253     }
XferDstATop4f1254     static Sk4px Xfer(const Sk4px& src, const Sk4px& dst) {
1255         return SrcATop4f::Xfer(dst, src);
1256     }
1257     static const bool kFoldCoverageIntoSrcAlpha = false;
1258     static const SkXfermode::Mode kMode = SkXfermode::kDstATop_Mode;
1259 };
1260 
1261 //  kXor_Mode   [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc]
1262 struct Xor4f {
XferXor4f1263     static SkPMFloat Xfer(const SkPMFloat& src, const SkPMFloat& dst) {
1264         const Sk4f inv255(gInv255);
1265         return check_as_pmfloat(src + dst - (src * Sk4f(dst.a()) + dst * Sk4f(src.a())) * inv255);
1266     }
XferXor4f1267     static Sk4px Xfer(const Sk4px& src, const Sk4px& dst) {
1268         return Sk4px::Wide(src.mulWiden(dst.alphas().inv()) + dst.mulWiden(src.alphas().inv()))
1269             .div255RoundNarrow();
1270     }
1271     static const bool kFoldCoverageIntoSrcAlpha = true;
1272     static const SkXfermode::Mode kMode = SkXfermode::kXor_Mode;
1273 };
1274 
1275 //  kPlus_Mode   [Sa + Da, Sc + Dc]
1276 struct Plus4f {
XferPlus4f1277     static SkPMFloat Xfer(const SkPMFloat& src, const SkPMFloat& dst) {
1278         return check_as_pmfloat(clamp_255(src + dst));
1279     }
XferPlus4f1280     static Sk4px Xfer(const Sk4px& src, const Sk4px& dst) {
1281         return src.saturatedAdd(dst);
1282     }
1283     static const bool kFoldCoverageIntoSrcAlpha = false;
1284     static const SkXfermode::Mode kMode = SkXfermode::kPlus_Mode;
1285 };
1286 
1287 //  kModulate_Mode   [Sa * Da, Sc * Dc]
1288 struct Modulate4f {
XferModulate4f1289     static SkPMFloat Xfer(const SkPMFloat& src, const SkPMFloat& dst) {
1290         const Sk4f inv255(gInv255);
1291         return check_as_pmfloat(src * dst * inv255);
1292     }
XferModulate4f1293     static Sk4px Xfer(const Sk4px& src, const Sk4px& dst) {
1294         return src.mulWiden(dst).div255RoundNarrow();
1295     }
1296     static const bool kFoldCoverageIntoSrcAlpha = false;
1297     static const SkXfermode::Mode kMode = SkXfermode::kModulate_Mode;
1298 };
1299 
1300 //  kScreen_Mode   [S + D - S * D]
1301 struct Screen4f {
XferScreen4f1302     static SkPMFloat Xfer(const SkPMFloat& src, const SkPMFloat& dst) {
1303         const Sk4f inv255(gInv255);
1304         return check_as_pmfloat(src + dst - src * dst * inv255);
1305     }
XferScreen4f1306     static Sk4px Xfer(const Sk4px& src, const Sk4px& dst) {
1307         // Doing the math as S + (1-S)*D or S + (D - S*D) means the add and subtract can be done
1308         // in 8-bit space without overflow.  S + (1-S)*D is a touch faster because inv() is cheap.
1309         return src + src.inv().mulWiden(dst).div255RoundNarrow();
1310     }
1311     static const bool kFoldCoverageIntoSrcAlpha = true;
1312     static const SkXfermode::Mode kMode = SkXfermode::kScreen_Mode;
1313 };
1314 
1315 struct Multiply4f {
XferMultiply4f1316     static SkPMFloat Xfer(const SkPMFloat& src, const SkPMFloat& dst) {
1317         const Sk4f inv255(gInv255);
1318         Sk4f sa = Sk4f(src.a());
1319         Sk4f da = Sk4f(dst.a());
1320         Sk4f sc = src;
1321         Sk4f dc = dst;
1322         Sk4f rc = sc + dc + (sc * (dc - da) - dc * sa) * inv255;
1323         // ra = srcover(sa, da), but the calc for rc happens to accomplish this for us
1324         return check_as_pmfloat(clamp_0_255(rc));
1325     }
XferMultiply4f1326     static Sk4px Xfer(const Sk4px& src, const Sk4px& dst) {
1327         return Sk4px::Wide(src.mulWiden(dst.alphas().inv()) +
1328                            dst.mulWiden(src.alphas().inv()) +
1329                            src.mulWiden(dst))
1330             .div255RoundNarrow();
1331     }
1332     static const bool kFoldCoverageIntoSrcAlpha = false;
1333     static const SkXfermode::Mode kMode = SkXfermode::kMultiply_Mode;
1334 };
1335 
1336 // [ sa + da - sa*da, sc + dc - 2*min(sc*da, dc*sa) ]  (And notice sa*da == min(sa*da, da*sa).)
1337 struct Difference4f {
XferDifference4f1338     static SkPMFloat Xfer(const SkPMFloat& src, const SkPMFloat& dst) {
1339         const Sk4f inv255(gInv255);
1340         Sk4f sa = Sk4f(src.a());
1341         Sk4f da = Sk4f(dst.a());
1342         Sk4f sc = src;
1343         Sk4f dc = dst;
1344         Sk4f min = Sk4f::Min(sc * da, dc * sa) * inv255;
1345         Sk4f ra = sc + dc - min;
1346         return check_as_pmfloat(ra - min * SkPMFloat(0, 1, 1, 1));
1347     }
XferDifference4f1348     static Sk4px Xfer(const Sk4px& src, const Sk4px& dst) {
1349         auto m = Sk4px::Wide(Sk16h::Min(src.mulWiden(dst.alphas()), dst.mulWiden(src.alphas())))
1350             .div255RoundNarrow();
1351         // There's no chance of underflow, and if we subtract m before adding src+dst, no overflow.
1352         return (src - m) + (dst - m.zeroAlphas());
1353     }
1354     static const bool kFoldCoverageIntoSrcAlpha = false;
1355     static const SkXfermode::Mode kMode = SkXfermode::kDifference_Mode;
1356 };
1357 
1358 // [ sa + da - sa*da, sc + dc - 2*sc*dc ]
1359 struct Exclusion4f {
XferExclusion4f1360     static SkPMFloat Xfer(const SkPMFloat& src, const SkPMFloat& dst) {
1361         const Sk4f inv255(gInv255);
1362         Sk4f sc = src;
1363         Sk4f dc = dst;
1364         Sk4f prod = sc * dc * inv255;
1365         Sk4f ra = sc + dc - prod;
1366         return check_as_pmfloat(ra - prod * SkPMFloat(0, 1, 1, 1));
1367     }
XferExclusion4f1368     static Sk4px Xfer(const Sk4px& src, const Sk4px& dst) {
1369         auto p = src.mulWiden(dst).div255RoundNarrow();
1370         // There's no chance of underflow, and if we subtract p before adding src+dst, no overflow.
1371         return (src - p) + (dst - p.zeroAlphas());
1372     }
1373     static const bool kFoldCoverageIntoSrcAlpha = false;
1374     static const SkXfermode::Mode kMode = SkXfermode::kExclusion_Mode;
1375 };
1376 
1377 template <typename ProcType>
1378 class SkT4fXfermode : public SkProcCoeffXfermode {
1379 public:
Create(const ProcCoeff & rec)1380     static SkXfermode* Create(const ProcCoeff& rec) {
1381         return SkNEW_ARGS(SkT4fXfermode, (rec));
1382     }
1383 
xfer32(SkPMColor dst[],const SkPMColor src[],int n,const SkAlpha aa[]) const1384     void xfer32(SkPMColor dst[], const SkPMColor src[], int n, const SkAlpha aa[]) const override {
1385         if (NULL == aa) {
1386             for (int i = 0; i < n; ++i) {
1387                 dst[i] = ProcType::Xfer(SkPMFloat(src[i]), SkPMFloat(dst[i])).round();
1388             }
1389         } else {
1390             for (int i = 0; i < n; ++i) {
1391                 const Sk4f aa4 = Sk4f(aa[i] * gInv255);
1392                 SkPMFloat dstF(dst[i]);
1393                 SkPMFloat srcF(src[i]);
1394                 Sk4f res;
1395                 if (ProcType::kFoldCoverageIntoSrcAlpha) {
1396                     Sk4f src4 = srcF;
1397                     res = ProcType::Xfer(src4 * aa4, dstF);
1398                 } else {
1399                     res = ramp(dstF, ProcType::Xfer(srcF, dstF), aa4);
1400                 }
1401                 dst[i] = SkPMFloat(res).round();
1402             }
1403         }
1404     }
1405 
1406 private:
SkT4fXfermode(const ProcCoeff & rec)1407     SkT4fXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, ProcType::kMode) {}
1408 
1409     typedef SkProcCoeffXfermode INHERITED;
1410 };
1411 
1412 template <typename ProcType>
1413 class SkT4pxXfermode : public SkProcCoeffXfermode {
1414 public:
Create(const ProcCoeff & rec)1415     static SkXfermode* Create(const ProcCoeff& rec) {
1416         return SkNEW_ARGS(SkT4pxXfermode, (rec));
1417     }
1418 
xfer32(SkPMColor dst[],const SkPMColor src[],int n,const SkAlpha aa[]) const1419     void xfer32(SkPMColor dst[], const SkPMColor src[], int n, const SkAlpha aa[]) const override {
1420         if (NULL == aa) {
1421             Sk4px::MapDstSrc(n, dst, src, [&](const Sk4px& dst4, const Sk4px& src4) {
1422                 return ProcType::Xfer(src4, dst4);
1423             });
1424         } else {
1425             Sk4px::MapDstSrcAlpha(n, dst, src, aa,
1426                     [&](const Sk4px& dst4, const Sk4px& src4, const Sk16b& alpha) {
1427                 // We can't exploit kFoldCoverageIntoSrcAlpha. That requires >=24-bit intermediates.
1428                 Sk4px res4 = ProcType::Xfer(src4, dst4);
1429                 return Sk4px::Wide(res4.mulWiden(alpha) + dst4.mulWiden(Sk4px(alpha).inv()))
1430                            .div255RoundNarrow();
1431             });
1432         }
1433     }
1434 
1435 private:
SkT4pxXfermode(const ProcCoeff & rec)1436     SkT4pxXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, ProcType::kMode) {}
1437 
1438     typedef SkProcCoeffXfermode INHERITED;
1439 };
1440 
1441 ///////////////////////////////////////////////////////////////////////////////
1442 
1443 class SkDstOutXfermode : public SkProcCoeffXfermode {
1444 public:
Create(const ProcCoeff & rec)1445     static SkDstOutXfermode* Create(const ProcCoeff& rec) {
1446         return SkNEW_ARGS(SkDstOutXfermode, (rec));
1447     }
1448 
1449     void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const override;
1450 
1451     SK_TO_STRING_OVERRIDE()
1452 
1453 private:
SkDstOutXfermode(const ProcCoeff & rec)1454     SkDstOutXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstOut_Mode) {}
1455 
1456     typedef SkProcCoeffXfermode INHERITED;
1457 };
1458 
xfer32(SkPMColor * SK_RESTRICT dst,const SkPMColor * SK_RESTRICT src,int count,const SkAlpha * SK_RESTRICT aa) const1459 void SkDstOutXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
1460                               const SkPMColor* SK_RESTRICT src, int count,
1461                               const SkAlpha* SK_RESTRICT aa) const {
1462     SkASSERT(dst && src);
1463 
1464     if (count <= 0) {
1465         return;
1466     }
1467     if (aa) {
1468         return this->INHERITED::xfer32(dst, src, count, aa);
1469     }
1470 
1471     do {
1472         unsigned a = SkGetPackedA32(*src);
1473         *dst = SkAlphaMulQ(*dst, SkAlpha255To256(255 - a));
1474         dst++;
1475         src++;
1476     } while (--count != 0);
1477 }
1478 
1479 #ifndef SK_IGNORE_TO_STRING
toString(SkString * str) const1480 void SkDstOutXfermode::toString(SkString* str) const {
1481     this->INHERITED::toString(str);
1482 }
1483 #endif
1484 
1485 ///////////////////////////////////////////////////////////////////////////////
1486 
1487 extern SkProcCoeffXfermode* SkPlatformXfermodeFactory(const ProcCoeff& rec, SkXfermode::Mode mode);
1488 extern SkXfermodeProc SkPlatformXfermodeProcFactory(SkXfermode::Mode mode);
1489 
1490 // Technically, can't be static and passed as a template parameter.  So we use anonymous namespace.
1491 namespace {
create_mode(int iMode)1492 SkXfermode* create_mode(int iMode) {
1493     SkXfermode::Mode mode = (SkXfermode::Mode)iMode;
1494 
1495     ProcCoeff rec = gProcCoeffs[mode];
1496     SkXfermodeProc pp = SkPlatformXfermodeProcFactory(mode);
1497     if (pp != NULL) {
1498         rec.fProc = pp;
1499     }
1500 
1501 #if defined(SK_4PX_XFERMODES_ARE_FAST) && !defined(SK_PREFER_LEGACY_FLOAT_XFERMODES)
1502     switch (mode) {
1503         case SkXfermode::kSrcATop_Mode:    return SkT4pxXfermode<SrcATop4f>::Create(rec);
1504         case SkXfermode::kDstATop_Mode:    return SkT4pxXfermode<DstATop4f>::Create(rec);
1505         case SkXfermode::kXor_Mode:        return SkT4pxXfermode<Xor4f>::Create(rec);
1506         case SkXfermode::kPlus_Mode:       return SkT4pxXfermode<Plus4f>::Create(rec);
1507         case SkXfermode::kModulate_Mode:   return SkT4pxXfermode<Modulate4f>::Create(rec);
1508         case SkXfermode::kScreen_Mode:     return SkT4pxXfermode<Screen4f>::Create(rec);
1509         case SkXfermode::kMultiply_Mode:   return SkT4pxXfermode<Multiply4f>::Create(rec);
1510         case SkXfermode::kDifference_Mode: return SkT4pxXfermode<Difference4f>::Create(rec);
1511         case SkXfermode::kExclusion_Mode:  return SkT4pxXfermode<Exclusion4f>::Create(rec);
1512         default: break;
1513     }
1514 #endif
1515 
1516 #if defined(SK_4F_XFERMODES_ARE_FAST)
1517     switch (mode) {
1518         case SkXfermode::kSrcATop_Mode:    return SkT4fXfermode<SrcATop4f>::Create(rec);
1519         case SkXfermode::kDstATop_Mode:    return SkT4fXfermode<DstATop4f>::Create(rec);
1520         case SkXfermode::kXor_Mode:        return SkT4fXfermode<Xor4f>::Create(rec);
1521         case SkXfermode::kPlus_Mode:       return SkT4fXfermode<Plus4f>::Create(rec);
1522         case SkXfermode::kModulate_Mode:   return SkT4fXfermode<Modulate4f>::Create(rec);
1523         case SkXfermode::kScreen_Mode:     return SkT4fXfermode<Screen4f>::Create(rec);
1524         case SkXfermode::kMultiply_Mode:   return SkT4fXfermode<Multiply4f>::Create(rec);
1525         case SkXfermode::kDifference_Mode: return SkT4fXfermode<Difference4f>::Create(rec);
1526         case SkXfermode::kExclusion_Mode:  return SkT4fXfermode<Exclusion4f>::Create(rec);
1527         default: break;
1528     }
1529 #endif
1530 
1531     SkXfermode* xfer = NULL;
1532 
1533     // check if we have a platform optim for that
1534     SkProcCoeffXfermode* xfm = SkPlatformXfermodeFactory(rec, mode);
1535     if (xfm != NULL) {
1536         xfer = xfm;
1537     } else {
1538         // All modes can in theory be represented by the ProcCoeff rec, since
1539         // it contains function ptrs. However, a few modes are both simple and
1540         // commonly used, so we call those out for their own subclasses here.
1541         switch (mode) {
1542             case SkXfermode::kClear_Mode:
1543                 xfer = SkClearXfermode::Create(rec);
1544                 break;
1545             case SkXfermode::kSrc_Mode:
1546                 xfer = SkSrcXfermode::Create(rec);
1547                 break;
1548             case SkXfermode::kSrcOver_Mode:
1549                 SkASSERT(false);    // should not land here
1550                 break;
1551             case SkXfermode::kDstIn_Mode:
1552                 xfer = SkDstInXfermode::Create(rec);
1553                 break;
1554             case SkXfermode::kDstOut_Mode:
1555                 xfer = SkDstOutXfermode::Create(rec);
1556                 break;
1557             default:
1558                 // no special-case, just rely in the rec and its function-ptrs
1559                 xfer = SkNEW_ARGS(SkProcCoeffXfermode, (rec, mode));
1560                 break;
1561         }
1562     }
1563     return xfer;
1564 }
1565 }  // namespace
1566 
1567 SK_DECLARE_STATIC_LAZY_PTR_ARRAY(SkXfermode, cached, SkXfermode::kLastMode + 1, create_mode);
1568 
Create(Mode mode)1569 SkXfermode* SkXfermode::Create(Mode mode) {
1570     SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount);
1571 
1572     if ((unsigned)mode >= kModeCount) {
1573         // report error
1574         return NULL;
1575     }
1576 
1577     // Skia's "default" mode is srcover. NULL in SkPaint is interpreted as srcover
1578     // so we can just return NULL from the factory.
1579     if (kSrcOver_Mode == mode) {
1580         return NULL;
1581     }
1582 
1583     return SkSafeRef(cached[mode]);
1584 }
1585 
GetProc(Mode mode)1586 SkXfermodeProc SkXfermode::GetProc(Mode mode) {
1587     SkXfermodeProc  proc = NULL;
1588     if ((unsigned)mode < kModeCount) {
1589         proc = gProcCoeffs[mode].fProc;
1590     }
1591     return proc;
1592 }
1593 
ModeAsCoeff(Mode mode,Coeff * src,Coeff * dst)1594 bool SkXfermode::ModeAsCoeff(Mode mode, Coeff* src, Coeff* dst) {
1595     SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount);
1596 
1597     if ((unsigned)mode >= (unsigned)kModeCount) {
1598         // illegal mode parameter
1599         return false;
1600     }
1601 
1602     const ProcCoeff& rec = gProcCoeffs[mode];
1603 
1604     if (CANNOT_USE_COEFF == rec.fSC) {
1605         return false;
1606     }
1607 
1608     SkASSERT(CANNOT_USE_COEFF != rec.fDC);
1609     if (src) {
1610         *src = rec.fSC;
1611     }
1612     if (dst) {
1613         *dst = rec.fDC;
1614     }
1615     return true;
1616 }
1617 
AsMode(const SkXfermode * xfer,Mode * mode)1618 bool SkXfermode::AsMode(const SkXfermode* xfer, Mode* mode) {
1619     if (NULL == xfer) {
1620         if (mode) {
1621             *mode = kSrcOver_Mode;
1622         }
1623         return true;
1624     }
1625     return xfer->asMode(mode);
1626 }
1627 
IsMode(const SkXfermode * xfer,Mode mode)1628 bool SkXfermode::IsMode(const SkXfermode* xfer, Mode mode) {
1629     // if xfer==null then the mode is srcover
1630     Mode m = kSrcOver_Mode;
1631     if (xfer && !xfer->asMode(&m)) {
1632         return false;
1633     }
1634     return mode == m;
1635 }
1636 
SupportsCoverageAsAlpha(const SkXfermode * xfer)1637 bool SkXfermode::SupportsCoverageAsAlpha(const SkXfermode* xfer) {
1638     // if xfer is NULL we treat it as srcOver which always supports coverageAsAlpha
1639     if (!xfer) {
1640         return true;
1641     }
1642 
1643     return xfer->supportsCoverageAsAlpha();
1644 }
1645 
IsOpaque(const SkXfermode * xfer,SrcColorOpacity opacityType)1646 bool SkXfermode::IsOpaque(const SkXfermode* xfer, SrcColorOpacity opacityType) {
1647     // if xfer is NULL we treat it as srcOver which is opaque if our src is opaque
1648     if (!xfer) {
1649         return SkXfermode::kOpaque_SrcColorOpacity == opacityType;
1650     }
1651 
1652     return xfer->isOpaque(opacityType);
1653 }
1654 
1655 ///////////////////////////////////////////////////////////////////////////////
1656 //////////// 16bit xfermode procs
1657 
1658 #ifdef SK_DEBUG
require_255(SkPMColor src)1659 static bool require_255(SkPMColor src) { return SkGetPackedA32(src) == 0xFF; }
require_0(SkPMColor src)1660 static bool require_0(SkPMColor src) { return SkGetPackedA32(src) == 0; }
1661 #endif
1662 
src_modeproc16_255(SkPMColor src,uint16_t dst)1663 static uint16_t src_modeproc16_255(SkPMColor src, uint16_t dst) {
1664     SkASSERT(require_255(src));
1665     return SkPixel32ToPixel16(src);
1666 }
1667 
dst_modeproc16(SkPMColor src,uint16_t dst)1668 static uint16_t dst_modeproc16(SkPMColor src, uint16_t dst) {
1669     return dst;
1670 }
1671 
srcover_modeproc16_0(SkPMColor src,uint16_t dst)1672 static uint16_t srcover_modeproc16_0(SkPMColor src, uint16_t dst) {
1673     SkASSERT(require_0(src));
1674     return dst;
1675 }
1676 
srcover_modeproc16_255(SkPMColor src,uint16_t dst)1677 static uint16_t srcover_modeproc16_255(SkPMColor src, uint16_t dst) {
1678     SkASSERT(require_255(src));
1679     return SkPixel32ToPixel16(src);
1680 }
1681 
dstover_modeproc16_0(SkPMColor src,uint16_t dst)1682 static uint16_t dstover_modeproc16_0(SkPMColor src, uint16_t dst) {
1683     SkASSERT(require_0(src));
1684     return dst;
1685 }
1686 
dstover_modeproc16_255(SkPMColor src,uint16_t dst)1687 static uint16_t dstover_modeproc16_255(SkPMColor src, uint16_t dst) {
1688     SkASSERT(require_255(src));
1689     return dst;
1690 }
1691 
srcin_modeproc16_255(SkPMColor src,uint16_t dst)1692 static uint16_t srcin_modeproc16_255(SkPMColor src, uint16_t dst) {
1693     SkASSERT(require_255(src));
1694     return SkPixel32ToPixel16(src);
1695 }
1696 
dstin_modeproc16_255(SkPMColor src,uint16_t dst)1697 static uint16_t dstin_modeproc16_255(SkPMColor src, uint16_t dst) {
1698     SkASSERT(require_255(src));
1699     return dst;
1700 }
1701 
dstout_modeproc16_0(SkPMColor src,uint16_t dst)1702 static uint16_t dstout_modeproc16_0(SkPMColor src, uint16_t dst) {
1703     SkASSERT(require_0(src));
1704     return dst;
1705 }
1706 
srcatop_modeproc16(SkPMColor src,uint16_t dst)1707 static uint16_t srcatop_modeproc16(SkPMColor src, uint16_t dst) {
1708     unsigned isa = 255 - SkGetPackedA32(src);
1709 
1710     return SkPackRGB16(
1711            SkPacked32ToR16(src) + SkAlphaMulAlpha(SkGetPackedR16(dst), isa),
1712            SkPacked32ToG16(src) + SkAlphaMulAlpha(SkGetPackedG16(dst), isa),
1713            SkPacked32ToB16(src) + SkAlphaMulAlpha(SkGetPackedB16(dst), isa));
1714 }
1715 
srcatop_modeproc16_0(SkPMColor src,uint16_t dst)1716 static uint16_t srcatop_modeproc16_0(SkPMColor src, uint16_t dst) {
1717     SkASSERT(require_0(src));
1718     return dst;
1719 }
1720 
srcatop_modeproc16_255(SkPMColor src,uint16_t dst)1721 static uint16_t srcatop_modeproc16_255(SkPMColor src, uint16_t dst) {
1722     SkASSERT(require_255(src));
1723     return SkPixel32ToPixel16(src);
1724 }
1725 
dstatop_modeproc16_255(SkPMColor src,uint16_t dst)1726 static uint16_t dstatop_modeproc16_255(SkPMColor src, uint16_t dst) {
1727     SkASSERT(require_255(src));
1728     return dst;
1729 }
1730 
1731 /*********
1732     darken and lighten boil down to this.
1733 
1734     darken  = (1 - Sa) * Dc + min(Sc, Dc)
1735     lighten = (1 - Sa) * Dc + max(Sc, Dc)
1736 
1737     if (Sa == 0) these become
1738         darken  = Dc + min(0, Dc) = 0
1739         lighten = Dc + max(0, Dc) = Dc
1740 
1741     if (Sa == 1) these become
1742         darken  = min(Sc, Dc)
1743         lighten = max(Sc, Dc)
1744 */
1745 
darken_modeproc16_0(SkPMColor src,uint16_t dst)1746 static uint16_t darken_modeproc16_0(SkPMColor src, uint16_t dst) {
1747     SkASSERT(require_0(src));
1748     return 0;
1749 }
1750 
darken_modeproc16_255(SkPMColor src,uint16_t dst)1751 static uint16_t darken_modeproc16_255(SkPMColor src, uint16_t dst) {
1752     SkASSERT(require_255(src));
1753     unsigned r = SkFastMin32(SkPacked32ToR16(src), SkGetPackedR16(dst));
1754     unsigned g = SkFastMin32(SkPacked32ToG16(src), SkGetPackedG16(dst));
1755     unsigned b = SkFastMin32(SkPacked32ToB16(src), SkGetPackedB16(dst));
1756     return SkPackRGB16(r, g, b);
1757 }
1758 
lighten_modeproc16_0(SkPMColor src,uint16_t dst)1759 static uint16_t lighten_modeproc16_0(SkPMColor src, uint16_t dst) {
1760     SkASSERT(require_0(src));
1761     return dst;
1762 }
1763 
lighten_modeproc16_255(SkPMColor src,uint16_t dst)1764 static uint16_t lighten_modeproc16_255(SkPMColor src, uint16_t dst) {
1765     SkASSERT(require_255(src));
1766     unsigned r = SkMax32(SkPacked32ToR16(src), SkGetPackedR16(dst));
1767     unsigned g = SkMax32(SkPacked32ToG16(src), SkGetPackedG16(dst));
1768     unsigned b = SkMax32(SkPacked32ToB16(src), SkGetPackedB16(dst));
1769     return SkPackRGB16(r, g, b);
1770 }
1771 
1772 struct Proc16Rec {
1773     SkXfermodeProc16    fProc16_0;
1774     SkXfermodeProc16    fProc16_255;
1775     SkXfermodeProc16    fProc16_General;
1776 };
1777 
1778 static const Proc16Rec gModeProcs16[] = {
1779     { NULL,                 NULL,                   NULL            }, // CLEAR
1780     { NULL,                 src_modeproc16_255,     NULL            },
1781     { dst_modeproc16,       dst_modeproc16,         dst_modeproc16  },
1782     { srcover_modeproc16_0, srcover_modeproc16_255, NULL            },
1783     { dstover_modeproc16_0, dstover_modeproc16_255, NULL            },
1784     { NULL,                 srcin_modeproc16_255,   NULL            },
1785     { NULL,                 dstin_modeproc16_255,   NULL            },
1786     { NULL,                 NULL,                   NULL            },// SRC_OUT
1787     { dstout_modeproc16_0,  NULL,                   NULL            },
1788     { srcatop_modeproc16_0, srcatop_modeproc16_255, srcatop_modeproc16  },
1789     { NULL,                 dstatop_modeproc16_255, NULL            },
1790     { NULL,                 NULL,                   NULL            }, // XOR
1791 
1792     { NULL,                 NULL,                   NULL            }, // plus
1793     { NULL,                 NULL,                   NULL            }, // modulate
1794     { NULL,                 NULL,                   NULL            }, // screen
1795     { NULL,                 NULL,                   NULL            }, // overlay
1796     { darken_modeproc16_0,  darken_modeproc16_255,  NULL            }, // darken
1797     { lighten_modeproc16_0, lighten_modeproc16_255, NULL            }, // lighten
1798     { NULL,                 NULL,                   NULL            }, // colordodge
1799     { NULL,                 NULL,                   NULL            }, // colorburn
1800     { NULL,                 NULL,                   NULL            }, // hardlight
1801     { NULL,                 NULL,                   NULL            }, // softlight
1802     { NULL,                 NULL,                   NULL            }, // difference
1803     { NULL,                 NULL,                   NULL            }, // exclusion
1804     { NULL,                 NULL,                   NULL            }, // multiply
1805     { NULL,                 NULL,                   NULL            }, // hue
1806     { NULL,                 NULL,                   NULL            }, // saturation
1807     { NULL,                 NULL,                   NULL            }, // color
1808     { NULL,                 NULL,                   NULL            }, // luminosity
1809 };
1810 
GetProc16(Mode mode,SkColor srcColor)1811 SkXfermodeProc16 SkXfermode::GetProc16(Mode mode, SkColor srcColor) {
1812     SkXfermodeProc16  proc16 = NULL;
1813     if ((unsigned)mode < kModeCount) {
1814         const Proc16Rec& rec = gModeProcs16[mode];
1815         unsigned a = SkColorGetA(srcColor);
1816 
1817         if (0 == a) {
1818             proc16 = rec.fProc16_0;
1819         } else if (255 == a) {
1820             proc16 = rec.fProc16_255;
1821         } else {
1822             proc16 = rec.fProc16_General;
1823         }
1824     }
1825     return proc16;
1826 }
1827 
1828 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkXfermode)
1829     SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkProcCoeffXfermode)
1830 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
1831