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