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