1
2/*
3 * Copyright 2006 The Android Open Source Project
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
9
10#include "SkXfermode.h"
11#include "SkColorPriv.h"
12
13#define SkAlphaMulAlpha(a, b)   SkMulDiv255Round(a, b)
14
15#if 0
16// idea for higher precision blends in xfer procs (and slightly faster)
17// see DstATop as a probable caller
18static U8CPU mulmuldiv255round(U8CPU a, U8CPU b, U8CPU c, U8CPU d) {
19    SkASSERT(a <= 255);
20    SkASSERT(b <= 255);
21    SkASSERT(c <= 255);
22    SkASSERT(d <= 255);
23    unsigned prod = SkMulS16(a, b) + SkMulS16(c, d) + 128;
24    unsigned result = (prod + (prod >> 8)) >> 8;
25    SkASSERT(result <= 255);
26    return result;
27}
28#endif
29
30static inline unsigned saturated_add(unsigned a, unsigned b) {
31    SkASSERT(a <= 255);
32    SkASSERT(b <= 255);
33    unsigned sum = a + b;
34    if (sum > 255) {
35        sum = 255;
36    }
37    return sum;
38}
39
40static inline int clamp_signed_byte(int n) {
41    if (n < 0) {
42        n = 0;
43    } else if (n > 255) {
44        n = 255;
45    }
46    return n;
47}
48
49static inline int clamp_div255round(int prod) {
50    if (prod <= 0) {
51        return 0;
52    } else if (prod >= 255*255) {
53        return 255;
54    } else {
55        return SkDiv255Round(prod);
56    }
57}
58
59static inline int clamp_max(int value, int max) {
60    if (value > max) {
61        value = max;
62    }
63    return value;
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// kMultiply_Mode
181static SkPMColor multiply_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
189// kScreen_Mode
190static inline int srcover_byte(int a, int b) {
191    return a + b - SkAlphaMulAlpha(a, b);
192}
193static SkPMColor screen_modeproc(SkPMColor src, SkPMColor dst) {
194    int a = srcover_byte(SkGetPackedA32(src), SkGetPackedA32(dst));
195    int r = srcover_byte(SkGetPackedR32(src), SkGetPackedR32(dst));
196    int g = srcover_byte(SkGetPackedG32(src), SkGetPackedG32(dst));
197    int b = srcover_byte(SkGetPackedB32(src), SkGetPackedB32(dst));
198    return SkPackARGB32(a, r, g, b);
199}
200
201// kOverlay_Mode
202static inline int overlay_byte(int sc, int dc, int sa, int da) {
203    int tmp = sc * (255 - da) + dc * (255 - sa);
204    int rc;
205    if (2 * dc <= da) {
206        rc = 2 * sc * dc;
207    } else {
208        rc = sa * da - 2 * (da - dc) * (sa - sc);
209    }
210    return clamp_div255round(rc + tmp);
211}
212static SkPMColor overlay_modeproc(SkPMColor src, SkPMColor dst) {
213    int sa = SkGetPackedA32(src);
214    int da = SkGetPackedA32(dst);
215    int a = srcover_byte(sa, da);
216    int r = overlay_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
217    int g = overlay_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
218    int b = overlay_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
219    return SkPackARGB32(a, r, g, b);
220}
221
222// kDarken_Mode
223static inline int darken_byte(int sc, int dc, int sa, int da) {
224    int sd = sc * da;
225    int ds = dc * sa;
226    if (sd < ds) {
227        // srcover
228        return sc + dc - SkDiv255Round(ds);
229    } else {
230        // dstover
231        return dc + sc - SkDiv255Round(sd);
232    }
233}
234static SkPMColor darken_modeproc(SkPMColor src, SkPMColor dst) {
235    int sa = SkGetPackedA32(src);
236    int da = SkGetPackedA32(dst);
237    int a = srcover_byte(sa, da);
238    int r = darken_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
239    int g = darken_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
240    int b = darken_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
241    return SkPackARGB32(a, r, g, b);
242}
243
244// kLighten_Mode
245static inline int lighten_byte(int sc, int dc, int sa, int da) {
246    int sd = sc * da;
247    int ds = dc * sa;
248    if (sd > ds) {
249        // srcover
250        return sc + dc - SkDiv255Round(ds);
251    } else {
252        // dstover
253        return dc + sc - SkDiv255Round(sd);
254    }
255}
256static SkPMColor lighten_modeproc(SkPMColor src, SkPMColor dst) {
257    int sa = SkGetPackedA32(src);
258    int da = SkGetPackedA32(dst);
259    int a = srcover_byte(sa, da);
260    int r = lighten_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
261    int g = lighten_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
262    int b = lighten_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
263    return SkPackARGB32(a, r, g, b);
264}
265
266// kColorDodge_Mode
267static inline int colordodge_byte(int sc, int dc, int sa, int da) {
268    int diff = sa - sc;
269    int rc;
270    if (0 == diff) {
271        rc = sa * da + sc * (255 - da) + dc * (255 - sa);
272        rc = SkDiv255Round(rc);
273    } else {
274        int tmp = (dc * sa << 15) / (da * diff);
275        rc = SkDiv255Round(sa * da) * tmp >> 15;
276        // don't clamp here, since we'll do it in our modeproc
277    }
278    return rc;
279}
280static SkPMColor colordodge_modeproc(SkPMColor src, SkPMColor dst) {
281    // added to avoid div-by-zero in colordodge_byte
282    if (0 == dst) {
283        return src;
284    }
285
286    int sa = SkGetPackedA32(src);
287    int da = SkGetPackedA32(dst);
288    int a = srcover_byte(sa, da);
289    int r = colordodge_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
290    int g = colordodge_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
291    int b = colordodge_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
292    r = clamp_max(r, a);
293    g = clamp_max(g, a);
294    b = clamp_max(b, a);
295    return SkPackARGB32(a, r, g, b);
296}
297
298// kColorBurn_Mode
299static inline int colorburn_byte(int sc, int dc, int sa, int da) {
300    int rc;
301    if (dc == da && 0 == sc) {
302        rc = sa * da + dc * (255 - sa);
303    } else if (0 == sc) {
304        return SkAlphaMulAlpha(dc, 255 - sa);
305    } else {
306        int tmp = (sa * (da - dc) * 256) / (sc * da);
307        if (tmp > 256) {
308            tmp = 256;
309        }
310        int tmp2 = sa * da;
311        rc = tmp2 - (tmp2 * tmp >> 8) + sc * (255 - da) + dc * (255 - sa);
312    }
313    return SkDiv255Round(rc);
314}
315static SkPMColor colorburn_modeproc(SkPMColor src, SkPMColor dst) {
316    // added to avoid div-by-zero in colorburn_byte
317    if (0 == dst) {
318        return src;
319    }
320
321    int sa = SkGetPackedA32(src);
322    int da = SkGetPackedA32(dst);
323    int a = srcover_byte(sa, da);
324    int r = colorburn_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
325    int g = colorburn_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
326    int b = colorburn_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
327    return SkPackARGB32(a, r, g, b);
328}
329
330// kHardLight_Mode
331static inline int hardlight_byte(int sc, int dc, int sa, int da) {
332    int rc;
333    if (2 * sc <= sa) {
334        rc = 2 * sc * dc;
335    } else {
336        rc = sa * da - 2 * (da - dc) * (sa - sc);
337    }
338    return clamp_div255round(rc + sc * (255 - da) + dc * (255 - sa));
339}
340static SkPMColor hardlight_modeproc(SkPMColor src, SkPMColor dst) {
341    int sa = SkGetPackedA32(src);
342    int da = SkGetPackedA32(dst);
343    int a = srcover_byte(sa, da);
344    int r = hardlight_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
345    int g = hardlight_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
346    int b = hardlight_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
347    return SkPackARGB32(a, r, g, b);
348}
349
350// returns 255 * sqrt(n/255)
351static U8CPU sqrt_unit_byte(U8CPU n) {
352    return SkSqrtBits(n, 15+4);
353}
354
355// kSoftLight_Mode
356static inline int softlight_byte(int sc, int dc, int sa, int da) {
357    int m = da ? dc * 256 / da : 0;
358    int rc;
359    if (2 * sc <= sa) {
360        rc = dc * (sa + ((2 * sc - sa) * (256 - m) >> 8));
361    } else if (4 * dc <= da) {
362        int tmp = (4 * m * (4 * m + 256) * (m - 256) >> 16) + 7 * m;
363        rc = dc * sa + (da * (2 * sc - sa) * tmp >> 8);
364    } else {
365        int tmp = sqrt_unit_byte(m) - m;
366        rc = dc * sa + (da * (2 * sc - sa) * tmp >> 8);
367    }
368    return clamp_div255round(rc + sc * (255 - da) + dc * (255 - sa));
369}
370static SkPMColor softlight_modeproc(SkPMColor src, SkPMColor dst) {
371    int sa = SkGetPackedA32(src);
372    int da = SkGetPackedA32(dst);
373    int a = srcover_byte(sa, da);
374    int r = softlight_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
375    int g = softlight_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
376    int b = softlight_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
377    return SkPackARGB32(a, r, g, b);
378}
379
380// kDifference_Mode
381static inline int difference_byte(int sc, int dc, int sa, int da) {
382    int tmp = SkMin32(sc * da, dc * sa);
383    return clamp_signed_byte(sc + dc - 2 * SkDiv255Round(tmp));
384}
385static SkPMColor difference_modeproc(SkPMColor src, SkPMColor dst) {
386    int sa = SkGetPackedA32(src);
387    int da = SkGetPackedA32(dst);
388    int a = srcover_byte(sa, da);
389    int r = difference_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
390    int g = difference_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
391    int b = difference_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
392    return SkPackARGB32(a, r, g, b);
393}
394
395// kExclusion_Mode
396static inline int exclusion_byte(int sc, int dc, int sa, int da) {
397    // this equations is wacky, wait for SVG to confirm it
398    int r = sc * da + dc * sa - 2 * sc * dc + sc * (255 - da) + dc * (255 - sa);
399    return clamp_div255round(r);
400}
401static SkPMColor exclusion_modeproc(SkPMColor src, SkPMColor dst) {
402    int sa = SkGetPackedA32(src);
403    int da = SkGetPackedA32(dst);
404    int a = srcover_byte(sa, da);
405    int r = exclusion_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
406    int g = exclusion_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
407    int b = exclusion_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
408    return SkPackARGB32(a, r, g, b);
409}
410
411struct ProcCoeff {
412    SkXfermodeProc      fProc;
413    SkXfermode::Coeff   fSC;
414    SkXfermode::Coeff   fDC;
415};
416
417#define CANNOT_USE_COEFF    SkXfermode::Coeff(-1)
418
419static const ProcCoeff gProcCoeffs[] = {
420    { clear_modeproc,   SkXfermode::kZero_Coeff,    SkXfermode::kZero_Coeff },
421    { src_modeproc,     SkXfermode::kOne_Coeff,     SkXfermode::kZero_Coeff },
422    { dst_modeproc,     SkXfermode::kZero_Coeff,    SkXfermode::kOne_Coeff },
423    { srcover_modeproc, SkXfermode::kOne_Coeff,     SkXfermode::kISA_Coeff },
424    { dstover_modeproc, SkXfermode::kIDA_Coeff,     SkXfermode::kOne_Coeff },
425    { srcin_modeproc,   SkXfermode::kDA_Coeff,      SkXfermode::kZero_Coeff },
426    { dstin_modeproc,   SkXfermode::kZero_Coeff,    SkXfermode::kSA_Coeff },
427    { srcout_modeproc,  SkXfermode::kIDA_Coeff,     SkXfermode::kZero_Coeff },
428    { dstout_modeproc,  SkXfermode::kZero_Coeff,    SkXfermode::kISA_Coeff },
429    { srcatop_modeproc, SkXfermode::kDA_Coeff,      SkXfermode::kISA_Coeff },
430    { dstatop_modeproc, SkXfermode::kIDA_Coeff,     SkXfermode::kSA_Coeff },
431    { xor_modeproc,     SkXfermode::kIDA_Coeff,     SkXfermode::kISA_Coeff },
432
433    { plus_modeproc,    SkXfermode::kOne_Coeff,     SkXfermode::kOne_Coeff },
434    { multiply_modeproc,SkXfermode::kZero_Coeff,    SkXfermode::kSC_Coeff },
435    { screen_modeproc,      CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
436    { overlay_modeproc,     CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
437    { darken_modeproc,      CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
438    { lighten_modeproc,     CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
439    { colordodge_modeproc,  CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
440    { colorburn_modeproc,   CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
441    { hardlight_modeproc,   CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
442    { softlight_modeproc,   CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
443    { difference_modeproc,  CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
444    { exclusion_modeproc,   CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
445};
446
447///////////////////////////////////////////////////////////////////////////////
448
449bool SkXfermode::asCoeff(Coeff* src, Coeff* dst) {
450    return false;
451}
452
453bool SkXfermode::asMode(Mode* mode) {
454    return false;
455}
456
457SkPMColor SkXfermode::xferColor(SkPMColor src, SkPMColor dst) {
458    // no-op. subclasses should override this
459    return dst;
460}
461
462void SkXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
463                        const SkPMColor* SK_RESTRICT src, int count,
464                        const SkAlpha* SK_RESTRICT aa) {
465    SkASSERT(dst && src && count >= 0);
466
467    if (NULL == aa) {
468        for (int i = count - 1; i >= 0; --i) {
469            dst[i] = this->xferColor(src[i], dst[i]);
470        }
471    } else {
472        for (int i = count - 1; i >= 0; --i) {
473            unsigned a = aa[i];
474            if (0 != a) {
475                SkPMColor dstC = dst[i];
476                SkPMColor C = this->xferColor(src[i], dstC);
477                if (0xFF != a) {
478                    C = SkFourByteInterp(C, dstC, a);
479                }
480                dst[i] = C;
481            }
482        }
483    }
484}
485
486void SkXfermode::xfer16(uint16_t* dst,
487                        const SkPMColor* SK_RESTRICT src, int count,
488                        const SkAlpha* SK_RESTRICT aa) {
489    SkASSERT(dst && src && count >= 0);
490
491    if (NULL == aa) {
492        for (int i = count - 1; i >= 0; --i) {
493            SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
494            dst[i] = SkPixel32ToPixel16_ToU16(this->xferColor(src[i], dstC));
495        }
496    } else {
497        for (int i = count - 1; i >= 0; --i) {
498            unsigned a = aa[i];
499            if (0 != a) {
500                SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
501                SkPMColor C = this->xferColor(src[i], dstC);
502                if (0xFF != a) {
503                    C = SkFourByteInterp(C, dstC, a);
504                }
505                dst[i] = SkPixel32ToPixel16_ToU16(C);
506            }
507        }
508    }
509}
510
511void SkXfermode::xfer4444(SkPMColor16* SK_RESTRICT dst,
512                          const SkPMColor* SK_RESTRICT src, int count,
513                          const SkAlpha* SK_RESTRICT aa)
514{
515    SkASSERT(dst && src && count >= 0);
516
517    if (NULL == aa) {
518        for (int i = count - 1; i >= 0; --i) {
519            SkPMColor dstC = SkPixel4444ToPixel32(dst[i]);
520            dst[i] = SkPixel32ToPixel4444(this->xferColor(src[i], dstC));
521        }
522    } else {
523        for (int i = count - 1; i >= 0; --i) {
524            unsigned a = aa[i];
525            if (0 != a) {
526                SkPMColor dstC = SkPixel4444ToPixel32(dst[i]);
527                SkPMColor C = this->xferColor(src[i], dstC);
528                if (0xFF != a) {
529                    C = SkFourByteInterp(C, dstC, a);
530                }
531                dst[i] = SkPixel32ToPixel4444(C);
532            }
533        }
534    }
535}
536
537void SkXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
538                        const SkPMColor src[], int count,
539                        const SkAlpha* SK_RESTRICT aa)
540{
541    SkASSERT(dst && src && count >= 0);
542
543    if (NULL == aa) {
544        for (int i = count - 1; i >= 0; --i) {
545            SkPMColor res = this->xferColor(src[i], (dst[i] << SK_A32_SHIFT));
546            dst[i] = SkToU8(SkGetPackedA32(res));
547        }
548    } else {
549        for (int i = count - 1; i >= 0; --i) {
550            unsigned a = aa[i];
551            if (0 != a) {
552                SkAlpha dstA = dst[i];
553                unsigned A = SkGetPackedA32(this->xferColor(src[i],
554                                            (SkPMColor)(dstA << SK_A32_SHIFT)));
555                if (0xFF != a) {
556                    A = SkAlphaBlend(A, dstA, SkAlpha255To256(a));
557                }
558                dst[i] = SkToU8(A);
559            }
560        }
561    }
562}
563
564///////////////////////////////////////////////////////////////////////////////
565
566void SkProcXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
567                            const SkPMColor* SK_RESTRICT src, int count,
568                            const SkAlpha* SK_RESTRICT aa) {
569    SkASSERT(dst && src && count >= 0);
570
571    SkXfermodeProc proc = fProc;
572
573    if (NULL != proc) {
574        if (NULL == aa) {
575            for (int i = count - 1; i >= 0; --i) {
576                dst[i] = proc(src[i], dst[i]);
577            }
578        } else {
579            for (int i = count - 1; i >= 0; --i) {
580                unsigned a = aa[i];
581                if (0 != a) {
582                    SkPMColor dstC = dst[i];
583                    SkPMColor C = proc(src[i], dstC);
584                    if (a != 0xFF) {
585                        C = SkFourByteInterp(C, dstC, a);
586                    }
587                    dst[i] = C;
588                }
589            }
590        }
591    }
592}
593
594void SkProcXfermode::xfer16(uint16_t* SK_RESTRICT dst,
595                            const SkPMColor* SK_RESTRICT src, int count,
596                            const SkAlpha* SK_RESTRICT aa) {
597    SkASSERT(dst && src && count >= 0);
598
599    SkXfermodeProc proc = fProc;
600
601    if (NULL != proc) {
602        if (NULL == aa) {
603            for (int i = count - 1; i >= 0; --i) {
604                SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
605                dst[i] = SkPixel32ToPixel16_ToU16(proc(src[i], dstC));
606            }
607        } else {
608            for (int i = count - 1; i >= 0; --i) {
609                unsigned a = aa[i];
610                if (0 != a) {
611                    SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
612                    SkPMColor C = proc(src[i], dstC);
613                    if (0xFF != a) {
614                        C = SkFourByteInterp(C, dstC, a);
615                    }
616                    dst[i] = SkPixel32ToPixel16_ToU16(C);
617                }
618            }
619        }
620    }
621}
622
623void SkProcXfermode::xfer4444(SkPMColor16* SK_RESTRICT dst,
624                              const SkPMColor* SK_RESTRICT src, int count,
625                              const SkAlpha* SK_RESTRICT aa) {
626    SkASSERT(dst && src && count >= 0);
627
628    SkXfermodeProc proc = fProc;
629
630    if (NULL != proc) {
631        if (NULL == aa) {
632            for (int i = count - 1; i >= 0; --i) {
633                SkPMColor dstC = SkPixel4444ToPixel32(dst[i]);
634                dst[i] = SkPixel32ToPixel4444(proc(src[i], dstC));
635            }
636        } else {
637            for (int i = count - 1; i >= 0; --i) {
638                unsigned a = aa[i];
639                if (0 != a) {
640                    SkPMColor dstC = SkPixel4444ToPixel32(dst[i]);
641                    SkPMColor C = proc(src[i], dstC);
642                    if (0xFF != a) {
643                        C = SkFourByteInterp(C, dstC, a);
644                    }
645                    dst[i] = SkPixel32ToPixel4444(C);
646                }
647            }
648        }
649    }
650}
651
652void SkProcXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
653                            const SkPMColor* SK_RESTRICT src, int count,
654                            const SkAlpha* SK_RESTRICT aa) {
655    SkASSERT(dst && src && count >= 0);
656
657    SkXfermodeProc proc = fProc;
658
659    if (NULL != proc) {
660        if (NULL == aa) {
661            for (int i = count - 1; i >= 0; --i) {
662                SkPMColor res = proc(src[i], dst[i] << SK_A32_SHIFT);
663                dst[i] = SkToU8(SkGetPackedA32(res));
664            }
665        } else {
666            for (int i = count - 1; i >= 0; --i) {
667                unsigned a = aa[i];
668                if (0 != a) {
669                    SkAlpha dstA = dst[i];
670                    SkPMColor res = proc(src[i], dstA << SK_A32_SHIFT);
671                    unsigned A = SkGetPackedA32(res);
672                    if (0xFF != a) {
673                        A = SkAlphaBlend(A, dstA, SkAlpha255To256(a));
674                    }
675                    dst[i] = SkToU8(A);
676                }
677            }
678        }
679    }
680}
681
682SkProcXfermode::SkProcXfermode(SkFlattenableReadBuffer& buffer)
683        : SkXfermode(buffer) {
684    // Might be a NULL if the Xfermode is recorded using the CrossProcess flag
685    fProc = (SkXfermodeProc)buffer.readFunctionPtr();
686}
687
688void SkProcXfermode::flatten(SkFlattenableWriteBuffer& buffer) {
689    if (buffer.isCrossProcess()) {
690        // function pointer is only valid in the current process. Write a NULL
691        // so it can't be accidentally used
692        buffer.writeFunctionPtr(NULL);
693    } else {
694        buffer.writeFunctionPtr((void*)fProc);
695    }
696}
697
698///////////////////////////////////////////////////////////////////////////////
699///////////////////////////////////////////////////////////////////////////////
700
701class SkProcCoeffXfermode : public SkProcXfermode {
702public:
703    SkProcCoeffXfermode(const ProcCoeff& rec, Mode mode)
704            : INHERITED(rec.fProc) {
705        fMode = mode;
706        // these may be valid, or may be CANNOT_USE_COEFF
707        fSrcCoeff = rec.fSC;
708        fDstCoeff = rec.fDC;
709    }
710
711    virtual bool asMode(Mode* mode) {
712        if (mode) {
713            *mode = fMode;
714        }
715        return true;
716    }
717
718    virtual bool asCoeff(Coeff* sc, Coeff* dc) {
719        if (CANNOT_USE_COEFF == fSrcCoeff) {
720            return false;
721        }
722
723        if (sc) {
724            *sc = fSrcCoeff;
725        }
726        if (dc) {
727            *dc = fDstCoeff;
728        }
729        return true;
730    }
731
732    virtual Factory getFactory() { return CreateProc; }
733    virtual void flatten(SkFlattenableWriteBuffer& buffer) {
734        this->INHERITED::flatten(buffer);
735        buffer.write32(fMode);
736    }
737
738    static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
739        return SkNEW_ARGS(SkProcCoeffXfermode, (buffer));
740    }
741
742protected:
743    SkProcCoeffXfermode(SkFlattenableReadBuffer& buffer)
744            : INHERITED(buffer) {
745        fMode = (SkXfermode::Mode)buffer.readU32();
746
747        if (buffer.getPictureVersion() == PICTURE_VERSION_ICS) {
748            fSrcCoeff = (Coeff)buffer.readU32();
749            fDstCoeff = (Coeff)buffer.readU32();
750            return;
751        }
752
753        const ProcCoeff& rec = gProcCoeffs[fMode];
754        // these may be valid, or may be CANNOT_USE_COEFF
755        fSrcCoeff = rec.fSC;
756        fDstCoeff = rec.fDC;
757        // now update our function-ptr in the super class
758        this->INHERITED::setProc(rec.fProc);
759    }
760
761private:
762    Mode    fMode;
763    Coeff   fSrcCoeff, fDstCoeff;
764
765
766    typedef SkProcXfermode INHERITED;
767};
768
769///////////////////////////////////////////////////////////////////////////////
770
771class SkClearXfermode : public SkProcCoeffXfermode {
772public:
773    SkClearXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kClear_Mode) {}
774
775    virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) SK_OVERRIDE;
776    virtual void xferA8(SkAlpha*, const SkPMColor*, int, const SkAlpha*) SK_OVERRIDE;
777    virtual Factory getFactory() SK_OVERRIDE { return CreateProc; }
778
779    static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
780        return SkNEW_ARGS(SkClearXfermode, (buffer));
781    }
782
783private:
784    SkClearXfermode(SkFlattenableReadBuffer& buffer)
785        : SkProcCoeffXfermode(buffer) {}
786
787};
788
789void SkClearXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
790                             const SkPMColor* SK_RESTRICT, int count,
791                             const SkAlpha* SK_RESTRICT aa) {
792    SkASSERT(dst && count >= 0);
793
794    if (NULL == aa) {
795        memset(dst, 0, count << 2);
796    } else {
797        for (int i = count - 1; i >= 0; --i) {
798            unsigned a = aa[i];
799            if (0xFF == a) {
800                dst[i] = 0;
801            } else if (a != 0) {
802                dst[i] = SkAlphaMulQ(dst[i], SkAlpha255To256(255 - a));
803            }
804        }
805    }
806}
807void SkClearXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
808                             const SkPMColor* SK_RESTRICT, int count,
809                             const SkAlpha* SK_RESTRICT aa) {
810    SkASSERT(dst && count >= 0);
811
812    if (NULL == aa) {
813        memset(dst, 0, count);
814    } else {
815        for (int i = count - 1; i >= 0; --i) {
816            unsigned a = aa[i];
817            if (0xFF == a) {
818                dst[i] = 0;
819            } else if (0 != a) {
820                dst[i] = SkAlphaMulAlpha(dst[i], 255 - a);
821            }
822        }
823    }
824}
825
826///////////////////////////////////////////////////////////////////////////////
827
828class SkSrcXfermode : public SkProcCoeffXfermode {
829public:
830    SkSrcXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kSrc_Mode) {}
831
832    virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) SK_OVERRIDE;
833    virtual void xferA8(SkAlpha*, const SkPMColor*, int, const SkAlpha*) SK_OVERRIDE;
834    virtual Factory getFactory() SK_OVERRIDE { return CreateProc; }
835
836    static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
837        return SkNEW_ARGS(SkSrcXfermode, (buffer));
838    }
839
840private:
841    SkSrcXfermode(SkFlattenableReadBuffer& buffer)
842        : SkProcCoeffXfermode(buffer) {}
843
844};
845
846void SkSrcXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
847                           const SkPMColor* SK_RESTRICT src, int count,
848                           const SkAlpha* SK_RESTRICT aa) {
849    SkASSERT(dst && src && count >= 0);
850
851    if (NULL == aa) {
852        memcpy(dst, src, count << 2);
853    } else {
854        for (int i = count - 1; i >= 0; --i) {
855            unsigned a = aa[i];
856            if (a == 0xFF) {
857                dst[i] = src[i];
858            } else if (a != 0) {
859                dst[i] = SkFourByteInterp(src[i], dst[i], a);
860            }
861        }
862    }
863}
864
865void SkSrcXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
866                           const SkPMColor* SK_RESTRICT src, int count,
867                           const SkAlpha* SK_RESTRICT aa) {
868    SkASSERT(dst && src && count >= 0);
869
870    if (NULL == aa) {
871        for (int i = count - 1; i >= 0; --i) {
872            dst[i] = SkToU8(SkGetPackedA32(src[i]));
873        }
874    } else {
875        for (int i = count - 1; i >= 0; --i) {
876            unsigned a = aa[i];
877            if (0 != a) {
878                unsigned srcA = SkGetPackedA32(src[i]);
879                if (a == 0xFF) {
880                    dst[i] = SkToU8(srcA);
881                } else {
882                    dst[i] = SkToU8(SkAlphaBlend(srcA, dst[i], a));
883                }
884            }
885        }
886    }
887}
888
889////////////////////////////////////////////////////////////////////////////////////
890
891class SkDstInXfermode : public SkProcCoeffXfermode {
892public:
893    SkDstInXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstIn_Mode) {}
894
895    virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) SK_OVERRIDE;
896    virtual Factory getFactory() SK_OVERRIDE { return CreateProc; }
897
898    static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
899        return SkNEW_ARGS(SkDstInXfermode, (buffer));
900    }
901
902private:
903    SkDstInXfermode(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {}
904
905    typedef SkProcCoeffXfermode INHERITED;
906};
907
908void SkDstInXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
909                             const SkPMColor* SK_RESTRICT src, int count,
910                             const SkAlpha* SK_RESTRICT aa) {
911    SkASSERT(dst && src);
912
913    if (count <= 0) {
914        return;
915    }
916    if (NULL != aa) {
917        return this->INHERITED::xfer32(dst, src, count, aa);
918    }
919
920    do {
921        unsigned a = SkGetPackedA32(*src);
922        *dst = SkAlphaMulQ(*dst, SkAlpha255To256(a));
923        dst++;
924        src++;
925    } while (--count != 0);
926}
927
928/////////////////////////////////////////////////////////////////////////////////////////
929
930class SkDstOutXfermode : public SkProcCoeffXfermode {
931public:
932    SkDstOutXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstOut_Mode) {}
933
934    virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) SK_OVERRIDE;
935    virtual Factory getFactory() SK_OVERRIDE { return CreateProc; }
936
937    static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) {
938        return SkNEW_ARGS(SkDstOutXfermode, (buffer));
939    }
940
941private:
942    SkDstOutXfermode(SkFlattenableReadBuffer& buffer)
943        : INHERITED(buffer) {}
944
945    typedef SkProcCoeffXfermode INHERITED;
946};
947
948void SkDstOutXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
949                              const SkPMColor* SK_RESTRICT src, int count,
950                              const SkAlpha* SK_RESTRICT aa) {
951    SkASSERT(dst && src);
952
953    if (count <= 0) {
954        return;
955    }
956    if (NULL != aa) {
957        return this->INHERITED::xfer32(dst, src, count, aa);
958    }
959
960    do {
961        unsigned a = SkGetPackedA32(*src);
962        *dst = SkAlphaMulQ(*dst, SkAlpha255To256(255 - a));
963        dst++;
964        src++;
965    } while (--count != 0);
966}
967
968///////////////////////////////////////////////////////////////////////////////
969
970SkXfermode* SkXfermode::Create(Mode mode) {
971    SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount);
972    SkASSERT((unsigned)mode < kModeCount);
973
974    const ProcCoeff& rec = gProcCoeffs[mode];
975
976    switch (mode) {
977        case kClear_Mode:
978            return SkNEW_ARGS(SkClearXfermode, (rec));
979        case kSrc_Mode:
980            return SkNEW_ARGS(SkSrcXfermode, (rec));
981        case kSrcOver_Mode:
982            return NULL;
983        case kDstIn_Mode:
984            return SkNEW_ARGS(SkDstInXfermode, (rec));
985        case kDstOut_Mode:
986            return SkNEW_ARGS(SkDstOutXfermode, (rec));
987        default:
988            return SkNEW_ARGS(SkProcCoeffXfermode, (rec, mode));
989    }
990}
991
992SkXfermodeProc SkXfermode::GetProc(Mode mode) {
993    SkXfermodeProc  proc = NULL;
994    if ((unsigned)mode < kModeCount) {
995        proc = gProcCoeffs[mode].fProc;
996    }
997    return proc;
998}
999
1000bool SkXfermode::ModeAsCoeff(Mode mode, Coeff* src, Coeff* dst) {
1001    SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount);
1002
1003    if ((unsigned)mode >= (unsigned)kModeCount) {
1004        // illegal mode parameter
1005        return false;
1006    }
1007
1008    const ProcCoeff& rec = gProcCoeffs[mode];
1009
1010    if (CANNOT_USE_COEFF == rec.fSC) {
1011        return false;
1012    }
1013
1014    SkASSERT(CANNOT_USE_COEFF != rec.fDC);
1015    if (src) {
1016        *src = rec.fSC;
1017    }
1018    if (dst) {
1019        *dst = rec.fDC;
1020    }
1021    return true;
1022}
1023
1024bool SkXfermode::AsMode(SkXfermode* xfer, Mode* mode) {
1025    if (NULL == xfer) {
1026        if (mode) {
1027            *mode = kSrcOver_Mode;
1028        }
1029        return true;
1030    }
1031    return xfer->asMode(mode);
1032}
1033
1034bool SkXfermode::AsCoeff(SkXfermode* xfer, Coeff* src, Coeff* dst) {
1035    if (NULL == xfer) {
1036        return ModeAsCoeff(kSrcOver_Mode, src, dst);
1037    }
1038    return xfer->asCoeff(src, dst);
1039}
1040
1041bool SkXfermode::IsMode(SkXfermode* xfer, Mode mode) {
1042    // if xfer==null then the mode is srcover
1043    Mode m = kSrcOver_Mode;
1044    if (xfer && !xfer->asMode(&m)) {
1045        return false;
1046    }
1047    return mode == m;
1048}
1049
1050///////////////////////////////////////////////////////////////////////////////
1051//////////// 16bit xfermode procs
1052
1053#ifdef SK_DEBUG
1054static bool require_255(SkPMColor src) { return SkGetPackedA32(src) == 0xFF; }
1055static bool require_0(SkPMColor src) { return SkGetPackedA32(src) == 0; }
1056#endif
1057
1058static uint16_t src_modeproc16_255(SkPMColor src, uint16_t dst) {
1059    SkASSERT(require_255(src));
1060    return SkPixel32ToPixel16(src);
1061}
1062
1063static uint16_t dst_modeproc16(SkPMColor src, uint16_t dst) {
1064    return dst;
1065}
1066
1067static uint16_t srcover_modeproc16_0(SkPMColor src, uint16_t dst) {
1068    SkASSERT(require_0(src));
1069    return dst;
1070}
1071
1072static uint16_t srcover_modeproc16_255(SkPMColor src, uint16_t dst) {
1073    SkASSERT(require_255(src));
1074    return SkPixel32ToPixel16(src);
1075}
1076
1077static uint16_t dstover_modeproc16_0(SkPMColor src, uint16_t dst) {
1078    SkASSERT(require_0(src));
1079    return dst;
1080}
1081
1082static uint16_t dstover_modeproc16_255(SkPMColor src, uint16_t dst) {
1083    SkASSERT(require_255(src));
1084    return dst;
1085}
1086
1087static uint16_t srcin_modeproc16_255(SkPMColor src, uint16_t dst) {
1088    SkASSERT(require_255(src));
1089    return SkPixel32ToPixel16(src);
1090}
1091
1092static uint16_t dstin_modeproc16_255(SkPMColor src, uint16_t dst) {
1093    SkASSERT(require_255(src));
1094    return dst;
1095}
1096
1097static uint16_t dstout_modeproc16_0(SkPMColor src, uint16_t dst) {
1098    SkASSERT(require_0(src));
1099    return dst;
1100}
1101
1102static uint16_t srcatop_modeproc16(SkPMColor src, uint16_t dst) {
1103    unsigned isa = 255 - SkGetPackedA32(src);
1104
1105    return SkPackRGB16(
1106           SkPacked32ToR16(src) + SkAlphaMulAlpha(SkGetPackedR16(dst), isa),
1107           SkPacked32ToG16(src) + SkAlphaMulAlpha(SkGetPackedG16(dst), isa),
1108           SkPacked32ToB16(src) + SkAlphaMulAlpha(SkGetPackedB16(dst), isa));
1109}
1110
1111static uint16_t srcatop_modeproc16_0(SkPMColor src, uint16_t dst) {
1112    SkASSERT(require_0(src));
1113    return dst;
1114}
1115
1116static uint16_t srcatop_modeproc16_255(SkPMColor src, uint16_t dst) {
1117    SkASSERT(require_255(src));
1118    return SkPixel32ToPixel16(src);
1119}
1120
1121static uint16_t dstatop_modeproc16_255(SkPMColor src, uint16_t dst) {
1122    SkASSERT(require_255(src));
1123    return dst;
1124}
1125
1126/*********
1127    darken and lighten boil down to this.
1128
1129    darken  = (1 - Sa) * Dc + min(Sc, Dc)
1130    lighten = (1 - Sa) * Dc + max(Sc, Dc)
1131
1132    if (Sa == 0) these become
1133        darken  = Dc + min(0, Dc) = 0
1134        lighten = Dc + max(0, Dc) = Dc
1135
1136    if (Sa == 1) these become
1137        darken  = min(Sc, Dc)
1138        lighten = max(Sc, Dc)
1139*/
1140
1141static uint16_t darken_modeproc16_0(SkPMColor src, uint16_t dst) {
1142    SkASSERT(require_0(src));
1143    return 0;
1144}
1145
1146static uint16_t darken_modeproc16_255(SkPMColor src, uint16_t dst) {
1147    SkASSERT(require_255(src));
1148    unsigned r = SkFastMin32(SkPacked32ToR16(src), SkGetPackedR16(dst));
1149    unsigned g = SkFastMin32(SkPacked32ToG16(src), SkGetPackedG16(dst));
1150    unsigned b = SkFastMin32(SkPacked32ToB16(src), SkGetPackedB16(dst));
1151    return SkPackRGB16(r, g, b);
1152}
1153
1154static uint16_t lighten_modeproc16_0(SkPMColor src, uint16_t dst) {
1155    SkASSERT(require_0(src));
1156    return dst;
1157}
1158
1159static uint16_t lighten_modeproc16_255(SkPMColor src, uint16_t dst) {
1160    SkASSERT(require_255(src));
1161    unsigned r = SkMax32(SkPacked32ToR16(src), SkGetPackedR16(dst));
1162    unsigned g = SkMax32(SkPacked32ToG16(src), SkGetPackedG16(dst));
1163    unsigned b = SkMax32(SkPacked32ToB16(src), SkGetPackedB16(dst));
1164    return SkPackRGB16(r, g, b);
1165}
1166
1167struct Proc16Rec {
1168    SkXfermodeProc16    fProc16_0;
1169    SkXfermodeProc16    fProc16_255;
1170    SkXfermodeProc16    fProc16_General;
1171};
1172
1173static const Proc16Rec gModeProcs16[] = {
1174    { NULL,                 NULL,                   NULL            }, // CLEAR
1175    { NULL,                 src_modeproc16_255,     NULL            },
1176    { dst_modeproc16,       dst_modeproc16,         dst_modeproc16  },
1177    { srcover_modeproc16_0, srcover_modeproc16_255, NULL            },
1178    { dstover_modeproc16_0, dstover_modeproc16_255, NULL            },
1179    { NULL,                 srcin_modeproc16_255,   NULL            },
1180    { NULL,                 dstin_modeproc16_255,   NULL            },
1181    { NULL,                 NULL,                   NULL            },// SRC_OUT
1182    { dstout_modeproc16_0,  NULL,                   NULL            },
1183    { srcatop_modeproc16_0, srcatop_modeproc16_255, srcatop_modeproc16  },
1184    { NULL,                 dstatop_modeproc16_255, NULL            },
1185    { NULL,                 NULL,                   NULL            }, // XOR
1186
1187    { NULL,                 NULL,                   NULL            }, // plus
1188    { NULL,                 NULL,                   NULL            }, // multiply
1189    { NULL,                 NULL,                   NULL            }, // screen
1190    { NULL,                 NULL,                   NULL            }, // overlay
1191    { darken_modeproc16_0,  darken_modeproc16_255,  NULL            }, // darken
1192    { lighten_modeproc16_0, lighten_modeproc16_255, NULL            }, // lighten
1193    { NULL,                 NULL,                   NULL            }, // colordodge
1194    { NULL,                 NULL,                   NULL            }, // colorburn
1195    { NULL,                 NULL,                   NULL            }, // hardlight
1196    { NULL,                 NULL,                   NULL            }, // softlight
1197    { NULL,                 NULL,                   NULL            }, // difference
1198    { NULL,                 NULL,                   NULL            }, // exclusion
1199};
1200
1201SkXfermodeProc16 SkXfermode::GetProc16(Mode mode, SkColor srcColor) {
1202    SkXfermodeProc16  proc16 = NULL;
1203    if ((unsigned)mode < kModeCount) {
1204        const Proc16Rec& rec = gModeProcs16[mode];
1205        unsigned a = SkColorGetA(srcColor);
1206
1207        if (0 == a) {
1208            proc16 = rec.fProc16_0;
1209        } else if (255 == a) {
1210            proc16 = rec.fProc16_255;
1211        } else {
1212            proc16 = rec.fProc16_General;
1213        }
1214    }
1215    return proc16;
1216}
1217
1218SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkXfermode)
1219    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkProcCoeffXfermode)
1220    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkClearXfermode)
1221    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSrcXfermode)
1222    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDstInXfermode)
1223    SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDstOutXfermode)
1224SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
1225