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 +