SkXfermode.cpp revision 8da9bc751e1898d50dd84d7e5ca666b00e4ff624
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::kLastSeparableMode;
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            // These all perform src-over on the alpha channel.
1004            builder->fsCodeAppendf("\t\t%s.a = %s.a + (1.0 - %s.a) * %s.a;\n",
1005                                    outputColor, inputColor, inputColor, dstColor);
1006
1007            switch (drawEffect.castEffect<XferEffect>().mode()) {
1008                case SkXfermode::kOverlay_Mode:
1009                    // Overlay is Hard-Light with the src and dst reversed
1010                    HardLight(builder, outputColor, dstColor, inputColor);
1011                    break;
1012                case SkXfermode::kDarken_Mode:
1013                    builder->fsCodeAppendf("\t\t%s.rgb = min((1.0 - %s.a) * %s.rgb + %s.rgb, "
1014                                                            "(1.0 - %s.a) * %s.rgb + %s.rgb);\n",
1015                                            outputColor,
1016                                            inputColor, dstColor, inputColor,
1017                                            dstColor, inputColor, dstColor);
1018                    break;
1019                case SkXfermode::kLighten_Mode:
1020                    builder->fsCodeAppendf("\t\t%s.rgb = max((1.0 - %s.a) * %s.rgb + %s.rgb, "
1021                                                            "(1.0 - %s.a) * %s.rgb + %s.rgb);\n",
1022                                            outputColor,
1023                                            inputColor, dstColor, inputColor,
1024                                            dstColor, inputColor, dstColor);
1025                    break;
1026                case SkXfermode::kColorDodge_Mode:
1027                    ColorDodgeComponent(builder, outputColor, inputColor, dstColor, 'r');
1028                    ColorDodgeComponent(builder, outputColor, inputColor, dstColor, 'g');
1029                    ColorDodgeComponent(builder, outputColor, inputColor, dstColor, 'b');
1030                    break;
1031                case SkXfermode::kColorBurn_Mode:
1032                    ColorBurnComponent(builder, outputColor, inputColor, dstColor, 'r');
1033                    ColorBurnComponent(builder, outputColor, inputColor, dstColor, 'g');
1034                    ColorBurnComponent(builder, outputColor, inputColor, dstColor, 'b');
1035                    break;
1036                case SkXfermode::kHardLight_Mode:
1037                    HardLight(builder, outputColor, inputColor, dstColor);
1038                    break;
1039                case SkXfermode::kSoftLight_Mode:
1040                    builder->fsCodeAppendf("\t\tif (0.0 == %s.a) {\n", dstColor);
1041                    builder->fsCodeAppendf("\t\t\t%s.rgba = %s;\n", outputColor, inputColor);
1042                    builder->fsCodeAppendf("\t\t} else {\n");
1043                    SoftLightComponentPosDstAlpha(builder, outputColor, inputColor, dstColor, 'r');
1044                    SoftLightComponentPosDstAlpha(builder, outputColor, inputColor, dstColor, 'g');
1045                    SoftLightComponentPosDstAlpha(builder, outputColor, inputColor, dstColor, 'b');
1046                    builder->fsCodeAppendf("\t\t}\n");
1047                    break;
1048                case SkXfermode::kDifference_Mode:
1049                    builder->fsCodeAppendf("\t\t%s.rgb = %s.rgb + %s.rgb -"
1050                                                       "2.0 * min(%s.rgb * %s.a, %s.rgb * %s.a);\n",
1051                                           outputColor, inputColor, dstColor, inputColor, dstColor,
1052                                           dstColor, inputColor);
1053                    break;
1054                case SkXfermode::kExclusion_Mode:
1055                    builder->fsCodeAppendf("\t\t%s.rgb = %s.rgb + %s.rgb - "
1056                                                        "2.0 * %s.rgb * %s.rgb;\n",
1057                                           outputColor, dstColor, inputColor, dstColor, inputColor);
1058                    break;
1059                case SkXfermode::kMultiply_Mode:
1060                    builder->fsCodeAppendf("\t\t%s.rgb = (1.0 - %s.a) * %s.rgb + "
1061                                                        "(1.0 - %s.a) * %s.rgb + "
1062                                                         "%s.rgb * %s.rgb;\n",
1063                                           outputColor, inputColor, dstColor, dstColor, inputColor,
1064                                           inputColor, dstColor);
1065                    break;
1066                case SkXfermode::kHue_Mode:
1067                case SkXfermode::kSaturation_Mode:
1068                case SkXfermode::kColor_Mode:
1069                case SkXfermode::kLuminosity_Mode:
1070                    GrCrash("Unimplemented XferEffect mode.");
1071                    break;
1072                default:
1073                    GrCrash("Unknown XferEffect mode.");
1074                    break;
1075            }
1076        }
1077
1078        static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {
1079            return drawEffect.castEffect<XferEffect>().mode();
1080        }
1081
1082        virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE {}
1083
1084    private:
1085        static void HardLight(GrGLShaderBuilder* builder,
1086                              const char* final,
1087                              const char* src,
1088                              const char* dst) {
1089            builder->fsCodeAppendf("\t\t%s.a = 1.0 - (1.0 - %s.a) * (1.0 - %s.a);\n",
1090                                   final, dst, src);
1091            builder->fsCodeAppendf("\t\t%s.rgb = mix(2.0 * %s.rgb * %s.rgb, ",
1092                                   final, src, dst);
1093            builder->fsCodeAppendf("%s.aaa * %s.aaa - 2.0 * (%s.aaa - %s.rgb) * (%s.aaa - %s.rgb),",
1094                                   src, dst, dst, dst, src, src);
1095            builder->fsCodeAppendf("vec3(greaterThan(2.0 * %s.rgb, %s.aaa)));\n",
1096                                   src, src);
1097            builder->fsCodeAppendf("\t\t%s.rgb += %s.rgb * (1.0 - %s.a) + %s.rgb * (1.0 - %s.a);\n",
1098                                   final, src, dst, dst, src);
1099        }
1100
1101        // Does one component of color-dodge
1102        static void ColorDodgeComponent(GrGLShaderBuilder* builder,
1103                                        const char* final,
1104                                        const char* src,
1105                                        const char* dst,
1106                                        const char component) {
1107            builder->fsCodeAppendf("\t\tif (0.0 == %s.%c) {\n", dst, component);
1108            builder->fsCodeAppendf("\t\t\t%s.%c = %s.%c * (1 - %s.a);\n",
1109                                   final, component, src, component, dst);
1110            builder->fsCodeAppend("\t\t} else {\n");
1111            builder->fsCodeAppendf("\t\t\tfloat d = %s.a - %s.%c;\n", src, src, component);
1112            builder->fsCodeAppend("\t\t\tif (0 == d) {\n");
1113            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",
1114                                   final, component, src, dst, src, component, dst, dst, component,
1115                                   src);
1116            builder->fsCodeAppend("\t\t\t} else {\n");
1117            builder->fsCodeAppendf("\t\t\t\td = min(%s.a, %s.%c * %s.a / d);\n",
1118                                   dst, dst, component, src);
1119            builder->fsCodeAppendf("\t\t\t\t%s.%c = d * %s.a + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);\n",
1120                                   final, component, src, src, component, dst, dst, component, src);
1121            builder->fsCodeAppend("\t\t\t}\n");
1122            builder->fsCodeAppend("\t\t}\n");
1123        }
1124
1125        // Does one component of color-burn
1126        static void ColorBurnComponent(GrGLShaderBuilder* builder,
1127                                       const char* final,
1128                                       const char* src,
1129                                       const char* dst,
1130                                       const char component) {
1131            builder->fsCodeAppendf("\t\tif (%s.a == %s.%c) {\n", dst, dst, component);
1132            builder->fsCodeAppendf("\t\t\t%s.%c = %s.a * %s.a + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);\n",
1133                                   final, component, src, dst, src, component, dst, dst, component,
1134                                   src);
1135            builder->fsCodeAppendf("\t\t} else if (0.0 == %s.%c) {\n", src, component);
1136            builder->fsCodeAppendf("\t\t\t%s.%c = %s.%c * (1.0 - %s.a);\n",
1137                                   final, component, dst, component, src);
1138            builder->fsCodeAppend("\t\t} else {\n");
1139            builder->fsCodeAppendf("\t\t\tfloat d = max(0.0, %s.a - (%s.a - %s.%c) * %s.a / %s.%c);\n",
1140                                   dst, dst, dst, component, src, src, component);
1141            builder->fsCodeAppendf("\t\t\t%s.%c = %s.a * d + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);\n",
1142                                   final, component, src, src, component, dst, dst, component, src);
1143            builder->fsCodeAppend("\t\t}\n");
1144        }
1145
1146        // Does one component of soft-light. Caller should have already checked that dst alpha > 0.
1147        static void SoftLightComponentPosDstAlpha(GrGLShaderBuilder* builder,
1148                                                  const char* final,
1149                                                  const char* src,
1150                                                  const char* dst,
1151                                                  const char component) {
1152            // if (2S < Sa)
1153            builder->fsCodeAppendf("\t\t\tif (2.0 * %s.%c <= %s.a) {\n", src, component, src);
1154            // (D^2 (Sa-2 S))/Da+(1-Da) S+D (-Sa+2 S+1)
1155            builder->fsCodeAppendf("\t\t\t\t%s.%c = (%s.%c*%s.%c*(%s.a - 2*%s.%c)) / %s.a + (1 - %s.a) * %s.%c + %s.%c*(-%s.a + 2*%s.%c + 1);\n",
1156                                   final, component, dst, component, dst, component, src, src,
1157                                   component, dst, dst, src, component, dst, component, src, src,
1158                                   component);
1159            // else if (4D < Da)
1160            builder->fsCodeAppendf("\t\t\t} else if (4.0 * %s.%c <= %s.a) {\n",
1161                                   dst, component, dst);
1162            builder->fsCodeAppendf("\t\t\t\tfloat DSqd = %s.%c * %s.%c;\n",
1163                                   dst, component, dst, component);
1164            builder->fsCodeAppendf("\t\t\t\tfloat DCub = DSqd * %s.%c;\n", dst, component);
1165            builder->fsCodeAppendf("\t\t\t\tfloat DaSqd = %s.a * %s.a;\n", dst, dst);
1166            builder->fsCodeAppendf("\t\t\t\tfloat DaCub = DaSqd * %s.a;\n", dst);
1167            // (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
1168            builder->fsCodeAppendf("\t\t\t\t%s.%c = (-DaCub*%s.%c + DaSqd*(%s.%c - %s.%c * (3*%s.a - 6*%s.%c - 1)) + 12*%s.a*DSqd*(%s.a - 2*%s.%c) - 16*DCub * (%s.a - 2*%s.%c)) / DaSqd;\n",
1169                                   final, component, src, component, src, component, dst, component,
1170                                   src, src, component, dst, src, src, component, src, src,
1171                                   component);
1172            builder->fsCodeAppendf("\t\t\t} else {\n");
1173            // -sqrt(Da * D) (Sa-2 S)-Da S+D (Sa-2 S+1)+S
1174            builder->fsCodeAppendf("\t\t\t\t%s.%c = -sqrt(%s.a*%s.%c)*(%s.a - 2*%s.%c) - %s.a*%s.%c + %s.%c*(%s.a - 2*%s.%c + 1) + %s.%c;\n",
1175                                    final, component, dst, dst, component, src, src, component, dst,
1176                                    src, component, dst, component, src, src, component, src,
1177                                    component);
1178            builder->fsCodeAppendf("\t\t\t}\n");
1179        }
1180
1181        typedef GrGLEffect INHERITED;
1182    };
1183
1184    GR_DECLARE_EFFECT_TEST;
1185
1186private:
1187    XferEffect(SkXfermode::Mode mode) : fMode(mode) { this->setWillReadDst(); }
1188    virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE { return true; }
1189
1190    SkXfermode::Mode fMode;
1191
1192    typedef GrEffect INHERITED;
1193};
1194
1195GR_DEFINE_EFFECT_TEST(XferEffect);
1196GrEffectRef* XferEffect::TestCreate(SkMWCRandom* rand,
1197                                    GrContext*,
1198                                    const GrDrawTargetCaps&,
1199                                    GrTexture*[]) {
1200    int mode = rand->nextRangeU(SkXfermode::kLastCoeffMode + 1, SkXfermode::kLastSeparableMode);
1201    static AutoEffectUnref gEffect(SkNEW_ARGS(XferEffect, (static_cast<SkXfermode::Mode>(mode))));
1202    return CreateEffectRef(gEffect);
1203}
1204
1205#endif
1206
1207///////////////////////////////////////////////////////////////////////////////
1208///////////////////////////////////////////////////////////////////////////////
1209
1210class SkProcCoeffXfermode : public SkProcXfermode {
1211public:
1212    SkProcCoeffXfermode(const ProcCoeff& rec, Mode mode)
1213            : INHERITED(rec.fProc) {
1214        fMode = mode;
1215        // these may be valid, or may be CANNOT_USE_COEFF
1216        fSrcCoeff = rec.fSC;
1217        fDstCoeff = rec.fDC;
1218    }
1219
1220    virtual bool asMode(Mode* mode) const SK_OVERRIDE {
1221        if (mode) {
1222            *mode = fMode;
1223        }
1224        return true;
1225    }
1226
1227    virtual bool asCoeff(Coeff* sc, Coeff* dc) const SK_OVERRIDE {
1228        if (CANNOT_USE_COEFF == fSrcCoeff) {
1229            return false;
1230        }
1231
1232        if (sc) {
1233            *sc = fSrcCoeff;
1234        }
1235        if (dc) {
1236            *dc = fDstCoeff;
1237        }
1238        return true;
1239    }
1240
1241#if SK_SUPPORT_GPU
1242    virtual bool asNewEffectOrCoeff(GrContext*,
1243                                    GrEffectRef** effect,
1244                                    Coeff* src,
1245                                    Coeff* dst) const SK_OVERRIDE {
1246        if (this->asCoeff(src, dst)) {
1247            return true;
1248        }
1249        if (XferEffect::IsSupportedMode(fMode)) {
1250            if (NULL != effect) {
1251                *effect = XferEffect::Create(fMode);
1252                SkASSERT(NULL != *effect);
1253            }
1254            return true;
1255        }
1256        return false;
1257    }
1258#endif
1259
1260    SK_DEVELOPER_TO_STRING()
1261    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkProcCoeffXfermode)
1262
1263protected:
1264    SkProcCoeffXfermode(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
1265        fMode = (SkXfermode::Mode)buffer.read32();
1266
1267        const ProcCoeff& rec = gProcCoeffs[fMode];
1268        // these may be valid, or may be CANNOT_USE_COEFF
1269        fSrcCoeff = rec.fSC;
1270        fDstCoeff = rec.fDC;
1271        // now update our function-ptr in the super class
1272        this->INHERITED::setProc(rec.fProc);
1273    }
1274
1275    virtual void flatten(SkFlattenableWriteBuffer& buffer) const SK_OVERRIDE {
1276        this->INHERITED::flatten(buffer);
1277        buffer.write32(fMode);
1278    }
1279
1280private:
1281    Mode    fMode;
1282    Coeff   fSrcCoeff, fDstCoeff;
1283
1284    typedef SkProcXfermode INHERITED;
1285};
1286
1287const char* SkXfermode::ModeName(Mode mode) {
1288    SkASSERT((unsigned) mode <= (unsigned)kLastMode);
1289    const char* gModeStrings[] = {
1290        "Clear", "Src", "Dst", "SrcOver", "DstOver", "SrcIn", "DstIn",
1291        "SrcOut", "DstOut", "SrcATop", "DstATop", "Xor", "Plus",
1292        "Modulate", "Screen", "Overlay", "Darken", "Lighten", "ColorDodge",
1293        "ColorBurn", "HardLight", "SoftLight", "Difference", "Exclusion",
1294        "Multiply", "Hue", "Saturation", "Color",  "Luminosity"
1295    };
1296    return gModeStrings[mode];
1297    SK_COMPILE_ASSERT(SK_ARRAY_COUNT(gModeStrings) == kLastMode + 1, mode_count);
1298}
1299
1300#ifdef SK_DEVELOPER
1301void SkProcCoeffXfermode::toString(SkString* str) const {
1302    str->append("SkProcCoeffXfermode: ");
1303
1304    str->append("mode: ");
1305    str->append(ModeName(fMode));
1306
1307    static const char* gCoeffStrings[kCoeffCount] = {
1308        "Zero", "One", "SC", "ISC", "DC", "IDC", "SA", "ISA", "DA", "IDA"
1309    };
1310
1311    str->append(" src: ");
1312    if (CANNOT_USE_COEFF == fSrcCoeff) {
1313        str->append("can't use");
1314    } else {
1315        str->append(gCoeffStrings[fSrcCoeff]);
1316    }
1317
1318    str->append(" dst: ");
1319    if (CANNOT_USE_COEFF == fDstCoeff) {
1320        str->append("can't use");
1321    } else {
1322        str->append(gCoeffStrings[fDstCoeff]);
1323    }
1324}
1325#endif
1326
1327///////////////////////////////////////////////////////////////////////////////
1328
1329class SkClearXfermode : public SkProcCoeffXfermode {
1330public:
1331    SkClearXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kClear_Mode) {}
1332
1333    virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
1334    virtual void xferA8(SkAlpha*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
1335
1336    SK_DEVELOPER_TO_STRING()
1337    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkClearXfermode)
1338
1339private:
1340    SkClearXfermode(SkFlattenableReadBuffer& buffer)
1341        : SkProcCoeffXfermode(buffer) {}
1342
1343    typedef SkProcCoeffXfermode INHERITED;
1344};
1345
1346void SkClearXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
1347                             const SkPMColor* SK_RESTRICT, int count,
1348                             const SkAlpha* SK_RESTRICT aa) const {
1349    SkASSERT(dst && count >= 0);
1350
1351    if (NULL == aa) {
1352        memset(dst, 0, count << 2);
1353    } else {
1354        for (int i = count - 1; i >= 0; --i) {
1355            unsigned a = aa[i];
1356            if (0xFF == a) {
1357                dst[i] = 0;
1358            } else if (a != 0) {
1359                dst[i] = SkAlphaMulQ(dst[i], SkAlpha255To256(255 - a));
1360            }
1361        }
1362    }
1363}
1364void SkClearXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
1365                             const SkPMColor* SK_RESTRICT, int count,
1366                             const SkAlpha* SK_RESTRICT aa) const {
1367    SkASSERT(dst && count >= 0);
1368
1369    if (NULL == aa) {
1370        memset(dst, 0, count);
1371    } else {
1372        for (int i = count - 1; i >= 0; --i) {
1373            unsigned a = aa[i];
1374            if (0xFF == a) {
1375                dst[i] = 0;
1376            } else if (0 != a) {
1377                dst[i] = SkAlphaMulAlpha(dst[i], 255 - a);
1378            }
1379        }
1380    }
1381}
1382
1383#ifdef SK_DEVELOPER
1384void SkClearXfermode::toString(SkString* str) const {
1385    this->INHERITED::toString(str);
1386}
1387#endif
1388
1389///////////////////////////////////////////////////////////////////////////////
1390
1391class SkSrcXfermode : public SkProcCoeffXfermode {
1392public:
1393    SkSrcXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kSrc_Mode) {}
1394
1395    virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
1396    virtual void xferA8(SkAlpha*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
1397
1398    SK_DEVELOPER_TO_STRING()
1399    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkSrcXfermode)
1400
1401private:
1402    SkSrcXfermode(SkFlattenableReadBuffer& buffer)
1403        : SkProcCoeffXfermode(buffer) {}
1404
1405    typedef SkProcCoeffXfermode INHERITED;
1406};
1407
1408void SkSrcXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
1409                           const SkPMColor* SK_RESTRICT src, int count,
1410                           const SkAlpha* SK_RESTRICT aa) const {
1411    SkASSERT(dst && src && count >= 0);
1412
1413    if (NULL == aa) {
1414        memcpy(dst, src, count << 2);
1415    } else {
1416        for (int i = count - 1; i >= 0; --i) {
1417            unsigned a = aa[i];
1418            if (a == 0xFF) {
1419                dst[i] = src[i];
1420            } else if (a != 0) {
1421                dst[i] = SkFourByteInterp(src[i], dst[i], a);
1422            }
1423        }
1424    }
1425}
1426
1427void SkSrcXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
1428                           const SkPMColor* SK_RESTRICT src, int count,
1429                           const SkAlpha* SK_RESTRICT aa) const {
1430    SkASSERT(dst && src && count >= 0);
1431
1432    if (NULL == aa) {
1433        for (int i = count - 1; i >= 0; --i) {
1434            dst[i] = SkToU8(SkGetPackedA32(src[i]));
1435        }
1436    } else {
1437        for (int i = count - 1; i >= 0; --i) {
1438            unsigned a = aa[i];
1439            if (0 != a) {
1440                unsigned srcA = SkGetPackedA32(src[i]);
1441                if (a == 0xFF) {
1442                    dst[i] = SkToU8(srcA);
1443                } else {
1444                    dst[i] = SkToU8(SkAlphaBlend(srcA, dst[i], a));
1445                }
1446            }
1447        }
1448    }
1449}
1450#ifdef SK_DEVELOPER
1451void SkSrcXfermode::toString(SkString* str) const {
1452    this->INHERITED::toString(str);
1453}
1454#endif
1455
1456///////////////////////////////////////////////////////////////////////////////
1457
1458class SkDstInXfermode : public SkProcCoeffXfermode {
1459public:
1460    SkDstInXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstIn_Mode) {}
1461
1462    virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
1463
1464    SK_DEVELOPER_TO_STRING()
1465    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDstInXfermode)
1466
1467private:
1468    SkDstInXfermode(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {}
1469
1470    typedef SkProcCoeffXfermode INHERITED;
1471};
1472
1473void SkDstInXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
1474                             const SkPMColor* SK_RESTRICT src, int count,
1475                             const SkAlpha* SK_RESTRICT aa) const {
1476    SkASSERT(dst && src);
1477
1478    if (count <= 0) {
1479        return;
1480    }
1481    if (NULL != aa) {
1482        return this->INHERITED::xfer32(dst, src, count, aa);
1483    }
1484
1485    do {
1486        unsigned a = SkGetPackedA32(*src);
1487        *dst = SkAlphaMulQ(*dst, SkAlpha255To256(a));
1488        dst++;
1489        src++;
1490    } while (--count != 0);
1491}
1492
1493#ifdef SK_DEVELOPER
1494void SkDstInXfermode::toString(SkString* str) const {
1495    this->INHERITED::toString(str);
1496}
1497#endif
1498
1499///////////////////////////////////////////////////////////////////////////////
1500
1501class SkDstOutXfermode : public SkProcCoeffXfermode {
1502public:
1503    SkDstOutXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstOut_Mode) {}
1504
1505    virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
1506
1507    SK_DEVELOPER_TO_STRING()
1508    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDstOutXfermode)
1509
1510private:
1511    SkDstOutXfermode(SkFlattenableReadBuffer& buffer)
1512        : INHERITED(buffer) {}
1513
1514    typedef SkProcCoeffXfermode INHERITED;
1515};
1516
1517void SkDstOutXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
1518                              const SkPMColor* SK_RESTRICT src, int count,
1519                              const SkAlpha* SK_RESTRICT aa) const {
1520    SkASSERT(dst && src);
1521
1522    if (count <= 0) {
1523        return;
1524    }
1525    if (NULL != aa) {
1526        return this->INHERITED::xfer32(dst, src, count, aa);
1527    }
1528
1529    do {
1530        unsigned a = SkGetPackedA32(*src);
1531        *dst = SkAlphaMulQ(*dst, SkAlpha255To256(255 - a));
1532        dst++;
1533        src++;
1534    } while (--count != 0);
1535}
1536
1537#ifdef SK_DEVELOPER
1538void SkDstOutXfermode::toString(SkString* str) const {
1539    this->INHERITED::toString(str);
1540}
1541#endif
1542
1543///////////////////////////////////////////////////////////////////////////////
1544
1545SkXfermode* SkXfermode::Create(Mode mode) {
1546    SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount);
1547    SkASSERT((unsigned)mode < kModeCount);
1548
1549    const ProcCoeff& rec = gProcCoeffs[mode];
1550
1551    switch (mode) {
1552        case kClear_Mode:
1553            return SkNEW_ARGS(SkClearXfermode, (rec));
1554        case kSrc_Mode:
1555            return SkNEW_ARGS(SkSrcXfermode, (rec));
1556        case kSrcOver_Mode:
1557            return NULL;
1558        case kDstIn_Mode:
1559            return SkNEW_ARGS(SkDstInXfermode, (rec));
1560        case kDstOut_Mode:
1561            return SkNEW_ARGS(SkDstOutXfermode, (rec));
1562        default:
1563            return SkNEW_ARGS(SkProcCoeffXfermode, (rec, mode));
1564    }
1565}
1566
1567SkXfermodeProc SkXfermode::GetProc(Mode mode) {
1568    SkXfermodeProc  proc = NULL;
1569    if ((unsigned)mode < kModeCount) {
1570        proc = gProcCoeffs[mode].fProc;
1571    }
1572    return proc;
1573}
1574
1575bool SkXfermode::ModeAsCoeff(Mode mode, Coeff* src, Coeff* dst) {
1576    SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount);
1577
1578    if ((unsigned)mode >= (unsigned)kModeCount) {
1579        // illegal mode parameter
1580        return false;
1581    }
1582
1583    const ProcCoeff& rec = gProcCoeffs[mode];
1584
1585    if (CANNOT_USE_COEFF == rec.fSC) {
1586        return false;
1587    }
1588
1589    SkASSERT(CANNOT_USE_COEFF != rec.fDC);
1590    if (src) {
1591        *src = rec.fSC;
1592    }
1593    if (dst) {
1594        *dst = rec.fDC;
1595    }
1596    return true;
1597}
1598
1599bool SkXfermode::AsMode(const SkXfermode* xfer, Mode* mode) {
1600    if (NULL == xfer) {
1601        if (mode) {
1602            *mode = kSrcOver_Mode;
1603        }
1604        return true;
1605    }
1606    return xfer->asMode(mode);
1607}
1608
1609bool SkXfermode::AsCoeff(const SkXfermode* xfer, Coeff* src, Coeff* dst) {
1610    if (NULL == xfer) {
1611        return ModeAsCoeff(kSrcOver_Mode, src, dst);
1612    }
1613    return xfer->asCoeff(src, dst);
1614}
1615
1616bool SkXfermode::IsMode(const SkXfermode* xfer, Mode mode) {
1617    // if xfer==null then the mode is srcover
1618    Mode m = kSrcOver_Mode;
1619    if (xfer && !xfer->asMode(&m)) {
1620        return false;
1621    }
1622    return mode == m;
1623}
1624
1625///////////////////////////////////////////////////////////////////////////////
1626//////////// 16bit xfermode procs
1627
1628#ifdef SK_DEBUG
1629static bool require_255(SkPMColor src) { return SkGetPackedA32(src) == 0xFF; }
1630static bool require_0(SkPMColor src) { return SkGetPackedA32(src) == 0; }
1631#endif
1632
1633static uint16_t src_modeproc16_255(SkPMColor src, uint16_t dst) {
1634    SkASSERT(require_255(src));
1635    return SkPixel32ToPixel16(src);
1636}
1637
1638static uint16_t dst_modeproc16(SkPMColor src, uint16_t dst) {
1639    return dst;
1640}
1641
1642static uint16_t srcover_modeproc16_0(SkPMColor src, uint16_t dst) {
1643    SkASSERT(require_0(src));
1644    return dst;
1645}
1646
1647static uint16_t srcover_modeproc16_255(SkPMColor src, uint16_t dst) {
1648    SkASSERT(require_255(src));
1649    return SkPixel32ToPixel16(src);
1650}
1651
1652static uint16_t dstover_modeproc16_0(SkPMColor src, uint16_t dst) {
1653    SkASSERT(require_0(src));
1654    return dst;
1655}
1656
1657static uint16_t dstover_modeproc16_255(SkPMColor src, uint16_t dst) {
1658    SkASSERT(require_255(src));
1659    return dst;
1660}
1661
1662static uint16_t srcin_modeproc16_255(SkPMColor src, uint16_t dst) {
1663    SkASSERT(require_255(src));
1664    return SkPixel32ToPixel16(src);
1665}
1666
1667static uint16_t dstin_modeproc16_255(SkPMColor src, uint16_t dst) {
1668    SkASSERT(require_255(src));
1669    return dst;
1670}
1671
1672static uint16_t dstout_modeproc16_0(SkPMColor src, uint16_t dst) {
1673    SkASSERT(require_0(src));
1674    return dst;
1675}
1676
1677static uint16_t srcatop_modeproc16(SkPMColor src, uint16_t dst) {
1678    unsigned isa = 255 - SkGetPackedA32(src);
1679
1680    return SkPackRGB16(
1681           SkPacked32ToR16(src) + SkAlphaMulAlpha(SkGetPackedR16(dst), isa),
1682           SkPacked32ToG16(src) + SkAlphaMulAlpha(SkGetPackedG16(dst), isa),
1683           SkPacked32ToB16(src) + SkAlphaMulAlpha(SkGetPackedB16(dst), isa));
1684}
1685
1686static uint16_t srcatop_modeproc16_0(SkPMColor src, uint16_t dst) {
1687    SkASSERT(require_0(src));
1688    return dst;
1689}
1690
1691static uint16_t srcatop_modeproc16_255(SkPMColor src, uint16_t dst) {
1692    SkASSERT(require_255(src));
1693    return SkPixel32ToPixel16(src);
1694}
1695
1696static uint16_t dstatop_modeproc16_255(SkPMColor src, uint16_t dst) {
1697    SkASSERT(require_255(src));
1698    return dst;
1699}
1700
1701/*********
1702    darken and lighten boil down to this.
1703
1704    darken  = (1 - Sa) * Dc + min(Sc, Dc)
1705    lighten = (1 - Sa) * Dc + max(Sc, Dc)
1706
1707    if (Sa == 0) these become
1708        darken  = Dc + min(0, Dc) = 0
1709        lighten = Dc + max(0, Dc) = Dc
1710
1711    if (Sa == 1) these become
1712        darken  = min(Sc, Dc)
1713        lighten = max(Sc, Dc)
1714*/
1715
1716static uint16_t darken_modeproc16_0(SkPMColor src, uint16_t dst) {
1717    SkASSERT(require_0(src));
1718    return 0;
1719}
1720
1721static uint16_t darken_modeproc16_255(SkPMColor src, uint16_t dst) {
1722    SkASSERT(require_255(src));
1723    unsigned r = SkFastMin32(SkPacked32ToR16(src), SkGetPackedR16(dst));
1724    unsigned g = SkFastMin32(SkPacked32ToG16(src), SkGetPackedG16(dst));
1725    unsigned b = SkFastMin32(SkPacked32ToB16(src), SkGetPackedB16(dst));
1726    return SkPackRGB16(r, g, b);
1727}
1728
1729static uint16_t lighten_modeproc16_0(SkPMColor src, uint16_t dst) {
1730    SkASSERT(require_0(src));
1731    return dst;
1732}
1733
1734static uint16_t lighten_modeproc16_255(SkPMColor src, uint16_t dst) {
1735    SkASSERT(require_255(src));
1736    unsigned r = SkMax32(SkPacked32ToR16(src), SkGetPackedR16(dst));
1737    unsigned g = SkMax32(SkPacked32ToG16(src), SkGetPackedG16(dst));
1738    unsigned b = SkMax32(SkPacked32ToB16(src), SkGetPackedB16(dst));
1739    return SkPackRGB16(r, g, b);
1740}
1741
1742struct Proc16Rec {
1743    SkXfermodeProc16    fProc16_0;
1744    SkXfermodeProc16    fProc16_255;
1745    SkXfermodeProc16    fProc16_General;
1746};
1747
1748static const Proc16Rec gModeProcs16[] = {
1749    { NULL,                 NULL,                   NULL            }, // CLEAR
1750    { NULL,                 src_modeproc16_255,     NULL            },
1751    { dst_modeproc16,       dst_modeproc16,         dst_modeproc16  },
1752    { srcover_modeproc16_0, srcover_modeproc16_255, NULL            },
1753    { dstover_modeproc16_0, dstover_modeproc16_255, NULL            },
1754    { NULL,                 srcin_modeproc16_255,   NULL            },
1755    { NULL,                 dstin_modeproc16_255,   NULL            },
1756    { NULL,                 NULL,                   NULL            },// SRC_OUT
1757    { dstout_modeproc16_0,  NULL,                   NULL            },
1758    { srcatop_modeproc16_0, srcatop_modeproc16_255, srcatop_modeproc16  },
1759    { NULL,                 dstatop_modeproc16_255, NULL            },
1760    { NULL,                 NULL,                   NULL            }, // XOR
1761
1762    { NULL,                 NULL,                   NULL            }, // plus
1763    { NULL,                 NULL,                   NULL            }, // modulate
1764    { NULL,                 NULL,                   NULL            }, // screen
1765    { NULL,                 NULL,                   NULL            }, // overlay
1766    { darken_modeproc16_0,  darken_modeproc16_255,  NULL            }, // darken
1767    { lighten_modeproc16_0, lighten_modeproc16_255, NULL            }, // lighten
1768    { NULL,                 NULL,                   NULL            }, // colordodge
1769    { NULL,                 NULL,                   NULL            }, // colorburn
1770    { NULL,                 NULL,                   NULL            }, // hardlight
1771    { NULL,                 NULL,                   NULL            }, // softlight
1772    { NULL,                 NULL,                   NULL            }, // difference
1773    { NULL,                 NULL,                   NULL            }, // exclusion
1774    { NULL,                 NULL,                   NULL            }, // multiply
1775    { NULL,                 NULL,                   NULL            }, // hue
1776    { NULL,                 NULL,                   NULL            }, // saturation
1777    { NULL,                 NULL,                   NULL            }, // color
1778    { NULL,                 NULL,                   NULL            }, // luminosity
1779};
1780
1781SkXfermodeProc16 SkXfermode::GetProc16(Mode mode, SkColor srcColor) {
1782    SkXfermodeProc16  proc16 = NULL;
1783    if ((unsigned)mode < kModeCount) {
1784        const Proc16Rec& rec = gModeProcs16[mode];
1785        unsigned a = SkColorGetA(srcColor);
1786
1787        if (0 == a) {
1788            proc16 = rec.fProc16_0;
1789        } else if (255 == a) {
1790            proc16 = rec.fProc16_255;
1791        } else {
1792            proc16 = rec.fProc16_General;
1793        }
1794    }
1795    return proc16;
1796}
1797
1798SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkXfermode)
1799    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkProcCoeffXfermode)
1800    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkClearXfermode)
1801    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSrcXfermode)
1802    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDstInXfermode)
1803    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDstOutXfermode)
1804SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
1805