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