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