SkXfermode.cpp revision 3006b2e013f29f8b00f6afabbe5b2a8737840bc6
1
2/*
3 * Copyright 2006 The Android Open Source Project
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
9#include "SkXfermode.h"
10#include "SkXfermode_opts_SSE2.h"
11#include "SkXfermode_proccoeff.h"
12#include "SkColorPriv.h"
13#include "SkLazyPtr.h"
14#include "SkMathPriv.h"
15#include "SkPMFloat.h"
16#include "SkReadBuffer.h"
17#include "SkString.h"
18#include "SkUtilsArm.h"
19#include "SkWriteBuffer.h"
20
21#ifndef SK_SUPPORT_LEGACY_SCALAR_XFERMODES
22#if SK_CPU_SSE_LEVEL >= SK_CPU_SSE_LEVEL_SSE2
23    /*
24     * To be conservative, we only enable the new code path (using SkPMFloat) when we
25     * "know" we're faster, which at the moment is only when we have SSE2 or better.
26     */
27#else
28    #define SK_SUPPORT_LEGACY_SCALAR_XFERMODES
29#endif
30#endif
31
32#if !SK_ARM_NEON_IS_NONE
33#include "SkXfermode_opts_arm_neon.h"
34#endif
35
36#define SkAlphaMulAlpha(a, b)   SkMulDiv255Round(a, b)
37
38static inline unsigned saturated_add(unsigned a, unsigned b) {
39    SkASSERT(a <= 255);
40    SkASSERT(b <= 255);
41    unsigned sum = a + b;
42    if (sum > 255) {
43        sum = 255;
44    }
45    return sum;
46}
47
48static inline int clamp_signed_byte(int n) {
49    if (n < 0) {
50        n = 0;
51    } else if (n > 255) {
52        n = 255;
53    }
54    return n;
55}
56
57static inline int clamp_div255round(int prod) {
58    if (prod <= 0) {
59        return 0;
60    } else if (prod >= 255*255) {
61        return 255;
62    } else {
63        return SkDiv255Round(prod);
64    }
65}
66
67///////////////////////////////////////////////////////////////////////////////
68
69//  kClear_Mode,    //!< [0, 0]
70static SkPMColor clear_modeproc(SkPMColor src, SkPMColor dst) {
71    return 0;
72}
73
74//  kSrc_Mode,      //!< [Sa, Sc]
75static SkPMColor src_modeproc(SkPMColor src, SkPMColor dst) {
76    return src;
77}
78
79//  kDst_Mode,      //!< [Da, Dc]
80static SkPMColor dst_modeproc(SkPMColor src, SkPMColor dst) {
81    return dst;
82}
83
84//  kSrcOver_Mode,  //!< [Sa + Da - Sa*Da, Sc + (1 - Sa)*Dc]
85static SkPMColor srcover_modeproc(SkPMColor src, SkPMColor dst) {
86#if 0
87    // this is the old, more-correct way, but it doesn't guarantee that dst==255
88    // will always stay opaque
89    return src + SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src)));
90#else
91    // this is slightly faster, but more importantly guarantees that dst==255
92    // will always stay opaque
93    return src + SkAlphaMulQ(dst, 256 - SkGetPackedA32(src));
94#endif
95}
96
97//  kDstOver_Mode,  //!< [Sa + Da - Sa*Da, Dc + (1 - Da)*Sc]
98static SkPMColor dstover_modeproc(SkPMColor src, SkPMColor dst) {
99    // this is the reverse of srcover, just flipping src and dst
100    // see srcover's comment about the 256 for opaqueness guarantees
101    return dst + SkAlphaMulQ(src, 256 - SkGetPackedA32(dst));
102}
103
104//  kSrcIn_Mode,    //!< [Sa * Da, Sc * Da]
105static SkPMColor srcin_modeproc(SkPMColor src, SkPMColor dst) {
106    return SkAlphaMulQ(src, SkAlpha255To256(SkGetPackedA32(dst)));
107}
108
109//  kDstIn_Mode,    //!< [Sa * Da, Sa * Dc]
110static SkPMColor dstin_modeproc(SkPMColor src, SkPMColor dst) {
111    return SkAlphaMulQ(dst, SkAlpha255To256(SkGetPackedA32(src)));
112}
113
114//  kSrcOut_Mode,   //!< [Sa * (1 - Da), Sc * (1 - Da)]
115static SkPMColor srcout_modeproc(SkPMColor src, SkPMColor dst) {
116    return SkAlphaMulQ(src, SkAlpha255To256(255 - SkGetPackedA32(dst)));
117}
118
119//  kDstOut_Mode,   //!< [Da * (1 - Sa), Dc * (1 - Sa)]
120static SkPMColor dstout_modeproc(SkPMColor src, SkPMColor dst) {
121    return SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src)));
122}
123
124//  kSrcATop_Mode,  //!< [Da, Sc * Da + (1 - Sa) * Dc]
125static SkPMColor srcatop_modeproc(SkPMColor src, SkPMColor dst) {
126    unsigned sa = SkGetPackedA32(src);
127    unsigned da = SkGetPackedA32(dst);
128    unsigned isa = 255 - sa;
129
130    return SkPackARGB32(da,
131                        SkAlphaMulAlpha(da, SkGetPackedR32(src)) +
132                            SkAlphaMulAlpha(isa, SkGetPackedR32(dst)),
133                        SkAlphaMulAlpha(da, SkGetPackedG32(src)) +
134                            SkAlphaMulAlpha(isa, SkGetPackedG32(dst)),
135                        SkAlphaMulAlpha(da, SkGetPackedB32(src)) +
136                            SkAlphaMulAlpha(isa, SkGetPackedB32(dst)));
137}
138
139//  kDstATop_Mode,  //!< [Sa, Sa * Dc + Sc * (1 - Da)]
140static SkPMColor dstatop_modeproc(SkPMColor src, SkPMColor dst) {
141    unsigned sa = SkGetPackedA32(src);
142    unsigned da = SkGetPackedA32(dst);
143    unsigned ida = 255 - da;
144
145    return SkPackARGB32(sa,
146                        SkAlphaMulAlpha(ida, SkGetPackedR32(src)) +
147                            SkAlphaMulAlpha(sa, SkGetPackedR32(dst)),
148                        SkAlphaMulAlpha(ida, SkGetPackedG32(src)) +
149                            SkAlphaMulAlpha(sa, SkGetPackedG32(dst)),
150                        SkAlphaMulAlpha(ida, SkGetPackedB32(src)) +
151                            SkAlphaMulAlpha(sa, SkGetPackedB32(dst)));
152}
153
154//  kXor_Mode   [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc]
155static SkPMColor xor_modeproc(SkPMColor src, SkPMColor dst) {
156    unsigned sa = SkGetPackedA32(src);
157    unsigned da = SkGetPackedA32(dst);
158    unsigned isa = 255 - sa;
159    unsigned ida = 255 - da;
160
161    return SkPackARGB32(sa + da - (SkAlphaMulAlpha(sa, da) << 1),
162                        SkAlphaMulAlpha(ida, SkGetPackedR32(src)) +
163                            SkAlphaMulAlpha(isa, SkGetPackedR32(dst)),
164                        SkAlphaMulAlpha(ida, SkGetPackedG32(src)) +
165                            SkAlphaMulAlpha(isa, SkGetPackedG32(dst)),
166                        SkAlphaMulAlpha(ida, SkGetPackedB32(src)) +
167                            SkAlphaMulAlpha(isa, SkGetPackedB32(dst)));
168}
169
170///////////////////////////////////////////////////////////////////////////////
171
172// kPlus_Mode
173static SkPMColor plus_modeproc(SkPMColor src, SkPMColor dst) {
174    unsigned b = saturated_add(SkGetPackedB32(src), SkGetPackedB32(dst));
175    unsigned g = saturated_add(SkGetPackedG32(src), SkGetPackedG32(dst));
176    unsigned r = saturated_add(SkGetPackedR32(src), SkGetPackedR32(dst));
177    unsigned a = saturated_add(SkGetPackedA32(src), SkGetPackedA32(dst));
178    return SkPackARGB32(a, r, g, b);
179}
180
181// kModulate_Mode
182static SkPMColor modulate_modeproc(SkPMColor src, SkPMColor dst) {
183    int a = SkAlphaMulAlpha(SkGetPackedA32(src), SkGetPackedA32(dst));
184    int r = SkAlphaMulAlpha(SkGetPackedR32(src), SkGetPackedR32(dst));
185    int g = SkAlphaMulAlpha(SkGetPackedG32(src), SkGetPackedG32(dst));
186    int b = SkAlphaMulAlpha(SkGetPackedB32(src), SkGetPackedB32(dst));
187    return SkPackARGB32(a, r, g, b);
188}
189
190static inline int srcover_byte(int a, int b) {
191    return a + b - SkAlphaMulAlpha(a, b);
192}
193
194// kMultiply_Mode
195// B(Cb, Cs) = Cb x Cs
196// multiply uses its own version of blendfunc_byte because sa and da are not needed
197static int blendfunc_multiply_byte(int sc, int dc, int sa, int da) {
198    return clamp_div255round(sc * (255 - da)  + dc * (255 - sa)  + sc * dc);
199}
200
201static SkPMColor multiply_modeproc(SkPMColor src, SkPMColor dst) {
202    int sa = SkGetPackedA32(src);
203    int da = SkGetPackedA32(dst);
204    int a = srcover_byte(sa, da);
205    int r = blendfunc_multiply_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
206    int g = blendfunc_multiply_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
207    int b = blendfunc_multiply_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
208    return SkPackARGB32(a, r, g, b);
209}
210
211// kScreen_Mode
212static SkPMColor screen_modeproc(SkPMColor src, SkPMColor dst) {
213    int a = srcover_byte(SkGetPackedA32(src), SkGetPackedA32(dst));
214    int r = srcover_byte(SkGetPackedR32(src), SkGetPackedR32(dst));
215    int g = srcover_byte(SkGetPackedG32(src), SkGetPackedG32(dst));
216    int b = srcover_byte(SkGetPackedB32(src), SkGetPackedB32(dst));
217    return SkPackARGB32(a, r, g, b);
218}
219
220// kOverlay_Mode
221static inline int overlay_byte(int sc, int dc, int sa, int da) {
222    int tmp = sc * (255 - da) + dc * (255 - sa);
223    int rc;
224    if (2 * dc <= da) {
225        rc = 2 * sc * dc;
226    } else {
227        rc = sa * da - 2 * (da - dc) * (sa - sc);
228    }
229    return clamp_div255round(rc + tmp);
230}
231static SkPMColor overlay_modeproc(SkPMColor src, SkPMColor dst) {
232    int sa = SkGetPackedA32(src);
233    int da = SkGetPackedA32(dst);
234    int a = srcover_byte(sa, da);
235    int r = overlay_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
236    int g = overlay_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
237    int b = overlay_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
238    return SkPackARGB32(a, r, g, b);
239}
240
241// kDarken_Mode
242static inline int darken_byte(int sc, int dc, int sa, int da) {
243    int sd = sc * da;
244    int ds = dc * sa;
245    if (sd < ds) {
246        // srcover
247        return sc + dc - SkDiv255Round(ds);
248    } else {
249        // dstover
250        return dc + sc - SkDiv255Round(sd);
251    }
252}
253static SkPMColor darken_modeproc(SkPMColor src, SkPMColor dst) {
254    int sa = SkGetPackedA32(src);
255    int da = SkGetPackedA32(dst);
256    int a = srcover_byte(sa, da);
257    int r = darken_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
258    int g = darken_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
259    int b = darken_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
260    return SkPackARGB32(a, r, g, b);
261}
262
263// kLighten_Mode
264static inline int lighten_byte(int sc, int dc, int sa, int da) {
265    int sd = sc * da;
266    int ds = dc * sa;
267    if (sd > ds) {
268        // srcover
269        return sc + dc - SkDiv255Round(ds);
270    } else {
271        // dstover
272        return dc + sc - SkDiv255Round(sd);
273    }
274}
275static SkPMColor lighten_modeproc(SkPMColor src, SkPMColor dst) {
276    int sa = SkGetPackedA32(src);
277    int da = SkGetPackedA32(dst);
278    int a = srcover_byte(sa, da);
279    int r = lighten_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
280    int g = lighten_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
281    int b = lighten_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
282    return SkPackARGB32(a, r, g, b);
283}
284
285// kColorDodge_Mode
286static inline int colordodge_byte(int sc, int dc, int sa, int da) {
287    int diff = sa - sc;
288    int rc;
289    if (0 == dc) {
290        return SkAlphaMulAlpha(sc, 255 - da);
291    } else if (0 == diff) {
292        rc = sa * da + sc * (255 - da) + dc * (255 - sa);
293    } else {
294        diff = dc * sa / diff;
295        rc = sa * ((da < diff) ? da : diff) + sc * (255 - da) + dc * (255 - sa);
296    }
297    return clamp_div255round(rc);
298}
299static SkPMColor colordodge_modeproc(SkPMColor src, SkPMColor dst) {
300    int sa = SkGetPackedA32(src);
301    int da = SkGetPackedA32(dst);
302    int a = srcover_byte(sa, da);
303    int r = colordodge_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
304    int g = colordodge_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
305    int b = colordodge_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
306    return SkPackARGB32(a, r, g, b);
307}
308
309// kColorBurn_Mode
310static inline int colorburn_byte(int sc, int dc, int sa, int da) {
311    int rc;
312    if (dc == da) {
313        rc = sa * da + sc * (255 - da) + dc * (255 - sa);
314    } else if (0 == sc) {
315        return SkAlphaMulAlpha(dc, 255 - sa);
316    } else {
317        int tmp = (da - dc) * sa / sc;
318        rc = sa * (da - ((da < tmp) ? da : tmp))
319            + sc * (255 - da) + dc * (255 - sa);
320    }
321    return clamp_div255round(rc);
322}
323static SkPMColor colorburn_modeproc(SkPMColor src, SkPMColor dst) {
324    int sa = SkGetPackedA32(src);
325    int da = SkGetPackedA32(dst);
326    int a = srcover_byte(sa, da);
327    int r = colorburn_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
328    int g = colorburn_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
329    int b = colorburn_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
330    return SkPackARGB32(a, r, g, b);
331}
332
333// kHardLight_Mode
334static inline int hardlight_byte(int sc, int dc, int sa, int da) {
335    int rc;
336    if (2 * sc <= sa) {
337        rc = 2 * sc * dc;
338    } else {
339        rc = sa * da - 2 * (da - dc) * (sa - sc);
340    }
341    return clamp_div255round(rc + sc * (255 - da) + dc * (255 - sa));
342}
343static SkPMColor hardlight_modeproc(SkPMColor src, SkPMColor dst) {
344    int sa = SkGetPackedA32(src);
345    int da = SkGetPackedA32(dst);
346    int a = srcover_byte(sa, da);
347    int r = hardlight_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
348    int g = hardlight_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
349    int b = hardlight_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
350    return SkPackARGB32(a, r, g, b);
351}
352
353// returns 255 * sqrt(n/255)
354static U8CPU sqrt_unit_byte(U8CPU n) {
355    return SkSqrtBits(n, 15+4);
356}
357
358// kSoftLight_Mode
359static inline int softlight_byte(int sc, int dc, int sa, int da) {
360    int m = da ? dc * 256 / da : 0;
361    int rc;
362    if (2 * sc <= sa) {
363        rc = dc * (sa + ((2 * sc - sa) * (256 - m) >> 8));
364    } else if (4 * dc <= da) {
365        int tmp = (4 * m * (4 * m + 256) * (m - 256) >> 16) + 7 * m;
366        rc = dc * sa + (da * (2 * sc - sa) * tmp >> 8);
367    } else {
368        int tmp = sqrt_unit_byte(m) - m;
369        rc = dc * sa + (da * (2 * sc - sa) * tmp >> 8);
370    }
371    return clamp_div255round(rc + sc * (255 - da) + dc * (255 - sa));
372}
373static SkPMColor softlight_modeproc(SkPMColor src, SkPMColor dst) {
374    int sa = SkGetPackedA32(src);
375    int da = SkGetPackedA32(dst);
376    int a = srcover_byte(sa, da);
377    int r = softlight_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
378    int g = softlight_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
379    int b = softlight_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
380    return SkPackARGB32(a, r, g, b);
381}
382
383// kDifference_Mode
384static inline int difference_byte(int sc, int dc, int sa, int da) {
385    int tmp = SkMin32(sc * da, dc * sa);
386    return clamp_signed_byte(sc + dc - 2 * SkDiv255Round(tmp));
387}
388static SkPMColor difference_modeproc(SkPMColor src, SkPMColor dst) {
389    int sa = SkGetPackedA32(src);
390    int da = SkGetPackedA32(dst);
391    int a = srcover_byte(sa, da);
392    int r = difference_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
393    int g = difference_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
394    int b = difference_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
395    return SkPackARGB32(a, r, g, b);
396}
397
398// kExclusion_Mode
399static inline int exclusion_byte(int sc, int dc, int, int) {
400    // this equations is wacky, wait for SVG to confirm it
401    //int r = sc * da + dc * sa - 2 * sc * dc + sc * (255 - da) + dc * (255 - sa);
402
403    // The above equation can be simplified as follows
404    int r = 255*(sc + dc) - 2 * sc * dc;
405    return clamp_div255round(r);
406}
407static SkPMColor exclusion_modeproc(SkPMColor src, SkPMColor dst) {
408    int sa = SkGetPackedA32(src);
409    int da = SkGetPackedA32(dst);
410    int a = srcover_byte(sa, da);
411    int r = exclusion_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
412    int g = exclusion_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
413    int b = exclusion_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
414    return SkPackARGB32(a, r, g, b);
415}
416
417// The CSS compositing spec introduces the following formulas:
418// (See https://dvcs.w3.org/hg/FXTF/rawfile/tip/compositing/index.html#blendingnonseparable)
419// SkComputeLuminance is similar to this formula but it uses the new definition from Rec. 709
420// while PDF and CG uses the one from Rec. Rec. 601
421// See http://www.glennchan.info/articles/technical/hd-versus-sd-color-space/hd-versus-sd-color-space.htm
422static inline int Lum(int r, int g, int b)
423{
424    return SkDiv255Round(r * 77 + g * 150 + b * 28);
425}
426
427static inline int min2(int a, int b) { return a < b ? a : b; }
428static inline int max2(int a, int b) { return a > b ? a : b; }
429#define minimum(a, b, c) min2(min2(a, b), c)
430#define maximum(a, b, c) max2(max2(a, b), c)
431
432static inline int Sat(int r, int g, int b) {
433    return maximum(r, g, b) - minimum(r, g, b);
434}
435
436static inline void setSaturationComponents(int* Cmin, int* Cmid, int* Cmax, int s) {
437    if(*Cmax > *Cmin) {
438        *Cmid =  SkMulDiv(*Cmid - *Cmin, s, *Cmax - *Cmin);
439        *Cmax = s;
440    } else {
441        *Cmax = 0;
442        *Cmid = 0;
443    }
444
445    *Cmin = 0;
446}
447
448static inline void SetSat(int* r, int* g, int* b, int s) {
449    if(*r <= *g) {
450        if(*g <= *b) {
451            setSaturationComponents(r, g, b, s);
452        } else if(*r <= *b) {
453            setSaturationComponents(r, b, g, s);
454        } else {
455            setSaturationComponents(b, r, g, s);
456        }
457    } else if(*r <= *b) {
458        setSaturationComponents(g, r, b, s);
459    } else if(*g <= *b) {
460        setSaturationComponents(g, b, r, s);
461    } else {
462        setSaturationComponents(b, g, r, s);
463    }
464}
465
466static inline void clipColor(int* r, int* g, int* b, int a) {
467    int L = Lum(*r, *g, *b);
468    int n = minimum(*r, *g, *b);
469    int x = maximum(*r, *g, *b);
470    int denom;
471    if ((n < 0) && (denom = L - n)) { // Compute denom and make sure it's non zero
472       *r = L + SkMulDiv(*r - L, L, denom);
473       *g = L + SkMulDiv(*g - L, L, denom);
474       *b = L + SkMulDiv(*b - L, L, denom);
475    }
476
477    if ((x > a) && (denom = x - L)) { // Compute denom and make sure it's non zero
478       int numer = a - L;
479       *r = L + SkMulDiv(*r - L, numer, denom);
480       *g = L + SkMulDiv(*g - L, numer, denom);
481       *b = L + SkMulDiv(*b - L, numer, denom);
482    }
483}
484
485static inline void SetLum(int* r, int* g, int* b, int a, int l) {
486  int d = l - Lum(*r, *g, *b);
487  *r +=  d;
488  *g +=  d;
489  *b +=  d;
490
491  clipColor(r, g, b, a);
492}
493
494// non-separable blend modes are done in non-premultiplied alpha
495#define  blendfunc_nonsep_byte(sc, dc, sa, da, blendval) \
496  clamp_div255round(sc * (255 - da) +  dc * (255 - sa) + blendval)
497
498// kHue_Mode
499// B(Cb, Cs) = SetLum(SetSat(Cs, Sat(Cb)), Lum(Cb))
500// Create a color with the hue of the source color and the saturation and luminosity of the backdrop color.
501static SkPMColor hue_modeproc(SkPMColor src, SkPMColor dst) {
502    int sr = SkGetPackedR32(src);
503    int sg = SkGetPackedG32(src);
504    int sb = SkGetPackedB32(src);
505    int sa = SkGetPackedA32(src);
506
507    int dr = SkGetPackedR32(dst);
508    int dg = SkGetPackedG32(dst);
509    int db = SkGetPackedB32(dst);
510    int da = SkGetPackedA32(dst);
511    int Sr, Sg, Sb;
512
513    if(sa && da) {
514        Sr = sr * sa;
515        Sg = sg * sa;
516        Sb = sb * sa;
517        SetSat(&Sr, &Sg, &Sb, Sat(dr, dg, db) * sa);
518        SetLum(&Sr, &Sg, &Sb, sa * da, Lum(dr, dg, db) * sa);
519    } else {
520        Sr = 0;
521        Sg = 0;
522        Sb = 0;
523    }
524
525    int a = srcover_byte(sa, da);
526    int r = blendfunc_nonsep_byte(sr, dr, sa, da, Sr);
527    int g = blendfunc_nonsep_byte(sg, dg, sa, da, Sg);
528    int b = blendfunc_nonsep_byte(sb, db, sa, da, Sb);
529    return SkPackARGB32(a, r, g, b);
530}
531
532// kSaturation_Mode
533// B(Cb, Cs) = SetLum(SetSat(Cb, Sat(Cs)), Lum(Cb))
534// Create a color with the saturation of the source color and the hue and luminosity of the backdrop color.
535static SkPMColor saturation_modeproc(SkPMColor src, SkPMColor dst) {
536    int sr = SkGetPackedR32(src);
537    int sg = SkGetPackedG32(src);
538    int sb = SkGetPackedB32(src);
539    int sa = SkGetPackedA32(src);
540
541    int dr = SkGetPackedR32(dst);
542    int dg = SkGetPackedG32(dst);
543    int db = SkGetPackedB32(dst);
544    int da = SkGetPackedA32(dst);
545    int Dr, Dg, Db;
546
547    if(sa && da) {
548        Dr = dr * sa;
549        Dg = dg * sa;
550        Db = db * sa;
551        SetSat(&Dr, &Dg, &Db, Sat(sr, sg, sb) * da);
552        SetLum(&Dr, &Dg, &Db, sa * da, Lum(dr, dg, db) * sa);
553    } else {
554        Dr = 0;
555        Dg = 0;
556        Db = 0;
557    }
558
559    int a = srcover_byte(sa, da);
560    int r = blendfunc_nonsep_byte(sr, dr, sa, da, Dr);
561    int g = blendfunc_nonsep_byte(sg, dg, sa, da, Dg);
562    int b = blendfunc_nonsep_byte(sb, db, sa, da, Db);
563    return SkPackARGB32(a, r, g, b);
564}
565
566// kColor_Mode
567// B(Cb, Cs) = SetLum(Cs, Lum(Cb))
568// Create a color with the hue and saturation of the source color and the luminosity of the backdrop color.
569static SkPMColor color_modeproc(SkPMColor src, SkPMColor dst) {
570    int sr = SkGetPackedR32(src);
571    int sg = SkGetPackedG32(src);
572    int sb = SkGetPackedB32(src);
573    int sa = SkGetPackedA32(src);
574
575    int dr = SkGetPackedR32(dst);
576    int dg = SkGetPackedG32(dst);
577    int db = SkGetPackedB32(dst);
578    int da = SkGetPackedA32(dst);
579    int Sr, Sg, Sb;
580
581    if(sa && da) {
582        Sr = sr * da;
583        Sg = sg * da;
584        Sb = sb * da;
585        SetLum(&Sr, &Sg, &Sb, sa * da, Lum(dr, dg, db) * sa);
586    } else {
587        Sr = 0;
588        Sg = 0;
589        Sb = 0;
590    }
591
592    int a = srcover_byte(sa, da);
593    int r = blendfunc_nonsep_byte(sr, dr, sa, da, Sr);
594    int g = blendfunc_nonsep_byte(sg, dg, sa, da, Sg);
595    int b = blendfunc_nonsep_byte(sb, db, sa, da, Sb);
596    return SkPackARGB32(a, r, g, b);
597}
598
599// kLuminosity_Mode
600// B(Cb, Cs) = SetLum(Cb, Lum(Cs))
601// Create a color with the luminosity of the source color and the hue and saturation of the backdrop color.
602static SkPMColor luminosity_modeproc(SkPMColor src, SkPMColor dst) {
603    int sr = SkGetPackedR32(src);
604    int sg = SkGetPackedG32(src);
605    int sb = SkGetPackedB32(src);
606    int sa = SkGetPackedA32(src);
607
608    int dr = SkGetPackedR32(dst);
609    int dg = SkGetPackedG32(dst);
610    int db = SkGetPackedB32(dst);
611    int da = SkGetPackedA32(dst);
612    int Dr, Dg, Db;
613
614    if(sa && da) {
615        Dr = dr * sa;
616        Dg = dg * sa;
617        Db = db * sa;
618        SetLum(&Dr, &Dg, &Db, sa * da, Lum(sr, sg, sb) * da);
619    } else {
620        Dr = 0;
621        Dg = 0;
622        Db = 0;
623    }
624
625    int a = srcover_byte(sa, da);
626    int r = blendfunc_nonsep_byte(sr, dr, sa, da, Dr);
627    int g = blendfunc_nonsep_byte(sg, dg, sa, da, Dg);
628    int b = blendfunc_nonsep_byte(sb, db, sa, da, Db);
629    return SkPackARGB32(a, r, g, b);
630}
631
632const ProcCoeff gProcCoeffs[] = {
633    { clear_modeproc,   SkXfermode::kZero_Coeff,    SkXfermode::kZero_Coeff },
634    { src_modeproc,     SkXfermode::kOne_Coeff,     SkXfermode::kZero_Coeff },
635    { dst_modeproc,     SkXfermode::kZero_Coeff,    SkXfermode::kOne_Coeff },
636    { srcover_modeproc, SkXfermode::kOne_Coeff,     SkXfermode::kISA_Coeff },
637    { dstover_modeproc, SkXfermode::kIDA_Coeff,     SkXfermode::kOne_Coeff },
638    { srcin_modeproc,   SkXfermode::kDA_Coeff,      SkXfermode::kZero_Coeff },
639    { dstin_modeproc,   SkXfermode::kZero_Coeff,    SkXfermode::kSA_Coeff },
640    { srcout_modeproc,  SkXfermode::kIDA_Coeff,     SkXfermode::kZero_Coeff },
641    { dstout_modeproc,  SkXfermode::kZero_Coeff,    SkXfermode::kISA_Coeff },
642    { srcatop_modeproc, SkXfermode::kDA_Coeff,      SkXfermode::kISA_Coeff },
643    { dstatop_modeproc, SkXfermode::kIDA_Coeff,     SkXfermode::kSA_Coeff },
644    { xor_modeproc,     SkXfermode::kIDA_Coeff,     SkXfermode::kISA_Coeff },
645
646    { plus_modeproc,    SkXfermode::kOne_Coeff,     SkXfermode::kOne_Coeff },
647    { modulate_modeproc,SkXfermode::kZero_Coeff,    SkXfermode::kSC_Coeff },
648    { screen_modeproc,  SkXfermode::kOne_Coeff,     SkXfermode::kISC_Coeff },
649    { overlay_modeproc,     CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
650    { darken_modeproc,      CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
651    { lighten_modeproc,     CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
652    { colordodge_modeproc,  CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
653    { colorburn_modeproc,   CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
654    { hardlight_modeproc,   CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
655    { softlight_modeproc,   CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
656    { difference_modeproc,  CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
657    { exclusion_modeproc,   CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
658    { multiply_modeproc,    CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
659    { hue_modeproc,         CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
660    { saturation_modeproc,  CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
661    { color_modeproc,       CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
662    { luminosity_modeproc,  CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
663};
664
665///////////////////////////////////////////////////////////////////////////////
666
667bool SkXfermode::asMode(Mode* mode) const {
668    return false;
669}
670
671bool SkXfermode::asFragmentProcessor(GrFragmentProcessor**, GrTexture*) const {
672    return false;
673}
674
675bool SkXfermode::asXPFactory(GrXPFactory**) const {
676    return false;
677}
678
679
680#if SK_SUPPORT_GPU
681#include "effects/GrPorterDuffXferProcessor.h"
682
683bool SkXfermode::AsXPFactory(SkXfermode* xfermode, GrXPFactory** xpf) {
684    if (NULL == xfermode) {
685        if (xpf) {
686            *xpf = GrPorterDuffXPFactory::Create(kSrcOver_Mode);
687        }
688        return true;
689    } else {
690        return xfermode->asXPFactory(xpf);
691    }
692}
693#else
694bool SkXfermode::AsXPFactory(SkXfermode* xfermode, GrXPFactory** xpf) {
695    return false;
696}
697#endif
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::xferA8(SkAlpha* SK_RESTRICT dst,
754                        const SkPMColor 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 res = this->xferColor(src[i], (dst[i] << SK_A32_SHIFT));
761            dst[i] = SkToU8(SkGetPackedA32(res));
762        }
763    } else {
764        for (int i = count - 1; i >= 0; --i) {
765            unsigned a = aa[i];
766            if (0 != a) {
767                SkAlpha dstA = dst[i];
768                unsigned A = SkGetPackedA32(this->xferColor(src[i],
769                                            (SkPMColor)(dstA << SK_A32_SHIFT)));
770                if (0xFF != a) {
771                    A = SkAlphaBlend(A, dstA, SkAlpha255To256(a));
772                }
773                dst[i] = SkToU8(A);
774            }
775        }
776    }
777}
778
779bool SkXfermode::supportsCoverageAsAlpha() const {
780    return false;
781}
782
783bool SkXfermode::isOpaque(SkXfermode::SrcColorOpacity opacityType) const {
784    return false;
785}
786
787///////////////////////////////////////////////////////////////////////////////
788///////////////////////////////////////////////////////////////////////////////
789
790SkFlattenable* SkProcCoeffXfermode::CreateProc(SkReadBuffer& buffer) {
791    uint32_t mode32 = buffer.read32();
792    if (!buffer.validate(mode32 < SK_ARRAY_COUNT(gProcCoeffs))) {
793        return NULL;
794    }
795    return SkXfermode::Create((SkXfermode::Mode)mode32);
796}
797
798void SkProcCoeffXfermode::flatten(SkWriteBuffer& buffer) const {
799    buffer.write32(fMode);
800}
801
802bool SkProcCoeffXfermode::asMode(Mode* mode) const {
803    if (mode) {
804        *mode = fMode;
805    }
806    return true;
807}
808
809bool SkProcCoeffXfermode::supportsCoverageAsAlpha() const {
810    if (CANNOT_USE_COEFF == fSrcCoeff) {
811        return false;
812    }
813
814    switch (fDstCoeff) {
815        case SkXfermode::kOne_Coeff:
816        case SkXfermode::kISA_Coeff:
817        case SkXfermode::kISC_Coeff:
818            return true;
819        default:
820            return false;
821    }
822}
823
824bool SkProcCoeffXfermode::isOpaque(SkXfermode::SrcColorOpacity opacityType) const {
825    if (CANNOT_USE_COEFF == fSrcCoeff) {
826        return false;
827    }
828
829    if (SkXfermode::kDA_Coeff == fSrcCoeff || SkXfermode::kDC_Coeff == fSrcCoeff ||
830        SkXfermode::kIDA_Coeff == fSrcCoeff || SkXfermode::kIDC_Coeff == fSrcCoeff) {
831        return false;
832    }
833
834    switch (fDstCoeff) {
835        case SkXfermode::kZero_Coeff:
836            return true;
837        case SkXfermode::kISA_Coeff:
838            return SkXfermode::kOpaque_SrcColorOpacity == opacityType;
839        case SkXfermode::kSA_Coeff:
840            return SkXfermode::kTransparentBlack_SrcColorOpacity == opacityType ||
841                   SkXfermode::kTransparentAlpha_SrcColorOpacity == opacityType;
842        case SkXfermode::kSC_Coeff:
843            return SkXfermode::kTransparentBlack_SrcColorOpacity == opacityType;
844        default:
845            return false;
846    }
847
848}
849
850void SkProcCoeffXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
851                                 const SkPMColor* SK_RESTRICT src, int count,
852                                 const SkAlpha* SK_RESTRICT aa) const {
853    SkASSERT(dst && src && count >= 0);
854
855    SkXfermodeProc proc = fProc;
856
857    if (proc) {
858        if (NULL == aa) {
859            for (int i = count - 1; i >= 0; --i) {
860                dst[i] = proc(src[i], dst[i]);
861            }
862        } else {
863            for (int i = count - 1; i >= 0; --i) {
864                unsigned a = aa[i];
865                if (0 != a) {
866                    SkPMColor dstC = dst[i];
867                    SkPMColor C = proc(src[i], dstC);
868                    if (a != 0xFF) {
869                        C = SkFourByteInterp(C, dstC, a);
870                    }
871                    dst[i] = C;
872                }
873            }
874        }
875    }
876}
877
878void SkProcCoeffXfermode::xfer16(uint16_t* SK_RESTRICT dst,
879                                 const SkPMColor* SK_RESTRICT src, int count,
880                                 const SkAlpha* SK_RESTRICT aa) const {
881    SkASSERT(dst && src && count >= 0);
882
883    SkXfermodeProc proc = fProc;
884
885    if (proc) {
886        if (NULL == aa) {
887            for (int i = count - 1; i >= 0; --i) {
888                SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
889                dst[i] = SkPixel32ToPixel16_ToU16(proc(src[i], dstC));
890            }
891        } else {
892            for (int i = count - 1; i >= 0; --i) {
893                unsigned a = aa[i];
894                if (0 != a) {
895                    SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
896                    SkPMColor C = proc(src[i], dstC);
897                    if (0xFF != a) {
898                        C = SkFourByteInterp(C, dstC, a);
899                    }
900                    dst[i] = SkPixel32ToPixel16_ToU16(C);
901                }
902            }
903        }
904    }
905}
906
907void SkProcCoeffXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
908                                 const SkPMColor* SK_RESTRICT src, int count,
909                                 const SkAlpha* SK_RESTRICT aa) const {
910    SkASSERT(dst && src && count >= 0);
911
912    SkXfermodeProc proc = fProc;
913
914    if (proc) {
915        if (NULL == aa) {
916            for (int i = count - 1; i >= 0; --i) {
917                SkPMColor res = proc(src[i], dst[i] << SK_A32_SHIFT);
918                dst[i] = SkToU8(SkGetPackedA32(res));
919            }
920        } else {
921            for (int i = count - 1; i >= 0; --i) {
922                unsigned a = aa[i];
923                if (0 != a) {
924                    SkAlpha dstA = dst[i];
925                    SkPMColor res = proc(src[i], dstA << SK_A32_SHIFT);
926                    unsigned A = SkGetPackedA32(res);
927                    if (0xFF != a) {
928                        A = SkAlphaBlend(A, dstA, SkAlpha255To256(a));
929                    }
930                    dst[i] = SkToU8(A);
931                }
932            }
933        }
934    }
935}
936
937#if SK_SUPPORT_GPU
938#include "effects/GrCustomXfermode.h"
939
940bool SkProcCoeffXfermode::asFragmentProcessor(GrFragmentProcessor** fp,
941                                              GrTexture* background) const {
942    if (GrCustomXfermode::IsSupportedMode(fMode)) {
943        if (fp) {
944            *fp = GrCustomXfermode::CreateFP(fMode, background);
945            SkASSERT(*fp);
946        }
947        return true;
948    }
949    return false;
950}
951
952bool SkProcCoeffXfermode::asXPFactory(GrXPFactory** xp) const {
953    if (CANNOT_USE_COEFF != fSrcCoeff) {
954        if (xp) {
955            *xp = GrPorterDuffXPFactory::Create(fMode);
956            SkASSERT(*xp);
957        }
958        return true;
959    }
960
961    if (GrCustomXfermode::IsSupportedMode(fMode)) {
962        if (xp) {
963            *xp = GrCustomXfermode::CreateXPFactory(fMode);
964            SkASSERT(*xp);
965        }
966        return true;
967    }
968    return false;
969}
970#endif
971
972const char* SkXfermode::ModeName(Mode mode) {
973    SkASSERT((unsigned) mode <= (unsigned)kLastMode);
974    const char* gModeStrings[] = {
975        "Clear", "Src", "Dst", "SrcOver", "DstOver", "SrcIn", "DstIn",
976        "SrcOut", "DstOut", "SrcATop", "DstATop", "Xor", "Plus",
977        "Modulate", "Screen", "Overlay", "Darken", "Lighten", "ColorDodge",
978        "ColorBurn", "HardLight", "SoftLight", "Difference", "Exclusion",
979        "Multiply", "Hue", "Saturation", "Color",  "Luminosity"
980    };
981    return gModeStrings[mode];
982    SK_COMPILE_ASSERT(SK_ARRAY_COUNT(gModeStrings) == kLastMode + 1, mode_count);
983}
984
985#ifndef SK_IGNORE_TO_STRING
986void SkProcCoeffXfermode::toString(SkString* str) const {
987    str->append("SkProcCoeffXfermode: ");
988
989    str->append("mode: ");
990    str->append(ModeName(fMode));
991
992    static const char* gCoeffStrings[kCoeffCount] = {
993        "Zero", "One", "SC", "ISC", "DC", "IDC", "SA", "ISA", "DA", "IDA"
994    };
995
996    str->append(" src: ");
997    if (CANNOT_USE_COEFF == fSrcCoeff) {
998        str->append("can't use");
999    } else {
1000        str->append(gCoeffStrings[fSrcCoeff]);
1001    }
1002
1003    str->append(" dst: ");
1004    if (CANNOT_USE_COEFF == fDstCoeff) {
1005        str->append("can't use");
1006    } else {
1007        str->append(gCoeffStrings[fDstCoeff]);
1008    }
1009}
1010#endif
1011
1012///////////////////////////////////////////////////////////////////////////////
1013
1014class SkClearXfermode : public SkProcCoeffXfermode {
1015public:
1016    static SkClearXfermode* Create(const ProcCoeff& rec) {
1017        return SkNEW_ARGS(SkClearXfermode, (rec));
1018    }
1019
1020    void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const override;
1021    void xferA8(SkAlpha*, const SkPMColor*, int, const SkAlpha*) const override;
1022
1023    SK_TO_STRING_OVERRIDE()
1024
1025private:
1026    SkClearXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kClear_Mode) {}
1027
1028    typedef SkProcCoeffXfermode INHERITED;
1029};
1030
1031void SkClearXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
1032                             const SkPMColor* SK_RESTRICT, int count,
1033                             const SkAlpha* SK_RESTRICT aa) const {
1034    SkASSERT(dst && count >= 0);
1035
1036    if (NULL == aa) {
1037        memset(dst, 0, count << 2);
1038    } else {
1039        for (int i = count - 1; i >= 0; --i) {
1040            unsigned a = aa[i];
1041            if (0xFF == a) {
1042                dst[i] = 0;
1043            } else if (a != 0) {
1044                dst[i] = SkAlphaMulQ(dst[i], SkAlpha255To256(255 - a));
1045            }
1046        }
1047    }
1048}
1049void SkClearXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
1050                             const SkPMColor* SK_RESTRICT, int count,
1051                             const SkAlpha* SK_RESTRICT aa) const {
1052    SkASSERT(dst && count >= 0);
1053
1054    if (NULL == aa) {
1055        memset(dst, 0, count);
1056    } else {
1057        for (int i = count - 1; i >= 0; --i) {
1058            unsigned a = aa[i];
1059            if (0xFF == a) {
1060                dst[i] = 0;
1061            } else if (0 != a) {
1062                dst[i] = SkAlphaMulAlpha(dst[i], 255 - a);
1063            }
1064        }
1065    }
1066}
1067
1068#ifndef SK_IGNORE_TO_STRING
1069void SkClearXfermode::toString(SkString* str) const {
1070    this->INHERITED::toString(str);
1071}
1072#endif
1073
1074///////////////////////////////////////////////////////////////////////////////
1075
1076class SkSrcXfermode : public SkProcCoeffXfermode {
1077public:
1078    static SkSrcXfermode* Create(const ProcCoeff& rec) {
1079        return SkNEW_ARGS(SkSrcXfermode, (rec));
1080    }
1081
1082    void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const override;
1083    void xferA8(SkAlpha*, const SkPMColor*, int, const SkAlpha*) const override;
1084
1085    SK_TO_STRING_OVERRIDE()
1086
1087private:
1088    SkSrcXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kSrc_Mode) {}
1089    typedef SkProcCoeffXfermode INHERITED;
1090};
1091
1092void SkSrcXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
1093                           const SkPMColor* SK_RESTRICT src, int count,
1094                           const SkAlpha* SK_RESTRICT aa) const {
1095    SkASSERT(dst && src && count >= 0);
1096
1097    if (NULL == aa) {
1098        memcpy(dst, src, count << 2);
1099    } else {
1100        for (int i = count - 1; i >= 0; --i) {
1101            unsigned a = aa[i];
1102            if (a == 0xFF) {
1103                dst[i] = src[i];
1104            } else if (a != 0) {
1105                dst[i] = SkFourByteInterp(src[i], dst[i], a);
1106            }
1107        }
1108    }
1109}
1110
1111void SkSrcXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
1112                           const SkPMColor* SK_RESTRICT src, int count,
1113                           const SkAlpha* SK_RESTRICT aa) const {
1114    SkASSERT(dst && src && count >= 0);
1115
1116    if (NULL == aa) {
1117        for (int i = count - 1; i >= 0; --i) {
1118            dst[i] = SkToU8(SkGetPackedA32(src[i]));
1119        }
1120    } else {
1121        for (int i = count - 1; i >= 0; --i) {
1122            unsigned a = aa[i];
1123            if (0 != a) {
1124                unsigned srcA = SkGetPackedA32(src[i]);
1125                if (a == 0xFF) {
1126                    dst[i] = SkToU8(srcA);
1127                } else {
1128                    dst[i] = SkToU8(SkAlphaBlend(srcA, dst[i], a));
1129                }
1130            }
1131        }
1132    }
1133}
1134#ifndef SK_IGNORE_TO_STRING
1135void SkSrcXfermode::toString(SkString* str) const {
1136    this->INHERITED::toString(str);
1137}
1138#endif
1139
1140///////////////////////////////////////////////////////////////////////////////
1141
1142class SkDstInXfermode : public SkProcCoeffXfermode {
1143public:
1144    static SkDstInXfermode* Create(const ProcCoeff& rec) {
1145        return SkNEW_ARGS(SkDstInXfermode, (rec));
1146    }
1147
1148    void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const override;
1149
1150    SK_TO_STRING_OVERRIDE()
1151
1152private:
1153    SkDstInXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstIn_Mode) {}
1154
1155    typedef SkProcCoeffXfermode INHERITED;
1156};
1157
1158void SkDstInXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
1159                             const SkPMColor* SK_RESTRICT src, int count,
1160                             const SkAlpha* SK_RESTRICT aa) const {
1161    SkASSERT(dst && src);
1162
1163    if (count <= 0) {
1164        return;
1165    }
1166    if (aa) {
1167        return this->INHERITED::xfer32(dst, src, count, aa);
1168    }
1169
1170    do {
1171        unsigned a = SkGetPackedA32(*src);
1172        *dst = SkAlphaMulQ(*dst, SkAlpha255To256(a));
1173        dst++;
1174        src++;
1175    } while (--count != 0);
1176}
1177
1178#ifndef SK_IGNORE_TO_STRING
1179void SkDstInXfermode::toString(SkString* str) const {
1180    this->INHERITED::toString(str);
1181}
1182#endif
1183
1184///////////////////////////////////////////////////////////////////////////////
1185
1186/* These modes can merge coverage into src-alpha
1187 *
1188{ dst_modeproc,     SkXfermode::kZero_Coeff,    SkXfermode::kOne_Coeff },
1189{ srcover_modeproc, SkXfermode::kOne_Coeff,     SkXfermode::kISA_Coeff },
1190{ dstover_modeproc, SkXfermode::kIDA_Coeff,     SkXfermode::kOne_Coeff },
1191{ dstout_modeproc,  SkXfermode::kZero_Coeff,    SkXfermode::kISA_Coeff },
1192{ srcatop_modeproc, SkXfermode::kDA_Coeff,      SkXfermode::kISA_Coeff },
1193{ xor_modeproc,     SkXfermode::kIDA_Coeff,     SkXfermode::kISA_Coeff },
1194{ plus_modeproc,    SkXfermode::kOne_Coeff,     SkXfermode::kOne_Coeff },
1195{ screen_modeproc,  SkXfermode::kOne_Coeff,     SkXfermode::kISC_Coeff },
1196*/
1197
1198#ifndef SK_SUPPORT_LEGACY_SCALAR_XFERMODES
1199static const float gInv255 = 0.0039215683f; //  (1.0f / 255) - ULP == SkBits2Float(0x3B808080)
1200
1201static Sk4f ramp(const Sk4f& v0, const Sk4f& v1, const Sk4f& t) {
1202    return v0 + (v1 - v0) * t;
1203}
1204
1205static Sk4f clamp_255(const Sk4f& value) {
1206    return Sk4f::Min(Sk4f(255), value);
1207}
1208
1209static Sk4f clamp_0_255(const Sk4f& value) {
1210    return Sk4f::Max(Sk4f(0), Sk4f::Min(Sk4f(255), value));
1211}
1212
1213/**
1214 *  Some modes can, due to very slight numerical error, generate "invalid" pmcolors...
1215 *
1216 *  e.g.
1217 *      alpha = 100.9999
1218 *      red   = 101
1219 *
1220 *  or
1221 *      alpha = 255.0001
1222 *
1223 *  If we know we're going to write-out the values as bytes, we can relax these somewhat,
1224 *  since we only really need to enforce that the bytes are valid premul...
1225 *
1226 *  To that end, this method asserts that the resulting pmcolor will be valid, but does not call
1227 *  SkPMFloat::isValid(), as that would fire sometimes, but not result in a bad pixel.
1228 */
1229static inline SkPMFloat check_as_pmfloat(const Sk4f& value) {
1230    SkPMFloat pm = value;
1231#ifdef SK_DEBUG
1232    (void)pm.round();
1233#endif
1234    return pm;
1235}
1236
1237//  kSrcATop_Mode,  //!< [Da, Sc * Da + (1 - Sa) * Dc]
1238struct SrcATop4f {
1239    static SkPMFloat Xfer(const SkPMFloat& src, const SkPMFloat& dst) {
1240        const Sk4f inv255(gInv255);
1241        return check_as_pmfloat(dst + (src * Sk4f(dst.a()) - dst * Sk4f(src.a())) * inv255);
1242    }
1243    static const bool kFoldCoverageIntoSrcAlpha = true;
1244    static const SkXfermode::Mode kMode = SkXfermode::kSrcATop_Mode;
1245};
1246
1247//  kDstATop_Mode,  //!< [Sa, Sa * Dc + Sc * (1 - Da)]
1248struct DstATop4f {
1249    static SkPMFloat Xfer(const SkPMFloat& src, const SkPMFloat& dst) {
1250        const Sk4f inv255(gInv255);
1251        return check_as_pmfloat(src + (dst * Sk4f(src.a()) - src * Sk4f(dst.a())) * inv255);
1252    }
1253    static const bool kFoldCoverageIntoSrcAlpha = false;
1254    static const SkXfermode::Mode kMode = SkXfermode::kDstATop_Mode;
1255};
1256
1257//  kXor_Mode   [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc]
1258struct Xor4f {
1259    static SkPMFloat Xfer(const SkPMFloat& src, const SkPMFloat& dst) {
1260        const Sk4f inv255(gInv255);
1261        return check_as_pmfloat(src + dst - (src * Sk4f(dst.a()) + dst * Sk4f(src.a())) * inv255);
1262    }
1263    static const bool kFoldCoverageIntoSrcAlpha = true;
1264    static const SkXfermode::Mode kMode = SkXfermode::kXor_Mode;
1265};
1266
1267//  kPlus_Mode   [Sa + Da, Sc + Dc]
1268struct Plus4f {
1269    static SkPMFloat Xfer(const SkPMFloat& src, const SkPMFloat& dst) {
1270        return check_as_pmfloat(clamp_255(src + dst));
1271    }
1272    static const bool kFoldCoverageIntoSrcAlpha = true;
1273    static const SkXfermode::Mode kMode = SkXfermode::kPlus_Mode;
1274};
1275
1276//  kModulate_Mode   [Sa * Da, Sc * Dc]
1277struct Modulate4f {
1278    static SkPMFloat Xfer(const SkPMFloat& src, const SkPMFloat& dst) {
1279        const Sk4f inv255(gInv255);
1280        return check_as_pmfloat(src * dst * inv255);
1281    }
1282    static const bool kFoldCoverageIntoSrcAlpha = false;
1283    static const SkXfermode::Mode kMode = SkXfermode::kModulate_Mode;
1284};
1285
1286//  kScreen_Mode   [S + D - S * D]
1287struct Screen4f {
1288    static SkPMFloat Xfer(const SkPMFloat& src, const SkPMFloat& dst) {
1289        const Sk4f inv255(gInv255);
1290        return check_as_pmfloat(src + dst - src * dst * inv255);
1291    }
1292    static const bool kFoldCoverageIntoSrcAlpha = true;
1293    static const SkXfermode::Mode kMode = SkXfermode::kScreen_Mode;
1294};
1295
1296struct Multiply4f {
1297    static SkPMFloat Xfer(const SkPMFloat& src, const SkPMFloat& dst) {
1298        const Sk4f inv255(gInv255);
1299        Sk4f sa = Sk4f(src.a());
1300        Sk4f da = Sk4f(dst.a());
1301        Sk4f sc = src;
1302        Sk4f dc = dst;
1303        Sk4f rc = sc + dc + (sc * (dc - da) - dc * sa) * inv255;
1304        // ra = srcover(sa, da), but the calc for rc happens to accomplish this for us
1305        return check_as_pmfloat(clamp_0_255(rc));
1306    }
1307    static const bool kFoldCoverageIntoSrcAlpha = false;
1308    static const SkXfermode::Mode kMode = SkXfermode::kMultiply_Mode;
1309};
1310
1311struct Difference4f {
1312    static SkPMFloat Xfer(const SkPMFloat& src, const SkPMFloat& dst) {
1313        const Sk4f inv255(gInv255);
1314        Sk4f sa = Sk4f(src.a());
1315        Sk4f da = Sk4f(dst.a());
1316        Sk4f sc = src;
1317        Sk4f dc = dst;
1318        Sk4f min = Sk4f::Min(sc * da, dc * sa) * inv255;
1319        Sk4f ra = sc + dc - min;
1320        return check_as_pmfloat(ra - min * SkPMFloat(0, 1, 1, 1));
1321    }
1322    static const bool kFoldCoverageIntoSrcAlpha = false;
1323    static const SkXfermode::Mode kMode = SkXfermode::kDifference_Mode;
1324};
1325
1326struct Exclusion4f {
1327    static SkPMFloat Xfer(const SkPMFloat& src, const SkPMFloat& dst) {
1328        const Sk4f inv255(gInv255);
1329        Sk4f sc = src;
1330        Sk4f dc = dst;
1331        Sk4f prod = sc * dc * inv255;
1332        Sk4f ra = sc + dc - prod;
1333        return check_as_pmfloat(ra - prod * SkPMFloat(0, 1, 1, 1));
1334    }
1335    static const bool kFoldCoverageIntoSrcAlpha = false;
1336    static const SkXfermode::Mode kMode = SkXfermode::kExclusion_Mode;
1337};
1338
1339template <typename ProcType>
1340class SkT4fXfermode : public SkProcCoeffXfermode {
1341public:
1342    static SkXfermode* Create(const ProcCoeff& rec) {
1343        return SkNEW_ARGS(SkT4fXfermode, (rec));
1344    }
1345
1346    void xfer32(SkPMColor dst[], const SkPMColor src[], int n, const SkAlpha aa[]) const override {
1347        if (NULL == aa) {
1348            for (int i = 0; i < n; ++i) {
1349                dst[i] = ProcType::Xfer(SkPMFloat(src[i]), SkPMFloat(dst[i])).round();
1350            }
1351        } else {
1352            for (int i = 0; i < n; ++i) {
1353                const Sk4f aa4 = Sk4f(aa[i] * gInv255);
1354                SkPMFloat dstF(dst[i]);
1355                SkPMFloat srcF(src[i]);
1356                Sk4f res;
1357                if (ProcType::kFoldCoverageIntoSrcAlpha) {
1358                    Sk4f src4 = srcF;
1359                    res = ProcType::Xfer(src4 * aa4, dstF);
1360                } else {
1361                    res = ramp(dstF, ProcType::Xfer(srcF, dstF), aa4);
1362                }
1363                dst[i] = SkPMFloat(res).round();
1364            }
1365        }
1366    }
1367
1368private:
1369    SkT4fXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, ProcType::kMode) {}
1370
1371    typedef SkProcCoeffXfermode INHERITED;
1372};
1373#endif
1374
1375///////////////////////////////////////////////////////////////////////////////
1376
1377class SkDstOutXfermode : public SkProcCoeffXfermode {
1378public:
1379    static SkDstOutXfermode* Create(const ProcCoeff& rec) {
1380        return SkNEW_ARGS(SkDstOutXfermode, (rec));
1381    }
1382
1383    void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const override;
1384
1385    SK_TO_STRING_OVERRIDE()
1386
1387private:
1388    SkDstOutXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstOut_Mode) {}
1389
1390    typedef SkProcCoeffXfermode INHERITED;
1391};
1392
1393void SkDstOutXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
1394                              const SkPMColor* SK_RESTRICT src, int count,
1395                              const SkAlpha* SK_RESTRICT aa) const {
1396    SkASSERT(dst && src);
1397
1398    if (count <= 0) {
1399        return;
1400    }
1401    if (aa) {
1402        return this->INHERITED::xfer32(dst, src, count, aa);
1403    }
1404
1405    do {
1406        unsigned a = SkGetPackedA32(*src);
1407        *dst = SkAlphaMulQ(*dst, SkAlpha255To256(255 - a));
1408        dst++;
1409        src++;
1410    } while (--count != 0);
1411}
1412
1413#ifndef SK_IGNORE_TO_STRING
1414void SkDstOutXfermode::toString(SkString* str) const {
1415    this->INHERITED::toString(str);
1416}
1417#endif
1418
1419///////////////////////////////////////////////////////////////////////////////
1420
1421extern SkProcCoeffXfermode* SkPlatformXfermodeFactory(const ProcCoeff& rec, SkXfermode::Mode mode);
1422extern SkXfermodeProc SkPlatformXfermodeProcFactory(SkXfermode::Mode mode);
1423
1424// Technically, can't be static and passed as a template parameter.  So we use anonymous namespace.
1425namespace {
1426SkXfermode* create_mode(int iMode) {
1427    SkXfermode::Mode mode = (SkXfermode::Mode)iMode;
1428
1429    ProcCoeff rec = gProcCoeffs[mode];
1430    SkXfermodeProc pp = SkPlatformXfermodeProcFactory(mode);
1431    if (pp != NULL) {
1432        rec.fProc = pp;
1433    }
1434
1435    SkXfermode* xfer = NULL;
1436
1437#ifndef SK_SUPPORT_LEGACY_SCALAR_XFERMODES
1438    switch (mode) {
1439        case SkXfermode::kSrcATop_Mode:
1440            xfer = SkT4fXfermode<SrcATop4f>::Create(rec);
1441            break;
1442        case SkXfermode::kDstATop_Mode:
1443            xfer = SkT4fXfermode<DstATop4f>::Create(rec);
1444            break;
1445        case SkXfermode::kXor_Mode:
1446            xfer = SkT4fXfermode<Xor4f>::Create(rec);
1447            break;
1448        case SkXfermode::kPlus_Mode:
1449            xfer = SkT4fXfermode<Plus4f>::Create(rec);
1450            break;
1451        case SkXfermode::kModulate_Mode:
1452            xfer = SkT4fXfermode<Modulate4f>::Create(rec);
1453            break;
1454        case SkXfermode::kScreen_Mode:
1455            xfer = SkT4fXfermode<Screen4f>::Create(rec);
1456            break;
1457        case SkXfermode::kMultiply_Mode:
1458            xfer = SkT4fXfermode<Multiply4f>::Create(rec);
1459            break;
1460        case SkXfermode::kDifference_Mode:
1461            xfer = SkT4fXfermode<Difference4f>::Create(rec);
1462            break;
1463        case SkXfermode::kExclusion_Mode:
1464            xfer = SkT4fXfermode<Exclusion4f>::Create(rec);
1465            break;
1466        default:
1467            break;
1468    }
1469    if (xfer) {
1470        return xfer;
1471    }
1472#endif
1473
1474    // check if we have a platform optim for that
1475    SkProcCoeffXfermode* xfm = SkPlatformXfermodeFactory(rec, mode);
1476    if (xfm != NULL) {
1477        xfer = xfm;
1478    } else {
1479        // All modes can in theory be represented by the ProcCoeff rec, since
1480        // it contains function ptrs. However, a few modes are both simple and
1481        // commonly used, so we call those out for their own subclasses here.
1482        switch (mode) {
1483            case SkXfermode::kClear_Mode:
1484                xfer = SkClearXfermode::Create(rec);
1485                break;
1486            case SkXfermode::kSrc_Mode:
1487                xfer = SkSrcXfermode::Create(rec);
1488                break;
1489            case SkXfermode::kSrcOver_Mode:
1490                SkASSERT(false);    // should not land here
1491                break;
1492            case SkXfermode::kDstIn_Mode:
1493                xfer = SkDstInXfermode::Create(rec);
1494                break;
1495            case SkXfermode::kDstOut_Mode:
1496                xfer = SkDstOutXfermode::Create(rec);
1497                break;
1498            default:
1499                // no special-case, just rely in the rec and its function-ptrs
1500                xfer = SkNEW_ARGS(SkProcCoeffXfermode, (rec, mode));
1501                break;
1502        }
1503    }
1504    return xfer;
1505}
1506}  // namespace
1507
1508SK_DECLARE_STATIC_LAZY_PTR_ARRAY(SkXfermode, cached, SkXfermode::kLastMode + 1, create_mode);
1509
1510SkXfermode* SkXfermode::Create(Mode mode) {
1511    SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount);
1512
1513    if ((unsigned)mode >= kModeCount) {
1514        // report error
1515        return NULL;
1516    }
1517
1518    // Skia's "default" mode is srcover. NULL in SkPaint is interpreted as srcover
1519    // so we can just return NULL from the factory.
1520    if (kSrcOver_Mode == mode) {
1521        return NULL;
1522    }
1523
1524    return SkSafeRef(cached[mode]);
1525}
1526
1527SkXfermodeProc SkXfermode::GetProc(Mode mode) {
1528    SkXfermodeProc  proc = NULL;
1529    if ((unsigned)mode < kModeCount) {
1530        proc = gProcCoeffs[mode].fProc;
1531    }
1532    return proc;
1533}
1534
1535bool SkXfermode::ModeAsCoeff(Mode mode, Coeff* src, Coeff* dst) {
1536    SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount);
1537
1538    if ((unsigned)mode >= (unsigned)kModeCount) {
1539        // illegal mode parameter
1540        return false;
1541    }
1542
1543    const ProcCoeff& rec = gProcCoeffs[mode];
1544
1545    if (CANNOT_USE_COEFF == rec.fSC) {
1546        return false;
1547    }
1548
1549    SkASSERT(CANNOT_USE_COEFF != rec.fDC);
1550    if (src) {
1551        *src = rec.fSC;
1552    }
1553    if (dst) {
1554        *dst = rec.fDC;
1555    }
1556    return true;
1557}
1558
1559bool SkXfermode::AsMode(const SkXfermode* xfer, Mode* mode) {
1560    if (NULL == xfer) {
1561        if (mode) {
1562            *mode = kSrcOver_Mode;
1563        }
1564        return true;
1565    }
1566    return xfer->asMode(mode);
1567}
1568
1569bool SkXfermode::IsMode(const SkXfermode* xfer, Mode mode) {
1570    // if xfer==null then the mode is srcover
1571    Mode m = kSrcOver_Mode;
1572    if (xfer && !xfer->asMode(&m)) {
1573        return false;
1574    }
1575    return mode == m;
1576}
1577
1578bool SkXfermode::SupportsCoverageAsAlpha(const SkXfermode* xfer) {
1579    // if xfer is NULL we treat it as srcOver which always supports coverageAsAlpha
1580    if (!xfer) {
1581        return true;
1582    }
1583
1584    return xfer->supportsCoverageAsAlpha();
1585}
1586
1587bool SkXfermode::IsOpaque(const SkXfermode* xfer, SrcColorOpacity opacityType) {
1588    // if xfer is NULL we treat it as srcOver which is opaque if our src is opaque
1589    if (!xfer) {
1590        return SkXfermode::kOpaque_SrcColorOpacity == opacityType;
1591    }
1592
1593    return xfer->isOpaque(opacityType);
1594}
1595
1596///////////////////////////////////////////////////////////////////////////////
1597//////////// 16bit xfermode procs
1598
1599#ifdef SK_DEBUG
1600static bool require_255(SkPMColor src) { return SkGetPackedA32(src) == 0xFF; }
1601static bool require_0(SkPMColor src) { return SkGetPackedA32(src) == 0; }
1602#endif
1603
1604static uint16_t src_modeproc16_255(SkPMColor src, uint16_t dst) {
1605    SkASSERT(require_255(src));
1606    return SkPixel32ToPixel16(src);
1607}
1608
1609static uint16_t dst_modeproc16(SkPMColor src, uint16_t dst) {
1610    return dst;
1611}
1612
1613static uint16_t srcover_modeproc16_0(SkPMColor src, uint16_t dst) {
1614    SkASSERT(require_0(src));
1615    return dst;
1616}
1617
1618static uint16_t srcover_modeproc16_255(SkPMColor src, uint16_t dst) {
1619    SkASSERT(require_255(src));
1620    return SkPixel32ToPixel16(src);
1621}
1622
1623static uint16_t dstover_modeproc16_0(SkPMColor src, uint16_t dst) {
1624    SkASSERT(require_0(src));
1625    return dst;
1626}
1627
1628static uint16_t dstover_modeproc16_255(SkPMColor src, uint16_t dst) {
1629    SkASSERT(require_255(src));
1630    return dst;
1631}
1632
1633static uint16_t srcin_modeproc16_255(SkPMColor src, uint16_t dst) {
1634    SkASSERT(require_255(src));
1635    return SkPixel32ToPixel16(src);
1636}
1637
1638static uint16_t dstin_modeproc16_255(SkPMColor src, uint16_t dst) {
1639    SkASSERT(require_255(src));
1640    return dst;
1641}
1642
1643static uint16_t dstout_modeproc16_0(SkPMColor src, uint16_t dst) {
1644    SkASSERT(require_0(src));
1645    return dst;
1646}
1647
1648static uint16_t srcatop_modeproc16(SkPMColor src, uint16_t dst) {
1649    unsigned isa = 255 - SkGetPackedA32(src);
1650
1651    return SkPackRGB16(
1652           SkPacked32ToR16(src) + SkAlphaMulAlpha(SkGetPackedR16(dst), isa),
1653           SkPacked32ToG16(src) + SkAlphaMulAlpha(SkGetPackedG16(dst), isa),
1654           SkPacked32ToB16(src) + SkAlphaMulAlpha(SkGetPackedB16(dst), isa));
1655}
1656
1657static uint16_t srcatop_modeproc16_0(SkPMColor src, uint16_t dst) {
1658    SkASSERT(require_0(src));
1659    return dst;
1660}
1661
1662static uint16_t srcatop_modeproc16_255(SkPMColor src, uint16_t dst) {
1663    SkASSERT(require_255(src));
1664    return SkPixel32ToPixel16(src);
1665}
1666
1667static uint16_t dstatop_modeproc16_255(SkPMColor src, uint16_t dst) {
1668    SkASSERT(require_255(src));
1669    return dst;
1670}
1671
1672/*********
1673    darken and lighten boil down to this.
1674
1675    darken  = (1 - Sa) * Dc + min(Sc, Dc)
1676    lighten = (1 - Sa) * Dc + max(Sc, Dc)
1677
1678    if (Sa == 0) these become
1679        darken  = Dc + min(0, Dc) = 0
1680        lighten = Dc + max(0, Dc) = Dc
1681
1682    if (Sa == 1) these become
1683        darken  = min(Sc, Dc)
1684        lighten = max(Sc, Dc)
1685*/
1686
1687static uint16_t darken_modeproc16_0(SkPMColor src, uint16_t dst) {
1688    SkASSERT(require_0(src));
1689    return 0;
1690}
1691
1692static uint16_t darken_modeproc16_255(SkPMColor src, uint16_t dst) {
1693    SkASSERT(require_255(src));
1694    unsigned r = SkFastMin32(SkPacked32ToR16(src), SkGetPackedR16(dst));
1695    unsigned g = SkFastMin32(SkPacked32ToG16(src), SkGetPackedG16(dst));
1696    unsigned b = SkFastMin32(SkPacked32ToB16(src), SkGetPackedB16(dst));
1697    return SkPackRGB16(r, g, b);
1698}
1699
1700static uint16_t lighten_modeproc16_0(SkPMColor src, uint16_t dst) {
1701    SkASSERT(require_0(src));
1702    return dst;
1703}
1704
1705static uint16_t lighten_modeproc16_255(SkPMColor src, uint16_t dst) {
1706    SkASSERT(require_255(src));
1707    unsigned r = SkMax32(SkPacked32ToR16(src), SkGetPackedR16(dst));
1708    unsigned g = SkMax32(SkPacked32ToG16(src), SkGetPackedG16(dst));
1709    unsigned b = SkMax32(SkPacked32ToB16(src), SkGetPackedB16(dst));
1710    return SkPackRGB16(r, g, b);
1711}
1712
1713struct Proc16Rec {
1714    SkXfermodeProc16    fProc16_0;
1715    SkXfermodeProc16    fProc16_255;
1716    SkXfermodeProc16    fProc16_General;
1717};
1718
1719static const Proc16Rec gModeProcs16[] = {
1720    { NULL,                 NULL,                   NULL            }, // CLEAR
1721    { NULL,                 src_modeproc16_255,     NULL            },
1722    { dst_modeproc16,       dst_modeproc16,         dst_modeproc16  },
1723    { srcover_modeproc16_0, srcover_modeproc16_255, NULL            },
1724    { dstover_modeproc16_0, dstover_modeproc16_255, NULL            },
1725    { NULL,                 srcin_modeproc16_255,   NULL            },
1726    { NULL,                 dstin_modeproc16_255,   NULL            },
1727    { NULL,                 NULL,                   NULL            },// SRC_OUT
1728    { dstout_modeproc16_0,  NULL,                   NULL            },
1729    { srcatop_modeproc16_0, srcatop_modeproc16_255, srcatop_modeproc16  },
1730    { NULL,                 dstatop_modeproc16_255, NULL            },
1731    { NULL,                 NULL,                   NULL            }, // XOR
1732
1733    { NULL,                 NULL,                   NULL            }, // plus
1734    { NULL,                 NULL,                   NULL            }, // modulate
1735    { NULL,                 NULL,                   NULL            }, // screen
1736    { NULL,                 NULL,                   NULL            }, // overlay
1737    { darken_modeproc16_0,  darken_modeproc16_255,  NULL            }, // darken
1738    { lighten_modeproc16_0, lighten_modeproc16_255, NULL            }, // lighten
1739    { NULL,                 NULL,                   NULL            }, // colordodge
1740    { NULL,                 NULL,                   NULL            }, // colorburn
1741    { NULL,                 NULL,                   NULL            }, // hardlight
1742    { NULL,                 NULL,                   NULL            }, // softlight
1743    { NULL,                 NULL,                   NULL            }, // difference
1744    { NULL,                 NULL,                   NULL            }, // exclusion
1745    { NULL,                 NULL,                   NULL            }, // multiply
1746    { NULL,                 NULL,                   NULL            }, // hue
1747    { NULL,                 NULL,                   NULL            }, // saturation
1748    { NULL,                 NULL,                   NULL            }, // color
1749    { NULL,                 NULL,                   NULL            }, // luminosity
1750};
1751
1752SkXfermodeProc16 SkXfermode::GetProc16(Mode mode, SkColor srcColor) {
1753    SkXfermodeProc16  proc16 = NULL;
1754    if ((unsigned)mode < kModeCount) {
1755        const Proc16Rec& rec = gModeProcs16[mode];
1756        unsigned a = SkColorGetA(srcColor);
1757
1758        if (0 == a) {
1759            proc16 = rec.fProc16_0;
1760        } else if (255 == a) {
1761            proc16 = rec.fProc16_255;
1762        } else {
1763            proc16 = rec.fProc16_General;
1764        }
1765    }
1766    return proc16;
1767}
1768
1769SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkXfermode)
1770    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkProcCoeffXfermode)
1771SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
1772