SkXfermode.cpp revision 2cf444f7040614b43af67e368f3aa636ebeaa45a
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, SkXfermode::kOne_Coeff, SkXfermode::kISC_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 all the separable xfer modes that cannot be expressed as Coeffs. 954 */ 955class XferEffect : public GrEffect { 956public: 957 static bool IsSupportedMode(SkXfermode::Mode mode) { 958 return mode > SkXfermode::kLastCoeffMode && mode <= SkXfermode::kLastMode; 959 } 960 961 static GrEffectRef* Create(SkXfermode::Mode mode) { 962 if (!IsSupportedMode(mode)) { 963 return NULL; 964 } else { 965 AutoEffectUnref effect(SkNEW_ARGS(XferEffect, (mode))); 966 return CreateEffectRef(effect); 967 } 968 } 969 970 virtual void getConstantColorComponents(GrColor* color, 971 uint32_t* validFlags) const SK_OVERRIDE { 972 *validFlags = 0; 973 } 974 975 virtual const GrBackendEffectFactory& getFactory() const SK_OVERRIDE { 976 return GrTBackendEffectFactory<XferEffect>::getInstance(); 977 } 978 979 static const char* Name() { return "XferEffect"; } 980 981 SkXfermode::Mode mode() const { return fMode; } 982 983 class GLEffect : public GrGLEffect { 984 public: 985 GLEffect(const GrBackendEffectFactory& factory, const GrDrawEffect&) 986 : GrGLEffect(factory ) { 987 } 988 virtual void emitCode(GrGLShaderBuilder* builder, 989 const GrDrawEffect& drawEffect, 990 EffectKey key, 991 const char* outputColor, 992 const char* inputColor, 993 const TextureSamplerArray& samplers) SK_OVERRIDE { 994 const char* dstColor = builder->dstColor(); 995 GrAssert(NULL != dstColor); 996 997 // We don't try to optimize for this case at all 998 if (NULL == inputColor) { 999 builder->fsCodeAppendf("\tconst vec4 ones = %s;\n", GrGLSLOnesVecf(4)); 1000 inputColor = "ones"; 1001 } 1002 1003 SkXfermode::Mode mode = drawEffect.castEffect<XferEffect>().mode(); 1004 builder->fsCodeAppendf("\t\t// SkXfermode::Mode: %s\n", SkXfermode::ModeName(mode)); 1005 1006 // These all perform src-over on the alpha channel. 1007 builder->fsCodeAppendf("\t\t%s.a = %s.a + (1.0 - %s.a) * %s.a;\n", 1008 outputColor, inputColor, inputColor, dstColor); 1009 1010 switch (mode) { 1011 case SkXfermode::kOverlay_Mode: 1012 // Overlay is Hard-Light with the src and dst reversed 1013 HardLight(builder, outputColor, dstColor, inputColor); 1014 break; 1015 case SkXfermode::kDarken_Mode: 1016 builder->fsCodeAppendf("\t\t%s.rgb = min((1.0 - %s.a) * %s.rgb + %s.rgb, " 1017 "(1.0 - %s.a) * %s.rgb + %s.rgb);\n", 1018 outputColor, 1019 inputColor, dstColor, inputColor, 1020 dstColor, inputColor, dstColor); 1021 break; 1022 case SkXfermode::kLighten_Mode: 1023 builder->fsCodeAppendf("\t\t%s.rgb = max((1.0 - %s.a) * %s.rgb + %s.rgb, " 1024 "(1.0 - %s.a) * %s.rgb + %s.rgb);\n", 1025 outputColor, 1026 inputColor, dstColor, inputColor, 1027 dstColor, inputColor, dstColor); 1028 break; 1029 case SkXfermode::kColorDodge_Mode: 1030 ColorDodgeComponent(builder, outputColor, inputColor, dstColor, 'r'); 1031 ColorDodgeComponent(builder, outputColor, inputColor, dstColor, 'g'); 1032 ColorDodgeComponent(builder, outputColor, inputColor, dstColor, 'b'); 1033 break; 1034 case SkXfermode::kColorBurn_Mode: 1035 ColorBurnComponent(builder, outputColor, inputColor, dstColor, 'r'); 1036 ColorBurnComponent(builder, outputColor, inputColor, dstColor, 'g'); 1037 ColorBurnComponent(builder, outputColor, inputColor, dstColor, 'b'); 1038 break; 1039 case SkXfermode::kHardLight_Mode: 1040 HardLight(builder, outputColor, inputColor, dstColor); 1041 break; 1042 case SkXfermode::kSoftLight_Mode: 1043 builder->fsCodeAppendf("\t\tif (0.0 == %s.a) {\n", dstColor); 1044 builder->fsCodeAppendf("\t\t\t%s.rgba = %s;\n", outputColor, inputColor); 1045 builder->fsCodeAppendf("\t\t} else {\n"); 1046 SoftLightComponentPosDstAlpha(builder, outputColor, inputColor, dstColor, 'r'); 1047 SoftLightComponentPosDstAlpha(builder, outputColor, inputColor, dstColor, 'g'); 1048 SoftLightComponentPosDstAlpha(builder, outputColor, inputColor, dstColor, 'b'); 1049 builder->fsCodeAppendf("\t\t}\n"); 1050 break; 1051 case SkXfermode::kDifference_Mode: 1052 builder->fsCodeAppendf("\t\t%s.rgb = %s.rgb + %s.rgb -" 1053 "2.0 * min(%s.rgb * %s.a, %s.rgb * %s.a);\n", 1054 outputColor, inputColor, dstColor, inputColor, dstColor, 1055 dstColor, inputColor); 1056 break; 1057 case SkXfermode::kExclusion_Mode: 1058 builder->fsCodeAppendf("\t\t%s.rgb = %s.rgb + %s.rgb - " 1059 "2.0 * %s.rgb * %s.rgb;\n", 1060 outputColor, dstColor, inputColor, dstColor, inputColor); 1061 break; 1062 case SkXfermode::kMultiply_Mode: 1063 builder->fsCodeAppendf("\t\t%s.rgb = (1.0 - %s.a) * %s.rgb + " 1064 "(1.0 - %s.a) * %s.rgb + " 1065 "%s.rgb * %s.rgb;\n", 1066 outputColor, inputColor, dstColor, dstColor, inputColor, 1067 inputColor, dstColor); 1068 break; 1069 case SkXfermode::kHue_Mode: { 1070 // SetLum(SetSat(S * Da, Sat(D * Sa)), Sa*Da, D*Sa) + (1 - Sa) * D + (1 - Da) * S 1071 SkString setSat, setLum; 1072 AddSatFunction(builder, &setSat); 1073 AddLumFunction(builder, &setLum); 1074 builder->fsCodeAppendf("\t\tvec4 dstSrcAlpha = %s * %s.a;\n", 1075 dstColor, inputColor); 1076 builder->fsCodeAppendf("\t\t%s.rgb = %s(%s(%s.rgb * %s.a, dstSrcAlpha.rgb), dstSrcAlpha.a, dstSrcAlpha.rgb);\n", 1077 outputColor, setLum.c_str(), setSat.c_str(), inputColor, 1078 dstColor); 1079 builder->fsCodeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n", 1080 outputColor, inputColor, dstColor, dstColor, inputColor); 1081 break; 1082 } 1083 case SkXfermode::kSaturation_Mode: { 1084 // SetLum(SetSat(D * Sa, Sat(S * Da)), Sa*Da, D*Sa)) + (1 - Sa) * D + (1 - Da) * S 1085 SkString setSat, setLum; 1086 AddSatFunction(builder, &setSat); 1087 AddLumFunction(builder, &setLum); 1088 builder->fsCodeAppendf("\t\tvec4 dstSrcAlpha = %s * %s.a;\n", 1089 dstColor, inputColor); 1090 builder->fsCodeAppendf("\t\t%s.rgb = %s(%s(dstSrcAlpha.rgb, %s.rgb * %s.a), dstSrcAlpha.a, dstSrcAlpha.rgb);\n", 1091 outputColor, setLum.c_str(), setSat.c_str(), inputColor, 1092 dstColor); 1093 builder->fsCodeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n", 1094 outputColor, inputColor, dstColor, dstColor, inputColor); 1095 break; 1096 } 1097 case SkXfermode::kColor_Mode: { 1098 // SetLum(S * Da, Sa* Da, D * Sa) + (1 - Sa) * D + (1 - Da) * S 1099 SkString setLum; 1100 AddLumFunction(builder, &setLum); 1101 builder->fsCodeAppendf("\t\tvec4 srcDstAlpha = %s * %s.a;\n", 1102 inputColor, dstColor); 1103 builder->fsCodeAppendf("\t\t%s.rgb = %s(srcDstAlpha.rgb, srcDstAlpha.a, %s.rgb * %s.a);\n", 1104 outputColor, setLum.c_str(), dstColor, inputColor); 1105 builder->fsCodeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n", 1106 outputColor, inputColor, dstColor, dstColor, inputColor); 1107 break; 1108 } 1109 case SkXfermode::kLuminosity_Mode: { 1110 // SetLum(D * Sa, Sa* Da, S * Da) + (1 - Sa) * D + (1 - Da) * S 1111 SkString setLum; 1112 AddLumFunction(builder, &setLum); 1113 builder->fsCodeAppendf("\t\tvec4 srcDstAlpha = %s * %s.a;\n", 1114 inputColor, dstColor); 1115 builder->fsCodeAppendf("\t\t%s.rgb = %s(%s.rgb * %s.a, srcDstAlpha.a, srcDstAlpha.rgb);\n", 1116 outputColor, setLum.c_str(), dstColor, inputColor); 1117 builder->fsCodeAppendf("\t\t%s.rgb += (1.0 - %s.a) * %s.rgb + (1.0 - %s.a) * %s.rgb;\n", 1118 outputColor, inputColor, dstColor, dstColor, inputColor); 1119 break; 1120 } 1121 default: 1122 GrCrash("Unknown XferEffect mode."); 1123 break; 1124 } 1125 } 1126 1127 static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) { 1128 return drawEffect.castEffect<XferEffect>().mode(); 1129 } 1130 1131 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE {} 1132 1133 private: 1134 static void HardLight(GrGLShaderBuilder* builder, 1135 const char* final, 1136 const char* src, 1137 const char* dst) { 1138 builder->fsCodeAppendf("\t\t%s.a = 1.0 - (1.0 - %s.a) * (1.0 - %s.a);\n", 1139 final, dst, src); 1140 builder->fsCodeAppendf("\t\t%s.rgb = mix(2.0 * %s.rgb * %s.rgb, ", 1141 final, src, dst); 1142 builder->fsCodeAppendf("%s.aaa * %s.aaa - 2.0 * (%s.aaa - %s.rgb) * (%s.aaa - %s.rgb),", 1143 src, dst, dst, dst, src, src); 1144 builder->fsCodeAppendf("vec3(greaterThan(2.0 * %s.rgb, %s.aaa)));\n", 1145 src, src); 1146 builder->fsCodeAppendf("\t\t%s.rgb += %s.rgb * (1.0 - %s.a) + %s.rgb * (1.0 - %s.a);\n", 1147 final, src, dst, dst, src); 1148 } 1149 1150 // Does one component of color-dodge 1151 static void ColorDodgeComponent(GrGLShaderBuilder* builder, 1152 const char* final, 1153 const char* src, 1154 const char* dst, 1155 const char component) { 1156 builder->fsCodeAppendf("\t\tif (0.0 == %s.%c) {\n", dst, component); 1157 builder->fsCodeAppendf("\t\t\t%s.%c = %s.%c * (1.0 - %s.a);\n", 1158 final, component, src, component, dst); 1159 builder->fsCodeAppend("\t\t} else {\n"); 1160 builder->fsCodeAppendf("\t\t\tfloat d = %s.a - %s.%c;\n", src, src, component); 1161 builder->fsCodeAppend("\t\t\tif (0.0 == d) {\n"); 1162 builder->fsCodeAppendf("\t\t\t\t%s.%c = %s.a * %s.a + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);\n", 1163 final, component, src, dst, src, component, dst, dst, component, 1164 src); 1165 builder->fsCodeAppend("\t\t\t} else {\n"); 1166 builder->fsCodeAppendf("\t\t\t\td = min(%s.a, %s.%c * %s.a / d);\n", 1167 dst, dst, component, src); 1168 builder->fsCodeAppendf("\t\t\t\t%s.%c = d * %s.a + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);\n", 1169 final, component, src, src, component, dst, dst, component, src); 1170 builder->fsCodeAppend("\t\t\t}\n"); 1171 builder->fsCodeAppend("\t\t}\n"); 1172 } 1173 1174 // Does one component of color-burn 1175 static void ColorBurnComponent(GrGLShaderBuilder* builder, 1176 const char* final, 1177 const char* src, 1178 const char* dst, 1179 const char component) { 1180 builder->fsCodeAppendf("\t\tif (%s.a == %s.%c) {\n", dst, dst, component); 1181 builder->fsCodeAppendf("\t\t\t%s.%c = %s.a * %s.a + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);\n", 1182 final, component, src, dst, src, component, dst, dst, component, 1183 src); 1184 builder->fsCodeAppendf("\t\t} else if (0.0 == %s.%c) {\n", src, component); 1185 builder->fsCodeAppendf("\t\t\t%s.%c = %s.%c * (1.0 - %s.a);\n", 1186 final, component, dst, component, src); 1187 builder->fsCodeAppend("\t\t} else {\n"); 1188 builder->fsCodeAppendf("\t\t\tfloat d = max(0.0, %s.a - (%s.a - %s.%c) * %s.a / %s.%c);\n", 1189 dst, dst, dst, component, src, src, component); 1190 builder->fsCodeAppendf("\t\t\t%s.%c = %s.a * d + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);\n", 1191 final, component, src, src, component, dst, dst, component, src); 1192 builder->fsCodeAppend("\t\t}\n"); 1193 } 1194 1195 // Does one component of soft-light. Caller should have already checked that dst alpha > 0. 1196 static void SoftLightComponentPosDstAlpha(GrGLShaderBuilder* builder, 1197 const char* final, 1198 const char* src, 1199 const char* dst, 1200 const char component) { 1201 // if (2S < Sa) 1202 builder->fsCodeAppendf("\t\t\tif (2.0 * %s.%c <= %s.a) {\n", src, component, src); 1203 // (D^2 (Sa-2 S))/Da+(1-Da) S+D (-Sa+2 S+1) 1204 builder->fsCodeAppendf("\t\t\t\t%s.%c = (%s.%c*%s.%c*(%s.a - 2.0*%s.%c)) / %s.a + (1.0 - %s.a) * %s.%c + %s.%c*(-%s.a + 2.0*%s.%c + 1.0);\n", 1205 final, component, dst, component, dst, component, src, src, 1206 component, dst, dst, src, component, dst, component, src, src, 1207 component); 1208 // else if (4D < Da) 1209 builder->fsCodeAppendf("\t\t\t} else if (4.0 * %s.%c <= %s.a) {\n", 1210 dst, component, dst); 1211 builder->fsCodeAppendf("\t\t\t\tfloat DSqd = %s.%c * %s.%c;\n", 1212 dst, component, dst, component); 1213 builder->fsCodeAppendf("\t\t\t\tfloat DCub = DSqd * %s.%c;\n", dst, component); 1214 builder->fsCodeAppendf("\t\t\t\tfloat DaSqd = %s.a * %s.a;\n", dst, dst); 1215 builder->fsCodeAppendf("\t\t\t\tfloat DaCub = DaSqd * %s.a;\n", dst); 1216 // (Da^3 (-S)+Da^2 (S-D (3 Sa-6 S-1))+12 Da D^2 (Sa-2 S)-16 D^3 (Sa-2 S))/Da^2 1217 builder->fsCodeAppendf("\t\t\t\t%s.%c = (-DaCub*%s.%c + DaSqd*(%s.%c - %s.%c * (3.0*%s.a - 6.0*%s.%c - 1.0)) + 12.0*%s.a*DSqd*(%s.a - 2.0*%s.%c) - 16.0*DCub * (%s.a - 2.0*%s.%c)) / DaSqd;\n", 1218 final, component, src, component, src, component, dst, component, 1219 src, src, component, dst, src, src, component, src, src, 1220 component); 1221 builder->fsCodeAppendf("\t\t\t} else {\n"); 1222 // -sqrt(Da * D) (Sa-2 S)-Da S+D (Sa-2 S+1)+S 1223 builder->fsCodeAppendf("\t\t\t\t%s.%c = -sqrt(%s.a*%s.%c)*(%s.a - 2.0*%s.%c) - %s.a*%s.%c + %s.%c*(%s.a - 2.0*%s.%c + 1.0) + %s.%c;\n", 1224 final, component, dst, dst, component, src, src, component, dst, 1225 src, component, dst, component, src, src, component, src, 1226 component); 1227 builder->fsCodeAppendf("\t\t\t}\n"); 1228 } 1229 1230 // Adds a function that takes two colors and an alpha as input. It produces a color with the 1231 // hue and saturation of the first color, the luminosity of the second color, and the input 1232 // alpha. It has this signature: 1233 // vec3 set_luminance(vec3 hueSatColor, float alpha, vec3 lumColor). 1234 static void AddLumFunction(GrGLShaderBuilder* builder, SkString* setLumFunction) { 1235 // Emit a helper that gets the luminance of a color. 1236 SkString getFunction; 1237 GrGLShaderVar getLumArgs[] = { 1238 GrGLShaderVar("color", kVec3f_GrSLType), 1239 }; 1240 SkString getLumBody("\treturn dot(vec3(0.3, 0.59, 0.11), color);\n"); 1241 builder->emitFunction(GrGLShaderBuilder::kFragment_ShaderType, 1242 kFloat_GrSLType, 1243 "luminance", 1244 SK_ARRAY_COUNT(getLumArgs), getLumArgs, 1245 getLumBody.c_str(), 1246 &getFunction); 1247 1248 // Emit the set luminance function. 1249 GrGLShaderVar setLumArgs[] = { 1250 GrGLShaderVar("hueSat", kVec3f_GrSLType), 1251 GrGLShaderVar("alpha", kFloat_GrSLType), 1252 GrGLShaderVar("lumColor", kVec3f_GrSLType), 1253 }; 1254 SkString setLumBody; 1255 setLumBody.printf("\tfloat diff = %s(lumColor - hueSat);\n", getFunction.c_str()); 1256 setLumBody.append("\tvec3 outColor = hueSat + diff;\n"); 1257 setLumBody.appendf("\tfloat outLum = %s(outColor);\n", getFunction.c_str()); 1258 setLumBody.append("\tfloat minComp = min(min(outColor.r, outColor.g), outColor.b);\n" 1259 "\tfloat maxComp = max(max(outColor.r, outColor.g), outColor.b);\n" 1260 "\tif (minComp < 0.0) {\n" 1261 "\t\toutColor = outLum + ((outColor - vec3(outLum, outLum, outLum)) * outLum) / (outLum - minComp);\n" 1262 "\t}\n" 1263 "\tif (maxComp > alpha) {\n" 1264 "\t\toutColor = outLum + ((outColor - vec3(outLum, outLum, outLum)) * (alpha - outLum)) / (maxComp - outLum);\n" 1265 "\t}\n" 1266 "\treturn outColor;\n"); 1267 builder->emitFunction(GrGLShaderBuilder::kFragment_ShaderType, 1268 kVec3f_GrSLType, 1269 "set_luminance", 1270 SK_ARRAY_COUNT(setLumArgs), setLumArgs, 1271 setLumBody.c_str(), 1272 setLumFunction); 1273 } 1274 1275 // Adds a function that creates a color with the hue and luminosity of one input color and 1276 // the saturation of another color. It will have this signature: 1277 // float set_saturation(vec3 hueLumColor, vec3 satColor) 1278 static void AddSatFunction(GrGLShaderBuilder* builder, SkString* setSatFunction) { 1279 // Emit a helper that gets the saturation of a color 1280 SkString getFunction; 1281 GrGLShaderVar getSatArgs[] = { GrGLShaderVar("color", kVec3f_GrSLType) }; 1282 SkString getSatBody; 1283 getSatBody.printf("\treturn max(max(color.r, color.g), color.b) - " 1284 "min(min(color.r, color.g), color.b);\n"); 1285 builder->emitFunction(GrGLShaderBuilder::kFragment_ShaderType, 1286 kFloat_GrSLType, 1287 "saturation", 1288 SK_ARRAY_COUNT(getSatArgs), getSatArgs, 1289 getSatBody.c_str(), 1290 &getFunction); 1291 1292 // Emit a helper that sets the saturation given sorted input channels 1293 SkString helperFunction; 1294 GrGLShaderVar helperArgs[] = { 1295 GrGLShaderVar("minComp", kFloat_GrSLType), 1296 GrGLShaderVar("midComp", kFloat_GrSLType), 1297 GrGLShaderVar("maxComp", kFloat_GrSLType), 1298 GrGLShaderVar("sat", kFloat_GrSLType), 1299 }; 1300 helperArgs[0].setTypeModifier(GrGLShaderVar::kInOut_TypeModifier); 1301 helperArgs[1].setTypeModifier(GrGLShaderVar::kInOut_TypeModifier); 1302 helperArgs[2].setTypeModifier(GrGLShaderVar::kInOut_TypeModifier); 1303 SkString helperBody; 1304 helperBody.append("\tif (minComp < maxComp) {\n" 1305 "\t\tmidComp = sat * (midComp - minComp) / (maxComp - minComp);\n" 1306 "\t\tmaxComp = sat;\n" 1307 "\t} else {\n" 1308 "\t\tmidComp = maxComp = 0.0;\n" 1309 "\t}\n" 1310 "\tminComp = 0.0;\n"); 1311 builder->emitFunction(GrGLShaderBuilder::kFragment_ShaderType, 1312 kVoid_GrSLType, 1313 "set_saturation_helper", 1314 SK_ARRAY_COUNT(helperArgs), helperArgs, 1315 helperBody.c_str(), 1316 &helperFunction); 1317 1318 GrGLShaderVar setSatArgs[] = { 1319 GrGLShaderVar("hueLumColor", kVec3f_GrSLType), 1320 GrGLShaderVar("satColor", kVec3f_GrSLType), 1321 }; 1322 const char* helpFunc = helperFunction.c_str(); 1323 SkString setSatBody; 1324 setSatBody.appendf("\tfloat sat = %s(satColor);\n" 1325 "\tif (hueLumColor.r <= hueLumColor.g) {\n" 1326 "\t\tif (hueLumColor.g <= hueLumColor.b) {\n" 1327 "\t\t\t%s(hueLumColor.r, hueLumColor.g, hueLumColor.b, sat);\n" 1328 "\t\t} else if (hueLumColor.r <= hueLumColor.b) {\n" 1329 "\t\t\t%s(hueLumColor.r, hueLumColor.b, hueLumColor.g, sat);\n" 1330 "\t\t} else {\n" 1331 "\t\t\t%s(hueLumColor.b, hueLumColor.r, hueLumColor.g, sat);\n" 1332 "\t\t}\n" 1333 "\t} else if (hueLumColor.r <= hueLumColor.b) {\n" 1334 "\t\t%s(hueLumColor.g, hueLumColor.r, hueLumColor.b, sat);\n" 1335 "\t} else if (hueLumColor.g <= hueLumColor.b) {\n" 1336 "\t\t%s(hueLumColor.g, hueLumColor.b, hueLumColor.r, sat);\n" 1337 "\t} else {\n" 1338 "\t\t%s(hueLumColor.b, hueLumColor.g, hueLumColor.r, sat);\n" 1339 "\t}\n" 1340 "\treturn hueLumColor;", 1341 getFunction.c_str(), helpFunc, helpFunc, helpFunc, helpFunc, 1342 helpFunc, helpFunc); 1343 builder->emitFunction(GrGLShaderBuilder::kFragment_ShaderType, 1344 kVec3f_GrSLType, 1345 "set_saturation", 1346 SK_ARRAY_COUNT(setSatArgs), setSatArgs, 1347 setSatBody.c_str(), 1348 setSatFunction); 1349 1350 } 1351 1352 typedef GrGLEffect INHERITED; 1353 }; 1354 1355 GR_DECLARE_EFFECT_TEST; 1356 1357private: 1358 XferEffect(SkXfermode::Mode mode) : fMode(mode) { this->setWillReadDst(); } 1359 virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE { return true; } 1360 1361 SkXfermode::Mode fMode; 1362 1363 typedef GrEffect INHERITED; 1364}; 1365 1366GR_DEFINE_EFFECT_TEST(XferEffect); 1367GrEffectRef* XferEffect::TestCreate(SkMWCRandom* rand, 1368 GrContext*, 1369 const GrDrawTargetCaps&, 1370 GrTexture*[]) { 1371 int mode; 1372 do { 1373 mode = rand->nextRangeU(SkXfermode::kLastCoeffMode + 1, SkXfermode::kLastSeparableMode); 1374 } while (mode == SkXfermode::kHardLight_Mode); 1375 1376 static AutoEffectUnref gEffect(SkNEW_ARGS(XferEffect, (static_cast<SkXfermode::Mode>(mode)))); 1377 return CreateEffectRef(gEffect); 1378} 1379 1380#endif 1381 1382/////////////////////////////////////////////////////////////////////////////// 1383/////////////////////////////////////////////////////////////////////////////// 1384 1385class SkProcCoeffXfermode : public SkProcXfermode { 1386public: 1387 SkProcCoeffXfermode(const ProcCoeff& rec, Mode mode) 1388 : INHERITED(rec.fProc) { 1389 fMode = mode; 1390 // these may be valid, or may be CANNOT_USE_COEFF 1391 fSrcCoeff = rec.fSC; 1392 fDstCoeff = rec.fDC; 1393 } 1394 1395 virtual bool asMode(Mode* mode) const SK_OVERRIDE { 1396 if (mode) { 1397 *mode = fMode; 1398 } 1399 return true; 1400 } 1401 1402 virtual bool asCoeff(Coeff* sc, Coeff* dc) const SK_OVERRIDE { 1403 if (CANNOT_USE_COEFF == fSrcCoeff) { 1404 return false; 1405 } 1406 1407 if (sc) { 1408 *sc = fSrcCoeff; 1409 } 1410 if (dc) { 1411 *dc = fDstCoeff; 1412 } 1413 return true; 1414 } 1415 1416#if SK_SUPPORT_GPU 1417 virtual bool asNewEffectOrCoeff(GrContext*, 1418 GrEffectRef** effect, 1419 Coeff* src, 1420 Coeff* dst) const SK_OVERRIDE { 1421 if (this->asCoeff(src, dst)) { 1422 return true; 1423 } 1424 if (XferEffect::IsSupportedMode(fMode)) { 1425 if (NULL != effect) { 1426 *effect = XferEffect::Create(fMode); 1427 SkASSERT(NULL != *effect); 1428 } 1429 return true; 1430 } 1431 return false; 1432 } 1433#endif 1434 1435 SK_DEVELOPER_TO_STRING() 1436 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkProcCoeffXfermode) 1437 1438protected: 1439 SkProcCoeffXfermode(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) { 1440 fMode = (SkXfermode::Mode)buffer.read32(); 1441 1442 const ProcCoeff& rec = gProcCoeffs[fMode]; 1443 // these may be valid, or may be CANNOT_USE_COEFF 1444 fSrcCoeff = rec.fSC; 1445 fDstCoeff = rec.fDC; 1446 // now update our function-ptr in the super class 1447 this->INHERITED::setProc(rec.fProc); 1448 } 1449 1450 virtual void flatten(SkFlattenableWriteBuffer& buffer) const SK_OVERRIDE { 1451 this->INHERITED::flatten(buffer); 1452 buffer.write32(fMode); 1453 } 1454 1455private: 1456 Mode fMode; 1457 Coeff fSrcCoeff, fDstCoeff; 1458 1459 typedef SkProcXfermode INHERITED; 1460}; 1461 1462const char* SkXfermode::ModeName(Mode mode) { 1463 SkASSERT((unsigned) mode <= (unsigned)kLastMode); 1464 const char* gModeStrings[] = { 1465 "Clear", "Src", "Dst", "SrcOver", "DstOver", "SrcIn", "DstIn", 1466 "SrcOut", "DstOut", "SrcATop", "DstATop", "Xor", "Plus", 1467 "Modulate", "Screen", "Overlay", "Darken", "Lighten", "ColorDodge", 1468 "ColorBurn", "HardLight", "SoftLight", "Difference", "Exclusion", 1469 "Multiply", "Hue", "Saturation", "Color", "Luminosity" 1470 }; 1471 return gModeStrings[mode]; 1472 SK_COMPILE_ASSERT(SK_ARRAY_COUNT(gModeStrings) == kLastMode + 1, mode_count); 1473} 1474 1475#ifdef SK_DEVELOPER 1476void SkProcCoeffXfermode::toString(SkString* str) const { 1477 str->append("SkProcCoeffXfermode: "); 1478 1479 str->append("mode: "); 1480 str->append(ModeName(fMode)); 1481 1482 static const char* gCoeffStrings[kCoeffCount] = { 1483 "Zero", "One", "SC", "ISC", "DC", "IDC", "SA", "ISA", "DA", "IDA" 1484 }; 1485 1486 str->append(" src: "); 1487 if (CANNOT_USE_COEFF == fSrcCoeff) { 1488 str->append("can't use"); 1489 } else { 1490 str->append(gCoeffStrings[fSrcCoeff]); 1491 } 1492 1493 str->append(" dst: "); 1494 if (CANNOT_USE_COEFF == fDstCoeff) { 1495 str->append("can't use"); 1496 } else { 1497 str->append(gCoeffStrings[fDstCoeff]); 1498 } 1499} 1500#endif 1501 1502/////////////////////////////////////////////////////////////////////////////// 1503 1504class SkClearXfermode : public SkProcCoeffXfermode { 1505public: 1506 SkClearXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kClear_Mode) {} 1507 1508 virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE; 1509 virtual void xferA8(SkAlpha*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE; 1510 1511 SK_DEVELOPER_TO_STRING() 1512 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkClearXfermode) 1513 1514private: 1515 SkClearXfermode(SkFlattenableReadBuffer& buffer) 1516 : SkProcCoeffXfermode(buffer) {} 1517 1518 typedef SkProcCoeffXfermode INHERITED; 1519}; 1520 1521void SkClearXfermode::xfer32(SkPMColor* SK_RESTRICT dst, 1522 const SkPMColor* SK_RESTRICT, int count, 1523 const SkAlpha* SK_RESTRICT aa) const { 1524 SkASSERT(dst && count >= 0); 1525 1526 if (NULL == aa) { 1527 memset(dst, 0, count << 2); 1528 } else { 1529 for (int i = count - 1; i >= 0; --i) { 1530 unsigned a = aa[i]; 1531 if (0xFF == a) { 1532 dst[i] = 0; 1533 } else if (a != 0) { 1534 dst[i] = SkAlphaMulQ(dst[i], SkAlpha255To256(255 - a)); 1535 } 1536 } 1537 } 1538} 1539void SkClearXfermode::xferA8(SkAlpha* SK_RESTRICT dst, 1540 const SkPMColor* SK_RESTRICT, int count, 1541 const SkAlpha* SK_RESTRICT aa) const { 1542 SkASSERT(dst && count >= 0); 1543 1544 if (NULL == aa) { 1545 memset(dst, 0, count); 1546 } else { 1547 for (int i = count - 1; i >= 0; --i) { 1548 unsigned a = aa[i]; 1549 if (0xFF == a) { 1550 dst[i] = 0; 1551 } else if (0 != a) { 1552 dst[i] = SkAlphaMulAlpha(dst[i], 255 - a); 1553 } 1554 } 1555 } 1556} 1557 1558#ifdef SK_DEVELOPER 1559void SkClearXfermode::toString(SkString* str) const { 1560 this->INHERITED::toString(str); 1561} 1562#endif 1563 1564/////////////////////////////////////////////////////////////////////////////// 1565 1566class SkSrcXfermode : public SkProcCoeffXfermode { 1567public: 1568 SkSrcXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kSrc_Mode) {} 1569 1570 virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE; 1571 virtual void xferA8(SkAlpha*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE; 1572 1573 SK_DEVELOPER_TO_STRING() 1574 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkSrcXfermode) 1575 1576private: 1577 SkSrcXfermode(SkFlattenableReadBuffer& buffer) 1578 : SkProcCoeffXfermode(buffer) {} 1579 1580 typedef SkProcCoeffXfermode INHERITED; 1581}; 1582 1583void SkSrcXfermode::xfer32(SkPMColor* SK_RESTRICT dst, 1584 const SkPMColor* SK_RESTRICT src, int count, 1585 const SkAlpha* SK_RESTRICT aa) const { 1586 SkASSERT(dst && src && count >= 0); 1587 1588 if (NULL == aa) { 1589 memcpy(dst, src, count << 2); 1590 } else { 1591 for (int i = count - 1; i >= 0; --i) { 1592 unsigned a = aa[i]; 1593 if (a == 0xFF) { 1594 dst[i] = src[i]; 1595 } else if (a != 0) { 1596 dst[i] = SkFourByteInterp(src[i], dst[i], a); 1597 } 1598 } 1599 } 1600} 1601 1602void SkSrcXfermode::xferA8(SkAlpha* SK_RESTRICT dst, 1603 const SkPMColor* SK_RESTRICT src, int count, 1604 const SkAlpha* SK_RESTRICT aa) const { 1605 SkASSERT(dst && src && count >= 0); 1606 1607 if (NULL == aa) { 1608 for (int i = count - 1; i >= 0; --i) { 1609 dst[i] = SkToU8(SkGetPackedA32(src[i])); 1610 } 1611 } else { 1612 for (int i = count - 1; i >= 0; --i) { 1613 unsigned a = aa[i]; 1614 if (0 != a) { 1615 unsigned srcA = SkGetPackedA32(src[i]); 1616 if (a == 0xFF) { 1617 dst[i] = SkToU8(srcA); 1618 } else { 1619 dst[i] = SkToU8(SkAlphaBlend(srcA, dst[i], a)); 1620 } 1621 } 1622 } 1623 } 1624} 1625#ifdef SK_DEVELOPER 1626void SkSrcXfermode::toString(SkString* str) const { 1627 this->INHERITED::toString(str); 1628} 1629#endif 1630 1631/////////////////////////////////////////////////////////////////////////////// 1632 1633class SkDstInXfermode : public SkProcCoeffXfermode { 1634public: 1635 SkDstInXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstIn_Mode) {} 1636 1637 virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE; 1638 1639 SK_DEVELOPER_TO_STRING() 1640 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDstInXfermode) 1641 1642private: 1643 SkDstInXfermode(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {} 1644 1645 typedef SkProcCoeffXfermode INHERITED; 1646}; 1647 1648void SkDstInXfermode::xfer32(SkPMColor* SK_RESTRICT dst, 1649 const SkPMColor* SK_RESTRICT src, int count, 1650 const SkAlpha* SK_RESTRICT aa) const { 1651 SkASSERT(dst && src); 1652 1653 if (count <= 0) { 1654 return; 1655 } 1656 if (NULL != aa) { 1657 return this->INHERITED::xfer32(dst, src, count, aa); 1658 } 1659 1660 do { 1661 unsigned a = SkGetPackedA32(*src); 1662 *dst = SkAlphaMulQ(*dst, SkAlpha255To256(a)); 1663 dst++; 1664 src++; 1665 } while (--count != 0); 1666} 1667 1668#ifdef SK_DEVELOPER 1669void SkDstInXfermode::toString(SkString* str) const { 1670 this->INHERITED::toString(str); 1671} 1672#endif 1673 1674/////////////////////////////////////////////////////////////////////////////// 1675 1676class SkDstOutXfermode : public SkProcCoeffXfermode { 1677public: 1678 SkDstOutXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstOut_Mode) {} 1679 1680 virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE; 1681 1682 SK_DEVELOPER_TO_STRING() 1683 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDstOutXfermode) 1684 1685private: 1686 SkDstOutXfermode(SkFlattenableReadBuffer& buffer) 1687 : INHERITED(buffer) {} 1688 1689 typedef SkProcCoeffXfermode INHERITED; 1690}; 1691 1692void SkDstOutXfermode::xfer32(SkPMColor* SK_RESTRICT dst, 1693 const SkPMColor* SK_RESTRICT src, int count, 1694 const SkAlpha* SK_RESTRICT aa) const { 1695 SkASSERT(dst && src); 1696 1697 if (count <= 0) { 1698 return; 1699 } 1700 if (NULL != aa) { 1701 return this->INHERITED::xfer32(dst, src, count, aa); 1702 } 1703 1704 do { 1705 unsigned a = SkGetPackedA32(*src); 1706 *dst = SkAlphaMulQ(*dst, SkAlpha255To256(255 - a)); 1707 dst++; 1708 src++; 1709 } while (--count != 0); 1710} 1711 1712#ifdef SK_DEVELOPER 1713void SkDstOutXfermode::toString(SkString* str) const { 1714 this->INHERITED::toString(str); 1715} 1716#endif 1717 1718/////////////////////////////////////////////////////////////////////////////// 1719 1720SkXfermode* SkXfermode::Create(Mode mode) { 1721 SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount); 1722 SkASSERT((unsigned)mode < kModeCount); 1723 1724 const ProcCoeff& rec = gProcCoeffs[mode]; 1725 1726 switch (mode) { 1727 case kClear_Mode: 1728 return SkNEW_ARGS(SkClearXfermode, (rec)); 1729 case kSrc_Mode: 1730 return SkNEW_ARGS(SkSrcXfermode, (rec)); 1731 case kSrcOver_Mode: 1732 return NULL; 1733 case kDstIn_Mode: 1734 return SkNEW_ARGS(SkDstInXfermode, (rec)); 1735 case kDstOut_Mode: 1736 return SkNEW_ARGS(SkDstOutXfermode, (rec)); 1737 default: 1738 return SkNEW_ARGS(SkProcCoeffXfermode, (rec, mode)); 1739 } 1740} 1741 1742SkXfermodeProc SkXfermode::GetProc(Mode mode) { 1743 SkXfermodeProc proc = NULL; 1744 if ((unsigned)mode < kModeCount) { 1745 proc = gProcCoeffs[mode].fProc; 1746 } 1747 return proc; 1748} 1749 1750bool SkXfermode::ModeAsCoeff(Mode mode, Coeff* src, Coeff* dst) { 1751 SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount); 1752 1753 if ((unsigned)mode >= (unsigned)kModeCount) { 1754 // illegal mode parameter 1755 return false; 1756 } 1757 1758 const ProcCoeff& rec = gProcCoeffs[mode]; 1759 1760 if (CANNOT_USE_COEFF == rec.fSC) { 1761 return false; 1762 } 1763 1764 SkASSERT(CANNOT_USE_COEFF != rec.fDC); 1765 if (src) { 1766 *src = rec.fSC; 1767 } 1768 if (dst) { 1769 *dst = rec.fDC; 1770 } 1771 return true; 1772} 1773 1774bool SkXfermode::AsMode(const SkXfermode* xfer, Mode* mode) { 1775 if (NULL == xfer) { 1776 if (mode) { 1777 *mode = kSrcOver_Mode; 1778 } 1779 return true; 1780 } 1781 return xfer->asMode(mode); 1782} 1783 1784bool SkXfermode::AsCoeff(const SkXfermode* xfer, Coeff* src, Coeff* dst) { 1785 if (NULL == xfer) { 1786 return ModeAsCoeff(kSrcOver_Mode, src, dst); 1787 } 1788 return xfer->asCoeff(src, dst); 1789} 1790 1791bool SkXfermode::IsMode(const SkXfermode* xfer, Mode mode) { 1792 // if xfer==null then the mode is srcover 1793 Mode m = kSrcOver_Mode; 1794 if (xfer && !xfer->asMode(&m)) { 1795 return false; 1796 } 1797 return mode == m; 1798} 1799 1800/////////////////////////////////////////////////////////////////////////////// 1801//////////// 16bit xfermode procs 1802 1803#ifdef SK_DEBUG 1804static bool require_255(SkPMColor src) { return SkGetPackedA32(src) == 0xFF; } 1805static bool require_0(SkPMColor src) { return SkGetPackedA32(src) == 0; } 1806#endif 1807 1808static uint16_t src_modeproc16_255(SkPMColor src, uint16_t dst) { 1809 SkASSERT(require_255(src)); 1810 return SkPixel32ToPixel16(src); 1811} 1812 1813static uint16_t dst_modeproc16(SkPMColor src, uint16_t dst) { 1814 return dst; 1815} 1816 1817static uint16_t srcover_modeproc16_0(SkPMColor src, uint16_t dst) { 1818 SkASSERT(require_0(src)); 1819 return dst; 1820} 1821 1822static uint16_t srcover_modeproc16_255(SkPMColor src, uint16_t dst) { 1823 SkASSERT(require_255(src)); 1824 return SkPixel32ToPixel16(src); 1825} 1826 1827static uint16_t dstover_modeproc16_0(SkPMColor src, uint16_t dst) { 1828 SkASSERT(require_0(src)); 1829 return dst; 1830} 1831 1832static uint16_t dstover_modeproc16_255(SkPMColor src, uint16_t dst) { 1833 SkASSERT(require_255(src)); 1834 return dst; 1835} 1836 1837static uint16_t srcin_modeproc16_255(SkPMColor src, uint16_t dst) { 1838 SkASSERT(require_255(src)); 1839 return SkPixel32ToPixel16(src); 1840} 1841 1842static uint16_t dstin_modeproc16_255(SkPMColor src, uint16_t dst) { 1843 SkASSERT(require_255(src)); 1844 return dst; 1845} 1846 1847static uint16_t dstout_modeproc16_0(SkPMColor src, uint16_t dst) { 1848 SkASSERT(require_0(src)); 1849 return dst; 1850} 1851 1852static uint16_t srcatop_modeproc16(SkPMColor src, uint16_t dst) { 1853 unsigned isa = 255 - SkGetPackedA32(src); 1854 1855 return SkPackRGB16( 1856 SkPacked32ToR16(src) + SkAlphaMulAlpha(SkGetPackedR16(dst), isa), 1857 SkPacked32ToG16(src) + SkAlphaMulAlpha(SkGetPackedG16(dst), isa), 1858 SkPacked32ToB16(src) + SkAlphaMulAlpha(SkGetPackedB16(dst), isa)); 1859} 1860 1861static uint16_t srcatop_modeproc16_0(SkPMColor src, uint16_t dst) { 1862 SkASSERT(require_0(src)); 1863 return dst; 1864} 1865 1866static uint16_t srcatop_modeproc16_255(SkPMColor src, uint16_t dst) { 1867 SkASSERT(require_255(src)); 1868 return SkPixel32ToPixel16(src); 1869} 1870 1871static uint16_t dstatop_modeproc16_255(SkPMColor src, uint16_t dst) { 1872 SkASSERT(require_255(src)); 1873 return dst; 1874} 1875 1876/********* 1877 darken and lighten boil down to this. 1878 1879 darken = (1 - Sa) * Dc + min(Sc, Dc) 1880 lighten = (1 - Sa) * Dc + max(Sc, Dc) 1881 1882 if (Sa == 0) these become 1883 darken = Dc + min(0, Dc) = 0 1884 lighten = Dc + max(0, Dc) = Dc 1885 1886 if (Sa == 1) these become 1887 darken = min(Sc, Dc) 1888 lighten = max(Sc, Dc) 1889*/ 1890 1891static uint16_t darken_modeproc16_0(SkPMColor src, uint16_t dst) { 1892 SkASSERT(require_0(src)); 1893 return 0; 1894} 1895 1896static uint16_t darken_modeproc16_255(SkPMColor src, uint16_t dst) { 1897 SkASSERT(require_255(src)); 1898 unsigned r = SkFastMin32(SkPacked32ToR16(src), SkGetPackedR16(dst)); 1899 unsigned g = SkFastMin32(SkPacked32ToG16(src), SkGetPackedG16(dst)); 1900 unsigned b = SkFastMin32(SkPacked32ToB16(src), SkGetPackedB16(dst)); 1901 return SkPackRGB16(r, g, b); 1902} 1903 1904static uint16_t lighten_modeproc16_0(SkPMColor src, uint16_t dst) { 1905 SkASSERT(require_0(src)); 1906 return dst; 1907} 1908 1909static uint16_t lighten_modeproc16_255(SkPMColor src, uint16_t dst) { 1910 SkASSERT(require_255(src)); 1911 unsigned r = SkMax32(SkPacked32ToR16(src), SkGetPackedR16(dst)); 1912 unsigned g = SkMax32(SkPacked32ToG16(src), SkGetPackedG16(dst)); 1913 unsigned b = SkMax32(SkPacked32ToB16(src), SkGetPackedB16(dst)); 1914 return SkPackRGB16(r, g, b); 1915} 1916 1917struct Proc16Rec { 1918 SkXfermodeProc16 fProc16_0; 1919 SkXfermodeProc16 fProc16_255; 1920 SkXfermodeProc16 fProc16_General; 1921}; 1922 1923static const Proc16Rec gModeProcs16[] = { 1924 { NULL, NULL, NULL }, // CLEAR 1925 { NULL, src_modeproc16_255, NULL }, 1926 { dst_modeproc16, dst_modeproc16, dst_modeproc16 }, 1927 { srcover_modeproc16_0, srcover_modeproc16_255, NULL }, 1928 { dstover_modeproc16_0, dstover_modeproc16_255, NULL }, 1929 { NULL, srcin_modeproc16_255, NULL }, 1930 { NULL, dstin_modeproc16_255, NULL }, 1931 { NULL, NULL, NULL },// SRC_OUT 1932 { dstout_modeproc16_0, NULL, NULL }, 1933 { srcatop_modeproc16_0, srcatop_modeproc16_255, srcatop_modeproc16 }, 1934 { NULL, dstatop_modeproc16_255, NULL }, 1935 { NULL, NULL, NULL }, // XOR 1936 1937 { NULL, NULL, NULL }, // plus 1938 { NULL, NULL, NULL }, // modulate 1939 { NULL, NULL, NULL }, // screen 1940 { NULL, NULL, NULL }, // overlay 1941 { darken_modeproc16_0, darken_modeproc16_255, NULL }, // darken 1942 { lighten_modeproc16_0, lighten_modeproc16_255, NULL }, // lighten 1943 { NULL, NULL, NULL }, // colordodge 1944 { NULL, NULL, NULL }, // colorburn 1945 { NULL, NULL, NULL }, // hardlight 1946 { NULL, NULL, NULL }, // softlight 1947 { NULL, NULL, NULL }, // difference 1948 { NULL, NULL, NULL }, // exclusion 1949 { NULL, NULL, NULL }, // multiply 1950 { NULL, NULL, NULL }, // hue 1951 { NULL, NULL, NULL }, // saturation 1952 { NULL, NULL, NULL }, // color 1953 { NULL, NULL, NULL }, // luminosity 1954}; 1955 1956SkXfermodeProc16 SkXfermode::GetProc16(Mode mode, SkColor srcColor) { 1957 SkXfermodeProc16 proc16 = NULL; 1958 if ((unsigned)mode < kModeCount) { 1959 const Proc16Rec& rec = gModeProcs16[mode]; 1960 unsigned a = SkColorGetA(srcColor); 1961 1962 if (0 == a) { 1963 proc16 = rec.fProc16_0; 1964 } else if (255 == a) { 1965 proc16 = rec.fProc16_255; 1966 } else { 1967 proc16 = rec.fProc16_General; 1968 } 1969 } 1970 return proc16; 1971} 1972 1973SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkXfermode) 1974 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkProcCoeffXfermode) 1975 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkClearXfermode) 1976 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSrcXfermode) 1977 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDstInXfermode) 1978 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDstOutXfermode) 1979SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END 1980