gfx/skia/patches/archive/0010-Bug-836892-Add-new-blending-modes-to-SkXfermode.patch

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/skia/patches/archive/0010-Bug-836892-Add-new-blending-modes-to-SkXfermode.patch	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,698 @@
     1.4 +# HG changeset patch
     1.5 +# User Rik Cabanier <cabanier@adobe.com>
     1.6 +# Date 1360273929 -46800
     1.7 +# Node ID 3ac8edca3a03b3d22240b5a5b95ae3b5ada9877d
     1.8 +# Parent  cbb67fe70b864b36165061e1fd3b083cd09af087
     1.9 +Bug 836892 - Add new blending modes to SkXfermode. r=gw280
    1.10 +
    1.11 +diff --git a/gfx/skia/include/core/SkXfermode.h b/gfx/skia/include/core/SkXfermode.h
    1.12 +--- a/gfx/skia/include/core/SkXfermode.h
    1.13 ++++ b/gfx/skia/include/core/SkXfermode.h
    1.14 +@@ -96,33 +96,37 @@ public:
    1.15 +         kDstOut_Mode,   //!< [Da * (1 - Sa), Dc * (1 - Sa)]
    1.16 +         kSrcATop_Mode,  //!< [Da, Sc * Da + (1 - Sa) * Dc]
    1.17 +         kDstATop_Mode,  //!< [Sa, Sa * Dc + Sc * (1 - Da)]
    1.18 +         kXor_Mode,      //!< [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc]
    1.19 + 
    1.20 +         // all remaining modes are defined in the SVG Compositing standard
    1.21 +         // http://www.w3.org/TR/2009/WD-SVGCompositing-20090430/
    1.22 +         kPlus_Mode,
    1.23 +-        kMultiply_Mode,
    1.24 + 
    1.25 +         // all above modes can be expressed as pair of src/dst Coeffs
    1.26 +         kCoeffModesCnt,
    1.27 + 
    1.28 +-        kScreen_Mode = kCoeffModesCnt,
    1.29 ++        kMultiply_Mode = kCoeffModesCnt,
    1.30 ++        kScreen_Mode,
    1.31 +         kOverlay_Mode,
    1.32 +         kDarken_Mode,
    1.33 +         kLighten_Mode,
    1.34 +         kColorDodge_Mode,
    1.35 +         kColorBurn_Mode,
    1.36 +         kHardLight_Mode,
    1.37 +         kSoftLight_Mode,
    1.38 +         kDifference_Mode,
    1.39 +         kExclusion_Mode,
    1.40 ++        kHue_Mode,
    1.41 ++        kSaturation_Mode,
    1.42 ++        kColor_Mode,
    1.43 ++        kLuminosity_Mode,
    1.44 + 
    1.45 +-        kLastMode = kExclusion_Mode
    1.46 ++        kLastMode = kLuminosity_Mode
    1.47 +     };
    1.48 + 
    1.49 +     /**
    1.50 +      *  If the xfermode is one of the modes in the Mode enum, then asMode()
    1.51 +      *  returns true and sets (if not null) mode accordingly. Otherwise it
    1.52 +      *  returns false and ignores the mode parameter.
    1.53 +      */
    1.54 +     virtual bool asMode(Mode* mode);
    1.55 +diff --git a/gfx/skia/src/core/SkXfermode.cpp b/gfx/skia/src/core/SkXfermode.cpp
    1.56 +--- a/gfx/skia/src/core/SkXfermode.cpp
    1.57 ++++ b/gfx/skia/src/core/SkXfermode.cpp
    1.58 +@@ -7,16 +7,18 @@
    1.59 +  */
    1.60 + 
    1.61 + 
    1.62 + #include "SkXfermode.h"
    1.63 + #include "SkColorPriv.h"
    1.64 + #include "SkFlattenableBuffers.h"
    1.65 + #include "SkMathPriv.h"
    1.66 + 
    1.67 ++#include <algorithm>
    1.68 ++
    1.69 + SK_DEFINE_INST_COUNT(SkXfermode)
    1.70 + 
    1.71 + #define SkAlphaMulAlpha(a, b)   SkMulDiv255Round(a, b)
    1.72 + 
    1.73 + #if 0
    1.74 + // idea for higher precision blends in xfer procs (and slightly faster)
    1.75 + // see DstATop as a probable caller
    1.76 + static U8CPU mulmuldiv255round(U8CPU a, U8CPU b, U8CPU c, U8CPU d) {
    1.77 +@@ -176,244 +178,439 @@ static SkPMColor xor_modeproc(SkPMColor 
    1.78 + static SkPMColor plus_modeproc(SkPMColor src, SkPMColor dst) {
    1.79 +     unsigned b = saturated_add(SkGetPackedB32(src), SkGetPackedB32(dst));
    1.80 +     unsigned g = saturated_add(SkGetPackedG32(src), SkGetPackedG32(dst));
    1.81 +     unsigned r = saturated_add(SkGetPackedR32(src), SkGetPackedR32(dst));
    1.82 +     unsigned a = saturated_add(SkGetPackedA32(src), SkGetPackedA32(dst));
    1.83 +     return SkPackARGB32(a, r, g, b);
    1.84 + }
    1.85 + 
    1.86 ++static inline int srcover_byte(int a, int b) {
    1.87 ++    return a + b - SkAlphaMulAlpha(a, b);
    1.88 ++}
    1.89 ++
    1.90 ++#define  blendfunc_byte(sc, dc, sa, da, blendfunc) \
    1.91 ++  clamp_div255round(sc * (255 - da)  + dc * (255 - sa)  + blendfunc(sc, dc, sa, da))
    1.92 ++
    1.93 + // kMultiply_Mode
    1.94 ++static inline int multiply_byte(int sc, int dc, int sa, int da) {
    1.95 ++    return sc * dc;
    1.96 ++}
    1.97 + static SkPMColor multiply_modeproc(SkPMColor src, SkPMColor dst) {
    1.98 +-    int a = SkAlphaMulAlpha(SkGetPackedA32(src), SkGetPackedA32(dst));
    1.99 +-    int r = SkAlphaMulAlpha(SkGetPackedR32(src), SkGetPackedR32(dst));
   1.100 +-    int g = SkAlphaMulAlpha(SkGetPackedG32(src), SkGetPackedG32(dst));
   1.101 +-    int b = SkAlphaMulAlpha(SkGetPackedB32(src), SkGetPackedB32(dst));
   1.102 ++    int sa = SkGetPackedA32(src);
   1.103 ++    int da = SkGetPackedA32(dst);
   1.104 ++    int a = srcover_byte(sa, da);
   1.105 ++    int r = blendfunc_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da, multiply_byte);
   1.106 ++    int g = blendfunc_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da, multiply_byte);
   1.107 ++    int b = blendfunc_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da, multiply_byte);
   1.108 +     return SkPackARGB32(a, r, g, b);
   1.109 + }
   1.110 + 
   1.111 + // kScreen_Mode
   1.112 +-static inline int srcover_byte(int a, int b) {
   1.113 +-    return a + b - SkAlphaMulAlpha(a, b);
   1.114 ++static inline int screen_byte(int sc, int dc, int sa, int da) {
   1.115 ++    return sc * da + sa * dc - sc * dc;
   1.116 + }
   1.117 + static SkPMColor screen_modeproc(SkPMColor src, SkPMColor dst) {
   1.118 +-    int a = srcover_byte(SkGetPackedA32(src), SkGetPackedA32(dst));
   1.119 +-    int r = srcover_byte(SkGetPackedR32(src), SkGetPackedR32(dst));
   1.120 +-    int g = srcover_byte(SkGetPackedG32(src), SkGetPackedG32(dst));
   1.121 +-    int b = srcover_byte(SkGetPackedB32(src), SkGetPackedB32(dst));
   1.122 ++    int sa = SkGetPackedA32(src);
   1.123 ++    int da = SkGetPackedA32(dst);
   1.124 ++    int a = srcover_byte(sa, da);
   1.125 ++    int r = blendfunc_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da, screen_byte);
   1.126 ++    int g = blendfunc_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da, screen_byte);
   1.127 ++    int b = blendfunc_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da, screen_byte);
   1.128 ++    return SkPackARGB32(a, r, g, b);
   1.129 ++}
   1.130 ++
   1.131 ++// kHardLight_Mode
   1.132 ++static inline int hardlight_byte(int sc, int dc, int sa, int da) {
   1.133 ++    if(!sa || !da)
   1.134 ++        return sc * da;
   1.135 ++    float Sc = (float)sc/sa;
   1.136 ++    float Dc = (float)dc/da;
   1.137 ++    if(Sc <= 0.5)
   1.138 ++        Sc *= 2 * Dc;
   1.139 ++    else
   1.140 ++        Sc = -1 + 2 * Sc + 2 * Dc - 2 * Sc * Dc;
   1.141 ++
   1.142 ++    return Sc * sa * da;
   1.143 ++}
   1.144 ++static SkPMColor hardlight_modeproc(SkPMColor src, SkPMColor dst) {
   1.145 ++    int sa = SkGetPackedA32(src);
   1.146 ++    int da = SkGetPackedA32(dst);
   1.147 ++    int a = srcover_byte(sa, da);
   1.148 ++    int r = blendfunc_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da, hardlight_byte);
   1.149 ++    int g = blendfunc_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da, hardlight_byte);
   1.150 ++    int b = blendfunc_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da, hardlight_byte);
   1.151 +     return SkPackARGB32(a, r, g, b);
   1.152 + }
   1.153 + 
   1.154 + // kOverlay_Mode
   1.155 + static inline int overlay_byte(int sc, int dc, int sa, int da) {
   1.156 +-    int tmp = sc * (255 - da) + dc * (255 - sa);
   1.157 +-    int rc;
   1.158 +-    if (2 * dc <= da) {
   1.159 +-        rc = 2 * sc * dc;
   1.160 +-    } else {
   1.161 +-        rc = sa * da - 2 * (da - dc) * (sa - sc);
   1.162 +-    }
   1.163 +-    return clamp_div255round(rc + tmp);
   1.164 ++    return hardlight_byte(dc, sc, da, sa);
   1.165 + }
   1.166 + static SkPMColor overlay_modeproc(SkPMColor src, SkPMColor dst) {
   1.167 +     int sa = SkGetPackedA32(src);
   1.168 +     int da = SkGetPackedA32(dst);
   1.169 +     int a = srcover_byte(sa, da);
   1.170 +-    int r = overlay_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
   1.171 +-    int g = overlay_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
   1.172 +-    int b = overlay_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
   1.173 ++    int r = blendfunc_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da, overlay_byte);
   1.174 ++    int g = blendfunc_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da, overlay_byte);
   1.175 ++    int b = blendfunc_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da, overlay_byte);
   1.176 +     return SkPackARGB32(a, r, g, b);
   1.177 + }
   1.178 + 
   1.179 + // kDarken_Mode
   1.180 + static inline int darken_byte(int sc, int dc, int sa, int da) {
   1.181 +-    int sd = sc * da;
   1.182 +-    int ds = dc * sa;
   1.183 +-    if (sd < ds) {
   1.184 +-        // srcover
   1.185 +-        return sc + dc - SkDiv255Round(ds);
   1.186 +-    } else {
   1.187 +-        // dstover
   1.188 +-        return dc + sc - SkDiv255Round(sd);
   1.189 +-    }
   1.190 ++    return SkMin32(sc * da, sa * dc);
   1.191 + }
   1.192 + static SkPMColor darken_modeproc(SkPMColor src, SkPMColor dst) {
   1.193 +     int sa = SkGetPackedA32(src);
   1.194 +     int da = SkGetPackedA32(dst);
   1.195 +     int a = srcover_byte(sa, da);
   1.196 +-    int r = darken_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
   1.197 +-    int g = darken_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
   1.198 +-    int b = darken_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
   1.199 ++    int r = blendfunc_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da, darken_byte);
   1.200 ++    int g = blendfunc_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da, darken_byte);
   1.201 ++    int b = blendfunc_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da, darken_byte);
   1.202 +     return SkPackARGB32(a, r, g, b);
   1.203 + }
   1.204 + 
   1.205 + // kLighten_Mode
   1.206 + static inline int lighten_byte(int sc, int dc, int sa, int da) {
   1.207 +-    int sd = sc * da;
   1.208 +-    int ds = dc * sa;
   1.209 +-    if (sd > ds) {
   1.210 +-        // srcover
   1.211 +-        return sc + dc - SkDiv255Round(ds);
   1.212 +-    } else {
   1.213 +-        // dstover
   1.214 +-        return dc + sc - SkDiv255Round(sd);
   1.215 +-    }
   1.216 ++    return SkMax32(sc * da, sa * dc);
   1.217 + }
   1.218 + static SkPMColor lighten_modeproc(SkPMColor src, SkPMColor dst) {
   1.219 +     int sa = SkGetPackedA32(src);
   1.220 +     int da = SkGetPackedA32(dst);
   1.221 +     int a = srcover_byte(sa, da);
   1.222 +-    int r = lighten_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
   1.223 +-    int g = lighten_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
   1.224 +-    int b = lighten_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
   1.225 ++    int r = blendfunc_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da, lighten_byte);
   1.226 ++    int g = blendfunc_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da, lighten_byte);
   1.227 ++    int b = blendfunc_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da, lighten_byte);
   1.228 +     return SkPackARGB32(a, r, g, b);
   1.229 + }
   1.230 + 
   1.231 + // kColorDodge_Mode
   1.232 + static inline int colordodge_byte(int sc, int dc, int sa, int da) {
   1.233 +-    int diff = sa - sc;
   1.234 +-    int rc;
   1.235 +-    if (0 == diff) {
   1.236 +-        rc = sa * da + sc * (255 - da) + dc * (255 - sa);
   1.237 +-        rc = SkDiv255Round(rc);
   1.238 +-    } else {
   1.239 +-        int tmp = (dc * sa << 15) / (da * diff);
   1.240 +-        rc = SkDiv255Round(sa * da) * tmp >> 15;
   1.241 +-        // don't clamp here, since we'll do it in our modeproc
   1.242 +-    }
   1.243 +-    return rc;
   1.244 ++    if (dc == 0)
   1.245 ++        return 0;
   1.246 ++    // Avoid division by 0
   1.247 ++    if (sc == sa)
   1.248 ++        return da * sa;
   1.249 ++
   1.250 ++    return SkMin32(sa * da, sa * sa * dc / (sa - sc));
   1.251 + }
   1.252 + static SkPMColor colordodge_modeproc(SkPMColor src, SkPMColor dst) {
   1.253 +-    // added to avoid div-by-zero in colordodge_byte
   1.254 +-    if (0 == dst) {
   1.255 +-        return src;
   1.256 +-    }
   1.257 +-
   1.258 +     int sa = SkGetPackedA32(src);
   1.259 +     int da = SkGetPackedA32(dst);
   1.260 +     int a = srcover_byte(sa, da);
   1.261 +-    int r = colordodge_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
   1.262 +-    int g = colordodge_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
   1.263 +-    int b = colordodge_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
   1.264 +-    r = clamp_max(r, a);
   1.265 +-    g = clamp_max(g, a);
   1.266 +-    b = clamp_max(b, a);
   1.267 ++    int r = blendfunc_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da, colordodge_byte);
   1.268 ++    int g = blendfunc_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da, colordodge_byte);
   1.269 ++    int b = blendfunc_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da, colordodge_byte);
   1.270 +     return SkPackARGB32(a, r, g, b);
   1.271 + }
   1.272 + 
   1.273 + // kColorBurn_Mode
   1.274 + static inline int colorburn_byte(int sc, int dc, int sa, int da) {
   1.275 +-    int rc;
   1.276 +-    if (dc == da && 0 == sc) {
   1.277 +-        rc = sa * da + dc * (255 - sa);
   1.278 +-    } else if (0 == sc) {
   1.279 +-        return SkAlphaMulAlpha(dc, 255 - sa);
   1.280 +-    } else {
   1.281 +-        int tmp = (sa * (da - dc) * 256) / (sc * da);
   1.282 +-        if (tmp > 256) {
   1.283 +-            tmp = 256;
   1.284 +-        }
   1.285 +-        int tmp2 = sa * da;
   1.286 +-        rc = tmp2 - (tmp2 * tmp >> 8) + sc * (255 - da) + dc * (255 - sa);
   1.287 +-    }
   1.288 +-    return SkDiv255Round(rc);
   1.289 ++    // Avoid division by 0
   1.290 ++    if(dc == da)
   1.291 ++        return sa * da;
   1.292 ++    if(sc == 0)
   1.293 ++        return 0;
   1.294 ++
   1.295 ++    return sa * da - SkMin32(sa * da, sa * sa * (da - dc) / sc);
   1.296 + }
   1.297 + static SkPMColor colorburn_modeproc(SkPMColor src, SkPMColor dst) {
   1.298 +-    // added to avoid div-by-zero in colorburn_byte
   1.299 +-    if (0 == dst) {
   1.300 +-        return src;
   1.301 +-    }
   1.302 +-
   1.303 +     int sa = SkGetPackedA32(src);
   1.304 +     int da = SkGetPackedA32(dst);
   1.305 +     int a = srcover_byte(sa, da);
   1.306 +-    int r = colorburn_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
   1.307 +-    int g = colorburn_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
   1.308 +-    int b = colorburn_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
   1.309 +-    return SkPackARGB32(a, r, g, b);
   1.310 +-}
   1.311 +-
   1.312 +-// kHardLight_Mode
   1.313 +-static inline int hardlight_byte(int sc, int dc, int sa, int da) {
   1.314 +-    int rc;
   1.315 +-    if (2 * sc <= sa) {
   1.316 +-        rc = 2 * sc * dc;
   1.317 +-    } else {
   1.318 +-        rc = sa * da - 2 * (da - dc) * (sa - sc);
   1.319 +-    }
   1.320 +-    return clamp_div255round(rc + sc * (255 - da) + dc * (255 - sa));
   1.321 +-}
   1.322 +-static SkPMColor hardlight_modeproc(SkPMColor src, SkPMColor dst) {
   1.323 +-    int sa = SkGetPackedA32(src);
   1.324 +-    int da = SkGetPackedA32(dst);
   1.325 +-    int a = srcover_byte(sa, da);
   1.326 +-    int r = hardlight_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
   1.327 +-    int g = hardlight_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
   1.328 +-    int b = hardlight_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
   1.329 ++    int r = blendfunc_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da, colorburn_byte);
   1.330 ++    int g = blendfunc_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da, colorburn_byte);
   1.331 ++    int b = blendfunc_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da, colorburn_byte);
   1.332 +     return SkPackARGB32(a, r, g, b);
   1.333 + }
   1.334 + 
   1.335 + // returns 255 * sqrt(n/255)
   1.336 + static U8CPU sqrt_unit_byte(U8CPU n) {
   1.337 +     return SkSqrtBits(n, 15+4);
   1.338 + }
   1.339 + 
   1.340 + // kSoftLight_Mode
   1.341 + static inline int softlight_byte(int sc, int dc, int sa, int da) {
   1.342 +     int m = da ? dc * 256 / da : 0;
   1.343 +     int rc;
   1.344 +-    if (2 * sc <= sa) {
   1.345 +-        rc = dc * (sa + ((2 * sc - sa) * (256 - m) >> 8));
   1.346 +-    } else if (4 * dc <= da) {
   1.347 ++    if (2 * sc <= sa)
   1.348 ++       return dc * (sa + ((2 * sc - sa) * (256 - m) >> 8));
   1.349 ++
   1.350 ++    if (4 * dc <= da) {
   1.351 +         int tmp = (4 * m * (4 * m + 256) * (m - 256) >> 16) + 7 * m;
   1.352 +-        rc = dc * sa + (da * (2 * sc - sa) * tmp >> 8);
   1.353 +-    } else {
   1.354 +-        int tmp = sqrt_unit_byte(m) - m;
   1.355 +-        rc = dc * sa + (da * (2 * sc - sa) * tmp >> 8);
   1.356 ++        return dc * sa + (da * (2 * sc - sa) * tmp >> 8);
   1.357 +     }
   1.358 +-    return clamp_div255round(rc + sc * (255 - da) + dc * (255 - sa));
   1.359 ++    int tmp = sqrt_unit_byte(m) - m;
   1.360 ++    return rc = dc * sa + (da * (2 * sc - sa) * tmp >> 8);
   1.361 + }
   1.362 + static SkPMColor softlight_modeproc(SkPMColor src, SkPMColor dst) {
   1.363 +     int sa = SkGetPackedA32(src);
   1.364 +     int da = SkGetPackedA32(dst);
   1.365 +     int a = srcover_byte(sa, da);
   1.366 +-    int r = softlight_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
   1.367 +-    int g = softlight_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
   1.368 +-    int b = softlight_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
   1.369 ++    int r = blendfunc_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da, softlight_byte);
   1.370 ++    int g = blendfunc_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da, softlight_byte);
   1.371 ++    int b = blendfunc_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da, softlight_byte);
   1.372 +     return SkPackARGB32(a, r, g, b);
   1.373 + }
   1.374 + 
   1.375 + // kDifference_Mode
   1.376 + static inline int difference_byte(int sc, int dc, int sa, int da) {
   1.377 +-    int tmp = SkMin32(sc * da, dc * sa);
   1.378 +-    return clamp_signed_byte(sc + dc - 2 * SkDiv255Round(tmp));
   1.379 ++    int tmp = dc * sa - sc * da;
   1.380 ++    if(tmp<0)
   1.381 ++        return - tmp;
   1.382 ++
   1.383 ++    return tmp;
   1.384 + }
   1.385 + static SkPMColor difference_modeproc(SkPMColor src, SkPMColor dst) {
   1.386 +     int sa = SkGetPackedA32(src);
   1.387 +     int da = SkGetPackedA32(dst);
   1.388 +     int a = srcover_byte(sa, da);
   1.389 +-    int r = difference_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
   1.390 +-    int g = difference_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
   1.391 +-    int b = difference_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
   1.392 ++    int r = blendfunc_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da, difference_byte);
   1.393 ++    int g = blendfunc_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da, difference_byte);
   1.394 ++    int b = blendfunc_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da, difference_byte);
   1.395 +     return SkPackARGB32(a, r, g, b);
   1.396 + }
   1.397 + 
   1.398 + // kExclusion_Mode
   1.399 + static inline int exclusion_byte(int sc, int dc, int sa, int da) {
   1.400 +-    // this equations is wacky, wait for SVG to confirm it
   1.401 +-    int r = sc * da + dc * sa - 2 * sc * dc + sc * (255 - da) + dc * (255 - sa);
   1.402 +-    return clamp_div255round(r);
   1.403 ++    return sc * da + dc * sa - 2 * dc * sc;
   1.404 + }
   1.405 + static SkPMColor exclusion_modeproc(SkPMColor src, SkPMColor dst) {
   1.406 +     int sa = SkGetPackedA32(src);
   1.407 +     int da = SkGetPackedA32(dst);
   1.408 +     int a = srcover_byte(sa, da);
   1.409 +-    int r = exclusion_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da);
   1.410 +-    int g = exclusion_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da);
   1.411 +-    int b = exclusion_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da);
   1.412 ++    int r = blendfunc_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da, exclusion_byte);
   1.413 ++    int g = blendfunc_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da, exclusion_byte);
   1.414 ++    int b = blendfunc_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da, exclusion_byte);
   1.415 ++    return SkPackARGB32(a, r, g, b);
   1.416 ++}
   1.417 ++
   1.418 ++///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
   1.419 ++struct BlendColor {
   1.420 ++    float r;
   1.421 ++    float g;
   1.422 ++    float b;
   1.423 ++
   1.424 ++    BlendColor(): r(0), g(0), b(0)
   1.425 ++      {}
   1.426 ++};
   1.427 ++
   1.428 ++static inline float Lum(BlendColor C)
   1.429 ++{
   1.430 ++    return C.r * 0.3 + C.g * 0.59 + C.b* 0.11;
   1.431 ++}
   1.432 ++
   1.433 ++static inline float SkMinFloat(float a, float b)
   1.434 ++{
   1.435 ++  if (a > b)
   1.436 ++    a = b;
   1.437 ++  return a;
   1.438 ++}
   1.439 ++
   1.440 ++static inline float SkMaxFloat(float a, float b)
   1.441 ++{
   1.442 ++  if (a < b)
   1.443 ++    a = b;
   1.444 ++  return a;
   1.445 ++}
   1.446 ++
   1.447 ++#define minimum(C) SkMinFloat(SkMinFloat(C.r, C.g), C.b)
   1.448 ++#define maximum(C) SkMaxFloat(SkMaxFloat(C.r, C.g), C.b)
   1.449 ++
   1.450 ++static inline float Sat(BlendColor c) {
   1.451 ++    return maximum(c) - minimum(c);
   1.452 ++}
   1.453 ++
   1.454 ++static inline void setSaturationComponents(float& Cmin, float& Cmid, float& Cmax, float s) {
   1.455 ++    if(Cmax > Cmin) {
   1.456 ++        Cmid =  (((Cmid - Cmin) * s ) / (Cmax - Cmin));
   1.457 ++        Cmax = s;
   1.458 ++    } else {
   1.459 ++        Cmax = 0;
   1.460 ++        Cmid = 0;
   1.461 ++    }
   1.462 ++    Cmin = 0;
   1.463 ++}
   1.464 ++
   1.465 ++static inline BlendColor SetSat(BlendColor C, float s) {
   1.466 ++    if(C.r <= C.g) {
   1.467 ++        if(C.g <= C.b)
   1.468 ++            setSaturationComponents(C.r, C.g, C.b, s);
   1.469 ++        else
   1.470 ++        if(C.r <= C.b)
   1.471 ++            setSaturationComponents(C.r, C.b, C.g, s);
   1.472 ++        else
   1.473 ++            setSaturationComponents(C.b, C.r, C.g, s);
   1.474 ++        } else if(C.r <= C.b)
   1.475 ++            setSaturationComponents(C.g, C.r, C.b, s);
   1.476 ++        else
   1.477 ++        if(C.g <= C.b)
   1.478 ++            setSaturationComponents(C.g, C.b, C.r, s);
   1.479 ++        else
   1.480 ++            setSaturationComponents(C.b, C.g, C.r, s);
   1.481 ++
   1.482 ++        return C;
   1.483 ++}
   1.484 ++
   1.485 ++static inline BlendColor clipColor(BlendColor C) {
   1.486 ++    float L = Lum(C);
   1.487 ++    float n = minimum(C);
   1.488 ++    float x = maximum(C);
   1.489 ++    if(n < 0) {
   1.490 ++       C.r = L + (((C.r - L) * L) / (L - n));
   1.491 ++       C.g = L + (((C.g - L) * L) / (L - n));
   1.492 ++       C.b = L + (((C.b - L) * L) / (L - n));
   1.493 ++    }
   1.494 ++
   1.495 ++    if(x > 1) {
   1.496 ++       C.r = L + (((C.r - L) * (1 - L)) / (x - L));
   1.497 ++       C.g = L + (((C.g - L) * (1 - L)) / (x - L));
   1.498 ++       C.b = L + (((C.b - L) * (1 - L)) / (x - L));
   1.499 ++    }
   1.500 ++    return C;
   1.501 ++}
   1.502 ++
   1.503 ++static inline BlendColor SetLum(BlendColor C, float l) {
   1.504 ++  float d = l - Lum(C);
   1.505 ++  C.r +=  d;
   1.506 ++  C.g +=  d;
   1.507 ++  C.b +=  d;
   1.508 ++
   1.509 ++  return clipColor(C);
   1.510 ++}
   1.511 ++
   1.512 ++#define  blendfunc_nonsep_byte(sc, dc, sa, da, blendval) \
   1.513 ++  clamp_div255round(sc * (255 - da)  + dc * (255 - sa)  +  (int)(sa * da * blendval))
   1.514 ++
   1.515 ++static SkPMColor hue_modeproc(SkPMColor src, SkPMColor dst) {
   1.516 ++    int sr = SkGetPackedR32(src);
   1.517 ++    int sg = SkGetPackedG32(src);
   1.518 ++    int sb = SkGetPackedB32(src);
   1.519 ++    int sa = SkGetPackedA32(src);
   1.520 ++
   1.521 ++    int dr = SkGetPackedR32(dst);
   1.522 ++    int dg = SkGetPackedG32(dst);
   1.523 ++    int db = SkGetPackedB32(dst);
   1.524 ++    int da = SkGetPackedA32(dst);
   1.525 ++
   1.526 ++    BlendColor Cs;
   1.527 ++    if(sa) {
   1.528 ++        Cs.r  = (float)sr / sa;
   1.529 ++        Cs.g = (float)sg / sa;
   1.530 ++        Cs.b = (float)sb / sa;
   1.531 ++        BlendColor Cd;
   1.532 ++        if(da) {
   1.533 ++            Cd.r =  (float)dr / da;
   1.534 ++            Cd.g = (float)dg / da;
   1.535 ++            Cd.b = (float)db / da;
   1.536 ++            Cs = SetLum(SetSat(Cs, Sat(Cd)), Lum(Cd));
   1.537 ++        }
   1.538 ++    }
   1.539 ++
   1.540 ++    int a = srcover_byte(sa, da);
   1.541 ++    int r = blendfunc_nonsep_byte(sr, dr, sa, da, Cs.r);
   1.542 ++    int g = blendfunc_nonsep_byte(sg, dg, sa, da, Cs.g);
   1.543 ++    int b = blendfunc_nonsep_byte(sb, db, sa, da, Cs.b);
   1.544 ++    return SkPackARGB32(a, r, g, b);
   1.545 ++}
   1.546 ++
   1.547 ++static SkPMColor saturation_modeproc(SkPMColor src, SkPMColor dst) {
   1.548 ++    int sr = SkGetPackedR32(src);
   1.549 ++    int sg = SkGetPackedG32(src);
   1.550 ++    int sb = SkGetPackedB32(src);
   1.551 ++    int sa = SkGetPackedA32(src);
   1.552 ++
   1.553 ++    int dr = SkGetPackedR32(dst);
   1.554 ++    int dg = SkGetPackedG32(dst);
   1.555 ++    int db = SkGetPackedB32(dst);
   1.556 ++    int da = SkGetPackedA32(dst);
   1.557 ++
   1.558 ++    BlendColor Cs;
   1.559 ++    if(sa) {
   1.560 ++        Cs.r  = (float)sr / sa;
   1.561 ++        Cs.g = (float)sg / sa;
   1.562 ++        Cs.b = (float)sb / sa;
   1.563 ++        BlendColor Cd;
   1.564 ++        if(da) {
   1.565 ++            Cd.r =  (float)dr / da;
   1.566 ++            Cd.g = (float)dg / da;
   1.567 ++            Cd.b = (float)db / da;
   1.568 ++            Cs = SetLum(SetSat(Cd, Sat(Cs)), Lum(Cd));
   1.569 ++        }
   1.570 ++    }
   1.571 ++
   1.572 ++    int a = srcover_byte(sa, da);
   1.573 ++    int r = blendfunc_nonsep_byte(sr, dr, sa, da, Cs.r);
   1.574 ++    int g = blendfunc_nonsep_byte(sg, dg, sa, da, Cs.g);
   1.575 ++    int b = blendfunc_nonsep_byte(sb, db, sa, da, Cs.b);
   1.576 ++    return SkPackARGB32(a, r, g, b);
   1.577 ++}
   1.578 ++
   1.579 ++static SkPMColor color_modeproc(SkPMColor src, SkPMColor dst) {
   1.580 ++    int sr = SkGetPackedR32(src);
   1.581 ++    int sg = SkGetPackedG32(src);
   1.582 ++    int sb = SkGetPackedB32(src);
   1.583 ++    int sa = SkGetPackedA32(src);
   1.584 ++
   1.585 ++    int dr = SkGetPackedR32(dst);
   1.586 ++    int dg = SkGetPackedG32(dst);
   1.587 ++    int db = SkGetPackedB32(dst);
   1.588 ++    int da = SkGetPackedA32(dst);
   1.589 ++
   1.590 ++    BlendColor Cs;
   1.591 ++    if(sa) {
   1.592 ++        Cs.r  = (float)sr / sa;
   1.593 ++        Cs.g = (float)sg / sa;
   1.594 ++        Cs.b = (float)sb / sa;
   1.595 ++        BlendColor Cd;
   1.596 ++        if(da) {
   1.597 ++            Cd.r =  (float)dr / da;
   1.598 ++            Cd.g = (float)dg / da;
   1.599 ++            Cd.b = (float)db / da;
   1.600 ++            Cs = SetLum(Cs, Lum(Cd));
   1.601 ++            }
   1.602 ++    }
   1.603 ++
   1.604 ++    int a = srcover_byte(sa, da);
   1.605 ++    int r = blendfunc_nonsep_byte(sr, dr, sa, da, Cs.r);
   1.606 ++    int g = blendfunc_nonsep_byte(sg, dg, sa, da, Cs.g);
   1.607 ++    int b = blendfunc_nonsep_byte(sb, db, sa, da, Cs.b);
   1.608 ++    return SkPackARGB32(a, r, g, b);
   1.609 ++}
   1.610 ++
   1.611 ++static SkPMColor luminosity_modeproc(SkPMColor src, SkPMColor dst) {
   1.612 ++    int sr = SkGetPackedR32(src);
   1.613 ++    int sg = SkGetPackedG32(src);
   1.614 ++    int sb = SkGetPackedB32(src);
   1.615 ++    int sa = SkGetPackedA32(src);
   1.616 ++
   1.617 ++    int dr = SkGetPackedR32(dst);
   1.618 ++    int dg = SkGetPackedG32(dst);
   1.619 ++    int db = SkGetPackedB32(dst);
   1.620 ++    int da = SkGetPackedA32(dst);
   1.621 ++
   1.622 ++    BlendColor Cs;
   1.623 ++    if(sa) {
   1.624 ++        Cs.r  = (float)sr / sa;
   1.625 ++        Cs.g = (float)sg / sa;
   1.626 ++        Cs.b = (float)sb / sa;
   1.627 ++        BlendColor Cd;
   1.628 ++        if(da) {
   1.629 ++            Cd.r =  (float)dr / da;
   1.630 ++            Cd.g = (float)dg / da;
   1.631 ++            Cd.b = (float)db / da;
   1.632 ++            Cs = SetLum(Cd, Lum(Cs));
   1.633 ++            }
   1.634 ++    }
   1.635 ++
   1.636 ++    int a = srcover_byte(sa, da);
   1.637 ++    int r = blendfunc_nonsep_byte(sr, dr, sa, da, Cs.r);
   1.638 ++    int g = blendfunc_nonsep_byte(sg, dg, sa, da, Cs.g);
   1.639 ++    int b = blendfunc_nonsep_byte(sb, db, sa, da, Cs.b);
   1.640 +     return SkPackARGB32(a, r, g, b);
   1.641 + }
   1.642 + 
   1.643 + struct ProcCoeff {
   1.644 +     SkXfermodeProc      fProc;
   1.645 +     SkXfermode::Coeff   fSC;
   1.646 +     SkXfermode::Coeff   fDC;
   1.647 + };
   1.648 +@@ -430,27 +627,31 @@ static const ProcCoeff gProcCoeffs[] = {
   1.649 +     { dstin_modeproc,   SkXfermode::kZero_Coeff,    SkXfermode::kSA_Coeff },
   1.650 +     { srcout_modeproc,  SkXfermode::kIDA_Coeff,     SkXfermode::kZero_Coeff },
   1.651 +     { dstout_modeproc,  SkXfermode::kZero_Coeff,    SkXfermode::kISA_Coeff },
   1.652 +     { srcatop_modeproc, SkXfermode::kDA_Coeff,      SkXfermode::kISA_Coeff },
   1.653 +     { dstatop_modeproc, SkXfermode::kIDA_Coeff,     SkXfermode::kSA_Coeff },
   1.654 +     { xor_modeproc,     SkXfermode::kIDA_Coeff,     SkXfermode::kISA_Coeff },
   1.655 + 
   1.656 +     { plus_modeproc,    SkXfermode::kOne_Coeff,     SkXfermode::kOne_Coeff },
   1.657 +-    { multiply_modeproc,SkXfermode::kZero_Coeff,    SkXfermode::kSC_Coeff },
   1.658 ++    { multiply_modeproc,    CANNOT_USE_COEFF,       CANNOT_USE_COEFF},
   1.659 +     { screen_modeproc,      CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
   1.660 +     { overlay_modeproc,     CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
   1.661 +     { darken_modeproc,      CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
   1.662 +     { lighten_modeproc,     CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
   1.663 +     { colordodge_modeproc,  CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
   1.664 +     { colorburn_modeproc,   CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
   1.665 +     { hardlight_modeproc,   CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
   1.666 +     { softlight_modeproc,   CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
   1.667 +     { difference_modeproc,  CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
   1.668 +     { exclusion_modeproc,   CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
   1.669 ++    { hue_modeproc,         CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
   1.670 ++    { saturation_modeproc,  CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
   1.671 ++    { color_modeproc,       CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
   1.672 ++    { luminosity_modeproc,  CANNOT_USE_COEFF,       CANNOT_USE_COEFF },
   1.673 + };
   1.674 + 
   1.675 + ///////////////////////////////////////////////////////////////////////////////
   1.676 + 
   1.677 + bool SkXfermode::asCoeff(Coeff* src, Coeff* dst) {
   1.678 +     return false;
   1.679 + }
   1.680 + 
   1.681 +@@ -1172,16 +1373,20 @@ static const Proc16Rec gModeProcs16[] = 
   1.682 +     { darken_modeproc16_0,  darken_modeproc16_255,  NULL            }, // darken
   1.683 +     { lighten_modeproc16_0, lighten_modeproc16_255, NULL            }, // lighten
   1.684 +     { NULL,                 NULL,                   NULL            }, // colordodge
   1.685 +     { NULL,                 NULL,                   NULL            }, // colorburn
   1.686 +     { NULL,                 NULL,                   NULL            }, // hardlight
   1.687 +     { NULL,                 NULL,                   NULL            }, // softlight
   1.688 +     { NULL,                 NULL,                   NULL            }, // difference
   1.689 +     { NULL,                 NULL,                   NULL            }, // exclusion
   1.690 ++    { NULL,                 NULL,                   NULL            }, // hue
   1.691 ++    { NULL,                 NULL,                   NULL            }, // saturation
   1.692 ++    { NULL,                 NULL,                   NULL            }, // color
   1.693 ++    { NULL,                 NULL,                   NULL            }, // luminosity
   1.694 + };
   1.695 + 
   1.696 + SkXfermodeProc16 SkXfermode::GetProc16(Mode mode, SkColor srcColor) {
   1.697 +     SkXfermodeProc16  proc16 = NULL;
   1.698 +     if ((unsigned)mode < kModeCount) {
   1.699 +         const Proc16Rec& rec = gModeProcs16[mode];
   1.700 +         unsigned a = SkColorGetA(srcColor);
   1.701 + 

mercurial