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