SkXfermode.cpp revision d7aaf6034e519ea9b70649c1d344f2f24de90ccb
1 2/* 3 * Copyright 2006 The Android Open Source Project 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9 10#include "SkXfermode.h" 11#include "SkColorPriv.h" 12#include "SkFlattenableBuffers.h" 13#include "SkMathPriv.h" 14#include "SkString.h" 15 16SK_DEFINE_INST_COUNT(SkXfermode) 17 18#define SkAlphaMulAlpha(a, b) SkMulDiv255Round(a, b) 19 20#if 0 21// idea for higher precision blends in xfer procs (and slightly faster) 22// see DstATop as a probable caller 23static U8CPU mulmuldiv255round(U8CPU a, U8CPU b, U8CPU c, U8CPU d) { 24 SkASSERT(a <= 255); 25 SkASSERT(b <= 255); 26 SkASSERT(c <= 255); 27 SkASSERT(d <= 255); 28 unsigned prod = SkMulS16(a, b) + SkMulS16(c, d) + 128; 29 unsigned result = (prod + (prod >> 8)) >> 8; 30 SkASSERT(result <= 255); 31 return result; 32} 33#endif 34 35static inline unsigned saturated_add(unsigned a, unsigned b) { 36 SkASSERT(a <= 255); 37 SkASSERT(b <= 255); 38 unsigned sum = a + b; 39 if (sum > 255) { 40 sum = 255; 41 } 42 return sum; 43} 44 45static inline int clamp_signed_byte(int n) { 46 if (n < 0) { 47 n = 0; 48 } else if (n > 255) { 49 n = 255; 50 } 51 return n; 52} 53 54static inline int clamp_div255round(int prod) { 55 if (prod <= 0) { 56 return 0; 57 } else if (prod >= 255*255) { 58 return 255; 59 } else { 60 return SkDiv255Round(prod); 61 } 62} 63 64static inline int clamp_max(int value, int max) { 65 if (value > max) { 66 value = max; 67 } 68 return value; 69} 70 71/////////////////////////////////////////////////////////////////////////////// 72 73// kClear_Mode, //!< [0, 0] 74static SkPMColor clear_modeproc(SkPMColor src, SkPMColor dst) { 75 return 0; 76} 77 78// kSrc_Mode, //!< [Sa, Sc] 79static SkPMColor src_modeproc(SkPMColor src, SkPMColor dst) { 80 return src; 81} 82 83// kDst_Mode, //!< [Da, Dc] 84static SkPMColor dst_modeproc(SkPMColor src, SkPMColor dst) { 85 return dst; 86} 87 88// kSrcOver_Mode, //!< [Sa + Da - Sa*Da, Sc + (1 - Sa)*Dc] 89static SkPMColor srcover_modeproc(SkPMColor src, SkPMColor dst) { 90#if 0 91 // this is the old, more-correct way, but it doesn't guarantee that dst==255 92 // will always stay opaque 93 return src + SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src))); 94#else 95 // this is slightly faster, but more importantly guarantees that dst==255 96 // will always stay opaque 97 return src + SkAlphaMulQ(dst, 256 - SkGetPackedA32(src)); 98#endif 99} 100 101// kDstOver_Mode, //!< [Sa + Da - Sa*Da, Dc + (1 - Da)*Sc] 102static SkPMColor dstover_modeproc(SkPMColor src, SkPMColor dst) { 103 // this is the reverse of srcover, just flipping src and dst 104 // see srcover's comment about the 256 for opaqueness guarantees 105 return dst + SkAlphaMulQ(src, 256 - SkGetPackedA32(dst)); 106} 107 108// kSrcIn_Mode, //!< [Sa * Da, Sc * Da] 109static SkPMColor srcin_modeproc(SkPMColor src, SkPMColor dst) { 110 return SkAlphaMulQ(src, SkAlpha255To256(SkGetPackedA32(dst))); 111} 112 113// kDstIn_Mode, //!< [Sa * Da, Sa * Dc] 114static SkPMColor dstin_modeproc(SkPMColor src, SkPMColor dst) { 115 return SkAlphaMulQ(dst, SkAlpha255To256(SkGetPackedA32(src))); 116} 117 118// kSrcOut_Mode, //!< [Sa * (1 - Da), Sc * (1 - Da)] 119static SkPMColor srcout_modeproc(SkPMColor src, SkPMColor dst) { 120 return SkAlphaMulQ(src, SkAlpha255To256(255 - SkGetPackedA32(dst))); 121} 122 123// kDstOut_Mode, //!< [Da * (1 - Sa), Dc * (1 - Sa)] 124static SkPMColor dstout_modeproc(SkPMColor src, SkPMColor dst) { 125 return SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src))); 126} 127 128// kSrcATop_Mode, //!< [Da, Sc * Da + (1 - Sa) * Dc] 129static SkPMColor srcatop_modeproc(SkPMColor src, SkPMColor dst) { 130 unsigned sa = SkGetPackedA32(src); 131 unsigned da = SkGetPackedA32(dst); 132 unsigned isa = 255 - sa; 133 134 return SkPackARGB32(da, 135 SkAlphaMulAlpha(da, SkGetPackedR32(src)) + 136 SkAlphaMulAlpha(isa, SkGetPackedR32(dst)), 137 SkAlphaMulAlpha(da, SkGetPackedG32(src)) + 138 SkAlphaMulAlpha(isa, SkGetPackedG32(dst)), 139 SkAlphaMulAlpha(da, SkGetPackedB32(src)) + 140 SkAlphaMulAlpha(isa, SkGetPackedB32(dst))); 141} 142 143// kDstATop_Mode, //!< [Sa, Sa * Dc + Sc * (1 - Da)] 144static SkPMColor dstatop_modeproc(SkPMColor src, SkPMColor dst) { 145 unsigned sa = SkGetPackedA32(src); 146 unsigned da = SkGetPackedA32(dst); 147 unsigned ida = 255 - da; 148 149 return SkPackARGB32(sa, 150 SkAlphaMulAlpha(ida, SkGetPackedR32(src)) + 151 SkAlphaMulAlpha(sa, SkGetPackedR32(dst)), 152 SkAlphaMulAlpha(ida, SkGetPackedG32(src)) + 153 SkAlphaMulAlpha(sa, SkGetPackedG32(dst)), 154 SkAlphaMulAlpha(ida, SkGetPackedB32(src)) + 155 SkAlphaMulAlpha(sa, SkGetPackedB32(dst))); 156} 157 158// kXor_Mode [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc] 159static SkPMColor xor_modeproc(SkPMColor src, SkPMColor dst) { 160 unsigned sa = SkGetPackedA32(src); 161 unsigned da = SkGetPackedA32(dst); 162 unsigned isa = 255 - sa; 163 unsigned ida = 255 - da; 164 165 return SkPackARGB32(sa + da - (SkAlphaMulAlpha(sa, da) << 1), 166 SkAlphaMulAlpha(ida, SkGetPackedR32(src)) + 167 SkAlphaMulAlpha(isa, SkGetPackedR32(dst)), 168 SkAlphaMulAlpha(ida, SkGetPackedG32(src)) + 169 SkAlphaMulAlpha(isa, SkGetPackedG32(dst)), 170 SkAlphaMulAlpha(ida, SkGetPackedB32(src)) + 171 SkAlphaMulAlpha(isa, SkGetPackedB32(dst))); 172} 173 174/////////////////////////////////////////////////////////////////////////////// 175 176// kPlus_Mode 177static SkPMColor plus_modeproc(SkPMColor src, SkPMColor dst) { 178 unsigned b = saturated_add(SkGetPackedB32(src), SkGetPackedB32(dst)); 179 unsigned g = saturated_add(SkGetPackedG32(src), SkGetPackedG32(dst)); 180 unsigned r = saturated_add(SkGetPackedR32(src), SkGetPackedR32(dst)); 181 unsigned a = saturated_add(SkGetPackedA32(src), SkGetPackedA32(dst)); 182 return SkPackARGB32(a, r, g, b); 183} 184 185// kModulate_Mode 186static SkPMColor modulate_modeproc(SkPMColor src, SkPMColor dst) { 187 int a = SkAlphaMulAlpha(SkGetPackedA32(src), SkGetPackedA32(dst)); 188 int r = SkAlphaMulAlpha(SkGetPackedR32(src), SkGetPackedR32(dst)); 189 int g = SkAlphaMulAlpha(SkGetPackedG32(src), SkGetPackedG32(dst)); 190 int b = SkAlphaMulAlpha(SkGetPackedB32(src), SkGetPackedB32(dst)); 191 return SkPackARGB32(a, r, g, b); 192} 193 194static inline int srcover_byte(int a, int b) { 195 return a + b - SkAlphaMulAlpha(a, b); 196} 197 198// kMultiply_Mode 199// B(Cb, Cs) = Cb x Cs 200// multiply uses its own version of blendfunc_byte because sa and da are not needed 201static int blendfunc_multiply_byte(int sc, int dc, int sa, int da) { 202 return clamp_div255round(sc * (255 - da) + dc * (255 - sa) + sc * dc); 203} 204 205static SkPMColor multiply_modeproc(SkPMColor src, SkPMColor dst) { 206 int sa = SkGetPackedA32(src); 207 int da = SkGetPackedA32(dst); 208 int a = srcover_byte(sa, da); 209 int r = blendfunc_multiply_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da); 210 int g = blendfunc_multiply_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da); 211 int b = blendfunc_multiply_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da); 212 return SkPackARGB32(a, r, g, b); 213} 214 215// kScreen_Mode 216static SkPMColor screen_modeproc(SkPMColor src, SkPMColor dst) { 217 int a = srcover_byte(SkGetPackedA32(src), SkGetPackedA32(dst)); 218 int r = srcover_byte(SkGetPackedR32(src), SkGetPackedR32(dst)); 219 int g = srcover_byte(SkGetPackedG32(src), SkGetPackedG32(dst)); 220 int b = srcover_byte(SkGetPackedB32(src), SkGetPackedB32(dst)); 221 return SkPackARGB32(a, r, g, b); 222} 223 224// kOverlay_Mode 225static inline int overlay_byte(int sc, int dc, int sa, int da) { 226 int tmp = sc * (255 - da) + dc * (255 - sa); 227 int rc; 228 if (2 * dc <= da) { 229 rc = 2 * sc * dc; 230 } else { 231 rc = sa * da - 2 * (da - dc) * (sa - sc); 232 } 233 return clamp_div255round(rc + tmp); 234} 235static SkPMColor overlay_modeproc(SkPMColor src, SkPMColor dst) { 236 int sa = SkGetPackedA32(src); 237 int da = SkGetPackedA32(dst); 238 int a = srcover_byte(sa, da); 239 int r = overlay_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da); 240 int g = overlay_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da); 241 int b = overlay_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da); 242 return SkPackARGB32(a, r, g, b); 243} 244 245// kDarken_Mode 246static inline int darken_byte(int sc, int dc, int sa, int da) { 247 int sd = sc * da; 248 int ds = dc * sa; 249 if (sd < ds) { 250 // srcover 251 return sc + dc - SkDiv255Round(ds); 252 } else { 253 // dstover 254 return dc + sc - SkDiv255Round(sd); 255 } 256} 257static SkPMColor darken_modeproc(SkPMColor src, SkPMColor dst) { 258 int sa = SkGetPackedA32(src); 259 int da = SkGetPackedA32(dst); 260 int a = srcover_byte(sa, da); 261 int r = darken_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da); 262 int g = darken_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da); 263 int b = darken_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da); 264 return SkPackARGB32(a, r, g, b); 265} 266 267// kLighten_Mode 268static inline int lighten_byte(int sc, int dc, int sa, int da) { 269 int sd = sc * da; 270 int ds = dc * sa; 271 if (sd > ds) { 272 // srcover 273 return sc + dc - SkDiv255Round(ds); 274 } else { 275 // dstover 276 return dc + sc - SkDiv255Round(sd); 277 } 278} 279static SkPMColor lighten_modeproc(SkPMColor src, SkPMColor dst) { 280 int sa = SkGetPackedA32(src); 281 int da = SkGetPackedA32(dst); 282 int a = srcover_byte(sa, da); 283 int r = lighten_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da); 284 int g = lighten_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da); 285 int b = lighten_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da); 286 return SkPackARGB32(a, r, g, b); 287} 288 289// kColorDodge_Mode 290static inline int colordodge_byte(int sc, int dc, int sa, int da) { 291 int diff = sa - sc; 292 int rc; 293 if (0 == dc) { 294 return SkAlphaMulAlpha(sc, 255 - da); 295 } else if (0 == diff) { 296 rc = sa * da + sc * (255 - da) + dc * (255 - sa); 297 } else { 298 diff = dc * sa / diff; 299 rc = sa * ((da < diff) ? da : diff) + sc * (255 - da) + dc * (255 - sa); 300 } 301 return clamp_div255round(rc); 302} 303static SkPMColor colordodge_modeproc(SkPMColor src, SkPMColor dst) { 304 int sa = SkGetPackedA32(src); 305 int da = SkGetPackedA32(dst); 306 int a = srcover_byte(sa, da); 307 int r = colordodge_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da); 308 int g = colordodge_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da); 309 int b = colordodge_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da); 310 return SkPackARGB32(a, r, g, b); 311} 312 313// kColorBurn_Mode 314static inline int colorburn_byte(int sc, int dc, int sa, int da) { 315 int rc; 316 if (dc == da) { 317 rc = sa * da + sc * (255 - da) + dc * (255 - sa); 318 } else if (0 == sc) { 319 return SkAlphaMulAlpha(dc, 255 - sa); 320 } else { 321 int tmp = (da - dc) * sa / sc; 322 rc = sa * (da - ((da < tmp) ? da : tmp)) 323 + sc * (255 - da) + dc * (255 - sa); 324 } 325 return clamp_div255round(rc); 326} 327static SkPMColor colorburn_modeproc(SkPMColor src, SkPMColor dst) { 328 int sa = SkGetPackedA32(src); 329 int da = SkGetPackedA32(dst); 330 int a = srcover_byte(sa, da); 331 int r = colorburn_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da); 332 int g = colorburn_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da); 333 int b = colorburn_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da); 334 return SkPackARGB32(a, r, g, b); 335} 336 337// kHardLight_Mode 338static inline int hardlight_byte(int sc, int dc, int sa, int da) { 339 int rc; 340 if (2 * sc <= sa) { 341 rc = 2 * sc * dc; 342 } else { 343 rc = sa * da - 2 * (da - dc) * (sa - sc); 344 } 345 return clamp_div255round(rc + sc * (255 - da) + dc * (255 - sa)); 346} 347static SkPMColor hardlight_modeproc(SkPMColor src, SkPMColor dst) { 348 int sa = SkGetPackedA32(src); 349 int da = SkGetPackedA32(dst); 350 int a = srcover_byte(sa, da); 351 int r = hardlight_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da); 352 int g = hardlight_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da); 353 int b = hardlight_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da); 354 return SkPackARGB32(a, r, g, b); 355} 356 357// returns 255 * sqrt(n/255) 358static U8CPU sqrt_unit_byte(U8CPU n) { 359 return SkSqrtBits(n, 15+4); 360} 361 362// kSoftLight_Mode 363static inline int softlight_byte(int sc, int dc, int sa, int da) { 364 int m = da ? dc * 256 / da : 0; 365 int rc; 366 if (2 * sc <= sa) { 367 rc = dc * (sa + ((2 * sc - sa) * (256 - m) >> 8)); 368 } else if (4 * dc <= da) { 369 int tmp = (4 * m * (4 * m + 256) * (m - 256) >> 16) + 7 * m; 370 rc = dc * sa + (da * (2 * sc - sa) * tmp >> 8); 371 } else { 372 int tmp = sqrt_unit_byte(m) - m; 373 rc = dc * sa + (da * (2 * sc - sa) * tmp >> 8); 374 } 375 return clamp_div255round(rc + sc * (255 - da) + dc * (255 - sa)); 376} 377static SkPMColor softlight_modeproc(SkPMColor src, SkPMColor dst) { 378 int sa = SkGetPackedA32(src); 379 int da = SkGetPackedA32(dst); 380 int a = srcover_byte(sa, da); 381 int r = softlight_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da); 382 int g = softlight_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da); 383 int b = softlight_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da); 384 return SkPackARGB32(a, r, g, b); 385} 386 387// kDifference_Mode 388static inline int difference_byte(int sc, int dc, int sa, int da) { 389 int tmp = SkMin32(sc * da, dc * sa); 390 return clamp_signed_byte(sc + dc - 2 * SkDiv255Round(tmp)); 391} 392static SkPMColor difference_modeproc(SkPMColor src, SkPMColor dst) { 393 int sa = SkGetPackedA32(src); 394 int da = SkGetPackedA32(dst); 395 int a = srcover_byte(sa, da); 396 int r = difference_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da); 397 int g = difference_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da); 398 int b = difference_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da); 399 return SkPackARGB32(a, r, g, b); 400} 401 402// kExclusion_Mode 403static inline int exclusion_byte(int sc, int dc, int sa, int da) { 404 // this equations is wacky, wait for SVG to confirm it 405 int r = sc * da + dc * sa - 2 * sc * dc + sc * (255 - da) + dc * (255 - sa); 406 return clamp_div255round(r); 407} 408static SkPMColor exclusion_modeproc(SkPMColor src, SkPMColor dst) { 409 int sa = SkGetPackedA32(src); 410 int da = SkGetPackedA32(dst); 411 int a = srcover_byte(sa, da); 412 int r = exclusion_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da); 413 int g = exclusion_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da); 414 int b = exclusion_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da); 415 return SkPackARGB32(a, r, g, b); 416} 417 418// The CSS compositing spec introduces the following formulas: 419// (See https://dvcs.w3.org/hg/FXTF/rawfile/tip/compositing/index.html#blendingnonseparable) 420// SkComputeLuminance is similar to this formula but it uses the new definition from Rec. 709 421// while PDF and CG uses the one from Rec. Rec. 601 422// See http://www.glennchan.info/articles/technical/hd-versus-sd-color-space/hd-versus-sd-color-space.htm 423static inline int Lum(int r, int g, int b) 424{ 425 return SkDiv255Round(r * 77 + g * 150 + b * 28); 426} 427 428static inline int min2(int a, int b) { return a < b ? a : b; } 429static inline int max2(int a, int b) { return a > b ? a : b; } 430#define minimum(a, b, c) min2(min2(a, b), c) 431#define maximum(a, b, c) max2(max2(a, b), c) 432 433static inline int Sat(int r, int g, int b) { 434 return maximum(r, g, b) - minimum(r, g, b); 435} 436 437static inline void setSaturationComponents(int* Cmin, int* Cmid, int* Cmax, int s) { 438 if(*Cmax > *Cmin) { 439 *Cmid = SkMulDiv(*Cmid - *Cmin, s, *Cmax - *Cmin); 440 *Cmax = s; 441 } else { 442 *Cmax = 0; 443 *Cmid = 0; 444 } 445 446 *Cmin = 0; 447} 448 449static inline void SetSat(int* r, int* g, int* b, int s) { 450 if(*r <= *g) { 451 if(*g <= *b) { 452 setSaturationComponents(r, g, b, s); 453 } else if(*r <= *b) { 454 setSaturationComponents(r, b, g, s); 455 } else { 456 setSaturationComponents(b, r, g, s); 457 } 458 } else if(*r <= *b) { 459 setSaturationComponents(g, r, b, s); 460 } else if(*g <= *b) { 461 setSaturationComponents(g, b, r, s); 462 } else { 463 setSaturationComponents(b, g, r, s); 464 } 465} 466 467static inline void clipColor(int* r, int* g, int* b, int a) { 468 int L = Lum(*r, *g, *b); 469 int n = minimum(*r, *g, *b); 470 int x = maximum(*r, *g, *b); 471 if(n < 0) { 472 *r = L + SkMulDiv(*r - L, L, L - n); 473 *g = L + SkMulDiv(*g - L, L, L - n); 474 *b = L + SkMulDiv(*b - L, L, L - n); 475 } 476 477 if (x > a) { 478 *r = L + SkMulDiv(*r - L, a - L, x - L); 479 *g = L + SkMulDiv(*g - L, a - L, x - L); 480 *b = L + SkMulDiv(*b - L, a - L, x - L); 481 } 482} 483 484static inline void SetLum(int* r, int* g, int* b, int a, int l) { 485 int d = l - Lum(*r, *g, *b); 486 *r += d; 487 *g += d; 488 *b += d; 489 490 clipColor(r, g, b, a); 491} 492 493// non-separable blend modes are done in non-premultiplied alpha 494#define blendfunc_nonsep_byte(sc, dc, sa, da, blendval) \ 495 clamp_div255round(sc * (255 - da) + dc * (255 - sa) + blendval) 496 497// kHue_Mode 498// B(Cb, Cs) = SetLum(SetSat(Cs, Sat(Cb)), Lum(Cb)) 499// Create a color with the hue of the source color and the saturation and luminosity of the backdrop color. 500static SkPMColor hue_modeproc(SkPMColor src, SkPMColor dst) { 501 int sr = SkGetPackedR32(src); 502 int sg = SkGetPackedG32(src); 503 int sb = SkGetPackedB32(src); 504 int sa = SkGetPackedA32(src); 505 506 int dr = SkGetPackedR32(dst); 507 int dg = SkGetPackedG32(dst); 508 int db = SkGetPackedB32(dst); 509 int da = SkGetPackedA32(dst); 510 int Sr, Sg, Sb; 511 512 if(sa && da) { 513 Sr = sr * sa; 514 Sg = sg * sa; 515 Sb = sb * sa; 516 SetSat(&Sr, &Sg, &Sb, Sat(dr, dg, db) * sa); 517 SetLum(&Sr, &Sg, &Sb, sa * da, Lum(dr, dg, db) * sa); 518 } else { 519 Sr = 0; 520 Sg = 0; 521 Sb = 0; 522 } 523 524 int a = srcover_byte(sa, da); 525 int r = blendfunc_nonsep_byte(sr, dr, sa, da, Sr); 526 int g = blendfunc_nonsep_byte(sg, dg, sa, da, Sg); 527 int b = blendfunc_nonsep_byte(sb, db, sa, da, Sb); 528 return SkPackARGB32(a, r, g, b); 529} 530 531// kSaturation_Mode 532// B(Cb, Cs) = SetLum(SetSat(Cb, Sat(Cs)), Lum(Cb)) 533// Create a color with the saturation of the source color and the hue and luminosity of the backdrop color. 534static SkPMColor saturation_modeproc(SkPMColor src, SkPMColor dst) { 535 int sr = SkGetPackedR32(src); 536 int sg = SkGetPackedG32(src); 537 int sb = SkGetPackedB32(src); 538 int sa = SkGetPackedA32(src); 539 540 int dr = SkGetPackedR32(dst); 541 int dg = SkGetPackedG32(dst); 542 int db = SkGetPackedB32(dst); 543 int da = SkGetPackedA32(dst); 544 int Dr, Dg, Db; 545 546 if(sa && da) { 547 Dr = dr * sa; 548 Dg = dg * sa; 549 Db = db * sa; 550 SetSat(&Dr, &Dg, &Db, Sat(sr, sg, sb) * da); 551 SetLum(&Dr, &Dg, &Db, sa * da, Lum(dr, dg, db) * sa); 552 } else { 553 Dr = 0; 554 Dg = 0; 555 Db = 0; 556 } 557 558 int a = srcover_byte(sa, da); 559 int r = blendfunc_nonsep_byte(sr, dr, sa, da, Dr); 560 int g = blendfunc_nonsep_byte(sg, dg, sa, da, Dg); 561 int b = blendfunc_nonsep_byte(sb, db, sa, da, Db); 562 return SkPackARGB32(a, r, g, b); 563} 564 565// kColor_Mode 566// B(Cb, Cs) = SetLum(Cs, Lum(Cb)) 567// Create a color with the hue and saturation of the source color and the luminosity of the backdrop color. 568static SkPMColor color_modeproc(SkPMColor src, SkPMColor dst) { 569 int sr = SkGetPackedR32(src); 570 int sg = SkGetPackedG32(src); 571 int sb = SkGetPackedB32(src); 572 int sa = SkGetPackedA32(src); 573 574 int dr = SkGetPackedR32(dst); 575 int dg = SkGetPackedG32(dst); 576 int db = SkGetPackedB32(dst); 577 int da = SkGetPackedA32(dst); 578 int Sr, Sg, Sb; 579 580 if(sa && da) { 581 Sr = sr * da; 582 Sg = sg * da; 583 Sb = sb * da; 584 SetLum(&Sr, &Sg, &Sb, sa * da, Lum(dr, dg, db) * sa); 585 } else { 586 Sr = 0; 587 Sg = 0; 588 Sb = 0; 589 } 590 591 int a = srcover_byte(sa, da); 592 int r = blendfunc_nonsep_byte(sr, dr, sa, da, Sr); 593 int g = blendfunc_nonsep_byte(sg, dg, sa, da, Sg); 594 int b = blendfunc_nonsep_byte(sb, db, sa, da, Sb); 595 return SkPackARGB32(a, r, g, b); 596} 597 598// kLuminosity_Mode 599// B(Cb, Cs) = SetLum(Cb, Lum(Cs)) 600// Create a color with the luminosity of the source color and the hue and saturation of the backdrop color. 601static SkPMColor luminosity_modeproc(SkPMColor src, SkPMColor dst) { 602 int sr = SkGetPackedR32(src); 603 int sg = SkGetPackedG32(src); 604 int sb = SkGetPackedB32(src); 605 int sa = SkGetPackedA32(src); 606 607 int dr = SkGetPackedR32(dst); 608 int dg = SkGetPackedG32(dst); 609 int db = SkGetPackedB32(dst); 610 int da = SkGetPackedA32(dst); 611 int Dr, Dg, Db; 612 613 if(sa && da) { 614 Dr = dr * sa; 615 Dg = dg * sa; 616 Db = db * sa; 617 SetLum(&Dr, &Dg, &Db, sa * da, Lum(sr, sg, sb) * da); 618 } else { 619 Dr = 0; 620 Dg = 0; 621 Db = 0; 622 } 623 624 int a = srcover_byte(sa, da); 625 int r = blendfunc_nonsep_byte(sr, dr, sa, da, Dr); 626 int g = blendfunc_nonsep_byte(sg, dg, sa, da, Dg); 627 int b = blendfunc_nonsep_byte(sb, db, sa, da, Db); 628 return SkPackARGB32(a, r, g, b); 629} 630 631 632struct ProcCoeff { 633 SkXfermodeProc fProc; 634 SkXfermode::Coeff fSC; 635 SkXfermode::Coeff fDC; 636}; 637 638#define CANNOT_USE_COEFF SkXfermode::Coeff(-1) 639 640static const ProcCoeff gProcCoeffs[] = { 641 { clear_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kZero_Coeff }, 642 { src_modeproc, SkXfermode::kOne_Coeff, SkXfermode::kZero_Coeff }, 643 { dst_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kOne_Coeff }, 644 { srcover_modeproc, SkXfermode::kOne_Coeff, SkXfermode::kISA_Coeff }, 645 { dstover_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kOne_Coeff }, 646 { srcin_modeproc, SkXfermode::kDA_Coeff, SkXfermode::kZero_Coeff }, 647 { dstin_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kSA_Coeff }, 648 { srcout_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kZero_Coeff }, 649 { dstout_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kISA_Coeff }, 650 { srcatop_modeproc, SkXfermode::kDA_Coeff, SkXfermode::kISA_Coeff }, 651 { dstatop_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kSA_Coeff }, 652 { xor_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kISA_Coeff }, 653 654 { plus_modeproc, SkXfermode::kOne_Coeff, SkXfermode::kOne_Coeff }, 655 { modulate_modeproc,SkXfermode::kZero_Coeff, SkXfermode::kSC_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 { multiply_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, 667 { hue_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, 668 { saturation_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, 669 { color_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, 670 { luminosity_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, 671}; 672 673/////////////////////////////////////////////////////////////////////////////// 674 675bool SkXfermode::asCoeff(Coeff* src, Coeff* dst) const { 676 return false; 677} 678 679bool SkXfermode::asMode(Mode* mode) const { 680 return false; 681} 682 683bool SkXfermode::asNewEffectOrCoeff(GrContext*, GrEffectRef**, Coeff* src, Coeff* dst) const { 684 return this->asCoeff(src, dst); 685} 686 687bool SkXfermode::AsNewEffectOrCoeff(SkXfermode* xfermode, 688 GrContext* context, 689 GrEffectRef** effect, 690 Coeff* src, 691 Coeff* dst) { 692 if (NULL == xfermode) { 693 return ModeAsCoeff(kSrcOver_Mode, src, dst); 694 } else { 695 return xfermode->asNewEffectOrCoeff(context, effect, src, dst); 696 } 697} 698 699SkPMColor SkXfermode::xferColor(SkPMColor src, SkPMColor dst) const{ 700 // no-op. subclasses should override this 701 return dst; 702} 703 704void SkXfermode::xfer32(SkPMColor* SK_RESTRICT dst, 705 const SkPMColor* SK_RESTRICT src, int count, 706 const SkAlpha* SK_RESTRICT aa) const { 707 SkASSERT(dst && src && count >= 0); 708 709 if (NULL == aa) { 710 for (int i = count - 1; i >= 0; --i) { 711 dst[i] = this->xferColor(src[i], dst[i]); 712 } 713 } else { 714 for (int i = count - 1; i >= 0; --i) { 715 unsigned a = aa[i]; 716 if (0 != a) { 717 SkPMColor dstC = dst[i]; 718 SkPMColor C = this->xferColor(src[i], dstC); 719 if (0xFF != a) { 720 C = SkFourByteInterp(C, dstC, a); 721 } 722 dst[i] = C; 723 } 724 } 725 } 726} 727 728void SkXfermode::xfer16(uint16_t* dst, 729 const SkPMColor* SK_RESTRICT src, int count, 730 const SkAlpha* SK_RESTRICT aa) const { 731 SkASSERT(dst && src && count >= 0); 732 733 if (NULL == aa) { 734 for (int i = count - 1; i >= 0; --i) { 735 SkPMColor dstC = SkPixel16ToPixel32(dst[i]); 736 dst[i] = SkPixel32ToPixel16_ToU16(this->xferColor(src[i], dstC)); 737 } 738 } else { 739 for (int i = count - 1; i >= 0; --i) { 740 unsigned a = aa[i]; 741 if (0 != a) { 742 SkPMColor dstC = SkPixel16ToPixel32(dst[i]); 743 SkPMColor C = this->xferColor(src[i], dstC); 744 if (0xFF != a) { 745 C = SkFourByteInterp(C, dstC, a); 746 } 747 dst[i] = SkPixel32ToPixel16_ToU16(C); 748 } 749 } 750 } 751} 752 753void SkXfermode::xfer4444(SkPMColor16* SK_RESTRICT dst, 754 const SkPMColor* SK_RESTRICT src, int count, 755 const SkAlpha* SK_RESTRICT aa) const { 756 SkASSERT(dst && src && count >= 0); 757 758 if (NULL == aa) { 759 for (int i = count - 1; i >= 0; --i) { 760 SkPMColor dstC = SkPixel4444ToPixel32(dst[i]); 761 dst[i] = SkPixel32ToPixel4444(this->xferColor(src[i], dstC)); 762 } 763 } else { 764 for (int i = count - 1; i >= 0; --i) { 765 unsigned a = aa[i]; 766 if (0 != a) { 767 SkPMColor dstC = SkPixel4444ToPixel32(dst[i]); 768 SkPMColor C = this->xferColor(src[i], dstC); 769 if (0xFF != a) { 770 C = SkFourByteInterp(C, dstC, a); 771 } 772 dst[i] = SkPixel32ToPixel4444(C); 773 } 774 } 775 } 776} 777 778void SkXfermode::xferA8(SkAlpha* SK_RESTRICT dst, 779 const SkPMColor src[], int count, 780 const SkAlpha* SK_RESTRICT aa) const { 781 SkASSERT(dst && src && count >= 0); 782 783 if (NULL == aa) { 784 for (int i = count - 1; i >= 0; --i) { 785 SkPMColor res = this->xferColor(src[i], (dst[i] << SK_A32_SHIFT)); 786 dst[i] = SkToU8(SkGetPackedA32(res)); 787 } 788 } else { 789 for (int i = count - 1; i >= 0; --i) { 790 unsigned a = aa[i]; 791 if (0 != a) { 792 SkAlpha dstA = dst[i]; 793 unsigned A = SkGetPackedA32(this->xferColor(src[i], 794 (SkPMColor)(dstA << SK_A32_SHIFT))); 795 if (0xFF != a) { 796 A = SkAlphaBlend(A, dstA, SkAlpha255To256(a)); 797 } 798 dst[i] = SkToU8(A); 799 } 800 } 801 } 802} 803 804/////////////////////////////////////////////////////////////////////////////// 805 806void SkProcXfermode::xfer32(SkPMColor* SK_RESTRICT dst, 807 const SkPMColor* SK_RESTRICT src, int count, 808 const SkAlpha* SK_RESTRICT aa) const { 809 SkASSERT(dst && src && count >= 0); 810 811 SkXfermodeProc proc = fProc; 812 813 if (NULL != proc) { 814 if (NULL == aa) { 815 for (int i = count - 1; i >= 0; --i) { 816 dst[i] = proc(src[i], dst[i]); 817 } 818 } else { 819 for (int i = count - 1; i >= 0; --i) { 820 unsigned a = aa[i]; 821 if (0 != a) { 822 SkPMColor dstC = dst[i]; 823 SkPMColor C = proc(src[i], dstC); 824 if (a != 0xFF) { 825 C = SkFourByteInterp(C, dstC, a); 826 } 827 dst[i] = C; 828 } 829 } 830 } 831 } 832} 833 834void SkProcXfermode::xfer16(uint16_t* SK_RESTRICT dst, 835 const SkPMColor* SK_RESTRICT src, int count, 836 const SkAlpha* SK_RESTRICT aa) const { 837 SkASSERT(dst && src && count >= 0); 838 839 SkXfermodeProc proc = fProc; 840 841 if (NULL != proc) { 842 if (NULL == aa) { 843 for (int i = count - 1; i >= 0; --i) { 844 SkPMColor dstC = SkPixel16ToPixel32(dst[i]); 845 dst[i] = SkPixel32ToPixel16_ToU16(proc(src[i], dstC)); 846 } 847 } else { 848 for (int i = count - 1; i >= 0; --i) { 849 unsigned a = aa[i]; 850 if (0 != a) { 851 SkPMColor dstC = SkPixel16ToPixel32(dst[i]); 852 SkPMColor C = proc(src[i], dstC); 853 if (0xFF != a) { 854 C = SkFourByteInterp(C, dstC, a); 855 } 856 dst[i] = SkPixel32ToPixel16_ToU16(C); 857 } 858 } 859 } 860 } 861} 862 863void SkProcXfermode::xfer4444(SkPMColor16* SK_RESTRICT dst, 864 const SkPMColor* SK_RESTRICT src, int count, 865 const SkAlpha* SK_RESTRICT aa) const { 866 SkASSERT(dst && src && count >= 0); 867 868 SkXfermodeProc proc = fProc; 869 870 if (NULL != proc) { 871 if (NULL == aa) { 872 for (int i = count - 1; i >= 0; --i) { 873 SkPMColor dstC = SkPixel4444ToPixel32(dst[i]); 874 dst[i] = SkPixel32ToPixel4444(proc(src[i], dstC)); 875 } 876 } else { 877 for (int i = count - 1; i >= 0; --i) { 878 unsigned a = aa[i]; 879 if (0 != a) { 880 SkPMColor dstC = SkPixel4444ToPixel32(dst[i]); 881 SkPMColor C = proc(src[i], dstC); 882 if (0xFF != a) { 883 C = SkFourByteInterp(C, dstC, a); 884 } 885 dst[i] = SkPixel32ToPixel4444(C); 886 } 887 } 888 } 889 } 890} 891 892void SkProcXfermode::xferA8(SkAlpha* SK_RESTRICT dst, 893 const SkPMColor* SK_RESTRICT src, int count, 894 const SkAlpha* SK_RESTRICT aa) const { 895 SkASSERT(dst && src && count >= 0); 896 897 SkXfermodeProc proc = fProc; 898 899 if (NULL != proc) { 900 if (NULL == aa) { 901 for (int i = count - 1; i >= 0; --i) { 902 SkPMColor res = proc(src[i], dst[i] << SK_A32_SHIFT); 903 dst[i] = SkToU8(SkGetPackedA32(res)); 904 } 905 } else { 906 for (int i = count - 1; i >= 0; --i) { 907 unsigned a = aa[i]; 908 if (0 != a) { 909 SkAlpha dstA = dst[i]; 910 SkPMColor res = proc(src[i], dstA << SK_A32_SHIFT); 911 unsigned A = SkGetPackedA32(res); 912 if (0xFF != a) { 913 A = SkAlphaBlend(A, dstA, SkAlpha255To256(a)); 914 } 915 dst[i] = SkToU8(A); 916 } 917 } 918 } 919 } 920} 921 922SkProcXfermode::SkProcXfermode(SkFlattenableReadBuffer& buffer) 923 : SkXfermode(buffer) { 924 fProc = NULL; 925 if (!buffer.isCrossProcess()) { 926 fProc = (SkXfermodeProc)buffer.readFunctionPtr(); 927 } 928} 929 930void SkProcXfermode::flatten(SkFlattenableWriteBuffer& buffer) const { 931 this->INHERITED::flatten(buffer); 932 if (!buffer.isCrossProcess()) { 933 buffer.writeFunctionPtr((void*)fProc); 934 } 935} 936 937#ifdef SK_DEVELOPER 938void SkProcXfermode::toString(SkString* str) const { 939 str->appendf("SkProcXfermode: %p", fProc); 940} 941#endif 942 943////////////////////////////////////////////////////////////////////////////// 944 945#if SK_SUPPORT_GPU 946 947#include "GrEffect.h" 948#include "GrEffectUnitTest.h" 949#include "GrTBackendEffectFactory.h" 950#include "gl/GrGLEffect.h" 951 952/** 953 * GrEffect that implements the kDarken_Mode Xfermode. It requires access to the dst pixel color 954 * in the shader. TODO: Make this work for all non-Coeff SkXfermode::Mode values. 955 */ 956class DarkenEffect : public GrEffect { 957public: 958 static GrEffectRef* Create() { 959 static AutoEffectUnref gEffect(SkNEW(DarkenEffect)); 960 return CreateEffectRef(gEffect); 961 } 962 963 virtual void getConstantColorComponents(GrColor* color, 964 uint32_t* validFlags) const SK_OVERRIDE { 965 *validFlags = 0; 966 } 967 968 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE { 969 return GrTBackendEffectFactory<DarkenEffect>::getInstance(); 970 } 971 972 static const char* Name() { return "XfermodeDarken"; } 973 974 class GLEffect : public GrGLEffect { 975 public: 976 GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&) 977 : GrGLEffect(factory ) { 978 } 979 virtual void emitCode(GrGLShaderBuilder* builder, 980 const GrDrawEffect& drawEffect, 981 EffectKey key, 982 const char* outputColor, 983 const char* inputColor, 984 const TextureSamplerArray& samplers) SK_OVERRIDE { 985 const char* dstColorName = builder->dstColor(); 986 GrAssert(NULL != dstColorName); 987 if (NULL == inputColor) { 988 // the input color is solid white 989 builder->fsCodeAppendf("\t\t%s.a = 1.0;\n", outputColor); 990 builder->fsCodeAppendf("\t\t%s.rgb = vec3(1.0, 1.0, 1.0) - %s.aaa + %s.rgb;\n", 991 outputColor, dstColorName, dstColorName); 992 } else { 993 builder->fsCodeAppendf("\t\t%s.a = 1.0 - (1.0 - %s.a) * (1.0 - %s.a);\n", 994 outputColor, dstColorName, inputColor); 995 builder->fsCodeAppendf("\t\t%s.rgb = min((1.0 - %s.a) * %s.rgb + %s.rgb," 996 " (1.0 - %s.a) * %s.rgb + %s.rgb);\n", 997 outputColor, 998 inputColor, dstColorName, inputColor, 999 dstColorName, inputColor, dstColorName); 1000 } 1001 } 1002 1003 static inline EffectKey GenKey(const GrDrawEffect&, const GrGLCaps&) { return 0; } 1004 1005 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE {} 1006 1007 private: 1008 typedef GrGLEffect INHERITED; 1009 }; 1010 1011 GR_DECLARE_EFFECT_TEST; 1012 1013private: 1014 DarkenEffect() { this->setWillReadDst(); } 1015 virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE { return true; } 1016 1017 typedef GrEffect INHERITED; 1018}; 1019 1020GR_DEFINE_EFFECT_TEST(DarkenEffect); 1021GrEffectRef* DarkenEffect::TestCreate(SkMWCRandom*, 1022 GrContext*, 1023 const GrDrawTargetCaps&, 1024 GrTexture*[]) { 1025 static AutoEffectUnref gEffect(SkNEW(DarkenEffect)); 1026 return CreateEffectRef(gEffect); 1027} 1028 1029#endif 1030 1031/////////////////////////////////////////////////////////////////////////////// 1032/////////////////////////////////////////////////////////////////////////////// 1033 1034class SkProcCoeffXfermode : public SkProcXfermode { 1035public: 1036 SkProcCoeffXfermode(const ProcCoeff& rec, Mode mode) 1037 : INHERITED(rec.fProc) { 1038 fMode = mode; 1039 // these may be valid, or may be CANNOT_USE_COEFF 1040 fSrcCoeff = rec.fSC; 1041 fDstCoeff = rec.fDC; 1042 } 1043 1044 virtual bool asMode(Mode* mode) const SK_OVERRIDE { 1045 if (mode) { 1046 *mode = fMode; 1047 } 1048 return true; 1049 } 1050 1051 virtual bool asCoeff(Coeff* sc, Coeff* dc) const SK_OVERRIDE { 1052 if (CANNOT_USE_COEFF == fSrcCoeff) { 1053 return false; 1054 } 1055 1056 if (sc) { 1057 *sc = fSrcCoeff; 1058 } 1059 if (dc) { 1060 *dc = fDstCoeff; 1061 } 1062 return true; 1063 } 1064 1065#if SK_SUPPORT_GPU 1066 virtual bool asNewEffectOrCoeff(GrContext*, 1067 GrEffectRef** effect, 1068 Coeff* src, 1069 Coeff* dst) const SK_OVERRIDE { 1070 if (this->asCoeff(src, dst)) { 1071 return true; 1072 } 1073 if (kDarken_Mode == fMode) { 1074 if (NULL != effect) { 1075 *effect = DarkenEffect::Create(); 1076 } 1077 return true; 1078 } 1079 return false; 1080 } 1081#endif 1082 1083 SK_DEVELOPER_TO_STRING() 1084 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkProcCoeffXfermode) 1085 1086protected: 1087 SkProcCoeffXfermode(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) { 1088 fMode = (SkXfermode::Mode)buffer.read32(); 1089 1090 const ProcCoeff& rec = gProcCoeffs[fMode]; 1091 // these may be valid, or may be CANNOT_USE_COEFF 1092 fSrcCoeff = rec.fSC; 1093 fDstCoeff = rec.fDC; 1094 // now update our function-ptr in the super class 1095 this->INHERITED::setProc(rec.fProc); 1096 } 1097 1098 virtual void flatten(SkFlattenableWriteBuffer& buffer) const SK_OVERRIDE { 1099 this->INHERITED::flatten(buffer); 1100 buffer.write32(fMode); 1101 } 1102 1103private: 1104 Mode fMode; 1105 Coeff fSrcCoeff, fDstCoeff; 1106 1107 typedef SkProcXfermode INHERITED; 1108}; 1109 1110const char* SkXfermode::ModeName(Mode mode) { 1111 SkASSERT((unsigned) mode <= (unsigned)kLastMode); 1112 const char* gModeStrings[] = { 1113 "Clear", "Src", "Dst", "SrcOver", "DstOver", "SrcIn", "DstIn", 1114 "SrcOut", "DstOut", "SrcATop", "DstATop", "Xor", "Plus", 1115 "Modulate", "Screen", "Overlay", "Darken", "Lighten", "ColorDodge", 1116 "ColorBurn", "HardLight", "SoftLight", "Difference", "Exclusion", 1117 "Multiply", "Hue", "Saturation", "Color", "Luminosity" 1118 }; 1119 return gModeStrings[mode]; 1120 SK_COMPILE_ASSERT(SK_ARRAY_COUNT(gModeStrings) == kLastMode + 1, mode_count); 1121} 1122 1123#ifdef SK_DEVELOPER 1124void SkProcCoeffXfermode::toString(SkString* str) const { 1125 str->append("SkProcCoeffXfermode: "); 1126 1127 str->append("mode: "); 1128 str->append(ModeName(fMode)); 1129 1130 static const char* gCoeffStrings[kCoeffCount] = { 1131 "Zero", "One", "SC", "ISC", "DC", "IDC", "SA", "ISA", "DA", "IDA" 1132 }; 1133 1134 str->append(" src: "); 1135 if (CANNOT_USE_COEFF == fSrcCoeff) { 1136 str->append("can't use"); 1137 } else { 1138 str->append(gCoeffStrings[fSrcCoeff]); 1139 } 1140 1141 str->append(" dst: "); 1142 if (CANNOT_USE_COEFF == fDstCoeff) { 1143 str->append("can't use"); 1144 } else { 1145 str->append(gCoeffStrings[fDstCoeff]); 1146 } 1147} 1148#endif 1149 1150/////////////////////////////////////////////////////////////////////////////// 1151 1152class SkClearXfermode : public SkProcCoeffXfermode { 1153public: 1154 SkClearXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kClear_Mode) {} 1155 1156 virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE; 1157 virtual void xferA8(SkAlpha*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE; 1158 1159 SK_DEVELOPER_TO_STRING() 1160 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkClearXfermode) 1161 1162private: 1163 SkClearXfermode(SkFlattenableReadBuffer& buffer) 1164 : SkProcCoeffXfermode(buffer) {} 1165 1166 typedef SkProcCoeffXfermode INHERITED; 1167}; 1168 1169void SkClearXfermode::xfer32(SkPMColor* SK_RESTRICT dst, 1170 const SkPMColor* SK_RESTRICT, int count, 1171 const SkAlpha* SK_RESTRICT aa) const { 1172 SkASSERT(dst && count >= 0); 1173 1174 if (NULL == aa) { 1175 memset(dst, 0, count << 2); 1176 } else { 1177 for (int i = count - 1; i >= 0; --i) { 1178 unsigned a = aa[i]; 1179 if (0xFF == a) { 1180 dst[i] = 0; 1181 } else if (a != 0) { 1182 dst[i] = SkAlphaMulQ(dst[i], SkAlpha255To256(255 - a)); 1183 } 1184 } 1185 } 1186} 1187void SkClearXfermode::xferA8(SkAlpha* SK_RESTRICT dst, 1188 const SkPMColor* SK_RESTRICT, int count, 1189 const SkAlpha* SK_RESTRICT aa) const { 1190 SkASSERT(dst && count >= 0); 1191 1192 if (NULL == aa) { 1193 memset(dst, 0, count); 1194 } else { 1195 for (int i = count - 1; i >= 0; --i) { 1196 unsigned a = aa[i]; 1197 if (0xFF == a) { 1198 dst[i] = 0; 1199 } else if (0 != a) { 1200 dst[i] = SkAlphaMulAlpha(dst[i], 255 - a); 1201 } 1202 } 1203 } 1204} 1205 1206#ifdef SK_DEVELOPER 1207void SkClearXfermode::toString(SkString* str) const { 1208 this->INHERITED::toString(str); 1209} 1210#endif 1211 1212/////////////////////////////////////////////////////////////////////////////// 1213 1214class SkSrcXfermode : public SkProcCoeffXfermode { 1215public: 1216 SkSrcXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kSrc_Mode) {} 1217 1218 virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE; 1219 virtual void xferA8(SkAlpha*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE; 1220 1221 SK_DEVELOPER_TO_STRING() 1222 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkSrcXfermode) 1223 1224private: 1225 SkSrcXfermode(SkFlattenableReadBuffer& buffer) 1226 : SkProcCoeffXfermode(buffer) {} 1227 1228 typedef SkProcCoeffXfermode INHERITED; 1229}; 1230 1231void SkSrcXfermode::xfer32(SkPMColor* SK_RESTRICT dst, 1232 const SkPMColor* SK_RESTRICT src, int count, 1233 const SkAlpha* SK_RESTRICT aa) const { 1234 SkASSERT(dst && src && count >= 0); 1235 1236 if (NULL == aa) { 1237 memcpy(dst, src, count << 2); 1238 } else { 1239 for (int i = count - 1; i >= 0; --i) { 1240 unsigned a = aa[i]; 1241 if (a == 0xFF) { 1242 dst[i] = src[i]; 1243 } else if (a != 0) { 1244 dst[i] = SkFourByteInterp(src[i], dst[i], a); 1245 } 1246 } 1247 } 1248} 1249 1250void SkSrcXfermode::xferA8(SkAlpha* SK_RESTRICT dst, 1251 const SkPMColor* SK_RESTRICT src, int count, 1252 const SkAlpha* SK_RESTRICT aa) const { 1253 SkASSERT(dst && src && count >= 0); 1254 1255 if (NULL == aa) { 1256 for (int i = count - 1; i >= 0; --i) { 1257 dst[i] = SkToU8(SkGetPackedA32(src[i])); 1258 } 1259 } else { 1260 for (int i = count - 1; i >= 0; --i) { 1261 unsigned a = aa[i]; 1262 if (0 != a) { 1263 unsigned srcA = SkGetPackedA32(src[i]); 1264 if (a == 0xFF) { 1265 dst[i] = SkToU8(srcA); 1266 } else { 1267 dst[i] = SkToU8(SkAlphaBlend(srcA, dst[i], a)); 1268 } 1269 } 1270 } 1271 } 1272} 1273#ifdef SK_DEVELOPER 1274void SkSrcXfermode::toString(SkString* str) const { 1275 this->INHERITED::toString(str); 1276} 1277#endif 1278 1279/////////////////////////////////////////////////////////////////////////////// 1280 1281class SkDstInXfermode : public SkProcCoeffXfermode { 1282public: 1283 SkDstInXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstIn_Mode) {} 1284 1285 virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE; 1286 1287 SK_DEVELOPER_TO_STRING() 1288 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDstInXfermode) 1289 1290private: 1291 SkDstInXfermode(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {} 1292 1293 typedef SkProcCoeffXfermode INHERITED; 1294}; 1295 1296void SkDstInXfermode::xfer32(SkPMColor* SK_RESTRICT dst, 1297 const SkPMColor* SK_RESTRICT src, int count, 1298 const SkAlpha* SK_RESTRICT aa) const { 1299 SkASSERT(dst && src); 1300 1301 if (count <= 0) { 1302 return; 1303 } 1304 if (NULL != aa) { 1305 return this->INHERITED::xfer32(dst, src, count, aa); 1306 } 1307 1308 do { 1309 unsigned a = SkGetPackedA32(*src); 1310 *dst = SkAlphaMulQ(*dst, SkAlpha255To256(a)); 1311 dst++; 1312 src++; 1313 } while (--count != 0); 1314} 1315 1316#ifdef SK_DEVELOPER 1317void SkDstInXfermode::toString(SkString* str) const { 1318 this->INHERITED::toString(str); 1319} 1320#endif 1321 1322/////////////////////////////////////////////////////////////////////////////// 1323 1324class SkDstOutXfermode : public SkProcCoeffXfermode { 1325public: 1326 SkDstOutXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstOut_Mode) {} 1327 1328 virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE; 1329 1330 SK_DEVELOPER_TO_STRING() 1331 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDstOutXfermode) 1332 1333private: 1334 SkDstOutXfermode(SkFlattenableReadBuffer& buffer) 1335 : INHERITED(buffer) {} 1336 1337 typedef SkProcCoeffXfermode INHERITED; 1338}; 1339 1340void SkDstOutXfermode::xfer32(SkPMColor* SK_RESTRICT dst, 1341 const SkPMColor* SK_RESTRICT src, int count, 1342 const SkAlpha* SK_RESTRICT aa) const { 1343 SkASSERT(dst && src); 1344 1345 if (count <= 0) { 1346 return; 1347 } 1348 if (NULL != aa) { 1349 return this->INHERITED::xfer32(dst, src, count, aa); 1350 } 1351 1352 do { 1353 unsigned a = SkGetPackedA32(*src); 1354 *dst = SkAlphaMulQ(*dst, SkAlpha255To256(255 - a)); 1355 dst++; 1356 src++; 1357 } while (--count != 0); 1358} 1359 1360#ifdef SK_DEVELOPER 1361void SkDstOutXfermode::toString(SkString* str) const { 1362 this->INHERITED::toString(str); 1363} 1364#endif 1365 1366/////////////////////////////////////////////////////////////////////////////// 1367 1368SkXfermode* SkXfermode::Create(Mode mode) { 1369 SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount); 1370 SkASSERT((unsigned)mode < kModeCount); 1371 1372 const ProcCoeff& rec = gProcCoeffs[mode]; 1373 1374 switch (mode) { 1375 case kClear_Mode: 1376 return SkNEW_ARGS(SkClearXfermode, (rec)); 1377 case kSrc_Mode: 1378 return SkNEW_ARGS(SkSrcXfermode, (rec)); 1379 case kSrcOver_Mode: 1380 return NULL; 1381 case kDstIn_Mode: 1382 return SkNEW_ARGS(SkDstInXfermode, (rec)); 1383 case kDstOut_Mode: 1384 return SkNEW_ARGS(SkDstOutXfermode, (rec)); 1385 default: 1386 return SkNEW_ARGS(SkProcCoeffXfermode, (rec, mode)); 1387 } 1388} 1389 1390SkXfermodeProc SkXfermode::GetProc(Mode mode) { 1391 SkXfermodeProc proc = NULL; 1392 if ((unsigned)mode < kModeCount) { 1393 proc = gProcCoeffs[mode].fProc; 1394 } 1395 return proc; 1396} 1397 1398bool SkXfermode::ModeAsCoeff(Mode mode, Coeff* src, Coeff* dst) { 1399 SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount); 1400 1401 if ((unsigned)mode >= (unsigned)kModeCount) { 1402 // illegal mode parameter 1403 return false; 1404 } 1405 1406 const ProcCoeff& rec = gProcCoeffs[mode]; 1407 1408 if (CANNOT_USE_COEFF == rec.fSC) { 1409 return false; 1410 } 1411 1412 SkASSERT(CANNOT_USE_COEFF != rec.fDC); 1413 if (src) { 1414 *src = rec.fSC; 1415 } 1416 if (dst) { 1417 *dst = rec.fDC; 1418 } 1419 return true; 1420} 1421 1422bool SkXfermode::AsMode(const SkXfermode* xfer, Mode* mode) { 1423 if (NULL == xfer) { 1424 if (mode) { 1425 *mode = kSrcOver_Mode; 1426 } 1427 return true; 1428 } 1429 return xfer->asMode(mode); 1430} 1431 1432bool SkXfermode::AsCoeff(const SkXfermode* xfer, Coeff* src, Coeff* dst) { 1433 if (NULL == xfer) { 1434 return ModeAsCoeff(kSrcOver_Mode, src, dst); 1435 } 1436 return xfer->asCoeff(src, dst); 1437} 1438 1439bool SkXfermode::IsMode(const SkXfermode* xfer, Mode mode) { 1440 // if xfer==null then the mode is srcover 1441 Mode m = kSrcOver_Mode; 1442 if (xfer && !xfer->asMode(&m)) { 1443 return false; 1444 } 1445 return mode == m; 1446} 1447 1448/////////////////////////////////////////////////////////////////////////////// 1449//////////// 16bit xfermode procs 1450 1451#ifdef SK_DEBUG 1452static bool require_255(SkPMColor src) { return SkGetPackedA32(src) == 0xFF; } 1453static bool require_0(SkPMColor src) { return SkGetPackedA32(src) == 0; } 1454#endif 1455 1456static uint16_t src_modeproc16_255(SkPMColor src, uint16_t dst) { 1457 SkASSERT(require_255(src)); 1458 return SkPixel32ToPixel16(src); 1459} 1460 1461static uint16_t dst_modeproc16(SkPMColor src, uint16_t dst) { 1462 return dst; 1463} 1464 1465static uint16_t srcover_modeproc16_0(SkPMColor src, uint16_t dst) { 1466 SkASSERT(require_0(src)); 1467 return dst; 1468} 1469 1470static uint16_t srcover_modeproc16_255(SkPMColor src, uint16_t dst) { 1471 SkASSERT(require_255(src)); 1472 return SkPixel32ToPixel16(src); 1473} 1474 1475static uint16_t dstover_modeproc16_0(SkPMColor src, uint16_t dst) { 1476 SkASSERT(require_0(src)); 1477 return dst; 1478} 1479 1480static uint16_t dstover_modeproc16_255(SkPMColor src, uint16_t dst) { 1481 SkASSERT(require_255(src)); 1482 return dst; 1483} 1484 1485static uint16_t srcin_modeproc16_255(SkPMColor src, uint16_t dst) { 1486 SkASSERT(require_255(src)); 1487 return SkPixel32ToPixel16(src); 1488} 1489 1490static uint16_t dstin_modeproc16_255(SkPMColor src, uint16_t dst) { 1491 SkASSERT(require_255(src)); 1492 return dst; 1493} 1494 1495static uint16_t dstout_modeproc16_0(SkPMColor src, uint16_t dst) { 1496 SkASSERT(require_0(src)); 1497 return dst; 1498} 1499 1500static uint16_t srcatop_modeproc16(SkPMColor src, uint16_t dst) { 1501 unsigned isa = 255 - SkGetPackedA32(src); 1502 1503 return SkPackRGB16( 1504 SkPacked32ToR16(src) + SkAlphaMulAlpha(SkGetPackedR16(dst), isa), 1505 SkPacked32ToG16(src) + SkAlphaMulAlpha(SkGetPackedG16(dst), isa), 1506 SkPacked32ToB16(src) + SkAlphaMulAlpha(SkGetPackedB16(dst), isa)); 1507} 1508 1509static uint16_t srcatop_modeproc16_0(SkPMColor src, uint16_t dst) { 1510 SkASSERT(require_0(src)); 1511 return dst; 1512} 1513 1514static uint16_t srcatop_modeproc16_255(SkPMColor src, uint16_t dst) { 1515 SkASSERT(require_255(src)); 1516 return SkPixel32ToPixel16(src); 1517} 1518 1519static uint16_t dstatop_modeproc16_255(SkPMColor src, uint16_t dst) { 1520 SkASSERT(require_255(src)); 1521 return dst; 1522} 1523 1524/********* 1525 darken and lighten boil down to this. 1526 1527 darken = (1 - Sa) * Dc + min(Sc, Dc) 1528 lighten = (1 - Sa) * Dc + max(Sc, Dc) 1529 1530 if (Sa == 0) these become 1531 darken = Dc + min(0, Dc) = 0 1532 lighten = Dc + max(0, Dc) = Dc 1533 1534 if (Sa == 1) these become 1535 darken = min(Sc, Dc) 1536 lighten = max(Sc, Dc) 1537*/ 1538 1539static uint16_t darken_modeproc16_0(SkPMColor src, uint16_t dst) { 1540 SkASSERT(require_0(src)); 1541 return 0; 1542} 1543 1544static uint16_t darken_modeproc16_255(SkPMColor src, uint16_t dst) { 1545 SkASSERT(require_255(src)); 1546 unsigned r = SkFastMin32(SkPacked32ToR16(src), SkGetPackedR16(dst)); 1547 unsigned g = SkFastMin32(SkPacked32ToG16(src), SkGetPackedG16(dst)); 1548 unsigned b = SkFastMin32(SkPacked32ToB16(src), SkGetPackedB16(dst)); 1549 return SkPackRGB16(r, g, b); 1550} 1551 1552static uint16_t lighten_modeproc16_0(SkPMColor src, uint16_t dst) { 1553 SkASSERT(require_0(src)); 1554 return dst; 1555} 1556 1557static uint16_t lighten_modeproc16_255(SkPMColor src, uint16_t dst) { 1558 SkASSERT(require_255(src)); 1559 unsigned r = SkMax32(SkPacked32ToR16(src), SkGetPackedR16(dst)); 1560 unsigned g = SkMax32(SkPacked32ToG16(src), SkGetPackedG16(dst)); 1561 unsigned b = SkMax32(SkPacked32ToB16(src), SkGetPackedB16(dst)); 1562 return SkPackRGB16(r, g, b); 1563} 1564 1565struct Proc16Rec { 1566 SkXfermodeProc16 fProc16_0; 1567 SkXfermodeProc16 fProc16_255; 1568 SkXfermodeProc16 fProc16_General; 1569}; 1570 1571static const Proc16Rec gModeProcs16[] = { 1572 { NULL, NULL, NULL }, // CLEAR 1573 { NULL, src_modeproc16_255, NULL }, 1574 { dst_modeproc16, dst_modeproc16, dst_modeproc16 }, 1575 { srcover_modeproc16_0, srcover_modeproc16_255, NULL }, 1576 { dstover_modeproc16_0, dstover_modeproc16_255, NULL }, 1577 { NULL, srcin_modeproc16_255, NULL }, 1578 { NULL, dstin_modeproc16_255, NULL }, 1579 { NULL, NULL, NULL },// SRC_OUT 1580 { dstout_modeproc16_0, NULL, NULL }, 1581 { srcatop_modeproc16_0, srcatop_modeproc16_255, srcatop_modeproc16 }, 1582 { NULL, dstatop_modeproc16_255, NULL }, 1583 { NULL, NULL, NULL }, // XOR 1584 1585 { NULL, NULL, NULL }, // plus 1586 { NULL, NULL, NULL }, // modulate 1587 { NULL, NULL, NULL }, // screen 1588 { NULL, NULL, NULL }, // overlay 1589 { darken_modeproc16_0, darken_modeproc16_255, NULL }, // darken 1590 { lighten_modeproc16_0, lighten_modeproc16_255, NULL }, // lighten 1591 { NULL, NULL, NULL }, // colordodge 1592 { NULL, NULL, NULL }, // colorburn 1593 { NULL, NULL, NULL }, // hardlight 1594 { NULL, NULL, NULL }, // softlight 1595 { NULL, NULL, NULL }, // difference 1596 { NULL, NULL, NULL }, // exclusion 1597 { NULL, NULL, NULL }, // multiply 1598 { NULL, NULL, NULL }, // hue 1599 { NULL, NULL, NULL }, // saturation 1600 { NULL, NULL, NULL }, // color 1601 { NULL, NULL, NULL }, // luminosity 1602}; 1603 1604SkXfermodeProc16 SkXfermode::GetProc16(Mode mode, SkColor srcColor) { 1605 SkXfermodeProc16 proc16 = NULL; 1606 if ((unsigned)mode < kModeCount) { 1607 const Proc16Rec& rec = gModeProcs16[mode]; 1608 unsigned a = SkColorGetA(srcColor); 1609 1610 if (0 == a) { 1611 proc16 = rec.fProc16_0; 1612 } else if (255 == a) { 1613 proc16 = rec.fProc16_255; 1614 } else { 1615 proc16 = rec.fProc16_General; 1616 } 1617 } 1618 return proc16; 1619} 1620 1621SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkXfermode) 1622 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkProcCoeffXfermode) 1623 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkClearXfermode) 1624 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSrcXfermode) 1625 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDstInXfermode) 1626 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDstOutXfermode) 1627SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END 1628