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