SkXfermode.cpp revision 54f0e9d784122cfd3f5968e0fea971d5b5a4805a
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
29static 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
41static 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
51static 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
60static 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]
73static SkPMColor clear_modeproc(SkPMColor src, SkPMColor dst) {
74    return 0;
75}
76
77//  kSrc_Mode,      //!< [Sa, Sc]
78static SkPMColor src_modeproc(SkPMColor src, SkPMColor dst) {
79    return src;
80}
81
82//  kDst_Mode,      //!< [Da, Dc]
83static SkPMColor dst_modeproc(SkPMColor src, SkPMColor dst) {
84    return dst;
85}
86
87//  kSrcOver_Mode,  //!< [Sa + Da - Sa*Da, Sc + (1 - Sa)*Dc]
88static 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]
101static 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]
108static SkPMColor srcin_modeproc(SkPMColor src, SkPMColor dst) {
109    return SkAlphaMulQ(src, SkAlpha255To256(SkGetPackedA32(dst)));
110}
111
112//  kDstIn_Mode,    //!< [Sa * Da, Sa * Dc]
113static 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)]
118static 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)]
123static 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]
128static 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)]
143static 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]
158static 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
176static 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
185static 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
193static 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
200static 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
204static 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
215static 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
224static 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}
234static 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
245static 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}
256static 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
267static 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}
278static 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
289static 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}
302static 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
313static 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}
326static 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
337static 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}
346static 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)
357static U8CPU sqrt_unit_byte(U8CPU n) {
358    return SkSqrtBits(n, 15+4);
359}
360
361// kSoftLight_Mode
362static 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}
376static 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
387static 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}
391static 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
402static 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}
410static 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
425static inline int Lum(int r, int g, int b)
426{
427    return SkDiv255Round(r * 77 + g * 150 + b * 28);
428}
429
430static inline int min2(int a, int b) { return a < b ? a : b; }
431static 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
435static inline int Sat(int r, int g, int b) {
436    return maximum(r, g, b) - minimum(r, g, b);
437}
438
439static 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
451static 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
469static 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
488static 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.
504static 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.
538static 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.
572static 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.
605static 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
635const 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
670bool SkXfermode::asCoeff(Coeff* src, Coeff* dst) const {
671    return false;
672}
673
674bool SkXfermode::asMode(Mode* mode) const {
675    return false;
676}
677
678bool SkXfermode::asFragmentProcessor(GrFragmentProcessor**, GrTexture*) const {
679    return false;
680}
681
682bool SkXfermode::asXPFactory(GrXPFactory**) const {
683    return false;
684}
685
686
687#if SK_SUPPORT_GPU
688#include "effects/GrPorterDuffXferProcessor.h"
689
690bool SkXfermode::AsFragmentProcessorOrXPFactory(SkXfermode* xfermode,
691                                                GrFragmentProcessor** fp,
692                                                GrXPFactory** xpf) {
693    Coeff src, dst;
694    Mode mode;
695    if (NULL == xfermode) {
696        *xpf = GrPorterDuffXPFactory::Create(kSrcOver_Mode);
697        return true;
698    } else if (xfermode->asMode(&mode) && mode <= kLastCoeffMode) {
699        *xpf = GrPorterDuffXPFactory::Create(mode);
700        return true;
701    } else if (xfermode->asCoeff(&src, &dst)) {
702        *xpf = GrPorterDuffXPFactory::Create(src, dst);
703        return true;
704    } else if (xfermode->asXPFactory(xpf)) {
705        return true;
706    } else {
707        return xfermode->asFragmentProcessor(fp, NULL);
708    }
709}
710#else
711bool SkXfermode::AsFragmentProcessorOrXPFactory(SkXfermode* xfermode,
712                                                GrFragmentProcessor** fp,
713                                                GrXPFactory** xpf) {
714    return false;
715}
716#endif
717
718SkPMColor SkXfermode::xferColor(SkPMColor src, SkPMColor dst) const{
719    // no-op. subclasses should override this
720    return dst;
721}
722
723void SkXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
724                        const SkPMColor* SK_RESTRICT src, int count,
725                        const SkAlpha* SK_RESTRICT aa) const {
726    SkASSERT(dst && src && count >= 0);
727
728    if (NULL == aa) {
729        for (int i = count - 1; i >= 0; --i) {
730            dst[i] = this->xferColor(src[i], dst[i]);
731        }
732    } else {
733        for (int i = count - 1; i >= 0; --i) {
734            unsigned a = aa[i];
735            if (0 != a) {
736                SkPMColor dstC = dst[i];
737                SkPMColor C = this->xferColor(src[i], dstC);
738                if (0xFF != a) {
739                    C = SkFourByteInterp(C, dstC, a);
740                }
741                dst[i] = C;
742            }
743        }
744    }
745}
746
747void SkXfermode::xfer16(uint16_t* dst,
748                        const SkPMColor* SK_RESTRICT src, int count,
749                        const SkAlpha* SK_RESTRICT aa) const {
750    SkASSERT(dst && src && count >= 0);
751
752    if (NULL == aa) {
753        for (int i = count - 1; i >= 0; --i) {
754            SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
755            dst[i] = SkPixel32ToPixel16_ToU16(this->xferColor(src[i], dstC));
756        }
757    } else {
758        for (int i = count - 1; i >= 0; --i) {
759            unsigned a = aa[i];
760            if (0 != a) {
761                SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
762                SkPMColor C = this->xferColor(src[i], dstC);
763                if (0xFF != a) {
764                    C = SkFourByteInterp(C, dstC, a);
765                }
766                dst[i] = SkPixel32ToPixel16_ToU16(C);
767            }
768        }
769    }
770}
771
772void SkXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
773                        const SkPMColor src[], int count,
774                        const SkAlpha* SK_RESTRICT aa) const {
775    SkASSERT(dst && src && count >= 0);
776
777    if (NULL == aa) {
778        for (int i = count - 1; i >= 0; --i) {
779            SkPMColor res = this->xferColor(src[i], (dst[i] << SK_A32_SHIFT));
780            dst[i] = SkToU8(SkGetPackedA32(res));
781        }
782    } else {
783        for (int i = count - 1; i >= 0; --i) {
784            unsigned a = aa[i];
785            if (0 != a) {
786                SkAlpha dstA = dst[i];
787                unsigned A = SkGetPackedA32(this->xferColor(src[i],
788                                            (SkPMColor)(dstA << SK_A32_SHIFT)));
789                if (0xFF != a) {
790                    A = SkAlphaBlend(A, dstA, SkAlpha255To256(a));
791                }
792                dst[i] = SkToU8(A);
793            }
794        }
795    }
796}
797
798///////////////////////////////////////////////////////////////////////////////
799///////////////////////////////////////////////////////////////////////////////
800
801SkFlattenable* SkProcCoeffXfermode::CreateProc(SkReadBuffer& buffer) {
802    uint32_t mode32 = buffer.read32();
803    if (!buffer.validate(mode32 < SK_ARRAY_COUNT(gProcCoeffs))) {
804        return NULL;
805    }
806    return SkXfermode::Create((SkXfermode::Mode)mode32);
807}
808
809void SkProcCoeffXfermode::flatten(SkWriteBuffer& buffer) const {
810    buffer.write32(fMode);
811}
812
813bool SkProcCoeffXfermode::asMode(Mode* mode) const {
814    if (mode) {
815        *mode = fMode;
816    }
817    return true;
818}
819
820bool SkProcCoeffXfermode::asCoeff(Coeff* sc, Coeff* dc) const {
821    if (CANNOT_USE_COEFF == fSrcCoeff) {
822        return false;
823    }
824
825    if (sc) {
826        *sc = fSrcCoeff;
827    }
828    if (dc) {
829        *dc = fDstCoeff;
830    }
831    return true;
832}
833
834void SkProcCoeffXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
835                                 const SkPMColor* SK_RESTRICT src, int count,
836                                 const SkAlpha* SK_RESTRICT aa) const {
837    SkASSERT(dst && src && count >= 0);
838
839    SkXfermodeProc proc = fProc;
840
841    if (proc) {
842        if (NULL == aa) {
843            for (int i = count - 1; i >= 0; --i) {
844                dst[i] = proc(src[i], dst[i]);
845            }
846        } else {
847            for (int i = count - 1; i >= 0; --i) {
848                unsigned a = aa[i];
849                if (0 != a) {
850                    SkPMColor dstC = dst[i];
851                    SkPMColor C = proc(src[i], dstC);
852                    if (a != 0xFF) {
853                        C = SkFourByteInterp(C, dstC, a);
854                    }
855                    dst[i] = C;
856                }
857            }
858        }
859    }
860}
861
862void SkProcCoeffXfermode::xfer16(uint16_t* SK_RESTRICT dst,
863                                 const SkPMColor* SK_RESTRICT src, int count,
864                                 const SkAlpha* SK_RESTRICT aa) const {
865    SkASSERT(dst && src && count >= 0);
866
867    SkXfermodeProc proc = fProc;
868
869    if (proc) {
870        if (NULL == aa) {
871            for (int i = count - 1; i >= 0; --i) {
872                SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
873                dst[i] = SkPixel32ToPixel16_ToU16(proc(src[i], dstC));
874            }
875        } else {
876            for (int i = count - 1; i >= 0; --i) {
877                unsigned a = aa[i];
878                if (0 != a) {
879                    SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
880                    SkPMColor C = proc(src[i], dstC);
881                    if (0xFF != a) {
882                        C = SkFourByteInterp(C, dstC, a);
883                    }
884                    dst[i] = SkPixel32ToPixel16_ToU16(C);
885                }
886            }
887        }
888    }
889}
890
891void SkProcCoeffXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
892                                 const SkPMColor* SK_RESTRICT src, int count,
893                                 const SkAlpha* SK_RESTRICT aa) const {
894    SkASSERT(dst && src && count >= 0);
895
896    SkXfermodeProc proc = fProc;
897
898    if (proc) {
899        if (NULL == aa) {
900            for (int i = count - 1; i >= 0; --i) {
901                SkPMColor res = proc(src[i], dst[i] << SK_A32_SHIFT);
902                dst[i] = SkToU8(SkGetPackedA32(res));
903            }
904        } else {
905            for (int i = count - 1; i >= 0; --i) {
906                unsigned a = aa[i];
907                if (0 != a) {
908                    SkAlpha dstA = dst[i];
909                    SkPMColor res = proc(src[i], dstA << SK_A32_SHIFT);
910                    unsigned A = SkGetPackedA32(res);
911                    if (0xFF != a) {
912                        A = SkAlphaBlend(A, dstA, SkAlpha255To256(a));
913                    }
914                    dst[i] = SkToU8(A);
915                }
916            }
917        }
918    }
919}
920
921#if SK_SUPPORT_GPU
922#include "effects/GrCustomXfermode.h"
923
924bool SkProcCoeffXfermode::asFragmentProcessor(GrFragmentProcessor** fp,
925                                              GrTexture* background) const {
926    if (GrCustomXfermode::IsSupportedMode(fMode)) {
927        if (fp) {
928            *fp = GrCustomXfermode::CreateFP(fMode, background);
929            SkASSERT(*fp);
930        }
931        return true;
932    }
933    return false;
934}
935
936bool SkProcCoeffXfermode::asXPFactory(GrXPFactory** xp) const {
937    if (GrCustomXfermode::IsSupportedMode(fMode)) {
938        if (xp) {
939            *xp = GrCustomXfermode::CreateXPFactory(fMode);
940            SkASSERT(*xp);
941        }
942        return true;
943    }
944    return false;
945}
946#endif
947
948const char* SkXfermode::ModeName(Mode mode) {
949    SkASSERT((unsigned) mode <= (unsigned)kLastMode);
950    const char* gModeStrings[] = {
951        "Clear", "Src", "Dst", "SrcOver", "DstOver", "SrcIn", "DstIn",
952        "SrcOut", "DstOut", "SrcATop", "DstATop", "Xor", "Plus",
953        "Modulate", "Screen", "Overlay", "Darken", "Lighten", "ColorDodge",
954        "ColorBurn", "HardLight", "SoftLight", "Difference", "Exclusion",
955        "Multiply", "Hue", "Saturation", "Color",  "Luminosity"
956    };
957    return gModeStrings[mode];
958    SK_COMPILE_ASSERT(SK_ARRAY_COUNT(gModeStrings) == kLastMode + 1, mode_count);
959}
960
961#ifndef SK_IGNORE_TO_STRING
962void SkProcCoeffXfermode::toString(SkString* str) const {
963    str->append("SkProcCoeffXfermode: ");
964
965    str->append("mode: ");
966    str->append(ModeName(fMode));
967
968    static const char* gCoeffStrings[kCoeffCount] = {
969        "Zero", "One", "SC", "ISC", "DC", "IDC", "SA", "ISA", "DA", "IDA"
970    };
971
972    str->append(" src: ");
973    if (CANNOT_USE_COEFF == fSrcCoeff) {
974        str->append("can't use");
975    } else {
976        str->append(gCoeffStrings[fSrcCoeff]);
977    }
978
979    str->append(" dst: ");
980    if (CANNOT_USE_COEFF == fDstCoeff) {
981        str->append("can't use");
982    } else {
983        str->append(gCoeffStrings[fDstCoeff]);
984    }
985}
986#endif
987
988///////////////////////////////////////////////////////////////////////////////
989
990class SkClearXfermode : public SkProcCoeffXfermode {
991public:
992    static SkClearXfermode* Create(const ProcCoeff& rec) {
993        return SkNEW_ARGS(SkClearXfermode, (rec));
994    }
995
996    void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
997    void xferA8(SkAlpha*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
998
999    SK_TO_STRING_OVERRIDE()
1000
1001private:
1002    SkClearXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kClear_Mode) {}
1003
1004    typedef SkProcCoeffXfermode INHERITED;
1005};
1006
1007void SkClearXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
1008                             const SkPMColor* SK_RESTRICT, int count,
1009                             const SkAlpha* SK_RESTRICT aa) const {
1010    SkASSERT(dst && count >= 0);
1011
1012    if (NULL == aa) {
1013        memset(dst, 0, count << 2);
1014    } else {
1015        for (int i = count - 1; i >= 0; --i) {
1016            unsigned a = aa[i];
1017            if (0xFF == a) {
1018                dst[i] = 0;
1019            } else if (a != 0) {
1020                dst[i] = SkAlphaMulQ(dst[i], SkAlpha255To256(255 - a));
1021            }
1022        }
1023    }
1024}
1025void SkClearXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
1026                             const SkPMColor* SK_RESTRICT, int count,
1027                             const SkAlpha* SK_RESTRICT aa) const {
1028    SkASSERT(dst && count >= 0);
1029
1030    if (NULL == aa) {
1031        memset(dst, 0, count);
1032    } else {
1033        for (int i = count - 1; i >= 0; --i) {
1034            unsigned a = aa[i];
1035            if (0xFF == a) {
1036                dst[i] = 0;
1037            } else if (0 != a) {
1038                dst[i] = SkAlphaMulAlpha(dst[i], 255 - a);
1039            }
1040        }
1041    }
1042}
1043
1044#ifndef SK_IGNORE_TO_STRING
1045void SkClearXfermode::toString(SkString* str) const {
1046    this->INHERITED::toString(str);
1047}
1048#endif
1049
1050///////////////////////////////////////////////////////////////////////////////
1051
1052class SkSrcXfermode : public SkProcCoeffXfermode {
1053public:
1054    static SkSrcXfermode* Create(const ProcCoeff& rec) {
1055        return SkNEW_ARGS(SkSrcXfermode, (rec));
1056    }
1057
1058    void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
1059    void xferA8(SkAlpha*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
1060
1061    SK_TO_STRING_OVERRIDE()
1062
1063private:
1064    SkSrcXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kSrc_Mode) {}
1065    typedef SkProcCoeffXfermode INHERITED;
1066};
1067
1068void SkSrcXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
1069                           const SkPMColor* SK_RESTRICT src, int count,
1070                           const SkAlpha* SK_RESTRICT aa) const {
1071    SkASSERT(dst && src && count >= 0);
1072
1073    if (NULL == aa) {
1074        memcpy(dst, src, count << 2);
1075    } else {
1076        for (int i = count - 1; i >= 0; --i) {
1077            unsigned a = aa[i];
1078            if (a == 0xFF) {
1079                dst[i] = src[i];
1080            } else if (a != 0) {
1081                dst[i] = SkFourByteInterp(src[i], dst[i], a);
1082            }
1083        }
1084    }
1085}
1086
1087void SkSrcXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
1088                           const SkPMColor* SK_RESTRICT src, int count,
1089                           const SkAlpha* SK_RESTRICT aa) const {
1090    SkASSERT(dst && src && count >= 0);
1091
1092    if (NULL == aa) {
1093        for (int i = count - 1; i >= 0; --i) {
1094            dst[i] = SkToU8(SkGetPackedA32(src[i]));
1095        }
1096    } else {
1097        for (int i = count - 1; i >= 0; --i) {
1098            unsigned a = aa[i];
1099            if (0 != a) {
1100                unsigned srcA = SkGetPackedA32(src[i]);
1101                if (a == 0xFF) {
1102                    dst[i] = SkToU8(srcA);
1103                } else {
1104                    dst[i] = SkToU8(SkAlphaBlend(srcA, dst[i], a));
1105                }
1106            }
1107        }
1108    }
1109}
1110#ifndef SK_IGNORE_TO_STRING
1111void SkSrcXfermode::toString(SkString* str) const {
1112    this->INHERITED::toString(str);
1113}
1114#endif
1115
1116///////////////////////////////////////////////////////////////////////////////
1117
1118class SkDstInXfermode : public SkProcCoeffXfermode {
1119public:
1120    static SkDstInXfermode* Create(const ProcCoeff& rec) {
1121        return SkNEW_ARGS(SkDstInXfermode, (rec));
1122    }
1123
1124    void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
1125
1126    SK_TO_STRING_OVERRIDE()
1127
1128private:
1129    SkDstInXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstIn_Mode) {}
1130
1131    typedef SkProcCoeffXfermode INHERITED;
1132};
1133
1134void SkDstInXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
1135                             const SkPMColor* SK_RESTRICT src, int count,
1136                             const SkAlpha* SK_RESTRICT aa) const {
1137    SkASSERT(dst && src);
1138
1139    if (count <= 0) {
1140        return;
1141    }
1142    if (aa) {
1143        return this->INHERITED::xfer32(dst, src, count, aa);
1144    }
1145
1146    do {
1147        unsigned a = SkGetPackedA32(*src);
1148        *dst = SkAlphaMulQ(*dst, SkAlpha255To256(a));
1149        dst++;
1150        src++;
1151    } while (--count != 0);
1152}
1153
1154#ifndef SK_IGNORE_TO_STRING
1155void SkDstInXfermode::toString(SkString* str) const {
1156    this->INHERITED::toString(str);
1157}
1158#endif
1159
1160///////////////////////////////////////////////////////////////////////////////
1161
1162class SkDstOutXfermode : public SkProcCoeffXfermode {
1163public:
1164    static SkDstOutXfermode* Create(const ProcCoeff& rec) {
1165        return SkNEW_ARGS(SkDstOutXfermode, (rec));
1166    }
1167
1168    void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
1169
1170    SK_TO_STRING_OVERRIDE()
1171
1172private:
1173    SkDstOutXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstOut_Mode) {}
1174
1175    typedef SkProcCoeffXfermode INHERITED;
1176};
1177
1178void SkDstOutXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
1179                              const SkPMColor* SK_RESTRICT src, int count,
1180                              const SkAlpha* SK_RESTRICT aa) const {
1181    SkASSERT(dst && src);
1182
1183    if (count <= 0) {
1184        return;
1185    }
1186    if (aa) {
1187        return this->INHERITED::xfer32(dst, src, count, aa);
1188    }
1189
1190    do {
1191        unsigned a = SkGetPackedA32(*src);
1192        *dst = SkAlphaMulQ(*dst, SkAlpha255To256(255 - a));
1193        dst++;
1194        src++;
1195    } while (--count != 0);
1196}
1197
1198#ifndef SK_IGNORE_TO_STRING
1199void SkDstOutXfermode::toString(SkString* str) const {
1200    this->INHERITED::toString(str);
1201}
1202#endif
1203
1204///////////////////////////////////////////////////////////////////////////////
1205
1206extern SkProcCoeffXfermode* SkPlatformXfermodeFactory(const ProcCoeff& rec, SkXfermode::Mode mode);
1207extern SkXfermodeProc SkPlatformXfermodeProcFactory(SkXfermode::Mode mode);
1208
1209// Technically, can't be static and passed as a template parameter.  So we use anonymous namespace.
1210namespace {
1211SkXfermode* create_mode(int iMode) {
1212    SkXfermode::Mode mode = (SkXfermode::Mode)iMode;
1213
1214    ProcCoeff rec = gProcCoeffs[mode];
1215    SkXfermodeProc pp = SkPlatformXfermodeProcFactory(mode);
1216    if (pp != NULL) {
1217        rec.fProc = pp;
1218    }
1219
1220    SkXfermode* xfer = NULL;
1221    // check if we have a platform optim for that
1222    SkProcCoeffXfermode* xfm = SkPlatformXfermodeFactory(rec, mode);
1223    if (xfm != NULL) {
1224        xfer = xfm;
1225    } else {
1226        // All modes can in theory be represented by the ProcCoeff rec, since
1227        // it contains function ptrs. However, a few modes are both simple and
1228        // commonly used, so we call those out for their own subclasses here.
1229        switch (mode) {
1230            case SkXfermode::kClear_Mode:
1231                xfer = SkClearXfermode::Create(rec);
1232                break;
1233            case SkXfermode::kSrc_Mode:
1234                xfer = SkSrcXfermode::Create(rec);
1235                break;
1236            case SkXfermode::kSrcOver_Mode:
1237                SkASSERT(false);    // should not land here
1238                break;
1239            case SkXfermode::kDstIn_Mode:
1240                xfer = SkDstInXfermode::Create(rec);
1241                break;
1242            case SkXfermode::kDstOut_Mode:
1243                xfer = SkDstOutXfermode::Create(rec);
1244                break;
1245            default:
1246                // no special-case, just rely in the rec and its function-ptrs
1247                xfer = SkNEW_ARGS(SkProcCoeffXfermode, (rec, mode));
1248                break;
1249        }
1250    }
1251    return xfer;
1252}
1253}  // namespace
1254
1255SK_DECLARE_STATIC_LAZY_PTR_ARRAY(SkXfermode, cached, SkXfermode::kLastMode + 1, create_mode);
1256
1257SkXfermode* SkXfermode::Create(Mode mode) {
1258    SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount);
1259
1260    if ((unsigned)mode >= kModeCount) {
1261        // report error
1262        return NULL;
1263    }
1264
1265    // Skia's "default" mode is srcover. NULL in SkPaint is interpreted as srcover
1266    // so we can just return NULL from the factory.
1267    if (kSrcOver_Mode == mode) {
1268        return NULL;
1269    }
1270
1271    return SkSafeRef(cached[mode]);
1272}
1273
1274SkXfermodeProc SkXfermode::GetProc(Mode mode) {
1275    SkXfermodeProc  proc = NULL;
1276    if ((unsigned)mode < kModeCount) {
1277        proc = gProcCoeffs[mode].fProc;
1278    }
1279    return proc;
1280}
1281
1282bool SkXfermode::ModeAsCoeff(Mode mode, Coeff* src, Coeff* dst) {
1283    SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount);
1284
1285    if ((unsigned)mode >= (unsigned)kModeCount) {
1286        // illegal mode parameter
1287        return false;
1288    }
1289
1290    const ProcCoeff& rec = gProcCoeffs[mode];
1291
1292    if (CANNOT_USE_COEFF == rec.fSC) {
1293        return false;
1294    }
1295
1296    SkASSERT(CANNOT_USE_COEFF != rec.fDC);
1297    if (src) {
1298        *src = rec.fSC;
1299    }
1300    if (dst) {
1301        *dst = rec.fDC;
1302    }
1303    return true;
1304}
1305
1306bool SkXfermode::AsMode(const SkXfermode* xfer, Mode* mode) {
1307    if (NULL == xfer) {
1308        if (mode) {
1309            *mode = kSrcOver_Mode;
1310        }
1311        return true;
1312    }
1313    return xfer->asMode(mode);
1314}
1315
1316bool SkXfermode::AsCoeff(const SkXfermode* xfer, Coeff* src, Coeff* dst) {
1317    if (NULL == xfer) {
1318        return ModeAsCoeff(kSrcOver_Mode, src, dst);
1319    }
1320    return xfer->asCoeff(src, dst);
1321}
1322
1323bool SkXfermode::IsMode(const SkXfermode* xfer, Mode mode) {
1324    // if xfer==null then the mode is srcover
1325    Mode m = kSrcOver_Mode;
1326    if (xfer && !xfer->asMode(&m)) {
1327        return false;
1328    }
1329    return mode == m;
1330}
1331
1332///////////////////////////////////////////////////////////////////////////////
1333//////////// 16bit xfermode procs
1334
1335#ifdef SK_DEBUG
1336static bool require_255(SkPMColor src) { return SkGetPackedA32(src) == 0xFF; }
1337static bool require_0(SkPMColor src) { return SkGetPackedA32(src) == 0; }
1338#endif
1339
1340static uint16_t src_modeproc16_255(SkPMColor src, uint16_t dst) {
1341    SkASSERT(require_255(src));
1342    return SkPixel32ToPixel16(src);
1343}
1344
1345static uint16_t dst_modeproc16(SkPMColor src, uint16_t dst) {
1346    return dst;
1347}
1348
1349static uint16_t srcover_modeproc16_0(SkPMColor src, uint16_t dst) {
1350    SkASSERT(require_0(src));
1351    return dst;
1352}
1353
1354static uint16_t srcover_modeproc16_255(SkPMColor src, uint16_t dst) {
1355    SkASSERT(require_255(src));
1356    return SkPixel32ToPixel16(src);
1357}
1358
1359static uint16_t dstover_modeproc16_0(SkPMColor src, uint16_t dst) {
1360    SkASSERT(require_0(src));
1361    return dst;
1362}
1363
1364static uint16_t dstover_modeproc16_255(SkPMColor src, uint16_t dst) {
1365    SkASSERT(require_255(src));
1366    return dst;
1367}
1368
1369static uint16_t srcin_modeproc16_255(SkPMColor src, uint16_t dst) {
1370    SkASSERT(require_255(src));
1371    return SkPixel32ToPixel16(src);
1372}
1373
1374static uint16_t dstin_modeproc16_255(SkPMColor src, uint16_t dst) {
1375    SkASSERT(require_255(src));
1376    return dst;
1377}
1378
1379static uint16_t dstout_modeproc16_0(SkPMColor src, uint16_t dst) {
1380    SkASSERT(require_0(src));
1381    return dst;
1382}
1383
1384static uint16_t srcatop_modeproc16(SkPMColor src, uint16_t dst) {
1385    unsigned isa = 255 - SkGetPackedA32(src);
1386
1387    return SkPackRGB16(
1388           SkPacked32ToR16(src) + SkAlphaMulAlpha(SkGetPackedR16(dst), isa),
1389           SkPacked32ToG16(src) + SkAlphaMulAlpha(SkGetPackedG16(dst), isa),
1390           SkPacked32ToB16(src) + SkAlphaMulAlpha(SkGetPackedB16(dst), isa));
1391}
1392
1393static uint16_t srcatop_modeproc16_0(SkPMColor src, uint16_t dst) {
1394    SkASSERT(require_0(src));
1395    return dst;
1396}
1397
1398static uint16_t srcatop_modeproc16_255(SkPMColor src, uint16_t dst) {
1399    SkASSERT(require_255(src));
1400    return SkPixel32ToPixel16(src);
1401}
1402
1403static uint16_t dstatop_modeproc16_255(SkPMColor src, uint16_t dst) {
1404    SkASSERT(require_255(src));
1405    return dst;
1406}
1407
1408/*********
1409    darken and lighten boil down to this.
1410
1411    darken  = (1 - Sa) * Dc + min(Sc, Dc)
1412    lighten = (1 - Sa) * Dc + max(Sc, Dc)
1413
1414    if (Sa == 0) these become
1415        darken  = Dc + min(0, Dc) = 0
1416        lighten = Dc + max(0, Dc) = Dc
1417
1418    if (Sa == 1) these become
1419        darken  = min(Sc, Dc)
1420        lighten = max(Sc, Dc)
1421*/
1422
1423static uint16_t darken_modeproc16_0(SkPMColor src, uint16_t dst) {
1424    SkASSERT(require_0(src));
1425    return 0;
1426}
1427
1428static uint16_t darken_modeproc16_255(SkPMColor src, uint16_t dst) {
1429    SkASSERT(require_255(src));
1430    unsigned r = SkFastMin32(SkPacked32ToR16(src), SkGetPackedR16(dst));
1431    unsigned g = SkFastMin32(SkPacked32ToG16(src), SkGetPackedG16(dst));
1432    unsigned b = SkFastMin32(SkPacked32ToB16(src), SkGetPackedB16(dst));
1433    return SkPackRGB16(r, g, b);
1434}
1435
1436static uint16_t lighten_modeproc16_0(SkPMColor src, uint16_t dst) {
1437    SkASSERT(require_0(src));
1438    return dst;
1439}
1440
1441static uint16_t lighten_modeproc16_255(SkPMColor src, uint16_t dst) {
1442    SkASSERT(require_255(src));
1443    unsigned r = SkMax32(SkPacked32ToR16(src), SkGetPackedR16(dst));
1444    unsigned g = SkMax32(SkPacked32ToG16(src), SkGetPackedG16(dst));
1445    unsigned b = SkMax32(SkPacked32ToB16(src), SkGetPackedB16(dst));
1446    return SkPackRGB16(r, g, b);
1447}
1448
1449struct Proc16Rec {
1450    SkXfermodeProc16    fProc16_0;
1451    SkXfermodeProc16    fProc16_255;
1452    SkXfermodeProc16    fProc16_General;
1453};
1454
1455static const Proc16Rec gModeProcs16[] = {
1456    { NULL,                 NULL,                   NULL            }, // CLEAR
1457    { NULL,                 src_modeproc16_255,     NULL            },
1458    { dst_modeproc16,       dst_modeproc16,         dst_modeproc16  },
1459    { srcover_modeproc16_0, srcover_modeproc16_255, NULL            },
1460    { dstover_modeproc16_0, dstover_modeproc16_255, NULL            },
1461    { NULL,                 srcin_modeproc16_255,   NULL            },
1462    { NULL,                 dstin_modeproc16_255,   NULL            },
1463    { NULL,                 NULL,                   NULL            },// SRC_OUT
1464    { dstout_modeproc16_0,  NULL,                   NULL            },
1465    { srcatop_modeproc16_0, srcatop_modeproc16_255, srcatop_modeproc16  },
1466    { NULL,                 dstatop_modeproc16_255, NULL            },
1467    { NULL,                 NULL,                   NULL            }, // XOR
1468
1469    { NULL,                 NULL,                   NULL            }, // plus
1470    { NULL,                 NULL,                   NULL            }, // modulate
1471    { NULL,                 NULL,                   NULL            }, // screen
1472    { NULL,                 NULL,                   NULL            }, // overlay
1473    { darken_modeproc16_0,  darken_modeproc16_255,  NULL            }, // darken
1474    { lighten_modeproc16_0, lighten_modeproc16_255, NULL            }, // lighten
1475    { NULL,                 NULL,                   NULL            }, // colordodge
1476    { NULL,                 NULL,                   NULL            }, // colorburn
1477    { NULL,                 NULL,                   NULL            }, // hardlight
1478    { NULL,                 NULL,                   NULL            }, // softlight
1479    { NULL,                 NULL,                   NULL            }, // difference
1480    { NULL,                 NULL,                   NULL            }, // exclusion
1481    { NULL,                 NULL,                   NULL            }, // multiply
1482    { NULL,                 NULL,                   NULL            }, // hue
1483    { NULL,                 NULL,                   NULL            }, // saturation
1484    { NULL,                 NULL,                   NULL            }, // color
1485    { NULL,                 NULL,                   NULL            }, // luminosity
1486};
1487
1488SkXfermodeProc16 SkXfermode::GetProc16(Mode mode, SkColor srcColor) {
1489    SkXfermodeProc16  proc16 = NULL;
1490    if ((unsigned)mode < kModeCount) {
1491        const Proc16Rec& rec = gModeProcs16[mode];
1492        unsigned a = SkColorGetA(srcColor);
1493
1494        if (0 == a) {
1495            proc16 = rec.fProc16_0;
1496        } else if (255 == a) {
1497            proc16 = rec.fProc16_255;
1498        } else {
1499            proc16 = rec.fProc16_General;
1500        }
1501    }
1502    return proc16;
1503}
1504
1505SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkXfermode)
1506    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkProcCoeffXfermode)
1507SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
1508