SkXfermode.cpp revision 8da9bc751e1898d50dd84d7e5ca666b00e4ff624
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::kLastSeparableMode; 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 // These all perform src-over on the alpha channel. 1004 builder->fsCodeAppendf("\t\t%s.a = %s.a + (1.0 - %s.a) * %s.a;\n", 1005 outputColor, inputColor, inputColor, dstColor); 1006 1007 switch (drawEffect.castEffect<XferEffect>().mode()) { 1008 case SkXfermode::kOverlay_Mode: 1009 // Overlay is Hard-Light with the src and dst reversed 1010 HardLight(builder, outputColor, dstColor, inputColor); 1011 break; 1012 case SkXfermode::kDarken_Mode: 1013 builder->fsCodeAppendf("\t\t%s.rgb = min((1.0 - %s.a) * %s.rgb + %s.rgb, " 1014 "(1.0 - %s.a) * %s.rgb + %s.rgb);\n", 1015 outputColor, 1016 inputColor, dstColor, inputColor, 1017 dstColor, inputColor, dstColor); 1018 break; 1019 case SkXfermode::kLighten_Mode: 1020 builder->fsCodeAppendf("\t\t%s.rgb = max((1.0 - %s.a) * %s.rgb + %s.rgb, " 1021 "(1.0 - %s.a) * %s.rgb + %s.rgb);\n", 1022 outputColor, 1023 inputColor, dstColor, inputColor, 1024 dstColor, inputColor, dstColor); 1025 break; 1026 case SkXfermode::kColorDodge_Mode: 1027 ColorDodgeComponent(builder, outputColor, inputColor, dstColor, 'r'); 1028 ColorDodgeComponent(builder, outputColor, inputColor, dstColor, 'g'); 1029 ColorDodgeComponent(builder, outputColor, inputColor, dstColor, 'b'); 1030 break; 1031 case SkXfermode::kColorBurn_Mode: 1032 ColorBurnComponent(builder, outputColor, inputColor, dstColor, 'r'); 1033 ColorBurnComponent(builder, outputColor, inputColor, dstColor, 'g'); 1034 ColorBurnComponent(builder, outputColor, inputColor, dstColor, 'b'); 1035 break; 1036 case SkXfermode::kHardLight_Mode: 1037 HardLight(builder, outputColor, inputColor, dstColor); 1038 break; 1039 case SkXfermode::kSoftLight_Mode: 1040 builder->fsCodeAppendf("\t\tif (0.0 == %s.a) {\n", dstColor); 1041 builder->fsCodeAppendf("\t\t\t%s.rgba = %s;\n", outputColor, inputColor); 1042 builder->fsCodeAppendf("\t\t} else {\n"); 1043 SoftLightComponentPosDstAlpha(builder, outputColor, inputColor, dstColor, 'r'); 1044 SoftLightComponentPosDstAlpha(builder, outputColor, inputColor, dstColor, 'g'); 1045 SoftLightComponentPosDstAlpha(builder, outputColor, inputColor, dstColor, 'b'); 1046 builder->fsCodeAppendf("\t\t}\n"); 1047 break; 1048 case SkXfermode::kDifference_Mode: 1049 builder->fsCodeAppendf("\t\t%s.rgb = %s.rgb + %s.rgb -" 1050 "2.0 * min(%s.rgb * %s.a, %s.rgb * %s.a);\n", 1051 outputColor, inputColor, dstColor, inputColor, dstColor, 1052 dstColor, inputColor); 1053 break; 1054 case SkXfermode::kExclusion_Mode: 1055 builder->fsCodeAppendf("\t\t%s.rgb = %s.rgb + %s.rgb - " 1056 "2.0 * %s.rgb * %s.rgb;\n", 1057 outputColor, dstColor, inputColor, dstColor, inputColor); 1058 break; 1059 case SkXfermode::kMultiply_Mode: 1060 builder->fsCodeAppendf("\t\t%s.rgb = (1.0 - %s.a) * %s.rgb + " 1061 "(1.0 - %s.a) * %s.rgb + " 1062 "%s.rgb * %s.rgb;\n", 1063 outputColor, inputColor, dstColor, dstColor, inputColor, 1064 inputColor, dstColor); 1065 break; 1066 case SkXfermode::kHue_Mode: 1067 case SkXfermode::kSaturation_Mode: 1068 case SkXfermode::kColor_Mode: 1069 case SkXfermode::kLuminosity_Mode: 1070 GrCrash("Unimplemented XferEffect mode."); 1071 break; 1072 default: 1073 GrCrash("Unknown XferEffect mode."); 1074 break; 1075 } 1076 } 1077 1078 static inline EffectKey GenKey(const GrDrawEffect& drawEffect, const GrGLCaps&) { 1079 return drawEffect.castEffect<XferEffect>().mode(); 1080 } 1081 1082 virtual void setData(const GrGLUniformManager&, const GrDrawEffect&) SK_OVERRIDE {} 1083 1084 private: 1085 static void HardLight(GrGLShaderBuilder* builder, 1086 const char* final, 1087 const char* src, 1088 const char* dst) { 1089 builder->fsCodeAppendf("\t\t%s.a = 1.0 - (1.0 - %s.a) * (1.0 - %s.a);\n", 1090 final, dst, src); 1091 builder->fsCodeAppendf("\t\t%s.rgb = mix(2.0 * %s.rgb * %s.rgb, ", 1092 final, src, dst); 1093 builder->fsCodeAppendf("%s.aaa * %s.aaa - 2.0 * (%s.aaa - %s.rgb) * (%s.aaa - %s.rgb),", 1094 src, dst, dst, dst, src, src); 1095 builder->fsCodeAppendf("vec3(greaterThan(2.0 * %s.rgb, %s.aaa)));\n", 1096 src, src); 1097 builder->fsCodeAppendf("\t\t%s.rgb += %s.rgb * (1.0 - %s.a) + %s.rgb * (1.0 - %s.a);\n", 1098 final, src, dst, dst, src); 1099 } 1100 1101 // Does one component of color-dodge 1102 static void ColorDodgeComponent(GrGLShaderBuilder* builder, 1103 const char* final, 1104 const char* src, 1105 const char* dst, 1106 const char component) { 1107 builder->fsCodeAppendf("\t\tif (0.0 == %s.%c) {\n", dst, component); 1108 builder->fsCodeAppendf("\t\t\t%s.%c = %s.%c * (1 - %s.a);\n", 1109 final, component, src, component, dst); 1110 builder->fsCodeAppend("\t\t} else {\n"); 1111 builder->fsCodeAppendf("\t\t\tfloat d = %s.a - %s.%c;\n", src, src, component); 1112 builder->fsCodeAppend("\t\t\tif (0 == d) {\n"); 1113 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", 1114 final, component, src, dst, src, component, dst, dst, component, 1115 src); 1116 builder->fsCodeAppend("\t\t\t} else {\n"); 1117 builder->fsCodeAppendf("\t\t\t\td = min(%s.a, %s.%c * %s.a / d);\n", 1118 dst, dst, component, src); 1119 builder->fsCodeAppendf("\t\t\t\t%s.%c = d * %s.a + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);\n", 1120 final, component, src, src, component, dst, dst, component, src); 1121 builder->fsCodeAppend("\t\t\t}\n"); 1122 builder->fsCodeAppend("\t\t}\n"); 1123 } 1124 1125 // Does one component of color-burn 1126 static void ColorBurnComponent(GrGLShaderBuilder* builder, 1127 const char* final, 1128 const char* src, 1129 const char* dst, 1130 const char component) { 1131 builder->fsCodeAppendf("\t\tif (%s.a == %s.%c) {\n", dst, dst, component); 1132 builder->fsCodeAppendf("\t\t\t%s.%c = %s.a * %s.a + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);\n", 1133 final, component, src, dst, src, component, dst, dst, component, 1134 src); 1135 builder->fsCodeAppendf("\t\t} else if (0.0 == %s.%c) {\n", src, component); 1136 builder->fsCodeAppendf("\t\t\t%s.%c = %s.%c * (1.0 - %s.a);\n", 1137 final, component, dst, component, src); 1138 builder->fsCodeAppend("\t\t} else {\n"); 1139 builder->fsCodeAppendf("\t\t\tfloat d = max(0.0, %s.a - (%s.a - %s.%c) * %s.a / %s.%c);\n", 1140 dst, dst, dst, component, src, src, component); 1141 builder->fsCodeAppendf("\t\t\t%s.%c = %s.a * d + %s.%c * (1.0 - %s.a) + %s.%c * (1.0 - %s.a);\n", 1142 final, component, src, src, component, dst, dst, component, src); 1143 builder->fsCodeAppend("\t\t}\n"); 1144 } 1145 1146 // Does one component of soft-light. Caller should have already checked that dst alpha > 0. 1147 static void SoftLightComponentPosDstAlpha(GrGLShaderBuilder* builder, 1148 const char* final, 1149 const char* src, 1150 const char* dst, 1151 const char component) { 1152 // if (2S < Sa) 1153 builder->fsCodeAppendf("\t\t\tif (2.0 * %s.%c <= %s.a) {\n", src, component, src); 1154 // (D^2 (Sa-2 S))/Da+(1-Da) S+D (-Sa+2 S+1) 1155 builder->fsCodeAppendf("\t\t\t\t%s.%c = (%s.%c*%s.%c*(%s.a - 2*%s.%c)) / %s.a + (1 - %s.a) * %s.%c + %s.%c*(-%s.a + 2*%s.%c + 1);\n", 1156 final, component, dst, component, dst, component, src, src, 1157 component, dst, dst, src, component, dst, component, src, src, 1158 component); 1159 // else if (4D < Da) 1160 builder->fsCodeAppendf("\t\t\t} else if (4.0 * %s.%c <= %s.a) {\n", 1161 dst, component, dst); 1162 builder->fsCodeAppendf("\t\t\t\tfloat DSqd = %s.%c * %s.%c;\n", 1163 dst, component, dst, component); 1164 builder->fsCodeAppendf("\t\t\t\tfloat DCub = DSqd * %s.%c;\n", dst, component); 1165 builder->fsCodeAppendf("\t\t\t\tfloat DaSqd = %s.a * %s.a;\n", dst, dst); 1166 builder->fsCodeAppendf("\t\t\t\tfloat DaCub = DaSqd * %s.a;\n", dst); 1167 // (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 1168 builder->fsCodeAppendf("\t\t\t\t%s.%c = (-DaCub*%s.%c + DaSqd*(%s.%c - %s.%c * (3*%s.a - 6*%s.%c - 1)) + 12*%s.a*DSqd*(%s.a - 2*%s.%c) - 16*DCub * (%s.a - 2*%s.%c)) / DaSqd;\n", 1169 final, component, src, component, src, component, dst, component, 1170 src, src, component, dst, src, src, component, src, src, 1171 component); 1172 builder->fsCodeAppendf("\t\t\t} else {\n"); 1173 // -sqrt(Da * D) (Sa-2 S)-Da S+D (Sa-2 S+1)+S 1174 builder->fsCodeAppendf("\t\t\t\t%s.%c = -sqrt(%s.a*%s.%c)*(%s.a - 2*%s.%c) - %s.a*%s.%c + %s.%c*(%s.a - 2*%s.%c + 1) + %s.%c;\n", 1175 final, component, dst, dst, component, src, src, component, dst, 1176 src, component, dst, component, src, src, component, src, 1177 component); 1178 builder->fsCodeAppendf("\t\t\t}\n"); 1179 } 1180 1181 typedef GrGLEffect INHERITED; 1182 }; 1183 1184 GR_DECLARE_EFFECT_TEST; 1185 1186private: 1187 XferEffect(SkXfermode::Mode mode) : fMode(mode) { this->setWillReadDst(); } 1188 virtual bool onIsEqual(const GrEffect& other) const SK_OVERRIDE { return true; } 1189 1190 SkXfermode::Mode fMode; 1191 1192 typedef GrEffect INHERITED; 1193}; 1194 1195GR_DEFINE_EFFECT_TEST(XferEffect); 1196GrEffectRef* XferEffect::TestCreate(SkMWCRandom* rand, 1197 GrContext*, 1198 const GrDrawTargetCaps&, 1199 GrTexture*[]) { 1200 int mode = rand->nextRangeU(SkXfermode::kLastCoeffMode + 1, SkXfermode::kLastSeparableMode); 1201 static AutoEffectUnref gEffect(SkNEW_ARGS(XferEffect, (static_cast<SkXfermode::Mode>(mode)))); 1202 return CreateEffectRef(gEffect); 1203} 1204 1205#endif 1206 1207/////////////////////////////////////////////////////////////////////////////// 1208/////////////////////////////////////////////////////////////////////////////// 1209 1210class SkProcCoeffXfermode : public SkProcXfermode { 1211public: 1212 SkProcCoeffXfermode(const ProcCoeff& rec, Mode mode) 1213 : INHERITED(rec.fProc) { 1214 fMode = mode; 1215 // these may be valid, or may be CANNOT_USE_COEFF 1216 fSrcCoeff = rec.fSC; 1217 fDstCoeff = rec.fDC; 1218 } 1219 1220 virtual bool asMode(Mode* mode) const SK_OVERRIDE { 1221 if (mode) { 1222 *mode = fMode; 1223 } 1224 return true; 1225 } 1226 1227 virtual bool asCoeff(Coeff* sc, Coeff* dc) const SK_OVERRIDE { 1228 if (CANNOT_USE_COEFF == fSrcCoeff) { 1229 return false; 1230 } 1231 1232 if (sc) { 1233 *sc = fSrcCoeff; 1234 } 1235 if (dc) { 1236 *dc = fDstCoeff; 1237 } 1238 return true; 1239 } 1240 1241#if SK_SUPPORT_GPU 1242 virtual bool asNewEffectOrCoeff(GrContext*, 1243 GrEffectRef** effect, 1244 Coeff* src, 1245 Coeff* dst) const SK_OVERRIDE { 1246 if (this->asCoeff(src, dst)) { 1247 return true; 1248 } 1249 if (XferEffect::IsSupportedMode(fMode)) { 1250 if (NULL != effect) { 1251 *effect = XferEffect::Create(fMode); 1252 SkASSERT(NULL != *effect); 1253 } 1254 return true; 1255 } 1256 return false; 1257 } 1258#endif 1259 1260 SK_DEVELOPER_TO_STRING() 1261 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkProcCoeffXfermode) 1262 1263protected: 1264 SkProcCoeffXfermode(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) { 1265 fMode = (SkXfermode::Mode)buffer.read32(); 1266 1267 const ProcCoeff& rec = gProcCoeffs[fMode]; 1268 // these may be valid, or may be CANNOT_USE_COEFF 1269 fSrcCoeff = rec.fSC; 1270 fDstCoeff = rec.fDC; 1271 // now update our function-ptr in the super class 1272 this->INHERITED::setProc(rec.fProc); 1273 } 1274 1275 virtual void flatten(SkFlattenableWriteBuffer& buffer) const SK_OVERRIDE { 1276 this->INHERITED::flatten(buffer); 1277 buffer.write32(fMode); 1278 } 1279 1280private: 1281 Mode fMode; 1282 Coeff fSrcCoeff, fDstCoeff; 1283 1284 typedef SkProcXfermode INHERITED; 1285}; 1286 1287const char* SkXfermode::ModeName(Mode mode) { 1288 SkASSERT((unsigned) mode <= (unsigned)kLastMode); 1289 const char* gModeStrings[] = { 1290 "Clear", "Src", "Dst", "SrcOver", "DstOver", "SrcIn", "DstIn", 1291 "SrcOut", "DstOut", "SrcATop", "DstATop", "Xor", "Plus", 1292 "Modulate", "Screen", "Overlay", "Darken", "Lighten", "ColorDodge", 1293 "ColorBurn", "HardLight", "SoftLight", "Difference", "Exclusion", 1294 "Multiply", "Hue", "Saturation", "Color", "Luminosity" 1295 }; 1296 return gModeStrings[mode]; 1297 SK_COMPILE_ASSERT(SK_ARRAY_COUNT(gModeStrings) == kLastMode + 1, mode_count); 1298} 1299 1300#ifdef SK_DEVELOPER 1301void SkProcCoeffXfermode::toString(SkString* str) const { 1302 str->append("SkProcCoeffXfermode: "); 1303 1304 str->append("mode: "); 1305 str->append(ModeName(fMode)); 1306 1307 static const char* gCoeffStrings[kCoeffCount] = { 1308 "Zero", "One", "SC", "ISC", "DC", "IDC", "SA", "ISA", "DA", "IDA" 1309 }; 1310 1311 str->append(" src: "); 1312 if (CANNOT_USE_COEFF == fSrcCoeff) { 1313 str->append("can't use"); 1314 } else { 1315 str->append(gCoeffStrings[fSrcCoeff]); 1316 } 1317 1318 str->append(" dst: "); 1319 if (CANNOT_USE_COEFF == fDstCoeff) { 1320 str->append("can't use"); 1321 } else { 1322 str->append(gCoeffStrings[fDstCoeff]); 1323 } 1324} 1325#endif 1326 1327/////////////////////////////////////////////////////////////////////////////// 1328 1329class SkClearXfermode : public SkProcCoeffXfermode { 1330public: 1331 SkClearXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kClear_Mode) {} 1332 1333 virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE; 1334 virtual void xferA8(SkAlpha*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE; 1335 1336 SK_DEVELOPER_TO_STRING() 1337 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkClearXfermode) 1338 1339private: 1340 SkClearXfermode(SkFlattenableReadBuffer& buffer) 1341 : SkProcCoeffXfermode(buffer) {} 1342 1343 typedef SkProcCoeffXfermode INHERITED; 1344}; 1345 1346void SkClearXfermode::xfer32(SkPMColor* SK_RESTRICT dst, 1347 const SkPMColor* SK_RESTRICT, int count, 1348 const SkAlpha* SK_RESTRICT aa) const { 1349 SkASSERT(dst && count >= 0); 1350 1351 if (NULL == aa) { 1352 memset(dst, 0, count << 2); 1353 } else { 1354 for (int i = count - 1; i >= 0; --i) { 1355 unsigned a = aa[i]; 1356 if (0xFF == a) { 1357 dst[i] = 0; 1358 } else if (a != 0) { 1359 dst[i] = SkAlphaMulQ(dst[i], SkAlpha255To256(255 - a)); 1360 } 1361 } 1362 } 1363} 1364void SkClearXfermode::xferA8(SkAlpha* SK_RESTRICT dst, 1365 const SkPMColor* SK_RESTRICT, int count, 1366 const SkAlpha* SK_RESTRICT aa) const { 1367 SkASSERT(dst && count >= 0); 1368 1369 if (NULL == aa) { 1370 memset(dst, 0, count); 1371 } else { 1372 for (int i = count - 1; i >= 0; --i) { 1373 unsigned a = aa[i]; 1374 if (0xFF == a) { 1375 dst[i] = 0; 1376 } else if (0 != a) { 1377 dst[i] = SkAlphaMulAlpha(dst[i], 255 - a); 1378 } 1379 } 1380 } 1381} 1382 1383#ifdef SK_DEVELOPER 1384void SkClearXfermode::toString(SkString* str) const { 1385 this->INHERITED::toString(str); 1386} 1387#endif 1388 1389/////////////////////////////////////////////////////////////////////////////// 1390 1391class SkSrcXfermode : public SkProcCoeffXfermode { 1392public: 1393 SkSrcXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kSrc_Mode) {} 1394 1395 virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE; 1396 virtual void xferA8(SkAlpha*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE; 1397 1398 SK_DEVELOPER_TO_STRING() 1399 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkSrcXfermode) 1400 1401private: 1402 SkSrcXfermode(SkFlattenableReadBuffer& buffer) 1403 : SkProcCoeffXfermode(buffer) {} 1404 1405 typedef SkProcCoeffXfermode INHERITED; 1406}; 1407 1408void SkSrcXfermode::xfer32(SkPMColor* SK_RESTRICT dst, 1409 const SkPMColor* SK_RESTRICT src, int count, 1410 const SkAlpha* SK_RESTRICT aa) const { 1411 SkASSERT(dst && src && count >= 0); 1412 1413 if (NULL == aa) { 1414 memcpy(dst, src, count << 2); 1415 } else { 1416 for (int i = count - 1; i >= 0; --i) { 1417 unsigned a = aa[i]; 1418 if (a == 0xFF) { 1419 dst[i] = src[i]; 1420 } else if (a != 0) { 1421 dst[i] = SkFourByteInterp(src[i], dst[i], a); 1422 } 1423 } 1424 } 1425} 1426 1427void SkSrcXfermode::xferA8(SkAlpha* SK_RESTRICT dst, 1428 const SkPMColor* SK_RESTRICT src, int count, 1429 const SkAlpha* SK_RESTRICT aa) const { 1430 SkASSERT(dst && src && count >= 0); 1431 1432 if (NULL == aa) { 1433 for (int i = count - 1; i >= 0; --i) { 1434 dst[i] = SkToU8(SkGetPackedA32(src[i])); 1435 } 1436 } else { 1437 for (int i = count - 1; i >= 0; --i) { 1438 unsigned a = aa[i]; 1439 if (0 != a) { 1440 unsigned srcA = SkGetPackedA32(src[i]); 1441 if (a == 0xFF) { 1442 dst[i] = SkToU8(srcA); 1443 } else { 1444 dst[i] = SkToU8(SkAlphaBlend(srcA, dst[i], a)); 1445 } 1446 } 1447 } 1448 } 1449} 1450#ifdef SK_DEVELOPER 1451void SkSrcXfermode::toString(SkString* str) const { 1452 this->INHERITED::toString(str); 1453} 1454#endif 1455 1456/////////////////////////////////////////////////////////////////////////////// 1457 1458class SkDstInXfermode : public SkProcCoeffXfermode { 1459public: 1460 SkDstInXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstIn_Mode) {} 1461 1462 virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE; 1463 1464 SK_DEVELOPER_TO_STRING() 1465 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDstInXfermode) 1466 1467private: 1468 SkDstInXfermode(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {} 1469 1470 typedef SkProcCoeffXfermode INHERITED; 1471}; 1472 1473void SkDstInXfermode::xfer32(SkPMColor* SK_RESTRICT dst, 1474 const SkPMColor* SK_RESTRICT src, int count, 1475 const SkAlpha* SK_RESTRICT aa) const { 1476 SkASSERT(dst && src); 1477 1478 if (count <= 0) { 1479 return; 1480 } 1481 if (NULL != aa) { 1482 return this->INHERITED::xfer32(dst, src, count, aa); 1483 } 1484 1485 do { 1486 unsigned a = SkGetPackedA32(*src); 1487 *dst = SkAlphaMulQ(*dst, SkAlpha255To256(a)); 1488 dst++; 1489 src++; 1490 } while (--count != 0); 1491} 1492 1493#ifdef SK_DEVELOPER 1494void SkDstInXfermode::toString(SkString* str) const { 1495 this->INHERITED::toString(str); 1496} 1497#endif 1498 1499/////////////////////////////////////////////////////////////////////////////// 1500 1501class SkDstOutXfermode : public SkProcCoeffXfermode { 1502public: 1503 SkDstOutXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstOut_Mode) {} 1504 1505 virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) const SK_OVERRIDE; 1506 1507 SK_DEVELOPER_TO_STRING() 1508 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDstOutXfermode) 1509 1510private: 1511 SkDstOutXfermode(SkFlattenableReadBuffer& buffer) 1512 : INHERITED(buffer) {} 1513 1514 typedef SkProcCoeffXfermode INHERITED; 1515}; 1516 1517void SkDstOutXfermode::xfer32(SkPMColor* SK_RESTRICT dst, 1518 const SkPMColor* SK_RESTRICT src, int count, 1519 const SkAlpha* SK_RESTRICT aa) const { 1520 SkASSERT(dst && src); 1521 1522 if (count <= 0) { 1523 return; 1524 } 1525 if (NULL != aa) { 1526 return this->INHERITED::xfer32(dst, src, count, aa); 1527 } 1528 1529 do { 1530 unsigned a = SkGetPackedA32(*src); 1531 *dst = SkAlphaMulQ(*dst, SkAlpha255To256(255 - a)); 1532 dst++; 1533 src++; 1534 } while (--count != 0); 1535} 1536 1537#ifdef SK_DEVELOPER 1538void SkDstOutXfermode::toString(SkString* str) const { 1539 this->INHERITED::toString(str); 1540} 1541#endif 1542 1543/////////////////////////////////////////////////////////////////////////////// 1544 1545SkXfermode* SkXfermode::Create(Mode mode) { 1546 SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount); 1547 SkASSERT((unsigned)mode < kModeCount); 1548 1549 const ProcCoeff& rec = gProcCoeffs[mode]; 1550 1551 switch (mode) { 1552 case kClear_Mode: 1553 return SkNEW_ARGS(SkClearXfermode, (rec)); 1554 case kSrc_Mode: 1555 return SkNEW_ARGS(SkSrcXfermode, (rec)); 1556 case kSrcOver_Mode: 1557 return NULL; 1558 case kDstIn_Mode: 1559 return SkNEW_ARGS(SkDstInXfermode, (rec)); 1560 case kDstOut_Mode: 1561 return SkNEW_ARGS(SkDstOutXfermode, (rec)); 1562 default: 1563 return SkNEW_ARGS(SkProcCoeffXfermode, (rec, mode)); 1564 } 1565} 1566 1567SkXfermodeProc SkXfermode::GetProc(Mode mode) { 1568 SkXfermodeProc proc = NULL; 1569 if ((unsigned)mode < kModeCount) { 1570 proc = gProcCoeffs[mode].fProc; 1571 } 1572 return proc; 1573} 1574 1575bool SkXfermode::ModeAsCoeff(Mode mode, Coeff* src, Coeff* dst) { 1576 SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount); 1577 1578 if ((unsigned)mode >= (unsigned)kModeCount) { 1579 // illegal mode parameter 1580 return false; 1581 } 1582 1583 const ProcCoeff& rec = gProcCoeffs[mode]; 1584 1585 if (CANNOT_USE_COEFF == rec.fSC) { 1586 return false; 1587 } 1588 1589 SkASSERT(CANNOT_USE_COEFF != rec.fDC); 1590 if (src) { 1591 *src = rec.fSC; 1592 } 1593 if (dst) { 1594 *dst = rec.fDC; 1595 } 1596 return true; 1597} 1598 1599bool SkXfermode::AsMode(const SkXfermode* xfer, Mode* mode) { 1600 if (NULL == xfer) { 1601 if (mode) { 1602 *mode = kSrcOver_Mode; 1603 } 1604 return true; 1605 } 1606 return xfer->asMode(mode); 1607} 1608 1609bool SkXfermode::AsCoeff(const SkXfermode* xfer, Coeff* src, Coeff* dst) { 1610 if (NULL == xfer) { 1611 return ModeAsCoeff(kSrcOver_Mode, src, dst); 1612 } 1613 return xfer->asCoeff(src, dst); 1614} 1615 1616bool SkXfermode::IsMode(const SkXfermode* xfer, Mode mode) { 1617 // if xfer==null then the mode is srcover 1618 Mode m = kSrcOver_Mode; 1619 if (xfer && !xfer->asMode(&m)) { 1620 return false; 1621 } 1622 return mode == m; 1623} 1624 1625/////////////////////////////////////////////////////////////////////////////// 1626//////////// 16bit xfermode procs 1627 1628#ifdef SK_DEBUG 1629static bool require_255(SkPMColor src) { return SkGetPackedA32(src) == 0xFF; } 1630static bool require_0(SkPMColor src) { return SkGetPackedA32(src) == 0; } 1631#endif 1632 1633static uint16_t src_modeproc16_255(SkPMColor src, uint16_t dst) { 1634 SkASSERT(require_255(src)); 1635 return SkPixel32ToPixel16(src); 1636} 1637 1638static uint16_t dst_modeproc16(SkPMColor src, uint16_t dst) { 1639 return dst; 1640} 1641 1642static uint16_t srcover_modeproc16_0(SkPMColor src, uint16_t dst) { 1643 SkASSERT(require_0(src)); 1644 return dst; 1645} 1646 1647static uint16_t srcover_modeproc16_255(SkPMColor src, uint16_t dst) { 1648 SkASSERT(require_255(src)); 1649 return SkPixel32ToPixel16(src); 1650} 1651 1652static uint16_t dstover_modeproc16_0(SkPMColor src, uint16_t dst) { 1653 SkASSERT(require_0(src)); 1654 return dst; 1655} 1656 1657static uint16_t dstover_modeproc16_255(SkPMColor src, uint16_t dst) { 1658 SkASSERT(require_255(src)); 1659 return dst; 1660} 1661 1662static uint16_t srcin_modeproc16_255(SkPMColor src, uint16_t dst) { 1663 SkASSERT(require_255(src)); 1664 return SkPixel32ToPixel16(src); 1665} 1666 1667static uint16_t dstin_modeproc16_255(SkPMColor src, uint16_t dst) { 1668 SkASSERT(require_255(src)); 1669 return dst; 1670} 1671 1672static uint16_t dstout_modeproc16_0(SkPMColor src, uint16_t dst) { 1673 SkASSERT(require_0(src)); 1674 return dst; 1675} 1676 1677static uint16_t srcatop_modeproc16(SkPMColor src, uint16_t dst) { 1678 unsigned isa = 255 - SkGetPackedA32(src); 1679 1680 return SkPackRGB16( 1681 SkPacked32ToR16(src) + SkAlphaMulAlpha(SkGetPackedR16(dst), isa), 1682 SkPacked32ToG16(src) + SkAlphaMulAlpha(SkGetPackedG16(dst), isa), 1683 SkPacked32ToB16(src) + SkAlphaMulAlpha(SkGetPackedB16(dst), isa)); 1684} 1685 1686static uint16_t srcatop_modeproc16_0(SkPMColor src, uint16_t dst) { 1687 SkASSERT(require_0(src)); 1688 return dst; 1689} 1690 1691static uint16_t srcatop_modeproc16_255(SkPMColor src, uint16_t dst) { 1692 SkASSERT(require_255(src)); 1693 return SkPixel32ToPixel16(src); 1694} 1695 1696static uint16_t dstatop_modeproc16_255(SkPMColor src, uint16_t dst) { 1697 SkASSERT(require_255(src)); 1698 return dst; 1699} 1700 1701/********* 1702 darken and lighten boil down to this. 1703 1704 darken = (1 - Sa) * Dc + min(Sc, Dc) 1705 lighten = (1 - Sa) * Dc + max(Sc, Dc) 1706 1707 if (Sa == 0) these become 1708 darken = Dc + min(0, Dc) = 0 1709 lighten = Dc + max(0, Dc) = Dc 1710 1711 if (Sa == 1) these become 1712 darken = min(Sc, Dc) 1713 lighten = max(Sc, Dc) 1714*/ 1715 1716static uint16_t darken_modeproc16_0(SkPMColor src, uint16_t dst) { 1717 SkASSERT(require_0(src)); 1718 return 0; 1719} 1720 1721static uint16_t darken_modeproc16_255(SkPMColor src, uint16_t dst) { 1722 SkASSERT(require_255(src)); 1723 unsigned r = SkFastMin32(SkPacked32ToR16(src), SkGetPackedR16(dst)); 1724 unsigned g = SkFastMin32(SkPacked32ToG16(src), SkGetPackedG16(dst)); 1725 unsigned b = SkFastMin32(SkPacked32ToB16(src), SkGetPackedB16(dst)); 1726 return SkPackRGB16(r, g, b); 1727} 1728 1729static uint16_t lighten_modeproc16_0(SkPMColor src, uint16_t dst) { 1730 SkASSERT(require_0(src)); 1731 return dst; 1732} 1733 1734static uint16_t lighten_modeproc16_255(SkPMColor src, uint16_t dst) { 1735 SkASSERT(require_255(src)); 1736 unsigned r = SkMax32(SkPacked32ToR16(src), SkGetPackedR16(dst)); 1737 unsigned g = SkMax32(SkPacked32ToG16(src), SkGetPackedG16(dst)); 1738 unsigned b = SkMax32(SkPacked32ToB16(src), SkGetPackedB16(dst)); 1739 return SkPackRGB16(r, g, b); 1740} 1741 1742struct Proc16Rec { 1743 SkXfermodeProc16 fProc16_0; 1744 SkXfermodeProc16 fProc16_255; 1745 SkXfermodeProc16 fProc16_General; 1746}; 1747 1748static const Proc16Rec gModeProcs16[] = { 1749 { NULL, NULL, NULL }, // CLEAR 1750 { NULL, src_modeproc16_255, NULL }, 1751 { dst_modeproc16, dst_modeproc16, dst_modeproc16 }, 1752 { srcover_modeproc16_0, srcover_modeproc16_255, NULL }, 1753 { dstover_modeproc16_0, dstover_modeproc16_255, NULL }, 1754 { NULL, srcin_modeproc16_255, NULL }, 1755 { NULL, dstin_modeproc16_255, NULL }, 1756 { NULL, NULL, NULL },// SRC_OUT 1757 { dstout_modeproc16_0, NULL, NULL }, 1758 { srcatop_modeproc16_0, srcatop_modeproc16_255, srcatop_modeproc16 }, 1759 { NULL, dstatop_modeproc16_255, NULL }, 1760 { NULL, NULL, NULL }, // XOR 1761 1762 { NULL, NULL, NULL }, // plus 1763 { NULL, NULL, NULL }, // modulate 1764 { NULL, NULL, NULL }, // screen 1765 { NULL, NULL, NULL }, // overlay 1766 { darken_modeproc16_0, darken_modeproc16_255, NULL }, // darken 1767 { lighten_modeproc16_0, lighten_modeproc16_255, NULL }, // lighten 1768 { NULL, NULL, NULL }, // colordodge 1769 { NULL, NULL, NULL }, // colorburn 1770 { NULL, NULL, NULL }, // hardlight 1771 { NULL, NULL, NULL }, // softlight 1772 { NULL, NULL, NULL }, // difference 1773 { NULL, NULL, NULL }, // exclusion 1774 { NULL, NULL, NULL }, // multiply 1775 { NULL, NULL, NULL }, // hue 1776 { NULL, NULL, NULL }, // saturation 1777 { NULL, NULL, NULL }, // color 1778 { NULL, NULL, NULL }, // luminosity 1779}; 1780 1781SkXfermodeProc16 SkXfermode::GetProc16(Mode mode, SkColor srcColor) { 1782 SkXfermodeProc16 proc16 = NULL; 1783 if ((unsigned)mode < kModeCount) { 1784 const Proc16Rec& rec = gModeProcs16[mode]; 1785 unsigned a = SkColorGetA(srcColor); 1786 1787 if (0 == a) { 1788 proc16 = rec.fProc16_0; 1789 } else if (255 == a) { 1790 proc16 = rec.fProc16_255; 1791 } else { 1792 proc16 = rec.fProc16_General; 1793 } 1794 } 1795 return proc16; 1796} 1797 1798SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkXfermode) 1799 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkProcCoeffXfermode) 1800 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkClearXfermode) 1801 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSrcXfermode) 1802 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDstInXfermode) 1803 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDstOutXfermode) 1804SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END 1805