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