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