tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

0010-Bug-836892-Add-new-blending-modes-to-SkXfermode.patch (26246B)


      1 # HG changeset patch
      2 # User Rik Cabanier <cabanier@adobe.com>
      3 # Date 1360273929 -46800
      4 # Node ID 3ac8edca3a03b3d22240b5a5b95ae3b5ada9877d
      5 # Parent  cbb67fe70b864b36165061e1fd3b083cd09af087
      6 Bug 836892 - Add new blending modes to SkXfermode. r=gw280
      7 
      8 diff --git a/gfx/skia/include/core/SkXfermode.h b/gfx/skia/include/core/SkXfermode.h
      9 --- a/gfx/skia/include/core/SkXfermode.h
     10 +++ b/gfx/skia/include/core/SkXfermode.h
     11 @@ -96,33 +96,37 @@ public:
     12         kDstOut_Mode,   //!< [Da * (1 - Sa), Dc * (1 - Sa)]
     13         kSrcATop_Mode,  //!< [Da, Sc * Da + (1 - Sa) * Dc]
     14         kDstATop_Mode,  //!< [Sa, Sa * Dc + Sc * (1 - Da)]
     15         kXor_Mode,      //!< [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc]
     16 
     17         // all remaining modes are defined in the SVG Compositing standard
     18         // http://www.w3.org/TR/2009/WD-SVGCompositing-20090430/
     19         kPlus_Mode,
     20 -        kMultiply_Mode,
     21 
     22         // all above modes can be expressed as pair of src/dst Coeffs
     23         kCoeffModesCnt,
     24 
     25 -        kScreen_Mode = kCoeffModesCnt,
     26 +        kMultiply_Mode = kCoeffModesCnt,
     27 +        kScreen_Mode,
     28         kOverlay_Mode,
     29         kDarken_Mode,
     30         kLighten_Mode,
     31         kColorDodge_Mode,
     32         kColorBurn_Mode,
     33         kHardLight_Mode,
     34         kSoftLight_Mode,
     35         kDifference_Mode,
     36         kExclusion_Mode,
     37 +        kHue_Mode,
     38 +        kSaturation_Mode,
     39 +        kColor_Mode,
     40 +        kLuminosity_Mode,
     41 
     42 -        kLastMode = kExclusion_Mode
     43 +        kLastMode = kLuminosity_Mode
     44     };
     45 
     46     /**
     47      *  If the xfermode is one of the modes in the Mode enum, then asMode()
     48      *  returns true and sets (if not null) mode accordingly. Otherwise it
     49      *  returns false and ignores the mode parameter.
     50      */
     51     virtual bool asMode(Mode* mode);
     52 diff --git a/gfx/skia/src/core/SkXfermode.cpp b/gfx/skia/src/core/SkXfermode.cpp
     53 --- a/gfx/skia/src/core/SkXfermode.cpp
     54 +++ b/gfx/skia/src/core/SkXfermode.cpp
     55 @@ -7,16 +7,18 @@
     56  */
     57 
     58 
     59 #include "SkXfermode.h"
     60 #include "SkColorPriv.h"
     61 #include "SkFlattenableBuffers.h"
     62 #include "SkMathPriv.h"
     63 
     64 +#include <algorithm>
     65 +
     66 SK_DEFINE_INST_COUNT(SkXfermode)
     67 
     68 #define SkAlphaMulAlpha(a, b)   SkMulDiv255Round(a, b)
     69 
     70 #if 0
     71 // idea for higher precision blends in xfer procs (and slightly faster)
     72 // see DstATop as a probable caller
     73 static U8CPU mulmuldiv255round(U8CPU a, U8CPU b, U8CPU c, U8CPU d) {
     74 @@ -176,244 +178,439 @@ static SkPMColor xor_modeproc(SkPMColor 
     75 static SkPMColor plus_modeproc(SkPMColor src, SkPMColor dst) {
     76     unsigned b = saturated_add(SkGetPackedB32(src), SkGetPackedB32(dst));
     77     unsigned g = saturated_add(SkGetPackedG32(src), SkGetPackedG32(dst));
     78     unsigned r = saturated_add(SkGetPackedR32(src), SkGetPackedR32(dst));
     79     unsigned a = saturated_add(SkGetPackedA32(src), SkGetPackedA32(dst));
     80     return SkPackARGB32(a, r, g, b);
     81 }
     82 
     83 +static inline int srcover_byte(int a, int b) {
     84 +    return a + b - SkAlphaMulAlpha(a, b);
     85 +}
     86 +
     87 +#define  blendfunc_byte(sc, dc, sa, da, blendfunc) \
     88 +  clamp_div255round(sc * (255 - da)  + dc * (255 - sa)  + blendfunc(sc, dc, sa, da))
     89 +
     90 // kMultiply_Mode
     91 +static inline int multiply_byte(int sc, int dc, int sa, int da) {
     92 +    return sc * dc;
     93 +}
     94 static SkPMColor multiply_modeproc(SkPMColor src, SkPMColor dst) {
     95 -    int a = SkAlphaMulAlpha(SkGetPackedA32(src), SkGetPackedA32(dst));
     96 -    int r = SkAlphaMulAlpha(SkGetPackedR32(src), SkGetPackedR32(dst));
     97 -    int g = SkAlphaMulAlpha(SkGetPackedG32(src), SkGetPackedG32(dst));
     98 -    int b = SkAlphaMulAlpha(SkGetPackedB32(src), SkGetPackedB32(dst));
     99 +    int sa = SkGetPackedA32(src);
    100 +    int da = SkGetPackedA32(dst);
    101 +    int a = srcover_byte(sa, da);
    102 +    int r = blendfunc_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da, multiply_byte);
    103 +    int g = blendfunc_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da, multiply_byte);
    104 +    int b = blendfunc_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da, multiply_byte);
    105     return SkPackARGB32(a, r, g, b);
    106 }
    107 
    108 // kScreen_Mode
    109 -static inline int srcover_byte(int a, int b) {
    110 -    return a + b - SkAlphaMulAlpha(a, b);
    111 +static inline int screen_byte(int sc, int dc, int sa, int da) {
    112 +    return sc * da + sa * dc - sc * dc;
    113 }
    114 static SkPMColor screen_modeproc(SkPMColor src, SkPMColor dst) {
    115 -    int a = srcover_byte(SkGetPackedA32(src), SkGetPackedA32(dst));
    116 -    int r = srcover_byte(SkGetPackedR32(src), SkGetPackedR32(dst));
    117 -    int g = srcover_byte(SkGetPackedG32(src), SkGetPackedG32(dst));
    118 -    int b = srcover_byte(SkGetPackedB32(src), SkGetPackedB32(dst));
    119 +    int sa = SkGetPackedA32(src);
    120 +    int da = SkGetPackedA32(dst);
    121 +    int a = srcover_byte(sa, da);
    122 +    int r = blendfunc_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da, screen_byte);
    123 +    int g = blendfunc_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da, screen_byte);
    124 +    int b = blendfunc_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da, screen_byte);
    125 +    return SkPackARGB32(a, r, g, b);
    126 +}
    127 +
    128 +// kHardLight_Mode
    129 +static inline int hardlight_byte(int sc, int dc, int sa, int da) {
    130 +    if(!sa || !da)
    131 +        return sc * da;
    132 +    float Sc = (float)sc/sa;
    133 +    float Dc = (float)dc/da;
    134 +    if(Sc <= 0.5)
    135 +        Sc *= 2 * Dc;
    136 +    else
    137 +        Sc = -1 + 2 * Sc + 2 * Dc - 2 * Sc * Dc;
    138 +
    139 +    return Sc * sa * da;
    140 +}
    141 +static SkPMColor hardlight_modeproc(SkPMColor src, SkPMColor dst) {
    142 +    int sa = SkGetPackedA32(src);
    143 +    int da = SkGetPackedA32(dst);
    144 +    int a = srcover_byte(sa, da);
    145 +    int r = blendfunc_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da, hardlight_byte);
    146 +    int g = blendfunc_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da, hardlight_byte);
    147 +    int b = blendfunc_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da, hardlight_byte);
    148     return SkPackARGB32(a, r, g, b);
    149 }
    150 
    151 // kOverlay_Mode
    152 static inline int overlay_byte(int sc, int dc, int sa, int da) {
    153 -    int tmp = sc * (255 - da) + dc * (255 - sa);
    154 -    int rc;
    155 -    if (2 * dc <= da) {
    156 -        rc = 2 * sc * dc;
    157 -    } else {
    158 -        rc = sa * da - 2 * (da - dc) * (sa - sc);
    159 -    }
    160 -    return clamp_div255round(rc + tmp);
    161 +    return hardlight_byte(dc, sc, da, sa);
    162 }
    163 static SkPMColor overlay_modeproc(SkPMColor src, SkPMColor dst) {
    164     int sa = SkGetPackedA32(src);
    165     int da = SkGetPackedA32(dst);
    166     int a = srcover_byte(sa, da);
    167 -    int r = overlay_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
    168 -    int g = overlay_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
    169 -    int b = overlay_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
    170 +    int r = blendfunc_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da, overlay_byte);
    171 +    int g = blendfunc_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da, overlay_byte);
    172 +    int b = blendfunc_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da, overlay_byte);
    173     return SkPackARGB32(a, r, g, b);
    174 }
    175 
    176 // kDarken_Mode
    177 static inline int darken_byte(int sc, int dc, int sa, int da) {
    178 -    int sd = sc * da;
    179 -    int ds = dc * sa;
    180 -    if (sd < ds) {
    181 -        // srcover
    182 -        return sc + dc - SkDiv255Round(ds);
    183 -    } else {
    184 -        // dstover
    185 -        return dc + sc - SkDiv255Round(sd);
    186 -    }
    187 +    return SkMin32(sc * da, sa * dc);
    188 }
    189 static SkPMColor darken_modeproc(SkPMColor src, SkPMColor dst) {
    190     int sa = SkGetPackedA32(src);
    191     int da = SkGetPackedA32(dst);
    192     int a = srcover_byte(sa, da);
    193 -    int r = darken_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
    194 -    int g = darken_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
    195 -    int b = darken_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
    196 +    int r = blendfunc_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da, darken_byte);
    197 +    int g = blendfunc_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da, darken_byte);
    198 +    int b = blendfunc_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da, darken_byte);
    199     return SkPackARGB32(a, r, g, b);
    200 }
    201 
    202 // kLighten_Mode
    203 static inline int lighten_byte(int sc, int dc, int sa, int da) {
    204 -    int sd = sc * da;
    205 -    int ds = dc * sa;
    206 -    if (sd > ds) {
    207 -        // srcover
    208 -        return sc + dc - SkDiv255Round(ds);
    209 -    } else {
    210 -        // dstover
    211 -        return dc + sc - SkDiv255Round(sd);
    212 -    }
    213 +    return SkMax32(sc * da, sa * dc);
    214 }
    215 static SkPMColor lighten_modeproc(SkPMColor src, SkPMColor dst) {
    216     int sa = SkGetPackedA32(src);
    217     int da = SkGetPackedA32(dst);
    218     int a = srcover_byte(sa, da);
    219 -    int r = lighten_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
    220 -    int g = lighten_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
    221 -    int b = lighten_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
    222 +    int r = blendfunc_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da, lighten_byte);
    223 +    int g = blendfunc_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da, lighten_byte);
    224 +    int b = blendfunc_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da, lighten_byte);
    225     return SkPackARGB32(a, r, g, b);
    226 }
    227 
    228 // kColorDodge_Mode
    229 static inline int colordodge_byte(int sc, int dc, int sa, int da) {
    230 -    int diff = sa - sc;
    231 -    int rc;
    232 -    if (0 == diff) {
    233 -        rc = sa * da + sc * (255 - da) + dc * (255 - sa);
    234 -        rc = SkDiv255Round(rc);
    235 -    } else {
    236 -        int tmp = (dc * sa << 15) / (da * diff);
    237 -        rc = SkDiv255Round(sa * da) * tmp >> 15;
    238 -        // don't clamp here, since we'll do it in our modeproc
    239 -    }
    240 -    return rc;
    241 +    if (dc == 0)
    242 +        return 0;
    243 +    // Avoid division by 0
    244 +    if (sc == sa)
    245 +        return da * sa;
    246 +
    247 +    return SkMin32(sa * da, sa * sa * dc / (sa - sc));
    248 }
    249 static SkPMColor colordodge_modeproc(SkPMColor src, SkPMColor dst) {
    250 -    // added to avoid div-by-zero in colordodge_byte
    251 -    if (0 == dst) {
    252 -        return src;
    253 -    }
    254 -
    255     int sa = SkGetPackedA32(src);
    256     int da = SkGetPackedA32(dst);
    257     int a = srcover_byte(sa, da);
    258 -    int r = colordodge_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
    259 -    int g = colordodge_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
    260 -    int b = colordodge_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
    261 -    r = clamp_max(r, a);
    262 -    g = clamp_max(g, a);
    263 -    b = clamp_max(b, a);
    264 +    int r = blendfunc_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da, colordodge_byte);
    265 +    int g = blendfunc_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da, colordodge_byte);
    266 +    int b = blendfunc_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da, colordodge_byte);
    267     return SkPackARGB32(a, r, g, b);
    268 }
    269 
    270 // kColorBurn_Mode
    271 static inline int colorburn_byte(int sc, int dc, int sa, int da) {
    272 -    int rc;
    273 -    if (dc == da && 0 == sc) {
    274 -        rc = sa * da + dc * (255 - sa);
    275 -    } else if (0 == sc) {
    276 -        return SkAlphaMulAlpha(dc, 255 - sa);
    277 -    } else {
    278 -        int tmp = (sa * (da - dc) * 256) / (sc * da);
    279 -        if (tmp > 256) {
    280 -            tmp = 256;
    281 -        }
    282 -        int tmp2 = sa * da;
    283 -        rc = tmp2 - (tmp2 * tmp >> 8) + sc * (255 - da) + dc * (255 - sa);
    284 -    }
    285 -    return SkDiv255Round(rc);
    286 +    // Avoid division by 0
    287 +    if(dc == da)
    288 +        return sa * da;
    289 +    if(sc == 0)
    290 +        return 0;
    291 +
    292 +    return sa * da - SkMin32(sa * da, sa * sa * (da - dc) / sc);
    293 }
    294 static SkPMColor colorburn_modeproc(SkPMColor src, SkPMColor dst) {
    295 -    // added to avoid div-by-zero in colorburn_byte
    296 -    if (0 == dst) {
    297 -        return src;
    298 -    }
    299 -
    300     int sa = SkGetPackedA32(src);
    301     int da = SkGetPackedA32(dst);
    302     int a = srcover_byte(sa, da);
    303 -    int r = colorburn_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
    304 -    int g = colorburn_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
    305 -    int b = colorburn_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
    306 -    return SkPackARGB32(a, r, g, b);
    307 -}
    308 -
    309 -// kHardLight_Mode
    310 -static inline int hardlight_byte(int sc, int dc, int sa, int da) {
    311 -    int rc;
    312 -    if (2 * sc <= sa) {
    313 -        rc = 2 * sc * dc;
    314 -    } else {
    315 -        rc = sa * da - 2 * (da - dc) * (sa - sc);
    316 -    }
    317 -    return clamp_div255round(rc + sc * (255 - da) + dc * (255 - sa));
    318 -}
    319 -static SkPMColor hardlight_modeproc(SkPMColor src, SkPMColor dst) {
    320 -    int sa = SkGetPackedA32(src);
    321 -    int da = SkGetPackedA32(dst);
    322 -    int a = srcover_byte(sa, da);
    323 -    int r = hardlight_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
    324 -    int g = hardlight_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
    325 -    int b = hardlight_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
    326 +    int r = blendfunc_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da, colorburn_byte);
    327 +    int g = blendfunc_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da, colorburn_byte);
    328 +    int b = blendfunc_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da, colorburn_byte);
    329     return SkPackARGB32(a, r, g, b);
    330 }
    331 
    332 // returns 255 * sqrt(n/255)
    333 static U8CPU sqrt_unit_byte(U8CPU n) {
    334     return SkSqrtBits(n, 15+4);
    335 }
    336 
    337 // kSoftLight_Mode
    338 static inline int softlight_byte(int sc, int dc, int sa, int da) {
    339     int m = da ? dc * 256 / da : 0;
    340     int rc;
    341 -    if (2 * sc <= sa) {
    342 -        rc = dc * (sa + ((2 * sc - sa) * (256 - m) >> 8));
    343 -    } else if (4 * dc <= da) {
    344 +    if (2 * sc <= sa)
    345 +       return dc * (sa + ((2 * sc - sa) * (256 - m) >> 8));
    346 +
    347 +    if (4 * dc <= da) {
    348         int tmp = (4 * m * (4 * m + 256) * (m - 256) >> 16) + 7 * m;
    349 -        rc = dc * sa + (da * (2 * sc - sa) * tmp >> 8);
    350 -    } else {
    351 -        int tmp = sqrt_unit_byte(m) - m;
    352 -        rc = dc * sa + (da * (2 * sc - sa) * tmp >> 8);
    353 +        return dc * sa + (da * (2 * sc - sa) * tmp >> 8);
    354     }
    355 -    return clamp_div255round(rc + sc * (255 - da) + dc * (255 - sa));
    356 +    int tmp = sqrt_unit_byte(m) - m;
    357 +    return rc = dc * sa + (da * (2 * sc - sa) * tmp >> 8);
    358 }
    359 static SkPMColor softlight_modeproc(SkPMColor src, SkPMColor dst) {
    360     int sa = SkGetPackedA32(src);
    361     int da = SkGetPackedA32(dst);
    362     int a = srcover_byte(sa, da);
    363 -    int r = softlight_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
    364 -    int g = softlight_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
    365 -    int b = softlight_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
    366 +    int r = blendfunc_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da, softlight_byte);
    367 +    int g = blendfunc_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da, softlight_byte);
    368 +    int b = blendfunc_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da, softlight_byte);
    369     return SkPackARGB32(a, r, g, b);
    370 }
    371 
    372 // kDifference_Mode
    373 static inline int difference_byte(int sc, int dc, int sa, int da) {
    374 -    int tmp = SkMin32(sc * da, dc * sa);
    375 -    return clamp_signed_byte(sc + dc - 2 * SkDiv255Round(tmp));
    376 +    int tmp = dc * sa - sc * da;
    377 +    if(tmp<0)
    378 +        return - tmp;
    379 +
    380 +    return tmp;
    381 }
    382 static SkPMColor difference_modeproc(SkPMColor src, SkPMColor dst) {
    383     int sa = SkGetPackedA32(src);
    384     int da = SkGetPackedA32(dst);
    385     int a = srcover_byte(sa, da);
    386 -    int r = difference_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
    387 -    int g = difference_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
    388 -    int b = difference_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
    389 +    int r = blendfunc_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da, difference_byte);
    390 +    int g = blendfunc_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da, difference_byte);
    391 +    int b = blendfunc_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da, difference_byte);
    392     return SkPackARGB32(a, r, g, b);
    393 }
    394 
    395 // kExclusion_Mode
    396 static inline int exclusion_byte(int sc, int dc, int sa, int da) {
    397 -    // this equations is wacky, wait for SVG to confirm it
    398 -    int r = sc * da + dc * sa - 2 * sc * dc + sc * (255 - da) + dc * (255 - sa);
    399 -    return clamp_div255round(r);
    400 +    return sc * da + dc * sa - 2 * dc * sc;
    401 }
    402 static SkPMColor exclusion_modeproc(SkPMColor src, SkPMColor dst) {
    403     int sa = SkGetPackedA32(src);
    404     int da = SkGetPackedA32(dst);
    405     int a = srcover_byte(sa, da);
    406 -    int r = exclusion_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
    407 -    int g = exclusion_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
    408 -    int b = exclusion_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
    409 +    int r = blendfunc_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da, exclusion_byte);
    410 +    int g = blendfunc_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da, exclusion_byte);
    411 +    int b = blendfunc_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da, exclusion_byte);
    412 +    return SkPackARGB32(a, r, g, b);
    413 +}
    414 +
    415 +///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    416 +struct BlendColor {
    417 +    float r;
    418 +    float g;
    419 +    float b;
    420 +
    421 +    BlendColor(): r(0), g(0), b(0)
    422 +      {}
    423 +};
    424 +
    425 +static inline float Lum(BlendColor C)
    426 +{
    427 +    return C.r * 0.3 + C.g * 0.59 + C.b* 0.11;
    428 +}
    429 +
    430 +static inline float SkMinFloat(float a, float b)
    431 +{
    432 +  if (a > b)
    433 +    a = b;
    434 +  return a;
    435 +}
    436 +
    437 +static inline float SkMaxFloat(float a, float b)
    438 +{
    439 +  if (a < b)
    440 +    a = b;
    441 +  return a;
    442 +}
    443 +
    444 +#define minimum(C) SkMinFloat(SkMinFloat(C.r, C.g), C.b)
    445 +#define maximum(C) SkMaxFloat(SkMaxFloat(C.r, C.g), C.b)
    446 +
    447 +static inline float Sat(BlendColor c) {
    448 +    return maximum(c) - minimum(c);
    449 +}
    450 +
    451 +static inline void setSaturationComponents(float& Cmin, float& Cmid, float& Cmax, float s) {
    452 +    if(Cmax > Cmin) {
    453 +        Cmid =  (((Cmid - Cmin) * s ) / (Cmax - Cmin));
    454 +        Cmax = s;
    455 +    } else {
    456 +        Cmax = 0;
    457 +        Cmid = 0;
    458 +    }
    459 +    Cmin = 0;
    460 +}
    461 +
    462 +static inline BlendColor SetSat(BlendColor C, float s) {
    463 +    if(C.r <= C.g) {
    464 +        if(C.g <= C.b)
    465 +            setSaturationComponents(C.r, C.g, C.b, s);
    466 +        else
    467 +        if(C.r <= C.b)
    468 +            setSaturationComponents(C.r, C.b, C.g, s);
    469 +        else
    470 +            setSaturationComponents(C.b, C.r, C.g, s);
    471 +        } else if(C.r <= C.b)
    472 +            setSaturationComponents(C.g, C.r, C.b, s);
    473 +        else
    474 +        if(C.g <= C.b)
    475 +            setSaturationComponents(C.g, C.b, C.r, s);
    476 +        else
    477 +            setSaturationComponents(C.b, C.g, C.r, s);
    478 +
    479 +        return C;
    480 +}
    481 +
    482 +static inline BlendColor clipColor(BlendColor C) {
    483 +    float L = Lum(C);
    484 +    float n = minimum(C);
    485 +    float x = maximum(C);
    486 +    if(n < 0) {
    487 +       C.r = L + (((C.r - L) * L) / (L - n));
    488 +       C.g = L + (((C.g - L) * L) / (L - n));
    489 +       C.b = L + (((C.b - L) * L) / (L - n));
    490 +    }
    491 +
    492 +    if(x > 1) {
    493 +       C.r = L + (((C.r - L) * (1 - L)) / (x - L));
    494 +       C.g = L + (((C.g - L) * (1 - L)) / (x - L));
    495 +       C.b = L + (((C.b - L) * (1 - L)) / (x - L));
    496 +    }
    497 +    return C;
    498 +}
    499 +
    500 +static inline BlendColor SetLum(BlendColor C, float l) {
    501 +  float d = l - Lum(C);
    502 +  C.r +=  d;
    503 +  C.g +=  d;
    504 +  C.b +=  d;
    505 +
    506 +  return clipColor(C);
    507 +}
    508 +
    509 +#define  blendfunc_nonsep_byte(sc, dc, sa, da, blendval) \
    510 +  clamp_div255round(sc * (255 - da)  + dc * (255 - sa)  +  (int)(sa * da * blendval))
    511 +
    512 +static SkPMColor hue_modeproc(SkPMColor src, SkPMColor dst) {
    513 +    int sr = SkGetPackedR32(src);
    514 +    int sg = SkGetPackedG32(src);
    515 +    int sb = SkGetPackedB32(src);
    516 +    int sa = SkGetPackedA32(src);
    517 +
    518 +    int dr = SkGetPackedR32(dst);
    519 +    int dg = SkGetPackedG32(dst);
    520 +    int db = SkGetPackedB32(dst);
    521 +    int da = SkGetPackedA32(dst);
    522 +
    523 +    BlendColor Cs;
    524 +    if(sa) {
    525 +        Cs.r  = (float)sr / sa;
    526 +        Cs.g = (float)sg / sa;
    527 +        Cs.b = (float)sb / sa;
    528 +        BlendColor Cd;
    529 +        if(da) {
    530 +            Cd.r =  (float)dr / da;
    531 +            Cd.g = (float)dg / da;
    532 +            Cd.b = (float)db / da;
    533 +            Cs = SetLum(SetSat(Cs, Sat(Cd)), Lum(Cd));
    534 +        }
    535 +    }
    536 +
    537 +    int a = srcover_byte(sa, da);
    538 +    int r = blendfunc_nonsep_byte(sr, dr, sa, da, Cs.r);
    539 +    int g = blendfunc_nonsep_byte(sg, dg, sa, da, Cs.g);
    540 +    int b = blendfunc_nonsep_byte(sb, db, sa, da, Cs.b);
    541 +    return SkPackARGB32(a, r, g, b);
    542 +}
    543 +
    544 +static SkPMColor saturation_modeproc(SkPMColor src, SkPMColor dst) {
    545 +    int sr = SkGetPackedR32(src);
    546 +    int sg = SkGetPackedG32(src);
    547 +    int sb = SkGetPackedB32(src);
    548 +    int sa = SkGetPackedA32(src);
    549 +
    550 +    int dr = SkGetPackedR32(dst);
    551 +    int dg = SkGetPackedG32(dst);
    552 +    int db = SkGetPackedB32(dst);
    553 +    int da = SkGetPackedA32(dst);
    554 +
    555 +    BlendColor Cs;
    556 +    if(sa) {
    557 +        Cs.r  = (float)sr / sa;
    558 +        Cs.g = (float)sg / sa;
    559 +        Cs.b = (float)sb / sa;
    560 +        BlendColor Cd;
    561 +        if(da) {
    562 +            Cd.r =  (float)dr / da;
    563 +            Cd.g = (float)dg / da;
    564 +            Cd.b = (float)db / da;
    565 +            Cs = SetLum(SetSat(Cd, Sat(Cs)), Lum(Cd));
    566 +        }
    567 +    }
    568 +
    569 +    int a = srcover_byte(sa, da);
    570 +    int r = blendfunc_nonsep_byte(sr, dr, sa, da, Cs.r);
    571 +    int g = blendfunc_nonsep_byte(sg, dg, sa, da, Cs.g);
    572 +    int b = blendfunc_nonsep_byte(sb, db, sa, da, Cs.b);
    573 +    return SkPackARGB32(a, r, g, b);
    574 +}
    575 +
    576 +static SkPMColor color_modeproc(SkPMColor src, SkPMColor dst) {
    577 +    int sr = SkGetPackedR32(src);
    578 +    int sg = SkGetPackedG32(src);
    579 +    int sb = SkGetPackedB32(src);
    580 +    int sa = SkGetPackedA32(src);
    581 +
    582 +    int dr = SkGetPackedR32(dst);
    583 +    int dg = SkGetPackedG32(dst);
    584 +    int db = SkGetPackedB32(dst);
    585 +    int da = SkGetPackedA32(dst);
    586 +
    587 +    BlendColor Cs;
    588 +    if(sa) {
    589 +        Cs.r  = (float)sr / sa;
    590 +        Cs.g = (float)sg / sa;
    591 +        Cs.b = (float)sb / sa;
    592 +        BlendColor Cd;
    593 +        if(da) {
    594 +            Cd.r =  (float)dr / da;
    595 +            Cd.g = (float)dg / da;
    596 +            Cd.b = (float)db / da;
    597 +            Cs = SetLum(Cs, Lum(Cd));
    598 +            }
    599 +    }
    600 +
    601 +    int a = srcover_byte(sa, da);
    602 +    int r = blendfunc_nonsep_byte(sr, dr, sa, da, Cs.r);
    603 +    int g = blendfunc_nonsep_byte(sg, dg, sa, da, Cs.g);
    604 +    int b = blendfunc_nonsep_byte(sb, db, sa, da, Cs.b);
    605 +    return SkPackARGB32(a, r, g, b);
    606 +}
    607 +
    608 +static SkPMColor luminosity_modeproc(SkPMColor src, SkPMColor dst) {
    609 +    int sr = SkGetPackedR32(src);
    610 +    int sg = SkGetPackedG32(src);
    611 +    int sb = SkGetPackedB32(src);
    612 +    int sa = SkGetPackedA32(src);
    613 +
    614 +    int dr = SkGetPackedR32(dst);
    615 +    int dg = SkGetPackedG32(dst);
    616 +    int db = SkGetPackedB32(dst);
    617 +    int da = SkGetPackedA32(dst);
    618 +
    619 +    BlendColor Cs;
    620 +    if(sa) {
    621 +        Cs.r  = (float)sr / sa;
    622 +        Cs.g = (float)sg / sa;
    623 +        Cs.b = (float)sb / sa;
    624 +        BlendColor Cd;
    625 +        if(da) {
    626 +            Cd.r =  (float)dr / da;
    627 +            Cd.g = (float)dg / da;
    628 +            Cd.b = (float)db / da;
    629 +            Cs = SetLum(Cd, Lum(Cs));
    630 +            }
    631 +    }
    632 +
    633 +    int a = srcover_byte(sa, da);
    634 +    int r = blendfunc_nonsep_byte(sr, dr, sa, da, Cs.r);
    635 +    int g = blendfunc_nonsep_byte(sg, dg, sa, da, Cs.g);
    636 +    int b = blendfunc_nonsep_byte(sb, db, sa, da, Cs.b);
    637     return SkPackARGB32(a, r, g, b);
    638 }
    639 
    640 struct ProcCoeff {
    641     SkXfermodeProc      fProc;
    642     SkXfermode::Coeff   fSC;
    643     SkXfermode::Coeff   fDC;
    644 };
    645 @@ -430,27 +627,31 @@ static const ProcCoeff gProcCoeffs[] = {
    646     { dstin_modeproc,   SkXfermode::kZero_Coeff,    SkXfermode::kSA_Coeff },
    647     { srcout_modeproc,  SkXfermode::kIDA_Coeff,     SkXfermode::kZero_Coeff },
    648     { dstout_modeproc,  SkXfermode::kZero_Coeff,    SkXfermode::kISA_Coeff },
    649     { srcatop_modeproc, SkXfermode::kDA_Coeff,      SkXfermode::kISA_Coeff },
    650     { dstatop_modeproc, SkXfermode::kIDA_Coeff,     SkXfermode::kSA_Coeff },
    651     { xor_modeproc,     SkXfermode::kIDA_Coeff,     SkXfermode::kISA_Coeff },
    652 
    653     { plus_modeproc,    SkXfermode::kOne_Coeff,     SkXfermode::kOne_Coeff },
    654 -    { multiply_modeproc,SkXfermode::kZero_Coeff,    SkXfermode::kSC_Coeff },
    655 +    { multiply_modeproc,    CANNOT_USE_COEFF,       CANNOT_USE_COEFF},
    656     { screen_modeproc,      CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
    657     { overlay_modeproc,     CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
    658     { darken_modeproc,      CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
    659     { lighten_modeproc,     CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
    660     { colordodge_modeproc,  CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
    661     { colorburn_modeproc,   CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
    662     { hardlight_modeproc,   CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
    663     { softlight_modeproc,   CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
    664     { difference_modeproc,  CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
    665     { exclusion_modeproc,   CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
    666 +    { hue_modeproc,         CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
    667 +    { saturation_modeproc,  CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
    668 +    { color_modeproc,       CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
    669 +    { luminosity_modeproc,  CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
    670 };
    671 
    672 ///////////////////////////////////////////////////////////////////////////////
    673 
    674 bool SkXfermode::asCoeff(Coeff* src, Coeff* dst) {
    675     return false;
    676 }
    677 
    678 @@ -1172,16 +1373,20 @@ static const Proc16Rec gModeProcs16[] = 
    679     { darken_modeproc16_0,  darken_modeproc16_255,  NULL            }, // darken
    680     { lighten_modeproc16_0, lighten_modeproc16_255, NULL            }, // lighten
    681     { NULL,                 NULL,                   NULL            }, // colordodge
    682     { NULL,                 NULL,                   NULL            }, // colorburn
    683     { NULL,                 NULL,                   NULL            }, // hardlight
    684     { NULL,                 NULL,                   NULL            }, // softlight
    685     { NULL,                 NULL,                   NULL            }, // difference
    686     { NULL,                 NULL,                   NULL            }, // exclusion
    687 +    { NULL,                 NULL,                   NULL            }, // hue
    688 +    { NULL,                 NULL,                   NULL            }, // saturation
    689 +    { NULL,                 NULL,                   NULL            }, // color
    690 +    { NULL,                 NULL,                   NULL            }, // luminosity
    691 };
    692 
    693 SkXfermodeProc16 SkXfermode::GetProc16(Mode mode, SkColor srcColor) {
    694     SkXfermodeProc16  proc16 = NULL;
    695     if ((unsigned)mode < kModeCount) {
    696         const Proc16Rec& rec = gModeProcs16[mode];
    697         unsigned a = SkColorGetA(srcColor);