LCOV - code coverage report
Current view: directory - gfx/skia/src/core - SkXfermode.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 628 5 0.8 %
Date: 2012-06-02 Functions: 121 2 1.7 %

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

Generated by: LCOV version 1.7