SkXfermode.cpp revision d7aaf6034e519ea9b70649c1d344f2f24de90ccb
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,      CANNOT_USE_COEFF,       CANNOT_USE_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 kDarken_Mode Xfermode. It requires access to the dst pixel color
954 * in the shader. TODO: Make this work for all non-Coeff SkXfermode::Mode values.
955 */
956class DarkenEffect : public GrEffect {
957public:
958    static GrEffectRef* Create() {
959        static AutoEffectUnref gEffect(SkNEW(DarkenEffect));
960        return CreateEffectRef(gEffect);
961    }
962
963    virtual void getConstantColorComponents(GrColor* color,
964                                            uint32_t* validFlags) const SK_OVERRIDE {
965        *validFlags = 0;
966    }
967
968    virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE {
969        return GrTBackendEffectFactory<DarkenEffect>::getInstance();
970    }
971
972    static const char* Name() { return "XfermodeDarken"; }
973
974    class GLEffect : public GrGLEffect {
975    public:
976        GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&)
977            : GrGLEffect(factory ) {
978        }
979        virtual void emitCode(GrGLShaderBuilder* builder,
980                              const GrDrawEffect& drawEffect,
981                              EffectKey key,
982                              const char* outputColor,
983                              const char* inputColor,
984                              const TextureSamplerArray& samplers) SK_OVERRIDE {
985            const char* dstColorName = builder->dstColor();
986            GrAssert(NULL != dstColorName);
987            if (NULL == inputColor) {
988                // the input color is solid white
989                builder->fsCodeAppendf("\t\t%s.a = 1.0;\n", outputColor);
990                builder->fsCodeAppendf("\t\t%s.rgb = vec3(1.0, 1.0, 1.0) - %s.aaa + %s.rgb;\n",
991                                       outputColor, dstColorName, dstColorName);
992            } else {
993                builder->fsCodeAppendf("\t\t%s.a = 1.0 - (1.0 - %s.a) * (1.0 - %s.a);\n",
994                                       outputColor, dstColorName, inputColor);
995                builder->fsCodeAppendf("\t\t%s.rgb = min((1.0 - %s.a) * %s.rgb + %s.rgb,"
996                                                       " (1.0 - %s.a) * %s.rgb + %s.rgb);\n",
997                                       outputColor,
998                                       inputColor, dstColorName, inputColor,
999                                       dstColorName, inputColor, dstColorName);
1000            }
1001        }
1002
1003        static inline EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&) { return 0; }
1004
1005        virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE {}
1006
1007    private:
1008        typedef GrGLEffect INHERITED;
1009    };
1010
1011    GR_DECLARE_EFFECT_TEST;
1012
1013private:
1014    DarkenEffect() { this->setWillReadDst(); }
1015    virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE { return true; }
1016
1017    typedef GrEffect INHERITED;
1018};
1019
1020GR_DEFINE_EFFECT_TEST(DarkenEffect);
1021GrEffectRef* DarkenEffect::TestCreate(SkMWCRandom*,
1022                                      GrContext*,
1023                                      const GrDrawTargetCaps&,
1024                                      GrTexture*[]) {
1025    static AutoEffectUnref gEffect(SkNEW(DarkenEffect));
1026    return CreateEffectRef(gEffect);
1027}
1028
1029#endif
1030
1031///////////////////////////////////////////////////////////////////////////////
1032///////////////////////////////////////////////////////////////////////////////
1033
1034class SkProcCoeffXfermode : public SkProcXfermode {
1035public:
1036    SkProcCoeffXfermode(const ProcCoeff& rec, Mode mode)
1037            : INHERITED(rec.fProc) {
1038        fMode = mode;
1039        // these may be valid, or may be CANNOT_USE_COEFF
1040        fSrcCoeff = rec.fSC;
1041        fDstCoeff = rec.fDC;
1042    }
1043
1044    virtual bool asMode(Mode* mode) const SK_OVERRIDE {
1045        if (mode) {
1046            *mode = fMode;
1047        }
1048        return true;
1049    }
1050
1051    virtual bool asCoeff(Coeff* sc, Coeff* dc) const SK_OVERRIDE {
1052        if (CANNOT_USE_COEFF == fSrcCoeff) {
1053            return false;
1054        }
1055
1056        if (sc) {
1057            *sc = fSrcCoeff;
1058        }
1059        if (dc) {
1060            *dc = fDstCoeff;
1061        }
1062        return true;
1063    }
1064
1065#if SK_SUPPORT_GPU
1066    virtual bool asNewEffectOrCoeff(GrContext*,
1067                                    GrEffectRef** effect,
1068                                    Coeff* src,
1069                                    Coeff* dst) const SK_OVERRIDE {
1070        if (this->asCoeff(src, dst)) {
1071            return true;
1072        }
1073        if (kDarken_Mode == fMode) {
1074            if (NULL != effect) {
1075                *effect = DarkenEffect::Create();
1076            }
1077            return true;
1078        }
1079        return false;
1080    }
1081#endif
1082
1083    SK_DEVELOPER_TO_STRING()
1084    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkProcCoeffXfermode)
1085
1086protected:
1087    SkProcCoeffXfermode(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
1088        fMode = (SkXfermode::Mode)buffer.read32();
1089
1090        const ProcCoeff& rec = gProcCoeffs[fMode];
1091        // these may be valid, or may be CANNOT_USE_COEFF
1092        fSrcCoeff = rec.fSC;
1093        fDstCoeff = rec.fDC;
1094        // now update our function-ptr in the super class
1095        this->INHERITED::setProc(rec.fProc);
1096    }
1097
1098    virtual void flatten(SkFlattenableWriteBuffer& buffer) const SK_OVERRIDE {
1099        this->INHERITED::flatten(buffer);
1100        buffer.write32(fMode);
1101    }
1102
1103private:
1104    Mode    fMode;
1105    Coeff   fSrcCoeff, fDstCoeff;
1106
1107    typedef SkProcXfermode INHERITED;
1108};
1109
1110const char* SkXfermode::ModeName(Mode mode) {
1111    SkASSERT((unsigned) mode <= (unsigned)kLastMode);
1112    const char* gModeStrings[] = {
1113        "Clear", "Src", "Dst", "SrcOver", "DstOver", "SrcIn", "DstIn",
1114        "SrcOut", "DstOut", "SrcATop", "DstATop", "Xor", "Plus",
1115        "Modulate", "Screen", "Overlay", "Darken", "Lighten", "ColorDodge",
1116        "ColorBurn", "HardLight", "SoftLight", "Difference", "Exclusion",
1117        "Multiply", "Hue", "Saturation", "Color",  "Luminosity"
1118    };
1119    return gModeStrings[mode];
1120    SK_COMPILE_ASSERT(SK_ARRAY_COUNT(gModeStrings) == kLastMode + 1, mode_count);
1121}
1122
1123#ifdef SK_DEVELOPER
1124void SkProcCoeffXfermode::toString(SkString* str) const {
1125    str->append("SkProcCoeffXfermode: ");
1126
1127    str->append("mode: ");
1128    str->append(ModeName(fMode));
1129
1130    static const char* gCoeffStrings[kCoeffCount] = {
1131        "Zero", "One", "SC", "ISC", "DC", "IDC", "SA", "ISA", "DA", "IDA"
1132    };
1133
1134    str->append(" src: ");
1135    if (CANNOT_USE_COEFF == fSrcCoeff) {
1136        str->append("can't use");
1137    } else {
1138        str->append(gCoeffStrings[fSrcCoeff]);
1139    }
1140
1141    str->append(" dst: ");
1142    if (CANNOT_USE_COEFF == fDstCoeff) {
1143        str->append("can't use");
1144    } else {
1145        str->append(gCoeffStrings[fDstCoeff]);
1146    }
1147}
1148#endif
1149
1150///////////////////////////////////////////////////////////////////////////////
1151
1152class SkClearXfermode : public SkProcCoeffXfermode {
1153public:
1154    SkClearXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kClear_Mode) {}
1155
1156    virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
1157    virtual void xferA8(SkAlpha*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
1158
1159    SK_DEVELOPER_TO_STRING()
1160    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkClearXfermode)
1161
1162private:
1163    SkClearXfermode(SkFlattenableReadBuffer& buffer)
1164        : SkProcCoeffXfermode(buffer) {}
1165
1166    typedef SkProcCoeffXfermode INHERITED;
1167};
1168
1169void SkClearXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
1170                             const SkPMColor* SK_RESTRICT, int count,
1171                             const SkAlpha* SK_RESTRICT aa) const {
1172    SkASSERT(dst && count >= 0);
1173
1174    if (NULL == aa) {
1175        memset(dst, 0, count << 2);
1176    } else {
1177        for (int i = count - 1; i >= 0; --i) {
1178            unsigned a = aa[i];
1179            if (0xFF == a) {
1180                dst[i] = 0;
1181            } else if (a != 0) {
1182                dst[i] = SkAlphaMulQ(dst[i], SkAlpha255To256(255 - a));
1183            }
1184        }
1185    }
1186}
1187void SkClearXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
1188                             const SkPMColor* SK_RESTRICT, int count,
1189                             const SkAlpha* SK_RESTRICT aa) const {
1190    SkASSERT(dst && count >= 0);
1191
1192    if (NULL == aa) {
1193        memset(dst, 0, count);
1194    } else {
1195        for (int i = count - 1; i >= 0; --i) {
1196            unsigned a = aa[i];
1197            if (0xFF == a) {
1198                dst[i] = 0;
1199            } else if (0 != a) {
1200                dst[i] = SkAlphaMulAlpha(dst[i], 255 - a);
1201            }
1202        }
1203    }
1204}
1205
1206#ifdef SK_DEVELOPER
1207void SkClearXfermode::toString(SkString* str) const {
1208    this->INHERITED::toString(str);
1209}
1210#endif
1211
1212///////////////////////////////////////////////////////////////////////////////
1213
1214class SkSrcXfermode : public SkProcCoeffXfermode {
1215public:
1216    SkSrcXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kSrc_Mode) {}
1217
1218    virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
1219    virtual void xferA8(SkAlpha*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
1220
1221    SK_DEVELOPER_TO_STRING()
1222    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkSrcXfermode)
1223
1224private:
1225    SkSrcXfermode(SkFlattenableReadBuffer& buffer)
1226        : SkProcCoeffXfermode(buffer) {}
1227
1228    typedef SkProcCoeffXfermode INHERITED;
1229};
1230
1231void SkSrcXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
1232                           const SkPMColor* SK_RESTRICT src, int count,
1233                           const SkAlpha* SK_RESTRICT aa) const {
1234    SkASSERT(dst && src && count >= 0);
1235
1236    if (NULL == aa) {
1237        memcpy(dst, src, count << 2);
1238    } else {
1239        for (int i = count - 1; i >= 0; --i) {
1240            unsigned a = aa[i];
1241            if (a == 0xFF) {
1242                dst[i] = src[i];
1243            } else if (a != 0) {
1244                dst[i] = SkFourByteInterp(src[i], dst[i], a);
1245            }
1246        }
1247    }
1248}
1249
1250void SkSrcXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
1251                           const SkPMColor* SK_RESTRICT src, int count,
1252                           const SkAlpha* SK_RESTRICT aa) const {
1253    SkASSERT(dst && src && count >= 0);
1254
1255    if (NULL == aa) {
1256        for (int i = count - 1; i >= 0; --i) {
1257            dst[i] = SkToU8(SkGetPackedA32(src[i]));
1258        }
1259    } else {
1260        for (int i = count - 1; i >= 0; --i) {
1261            unsigned a = aa[i];
1262            if (0 != a) {
1263                unsigned srcA = SkGetPackedA32(src[i]);
1264                if (a == 0xFF) {
1265                    dst[i] = SkToU8(srcA);
1266                } else {
1267                    dst[i] = SkToU8(SkAlphaBlend(srcA, dst[i], a));
1268                }
1269            }
1270        }
1271    }
1272}
1273#ifdef SK_DEVELOPER
1274void SkSrcXfermode::toString(SkString* str) const {
1275    this->INHERITED::toString(str);
1276}
1277#endif
1278
1279///////////////////////////////////////////////////////////////////////////////
1280
1281class SkDstInXfermode : public SkProcCoeffXfermode {
1282public:
1283    SkDstInXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstIn_Mode) {}
1284
1285    virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
1286
1287    SK_DEVELOPER_TO_STRING()
1288    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDstInXfermode)
1289
1290private:
1291    SkDstInXfermode(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {}
1292
1293    typedef SkProcCoeffXfermode INHERITED;
1294};
1295
1296void SkDstInXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
1297                             const SkPMColor* SK_RESTRICT src, int count,
1298                             const SkAlpha* SK_RESTRICT aa) const {
1299    SkASSERT(dst && src);
1300
1301    if (count <= 0) {
1302        return;
1303    }
1304    if (NULL != aa) {
1305        return this->INHERITED::xfer32(dst, src, count, aa);
1306    }
1307
1308    do {
1309        unsigned a = SkGetPackedA32(*src);
1310        *dst = SkAlphaMulQ(*dst, SkAlpha255To256(a));
1311        dst++;
1312        src++;
1313    } while (--count != 0);
1314}
1315
1316#ifdef SK_DEVELOPER
1317void SkDstInXfermode::toString(SkString* str) const {
1318    this->INHERITED::toString(str);
1319}
1320#endif
1321
1322///////////////////////////////////////////////////////////////////////////////
1323
1324class SkDstOutXfermode : public SkProcCoeffXfermode {
1325public:
1326    SkDstOutXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstOut_Mode) {}
1327
1328    virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
1329
1330    SK_DEVELOPER_TO_STRING()
1331    SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDstOutXfermode)
1332
1333private:
1334    SkDstOutXfermode(SkFlattenableReadBuffer& buffer)
1335        : INHERITED(buffer) {}
1336
1337    typedef SkProcCoeffXfermode INHERITED;
1338};
1339
1340void SkDstOutXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
1341                              const SkPMColor* SK_RESTRICT src, int count,
1342                              const SkAlpha* SK_RESTRICT aa) const {
1343    SkASSERT(dst && src);
1344
1345    if (count <= 0) {
1346        return;
1347    }
1348    if (NULL != aa) {
1349        return this->INHERITED::xfer32(dst, src, count, aa);
1350    }
1351
1352    do {
1353        unsigned a = SkGetPackedA32(*src);
1354        *dst = SkAlphaMulQ(*dst, SkAlpha255To256(255 - a));
1355        dst++;
1356        src++;
1357    } while (--count != 0);
1358}
1359
1360#ifdef SK_DEVELOPER
1361void SkDstOutXfermode::toString(SkString* str) const {
1362    this->INHERITED::toString(str);
1363}
1364#endif
1365
1366///////////////////////////////////////////////////////////////////////////////
1367
1368SkXfermode* SkXfermode::Create(Mode mode) {
1369    SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount);
1370    SkASSERT((unsigned)mode < kModeCount);
1371
1372    const ProcCoeff& rec = gProcCoeffs[mode];
1373
1374    switch (mode) {
1375        case kClear_Mode:
1376            return SkNEW_ARGS(SkClearXfermode, (rec));
1377        case kSrc_Mode:
1378            return SkNEW_ARGS(SkSrcXfermode, (rec));
1379        case kSrcOver_Mode:
1380            return NULL;
1381        case kDstIn_Mode:
1382            return SkNEW_ARGS(SkDstInXfermode, (rec));
1383        case kDstOut_Mode:
1384            return SkNEW_ARGS(SkDstOutXfermode, (rec));
1385        default:
1386            return SkNEW_ARGS(SkProcCoeffXfermode, (rec, mode));
1387    }
1388}
1389
1390SkXfermodeProc SkXfermode::GetProc(Mode mode) {
1391    SkXfermodeProc  proc = NULL;
1392    if ((unsigned)mode < kModeCount) {
1393        proc = gProcCoeffs[mode].fProc;
1394    }
1395    return proc;
1396}
1397
1398bool SkXfermode::ModeAsCoeff(Mode mode, Coeff* src, Coeff* dst) {
1399    SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount);
1400
1401    if ((unsigned)mode >= (unsigned)kModeCount) {
1402        // illegal mode parameter
1403        return false;
1404    }
1405
1406    const ProcCoeff& rec = gProcCoeffs[mode];
1407
1408    if (CANNOT_USE_COEFF == rec.fSC) {
1409        return false;
1410    }
1411
1412    SkASSERT(CANNOT_USE_COEFF != rec.fDC);
1413    if (src) {
1414        *src = rec.fSC;
1415    }
1416    if (dst) {
1417        *dst = rec.fDC;
1418    }
1419    return true;
1420}
1421
1422bool SkXfermode::AsMode(const SkXfermode* xfer, Mode* mode) {
1423    if (NULL == xfer) {
1424        if (mode) {
1425            *mode = kSrcOver_Mode;
1426        }
1427        return true;
1428    }
1429    return xfer->asMode(mode);
1430}
1431
1432bool SkXfermode::AsCoeff(const SkXfermode* xfer, Coeff* src, Coeff* dst) {
1433    if (NULL == xfer) {
1434        return ModeAsCoeff(kSrcOver_Mode, src, dst);
1435    }
1436    return xfer->asCoeff(src, dst);
1437}
1438
1439bool SkXfermode::IsMode(const SkXfermode* xfer, Mode mode) {
1440    // if xfer==null then the mode is srcover
1441    Mode m = kSrcOver_Mode;
1442    if (xfer && !xfer->asMode(&m)) {
1443        return false;
1444    }
1445    return mode == m;
1446}
1447
1448///////////////////////////////////////////////////////////////////////////////
1449//////////// 16bit xfermode procs
1450
1451#ifdef SK_DEBUG
1452static bool require_255(SkPMColor src) { return SkGetPackedA32(src) == 0xFF; }
1453static bool require_0(SkPMColor src) { return SkGetPackedA32(src) == 0; }
1454#endif
1455
1456static uint16_t src_modeproc16_255(SkPMColor src, uint16_t dst) {
1457    SkASSERT(require_255(src));
1458    return SkPixel32ToPixel16(src);
1459}
1460
1461static uint16_t dst_modeproc16(SkPMColor src, uint16_t dst) {
1462    return dst;
1463}
1464
1465static uint16_t srcover_modeproc16_0(SkPMColor src, uint16_t dst) {
1466    SkASSERT(require_0(src));
1467    return dst;
1468}
1469
1470static uint16_t srcover_modeproc16_255(SkPMColor src, uint16_t dst) {
1471    SkASSERT(require_255(src));
1472    return SkPixel32ToPixel16(src);
1473}
1474
1475static uint16_t dstover_modeproc16_0(SkPMColor src, uint16_t dst) {
1476    SkASSERT(require_0(src));
1477    return dst;
1478}
1479
1480static uint16_t dstover_modeproc16_255(SkPMColor src, uint16_t dst) {
1481    SkASSERT(require_255(src));
1482    return dst;
1483}
1484
1485static uint16_t srcin_modeproc16_255(SkPMColor src, uint16_t dst) {
1486    SkASSERT(require_255(src));
1487    return SkPixel32ToPixel16(src);
1488}
1489
1490static uint16_t dstin_modeproc16_255(SkPMColor src, uint16_t dst) {
1491    SkASSERT(require_255(src));
1492    return dst;
1493}
1494
1495static uint16_t dstout_modeproc16_0(SkPMColor src, uint16_t dst) {
1496    SkASSERT(require_0(src));
1497    return dst;
1498}
1499
1500static uint16_t srcatop_modeproc16(SkPMColor src, uint16_t dst) {
1501    unsigned isa = 255 - SkGetPackedA32(src);
1502
1503    return SkPackRGB16(
1504           SkPacked32ToR16(src) + SkAlphaMulAlpha(SkGetPackedR16(dst), isa),
1505           SkPacked32ToG16(src) + SkAlphaMulAlpha(SkGetPackedG16(dst), isa),
1506           SkPacked32ToB16(src) + SkAlphaMulAlpha(SkGetPackedB16(dst), isa));
1507}
1508
1509static uint16_t srcatop_modeproc16_0(SkPMColor src, uint16_t dst) {
1510    SkASSERT(require_0(src));
1511    return dst;
1512}
1513
1514static uint16_t srcatop_modeproc16_255(SkPMColor src, uint16_t dst) {
1515    SkASSERT(require_255(src));
1516    return SkPixel32ToPixel16(src);
1517}
1518
1519static uint16_t dstatop_modeproc16_255(SkPMColor src, uint16_t dst) {
1520    SkASSERT(require_255(src));
1521    return dst;
1522}
1523
1524/*********
1525    darken and lighten boil down to this.
1526
1527    darken  = (1 - Sa) * Dc + min(Sc, Dc)
1528    lighten = (1 - Sa) * Dc + max(Sc, Dc)
1529
1530    if (Sa == 0) these become
1531        darken  = Dc + min(0, Dc) = 0
1532        lighten = Dc + max(0, Dc) = Dc
1533
1534    if (Sa == 1) these become
1535        darken  = min(Sc, Dc)
1536        lighten = max(Sc, Dc)
1537*/
1538
1539static uint16_t darken_modeproc16_0(SkPMColor src, uint16_t dst) {
1540    SkASSERT(require_0(src));
1541    return 0;
1542}
1543
1544static uint16_t darken_modeproc16_255(SkPMColor src, uint16_t dst) {
1545    SkASSERT(require_255(src));
1546    unsigned r = SkFastMin32(SkPacked32ToR16(src), SkGetPackedR16(dst));
1547    unsigned g = SkFastMin32(SkPacked32ToG16(src), SkGetPackedG16(dst));
1548    unsigned b = SkFastMin32(SkPacked32ToB16(src), SkGetPackedB16(dst));
1549    return SkPackRGB16(r, g, b);
1550}
1551
1552static uint16_t lighten_modeproc16_0(SkPMColor src, uint16_t dst) {
1553    SkASSERT(require_0(src));
1554    return dst;
1555}
1556
1557static uint16_t lighten_modeproc16_255(SkPMColor src, uint16_t dst) {
1558    SkASSERT(require_255(src));
1559    unsigned r = SkMax32(SkPacked32ToR16(src), SkGetPackedR16(dst));
1560    unsigned g = SkMax32(SkPacked32ToG16(src), SkGetPackedG16(dst));
1561    unsigned b = SkMax32(SkPacked32ToB16(src), SkGetPackedB16(dst));
1562    return SkPackRGB16(r, g, b);
1563}
1564
1565struct Proc16Rec {
1566    SkXfermodeProc16    fProc16_0;
1567    SkXfermodeProc16    fProc16_255;
1568    SkXfermodeProc16    fProc16_General;
1569};
1570
1571static const Proc16Rec gModeProcs16[] = {
1572    { NULL,                 NULL,                   NULL            }, // CLEAR
1573    { NULL,                 src_modeproc16_255,     NULL            },
1574    { dst_modeproc16,       dst_modeproc16,         dst_modeproc16  },
1575    { srcover_modeproc16_0, srcover_modeproc16_255, NULL            },
1576    { dstover_modeproc16_0, dstover_modeproc16_255, NULL            },
1577    { NULL,                 srcin_modeproc16_255,   NULL            },
1578    { NULL,                 dstin_modeproc16_255,   NULL            },
1579    { NULL,                 NULL,                   NULL            },// SRC_OUT
1580    { dstout_modeproc16_0,  NULL,                   NULL            },
1581    { srcatop_modeproc16_0, srcatop_modeproc16_255, srcatop_modeproc16  },
1582    { NULL,                 dstatop_modeproc16_255, NULL            },
1583    { NULL,                 NULL,                   NULL            }, // XOR
1584
1585    { NULL,                 NULL,                   NULL            }, // plus
1586    { NULL,                 NULL,                   NULL            }, // modulate
1587    { NULL,                 NULL,                   NULL            }, // screen
1588    { NULL,                 NULL,                   NULL            }, // overlay
1589    { darken_modeproc16_0,  darken_modeproc16_255,  NULL            }, // darken
1590    { lighten_modeproc16_0, lighten_modeproc16_255, NULL            }, // lighten
1591    { NULL,                 NULL,                   NULL            }, // colordodge
1592    { NULL,                 NULL,                   NULL            }, // colorburn
1593    { NULL,                 NULL,                   NULL            }, // hardlight
1594    { NULL,                 NULL,                   NULL            }, // softlight
1595    { NULL,                 NULL,                   NULL            }, // difference
1596    { NULL,                 NULL,                   NULL            }, // exclusion
1597    { NULL,                 NULL,                   NULL            }, // multiply
1598    { NULL,                 NULL,                   NULL            }, // hue
1599    { NULL,                 NULL,                   NULL            }, // saturation
1600    { NULL,                 NULL,                   NULL            }, // color
1601    { NULL,                 NULL,                   NULL            }, // luminosity
1602};
1603
1604SkXfermodeProc16 SkXfermode::GetProc16(Mode mode, SkColor srcColor) {
1605    SkXfermodeProc16  proc16 = NULL;
1606    if ((unsigned)mode < kModeCount) {
1607        const Proc16Rec& rec = gModeProcs16[mode];
1608        unsigned a = SkColorGetA(srcColor);
1609
1610        if (0 == a) {
1611            proc16 = rec.fProc16_0;
1612        } else if (255 == a) {
1613            proc16 = rec.fProc16_255;
1614        } else {
1615            proc16 = rec.fProc16_General;
1616        }
1617    }
1618    return proc16;
1619}
1620
1621SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkXfermode)
1622    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkProcCoeffXfermode)
1623    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkClearXfermode)
1624    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSrcXfermode)
1625    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDstInXfermode)
1626    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDstOutXfermode)
1627SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
1628