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