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