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