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