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);