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