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 "SkColorPriv.h"
     12 #include "SkFlattenableBuffers.h"
     13 #include "SkMathPriv.h"
     14 #include "SkString.h"
     15 
     16 SK_DEFINE_INST_COUNT(SkXfermode)
     17 
     18 #define SkAlphaMulAlpha(a, b)   SkMulDiv255Round(a, b)
     19 
     20 #if 0
     21 // idea for higher precision blends in xfer procs (and slightly faster)
     22 // see DstATop as a probable caller
     23 static U8CPU mulmuldiv255round(U8CPU a, U8CPU b, U8CPU c, U8CPU d) {
     24     SkASSERT(a <= 255);
     25     SkASSERT(b <= 255);
     26     SkASSERT(c <= 255);
     27     SkASSERT(d <= 255);
     28     unsigned prod = SkMulS16(a, b) + SkMulS16(c, d) + 128;
     29     unsigned result = (prod + (prod >> 8)) >> 8;
     30     SkASSERT(result <= 255);
     31     return result;
     32 }
     33 #endif
     34 
     35 static inline unsigned saturated_add(unsigned a, unsigned b) {
     36     SkASSERT(a <= 255);
     37     SkASSERT(b <= 255);
     38     unsigned sum = a + b;
     39     if (sum > 255) {
     40         sum = 255;
     41     }
     42     return sum;
     43 }
     44 
     45 static inline int clamp_signed_byte(int n) {
     46     if (n < 0) {
     47         n = 0;
     48     } else if (n > 255) {
     49         n = 255;
     50     }
     51     return n;
     52 }
     53 
     54 static inline int clamp_div255round(int prod) {
     55     if (prod <= 0) {
     56         return 0;
     57     } else if (prod >= 255*255) {
     58         return 255;
     59     } else {
     60         return SkDiv255Round(prod);
     61     }
     62 }
     63 
     64 static inline int clamp_max(int value, int max) {
     65     if (value > max) {
     66         value = max;
     67     }
     68     return value;
     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     if(n < 0) {
    475        *r = L + SkMulDiv(*r - L, L, L - n);
    476        *g = L + SkMulDiv(*g - L, L, L - n);
    477        *b = L + SkMulDiv(*b - L, L, L - n);
    478     }
    479 
    480     if (x > a) {
    481        *r = L + SkMulDiv(*r - L, a - L, x - L);
    482        *g = L + SkMulDiv(*g - L, a - L, x - L);
    483        *b = L + SkMulDiv(*b - L, a - L, x - L);
    484     }
    485 }
    486 
    487 static inline void SetLum(int* r, int* g, int* b, int a, int l) {
    488   int d = l - Lum(*r, *g, *b);
    489   *r +=  d;
    490   *g +=  d;
    491   *b +=  d;
    492 
    493   clipColor(r, g, b, a);
    494 }
    495 
    496 // non-separable blend modes are done in non-premultiplied alpha
    497 #define  blendfunc_nonsep_byte(sc, dc, sa, da, blendval) \
    498   clamp_div255round(sc * (255 - da) +  dc * (255 - sa) + blendval)
    499 
    500 // kHue_Mode
    501 // B(Cb, Cs) = SetLum(SetSat(Cs, Sat(Cb)), Lum(Cb))
    502 // Create a color with the hue of the source color and the saturation and luminosity of the backdrop color.
    503 static SkPMColor hue_modeproc(SkPMColor src, SkPMColor dst) {
    504     int sr = SkGetPackedR32(src);
    505     int sg = SkGetPackedG32(src);
    506     int sb = SkGetPackedB32(src);
    507     int sa = SkGetPackedA32(src);
    508 
    509     int dr = SkGetPackedR32(dst);
    510     int dg = SkGetPackedG32(dst);
    511     int db = SkGetPackedB32(dst);
    512     int da = SkGetPackedA32(dst);
    513     int Sr, Sg, Sb;
    514 
    515     if(sa && da) {
    516         Sr = sr * sa;
    517         Sg = sg * sa;
    518         Sb = sb * sa;
    519         SetSat(&Sr, &Sg, &Sb, Sat(dr, dg, db) * sa);
    520         SetLum(&Sr, &Sg, &Sb, sa * da, Lum(dr, dg, db) * sa);
    521     } else {
    522         Sr = 0;
    523         Sg = 0;
    524         Sb = 0;
    525     }
    526 
    527     int a = srcover_byte(sa, da);
    528     int r = blendfunc_nonsep_byte(sr, dr, sa, da, Sr);
    529     int g = blendfunc_nonsep_byte(sg, dg, sa, da, Sg);
    530     int b = blendfunc_nonsep_byte(sb, db, sa, da, Sb);
    531     return SkPackARGB32(a, r, g, b);
    532 }
    533 
    534 // kSaturation_Mode
    535 // B(Cb, Cs) = SetLum(SetSat(Cb, Sat(Cs)), Lum(Cb))
    536 // Create a color with the saturation of the source color and the hue and luminosity of the backdrop color.
    537 static SkPMColor saturation_modeproc(SkPMColor src, SkPMColor dst) {
    538     int sr = SkGetPackedR32(src);
    539     int sg = SkGetPackedG32(src);
    540     int sb = SkGetPackedB32(src);
    541     int sa = SkGetPackedA32(src);
    542 
    543     int dr = SkGetPackedR32(dst);
    544     int dg = SkGetPackedG32(dst);
    545     int db = SkGetPackedB32(dst);
    546     int da = SkGetPackedA32(dst);
    547     int Dr, Dg, Db;
    548 
    549     if(sa && da) {
    550         Dr = dr * sa;
    551         Dg = dg * sa;
    552         Db = db * sa;
    553         SetSat(&Dr, &Dg, &Db, Sat(sr, sg, sb) * da);
    554         SetLum(&Dr, &Dg, &Db, sa * da, Lum(dr, dg, db) * sa);
    555     } else {
    556         Dr = 0;
    557         Dg = 0;
    558         Db = 0;
    559     }
    560 
    561     int a = srcover_byte(sa, da);
    562     int r = blendfunc_nonsep_byte(sr, dr, sa, da, Dr);
    563     int g = blendfunc_nonsep_byte(sg, dg, sa, da, Dg);
    564     int b = blendfunc_nonsep_byte(sb, db, sa, da, Db);
    565     return SkPackARGB32(a, r, g, b);
    566 }
    567 
    568 // kColor_Mode
    569 // B(Cb, Cs) = SetLum(Cs, Lum(Cb))
    570 // Create a color with the hue and saturation of the source color and the luminosity of the backdrop color.
    571 static SkPMColor color_modeproc(SkPMColor src, SkPMColor dst) {
    572     int sr = SkGetPackedR32(src);
    573     int sg = SkGetPackedG32(src);
    574     int sb = SkGetPackedB32(src);
    575     int sa = SkGetPackedA32(src);
    576 
    577     int dr = SkGetPackedR32(dst);
    578     int dg = SkGetPackedG32(dst);
    579     int db = SkGetPackedB32(dst);
    580     int da = SkGetPackedA32(dst);
    581     int Sr, Sg, Sb;
    582 
    583     if(sa && da) {
    584         Sr = sr * da;
    585         Sg = sg * da;
    586         Sb = sb * da;
    587         SetLum(&Sr, &Sg, &Sb, sa * da, Lum(dr, dg, db) * sa);
    588     } else {
    589         Sr = 0;
    590         Sg = 0;
    591         Sb = 0;
    592     }
    593 
    594     int a = srcover_byte(sa, da);
    595     int r = blendfunc_nonsep_byte(sr, dr, sa, da, Sr);
    596     int g = blendfunc_nonsep_byte(sg, dg, sa, da, Sg);
    597     int b = blendfunc_nonsep_byte(sb, db, sa, da, Sb);
    598     return SkPackARGB32(a, r, g, b);
    599 }
    600 
    601 // kLuminosity_Mode
    602 // B(Cb, Cs) = SetLum(Cb, Lum(Cs))
    603 // Create a color with the luminosity of the source color and the hue and saturation of the backdrop color.
    604 static SkPMColor luminosity_modeproc(SkPMColor src, SkPMColor dst) {
    605     int sr = SkGetPackedR32(src);
    606     int sg = SkGetPackedG32(src);
    607     int sb = SkGetPackedB32(src);
    608     int sa = SkGetPackedA32(src);
    609 
    610     int dr = SkGetPackedR32(dst);
    611     int dg = SkGetPackedG32(dst);
    612     int db = SkGetPackedB32(dst);
    613     int da = SkGetPackedA32(dst);
    614     int Dr, Dg, Db;
    615 
    616     if(sa && da) {
    617         Dr = dr * sa;
    618         Dg = dg * sa;
    619         Db = db * sa;
    620         SetLum(&Dr, &Dg, &Db, sa * da, Lum(sr, sg, sb) * da);
    621     } else {
    622         Dr = 0;
    623         Dg = 0;
    624         Db = 0;
    625     }
    626 
    627     int a = srcover_byte(sa, da);
    628     int r = blendfunc_nonsep_byte(sr, dr, sa, da, Dr);
    629     int g = blendfunc_nonsep_byte(sg, dg, sa, da, Dg);
    630     int b = blendfunc_nonsep_byte(sb, db, sa, da, Db);
    631     return SkPackARGB32(a, r, g, b);
    632 }
    633 
    634 
    635 struct ProcCoeff {
    636     SkXfermodeProc      fProc;
    637     SkXfermode::Coeff   fSC;
    638     SkXfermode::Coeff   fDC;
    639 };
    640 
    641 #define CANNOT_USE_COEFF    SkXfermode::Coeff(-1)
    642 
    643 static const ProcCoeff gProcCoeffs[] = {
    644     { clear_modeproc,   SkXfermode::kZero_Coeff,    SkXfermode::kZero_Coeff },
    645     { src_modeproc,     SkXfermode::kOne_Coeff,     SkXfermode::kZero_Coeff },
    646     { dst_modeproc,     SkXfermode::kZero_Coeff,    SkXfermode::kOne_Coeff },
    647     { srcover_modeproc, SkXfermode::kOne_Coeff,     SkXfermode::kISA_Coeff },
    648     { dstover_modeproc, SkXfermode::kIDA_Coeff,     SkXfermode::kOne_Coeff },
    649     { srcin_modeproc,   SkXfermode::kDA_Coeff,      SkXfermode::kZero_Coeff },
    650     { dstin_modeproc,   SkXfermode::kZero_Coeff,    SkXfermode::kSA_Coeff },
    651     { srcout_modeproc,  SkXfermode::kIDA_Coeff,     SkXfermode::kZero_Coeff },
    652     { dstout_modeproc,  SkXfermode::kZero_Coeff,    SkXfermode::kISA_Coeff },
    653     { srcatop_modeproc, SkXfermode::kDA_Coeff,      SkXfermode::kISA_Coeff },
    654     { dstatop_modeproc, SkXfermode::kIDA_Coeff,     SkXfermode::kSA_Coeff },
    655     { xor_modeproc,     SkXfermode::kIDA_Coeff,     SkXfermode::kISA_Coeff },
    656 
    657     { plus_modeproc,    SkXfermode::kOne_Coeff,     SkXfermode::kOne_Coeff },
    658     { modulate_modeproc,SkXfermode::kZero_Coeff,    SkXfermode::kSC_Coeff },
    659     { screen_modeproc,  SkXfermode::kOne_Coeff,     SkXfermode::kISC_Coeff },
    660     { overlay_modeproc,     CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
    661     { darken_modeproc,      CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
    662     { lighten_modeproc,     CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
    663     { colordodge_modeproc,  CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
    664     { colorburn_modeproc,   CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
    665     { hardlight_modeproc,   CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
    666     { softlight_modeproc,   CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
    667     { difference_modeproc,  CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
    668     { exclusion_modeproc,   CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
    669     { multiply_modeproc,    CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
    670     { hue_modeproc,         CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
    671     { saturation_modeproc,  CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
    672     { color_modeproc,       CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
    673     { luminosity_modeproc,  CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
    674 };
    675 
    676 ///////////////////////////////////////////////////////////////////////////////
    677 
    678 bool SkXfermode::asCoeff(Coeff* src, Coeff* dst) const {
    679     return false;
    680 }
    681 
    682 bool SkXfermode::asMode(Mode* mode) const {
    683     return false;
    684 }
    685 
    686 bool SkXfermode::asNewEffectOrCoeff(GrContext*, GrEffectRef**, Coeff* src, Coeff* dst, GrTexture*) const {
    687     return this->asCoeff(src, dst);
    688 }
    689 
    690 bool SkXfermode::AsNewEffectOrCoeff(SkXfermode* xfermode,
    691                                     GrContext* context,
    692                                     GrEffectRef** effect,
    693                                     Coeff* src,
    694                                     Coeff* dst,
    695                                     GrTexture* background) {
    696     if (NULL == xfermode) {
    697         return ModeAsCoeff(kSrcOver_Mode, src, dst);
    698     } else {
    699         return xfermode->asNewEffectOrCoeff(context, effect, src, dst, background);
    700     }
    701 }
    702 
    703 SkPMColor SkXfermode::xferColor(SkPMColor src, SkPMColor dst) const{
    704     // no-op. subclasses should override this
    705     return dst;
    706 }
    707 
    708 void SkXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
    709                         const SkPMColor* SK_RESTRICT src, int count,
    710                         const SkAlpha* SK_RESTRICT aa) const {
    711     SkASSERT(dst && src && count >= 0);
    712 
    713     if (NULL == aa) {
    714         for (int i = count - 1; i >= 0; --i) {
    715             dst[i] = this->xferColor(src[i], dst[i]);
    716         }
    717     } else {
    718         for (int i = count - 1; i >= 0; --i) {
    719             unsigned a = aa[i];
    720             if (0 != a) {
    721                 SkPMColor dstC = dst[i];
    722                 SkPMColor C = this->xferColor(src[i], dstC);
    723                 if (0xFF != a) {
    724                     C = SkFourByteInterp(C, dstC, a);
    725                 }
    726                 dst[i] = C;
    727             }
    728         }
    729     }
    730 }
    731 
    732 void SkXfermode::xfer16(uint16_t* dst,
    733                         const SkPMColor* SK_RESTRICT src, int count,
    734                         const SkAlpha* SK_RESTRICT aa) const {
    735     SkASSERT(dst && src && count >= 0);
    736 
    737     if (NULL == aa) {
    738         for (int i = count - 1; i >= 0; --i) {
    739             SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
    740             dst[i] = SkPixel32ToPixel16_ToU16(this->xferColor(src[i], dstC));
    741         }
    742     } else {
    743         for (int i = count - 1; i >= 0; --i) {
    744             unsigned a = aa[i];
    745             if (0 != a) {
    746                 SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
    747                 SkPMColor C = this->xferColor(src[i], dstC);
    748                 if (0xFF != a) {
    749                     C = SkFourByteInterp(C, dstC, a);
    750                 }
    751                 dst[i] = SkPixel32ToPixel16_ToU16(C);
    752             }
    753         }
    754     }
    755 }
    756 
    757 void SkXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
    758                         const SkPMColor src[], int count,
    759                         const SkAlpha* SK_RESTRICT aa) const {
    760     SkASSERT(dst && src && count >= 0);
    761 
    762     if (NULL == aa) {
    763         for (int i = count - 1; i >= 0; --i) {
    764             SkPMColor res = this->xferColor(src[i], (dst[i] << SK_A32_SHIFT));
    765             dst[i] = SkToU8(SkGetPackedA32(res));
    766         }
    767     } else {
    768         for (int i = count - 1; i >= 0; --i) {
    769             unsigned a = aa[i];
    770             if (0 != a) {
    771                 SkAlpha dstA = dst[i];
    772                 unsigned A = SkGetPackedA32(this->xferColor(src[i],
    773                                             (SkPMColor)(dstA << SK_A32_SHIFT)));
    774                 if (0xFF != a) {
    775                     A = SkAlphaBlend(A, dstA, SkAlpha255To256(a));
    776                 }
    777                 dst[i] = SkToU8(A);
    778             }
    779         }
    780     }
    781 }
    782 
    783 ///////////////////////////////////////////////////////////////////////////////
    784 
    785 void SkProcXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
    786                             const SkPMColor* SK_RESTRICT src, int count,
    787                             const SkAlpha* SK_RESTRICT aa) const {
    788     SkASSERT(dst && src && count >= 0);
    789 
    790     SkXfermodeProc proc = fProc;
    791 
    792     if (NULL != proc) {
    793         if (NULL == aa) {
    794             for (int i = count - 1; i >= 0; --i) {
    795                 dst[i] = proc(src[i], dst[i]);
    796             }
    797         } else {
    798             for (int i = count - 1; i >= 0; --i) {
    799                 unsigned a = aa[i];
    800                 if (0 != a) {
    801                     SkPMColor dstC = dst[i];
    802                     SkPMColor C = proc(src[i], dstC);
    803                     if (a != 0xFF) {
    804                         C = SkFourByteInterp(C, dstC, a);
    805                     }
    806                     dst[i] = C;
    807                 }
    808             }
    809         }
    810     }
    811 }
    812 
    813 void SkProcXfermode::xfer16(uint16_t* SK_RESTRICT dst,
    814                             const SkPMColor* SK_RESTRICT src, int count,
    815                             const SkAlpha* SK_RESTRICT aa) const {
    816     SkASSERT(dst && src && count >= 0);
    817 
    818     SkXfermodeProc proc = fProc;
    819 
    820     if (NULL != proc) {
    821         if (NULL == aa) {
    822             for (int i = count - 1; i >= 0; --i) {
    823                 SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
    824                 dst[i] = SkPixel32ToPixel16_ToU16(proc(src[i], dstC));
    825             }
    826         } else {
    827             for (int i = count - 1; i >= 0; --i) {
    828                 unsigned a = aa[i];
    829                 if (0 != a) {
    830                     SkPMColor dstC = SkPixel16ToPixel32(dst[i]);
    831                     SkPMColor C = proc(src[i], dstC);
    832                     if (0xFF != a) {
    833                         C = SkFourByteInterp(C, dstC, a);
    834                     }
    835                     dst[i] = SkPixel32ToPixel16_ToU16(C);
    836                 }
    837             }
    838         }
    839     }
    840 }
    841 
    842 void SkProcXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
    843                             const SkPMColor* SK_RESTRICT src, int count,
    844                             const SkAlpha* SK_RESTRICT aa) const {
    845     SkASSERT(dst && src && count >= 0);
    846 
    847     SkXfermodeProc proc = fProc;
    848 
    849     if (NULL != proc) {
    850         if (NULL == aa) {
    851             for (int i = count - 1; i >= 0; --i) {
    852                 SkPMColor res = proc(src[i], dst[i] << SK_A32_SHIFT);
    853                 dst[i] = SkToU8(SkGetPackedA32(res));
    854             }
    855         } else {
    856             for (int i = count - 1; i >= 0; --i) {
    857                 unsigned a = aa[i];
    858                 if (0 != a) {
    859                     SkAlpha dstA = dst[i];
    860                     SkPMColor res = proc(src[i], dstA << SK_A32_SHIFT);
    861                     unsigned A = SkGetPackedA32(res);
    862                     if (0xFF != a) {
    863                         A = SkAlphaBlend(A, dstA, SkAlpha255To256(a));
    864                     }
    865                     dst[i] = SkToU8(A);
    866                 }
    867             }
    868         }
    869     }
    870 }
    871 
    872 SkProcXfermode::SkProcXfermode(SkFlattenableReadBuffer& buffer)
    873         : SkXfermode(buffer) {
    874     fProc = NULL;
    875     if (!buffer.isCrossProcess()) {
    876         fProc = (SkXfermodeProc)buffer.readFunctionPtr();
    877     }
    878 }
    879 
    880 void SkProcXfermode::flatten(SkFlattenableWriteBuffer& buffer) const {
    881     this->INHERITED::flatten(buffer);
    882     if (!buffer.isCrossProcess()) {
    883         buffer.writeFunctionPtr((void*)fProc);
    884     }
    885 }
    886 
    887 #ifdef SK_DEVELOPER
    888 void SkProcXfermode::toString(SkString* str) const {
    889     str->appendf("SkProcXfermode: %p", fProc);
    890 }
    891 #endif
    892 
    893 //////////////////////////////////////////////////////////////////////////////
    894 
    895 #if SK_SUPPORT_GPU
    896 
    897 #include "GrEffect.h"
    898 #include "GrEffectUnitTest.h"
    899 #include "GrTBackendEffectFactory.h"
    900 #include "gl/GrGLEffect.h"
    901 #include "gl/GrGLEffectMatrix.h"
    902 
    903 /**
    904  * GrEffect that implements the all the separable xfer modes that cannot be expressed as Coeffs.
    905  */
    906 class XferEffect : public GrEffect {
    907 public:
    908     static bool IsSupportedMode(SkXfermode::Mode mode) {
    909         return mode > SkXfermode::kLastCoeffMode && mode <= SkXfermode::kLastMode;
    910     }
    911 
    912     static GrEffectRef* Create(SkXfermode::Mode mode, GrTexture* background) {
    913         if (!IsSupportedMode(mode)) {
    914             return NULL;
    915         } else {
    916             AutoEffectUnref effect(SkNEW_ARGS(XferEffect, (mode, background)));
    917             return CreateEffectRef(effect);
    918         }
    919     }
    920 
    921     virtual void getConstantColorComponents(GrColor* color,
    922                                             uint32_t* validFlags) const SK_OVERRIDE {
    923         *validFlags = 0;
    924     }
    925 
    926     virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE {
    927         return GrTBackendEffectFactory<XferEffect>::getInstance();
    928     }
    929 
    930     static const char* Name() { return "XferEffect"; }
    931 
    932     SkXfermode::Mode mode() const { return fMode; }
    933     const GrTextureAccess&  backgroundAccess() const { return fBackgroundAccess; }
    934 
    935     class GLEffect : public GrGLEffect {
    936     public:
    937         GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&)
    938             : GrGLEffect(factory )
    939             , fBackgroundEffectMatrix(kCoordsType) {
    940         }
    941         virtual void emitCode(GrGLShaderBuilder* builder,
    942                               const GrDrawEffect& drawEffect,
    943                               EffectKey key,
    944                               const char* outputColor,
    945                               const char* inputColor,
    946                               const TextureSamplerArray& samplers) SK_OVERRIDE {
    947             SkXfermode::Mode mode = drawEffect.castEffect<XferEffect>().mode();
    948             const GrTexture* backgroundTex = drawEffect.castEffect<XferEffect>().backgroundAccess().getTexture();
    949             const char* dstColor;
    950             if (backgroundTex) {
    951                 const char* bgCoords;
    952                 GrSLType bgCoordsType = fBackgroundEffectMatrix.emitCode(builder, key, &bgCoords, NULL, "BG");
    953                 dstColor = "bgColor";
    954                 builder->fsCodeAppendf("\t\tvec4 %s = ", dstColor);
    955                 builder->appendTextureLookup(GrGLShaderBuilder::kFragment_ShaderType,
    956                                              samplers[0],
    957                                              bgCoords,
    958                                              bgCoordsType);
    959                 builder->fsCodeAppendf(";\n");
    960             } else {
    961                 dstColor = builder->dstColor();
    962             }
    963             GrAssert(NULL != dstColor);
    964 
    965             // We don't try to optimize for this case at all
    966             if (NULL == inputColor) {
    967                 builder->fsCodeAppendf("\t\tconst vec4 ones = %s;\n", GrGLSLOnesVecf(4));
    968                 inputColor = "ones";
    969             }
    970             builder->fsCodeAppendf("\t\t// SkXfermode::Mode: %s\n", SkXfermode::ModeName(mode));
    971 
    972             // These all perform src-over on the alpha channel.
    973             builder->fsCodeAppendf("\t\t%s.a = %s.a + (1.0 - %s.a) * %s.a;\n",
    974                                     outputColor, inputColor, inputColor, dstColor);
    975 
    976             switch (mode) {
    977                 case SkXfermode::kOverlay_Mode:
    978                     // Overlay is Hard-Light with the src and dst reversed
    979                     HardLight(builder, outputColor, dstColor, inputColor);
    980                     break;
    981                 case SkXfermode::kDarken_Mode:
    982                     builder->fsCodeAppendf("\t\t%s.rgb = min((1.0 - %s.a) * %s.rgb + %s.rgb, "
    983                                                             "(1.0 - %s.a) * %s.rgb + %s.rgb);\n",
    984                                             outputColor,
    985                                             inputColor, dstColor, inputColor,
    986                                             dstColor, inputColor, dstColor);
    987                     break;
    988                 case SkXfermode::kLighten_Mode:
    989                     builder->fsCodeAppendf("\t\t%s.rgb = max((1.0 - %s.a) * %s.rgb + %s.rgb, "
    990                                                             "(1.0 - %s.a) * %s.rgb + %s.rgb);\n",
    991                                             outputColor,
    992                                             inputColor, dstColor, inputColor,
    993                                             dstColor, inputColor, dstColor);
    994                     break;
    995                 case SkXfermode::kColorDodge_Mode:
    996                     ColorDodgeComponent(builder, outputColor, inputColor, dstColor, 'r');
    997                     ColorDodgeComponent(builder, outputColor, inputColor, dstColor, 'g');
    998                     ColorDodgeComponent(builder, outputColor, inputColor, dstColor, 'b');
    999                     break;
   1000                 case SkXfermode::kColorBurn_Mode:
   1001                     ColorBurnComponent(builder, outputColor, inputColor, dstColor, 'r');
   1002                     ColorBurnComponent(builder, outputColor, inputColor, dstColor, 'g');
   1003                     ColorBurnComponent(builder, outputColor, inputColor, dstColor, 'b');
   1004                     break;
   1005                 case SkXfermode::kHardLight_Mode:
   1006                     HardLight(builder, outputColor, inputColor, dstColor);
   1007                     break;
   1008                 case SkXfermode::kSoftLight_Mode:
   1009                     builder->fsCodeAppendf("\t\tif (0.0 == %s.a) {\n", dstColor);
   1010                     builder->fsCodeAppendf("\t\t\t%s.rgba = %s;\n", outputColor, inputColor);
   1011                     builder->fsCodeAppendf("\t\t} else {\n");
   1012                     SoftLightComponentPosDstAlpha(builder, outputColor, inputColor, dstColor, 'r');
   1013                     SoftLightComponentPosDstAlpha(builder, outputColor, inputColor, dstColor, 'g');
   1014                     SoftLightComponentPosDstAlpha(builder, outputColor, inputColor, dstColor, 'b');
   1015                     builder->fsCodeAppendf("\t\t}\n");
   1016                     break;
   1017                 case SkXfermode::kDifference_Mode:
   1018                     builder->fsCodeAppendf("\t\t%s.rgb = %s.rgb + %s.rgb -"
   1019                                                        "2.0 * min(%s.rgb * %s.a, %s.rgb * %s.a);\n",
   1020                                            outputColor, inputColor, dstColor, inputColor, dstColor,
   1021                                            dstColor, inputColor);
   1022                     break;
   1023                 case SkXfermode::kExclusion_Mode:
   1024                     builder->fsCodeAppendf("\t\t%s.rgb = %s.rgb + %s.rgb - "
   1025                                                         "2.0 * %s.rgb * %s.rgb;\n",
   1026                                            outputColor, dstColor, inputColor, dstColor, inputColor);
   1027                     break;
   1028                 case SkXfermode::kMultiply_Mode:
   1029                     builder->fsCodeAppendf("\t\t%s.rgb = (1.0 - %s.a) * %s.rgb + "
   1030                                                         "(1.0 - %s.a) * %s.rgb + "
   1031                                                          "%s.rgb * %s.rgb;\n",
   1032                                            outputColor, inputColor, dstColor, dstColor, inputColor,
   1033                                            inputColor, dstColor);
   1034                     break;
   1035                 case SkXfermode::kHue_Mode: {
   1036                     //  SetLum(SetSat(S * Da, Sat(D * Sa)), Sa*Da, D*Sa) + (1 - Sa) * D + (1 - Da) * S
   1037                     SkString setSat, setLum;
   1038                     AddSatFunction(builder, &setSat);
   1039                     AddLumFunction(builder, &setLum);
   1040                     builder->fsCodeAppendf("\t\tvec4 dstSrcAlpha = %s * %s.a;\n",
   1041                                            dstColor, inputColor);
   1042                     builder->fsCodeAppendf("\t\t%s.rgb = %s(%s(%s.rgb * %s.a, dstSrcAlpha.rgb), dstSrcAlpha.a, dstSrcAlpha.rgb);\n",
   1043                                            outputColor, setLum.c_str(), setSat.c_str(), inputColor,
   1044                                            dstColor);
   1045                     builder->fsCodeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n",
   1046                                            outputColor, inputColor, dstColor, dstColor, inputColor);
   1047                     break;
   1048                 }
   1049                 case SkXfermode::kSaturation_Mode: {
   1050                     // SetLum(SetSat(D * Sa, Sat(S * Da)), Sa*Da, D*Sa)) + (1 - Sa) * D + (1 - Da) * S
   1051                     SkString setSat, setLum;
   1052                     AddSatFunction(builder, &setSat);
   1053                     AddLumFunction(builder, &setLum);
   1054                     builder->fsCodeAppendf("\t\tvec4 dstSrcAlpha = %s * %s.a;\n",
   1055                                            dstColor, inputColor);
   1056                     builder->fsCodeAppendf("\t\t%s.rgb = %s(%s(dstSrcAlpha.rgb, %s.rgb * %s.a), dstSrcAlpha.a, dstSrcAlpha.rgb);\n",
   1057                                            outputColor, setLum.c_str(), setSat.c_str(), inputColor,
   1058                                            dstColor);
   1059                     builder->fsCodeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n",
   1060                                            outputColor, inputColor, dstColor, dstColor, inputColor);
   1061                     break;
   1062                 }
   1063                 case SkXfermode::kColor_Mode: {
   1064                     //  SetLum(S * Da, Sa* Da, D * Sa) + (1 - Sa) * D + (1 - Da) * S
   1065                     SkString setLum;
   1066                     AddLumFunction(builder, &setLum);
   1067                     builder->fsCodeAppendf("\t\tvec4 srcDstAlpha = %s * %s.a;\n",
   1068                                            inputColor, dstColor);
   1069                     builder->fsCodeAppendf("\t\t%s.rgb = %s(srcDstAlpha.rgb, srcDstAlpha.a, %s.rgb * %s.a);\n",
   1070                                            outputColor, setLum.c_str(), dstColor, inputColor);
   1071                     builder->fsCodeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n",
   1072                                            outputColor, inputColor, dstColor, dstColor, inputColor);
   1073                     break;
   1074                 }
   1075                 case SkXfermode::kLuminosity_Mode: {
   1076                     //  SetLum(D * Sa, Sa* Da, S * Da) + (1 - Sa) * D + (1 - Da) * S
   1077                     SkString setLum;
   1078                     AddLumFunction(builder, &setLum);
   1079                     builder->fsCodeAppendf("\t\tvec4 srcDstAlpha = %s * %s.a;\n",
   1080                                            inputColor, dstColor);
   1081                     builder->fsCodeAppendf("\t\t%s.rgb = %s(%s.rgb * %s.a, srcDstAlpha.a, srcDstAlpha.rgb);\n",
   1082                                            outputColor, setLum.c_str(), dstColor, inputColor);
   1083                     builder->fsCodeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n",
   1084                                            outputColor, inputColor, dstColor, dstColor, inputColor);
   1085                     break;
   1086                 }
   1087                 default:
   1088                     GrCrash("Unknown XferEffect mode.");
   1089                     break;
   1090             }
   1091         }
   1092 
   1093         static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) {
   1094             const XferEffect& xfer = drawEffect.castEffect<XferEffect>();
   1095             GrTexture* bgTex = xfer.backgroundAccess().getTexture();
   1096             EffectKey bgKey = 0;
   1097             if (bgTex) {
   1098                 bgKey = GrGLEffectMatrix::GenKey(GrEffect::MakeDivByTextureWHMatrix(bgTex),
   1099                                                  drawEffect,
   1100                                                  GLEffect::kCoordsType,
   1101                                                  bgTex);
   1102             }
   1103             EffectKey modeKey = xfer.mode() << GrGLEffectMatrix::kKeyBits;
   1104             return modeKey | bgKey;
   1105         }
   1106 
   1107         virtual void setData(const GrGLUniformManager& uman, const GrDrawEffect& drawEffect) SK_OVERRIDE {
   1108             const XferEffect& xfer = drawEffect.castEffect<XferEffect>();
   1109             GrTexture* bgTex = xfer.backgroundAccess().getTexture();
   1110             if (bgTex) {
   1111                 fBackgroundEffectMatrix.setData(uman,
   1112                                                 GrEffect::MakeDivByTextureWHMatrix(bgTex),
   1113                                                 drawEffect,
   1114                                                 bgTex);
   1115             }
   1116         }
   1117 
   1118     private:
   1119         static void HardLight(GrGLShaderBuilder* builder,
   1120                               const char* final,
   1121                               const char* src,
   1122                               const char* dst) {
   1123             static const char kComponents[] = {'r', 'g', 'b'};
   1124             for (size_t i = 0; i < SK_ARRAY_COUNT(kComponents); ++i) {
   1125                 char component = kComponents[i];
   1126                 builder->fsCodeAppendf("\t\tif (2.0 * %s.%c <= %s.a) {\n", src, component, src);
   1127                 builder->fsCodeAppendf("\t\t\t%s.%c = 2.0 * %s.%c * %s.%c;\n", final, component, src, component, dst, component);
   1128                 builder->fsCodeAppend("\t\t} else {\n");
   1129                 builder->fsCodeAppendf("\t\t\t%s.%c = %s.a * %s.a - 2.0 * (%s.a - %s.%c) * (%s.a - %s.%c);\n",
   1130                                        final, component, src, dst, dst, dst, component, src, src, component);
   1131                 builder->fsCodeAppend("\t\t}\n");
   1132             }
   1133             builder->fsCodeAppendf("\t\t%s.rgb += %s.rgb * (1.0 - %s.a) + %s.rgb * (1.0 - %s.a);\n",
   1134                                    final, src, dst, dst, src);
   1135         }
   1136 
   1137         // Does one component of color-dodge
   1138         static void ColorDodgeComponent(GrGLShaderBuilder* builder,
   1139                                         const char* final,
   1140                                         const char* src,
   1141                                         const char* dst,
   1142                                         const char component) {
   1143             builder->fsCodeAppendf("\t\tif (0.0 == %s.%c) {\n", dst, component);
   1144             builder->fsCodeAppendf("\t\t\t%s.%c = %s.%c * (1.0 - %s.a);\n",
   1145                                    final, component, src, component, dst);
   1146             builder->fsCodeAppend("\t\t} else {\n");
   1147             builder->fsCodeAppendf("\t\t\tfloat d = %s.a - %s.%c;\n", src, src, component);
   1148             builder->fsCodeAppend("\t\t\tif (0.0 == d) {\n");
   1149             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",
   1150                                    final, component, src, dst, src, component, dst, dst, component,
   1151                                    src);
   1152             builder->fsCodeAppend("\t\t\t} else {\n");
   1153             builder->fsCodeAppendf("\t\t\t\td = min(%s.a, %s.%c * %s.a / d);\n",
   1154                                    dst, dst, component, src);
   1155             builder->fsCodeAppendf("\t\t\t\t%s.%c = d * %s.a + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);\n",
   1156                                    final, component, src, src, component, dst, dst, component, src);
   1157             builder->fsCodeAppend("\t\t\t}\n");
   1158             builder->fsCodeAppend("\t\t}\n");
   1159         }
   1160 
   1161         // Does one component of color-burn
   1162         static void ColorBurnComponent(GrGLShaderBuilder* builder,
   1163                                        const char* final,
   1164                                        const char* src,
   1165                                        const char* dst,
   1166                                        const char component) {
   1167             builder->fsCodeAppendf("\t\tif (%s.a == %s.%c) {\n", dst, dst, component);
   1168             builder->fsCodeAppendf("\t\t\t%s.%c = %s.a * %s.a + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);\n",
   1169                                    final, component, src, dst, src, component, dst, dst, component,
   1170                                    src);
   1171             builder->fsCodeAppendf("\t\t} else if (0.0 == %s.%c) {\n", src, component);
   1172             builder->fsCodeAppendf("\t\t\t%s.%c = %s.%c * (1.0 - %s.a);\n",
   1173                                    final, component, dst, component, src);
   1174             builder->fsCodeAppend("\t\t} else {\n");
   1175             builder->fsCodeAppendf("\t\t\tfloat d = max(0.0, %s.a - (%s.a - %s.%c) * %s.a / %s.%c);\n",
   1176                                    dst, dst, dst, component, src, src, component);
   1177             builder->fsCodeAppendf("\t\t\t%s.%c = %s.a * d + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);\n",
   1178                                    final, component, src, src, component, dst, dst, component, src);
   1179             builder->fsCodeAppend("\t\t}\n");
   1180         }
   1181 
   1182         // Does one component of soft-light. Caller should have already checked that dst alpha > 0.
   1183         static void SoftLightComponentPosDstAlpha(GrGLShaderBuilder* builder,
   1184                                                   const char* final,
   1185                                                   const char* src,
   1186                                                   const char* dst,
   1187                                                   const char component) {
   1188             // if (2S < Sa)
   1189             builder->fsCodeAppendf("\t\t\tif (2.0 * %s.%c <= %s.a) {\n", src, component, src);
   1190             // (D^2 (Sa-2 S))/Da+(1-Da) S+D (-Sa+2 S+1)
   1191             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",
   1192                                    final, component, dst, component, dst, component, src, src,
   1193                                    component, dst, dst, src, component, dst, component, src, src,
   1194                                    component);
   1195             // else if (4D < Da)
   1196             builder->fsCodeAppendf("\t\t\t} else if (4.0 * %s.%c <= %s.a) {\n",
   1197                                    dst, component, dst);
   1198             builder->fsCodeAppendf("\t\t\t\tfloat DSqd = %s.%c * %s.%c;\n",
   1199                                    dst, component, dst, component);
   1200             builder->fsCodeAppendf("\t\t\t\tfloat DCub = DSqd * %s.%c;\n", dst, component);
   1201             builder->fsCodeAppendf("\t\t\t\tfloat DaSqd = %s.a * %s.a;\n", dst, dst);
   1202             builder->fsCodeAppendf("\t\t\t\tfloat DaCub = DaSqd * %s.a;\n", dst);
   1203             // (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
   1204             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",
   1205                                    final, component, src, component, src, component, dst, component,
   1206                                    src, src, component, dst, src, src, component, src, src,
   1207                                    component);
   1208             builder->fsCodeAppendf("\t\t\t} else {\n");
   1209             // -sqrt(Da * D) (Sa-2 S)-Da S+D (Sa-2 S+1)+S
   1210             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",
   1211                                     final, component, dst, dst, component, src, src, component, dst,
   1212                                     src, component, dst, component, src, src, component, src,
   1213                                     component);
   1214             builder->fsCodeAppendf("\t\t\t}\n");
   1215         }
   1216 
   1217         // Adds a function that takes two colors and an alpha as input. It produces a color with the
   1218         // hue and saturation of the first color, the luminosity of the second color, and the input
   1219         // alpha. It has this signature:
   1220         //      vec3 set_luminance(vec3 hueSatColor, float alpha, vec3 lumColor).
   1221         static void AddLumFunction(GrGLShaderBuilder* builder, SkString* setLumFunction) {
   1222             // Emit a helper that gets the luminance of a color.
   1223             SkString getFunction;
   1224             GrGLShaderVar getLumArgs[] = {
   1225                 GrGLShaderVar("color", kVec3f_GrSLType),
   1226             };
   1227             SkString getLumBody("\treturn dot(vec3(0.3, 0.59, 0.11), color);\n");
   1228             builder->emitFunction(GrGLShaderBuilder::kFragment_ShaderType,
   1229                                   kFloat_GrSLType,
   1230                                   "luminance",
   1231                                    SK_ARRAY_COUNT(getLumArgs), getLumArgs,
   1232                                    getLumBody.c_str(),
   1233                                    &getFunction);
   1234 
   1235             // Emit the set luminance function.
   1236             GrGLShaderVar setLumArgs[] = {
   1237                 GrGLShaderVar("hueSat", kVec3f_GrSLType),
   1238                 GrGLShaderVar("alpha", kFloat_GrSLType),
   1239                 GrGLShaderVar("lumColor", kVec3f_GrSLType),
   1240             };
   1241             SkString setLumBody;
   1242             setLumBody.printf("\tfloat diff = %s(lumColor - hueSat);\n", getFunction.c_str());
   1243             setLumBody.append("\tvec3 outColor = hueSat + diff;\n");
   1244             setLumBody.appendf("\tfloat outLum = %s(outColor);\n", getFunction.c_str());
   1245             setLumBody.append("\tfloat minComp = min(min(outColor.r, outColor.g), outColor.b);\n"
   1246                               "\tfloat maxComp = max(max(outColor.r, outColor.g), outColor.b);\n"
   1247                               "\tif (minComp < 0.0) {\n"
   1248                               "\t\toutColor = outLum + ((outColor - vec3(outLum, outLum, outLum)) * outLum) / (outLum - minComp);\n"
   1249                               "\t}\n"
   1250                               "\tif (maxComp > alpha) {\n"
   1251                               "\t\toutColor = outLum + ((outColor - vec3(outLum, outLum, outLum)) * (alpha - outLum)) / (maxComp - outLum);\n"
   1252                               "\t}\n"
   1253                               "\treturn outColor;\n");
   1254             builder->emitFunction(GrGLShaderBuilder::kFragment_ShaderType,
   1255                         kVec3f_GrSLType,
   1256                         "set_luminance",
   1257                         SK_ARRAY_COUNT(setLumArgs), setLumArgs,
   1258                         setLumBody.c_str(),
   1259                         setLumFunction);
   1260         }
   1261 
   1262         // Adds a function that creates a color with the hue and luminosity of one input color and
   1263         // the saturation of another color. It will have this signature:
   1264         //      float set_saturation(vec3 hueLumColor, vec3 satColor)
   1265         static void AddSatFunction(GrGLShaderBuilder* builder, SkString* setSatFunction) {
   1266             // Emit a helper that gets the saturation of a color
   1267             SkString getFunction;
   1268             GrGLShaderVar getSatArgs[] = { GrGLShaderVar("color", kVec3f_GrSLType) };
   1269             SkString getSatBody;
   1270             getSatBody.printf("\treturn max(max(color.r, color.g), color.b) - "
   1271                               "min(min(color.r, color.g), color.b);\n");
   1272             builder->emitFunction(GrGLShaderBuilder::kFragment_ShaderType,
   1273                                   kFloat_GrSLType,
   1274                                   "saturation",
   1275                                   SK_ARRAY_COUNT(getSatArgs), getSatArgs,
   1276                                   getSatBody.c_str(),
   1277                                   &getFunction);
   1278 
   1279             // Emit a helper that sets the saturation given sorted input channels. This used
   1280             // to use inout params for min, mid, and max components but that seems to cause
   1281             // problems on PowerVR drivers. So instead it returns a vec3 where r, g ,b are the
   1282             // adjusted min, mid, and max inputs, respectively.
   1283             SkString helperFunction;
   1284             GrGLShaderVar helperArgs[] = {
   1285                 GrGLShaderVar("minComp", kFloat_GrSLType),
   1286                 GrGLShaderVar("midComp", kFloat_GrSLType),
   1287                 GrGLShaderVar("maxComp", kFloat_GrSLType),
   1288                 GrGLShaderVar("sat", kFloat_GrSLType),
   1289             };
   1290             static const char kHelperBody[] = "\tif (minComp < maxComp) {\n"
   1291                                               "\t\tvec3 result;\n"
   1292                                               "\t\tresult.r = 0.0;\n"
   1293                                               "\t\tresult.g = sat * (midComp - minComp) / (maxComp - minComp);\n"
   1294                                               "\t\tresult.b = sat;\n"
   1295                                               "\t\treturn result;\n"
   1296                                               "\t} else {\n"
   1297                                               "\t\treturn vec3(0, 0, 0);\n"
   1298                                               "\t}\n";
   1299             builder->emitFunction(GrGLShaderBuilder::kFragment_ShaderType,
   1300                                   kVec3f_GrSLType,
   1301                                   "set_saturation_helper",
   1302                                   SK_ARRAY_COUNT(helperArgs), helperArgs,
   1303                                   kHelperBody,
   1304                                   &helperFunction);
   1305 
   1306             GrGLShaderVar setSatArgs[] = {
   1307                 GrGLShaderVar("hueLumColor", kVec3f_GrSLType),
   1308                 GrGLShaderVar("satColor", kVec3f_GrSLType),
   1309             };
   1310             const char* helpFunc = helperFunction.c_str();
   1311             SkString setSatBody;
   1312             setSatBody.appendf("\tfloat sat = %s(satColor);\n"
   1313                                "\tif (hueLumColor.r <= hueLumColor.g) {\n"
   1314                                "\t\tif (hueLumColor.g <= hueLumColor.b) {\n"
   1315                                "\t\t\thueLumColor.rgb = %s(hueLumColor.r, hueLumColor.g, hueLumColor.b, sat);\n"
   1316                                "\t\t} else if (hueLumColor.r <= hueLumColor.b) {\n"
   1317                                "\t\t\thueLumColor.rbg = %s(hueLumColor.r, hueLumColor.b, hueLumColor.g, sat);\n"
   1318                                "\t\t} else {\n"
   1319                                "\t\t\thueLumColor.brg = %s(hueLumColor.b, hueLumColor.r, hueLumColor.g, sat);\n"
   1320                                "\t\t}\n"
   1321                                "\t} else if (hueLumColor.r <= hueLumColor.b) {\n"
   1322                                "\t\thueLumColor.grb = %s(hueLumColor.g, hueLumColor.r, hueLumColor.b, sat);\n"
   1323                                "\t} else if (hueLumColor.g <= hueLumColor.b) {\n"
   1324                                "\t\thueLumColor.gbr = %s(hueLumColor.g, hueLumColor.b, hueLumColor.r, sat);\n"
   1325                                "\t} else {\n"
   1326                                "\t\thueLumColor.bgr = %s(hueLumColor.b, hueLumColor.g, hueLumColor.r, sat);\n"
   1327                                "\t}\n"
   1328                                "\treturn hueLumColor;\n",
   1329                                getFunction.c_str(), helpFunc, helpFunc, helpFunc, helpFunc,
   1330                                helpFunc, helpFunc);
   1331             builder->emitFunction(GrGLShaderBuilder::kFragment_ShaderType,
   1332                                   kVec3f_GrSLType,
   1333                                   "set_saturation",
   1334                                   SK_ARRAY_COUNT(setSatArgs), setSatArgs,
   1335                                   setSatBody.c_str(),
   1336                                   setSatFunction);
   1337 
   1338         }
   1339 
   1340         static const GrEffect::CoordsType kCoordsType = GrEffect::kLocal_CoordsType;
   1341         GrGLEffectMatrix   fBackgroundEffectMatrix;
   1342         typedef GrGLEffect INHERITED;
   1343     };
   1344 
   1345     GR_DECLARE_EFFECT_TEST;
   1346 
   1347 private:
   1348     XferEffect(SkXfermode::Mode mode, GrTexture* background)
   1349         : fMode(mode) {
   1350         if (background) {
   1351             fBackgroundAccess.reset(background);
   1352             this->addTextureAccess(&fBackgroundAccess);
   1353         } else {
   1354             this->setWillReadDstColor();
   1355         }
   1356     }
   1357     virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE {
   1358         const XferEffect& s = CastEffect<XferEffect>(other);
   1359         return fMode == s.fMode &&
   1360                fBackgroundAccess.getTexture() == s.fBackgroundAccess.getTexture();
   1361     }
   1362 
   1363     SkXfermode::Mode fMode;
   1364     GrTextureAccess  fBackgroundAccess;
   1365 
   1366     typedef GrEffect INHERITED;
   1367 };
   1368 
   1369 GR_DEFINE_EFFECT_TEST(XferEffect);
   1370 GrEffectRef* XferEffect::TestCreate(SkMWCRandom* rand,
   1371                                     GrContext*,
   1372                                     const GrDrawTargetCaps&,
   1373                                     GrTexture*[]) {
   1374     int mode = rand->nextRangeU(SkXfermode::kLastCoeffMode + 1, SkXfermode::kLastSeparableMode);
   1375 
   1376     static AutoEffectUnref gEffect(SkNEW_ARGS(XferEffect, (static_cast<SkXfermode::Mode>(mode), NULL)));
   1377     return CreateEffectRef(gEffect);
   1378 }
   1379 
   1380 #endif
   1381 
   1382 ///////////////////////////////////////////////////////////////////////////////
   1383 ///////////////////////////////////////////////////////////////////////////////
   1384 
   1385 class SkProcCoeffXfermode : public SkProcXfermode {
   1386 public:
   1387     SkProcCoeffXfermode(const ProcCoeff& rec, Mode mode)
   1388             : INHERITED(rec.fProc) {
   1389         fMode = mode;
   1390         // these may be valid, or may be CANNOT_USE_COEFF
   1391         fSrcCoeff = rec.fSC;
   1392         fDstCoeff = rec.fDC;
   1393     }
   1394 
   1395     virtual bool asMode(Mode* mode) const SK_OVERRIDE {
   1396         if (mode) {
   1397             *mode = fMode;
   1398         }
   1399         return true;
   1400     }
   1401 
   1402     virtual bool asCoeff(Coeff* sc, Coeff* dc) const SK_OVERRIDE {
   1403         if (CANNOT_USE_COEFF == fSrcCoeff) {
   1404             return false;
   1405         }
   1406 
   1407         if (sc) {
   1408             *sc = fSrcCoeff;
   1409         }
   1410         if (dc) {
   1411             *dc = fDstCoeff;
   1412         }
   1413         return true;
   1414     }
   1415 
   1416 #if SK_SUPPORT_GPU
   1417     virtual bool asNewEffectOrCoeff(GrContext*,
   1418                                     GrEffectRef** effect,
   1419                                     Coeff* src,
   1420                                     Coeff* dst,
   1421                                     GrTexture* background) const SK_OVERRIDE {
   1422         if (this->asCoeff(src, dst)) {
   1423             return true;
   1424         }
   1425         if (XferEffect::IsSupportedMode(fMode)) {
   1426             if (NULL != effect) {
   1427                 *effect = XferEffect::Create(fMode, background);
   1428                 SkASSERT(NULL != *effect);
   1429             }
   1430             return true;
   1431         }
   1432         return false;
   1433     }
   1434 #endif
   1435 
   1436     SK_DEVELOPER_TO_STRING()
   1437     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkProcCoeffXfermode)
   1438 
   1439 protected:
   1440     SkProcCoeffXfermode(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
   1441         fMode = (SkXfermode::Mode)buffer.read32();
   1442 
   1443         const ProcCoeff& rec = gProcCoeffs[fMode];
   1444         // these may be valid, or may be CANNOT_USE_COEFF
   1445         fSrcCoeff = rec.fSC;
   1446         fDstCoeff = rec.fDC;
   1447         // now update our function-ptr in the super class
   1448         this->INHERITED::setProc(rec.fProc);
   1449     }
   1450 
   1451     virtual void flatten(SkFlattenableWriteBuffer& buffer) const SK_OVERRIDE {
   1452         this->INHERITED::flatten(buffer);
   1453         buffer.write32(fMode);
   1454     }
   1455 
   1456 private:
   1457     Mode    fMode;
   1458     Coeff   fSrcCoeff, fDstCoeff;
   1459 
   1460     typedef SkProcXfermode INHERITED;
   1461 };
   1462 
   1463 const char* SkXfermode::ModeName(Mode mode) {
   1464     SkASSERT((unsigned) mode <= (unsigned)kLastMode);
   1465     const char* gModeStrings[] = {
   1466         "Clear", "Src", "Dst", "SrcOver", "DstOver", "SrcIn", "DstIn",
   1467         "SrcOut", "DstOut", "SrcATop", "DstATop", "Xor", "Plus",
   1468         "Modulate", "Screen", "Overlay", "Darken", "Lighten", "ColorDodge",
   1469         "ColorBurn", "HardLight", "SoftLight", "Difference", "Exclusion",
   1470         "Multiply", "Hue", "Saturation", "Color",  "Luminosity"
   1471     };
   1472     return gModeStrings[mode];
   1473     SK_COMPILE_ASSERT(SK_ARRAY_COUNT(gModeStrings) == kLastMode + 1, mode_count);
   1474 }
   1475 
   1476 #ifdef SK_DEVELOPER
   1477 void SkProcCoeffXfermode::toString(SkString* str) const {
   1478     str->append("SkProcCoeffXfermode: ");
   1479 
   1480     str->append("mode: ");
   1481     str->append(ModeName(fMode));
   1482 
   1483     static const char* gCoeffStrings[kCoeffCount] = {
   1484         "Zero", "One", "SC", "ISC", "DC", "IDC", "SA", "ISA", "DA", "IDA"
   1485     };
   1486 
   1487     str->append(" src: ");
   1488     if (CANNOT_USE_COEFF == fSrcCoeff) {
   1489         str->append("can't use");
   1490     } else {
   1491         str->append(gCoeffStrings[fSrcCoeff]);
   1492     }
   1493 
   1494     str->append(" dst: ");
   1495     if (CANNOT_USE_COEFF == fDstCoeff) {
   1496         str->append("can't use");
   1497     } else {
   1498         str->append(gCoeffStrings[fDstCoeff]);
   1499     }
   1500 }
   1501 #endif
   1502 
   1503 ///////////////////////////////////////////////////////////////////////////////
   1504 
   1505 class SkClearXfermode : public SkProcCoeffXfermode {
   1506 public:
   1507     SkClearXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kClear_Mode) {}
   1508 
   1509     virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
   1510     virtual void xferA8(SkAlpha*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
   1511 
   1512     SK_DEVELOPER_TO_STRING()
   1513     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkClearXfermode)
   1514 
   1515 private:
   1516     SkClearXfermode(SkFlattenableReadBuffer& buffer)
   1517         : SkProcCoeffXfermode(buffer) {}
   1518 
   1519     typedef SkProcCoeffXfermode INHERITED;
   1520 };
   1521 
   1522 void SkClearXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
   1523                              const SkPMColor* SK_RESTRICT, int count,
   1524                              const SkAlpha* SK_RESTRICT aa) const {
   1525     SkASSERT(dst && count >= 0);
   1526 
   1527     if (NULL == aa) {
   1528         memset(dst, 0, count << 2);
   1529     } else {
   1530         for (int i = count - 1; i >= 0; --i) {
   1531             unsigned a = aa[i];
   1532             if (0xFF == a) {
   1533                 dst[i] = 0;
   1534             } else if (a != 0) {
   1535                 dst[i] = SkAlphaMulQ(dst[i], SkAlpha255To256(255 - a));
   1536             }
   1537         }
   1538     }
   1539 }
   1540 void SkClearXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
   1541                              const SkPMColor* SK_RESTRICT, int count,
   1542                              const SkAlpha* SK_RESTRICT aa) const {
   1543     SkASSERT(dst && count >= 0);
   1544 
   1545     if (NULL == aa) {
   1546         memset(dst, 0, count);
   1547     } else {
   1548         for (int i = count - 1; i >= 0; --i) {
   1549             unsigned a = aa[i];
   1550             if (0xFF == a) {
   1551                 dst[i] = 0;
   1552             } else if (0 != a) {
   1553                 dst[i] = SkAlphaMulAlpha(dst[i], 255 - a);
   1554             }
   1555         }
   1556     }
   1557 }
   1558 
   1559 #ifdef SK_DEVELOPER
   1560 void SkClearXfermode::toString(SkString* str) const {
   1561     this->INHERITED::toString(str);
   1562 }
   1563 #endif
   1564 
   1565 ///////////////////////////////////////////////////////////////////////////////
   1566 
   1567 class SkSrcXfermode : public SkProcCoeffXfermode {
   1568 public:
   1569     SkSrcXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kSrc_Mode) {}
   1570 
   1571     virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
   1572     virtual void xferA8(SkAlpha*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
   1573 
   1574     SK_DEVELOPER_TO_STRING()
   1575     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkSrcXfermode)
   1576 
   1577 private:
   1578     SkSrcXfermode(SkFlattenableReadBuffer& buffer)
   1579         : SkProcCoeffXfermode(buffer) {}
   1580 
   1581     typedef SkProcCoeffXfermode INHERITED;
   1582 };
   1583 
   1584 void SkSrcXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
   1585                            const SkPMColor* SK_RESTRICT src, int count,
   1586                            const SkAlpha* SK_RESTRICT aa) const {
   1587     SkASSERT(dst && src && count >= 0);
   1588 
   1589     if (NULL == aa) {
   1590         memcpy(dst, src, count << 2);
   1591     } else {
   1592         for (int i = count - 1; i >= 0; --i) {
   1593             unsigned a = aa[i];
   1594             if (a == 0xFF) {
   1595                 dst[i] = src[i];
   1596             } else if (a != 0) {
   1597                 dst[i] = SkFourByteInterp(src[i], dst[i], a);
   1598             }
   1599         }
   1600     }
   1601 }
   1602 
   1603 void SkSrcXfermode::xferA8(SkAlpha* SK_RESTRICT dst,
   1604                            const SkPMColor* SK_RESTRICT src, int count,
   1605                            const SkAlpha* SK_RESTRICT aa) const {
   1606     SkASSERT(dst && src && count >= 0);
   1607 
   1608     if (NULL == aa) {
   1609         for (int i = count - 1; i >= 0; --i) {
   1610             dst[i] = SkToU8(SkGetPackedA32(src[i]));
   1611         }
   1612     } else {
   1613         for (int i = count - 1; i >= 0; --i) {
   1614             unsigned a = aa[i];
   1615             if (0 != a) {
   1616                 unsigned srcA = SkGetPackedA32(src[i]);
   1617                 if (a == 0xFF) {
   1618                     dst[i] = SkToU8(srcA);
   1619                 } else {
   1620                     dst[i] = SkToU8(SkAlphaBlend(srcA, dst[i], a));
   1621                 }
   1622             }
   1623         }
   1624     }
   1625 }
   1626 #ifdef SK_DEVELOPER
   1627 void SkSrcXfermode::toString(SkString* str) const {
   1628     this->INHERITED::toString(str);
   1629 }
   1630 #endif
   1631 
   1632 ///////////////////////////////////////////////////////////////////////////////
   1633 
   1634 class SkDstInXfermode : public SkProcCoeffXfermode {
   1635 public:
   1636     SkDstInXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstIn_Mode) {}
   1637 
   1638     virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
   1639 
   1640     SK_DEVELOPER_TO_STRING()
   1641     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDstInXfermode)
   1642 
   1643 private:
   1644     SkDstInXfermode(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {}
   1645 
   1646     typedef SkProcCoeffXfermode INHERITED;
   1647 };
   1648 
   1649 void SkDstInXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
   1650                              const SkPMColor* SK_RESTRICT src, int count,
   1651                              const SkAlpha* SK_RESTRICT aa) const {
   1652     SkASSERT(dst && src);
   1653 
   1654     if (count <= 0) {
   1655         return;
   1656     }
   1657     if (NULL != aa) {
   1658         return this->INHERITED::xfer32(dst, src, count, aa);
   1659     }
   1660 
   1661     do {
   1662         unsigned a = SkGetPackedA32(*src);
   1663         *dst = SkAlphaMulQ(*dst, SkAlpha255To256(a));
   1664         dst++;
   1665         src++;
   1666     } while (--count != 0);
   1667 }
   1668 
   1669 #ifdef SK_DEVELOPER
   1670 void SkDstInXfermode::toString(SkString* str) const {
   1671     this->INHERITED::toString(str);
   1672 }
   1673 #endif
   1674 
   1675 ///////////////////////////////////////////////////////////////////////////////
   1676 
   1677 class SkDstOutXfermode : public SkProcCoeffXfermode {
   1678 public:
   1679     SkDstOutXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstOut_Mode) {}
   1680 
   1681     virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE;
   1682 
   1683     SK_DEVELOPER_TO_STRING()
   1684     SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDstOutXfermode)
   1685 
   1686 private:
   1687     SkDstOutXfermode(SkFlattenableReadBuffer& buffer)
   1688         : INHERITED(buffer) {}
   1689 
   1690     typedef SkProcCoeffXfermode INHERITED;
   1691 };
   1692 
   1693 void SkDstOutXfermode::xfer32(SkPMColor* SK_RESTRICT dst,
   1694                               const SkPMColor* SK_RESTRICT src, int count,
   1695                               const SkAlpha* SK_RESTRICT aa) const {
   1696     SkASSERT(dst && src);
   1697 
   1698     if (count <= 0) {
   1699         return;
   1700     }
   1701     if (NULL != aa) {
   1702         return this->INHERITED::xfer32(dst, src, count, aa);
   1703     }
   1704 
   1705     do {
   1706         unsigned a = SkGetPackedA32(*src);
   1707         *dst = SkAlphaMulQ(*dst, SkAlpha255To256(255 - a));
   1708         dst++;
   1709         src++;
   1710     } while (--count != 0);
   1711 }
   1712 
   1713 #ifdef SK_DEVELOPER
   1714 void SkDstOutXfermode::toString(SkString* str) const {
   1715     this->INHERITED::toString(str);
   1716 }
   1717 #endif
   1718 
   1719 ///////////////////////////////////////////////////////////////////////////////
   1720 
   1721 SkXfermode* SkXfermode::Create(Mode mode) {
   1722     SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount);
   1723     SkASSERT((unsigned)mode < kModeCount);
   1724 
   1725     const ProcCoeff& rec = gProcCoeffs[mode];
   1726 
   1727     switch (mode) {
   1728         case kClear_Mode:
   1729             return SkNEW_ARGS(SkClearXfermode, (rec));
   1730         case kSrc_Mode:
   1731             return SkNEW_ARGS(SkSrcXfermode, (rec));
   1732         case kSrcOver_Mode:
   1733             return NULL;
   1734         case kDstIn_Mode:
   1735             return SkNEW_ARGS(SkDstInXfermode, (rec));
   1736         case kDstOut_Mode:
   1737             return SkNEW_ARGS(SkDstOutXfermode, (rec));
   1738         default:
   1739             return SkNEW_ARGS(SkProcCoeffXfermode, (rec, mode));
   1740     }
   1741 }
   1742 
   1743 SkXfermodeProc SkXfermode::GetProc(Mode mode) {
   1744     SkXfermodeProc  proc = NULL;
   1745     if ((unsigned)mode < kModeCount) {
   1746         proc = gProcCoeffs[mode].fProc;
   1747     }
   1748     return proc;
   1749 }
   1750 
   1751 bool SkXfermode::ModeAsCoeff(Mode mode, Coeff* src, Coeff* dst) {
   1752     SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount);
   1753 
   1754     if ((unsigned)mode >= (unsigned)kModeCount) {
   1755         // illegal mode parameter
   1756         return false;
   1757     }
   1758 
   1759     const ProcCoeff& rec = gProcCoeffs[mode];
   1760 
   1761     if (CANNOT_USE_COEFF == rec.fSC) {
   1762         return false;
   1763     }
   1764 
   1765     SkASSERT(CANNOT_USE_COEFF != rec.fDC);
   1766     if (src) {
   1767         *src = rec.fSC;
   1768     }
   1769     if (dst) {
   1770         *dst = rec.fDC;
   1771     }
   1772     return true;
   1773 }
   1774 
   1775 bool SkXfermode::AsMode(const SkXfermode* xfer, Mode* mode) {
   1776     if (NULL == xfer) {
   1777         if (mode) {
   1778             *mode = kSrcOver_Mode;
   1779         }
   1780         return true;
   1781     }
   1782     return xfer->asMode(mode);
   1783 }
   1784 
   1785 bool SkXfermode::AsCoeff(const SkXfermode* xfer, Coeff* src, Coeff* dst) {
   1786     if (NULL == xfer) {
   1787         return ModeAsCoeff(kSrcOver_Mode, src, dst);
   1788     }
   1789     return xfer->asCoeff(src, dst);
   1790 }
   1791 
   1792 bool SkXfermode::IsMode(const SkXfermode* xfer, Mode mode) {
   1793     // if xfer==null then the mode is srcover
   1794     Mode m = kSrcOver_Mode;
   1795     if (xfer && !xfer->asMode(&m)) {
   1796         return false;
   1797     }
   1798     return mode == m;
   1799 }
   1800 
   1801 ///////////////////////////////////////////////////////////////////////////////
   1802 //////////// 16bit xfermode procs
   1803 
   1804 #ifdef SK_DEBUG
   1805 static bool require_255(SkPMColor src) { return SkGetPackedA32(src) == 0xFF; }
   1806 static bool require_0(SkPMColor src) { return SkGetPackedA32(src) == 0; }
   1807 #endif
   1808 
   1809 static uint16_t src_modeproc16_255(SkPMColor src, uint16_t dst) {
   1810     SkASSERT(require_255(src));
   1811     return SkPixel32ToPixel16(src);
   1812 }
   1813 
   1814 static uint16_t dst_modeproc16(SkPMColor src, uint16_t dst) {
   1815     return dst;
   1816 }
   1817 
   1818 static uint16_t srcover_modeproc16_0(SkPMColor src, uint16_t dst) {
   1819     SkASSERT(require_0(src));
   1820     return dst;
   1821 }
   1822 
   1823 static uint16_t srcover_modeproc16_255(SkPMColor src, uint16_t dst) {
   1824     SkASSERT(require_255(src));
   1825     return SkPixel32ToPixel16(src);
   1826 }
   1827 
   1828 static uint16_t dstover_modeproc16_0(SkPMColor src, uint16_t dst) {
   1829     SkASSERT(require_0(src));
   1830     return dst;
   1831 }
   1832 
   1833 static uint16_t dstover_modeproc16_255(SkPMColor src, uint16_t dst) {
   1834     SkASSERT(require_255(src));
   1835     return dst;
   1836 }
   1837 
   1838 static uint16_t srcin_modeproc16_255(SkPMColor src, uint16_t dst) {
   1839     SkASSERT(require_255(src));
   1840     return SkPixel32ToPixel16(src);
   1841 }
   1842 
   1843 static uint16_t dstin_modeproc16_255(SkPMColor src, uint16_t dst) {
   1844     SkASSERT(require_255(src));
   1845     return dst;
   1846 }
   1847 
   1848 static uint16_t dstout_modeproc16_0(SkPMColor src, uint16_t dst) {
   1849     SkASSERT(require_0(src));
   1850     return dst;
   1851 }
   1852 
   1853 static uint16_t srcatop_modeproc16(SkPMColor src, uint16_t dst) {
   1854     unsigned isa = 255 - SkGetPackedA32(src);
   1855 
   1856     return SkPackRGB16(
   1857            SkPacked32ToR16(src) + SkAlphaMulAlpha(SkGetPackedR16(dst), isa),
   1858            SkPacked32ToG16(src) + SkAlphaMulAlpha(SkGetPackedG16(dst), isa),
   1859            SkPacked32ToB16(src) + SkAlphaMulAlpha(SkGetPackedB16(dst), isa));
   1860 }
   1861 
   1862 static uint16_t srcatop_modeproc16_0(SkPMColor src, uint16_t dst) {
   1863     SkASSERT(require_0(src));
   1864     return dst;
   1865 }
   1866 
   1867 static uint16_t srcatop_modeproc16_255(SkPMColor src, uint16_t dst) {
   1868     SkASSERT(require_255(src));
   1869     return SkPixel32ToPixel16(src);
   1870 }
   1871 
   1872 static uint16_t dstatop_modeproc16_255(SkPMColor src, uint16_t dst) {
   1873     SkASSERT(require_255(src));
   1874     return dst;
   1875 }
   1876 
   1877 /*********
   1878     darken and lighten boil down to this.
   1879 
   1880     darken  = (1 - Sa) * Dc + min(Sc, Dc)
   1881     lighten = (1 - Sa) * Dc + max(Sc, Dc)
   1882 
   1883     if (Sa == 0) these become
   1884         darken  = Dc + min(0, Dc) = 0
   1885         lighten = Dc + max(0, Dc) = Dc
   1886 
   1887     if (Sa == 1) these become
   1888         darken  = min(Sc, Dc)
   1889         lighten = max(Sc, Dc)
   1890 */
   1891 
   1892 static uint16_t darken_modeproc16_0(SkPMColor src, uint16_t dst) {
   1893     SkASSERT(require_0(src));
   1894     return 0;
   1895 }
   1896 
   1897 static uint16_t darken_modeproc16_255(SkPMColor src, uint16_t dst) {
   1898     SkASSERT(require_255(src));
   1899     unsigned r = SkFastMin32(SkPacked32ToR16(src), SkGetPackedR16(dst));
   1900     unsigned g = SkFastMin32(SkPacked32ToG16(src), SkGetPackedG16(dst));
   1901     unsigned b = SkFastMin32(SkPacked32ToB16(src), SkGetPackedB16(dst));
   1902     return SkPackRGB16(r, g, b);
   1903 }
   1904 
   1905 static uint16_t lighten_modeproc16_0(SkPMColor src, uint16_t dst) {
   1906     SkASSERT(require_0(src));
   1907     return dst;
   1908 }
   1909 
   1910 static uint16_t lighten_modeproc16_255(SkPMColor src, uint16_t dst) {
   1911     SkASSERT(require_255(src));
   1912     unsigned r = SkMax32(SkPacked32ToR16(src), SkGetPackedR16(dst));
   1913     unsigned g = SkMax32(SkPacked32ToG16(src), SkGetPackedG16(dst));
   1914     unsigned b = SkMax32(SkPacked32ToB16(src), SkGetPackedB16(dst));
   1915     return SkPackRGB16(r, g, b);
   1916 }
   1917 
   1918 struct Proc16Rec {
   1919     SkXfermodeProc16    fProc16_0;
   1920     SkXfermodeProc16    fProc16_255;
   1921     SkXfermodeProc16    fProc16_General;
   1922 };
   1923 
   1924 static const Proc16Rec gModeProcs16[] = {
   1925     { NULL,                 NULL,                   NULL            }, // CLEAR
   1926     { NULL,                 src_modeproc16_255,     NULL            },
   1927     { dst_modeproc16,       dst_modeproc16,         dst_modeproc16  },
   1928     { srcover_modeproc16_0, srcover_modeproc16_255, NULL            },
   1929     { dstover_modeproc16_0, dstover_modeproc16_255, NULL            },
   1930     { NULL,                 srcin_modeproc16_255,   NULL            },
   1931     { NULL,                 dstin_modeproc16_255,   NULL            },
   1932     { NULL,                 NULL,                   NULL            },// SRC_OUT
   1933     { dstout_modeproc16_0,  NULL,                   NULL            },
   1934     { srcatop_modeproc16_0, srcatop_modeproc16_255, srcatop_modeproc16  },
   1935     { NULL,                 dstatop_modeproc16_255, NULL            },
   1936     { NULL,                 NULL,                   NULL            }, // XOR
   1937 
   1938     { NULL,                 NULL,                   NULL            }, // plus
   1939     { NULL,                 NULL,                   NULL            }, // modulate
   1940     { NULL,                 NULL,                   NULL            }, // screen
   1941     { NULL,                 NULL,                   NULL            }, // overlay
   1942     { darken_modeproc16_0,  darken_modeproc16_255,  NULL            }, // darken
   1943     { lighten_modeproc16_0, lighten_modeproc16_255, NULL            }, // lighten
   1944     { NULL,                 NULL,                   NULL            }, // colordodge
   1945     { NULL,                 NULL,                   NULL            }, // colorburn
   1946     { NULL,                 NULL,                   NULL            }, // hardlight
   1947     { NULL,                 NULL,                   NULL            }, // softlight
   1948     { NULL,                 NULL,                   NULL            }, // difference
   1949     { NULL,                 NULL,                   NULL            }, // exclusion
   1950     { NULL,                 NULL,                   NULL            }, // multiply
   1951     { NULL,                 NULL,                   NULL            }, // hue
   1952     { NULL,                 NULL,                   NULL            }, // saturation
   1953     { NULL,                 NULL,                   NULL            }, // color
   1954     { NULL,                 NULL,                   NULL            }, // luminosity
   1955 };
   1956 
   1957 SkXfermodeProc16 SkXfermode::GetProc16(Mode mode, SkColor srcColor) {
   1958     SkXfermodeProc16  proc16 = NULL;
   1959     if ((unsigned)mode < kModeCount) {
   1960         const Proc16Rec& rec = gModeProcs16[mode];
   1961         unsigned a = SkColorGetA(srcColor);
   1962 
   1963         if (0 == a) {
   1964             proc16 = rec.fProc16_0;
   1965         } else if (255 == a) {
   1966             proc16 = rec.fProc16_255;
   1967         } else {
   1968             proc16 = rec.fProc16_General;
   1969         }
   1970     }
   1971     return proc16;
   1972 }
   1973 
   1974 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkXfermode)
   1975     SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkProcCoeffXfermode)
   1976     SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkClearXfermode)
   1977     SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSrcXfermode)
   1978     SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDstInXfermode)
   1979     SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDstOutXfermode)
   1980 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
   1981