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