SkXfermode.cpp revision 2cf444f7040614b43af67e368f3aa636ebeaa45a
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
10#include "SkXfermode.h"
11#include "SkColorPriv.h"
12#include "SkFlattenableBuffers.h"
13#include "SkMathPriv.h"
14#include "SkString.h"
15
16SK_DEFINE_INST_COUNT(SkXfermode)
17
18#define SkAlphaMulAlpha(a, b)   SkMulDiv255Round(a, b)
19
20#if 0
21// idea for higher precision blends in xfer procs (and slightly faster)
22// see DstATop as a probable caller
23static U8CPU mulmuldiv255round(U8CPU a, U8CPU b, U8CPU c, U8CPU d) {
24    SkASSERT(a <= 255);
25    SkASSERT(b <= 255);
26    SkASSERT(c <= 255);
27    SkASSERT(d <= 255);
28    unsigned prod = SkMulS16(a, b) + SkMulS16(c, d) + 128;
29    unsigned result = (prod + (prod >> 8)) >> 8;
30    SkASSERT(result <= 255);
31    return result;
32}
33#endif
34
35static inline unsigned saturated_add(unsigned a, unsigned b) {
36    SkASSERT(a <= 255);
37    SkASSERT(b <= 255);
38    unsigned sum = a + b;
39    if (sum > 255) {
40        sum = 255;
41    }
42    return sum;
43}
44
45static inline int clamp_signed_byte(int n) {
46    if (n < 0) {
47        n = 0;
48    } else if (n > 255) {
49        n = 255;
50    }
51    return n;
52}
53
54static inline int clamp_div255round(int prod) {
55    if (prod <= 0) {
56        return 0;
57    } else if (prod >= 255*255) {
58        return 255;
59    } else {
60        return SkDiv255Round(prod);
61    }
62}
63
64static inline int clamp_max(int value, int max) {
65    if (value > max) {
66        value = max;
67    }
68    return value;
69}
70
71///////////////////////////////////////////////////////////////////////////////
72
73//  kClear_Mode,    //!< [0, 0]
74static SkPMColor clear_modeproc(SkPMColor src, SkPMColor dst) {
75    return 0;
76}
77
78//  kSrc_Mode,      //!< [Sa, Sc]
79static SkPMColor src_modeproc(SkPMColor src, SkPMColor dst) {
80    return src;
81}
82
83//  kDst_Mode,      //!< [Da, Dc]
84static SkPMColor dst_modeproc(SkPMColor src, SkPMColor dst) {
85    return dst;
86}
87
88//  kSrcOver_Mode,  //!< [Sa + Da - Sa*Da, Sc + (1 - Sa)*Dc]
89static SkPMColor srcover_modeproc(SkPMColor src, SkPMColor dst) {
90#if 0
91    // this is the old, more-correct way, but it doesn't guarantee that dst==255
92    // will always stay opaque
93    return src + SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src)));
94#else
95    // this is slightly faster, but more importantly guarantees that dst==255
96    // will always stay opaque
97    return src + SkAlphaMulQ(dst, 256 - SkGetPackedA32(src));
98#endif
99}
100
101//  kDstOver_Mode,  //!< [Sa + Da - Sa*Da, Dc + (1 - Da)*Sc]
102static SkPMColor dstover_modeproc(SkPMColor src, SkPMColor dst) {
103    // this is the reverse of srcover, just flipping src and dst
104    // see srcover's comment about the 256 for opaqueness guarantees
105    return dst + SkAlphaMulQ(src, 256 - SkGetPackedA32(dst));
106}
107
108//  kSrcIn_Mode,    //!< [Sa * Da, Sc * Da]
109static SkPMColor srcin_modeproc(SkPMColor src, SkPMColor dst) {
110    return SkAlphaMulQ(src, SkAlpha255To256(SkGetPackedA32(dst)));
111}
112
113//  kDstIn_Mode,    //!< [Sa * Da, Sa * Dc]
114static SkPMColor dstin_modeproc(SkPMColor src, SkPMColor dst) {
115    return SkAlphaMulQ(dst, SkAlpha255To256(SkGetPackedA32(src)));
116}
117
118//  kSrcOut_Mode,   //!< [Sa * (1 - Da), Sc * (1 - Da)]
119static SkPMColor srcout_modeproc(SkPMColor src, SkPMColor dst) {
120    return SkAlphaMulQ(src, SkAlpha255To256(255 - SkGetPackedA32(dst)));
121}
122
123//  kDstOut_Mode,   //!< [Da * (1 - Sa), Dc * (1 - Sa)]
124static SkPMColor dstout_modeproc(SkPMColor src, SkPMColor dst) {
125    return SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src)));
126}
127
128//  kSrcATop_Mode,  //!< [Da, Sc * Da + (1 - Sa) * Dc]
129static SkPMColor srcatop_modeproc(SkPMColor src, SkPMColor dst) {
130    unsigned sa = SkGetPackedA32(src);
131    unsigned da = SkGetPackedA32(dst);
132    unsigned isa = 255 - sa;
133
134    return SkPackARGB32(da,
135                        SkAlphaMulAlpha(da, SkGetPackedR32(src)) +
136                            SkAlphaMulAlpha(isa, SkGetPackedR32(dst)),
137                        SkAlphaMulAlpha(da, SkGetPackedG32(src)) +
138                            SkAlphaMulAlpha(isa, SkGetPackedG32(dst)),
139                        SkAlphaMulAlpha(da, SkGetPackedB32(src)) +
140                            SkAlphaMulAlpha(isa, SkGetPackedB32(dst)));
141}
142
143//  kDstATop_Mode,  //!< [Sa, Sa * Dc + Sc * (1 - Da)]
144static SkPMColor dstatop_modeproc(SkPMColor src, SkPMColor dst) {
145    unsigned sa = SkGetPackedA32(src);
146    unsigned da = SkGetPackedA32(dst);
147    unsigned ida = 255 - da;
148
149    return SkPackARGB32(sa,
150                        SkAlphaMulAlpha(ida, SkGetPackedR32(src)) +
151                            SkAlphaMulAlpha(sa, SkGetPackedR32(dst)),
152                        SkAlphaMulAlpha(ida, SkGetPackedG32(src)) +
153                            SkAlphaMulAlpha(sa, SkGetPackedG32(dst)),
154                        SkAlphaMulAlpha(ida, SkGetPackedB32(src)) +
155                            SkAlphaMulAlpha(sa, SkGetPackedB32(dst)));
156}
157
158//  kXor_Mode   [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc]
159static SkPMColor xor_modeproc(SkPMColor src, SkPMColor dst) {
160    unsigned sa = SkGetPackedA32(src);
161    unsigned da = SkGetPackedA32(dst);
162    unsigned isa = 255 - sa;
163    unsigned ida = 255 - da;
164
165    return SkPackARGB32(sa + da - (SkAlphaMulAlpha(sa, da) << 1),
166                        SkAlphaMulAlpha(ida, SkGetPackedR32(src)) +
167                            SkAlphaMulAlpha(isa, SkGetPackedR32(dst)),
168                        SkAlphaMulAlpha(ida, SkGetPackedG32(src)) +
169                            SkAlphaMulAlpha(isa, SkGetPackedG32(dst)),
170                        SkAlphaMulAlpha(ida, SkGetPackedB32(src)) +
171                            SkAlphaMulAlpha(isa, SkGetPackedB32(dst)));
172}
173
174///////////////////////////////////////////////////////////////////////////////
175
176// kPlus_Mode
177static SkPMColor plus_modeproc(SkPMColor src, SkPMColor dst) {
178    unsigned b = saturated_add(SkGetPackedB32(src), SkGetPackedB32(dst));
179    unsigned g = saturated_add(SkGetPackedG32(src), SkGetPackedG32(dst));
180    unsigned r = saturated_add(SkGetPackedR32(src), SkGetPackedR32(dst));
181    unsigned a = saturated_add(SkGetPackedA32(src), SkGetPackedA32(dst));
182    return SkPackARGB32(a, r, g, b);
183}
184
185// kModulate_Mode
186static SkPMColor modulate_modeproc(SkPMColor src, SkPMColor dst) {
187    int a = SkAlphaMulAlpha(SkGetPackedA32(src), SkGetPackedA32(dst));
188    int r = SkAlphaMulAlpha(SkGetPackedR32(src), SkGetPackedR32(dst));
189    int g = SkAlphaMulAlpha(SkGetPackedG32(src), SkGetPackedG32(dst));
190    int b = SkAlphaMulAlpha(SkGetPackedB32(src), SkGetPackedB32(dst));
191    return SkPackARGB32(a, r, g, b);
192}
193
194static inline int srcover_byte(int a, int b) {
195    return a + b - SkAlphaMulAlpha(a, b);
196}
197
198// kMultiply_Mode
199// B(Cb, Cs) = Cb x Cs
200// multiply uses its own version of blendfunc_byte because sa and da are not needed
201static int blendfunc_multiply_byte(int sc, int dc, int sa, int da) {
202    return clamp_div255round(sc * (255 - da)  + dc * (255 - sa)  + sc * dc);
203}
204
205static SkPMColor multiply_modeproc(SkPMColor src, SkPMColor dst) {
206    int sa = SkGetPackedA32(src);
207    int da = SkGetPackedA32(dst);
208    int a = srcover_byte(sa, da);
209    int r = blendfunc_multiply_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
210    int g = blendfunc_multiply_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
211    int b = blendfunc_multiply_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
212    return SkPackARGB32(a, r, g, b);
213}
214
215// kScreen_Mode
216static SkPMColor screen_modeproc(SkPMColor src, SkPMColor dst) {
217    int a = srcover_byte(SkGetPackedA32(src), SkGetPackedA32(dst));
218    int r = srcover_byte(SkGetPackedR32(src), SkGetPackedR32(dst));
219    int g = srcover_byte(SkGetPackedG32(src), SkGetPackedG32(dst));
220    int b = srcover_byte(SkGetPackedB32(src), SkGetPackedB32(dst));
221    return SkPackARGB32(a, r, g, b);
222}
223
224// kOverlay_Mode
225static inline int overlay_byte(int sc, int dc, int sa, int da) {
226    int tmp = sc * (255 - da) + dc * (255 - sa);
227    int rc;
228    if (2 * dc <= da) {
229        rc = 2 * sc * dc;
230    } else {
231        rc = sa * da - 2 * (da - dc) * (sa - sc);
232    }
233    return clamp_div255round(rc + tmp);
234}
235static SkPMColor overlay_modeproc(SkPMColor src, SkPMColor dst) {
236    int sa = SkGetPackedA32(src);
237    int da = SkGetPackedA32(dst);
238    int a = srcover_byte(sa, da);
239    int r = overlay_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
240    int g = overlay_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
241    int b = overlay_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
242    return SkPackARGB32(a, r, g, b);
243}
244
245// kDarken_Mode
246static inline int darken_byte(int sc, int dc, int sa, int da) {
247    int sd = sc * da;
248    int ds = dc * sa;
249    if (sd < ds) {
250        // srcover
251        return sc + dc - SkDiv255Round(ds);
252    } else {
253        // dstover
254        return dc + sc - SkDiv255Round(sd);
255    }
256}
257static SkPMColor darken_modeproc(SkPMColor src, SkPMColor dst) {
258    int sa = SkGetPackedA32(src);
259    int da = SkGetPackedA32(dst);
260    int a = srcover_byte(sa, da);
261    int r = darken_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
262    int g = darken_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
263    int b = darken_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
264    return SkPackARGB32(a, r, g, b);
265}
266
267// kLighten_Mode
268static inline int lighten_byte(int sc, int dc, int sa, int da) {
269    int sd = sc * da;
270    int ds = dc * sa;
271    if (sd > ds) {
272        // srcover
273        return sc + dc - SkDiv255Round(ds);
274    } else {
275        // dstover
276        return dc + sc - SkDiv255Round(sd);
277    }
278}
279static SkPMColor lighten_modeproc(SkPMColor src, SkPMColor dst) {
280    int sa = SkGetPackedA32(src);
281    int da = SkGetPackedA32(dst);
282    int a = srcover_byte(sa, da);
283    int r = lighten_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
284    int g = lighten_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
285    int b = lighten_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
286    return SkPackARGB32(a, r, g, b);
287}
288
289// kColorDodge_Mode
290static inline int colordodge_byte(int sc, int dc, int sa, int da) {
291    int diff = sa - sc;
292    int rc;
293    if (0 == dc) {
294        return SkAlphaMulAlpha(sc, 255 - da);
295    } else if (0 == diff) {
296        rc = sa * da + sc * (255 - da) + dc * (255 - sa);
297    } else {
298        diff = dc * sa / diff;
299        rc = sa * ((da < diff) ? da : diff) + sc * (255 - da) + dc * (255 - sa);
300    }
301    return clamp_div255round(rc);
302}
303static SkPMColor colordodge_modeproc(SkPMColor src, SkPMColor dst) {
304    int sa = SkGetPackedA32(src);
305    int da = SkGetPackedA32(dst);
306    int a = srcover_byte(sa, da);
307    int r = colordodge_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
308    int g = colordodge_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
309    int b = colordodge_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
310    return SkPackARGB32(a, r, g, b);
311}
312
313// kColorBurn_Mode
314static inline int colorburn_byte(int sc, int dc, int sa, int da) {
315    int rc;
316    if (dc == da) {
317        rc = sa * da + sc * (255 - da) + dc * (255 - sa);
318    } else if (0 == sc) {
319        return SkAlphaMulAlpha(dc, 255 - sa);
320    } else {
321        int tmp = (da - dc) * sa / sc;
322        rc = sa * (da - ((da < tmp) ? da : tmp))
323            + sc * (255 - da) + dc * (255 - sa);
324    }
325    return clamp_div255round(rc);
326}
327static SkPMColor colorburn_modeproc(SkPMColor src, SkPMColor dst) {
328    int sa = SkGetPackedA32(src);
329    int da = SkGetPackedA32(dst);
330    int a = srcover_byte(sa, da);
331    int r = colorburn_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
332    int g = colorburn_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
333    int b = colorburn_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
334    return SkPackARGB32(a, r, g, b);
335}
336
337// kHardLight_Mode
338static inline int hardlight_byte(int sc, int dc, int sa, int da) {
339    int rc;
340    if (2 * sc <= sa) {
341        rc = 2 * sc * dc;
342    } else {
343        rc = sa * da - 2 * (da - dc) * (sa - sc);
344    }
345    return clamp_div255round(rc + sc * (255 - da) + dc * (255 - sa));
346}
347static SkPMColor hardlight_modeproc(SkPMColor src, SkPMColor dst) {
348    int sa = SkGetPackedA32(src);
349    int da = SkGetPackedA32(dst);
350    int a = srcover_byte(sa, da);
351    int r = hardlight_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
352    int g = hardlight_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
353    int b = hardlight_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
354    return SkPackARGB32(a, r, g, b);
355}
356
357// returns 255 * sqrt(n/255)
358static U8CPU sqrt_unit_byte(U8CPU n) {
359    return SkSqrtBits(n, 15+4);
360}
361
362// kSoftLight_Mode
363static inline int softlight_byte(int sc, int dc, int sa, int da) {
364    int m = da ? dc * 256 / da : 0;
365    int rc;
366    if (2 * sc <= sa) {
367        rc = dc * (sa + ((2 * sc - sa) * (256 - m) >> 8));
368    } else if (4 * dc <= da) {
369        int tmp = (4 * m * (4 * m + 256) * (m - 256) >> 16) + 7 * m;
370        rc = dc * sa + (da * (2 * sc - sa) * tmp >> 8);
371    } else {
372        int tmp = sqrt_unit_byte(m) - m;
373        rc = dc * sa + (da * (2 * sc - sa) * tmp >> 8);
374    }
375    return clamp_div255round(rc + sc * (255 - da) + dc * (255 - sa));
376}
377static SkPMColor softlight_modeproc(SkPMColor src, SkPMColor dst) {
378    int sa = SkGetPackedA32(src);
379    int da = SkGetPackedA32(dst);
380    int a = srcover_byte(sa, da);
381    int r = softlight_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
382    int g = softlight_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
383    int b = softlight_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
384    return SkPackARGB32(a, r, g, b);
385}
386
387// kDifference_Mode
388static inline int difference_byte(int sc, int dc, int sa, int da) {
389    int tmp = SkMin32(sc * da, dc * sa);
390    return clamp_signed_byte(sc + dc - 2 * SkDiv255Round(tmp));
391}
392static SkPMColor difference_modeproc(SkPMColor src, SkPMColor dst) {
393    int sa = SkGetPackedA32(src);
394    int da = SkGetPackedA32(dst);
395    int a = srcover_byte(sa, da);
396    int r = difference_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
397    int g = difference_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
398    int b = difference_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
399    return SkPackARGB32(a, r, g, b);
400}
401
402// kExclusion_Mode
403static inline int exclusion_byte(int sc, int dc, int sa, int da) {
404    // this equations is wacky, wait for SVG to confirm it
405    int r = sc * da + dc * sa - 2 * sc * dc + sc * (255 - da) + dc * (255 - sa);
406    return clamp_div255round(r);
407}
408static SkPMColor exclusion_modeproc(SkPMColor src, SkPMColor dst) {
409    int sa = SkGetPackedA32(src);
410    int da = SkGetPackedA32(dst);
411    int a = srcover_byte(sa, da);
412    int r = exclusion_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
413    int g = exclusion_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
414    int b = exclusion_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
415    return SkPackARGB32(a, r, g, b);
416}
417
418// The CSS compositing spec introduces the following formulas:
419// (See https://dvcs.w3.org/hg/FXTF/rawfile/tip/compositing/index.html#blendingnonseparable)
420// SkComputeLuminance is similar to this formula but it uses the new definition from Rec. 709
421// while PDF and CG uses the one from Rec. Rec. 601
422// See http://www.glennchan.info/articles/technical/hd-versus-sd-color-space/hd-versus-sd-color-space.htm
423static inline int Lum(int r, int g, int b)
424{
425    return SkDiv255Round(r * 77 + g * 150 + b * 28);
426}
427
428static inline int min2(int a, int b) { return a < b ? a : b; }
429static inline int max2(int a, int b) { return a > b ? a : b; }
430#define minimum(a, b, c) min2(min2(a, b), c)
431#define maximum(a, b, c) max2(max2(a, b), c)
432
433static inline int Sat(int r, int g, int b) {
434    return maximum(r, g, b) - minimum(r, g, b);
435}
436
437static inline void setSaturationComponents(int* Cmin, int* Cmid, int* Cmax, int s) {
438    if(*Cmax > *Cmin) {
439        *Cmid =  SkMulDiv(*Cmid - *Cmin, s, *Cmax - *Cmin);
440        *Cmax = s;
441    } else {
442        *Cmax = 0;
443        *Cmid = 0;
444    }
445
446    *Cmin = 0;
447}
448
449static inline void SetSat(int* r, int* g, int* b, int s) {
450    if(*r <= *g) {
451        if(*g <= *b) {
452            setSaturationComponents(r, g, b, s);
453        } else if(*r <= *b) {
454            setSaturationComponents(r, b, g, s);
455        } else {
456            setSaturationComponents(b, r, g, s);
457        }
458    } else if(*r <= *b) {
459        setSaturationComponents(g, r, b, s);
460    } else if(*g <= *b) {
461        setSaturationComponents(g, b, r, s);
462    } else {
463        setSaturationComponents(b, g, r, s);
464    }
465}
466
467static inline void clipColor(int* r, int* g, int* b, int a) {
468    int L = Lum(*r, *g, *b);
469    int n = minimum(*r, *g, *b);
470    int x = maximum(*r, *g, *b);
471    if(n < 0) {
472       *r = L + SkMulDiv(*r - L, L, L - n);
473       *g = L + SkMulDiv(*g - L, L, L - n);
474       *b = L + SkMulDiv(*b - L, L, L - n);
475    }
476
477    if (x > a) {
478       *r = L + SkMulDiv(*r - L, a - L, x - L);
479       *g = L + SkMulDiv(*g - L, a - L, x - L);
480       *b = L + SkMulDiv(*b - L, a - L, x - L);
481    }
482}
483
484static inline void SetLum(int* r, int* g, int* b, int a, int l) {
485  int d = l - Lum(*r, *g, *b);
486  *r +=  d;
487  *g +=  d;
488  *b +=  d;
489
490  clipColor(r, g, b, a);
491}
492
493// non-separable blend modes are done in non-premultiplied alpha
494#define  blendfunc_nonsep_byte(sc, dc, sa, da, blendval) \
495  clamp_div255round(sc * (255 - da) +  dc * (255 - sa) + blendval)
496
497// kHue_Mode
498// B(Cb, Cs) = SetLum(SetSat(Cs, Sat(Cb)), Lum(Cb))
499// Create a color with the hue of the source color and the saturation and luminosity of the backdrop color.
500static SkPMColor hue_modeproc(SkPMColor src, SkPMColor dst) {
501    int sr = SkGetPackedR32(src);
502    int sg = SkGetPackedG32(src);
503    int sb = SkGetPackedB32(src);
504    int sa = SkGetPackedA32(src);
505
506    int dr = SkGetPackedR32(dst);
507    int dg = SkGetPackedG32(dst);
508    int db = SkGetPackedB32(dst);
509    int da = SkGetPackedA32(dst);
510    int Sr, Sg, Sb;
511
512    if(sa && da) {
513        Sr = sr * sa;
514        Sg = sg * sa;
515        Sb = sb * sa;
516        SetSat(&Sr, &Sg, &Sb, Sat(dr, dg, db) * sa);
517        SetLum(&Sr, &Sg, &Sb, sa * da, Lum(dr, dg, db) * sa);
518    } else {
519        Sr = 0;
520        Sg = 0;
521        Sb = 0;
522    }
523
524    int a = srcover_byte(sa, da);
525    int r = blendfunc_nonsep_byte(sr, dr, sa, da, Sr);
526    int g = blendfunc_nonsep_byte(sg, dg, sa, da, Sg);
527    int b = blendfunc_nonsep_byte(sb, db, sa, da, Sb);
528    return SkPackARGB32(a, r, g, b);
529}
530
531// kSaturation_Mode
532// B(Cb, Cs) = SetLum(SetSat(Cb, Sat(Cs)), Lum(Cb))
533// Create a color with the saturation of the source color and the hue and luminosity of the backdrop color.
534static SkPMColor saturation_modeproc(SkPMColor src, SkPMColor dst) {
535    int sr = SkGetPackedR32(src);
536    int sg = SkGetPackedG32(src);
537    int sb = SkGetPackedB32(src);
538    int sa = SkGetPackedA32(src);
539
540    int dr = SkGetPackedR32(dst);
541    int dg = SkGetPackedG32(dst);
542    int db = SkGetPackedB32(dst);
543    int da = SkGetPackedA32(dst);
544    int Dr, Dg, Db;
545
546    if(sa && da) {
547        Dr = dr * sa;
548        Dg = dg * sa;
549        Db = db * sa;
550        SetSat(&Dr, &Dg, &Db, Sat(sr, sg, sb) * da);
551        SetLum(&Dr, &Dg, &Db, sa * da, Lum(dr, dg, db) * sa);
552    } else {
553        Dr = 0;
554        Dg = 0;
555        Db = 0;
556    }
557
558    int a = srcover_byte(sa, da);
559    int r = blendfunc_nonsep_byte(sr, dr, sa, da, Dr);
560    int g = blendfunc_nonsep_byte(sg, dg, sa, da, Dg);
561    int b = blendfunc_nonsep_byte(sb, db, sa, da, Db);
562    return SkPackARGB32(a, r, g, b);
563}
564
565// kColor_Mode
566// B(Cb, Cs) = SetLum(Cs, Lum(Cb))
567// Create a color with the hue and saturation of the source color and the luminosity of the backdrop color.
568static SkPMColor color_modeproc(SkPMColor src, SkPMColor dst) {
569    int sr = SkGetPackedR32(src);
570    int sg = SkGetPackedG32(src);
571    int sb = SkGetPackedB32(src);
572    int sa = SkGetPackedA32(src);
573
574    int dr = SkGetPackedR32(dst);
575    int dg = SkGetPackedG32(dst);
576    int db = SkGetPackedB32(dst);
577    int da = SkGetPackedA32(dst);
578    int Sr, Sg, Sb;
579
580    if(sa && da) {
581        Sr = sr * da;
582        Sg = sg * da;
583        Sb = sb * da;
584        SetLum(&Sr, &Sg, &Sb, sa * da, Lum(dr, dg, db) * sa);
585    } else {
586        Sr = 0;
587        Sg = 0;
588        Sb = 0;
589    }
590
591    int a = srcover_byte(sa, da);
592    int r = blendfunc_nonsep_byte(sr, dr, sa, da, Sr);
593    int g = blendfunc_nonsep_byte(sg, dg, sa, da, Sg);
594    int b = blendfunc_nonsep_byte(sb, db, sa, da, Sb);
595    return SkPackARGB32(a, r, g, b);
596}
597
598// kLuminosity_Mode
599// B(Cb, Cs) = SetLum(Cb, Lum(Cs))
600// Create a color with the luminosity of the source color and the hue and saturation of the backdrop color.
601static SkPMColor luminosity_modeproc(SkPMColor src, SkPMColor dst) {
602    int sr = SkGetPackedR32(src);
603    int sg = SkGetPackedG32(src);
604    int sb = SkGetPackedB32(src);
605    int sa = SkGetPackedA32(src);
606
607    int dr = SkGetPackedR32(dst);
608    int dg = SkGetPackedG32(dst);
609    int db = SkGetPackedB32(dst);
610    int da = SkGetPackedA32(dst);
611    int Dr, Dg, Db;
612
613    if(sa && da) {
614        Dr = dr * sa;
615        Dg = dg * sa;
616        Db = db * sa;
617        SetLum(&Dr, &Dg, &Db, sa * da, Lum(sr, sg, sb) * da);
618    } else {
619        Dr = 0;
620        Dg = 0;
621        Db = 0;
622    }
623
624    int a = srcover_byte(sa, da);
625    int r = blendfunc_nonsep_byte(sr, dr, sa, da, Dr);
626    int g = blendfunc_nonsep_byte(sg, dg, sa, da, Dg);
627    int b = blendfunc_nonsep_byte(sb, db, sa, da, Db);
628    return SkPackARGB32(a, r, g, b);
629}
630
631
632struct ProcCoeff {
633    SkXfermodeProc      fProc;
634    SkXfermode::Coeff   fSC;
635    SkXfermode::Coeff   fDC;
636};
637
638#define CANNOT_USE_COEFF    SkXfermode::Coeff(-1)
639
640static const ProcCoeff gProcCoeffs[] = {
641    { clear_modeproc,   SkXfermode::kZero_Coeff,    SkXfermode::kZero_Coeff },
642    { src_modeproc,     SkXfermode::kOne_Coeff,     SkXfermode::kZero_Coeff },
643    { dst_modeproc,     SkXfermode::kZero_Coeff,    SkXfermode::kOne_Coeff },
644    { srcover_modeproc, SkXfermode::kOne_Coeff,     SkXfermode::kISA_Coeff },
645    { dstover_modeproc, SkXfermode::kIDA_Coeff,     SkXfermode::kOne_Coeff },
646    { srcin_modeproc,   SkXfermode::kDA_Coeff,      SkXfermode::kZero_Coeff },
647    { dstin_modeproc,   SkXfermode::kZero_Coeff,    SkXfermode::kSA_Coeff },
648    { srcout_modeproc,  SkXfermode::kIDA_Coeff,     SkXfermode::kZero_Coeff },
649    { dstout_modeproc,  SkXfermode::kZero_Coeff,    SkXfermode::kISA_Coeff },
650    { srcatop_modeproc, SkXfermode::kDA_Coeff,      SkXfermode::kISA_Coeff },
651    { dstatop_modeproc, SkXfermode::kIDA_Coeff,     SkXfermode::kSA_Coeff },
652    { xor_modeproc,     SkXfermode::kIDA_Coeff,     SkXfermode::kISA_Coeff },
653
654    { plus_modeproc,    SkXfermode::kOne_Coeff,     SkXfermode::kOne_Coeff },
655    { modulate_modeproc,SkXfermode::kZero_Coeff,    SkXfermode::kSC_Coeff },
656    { screen_modeproc,  SkXfermode::kOne_Coeff,     SkXfermode::kISC_Coeff },
657    { overlay_modeproc,     CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
658    { darken_modeproc,      CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
659    { lighten_modeproc,     CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
660    { colordodge_modeproc,  CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
661    { colorburn_modeproc,   CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
662    { hardlight_modeproc,   CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
663    { softlight_modeproc,   CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
664    { difference_modeproc,  CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
665    { exclusion_modeproc,   CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
666    { multiply_modeproc,    CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
667    { hue_modeproc,         CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
668    { saturation_modeproc,  CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
669    { color_modeproc,       CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
670    { luminosity_modeproc,  CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
671};
672
673///////////////////////////////////////////////////////////////////////////////
674
675bool SkXfermode::asCoeff(Coeff* src, Coeff* dst) const {
676    return false;
677}
678
679bool SkXfermode::asMode(Mode* mode) const {
680    return false;
681}
682
683bool SkXfermode::asNewEffectOrCoeff(GrContext*, GrEffectRef**, Coeff* src, Coeff* dst) const {
684    return this->asCoeff(src, dst);
685}
686
687bool SkXfermode::AsNewEffectOrCoeff(SkXfermode* xfermode,
688                                    GrContext* context,
689                                    GrEffectRef** effect,
690                                    Coeff* src,
691                                    Coeff* dst) {
692    if (NULL == xfermode) {
693        return ModeAsCoeff(kSrcOver_Mode, src, dst);
694    } else {
695        return xfermode->asNewEffectOrCoeff(context, effect, src, dst);
696    }
697}
698
699SkPMColor SkXfermode::xferColor(SkPMColor src, SkPMColor dst) const{
700    // no-op. subclasses should override this
701    return dst;
702}
703
704void SkXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
705                        const SkPMColor* SK_RESTRICT src, int count,
706                        const SkAlpha* SK_RESTRICT aa) const {
707    SkASSERT(dst && src && count >= 0);
708
709    if (NULL == aa) {
710        for (int i = count - 1; i >= 0; --i) {
711            dst[i] = this->xferColor(src[i], dst[i]);
712        }
713    } else {
714        for (int i = count - 1; i >= 0; --i) {
715            unsigned a = aa[i];
716            if (0 != a) {
717                SkPMColor dstC = dst[i];
718                SkPMColor C = this->xferColor(src[i], dstC);
719                if (0xFF != a) {
720                    C = SkFourByteInterp(C, dstC, a);
721                }
722                dst[i] = C;
723            }
724        }
725    }
726}
727
728void SkXfermode::xfer16(uint16_t* dst,
729                        const SkPMColor* SK_RESTRICT src, int count,
730                        const SkAlpha* SK_RESTRICT aa) const {
731    SkASSERT(dst && src && count >= 0);
732
733    if (NULL == aa) {
734        for (int i = count - 1; i >= 0; --i) {
735            SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
736            dst[i] = SkPixel32ToPixel16_ToU16(this->xferColor(src[i], dstC));
737        }
738    } else {
739        for (int i = count - 1; i >= 0; --i) {
740            unsigned a = aa[i];
741            if (0 != a) {
742                SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
743                SkPMColor C = this->xferColor(src[i], dstC);
744                if (0xFF != a) {
745                    C = SkFourByteInterp(C, dstC, a);
746                }
747                dst[i] = SkPixel32ToPixel16_ToU16(C);
748            }
749        }
750    }
751}
752
753void SkXfermode::xfer4444(SkPMColor16* SK_RESTRICT dst,
754                          const SkPMColor* SK_RESTRICT src, int count,
755                          const SkAlpha* SK_RESTRICT aa) const {
756    SkASSERT(dst && src && count >= 0);
757
758    if (NULL == aa) {
759        for (int i = count - 1; i >= 0; --i) {
760            SkPMColor dstC = SkPixel4444ToPixel32(dst[i]);
761            dst[i] = SkPixel32ToPixel4444(this->xferColor(src[i], dstC));
762        }
763    } else {
764        for (int i = count - 1; i >= 0; --i) {
765            unsigned a = aa[i];
766            if (0 != a) {
767                SkPMColor dstC = SkPixel4444ToPixel32(dst[i]);
768                SkPMColor C = this->xferColor(src[i], dstC);
769                if (0xFF != a) {
770                    C = SkFourByteInterp(C, dstC, a);
771                }
772                dst[i] = SkPixel32ToPixel4444(C);
773            }
774        }
775    }
776}
777
778void SkXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
779                        const SkPMColor src[], int count,
780                        const SkAlpha* SK_RESTRICT aa) const {
781    SkASSERT(dst && src && count >= 0);
782
783    if (NULL == aa) {
784        for (int i = count - 1; i >= 0; --i) {
785            SkPMColor res = this->xferColor(src[i], (dst[i] << SK_A32_SHIFT));
786            dst[i] = SkToU8(SkGetPackedA32(res));
787        }
788    } else {
789        for (int i = count - 1; i >= 0; --i) {
790            unsigned a = aa[i];
791            if (0 != a) {
792                SkAlpha dstA = dst[i];
793                unsigned A = SkGetPackedA32(this->xferColor(src[i],
794                                            (SkPMColor)(dstA << SK_A32_SHIFT)));
795                if (0xFF != a) {
796                    A = SkAlphaBlend(A, dstA, SkAlpha255To256(a));
797                }
798                dst[i] = SkToU8(A);
799            }
800        }
801    }
802}
803
804///////////////////////////////////////////////////////////////////////////////
805
806void SkProcXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
807                            const SkPMColor* SK_RESTRICT src, int count,
808                            const SkAlpha* SK_RESTRICT aa) const {
809    SkASSERT(dst && src && count >= 0);
810
811    SkXfermodeProc proc = fProc;
812
813    if (NULL != proc) {
814        if (NULL == aa) {
815            for (int i = count - 1; i >= 0; --i) {
816                dst[i] = proc(src[i], dst[i]);
817            }
818        } else {
819            for (int i = count - 1; i >= 0; --i) {
820                unsigned a = aa[i];
821                if (0 != a) {
822                    SkPMColor dstC = dst[i];
823                    SkPMColor C = proc(src[i], dstC);
824                    if (a != 0xFF) {
825                        C = SkFourByteInterp(C, dstC, a);
826                    }
827                    dst[i] = C;
828                }
829            }
830        }
831    }
832}
833
834void SkProcXfermode::xfer16(uint16_t* 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 (NULL != proc) {
842        if (NULL == aa) {
843            for (int i = count - 1; i >= 0; --i) {
844                SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
845                dst[i] = SkPixel32ToPixel16_ToU16(proc(src[i], dstC));
846            }
847        } else {
848            for (int i = count - 1; i >= 0; --i) {
849                unsigned a = aa[i];
850                if (0 != a) {
851                    SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
852                    SkPMColor C = proc(src[i], dstC);
853                    if (0xFF != a) {
854                        C = SkFourByteInterp(C, dstC, a);
855                    }
856                    dst[i] = SkPixel32ToPixel16_ToU16(C);
857                }
858            }
859        }
860    }
861}
862
863void SkProcXfermode::xfer4444(SkPMColor16* SK_RESTRICT dst,
864                              const SkPMColor* SK_RESTRICT src, int count,
865                              const SkAlpha* SK_RESTRICT aa) const {
866    SkASSERT(dst && src && count >= 0);
867
868    SkXfermodeProc proc = fProc;
869
870    if (NULL != proc) {
871        if (NULL == aa) {
872            for (int i = count - 1; i >= 0; --i) {
873                SkPMColor dstC = SkPixel4444ToPixel32(dst[i]);
874                dst[i] = SkPixel32ToPixel4444(proc(src[i], dstC));
875            }
876        } else {
877            for (int i = count - 1; i >= 0; --i) {
878                unsigned a = aa[i];
879                if (0 != a) {
880                    SkPMColor dstC = SkPixel4444ToPixel32(dst[i]);
881                    SkPMColor C = proc(src[i], dstC);
882                    if (0xFF != a) {
883                        C = SkFourByteInterp(C, dstC, a);
884                    }
885                    dst[i] = SkPixel32ToPixel4444(C);
886                }
887            }
888        }
889    }
890}
891
892void SkProcXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
893                            const SkPMColor* SK_RESTRICT src, int count,
894                            const SkAlpha* SK_RESTRICT aa) const {
895    SkASSERT(dst && src && count >= 0);
896
897    SkXfermodeProc proc = fProc;
898
899    if (NULL != proc) {
900        if (NULL == aa) {
901            for (int i = count - 1; i >= 0; --i) {
902                SkPMColor res = proc(src[i], dst[i] << SK_A32_SHIFT);
903                dst[i] = SkToU8(SkGetPackedA32(res));
904            }
905        } else {
906            for (int i = count - 1; i >= 0; --i) {
907                unsigned a = aa[i];
908                if (0 != a) {
909                    SkAlpha dstA = dst[i];
910                    SkPMColor res = proc(src[i], dstA << SK_A32_SHIFT);
911                    unsigned A = SkGetPackedA32(res);
912                    if (0xFF != a) {
913                        A = SkAlphaBlend(A, dstA, SkAlpha255To256(a));
914                    }
915                    dst[i] = SkToU8(A);
916                }
917            }
918        }
919    }
920}
921
922SkProcXfermode::SkProcXfermode(SkFlattenableReadBuffer& buffer)
923        : SkXfermode(buffer) {
924    fProc = NULL;
925    if (!buffer.isCrossProcess()) {
926        fProc = (SkXfermodeProc)buffer.readFunctionPtr();
927    }
928}
929
930void SkProcXfermode::flatten(SkFlattenableWriteBuffer& buffer) const {
931    this->INHERITED::flatten(buffer);
932    if (!buffer.isCrossProcess()) {
933        buffer.writeFunctionPtr((void*)fProc);
934    }
935}
936
937#ifdef SK_DEVELOPER
938void SkProcXfermode::toString(SkString* str) const {
939    str->appendf("SkProcXfermode: %p", fProc);
940}
941#endif
942
943//////////////////////////////////////////////////////////////////////////////
944
945#if SK_SUPPORT_GPU
946
947#include "GrEffect.h"
948#include "GrEffectUnitTest.h"
949#include "GrTBackendEffectFactory.h"
950#include "gl/GrGLEffect.h"
951
952/**
953 * GrEffect that implements the all the separable xfer modes that cannot be expressed as Coeffs.
954 */
955class XferEffect : public GrEffect {
956public:
957    static bool IsSupportedMode(SkXfermode::Mode mode) {
958        return mode > SkXfermode::kLastCoeffMode && mode <= SkXfermode::kLastMode;
959    }
960
961    static GrEffectRef* Create(SkXfermode::Mode mode) {
962        if (!IsSupportedMode(mode)) {
963            return NULL;
964        } else {
965            AutoEffectUnref effect(SkNEW_ARGS(XferEffect, (mode)));
966            return CreateEffectRef(effect);
967        }
968    }
969
970    virtual void getConstantColorComponents(GrColor* color,
971                                            uint32_t* validFlags) const SK_OVERRIDE {
972        *validFlags = 0;
973    }
974
975    virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE {
976        return GrTBackendEffectFactory<XferEffect>::getInstance();
977    }
978
979    static const char* Name() { return "XferEffect"; }
980
981    SkXfermode::Mode mode() const { return fMode; }
982
983    class GLEffect : public GrGLEffect {
984    public:
985        GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&)
986            : GrGLEffect(factory ) {
987        }
988        virtual void emitCode(GrGLShaderBuilder* builder,
989                              const GrDrawEffect& drawEffect,
990                              EffectKey key,
991                              const char* outputColor,
992                              const char* inputColor,
993                              const TextureSamplerArray& samplers) SK_OVERRIDE {
994            const char* dstColor = builder->dstColor();
995            GrAssert(NULL != dstColor);
996
997            // We don't try to optimize for this case at all
998            if (NULL == inputColor) {
999                builder->fsCodeAppendf("\tconst vec4 ones = %s;\n", GrGLSLOnesVecf(4));
1000                inputColor = "ones";
1001            }
1002
1003            SkXfermode::Mode mode = drawEffect.castEffect<XferEffect>().mode();
1004            builder->fsCodeAppendf("\t\t// SkXfermode::Mode: %s\n", SkXfermode::ModeName(mode));
1005
1006            // These all perform src-over on the alpha channel.
1007            builder->fsCodeAppendf("\t\t%s.a = %s.a + (1.0 - %s.a) * %s.a;\n",
1008                                    outputColor, inputColor, inputColor, dstColor);
1009
1010            switch (mode) {
1011                case SkXfermode::kOverlay_Mode:
1012                    // Overlay is Hard-Light with the src and dst reversed
1013                    HardLight(builder, outputColor, dstColor, inputColor);
1014                    break;
1015                case SkXfermode::kDarken_Mode:
1016                    builder->fsCodeAppendf("\t\t%s.rgb = min((1.0 - %s.a) * %s.rgb + %s.rgb, "
1017                                                            "(1.0 - %s.a) * %s.rgb + %s.rgb);\n",
1018                                            outputColor,
1019                                            inputColor, dstColor, inputColor,
1020                                            dstColor, inputColor, dstColor);
1021                    break;
1022                case SkXfermode::kLighten_Mode:
1023                    builder->fsCodeAppendf("\t\t%s.rgb = max((1.0 - %s.a) * %s.rgb + %s.rgb, "
1024                                                            "(1.0 - %s.a) * %s.rgb + %s.rgb);\n",
1025                                            outputColor,
1026                                            inputColor, dstColor, inputColor,
1027                                            dstColor, inputColor, dstColor);
1028                    break;
1029                case SkXfermode::kColorDodge_Mode:
1030                    ColorDodgeComponent(builder, outputColor, inputColor, dstColor, 'r');
1031                    ColorDodgeComponent(builder, outputColor, inputColor, dstColor, 'g');
1032                    ColorDodgeComponent(builder, outputColor, inputColor, dstColor, 'b');
1033                    break;
1034                case SkXfermode::kColorBurn_Mode:
1035                    ColorBurnComponent(builder, outputColor, inputColor, dstColor, 'r');
1036                    ColorBurnComponent(builder, outputColor, inputColor, dstColor, 'g');
1037                    ColorBurnComponent(builder, outputColor, inputColor, dstColor, 'b');
1038                    break;
1039                case SkXfermode::kHardLight_Mode:
1040                    HardLight(builder, outputColor, inputColor, dstColor);
1041                    break;
1042                case SkXfermode::kSoftLight_Mode:
1043                    builder->fsCodeAppendf("\t\tif (0.0 == %s.a) {\n", dstColor);
1044                    builder->fsCodeAppendf("\t\t\t%s.rgba = %s;\n", outputColor, inputColor);
1045                    builder->fsCodeAppendf("\t\t} else {\n");
1046                    SoftLightComponentPosDstAlpha(builder, outputColor, inputColor, dstColor, 'r');
1047                    SoftLightComponentPosDstAlpha(builder, outputColor, inputColor, dstColor, 'g');
1048                    SoftLightComponentPosDstAlpha(builder, outputColor, inputColor, dstColor, 'b');
1049                    builder->fsCodeAppendf("\t\t}\n");
1050                    break;
1051                case SkXfermode::kDifference_Mode:
1052                    builder->fsCodeAppendf("\t\t%s.rgb = %s.rgb + %s.rgb -"
1053                                                       "2.0 * min(%s.rgb * %s.a, %s.rgb * %s.a);\n",
1054                                           outputColor, inputColor, dstColor, inputColor, dstColor,
1055                                           dstColor, inputColor);
1056                    break;
1057                case SkXfermode::kExclusion_Mode:
1058                    builder->fsCodeAppendf("\t\t%s.rgb = %s.rgb + %s.rgb - "
1059                                                        "2.0 * %s.rgb * %s.rgb;\n",
1060                                           outputColor, dstColor, inputColor, dstColor, inputColor);
1061                    break;
1062                case SkXfermode::kMultiply_Mode:
1063                    builder->fsCodeAppendf("\t\t%s.rgb = (1.0 - %s.a) * %s.rgb + "
1064                                                        "(1.0 - %s.a) * %s.rgb + "
1065                                                         "%s.rgb * %s.rgb;\n",
1066                                           outputColor, inputColor, dstColor, dstColor, inputColor,
1067                                           inputColor, dstColor);
1068                    break;
1069                case SkXfermode::kHue_Mode: {
1070                    //  SetLum(SetSat(S * Da, Sat(D * Sa)), Sa*Da, D*Sa) + (1 - Sa) * D + (1 - Da) * S
1071                    SkString setSat, setLum;
1072                    AddSatFunction(builder, &setSat);
1073                    AddLumFunction(builder, &setLum);
1074                    builder->fsCodeAppendf("\t\tvec4 dstSrcAlpha = %s * %s.a;\n",
1075                                           dstColor, inputColor);
1076                    builder->fsCodeAppendf("\t\t%s.rgb = %s(%s(%s.rgb * %s.a, dstSrcAlpha.rgb), dstSrcAlpha.a, dstSrcAlpha.rgb);\n",
1077                                           outputColor, setLum.c_str(), setSat.c_str(), inputColor,
1078                                           dstColor);
1079                    builder->fsCodeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n",
1080                                           outputColor, inputColor, dstColor, dstColor, inputColor);
1081                    break;
1082                }
1083                case SkXfermode::kSaturation_Mode: {
1084                    // SetLum(SetSat(D * Sa, Sat(S * Da)), Sa*Da, D*Sa)) + (1 - Sa) * D + (1 - Da) * S
1085                    SkString setSat, setLum;
1086                    AddSatFunction(builder, &setSat);
1087                    AddLumFunction(builder, &setLum);
1088                    builder->fsCodeAppendf("\t\tvec4 dstSrcAlpha = %s * %s.a;\n",
1089                                           dstColor, inputColor);
1090                    builder->fsCodeAppendf("\t\t%s.rgb = %s(%s(dstSrcAlpha.rgb, %s.rgb * %s.a), dstSrcAlpha.a, dstSrcAlpha.rgb);\n",
1091                                           outputColor, setLum.c_str(), setSat.c_str(), inputColor,
1092                                           dstColor);
1093                    builder->fsCodeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n",
1094                                           outputColor, inputColor, dstColor, dstColor, inputColor);
1095                    break;
1096                }
1097                case SkXfermode::kColor_Mode: {
1098                    //  SetLum(S * Da, Sa* Da, D * Sa) + (1 - Sa) * D + (1 - Da) * S
1099                    SkString setLum;
1100                    AddLumFunction(builder, &setLum);
1101                    builder->fsCodeAppendf("\t\tvec4 srcDstAlpha = %s * %s.a;\n",
1102                                           inputColor, dstColor);
1103                    builder->fsCodeAppendf("\t\t%s.rgb = %s(srcDstAlpha.rgb, srcDstAlpha.a, %s.rgb * %s.a);\n",
1104                                           outputColor, setLum.c_str(), dstColor, inputColor);
1105                    builder->fsCodeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n",
1106                                           outputColor, inputColor, dstColor, dstColor, inputColor);
1107                    break;
1108                }
1109                case SkXfermode::kLuminosity_Mode: {
1110                    //  SetLum(D * Sa, Sa* Da, S * Da) + (1 - Sa) * D + (1 - Da) * S
1111                    SkString setLum;
1112                    AddLumFunction(builder, &setLum);
1113                    builder->fsCodeAppendf("\t\tvec4 srcDstAlpha = %s * %s.a;\n",
1114                                           inputColor, dstColor);
1115                    builder->fsCodeAppendf("\t\t%s.rgb = %s(%s.rgb * %s.a, srcDstAlpha.a, srcDstAlpha.rgb);\n",
1116                                           outputColor, setLum.c_str(), dstColor, inputColor);
1117                    builder->fsCodeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n",
1118                                           outputColor, inputColor, dstColor, dstColor, inputColor);
1119                    break;
1120                }
1121                default:
1122                    GrCrash("Unknown XferEffect mode.");
1123                    break;
1124            }
1125        }
1126
1127        static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {
1128            return drawEffect.castEffect<XferEffect>().mode();
1129        }
1130
1131        virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE {}
1132
1133    private:
1134        static void HardLight(GrGLShaderBuilder* builder,
1135                              const char* final,
1136                              const char* src,
1137                              const char* dst) {
1138            builder->fsCodeAppendf("\t\t%s.a = 1.0 - (1.0 - %s.a) * (1.0 - %s.a);\n",
1139                                   final, dst, src);
1140            builder->fsCodeAppendf("\t\t%s.rgb = mix(2.0 * %s.rgb * %s.rgb, ",
1141                                   final, src, dst);
1142            builder->fsCodeAppendf("%s.aaa * %s.aaa - 2.0 * (%s.aaa - %s.rgb) * (%s.aaa - %s.rgb),",
1143                                   src, dst, dst, dst, src, src);
1144            builder->fsCodeAppendf("vec3(greaterThan(2.0 * %s.rgb, %s.aaa)));\n",
1145                                   src, src);
1146            builder->fsCodeAppendf("\t\t%s.rgb += %s.rgb * (1.0 - %s.a) + %s.rgb * (1.0 - %s.a);\n",
1147                                   final, src, dst, dst, src);
1148        }
1149
1150        // Does one component of color-dodge
1151        static void ColorDodgeComponent(GrGLShaderBuilder* builder,
1152                                        const char* final,
1153                                        const char* src,
1154                                        const char* dst,
1155                                        const char component) {
1156            builder->fsCodeAppendf("\t\tif (0.0 == %s.%c) {\n", dst, component);
1157            builder->fsCodeAppendf("\t\t\t%s.%c = %s.%c * (1.0 - %s.a);\n",
1158                                   final, component, src, component, dst);
1159            builder->fsCodeAppend("\t\t} else {\n");
1160            builder->fsCodeAppendf("\t\t\tfloat d = %s.a - %s.%c;\n", src, src, component);
1161            builder->fsCodeAppend("\t\t\tif (0.0 == d) {\n");
1162            builder->fsCodeAppendf("\t\t\t\t%s.%c = %s.a * %s.a + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);\n",
1163                                   final, component, src, dst, src, component, dst, dst, component,
1164                                   src);
1165            builder->fsCodeAppend("\t\t\t} else {\n");
1166            builder->fsCodeAppendf("\t\t\t\td = min(%s.a, %s.%c * %s.a / d);\n",
1167                                   dst, dst, component, src);
1168            builder->fsCodeAppendf("\t\t\t\t%s.%c = d * %s.a + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);\n",
1169                                   final, component, src, src, component, dst, dst, component, src);
1170            builder->fsCodeAppend("\t\t\t}\n");
1171            builder->fsCodeAppend("\t\t}\n");
1172        }
1173
1174        // Does one component of color-burn
1175        static void ColorBurnComponent(GrGLShaderBuilder* builder,
1176                                       const char* final,
1177                                       const char* src,
1178                                       const char* dst,
1179                                       const char component) {
1180            builder->fsCodeAppendf("\t\tif (%s.a == %s.%c) {\n", dst, dst, component);
1181            builder->fsCodeAppendf("\t\t\t%s.%c = %s.a * %s.a + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);\n",
1182                                   final, component, src, dst, src, component, dst, dst, component,
1183                                   src);
1184            builder->fsCodeAppendf("\t\t} else if (0.0 == %s.%c) {\n", src, component);
1185            builder->fsCodeAppendf("\t\t\t%s.%c = %s.%c * (1.0 - %s.a);\n",
1186                                   final, component, dst, component, src);
1187            builder->fsCodeAppend("\t\t} else {\n");
1188            builder->fsCodeAppendf("\t\t\tfloat d = max(0.0, %s.a - (%s.a - %s.%c) * %s.a / %s.%c);\n",
1189                                   dst, dst, dst, component, src, src, component);
1190            builder->fsCodeAppendf("\t\t\t%s.%c = %s.a * d + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);\n",
1191                                   final, component, src, src, component, dst, dst, component, src);
1192            builder->fsCodeAppend("\t\t}\n");
1193        }
1194
1195        // Does one component of soft-light. Caller should have already checked that dst alpha > 0.
1196        static void SoftLightComponentPosDstAlpha(GrGLShaderBuilder* builder,
1197                                                  const char* final,
1198                                                  const char* src,
1199                                                  const char* dst,
1200                                                  const char component) {
1201            // if (2S < Sa)
1202            builder->fsCodeAppendf("\t\t\tif (2.0 * %s.%c <= %s.a) {\n", src, component, src);
1203            // (D^2 (Sa-2 S))/Da+(1-Da) S+D (-Sa+2 S+1)
1204            builder->fsCodeAppendf("\t\t\t\t%s.%c = (%s.%c*%s.%c*(%s.a - 2.0*%s.%c)) / %s.a + (1.0 - %s.a) * %s.%c + %s.%c*(-%s.a + 2.0*%s.%c + 1.0);\n",
1205                                   final, component, dst, component, dst, component, src, src,
1206                                   component, dst, dst, src, component, dst, component, src, src,
1207                                   component);
1208            // else if (4D < Da)
1209            builder->fsCodeAppendf("\t\t\t} else if (4.0 * %s.%c <= %s.a) {\n",
1210                                   dst, component, dst);
1211            builder->fsCodeAppendf("\t\t\t\tfloat DSqd = %s.%c * %s.%c;\n",
1212                                   dst, component, dst, component);
1213            builder->fsCodeAppendf("\t\t\t\tfloat DCub = DSqd * %s.%c;\n", dst, component);
1214            builder->fsCodeAppendf("\t\t\t\tfloat DaSqd = %s.a * %s.a;\n", dst, dst);
1215            builder->fsCodeAppendf("\t\t\t\tfloat DaCub = DaSqd * %s.a;\n", dst);
1216            // (Da^3 (-S)+Da^2 (S-D (3 Sa-6 S-1))+12 Da D^2 (Sa-2 S)-16 D^3 (Sa-2 S))/Da^2
1217            builder->fsCodeAppendf("\t\t\t\t%s.%c = (-DaCub*%s.%c + DaSqd*(%s.%c - %s.%c * (3.0*%s.a - 6.0*%s.%c - 1.0)) + 12.0*%s.a*DSqd*(%s.a - 2.0*%s.%c) - 16.0*DCub * (%s.a - 2.0*%s.%c)) / DaSqd;\n",
1218                                   final, component, src, component, src, component, dst, component,
1219                                   src, src, component, dst, src, src, component, src, src,
1220                                   component);
1221            builder->fsCodeAppendf("\t\t\t} else {\n");
1222            // -sqrt(Da * D) (Sa-2 S)-Da S+D (Sa-2 S+1)+S
1223            builder->fsCodeAppendf("\t\t\t\t%s.%c = -sqrt(%s.a*%s.%c)*(%s.a - 2.0*%s.%c) - %s.a*%s.%c + %s.%c*(%s.a - 2.0*%s.%c + 1.0) + %s.%c;\n",
1224                                    final, component, dst, dst, component, src, src, component, dst,
1225                                    src, component, dst, component, src, src, component, src,
1226                                    component);
1227            builder->fsCodeAppendf("\t\t\t}\n");
1228        }
1229
1230        // Adds a function that takes two colors and an alpha as input. It produces a color with the
1231        // hue and saturation of the first color, the luminosity of the second color, and the input
1232        // alpha. It has this signature:
1233        //      vec3 set_luminance(vec3 hueSatColor, float alpha, vec3 lumColor).
1234        static void AddLumFunction(GrGLShaderBuilder* builder, SkString* setLumFunction) {
1235            // Emit a helper that gets the luminance of a color.
1236            SkString getFunction;
1237            GrGLShaderVar getLumArgs[] = {
1238                GrGLShaderVar("color", kVec3f_GrSLType),
1239            };
1240            SkString getLumBody("\treturn dot(vec3(0.3, 0.59, 0.11), color);\n");
1241            builder->emitFunction(GrGLShaderBuilder::kFragment_ShaderType,
1242                                  kFloat_GrSLType,
1243                                  "luminance",
1244                                   SK_ARRAY_COUNT(getLumArgs), getLumArgs,
1245                                   getLumBody.c_str(),
1246                                   &getFunction);
1247
1248            // Emit the set luminance function.
1249            GrGLShaderVar setLumArgs[] = {
1250                GrGLShaderVar("hueSat", kVec3f_GrSLType),
1251                GrGLShaderVar("alpha", kFloat_GrSLType),
1252                GrGLShaderVar("lumColor", kVec3f_GrSLType),
1253            };
1254            SkString setLumBody;
1255            setLumBody.printf("\tfloat diff = %s(lumColor - hueSat);\n", getFunction.c_str());
1256            setLumBody.append("\tvec3 outColor = hueSat + diff;\n");
1257            setLumBody.appendf("\tfloat outLum = %s(outColor);\n", getFunction.c_str());
1258            setLumBody.append("\tfloat minComp = min(min(outColor.r, outColor.g), outColor.b);\n"
1259                              "\tfloat maxComp = max(max(outColor.r, outColor.g), outColor.b);\n"
1260                              "\tif (minComp < 0.0) {\n"
1261                              "\t\toutColor = outLum + ((outColor - vec3(outLum, outLum, outLum)) * outLum) / (outLum - minComp);\n"
1262                              "\t}\n"
1263                              "\tif (maxComp > alpha) {\n"
1264                              "\t\toutColor = outLum + ((outColor - vec3(outLum, outLum, outLum)) * (alpha - outLum)) / (maxComp - outLum);\n"
1265                              "\t}\n"
1266                              "\treturn outColor;\n");
1267            builder->emitFunction(GrGLShaderBuilder::kFragment_ShaderType,
1268                        kVec3f_GrSLType,
1269                        "set_luminance",
1270                        SK_ARRAY_COUNT(setLumArgs), setLumArgs,
1271                        setLumBody.c_str(),
1272                        setLumFunction);
1273        }
1274
1275        // Adds a function that creates a color with the hue and luminosity of one input color and
1276        // the saturation of another color. It will have this signature:
1277        //      float set_saturation(vec3 hueLumColor, vec3 satColor)
1278        static void AddSatFunction(GrGLShaderBuilder* builder, SkString* setSatFunction) {
1279            // Emit a helper that gets the saturation of a color
1280            SkString getFunction;
1281            GrGLShaderVar getSatArgs[] = { GrGLShaderVar("color", kVec3f_GrSLType) };
1282            SkString getSatBody;
1283            getSatBody.printf("\treturn max(max(color.r, color.g), color.b) - "
1284                              "min(min(color.r, color.g), color.b);\n");
1285            builder->emitFunction(GrGLShaderBuilder::kFragment_ShaderType,
1286                                  kFloat_GrSLType,
1287                                  "saturation",
1288                                  SK_ARRAY_COUNT(getSatArgs), getSatArgs,
1289                                  getSatBody.c_str(),
1290                                  &getFunction);
1291
1292            // Emit a helper that sets the saturation given sorted input channels
1293            SkString helperFunction;
1294            GrGLShaderVar helperArgs[] = {
1295                GrGLShaderVar("minComp", kFloat_GrSLType),
1296                GrGLShaderVar("midComp", kFloat_GrSLType),
1297                GrGLShaderVar("maxComp", kFloat_GrSLType),
1298                GrGLShaderVar("sat", kFloat_GrSLType),
1299            };
1300            helperArgs[0].setTypeModifier(GrGLShaderVar::kInOut_TypeModifier);
1301            helperArgs[1].setTypeModifier(GrGLShaderVar::kInOut_TypeModifier);
1302            helperArgs[2].setTypeModifier(GrGLShaderVar::kInOut_TypeModifier);
1303            SkString helperBody;
1304            helperBody.append("\tif (minComp < maxComp) {\n"
1305                              "\t\tmidComp = sat * (midComp - minComp) / (maxComp - minComp);\n"
1306                              "\t\tmaxComp = sat;\n"
1307                              "\t} else {\n"
1308                              "\t\tmidComp = maxComp = 0.0;\n"
1309                              "\t}\n"
1310                              "\tminComp = 0.0;\n");
1311            builder->emitFunction(GrGLShaderBuilder::kFragment_ShaderType,
1312                                  kVoid_GrSLType,
1313                                  "set_saturation_helper",
1314                                  SK_ARRAY_COUNT(helperArgs), helperArgs,
1315                                  helperBody.c_str(),
1316                                  &helperFunction);
1317
1318            GrGLShaderVar setSatArgs[] = {
1319                GrGLShaderVar("hueLumColor", kVec3f_GrSLType),
1320                GrGLShaderVar("satColor", kVec3f_GrSLType),
1321            };
1322            const char* helpFunc = helperFunction.c_str();
1323            SkString setSatBody;
1324            setSatBody.appendf("\tfloat sat = %s(satColor);\n"
1325                               "\tif (hueLumColor.r <= hueLumColor.g) {\n"
1326                               "\t\tif (hueLumColor.g <= hueLumColor.b) {\n"
1327                               "\t\t\t%s(hueLumColor.r, hueLumColor.g, hueLumColor.b, sat);\n"
1328                               "\t\t} else if (hueLumColor.r <= hueLumColor.b) {\n"
1329                               "\t\t\t%s(hueLumColor.r, hueLumColor.b, hueLumColor.g, sat);\n"
1330                               "\t\t} else {\n"
1331                               "\t\t\t%s(hueLumColor.b, hueLumColor.r, hueLumColor.g, sat);\n"
1332                               "\t\t}\n"
1333                               "\t} else if (hueLumColor.r <= hueLumColor.b) {\n"
1334                               "\t\t%s(hueLumColor.g, hueLumColor.r, hueLumColor.b, sat);\n"
1335                               "\t} else if (hueLumColor.g <= hueLumColor.b) {\n"
1336                               "\t\t%s(hueLumColor.g, hueLumColor.b, hueLumColor.r, sat);\n"
1337                               "\t} else {\n"
1338                               "\t\t%s(hueLumColor.b, hueLumColor.g, hueLumColor.r, sat);\n"
1339                               "\t}\n"
1340                               "\treturn hueLumColor;",
1341                               getFunction.c_str(), helpFunc, helpFunc, helpFunc, helpFunc,
1342                               helpFunc, helpFunc);
1343            builder->emitFunction(GrGLShaderBuilder::kFragment_ShaderType,
1344                                  kVec3f_GrSLType,
1345                                  "set_saturation",
1346                                  SK_ARRAY_COUNT(setSatArgs), setSatArgs,
1347                                  setSatBody.c_str(),
1348                                  setSatFunction);
1349
1350        }
1351
1352        typedef GrGLEffect INHERITED;
1353    };
1354
1355    GR_DECLARE_EFFECT_TEST;
1356
1357private:
1358    XferEffect(SkXfermode::Mode mode) : fMode(mode) { this->setWillReadDst(); }
1359    virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE { return true; }
1360
1361    SkXfermode::Mode fMode;
1362
1363    typedef GrEffect INHERITED;
1364};
1365
1366GR_DEFINE_EFFECT_TEST(XferEffect);
1367GrEffectRef* XferEffect::TestCreate(SkMWCRandom* rand,
1368                                    GrContext*,
1369                                    const GrDrawTargetCaps&,
1370                                    GrTexture*[]) {
1371    int mode;
1372    do {
1373        mode = rand->nextRangeU(SkXfermode::kLastCoeffMode + 1, SkXfermode::kLastSeparableMode);
1374    } while (mode == SkXfermode::kHardLight_Mode);
1375
1376    static AutoEffectUnref gEffect(SkNEW_ARGS(XferEffect, (static_cast<SkXfermode::Mode>(mode))));
1377    return CreateEffectRef(gEffect);
1378}
1379
1380#endif
1381
1382///////////////////////////////////////////////////////////////////////////////
1383///////////////////////////////////////////////////////////////////////////////
1384
1385class SkProcCoeffXfermode : public SkProcXfermode {
1386public:
1387    SkProcCoeffXfermode(const ProcCoeff& rec, Mode mode)
1388            : INHERITED(rec.fProc) {
1389        fMode = mode;
1390        // these may be valid, or may be CANNOT_USE_COEFF
1391        fSrcCoeff = rec.fSC;
1392        fDstCoeff = rec.fDC;
1393    }
1394
1395    virtual bool asMode(Mode* mode) const SK_OVERRIDE {
1396        if (mode) {
1397            *mode = fMode;
1398        }
1399        return true;
1400    }
1401
1402    virtual bool asCoeff(Coeff* sc, Coeff* dc) const SK_OVERRIDE {
1403        if (CANNOT_USE_COEFF == fSrcCoeff) {
1404            return false;
1405        }
1406
1407        if (sc) {
1408            *sc = fSrcCoeff;
1409        }
1410        if (dc) {
1411            *dc = fDstCoeff;
1412        }
1413        return true;
1414    }
1415
1416#if SK_SUPPORT_GPU
1417    virtual bool asNewEffectOrCoeff(GrContext*,
1418                                    GrEffectRef** effect,
1419                                    Coeff* src,
1420                                    Coeff* dst) const SK_OVERRIDE {
1421        if (this->asCoeff(src, dst)) {
1422            return true;
1423        }
1424        if (XferEffect::IsSupportedMode(fMode)) {
1425            if (NULL != effect) {
1426                *effect = XferEffect::Create(fMode);
1427                SkASSERT(NULL != *effect);
1428            }
1429            return true;
1430        }
1431        return false;
1432    }
1433#endif
1434
1435    SK_DEVELOPER_TO_STRING()
1436    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkProcCoeffXfermode)
1437
1438protected:
1439    SkProcCoeffXfermode(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
1440        fMode = (SkXfermode::Mode)buffer.read32();
1441
1442        const ProcCoeff& rec = gProcCoeffs[fMode];
1443        // these may be valid, or may be CANNOT_USE_COEFF
1444        fSrcCoeff = rec.fSC;
1445        fDstCoeff = rec.fDC;
1446        // now update our function-ptr in the super class
1447        this->INHERITED::setProc(rec.fProc);
1448    }
1449
1450    virtual void flatten(SkFlattenableWriteBuffer& buffer) const SK_OVERRIDE {
1451        this->INHERITED::flatten(buffer);
1452        buffer.write32(fMode);
1453    }
1454
1455private:
1456    Mode    fMode;
1457    Coeff   fSrcCoeff, fDstCoeff;
1458
1459    typedef SkProcXfermode INHERITED;
1460};
1461
1462const char* SkXfermode::ModeName(Mode mode) {
1463    SkASSERT((unsigned) mode <= (unsigned)kLastMode);
1464    const char* gModeStrings[] = {
1465        "Clear", "Src", "Dst", "SrcOver", "DstOver", "SrcIn", "DstIn",
1466        "SrcOut", "DstOut", "SrcATop", "DstATop", "Xor", "Plus",
1467        "Modulate", "Screen", "Overlay", "Darken", "Lighten", "ColorDodge",
1468        "ColorBurn", "HardLight", "SoftLight", "Difference", "Exclusion",
1469        "Multiply", "Hue", "Saturation", "Color",  "Luminosity"
1470    };
1471    return gModeStrings[mode];
1472    SK_COMPILE_ASSERT(SK_ARRAY_COUNT(gModeStrings) == kLastMode + 1, mode_count);
1473}
1474
1475#ifdef SK_DEVELOPER
1476void SkProcCoeffXfermode::toString(SkString* str) const {
1477    str->append("SkProcCoeffXfermode: ");
1478
1479    str->append("mode: ");
1480    str->append(ModeName(fMode));
1481
1482    static const char* gCoeffStrings[kCoeffCount] = {
1483        "Zero", "One", "SC", "ISC", "DC", "IDC", "SA", "ISA", "DA", "IDA"
1484    };
1485
1486    str->append(" src: ");
1487    if (CANNOT_USE_COEFF == fSrcCoeff) {
1488        str->append("can't use");
1489    } else {
1490        str->append(gCoeffStrings[fSrcCoeff]);
1491    }
1492
1493    str->append(" dst: ");
1494    if (CANNOT_USE_COEFF == fDstCoeff) {
1495        str->append("can't use");
1496    } else {
1497        str->append(gCoeffStrings[fDstCoeff]);
1498    }
1499}
1500#endif
1501
1502///////////////////////////////////////////////////////////////////////////////
1503
1504class SkClearXfermode : public SkProcCoeffXfermode {
1505public:
1506    SkClearXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kClear_Mode) {}
1507
1508    virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
1509    virtual void xferA8(SkAlpha*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
1510
1511    SK_DEVELOPER_TO_STRING()
1512    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkClearXfermode)
1513
1514private:
1515    SkClearXfermode(SkFlattenableReadBuffer& buffer)
1516        : SkProcCoeffXfermode(buffer) {}
1517
1518    typedef SkProcCoeffXfermode INHERITED;
1519};
1520
1521void SkClearXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
1522                             const SkPMColor* SK_RESTRICT, int count,
1523                             const SkAlpha* SK_RESTRICT aa) const {
1524    SkASSERT(dst && count >= 0);
1525
1526    if (NULL == aa) {
1527        memset(dst, 0, count << 2);
1528    } else {
1529        for (int i = count - 1; i >= 0; --i) {
1530            unsigned a = aa[i];
1531            if (0xFF == a) {
1532                dst[i] = 0;
1533            } else if (a != 0) {
1534                dst[i] = SkAlphaMulQ(dst[i], SkAlpha255To256(255 - a));
1535            }
1536        }
1537    }
1538}
1539void SkClearXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
1540                             const SkPMColor* SK_RESTRICT, int count,
1541                             const SkAlpha* SK_RESTRICT aa) const {
1542    SkASSERT(dst && count >= 0);
1543
1544    if (NULL == aa) {
1545        memset(dst, 0, count);
1546    } else {
1547        for (int i = count - 1; i >= 0; --i) {
1548            unsigned a = aa[i];
1549            if (0xFF == a) {
1550                dst[i] = 0;
1551            } else if (0 != a) {
1552                dst[i] = SkAlphaMulAlpha(dst[i], 255 - a);
1553            }
1554        }
1555    }
1556}
1557
1558#ifdef SK_DEVELOPER
1559void SkClearXfermode::toString(SkString* str) const {
1560    this->INHERITED::toString(str);
1561}
1562#endif
1563
1564///////////////////////////////////////////////////////////////////////////////
1565
1566class SkSrcXfermode : public SkProcCoeffXfermode {
1567public:
1568    SkSrcXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kSrc_Mode) {}
1569
1570    virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
1571    virtual void xferA8(SkAlpha*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
1572
1573    SK_DEVELOPER_TO_STRING()
1574    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkSrcXfermode)
1575
1576private:
1577    SkSrcXfermode(SkFlattenableReadBuffer& buffer)
1578        : SkProcCoeffXfermode(buffer) {}
1579
1580    typedef SkProcCoeffXfermode INHERITED;
1581};
1582
1583void SkSrcXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
1584                           const SkPMColor* SK_RESTRICT src, int count,
1585                           const SkAlpha* SK_RESTRICT aa) const {
1586    SkASSERT(dst && src && count >= 0);
1587
1588    if (NULL == aa) {
1589        memcpy(dst, src, count << 2);
1590    } else {
1591        for (int i = count - 1; i >= 0; --i) {
1592            unsigned a = aa[i];
1593            if (a == 0xFF) {
1594                dst[i] = src[i];
1595            } else if (a != 0) {
1596                dst[i] = SkFourByteInterp(src[i], dst[i], a);
1597            }
1598        }
1599    }
1600}
1601
1602void SkSrcXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
1603                           const SkPMColor* SK_RESTRICT src, int count,
1604                           const SkAlpha* SK_RESTRICT aa) const {
1605    SkASSERT(dst && src && count >= 0);
1606
1607    if (NULL == aa) {
1608        for (int i = count - 1; i >= 0; --i) {
1609            dst[i] = SkToU8(SkGetPackedA32(src[i]));
1610        }
1611    } else {
1612        for (int i = count - 1; i >= 0; --i) {
1613            unsigned a = aa[i];
1614            if (0 != a) {
1615                unsigned srcA = SkGetPackedA32(src[i]);
1616                if (a == 0xFF) {
1617                    dst[i] = SkToU8(srcA);
1618                } else {
1619                    dst[i] = SkToU8(SkAlphaBlend(srcA, dst[i], a));
1620                }
1621            }
1622        }
1623    }
1624}
1625#ifdef SK_DEVELOPER
1626void SkSrcXfermode::toString(SkString* str) const {
1627    this->INHERITED::toString(str);
1628}
1629#endif
1630
1631///////////////////////////////////////////////////////////////////////////////
1632
1633class SkDstInXfermode : public SkProcCoeffXfermode {
1634public:
1635    SkDstInXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstIn_Mode) {}
1636
1637    virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
1638
1639    SK_DEVELOPER_TO_STRING()
1640    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDstInXfermode)
1641
1642private:
1643    SkDstInXfermode(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {}
1644
1645    typedef SkProcCoeffXfermode INHERITED;
1646};
1647
1648void SkDstInXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
1649                             const SkPMColor* SK_RESTRICT src, int count,
1650                             const SkAlpha* SK_RESTRICT aa) const {
1651    SkASSERT(dst && src);
1652
1653    if (count <= 0) {
1654        return;
1655    }
1656    if (NULL != aa) {
1657        return this->INHERITED::xfer32(dst, src, count, aa);
1658    }
1659
1660    do {
1661        unsigned a = SkGetPackedA32(*src);
1662        *dst = SkAlphaMulQ(*dst, SkAlpha255To256(a));
1663        dst++;
1664        src++;
1665    } while (--count != 0);
1666}
1667
1668#ifdef SK_DEVELOPER
1669void SkDstInXfermode::toString(SkString* str) const {
1670    this->INHERITED::toString(str);
1671}
1672#endif
1673
1674///////////////////////////////////////////////////////////////////////////////
1675
1676class SkDstOutXfermode : public SkProcCoeffXfermode {
1677public:
1678    SkDstOutXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstOut_Mode) {}
1679
1680    virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
1681
1682    SK_DEVELOPER_TO_STRING()
1683    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDstOutXfermode)
1684
1685private:
1686    SkDstOutXfermode(SkFlattenableReadBuffer& buffer)
1687        : INHERITED(buffer) {}
1688
1689    typedef SkProcCoeffXfermode INHERITED;
1690};
1691
1692void SkDstOutXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
1693                              const SkPMColor* SK_RESTRICT src, int count,
1694                              const SkAlpha* SK_RESTRICT aa) const {
1695    SkASSERT(dst && src);
1696
1697    if (count <= 0) {
1698        return;
1699    }
1700    if (NULL != aa) {
1701        return this->INHERITED::xfer32(dst, src, count, aa);
1702    }
1703
1704    do {
1705        unsigned a = SkGetPackedA32(*src);
1706        *dst = SkAlphaMulQ(*dst, SkAlpha255To256(255 - a));
1707        dst++;
1708        src++;
1709    } while (--count != 0);
1710}
1711
1712#ifdef SK_DEVELOPER
1713void SkDstOutXfermode::toString(SkString* str) const {
1714    this->INHERITED::toString(str);
1715}
1716#endif
1717
1718///////////////////////////////////////////////////////////////////////////////
1719
1720SkXfermode* SkXfermode::Create(Mode mode) {
1721    SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount);
1722    SkASSERT((unsigned)mode < kModeCount);
1723
1724    const ProcCoeff& rec = gProcCoeffs[mode];
1725
1726    switch (mode) {
1727        case kClear_Mode:
1728            return SkNEW_ARGS(SkClearXfermode, (rec));
1729        case kSrc_Mode:
1730            return SkNEW_ARGS(SkSrcXfermode, (rec));
1731        case kSrcOver_Mode:
1732            return NULL;
1733        case kDstIn_Mode:
1734            return SkNEW_ARGS(SkDstInXfermode, (rec));
1735        case kDstOut_Mode:
1736            return SkNEW_ARGS(SkDstOutXfermode, (rec));
1737        default:
1738            return SkNEW_ARGS(SkProcCoeffXfermode, (rec, mode));
1739    }
1740}
1741
1742SkXfermodeProc SkXfermode::GetProc(Mode mode) {
1743    SkXfermodeProc  proc = NULL;
1744    if ((unsigned)mode < kModeCount) {
1745        proc = gProcCoeffs[mode].fProc;
1746    }
1747    return proc;
1748}
1749
1750bool SkXfermode::ModeAsCoeff(Mode mode, Coeff* src, Coeff* dst) {
1751    SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount);
1752
1753    if ((unsigned)mode >= (unsigned)kModeCount) {
1754        // illegal mode parameter
1755        return false;
1756    }
1757
1758    const ProcCoeff& rec = gProcCoeffs[mode];
1759
1760    if (CANNOT_USE_COEFF == rec.fSC) {
1761        return false;
1762    }
1763
1764    SkASSERT(CANNOT_USE_COEFF != rec.fDC);
1765    if (src) {
1766        *src = rec.fSC;
1767    }
1768    if (dst) {
1769        *dst = rec.fDC;
1770    }
1771    return true;
1772}
1773
1774bool SkXfermode::AsMode(const SkXfermode* xfer, Mode* mode) {
1775    if (NULL == xfer) {
1776        if (mode) {
1777            *mode = kSrcOver_Mode;
1778        }
1779        return true;
1780    }
1781    return xfer->asMode(mode);
1782}
1783
1784bool SkXfermode::AsCoeff(const SkXfermode* xfer, Coeff* src, Coeff* dst) {
1785    if (NULL == xfer) {
1786        return ModeAsCoeff(kSrcOver_Mode, src, dst);
1787    }
1788    return xfer->asCoeff(src, dst);
1789}
1790
1791bool SkXfermode::IsMode(const SkXfermode* xfer, Mode mode) {
1792    // if xfer==null then the mode is srcover
1793    Mode m = kSrcOver_Mode;
1794    if (xfer && !xfer->asMode(&m)) {
1795        return false;
1796    }
1797    return mode == m;
1798}
1799
1800///////////////////////////////////////////////////////////////////////////////
1801//////////// 16bit xfermode procs
1802
1803#ifdef SK_DEBUG
1804static bool require_255(SkPMColor src) { return SkGetPackedA32(src) == 0xFF; }
1805static bool require_0(SkPMColor src) { return SkGetPackedA32(src) == 0; }
1806#endif
1807
1808static uint16_t src_modeproc16_255(SkPMColor src, uint16_t dst) {
1809    SkASSERT(require_255(src));
1810    return SkPixel32ToPixel16(src);
1811}
1812
1813static uint16_t dst_modeproc16(SkPMColor src, uint16_t dst) {
1814    return dst;
1815}
1816
1817static uint16_t srcover_modeproc16_0(SkPMColor src, uint16_t dst) {
1818    SkASSERT(require_0(src));
1819    return dst;
1820}
1821
1822static uint16_t srcover_modeproc16_255(SkPMColor src, uint16_t dst) {
1823    SkASSERT(require_255(src));
1824    return SkPixel32ToPixel16(src);
1825}
1826
1827static uint16_t dstover_modeproc16_0(SkPMColor src, uint16_t dst) {
1828    SkASSERT(require_0(src));
1829    return dst;
1830}
1831
1832static uint16_t dstover_modeproc16_255(SkPMColor src, uint16_t dst) {
1833    SkASSERT(require_255(src));
1834    return dst;
1835}
1836
1837static uint16_t srcin_modeproc16_255(SkPMColor src, uint16_t dst) {
1838    SkASSERT(require_255(src));
1839    return SkPixel32ToPixel16(src);
1840}
1841
1842static uint16_t dstin_modeproc16_255(SkPMColor src, uint16_t dst) {
1843    SkASSERT(require_255(src));
1844    return dst;
1845}
1846
1847static uint16_t dstout_modeproc16_0(SkPMColor src, uint16_t dst) {
1848    SkASSERT(require_0(src));
1849    return dst;
1850}
1851
1852static uint16_t srcatop_modeproc16(SkPMColor src, uint16_t dst) {
1853    unsigned isa = 255 - SkGetPackedA32(src);
1854
1855    return SkPackRGB16(
1856           SkPacked32ToR16(src) + SkAlphaMulAlpha(SkGetPackedR16(dst), isa),
1857           SkPacked32ToG16(src) + SkAlphaMulAlpha(SkGetPackedG16(dst), isa),
1858           SkPacked32ToB16(src) + SkAlphaMulAlpha(SkGetPackedB16(dst), isa));
1859}
1860
1861static uint16_t srcatop_modeproc16_0(SkPMColor src, uint16_t dst) {
1862    SkASSERT(require_0(src));
1863    return dst;
1864}
1865
1866static uint16_t srcatop_modeproc16_255(SkPMColor src, uint16_t dst) {
1867    SkASSERT(require_255(src));
1868    return SkPixel32ToPixel16(src);
1869}
1870
1871static uint16_t dstatop_modeproc16_255(SkPMColor src, uint16_t dst) {
1872    SkASSERT(require_255(src));
1873    return dst;
1874}
1875
1876/*********
1877    darken and lighten boil down to this.
1878
1879    darken  = (1 - Sa) * Dc + min(Sc, Dc)
1880    lighten = (1 - Sa) * Dc + max(Sc, Dc)
1881
1882    if (Sa == 0) these become
1883        darken  = Dc + min(0, Dc) = 0
1884        lighten = Dc + max(0, Dc) = Dc
1885
1886    if (Sa == 1) these become
1887        darken  = min(Sc, Dc)
1888        lighten = max(Sc, Dc)
1889*/
1890
1891static uint16_t darken_modeproc16_0(SkPMColor src, uint16_t dst) {
1892    SkASSERT(require_0(src));
1893    return 0;
1894}
1895
1896static uint16_t darken_modeproc16_255(SkPMColor src, uint16_t dst) {
1897    SkASSERT(require_255(src));
1898    unsigned r = SkFastMin32(SkPacked32ToR16(src), SkGetPackedR16(dst));
1899    unsigned g = SkFastMin32(SkPacked32ToG16(src), SkGetPackedG16(dst));
1900    unsigned b = SkFastMin32(SkPacked32ToB16(src), SkGetPackedB16(dst));
1901    return SkPackRGB16(r, g, b);
1902}
1903
1904static uint16_t lighten_modeproc16_0(SkPMColor src, uint16_t dst) {
1905    SkASSERT(require_0(src));
1906    return dst;
1907}
1908
1909static uint16_t lighten_modeproc16_255(SkPMColor src, uint16_t dst) {
1910    SkASSERT(require_255(src));
1911    unsigned r = SkMax32(SkPacked32ToR16(src), SkGetPackedR16(dst));
1912    unsigned g = SkMax32(SkPacked32ToG16(src), SkGetPackedG16(dst));
1913    unsigned b = SkMax32(SkPacked32ToB16(src), SkGetPackedB16(dst));
1914    return SkPackRGB16(r, g, b);
1915}
1916
1917struct Proc16Rec {
1918    SkXfermodeProc16    fProc16_0;
1919    SkXfermodeProc16    fProc16_255;
1920    SkXfermodeProc16    fProc16_General;
1921};
1922
1923static const Proc16Rec gModeProcs16[] = {
1924    { NULL,                 NULL,                   NULL            }, // CLEAR
1925    { NULL,                 src_modeproc16_255,     NULL            },
1926    { dst_modeproc16,       dst_modeproc16,         dst_modeproc16  },
1927    { srcover_modeproc16_0, srcover_modeproc16_255, NULL            },
1928    { dstover_modeproc16_0, dstover_modeproc16_255, NULL            },
1929    { NULL,                 srcin_modeproc16_255,   NULL            },
1930    { NULL,                 dstin_modeproc16_255,   NULL            },
1931    { NULL,                 NULL,                   NULL            },// SRC_OUT
1932    { dstout_modeproc16_0,  NULL,                   NULL            },
1933    { srcatop_modeproc16_0, srcatop_modeproc16_255, srcatop_modeproc16  },
1934    { NULL,                 dstatop_modeproc16_255, NULL            },
1935    { NULL,                 NULL,                   NULL            }, // XOR
1936
1937    { NULL,                 NULL,                   NULL            }, // plus
1938    { NULL,                 NULL,                   NULL            }, // modulate
1939    { NULL,                 NULL,                   NULL            }, // screen
1940    { NULL,                 NULL,                   NULL            }, // overlay
1941    { darken_modeproc16_0,  darken_modeproc16_255,  NULL            }, // darken
1942    { lighten_modeproc16_0, lighten_modeproc16_255, NULL            }, // lighten
1943    { NULL,                 NULL,                   NULL            }, // colordodge
1944    { NULL,                 NULL,                   NULL            }, // colorburn
1945    { NULL,                 NULL,                   NULL            }, // hardlight
1946    { NULL,                 NULL,                   NULL            }, // softlight
1947    { NULL,                 NULL,                   NULL            }, // difference
1948    { NULL,                 NULL,                   NULL            }, // exclusion
1949    { NULL,                 NULL,                   NULL            }, // multiply
1950    { NULL,                 NULL,                   NULL            }, // hue
1951    { NULL,                 NULL,                   NULL            }, // saturation
1952    { NULL,                 NULL,                   NULL            }, // color
1953    { NULL,                 NULL,                   NULL            }, // luminosity
1954};
1955
1956SkXfermodeProc16 SkXfermode::GetProc16(Mode mode, SkColor srcColor) {
1957    SkXfermodeProc16  proc16 = NULL;
1958    if ((unsigned)mode < kModeCount) {
1959        const Proc16Rec& rec = gModeProcs16[mode];
1960        unsigned a = SkColorGetA(srcColor);
1961
1962        if (0 == a) {
1963            proc16 = rec.fProc16_0;
1964        } else if (255 == a) {
1965            proc16 = rec.fProc16_255;
1966        } else {
1967            proc16 = rec.fProc16_General;
1968        }
1969    }
1970    return proc16;
1971}
1972
1973SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkXfermode)
1974    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkProcCoeffXfermode)
1975    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkClearXfermode)
1976    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSrcXfermode)
1977    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDstInXfermode)
1978    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDstOutXfermode)
1979SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
1980