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