SkXfermode.cpp revision ba28d03e94dc221d6a803bf2a84a420b9159255c
1 2/* 3 * Copyright 2006 The Android Open Source Project 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9 10#include "SkXfermode.h" 11#include "SkColorPriv.h" 12 13#define SkAlphaMulAlpha(a, b) SkMulDiv255Round(a, b) 14 15#if 0 16// idea for higher precision blends in xfer procs (and slightly faster) 17// see DstATop as a probable caller 18static U8CPU mulmuldiv255round(U8CPU a, U8CPU b, U8CPU c, U8CPU d) { 19 SkASSERT(a <= 255); 20 SkASSERT(b <= 255); 21 SkASSERT(c <= 255); 22 SkASSERT(d <= 255); 23 unsigned prod = SkMulS16(a, b) + SkMulS16(c, d) + 128; 24 unsigned result = (prod + (prod >> 8)) >> 8; 25 SkASSERT(result <= 255); 26 return result; 27} 28#endif 29 30static inline unsigned saturated_add(unsigned a, unsigned b) { 31 SkASSERT(a <= 255); 32 SkASSERT(b <= 255); 33 unsigned sum = a + b; 34 if (sum > 255) { 35 sum = 255; 36 } 37 return sum; 38} 39 40static inline int clamp_signed_byte(int n) { 41 if (n < 0) { 42 n = 0; 43 } else if (n > 255) { 44 n = 255; 45 } 46 return n; 47} 48 49static inline int clamp_div255round(int prod) { 50 if (prod <= 0) { 51 return 0; 52 } else if (prod >= 255*255) { 53 return 255; 54 } else { 55 return SkDiv255Round(prod); 56 } 57} 58 59static inline int clamp_max(int value, int max) { 60 if (value > max) { 61 value = max; 62 } 63 return value; 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// kMultiply_Mode 181static SkPMColor multiply_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 189// kScreen_Mode 190static inline int srcover_byte(int a, int b) { 191 return a + b - SkAlphaMulAlpha(a, b); 192} 193static SkPMColor screen_modeproc(SkPMColor src, SkPMColor dst) { 194 int a = srcover_byte(SkGetPackedA32(src), SkGetPackedA32(dst)); 195 int r = srcover_byte(SkGetPackedR32(src), SkGetPackedR32(dst)); 196 int g = srcover_byte(SkGetPackedG32(src), SkGetPackedG32(dst)); 197 int b = srcover_byte(SkGetPackedB32(src), SkGetPackedB32(dst)); 198 return SkPackARGB32(a, r, g, b); 199} 200 201// kOverlay_Mode 202static inline int overlay_byte(int sc, int dc, int sa, int da) { 203 int tmp = sc * (255 - da) + dc * (255 - sa); 204 int rc; 205 if (2 * dc <= da) { 206 rc = 2 * sc * dc; 207 } else { 208 rc = sa * da - 2 * (da - dc) * (sa - sc); 209 } 210 return clamp_div255round(rc + tmp); 211} 212static SkPMColor overlay_modeproc(SkPMColor src, SkPMColor dst) { 213 int sa = SkGetPackedA32(src); 214 int da = SkGetPackedA32(dst); 215 int a = srcover_byte(sa, da); 216 int r = overlay_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da); 217 int g = overlay_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da); 218 int b = overlay_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da); 219 return SkPackARGB32(a, r, g, b); 220} 221 222// kDarken_Mode 223static inline int darken_byte(int sc, int dc, int sa, int da) { 224 int sd = sc * da; 225 int ds = dc * sa; 226 if (sd < ds) { 227 // srcover 228 return sc + dc - SkDiv255Round(ds); 229 } else { 230 // dstover 231 return dc + sc - SkDiv255Round(sd); 232 } 233} 234static SkPMColor darken_modeproc(SkPMColor src, SkPMColor dst) { 235 int sa = SkGetPackedA32(src); 236 int da = SkGetPackedA32(dst); 237 int a = srcover_byte(sa, da); 238 int r = darken_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da); 239 int g = darken_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da); 240 int b = darken_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da); 241 return SkPackARGB32(a, r, g, b); 242} 243 244// kLighten_Mode 245static inline int lighten_byte(int sc, int dc, int sa, int da) { 246 int sd = sc * da; 247 int ds = dc * sa; 248 if (sd > ds) { 249 // srcover 250 return sc + dc - SkDiv255Round(ds); 251 } else { 252 // dstover 253 return dc + sc - SkDiv255Round(sd); 254 } 255} 256static SkPMColor lighten_modeproc(SkPMColor src, SkPMColor dst) { 257 int sa = SkGetPackedA32(src); 258 int da = SkGetPackedA32(dst); 259 int a = srcover_byte(sa, da); 260 int r = lighten_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da); 261 int g = lighten_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da); 262 int b = lighten_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da); 263 return SkPackARGB32(a, r, g, b); 264} 265 266// kColorDodge_Mode 267static inline int colordodge_byte(int sc, int dc, int sa, int da) { 268 int diff = sa - sc; 269 int rc; 270 if (0 == diff) { 271 rc = sa * da + sc * (255 - da) + dc * (255 - sa); 272 rc = SkDiv255Round(rc); 273 } else { 274 int tmp = (dc * sa << 15) / (da * diff); 275 rc = SkDiv255Round(sa * da) * tmp >> 15; 276 // don't clamp here, since we'll do it in our modeproc 277 } 278 return rc; 279} 280static SkPMColor colordodge_modeproc(SkPMColor src, SkPMColor dst) { 281 // added to avoid div-by-zero in colordodge_byte 282 if (0 == dst) { 283 return src; 284 } 285 286 int sa = SkGetPackedA32(src); 287 int da = SkGetPackedA32(dst); 288 int a = srcover_byte(sa, da); 289 int r = colordodge_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da); 290 int g = colordodge_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da); 291 int b = colordodge_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da); 292 r = clamp_max(r, a); 293 g = clamp_max(g, a); 294 b = clamp_max(b, a); 295 return SkPackARGB32(a, r, g, b); 296} 297 298// kColorBurn_Mode 299static inline int colorburn_byte(int sc, int dc, int sa, int da) { 300 int rc; 301 if (dc == da && 0 == sc) { 302 rc = sa * da + dc * (255 - sa); 303 } else if (0 == sc) { 304 return SkAlphaMulAlpha(dc, 255 - sa); 305 } else { 306 int tmp = (sa * (da - dc) * 256) / (sc * da); 307 if (tmp > 256) { 308 tmp = 256; 309 } 310 int tmp2 = sa * da; 311 rc = tmp2 - (tmp2 * tmp >> 8) + sc * (255 - da) + dc * (255 - sa); 312 } 313 return SkDiv255Round(rc); 314} 315static SkPMColor colorburn_modeproc(SkPMColor src, SkPMColor dst) { 316 // added to avoid div-by-zero in colorburn_byte 317 if (0 == dst) { 318 return src; 319 } 320 321 int sa = SkGetPackedA32(src); 322 int da = SkGetPackedA32(dst); 323 int a = srcover_byte(sa, da); 324 int r = colorburn_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da); 325 int g = colorburn_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da); 326 int b = colorburn_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da); 327 return SkPackARGB32(a, r, g, b); 328} 329 330// kHardLight_Mode 331static inline int hardlight_byte(int sc, int dc, int sa, int da) { 332 int rc; 333 if (2 * sc <= sa) { 334 rc = 2 * sc * dc; 335 } else { 336 rc = sa * da - 2 * (da - dc) * (sa - sc); 337 } 338 return clamp_div255round(rc + sc * (255 - da) + dc * (255 - sa)); 339} 340static SkPMColor hardlight_modeproc(SkPMColor src, SkPMColor dst) { 341 int sa = SkGetPackedA32(src); 342 int da = SkGetPackedA32(dst); 343 int a = srcover_byte(sa, da); 344 int r = hardlight_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da); 345 int g = hardlight_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da); 346 int b = hardlight_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da); 347 return SkPackARGB32(a, r, g, b); 348} 349 350// returns 255 * sqrt(n/255) 351static U8CPU sqrt_unit_byte(U8CPU n) { 352 return SkSqrtBits(n, 15+4); 353} 354 355// kSoftLight_Mode 356static inline int softlight_byte(int sc, int dc, int sa, int da) { 357 int m = da ? dc * 256 / da : 0; 358 int rc; 359 if (2 * sc <= sa) { 360 rc = dc * (sa + ((2 * sc - sa) * (256 - m) >> 8)); 361 } else if (4 * dc <= da) { 362 int tmp = (4 * m * (4 * m + 256) * (m - 256) >> 16) + 7 * m; 363 rc = dc * sa + (da * (2 * sc - sa) * tmp >> 8); 364 } else { 365 int tmp = sqrt_unit_byte(m) - m; 366 rc = dc * sa + (da * (2 * sc - sa) * tmp >> 8); 367 } 368 return clamp_div255round(rc + sc * (255 - da) + dc * (255 - sa)); 369} 370static SkPMColor softlight_modeproc(SkPMColor src, SkPMColor dst) { 371 int sa = SkGetPackedA32(src); 372 int da = SkGetPackedA32(dst); 373 int a = srcover_byte(sa, da); 374 int r = softlight_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da); 375 int g = softlight_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da); 376 int b = softlight_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da); 377 return SkPackARGB32(a, r, g, b); 378} 379 380// kDifference_Mode 381static inline int difference_byte(int sc, int dc, int sa, int da) { 382 int tmp = SkMin32(sc * da, dc * sa); 383 return clamp_signed_byte(sc + dc - 2 * SkDiv255Round(tmp)); 384} 385static SkPMColor difference_modeproc(SkPMColor src, SkPMColor dst) { 386 int sa = SkGetPackedA32(src); 387 int da = SkGetPackedA32(dst); 388 int a = srcover_byte(sa, da); 389 int r = difference_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da); 390 int g = difference_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da); 391 int b = difference_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da); 392 return SkPackARGB32(a, r, g, b); 393} 394 395// kExclusion_Mode 396static inline int exclusion_byte(int sc, int dc, int sa, int da) { 397 // this equations is wacky, wait for SVG to confirm it 398 int r = sc * da + dc * sa - 2 * sc * dc + sc * (255 - da) + dc * (255 - sa); 399 return clamp_div255round(r); 400} 401static SkPMColor exclusion_modeproc(SkPMColor src, SkPMColor dst) { 402 int sa = SkGetPackedA32(src); 403 int da = SkGetPackedA32(dst); 404 int a = srcover_byte(sa, da); 405 int r = exclusion_byte(SkGetPackedR32(src), SkGetPackedR32(dst), sa, da); 406 int g = exclusion_byte(SkGetPackedG32(src), SkGetPackedG32(dst), sa, da); 407 int b = exclusion_byte(SkGetPackedB32(src), SkGetPackedB32(dst), sa, da); 408 return SkPackARGB32(a, r, g, b); 409} 410 411struct ProcCoeff { 412 SkXfermodeProc fProc; 413 SkXfermode::Coeff fSC; 414 SkXfermode::Coeff fDC; 415}; 416 417#define CANNOT_USE_COEFF SkXfermode::Coeff(-1) 418 419static const ProcCoeff gProcCoeffs[] = { 420 { clear_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kZero_Coeff }, 421 { src_modeproc, SkXfermode::kOne_Coeff, SkXfermode::kZero_Coeff }, 422 { dst_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kOne_Coeff }, 423 { srcover_modeproc, SkXfermode::kOne_Coeff, SkXfermode::kISA_Coeff }, 424 { dstover_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kOne_Coeff }, 425 { srcin_modeproc, SkXfermode::kDA_Coeff, SkXfermode::kZero_Coeff }, 426 { dstin_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kSA_Coeff }, 427 { srcout_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kZero_Coeff }, 428 { dstout_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kISA_Coeff }, 429 { srcatop_modeproc, SkXfermode::kDA_Coeff, SkXfermode::kISA_Coeff }, 430 { dstatop_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kSA_Coeff }, 431 { xor_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kISA_Coeff }, 432 433 { plus_modeproc, SkXfermode::kOne_Coeff, SkXfermode::kOne_Coeff }, 434 { multiply_modeproc,SkXfermode::kZero_Coeff, SkXfermode::kSC_Coeff }, 435 { screen_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, 436 { overlay_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, 437 { darken_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, 438 { lighten_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, 439 { colordodge_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, 440 { colorburn_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, 441 { hardlight_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, 442 { softlight_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, 443 { difference_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, 444 { exclusion_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, 445}; 446 447/////////////////////////////////////////////////////////////////////////////// 448 449bool SkXfermode::asCoeff(Coeff* src, Coeff* dst) { 450 return false; 451} 452 453bool SkXfermode::asMode(Mode* mode) { 454 return false; 455} 456 457SkPMColor SkXfermode::xferColor(SkPMColor src, SkPMColor dst) { 458 // no-op. subclasses should override this 459 return dst; 460} 461 462void SkXfermode::xfer32(SkPMColor* SK_RESTRICT dst, 463 const SkPMColor* SK_RESTRICT src, int count, 464 const SkAlpha* SK_RESTRICT aa) { 465 SkASSERT(dst && src && count >= 0); 466 467 if (NULL == aa) { 468 for (int i = count - 1; i >= 0; --i) { 469 dst[i] = this->xferColor(src[i], dst[i]); 470 } 471 } else { 472 for (int i = count - 1; i >= 0; --i) { 473 unsigned a = aa[i]; 474 if (0 != a) { 475 SkPMColor dstC = dst[i]; 476 SkPMColor C = this->xferColor(src[i], dstC); 477 if (0xFF != a) { 478 C = SkFourByteInterp(C, dstC, a); 479 } 480 dst[i] = C; 481 } 482 } 483 } 484} 485 486void SkXfermode::xfer16(uint16_t* dst, 487 const SkPMColor* SK_RESTRICT src, int count, 488 const SkAlpha* SK_RESTRICT aa) { 489 SkASSERT(dst && src && count >= 0); 490 491 if (NULL == aa) { 492 for (int i = count - 1; i >= 0; --i) { 493 SkPMColor dstC = SkPixel16ToPixel32(dst[i]); 494 dst[i] = SkPixel32ToPixel16_ToU16(this->xferColor(src[i], dstC)); 495 } 496 } else { 497 for (int i = count - 1; i >= 0; --i) { 498 unsigned a = aa[i]; 499 if (0 != a) { 500 SkPMColor dstC = SkPixel16ToPixel32(dst[i]); 501 SkPMColor C = this->xferColor(src[i], dstC); 502 if (0xFF != a) { 503 C = SkFourByteInterp(C, dstC, a); 504 } 505 dst[i] = SkPixel32ToPixel16_ToU16(C); 506 } 507 } 508 } 509} 510 511void SkXfermode::xfer4444(SkPMColor16* SK_RESTRICT dst, 512 const SkPMColor* SK_RESTRICT src, int count, 513 const SkAlpha* SK_RESTRICT aa) 514{ 515 SkASSERT(dst && src && count >= 0); 516 517 if (NULL == aa) { 518 for (int i = count - 1; i >= 0; --i) { 519 SkPMColor dstC = SkPixel4444ToPixel32(dst[i]); 520 dst[i] = SkPixel32ToPixel4444(this->xferColor(src[i], dstC)); 521 } 522 } else { 523 for (int i = count - 1; i >= 0; --i) { 524 unsigned a = aa[i]; 525 if (0 != a) { 526 SkPMColor dstC = SkPixel4444ToPixel32(dst[i]); 527 SkPMColor C = this->xferColor(src[i], dstC); 528 if (0xFF != a) { 529 C = SkFourByteInterp(C, dstC, a); 530 } 531 dst[i] = SkPixel32ToPixel4444(C); 532 } 533 } 534 } 535} 536 537void SkXfermode::xferA8(SkAlpha* SK_RESTRICT dst, 538 const SkPMColor src[], int count, 539 const SkAlpha* SK_RESTRICT aa) 540{ 541 SkASSERT(dst && src && count >= 0); 542 543 if (NULL == aa) { 544 for (int i = count - 1; i >= 0; --i) { 545 SkPMColor res = this->xferColor(src[i], (dst[i] << SK_A32_SHIFT)); 546 dst[i] = SkToU8(SkGetPackedA32(res)); 547 } 548 } else { 549 for (int i = count - 1; i >= 0; --i) { 550 unsigned a = aa[i]; 551 if (0 != a) { 552 SkAlpha dstA = dst[i]; 553 unsigned A = SkGetPackedA32(this->xferColor(src[i], 554 (SkPMColor)(dstA << SK_A32_SHIFT))); 555 if (0xFF != a) { 556 A = SkAlphaBlend(A, dstA, SkAlpha255To256(a)); 557 } 558 dst[i] = SkToU8(A); 559 } 560 } 561 } 562} 563 564/////////////////////////////////////////////////////////////////////////////// 565 566void SkProcXfermode::xfer32(SkPMColor* SK_RESTRICT dst, 567 const SkPMColor* SK_RESTRICT src, int count, 568 const SkAlpha* SK_RESTRICT aa) { 569 SkASSERT(dst && src && count >= 0); 570 571 SkXfermodeProc proc = fProc; 572 573 if (NULL != proc) { 574 if (NULL == aa) { 575 for (int i = count - 1; i >= 0; --i) { 576 dst[i] = proc(src[i], dst[i]); 577 } 578 } else { 579 for (int i = count - 1; i >= 0; --i) { 580 unsigned a = aa[i]; 581 if (0 != a) { 582 SkPMColor dstC = dst[i]; 583 SkPMColor C = proc(src[i], dstC); 584 if (a != 0xFF) { 585 C = SkFourByteInterp(C, dstC, a); 586 } 587 dst[i] = C; 588 } 589 } 590 } 591 } 592} 593 594void SkProcXfermode::xfer16(uint16_t* SK_RESTRICT dst, 595 const SkPMColor* SK_RESTRICT src, int count, 596 const SkAlpha* SK_RESTRICT aa) { 597 SkASSERT(dst && src && count >= 0); 598 599 SkXfermodeProc proc = fProc; 600 601 if (NULL != proc) { 602 if (NULL == aa) { 603 for (int i = count - 1; i >= 0; --i) { 604 SkPMColor dstC = SkPixel16ToPixel32(dst[i]); 605 dst[i] = SkPixel32ToPixel16_ToU16(proc(src[i], dstC)); 606 } 607 } else { 608 for (int i = count - 1; i >= 0; --i) { 609 unsigned a = aa[i]; 610 if (0 != a) { 611 SkPMColor dstC = SkPixel16ToPixel32(dst[i]); 612 SkPMColor C = proc(src[i], dstC); 613 if (0xFF != a) { 614 C = SkFourByteInterp(C, dstC, a); 615 } 616 dst[i] = SkPixel32ToPixel16_ToU16(C); 617 } 618 } 619 } 620 } 621} 622 623void SkProcXfermode::xfer4444(SkPMColor16* SK_RESTRICT dst, 624 const SkPMColor* SK_RESTRICT src, int count, 625 const SkAlpha* SK_RESTRICT aa) { 626 SkASSERT(dst && src && count >= 0); 627 628 SkXfermodeProc proc = fProc; 629 630 if (NULL != proc) { 631 if (NULL == aa) { 632 for (int i = count - 1; i >= 0; --i) { 633 SkPMColor dstC = SkPixel4444ToPixel32(dst[i]); 634 dst[i] = SkPixel32ToPixel4444(proc(src[i], dstC)); 635 } 636 } else { 637 for (int i = count - 1; i >= 0; --i) { 638 unsigned a = aa[i]; 639 if (0 != a) { 640 SkPMColor dstC = SkPixel4444ToPixel32(dst[i]); 641 SkPMColor C = proc(src[i], dstC); 642 if (0xFF != a) { 643 C = SkFourByteInterp(C, dstC, a); 644 } 645 dst[i] = SkPixel32ToPixel4444(C); 646 } 647 } 648 } 649 } 650} 651 652void SkProcXfermode::xferA8(SkAlpha* SK_RESTRICT dst, 653 const SkPMColor* SK_RESTRICT src, int count, 654 const SkAlpha* SK_RESTRICT aa) { 655 SkASSERT(dst && src && count >= 0); 656 657 SkXfermodeProc proc = fProc; 658 659 if (NULL != proc) { 660 if (NULL == aa) { 661 for (int i = count - 1; i >= 0; --i) { 662 SkPMColor res = proc(src[i], dst[i] << SK_A32_SHIFT); 663 dst[i] = SkToU8(SkGetPackedA32(res)); 664 } 665 } else { 666 for (int i = count - 1; i >= 0; --i) { 667 unsigned a = aa[i]; 668 if (0 != a) { 669 SkAlpha dstA = dst[i]; 670 SkPMColor res = proc(src[i], dstA << SK_A32_SHIFT); 671 unsigned A = SkGetPackedA32(res); 672 if (0xFF != a) { 673 A = SkAlphaBlend(A, dstA, SkAlpha255To256(a)); 674 } 675 dst[i] = SkToU8(A); 676 } 677 } 678 } 679 } 680} 681 682SkProcXfermode::SkProcXfermode(SkFlattenableReadBuffer& buffer) 683 : SkXfermode(buffer) { 684 // Might be a NULL if the Xfermode is recorded using the CrossProcess flag 685 fProc = (SkXfermodeProc)buffer.readFunctionPtr(); 686} 687 688void SkProcXfermode::flatten(SkFlattenableWriteBuffer& buffer) { 689 if (buffer.isCrossProcess()) { 690 // function pointer is only valid in the current process. Write a NULL 691 // so it can't be accidentally used 692 buffer.writeFunctionPtr(NULL); 693 } else { 694 buffer.writeFunctionPtr((void*)fProc); 695 } 696} 697 698/////////////////////////////////////////////////////////////////////////////// 699/////////////////////////////////////////////////////////////////////////////// 700 701class SkProcCoeffXfermode : public SkProcXfermode { 702public: 703 SkProcCoeffXfermode(const ProcCoeff& rec, Mode mode) 704 : INHERITED(rec.fProc) { 705 fMode = mode; 706 // these may be valid, or may be CANNOT_USE_COEFF 707 fSrcCoeff = rec.fSC; 708 fDstCoeff = rec.fDC; 709 } 710 711 virtual bool asMode(Mode* mode) { 712 if (mode) { 713 *mode = fMode; 714 } 715 return true; 716 } 717 718 virtual bool asCoeff(Coeff* sc, Coeff* dc) { 719 if (CANNOT_USE_COEFF == fSrcCoeff) { 720 return false; 721 } 722 723 if (sc) { 724 *sc = fSrcCoeff; 725 } 726 if (dc) { 727 *dc = fDstCoeff; 728 } 729 return true; 730 } 731 732 virtual void flatten(SkFlattenableWriteBuffer& buffer) { 733 this->INHERITED::flatten(buffer); 734 buffer.write32(fMode); 735 } 736 737 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkProcCoeffXfermode) 738 739protected: 740 SkProcCoeffXfermode(SkFlattenableReadBuffer& buffer) 741 : INHERITED(buffer) { 742 fMode = (SkXfermode::Mode)buffer.readU32(); 743 744 const ProcCoeff& rec = gProcCoeffs[fMode]; 745 // these may be valid, or may be CANNOT_USE_COEFF 746 fSrcCoeff = rec.fSC; 747 fDstCoeff = rec.fDC; 748 // now update our function-ptr in the super class 749 this->INHERITED::setProc(rec.fProc); 750 } 751 752private: 753 Mode fMode; 754 Coeff fSrcCoeff, fDstCoeff; 755 756 757 typedef SkProcXfermode INHERITED; 758}; 759 760/////////////////////////////////////////////////////////////////////////////// 761 762class SkClearXfermode : public SkProcCoeffXfermode { 763public: 764 SkClearXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kClear_Mode) {} 765 766 virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) SK_OVERRIDE; 767 virtual void xferA8(SkAlpha*, const SkPMColor*, int, const SkAlpha*) SK_OVERRIDE; 768 769 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkClearXfermode) 770 771private: 772 SkClearXfermode(SkFlattenableReadBuffer& buffer) 773 : SkProcCoeffXfermode(buffer) {} 774 775}; 776 777void SkClearXfermode::xfer32(SkPMColor* SK_RESTRICT dst, 778 const SkPMColor* SK_RESTRICT, int count, 779 const SkAlpha* SK_RESTRICT aa) { 780 SkASSERT(dst && count >= 0); 781 782 if (NULL == aa) { 783 memset(dst, 0, count << 2); 784 } else { 785 for (int i = count - 1; i >= 0; --i) { 786 unsigned a = aa[i]; 787 if (0xFF == a) { 788 dst[i] = 0; 789 } else if (a != 0) { 790 dst[i] = SkAlphaMulQ(dst[i], SkAlpha255To256(255 - a)); 791 } 792 } 793 } 794} 795void SkClearXfermode::xferA8(SkAlpha* SK_RESTRICT dst, 796 const SkPMColor* SK_RESTRICT, int count, 797 const SkAlpha* SK_RESTRICT aa) { 798 SkASSERT(dst && count >= 0); 799 800 if (NULL == aa) { 801 memset(dst, 0, count); 802 } else { 803 for (int i = count - 1; i >= 0; --i) { 804 unsigned a = aa[i]; 805 if (0xFF == a) { 806 dst[i] = 0; 807 } else if (0 != a) { 808 dst[i] = SkAlphaMulAlpha(dst[i], 255 - a); 809 } 810 } 811 } 812} 813 814/////////////////////////////////////////////////////////////////////////////// 815 816class SkSrcXfermode : public SkProcCoeffXfermode { 817public: 818 SkSrcXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kSrc_Mode) {} 819 820 virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) SK_OVERRIDE; 821 virtual void xferA8(SkAlpha*, const SkPMColor*, int, const SkAlpha*) SK_OVERRIDE; 822 823 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkSrcXfermode) 824 825private: 826 SkSrcXfermode(SkFlattenableReadBuffer& buffer) 827 : SkProcCoeffXfermode(buffer) {} 828 829}; 830 831void SkSrcXfermode::xfer32(SkPMColor* SK_RESTRICT dst, 832 const SkPMColor* SK_RESTRICT src, int count, 833 const SkAlpha* SK_RESTRICT aa) { 834 SkASSERT(dst && src && count >= 0); 835 836 if (NULL == aa) { 837 memcpy(dst, src, count << 2); 838 } else { 839 for (int i = count - 1; i >= 0; --i) { 840 unsigned a = aa[i]; 841 if (a == 0xFF) { 842 dst[i] = src[i]; 843 } else if (a != 0) { 844 dst[i] = SkFourByteInterp(src[i], dst[i], a); 845 } 846 } 847 } 848} 849 850void SkSrcXfermode::xferA8(SkAlpha* SK_RESTRICT dst, 851 const SkPMColor* SK_RESTRICT src, int count, 852 const SkAlpha* SK_RESTRICT aa) { 853 SkASSERT(dst && src && count >= 0); 854 855 if (NULL == aa) { 856 for (int i = count - 1; i >= 0; --i) { 857 dst[i] = SkToU8(SkGetPackedA32(src[i])); 858 } 859 } else { 860 for (int i = count - 1; i >= 0; --i) { 861 unsigned a = aa[i]; 862 if (0 != a) { 863 unsigned srcA = SkGetPackedA32(src[i]); 864 if (a == 0xFF) { 865 dst[i] = SkToU8(srcA); 866 } else { 867 dst[i] = SkToU8(SkAlphaBlend(srcA, dst[i], a)); 868 } 869 } 870 } 871 } 872} 873 874//////////////////////////////////////////////////////////////////////////////////// 875 876class SkDstInXfermode : public SkProcCoeffXfermode { 877public: 878 SkDstInXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstIn_Mode) {} 879 880 virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) SK_OVERRIDE; 881 882 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDstInXfermode) 883 884private: 885 SkDstInXfermode(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {} 886 887 typedef SkProcCoeffXfermode INHERITED; 888}; 889 890void SkDstInXfermode::xfer32(SkPMColor* SK_RESTRICT dst, 891 const SkPMColor* SK_RESTRICT src, int count, 892 const SkAlpha* SK_RESTRICT aa) { 893 SkASSERT(dst && src); 894 895 if (count <= 0) { 896 return; 897 } 898 if (NULL != aa) { 899 return this->INHERITED::xfer32(dst, src, count, aa); 900 } 901 902 do { 903 unsigned a = SkGetPackedA32(*src); 904 *dst = SkAlphaMulQ(*dst, SkAlpha255To256(a)); 905 dst++; 906 src++; 907 } while (--count != 0); 908} 909 910///////////////////////////////////////////////////////////////////////////////////////// 911 912class SkDstOutXfermode : public SkProcCoeffXfermode { 913public: 914 SkDstOutXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstOut_Mode) {} 915 916 virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) SK_OVERRIDE; 917 918 SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkDstOutXfermode) 919 920private: 921 SkDstOutXfermode(SkFlattenableReadBuffer& buffer) 922 : INHERITED(buffer) {} 923 924 typedef SkProcCoeffXfermode INHERITED; 925}; 926 927void SkDstOutXfermode::xfer32(SkPMColor* SK_RESTRICT dst, 928 const SkPMColor* SK_RESTRICT src, int count, 929 const SkAlpha* SK_RESTRICT aa) { 930 SkASSERT(dst && src); 931 932 if (count <= 0) { 933 return; 934 } 935 if (NULL != aa) { 936 return this->INHERITED::xfer32(dst, src, count, aa); 937 } 938 939 do { 940 unsigned a = SkGetPackedA32(*src); 941 *dst = SkAlphaMulQ(*dst, SkAlpha255To256(255 - a)); 942 dst++; 943 src++; 944 } while (--count != 0); 945} 946 947/////////////////////////////////////////////////////////////////////////////// 948 949SkXfermode* SkXfermode::Create(Mode mode) { 950 SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount); 951 SkASSERT((unsigned)mode < kModeCount); 952 953 const ProcCoeff& rec = gProcCoeffs[mode]; 954 955 switch (mode) { 956 case kClear_Mode: 957 return SkNEW_ARGS(SkClearXfermode, (rec)); 958 case kSrc_Mode: 959 return SkNEW_ARGS(SkSrcXfermode, (rec)); 960 case kSrcOver_Mode: 961 return NULL; 962 case kDstIn_Mode: 963 return SkNEW_ARGS(SkDstInXfermode, (rec)); 964 case kDstOut_Mode: 965 return SkNEW_ARGS(SkDstOutXfermode, (rec)); 966 default: 967 return SkNEW_ARGS(SkProcCoeffXfermode, (rec, mode)); 968 } 969} 970 971SkXfermodeProc SkXfermode::GetProc(Mode mode) { 972 SkXfermodeProc proc = NULL; 973 if ((unsigned)mode < kModeCount) { 974 proc = gProcCoeffs[mode].fProc; 975 } 976 return proc; 977} 978 979bool SkXfermode::ModeAsCoeff(Mode mode, Coeff* src, Coeff* dst) { 980 SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount); 981 982 if ((unsigned)mode >= (unsigned)kModeCount) { 983 // illegal mode parameter 984 return false; 985 } 986 987 const ProcCoeff& rec = gProcCoeffs[mode]; 988 989 if (CANNOT_USE_COEFF == rec.fSC) { 990 return false; 991 } 992 993 SkASSERT(CANNOT_USE_COEFF != rec.fDC); 994 if (src) { 995 *src = rec.fSC; 996 } 997 if (dst) { 998 *dst = rec.fDC; 999 } 1000 return true; 1001} 1002 1003bool SkXfermode::AsMode(SkXfermode* xfer, Mode* mode) { 1004 if (NULL == xfer) { 1005 if (mode) { 1006 *mode = kSrcOver_Mode; 1007 } 1008 return true; 1009 } 1010 return xfer->asMode(mode); 1011} 1012 1013bool SkXfermode::AsCoeff(SkXfermode* xfer, Coeff* src, Coeff* dst) { 1014 if (NULL == xfer) { 1015 return ModeAsCoeff(kSrcOver_Mode, src, dst); 1016 } 1017 return xfer->asCoeff(src, dst); 1018} 1019 1020bool SkXfermode::IsMode(SkXfermode* xfer, Mode mode) { 1021 // if xfer==null then the mode is srcover 1022 Mode m = kSrcOver_Mode; 1023 if (xfer && !xfer->asMode(&m)) { 1024 return false; 1025 } 1026 return mode == m; 1027} 1028 1029/////////////////////////////////////////////////////////////////////////////// 1030//////////// 16bit xfermode procs 1031 1032#ifdef SK_DEBUG 1033static bool require_255(SkPMColor src) { return SkGetPackedA32(src) == 0xFF; } 1034static bool require_0(SkPMColor src) { return SkGetPackedA32(src) == 0; } 1035#endif 1036 1037static uint16_t src_modeproc16_255(SkPMColor src, uint16_t dst) { 1038 SkASSERT(require_255(src)); 1039 return SkPixel32ToPixel16(src); 1040} 1041 1042static uint16_t dst_modeproc16(SkPMColor src, uint16_t dst) { 1043 return dst; 1044} 1045 1046static uint16_t srcover_modeproc16_0(SkPMColor src, uint16_t dst) { 1047 SkASSERT(require_0(src)); 1048 return dst; 1049} 1050 1051static uint16_t srcover_modeproc16_255(SkPMColor src, uint16_t dst) { 1052 SkASSERT(require_255(src)); 1053 return SkPixel32ToPixel16(src); 1054} 1055 1056static uint16_t dstover_modeproc16_0(SkPMColor src, uint16_t dst) { 1057 SkASSERT(require_0(src)); 1058 return dst; 1059} 1060 1061static uint16_t dstover_modeproc16_255(SkPMColor src, uint16_t dst) { 1062 SkASSERT(require_255(src)); 1063 return dst; 1064} 1065 1066static uint16_t srcin_modeproc16_255(SkPMColor src, uint16_t dst) { 1067 SkASSERT(require_255(src)); 1068 return SkPixel32ToPixel16(src); 1069} 1070 1071static uint16_t dstin_modeproc16_255(SkPMColor src, uint16_t dst) { 1072 SkASSERT(require_255(src)); 1073 return dst; 1074} 1075 1076static uint16_t dstout_modeproc16_0(SkPMColor src, uint16_t dst) { 1077 SkASSERT(require_0(src)); 1078 return dst; 1079} 1080 1081static uint16_t srcatop_modeproc16(SkPMColor src, uint16_t dst) { 1082 unsigned isa = 255 - SkGetPackedA32(src); 1083 1084 return SkPackRGB16( 1085 SkPacked32ToR16(src) + SkAlphaMulAlpha(SkGetPackedR16(dst), isa), 1086 SkPacked32ToG16(src) + SkAlphaMulAlpha(SkGetPackedG16(dst), isa), 1087 SkPacked32ToB16(src) + SkAlphaMulAlpha(SkGetPackedB16(dst), isa)); 1088} 1089 1090static uint16_t srcatop_modeproc16_0(SkPMColor src, uint16_t dst) { 1091 SkASSERT(require_0(src)); 1092 return dst; 1093} 1094 1095static uint16_t srcatop_modeproc16_255(SkPMColor src, uint16_t dst) { 1096 SkASSERT(require_255(src)); 1097 return SkPixel32ToPixel16(src); 1098} 1099 1100static uint16_t dstatop_modeproc16_255(SkPMColor src, uint16_t dst) { 1101 SkASSERT(require_255(src)); 1102 return dst; 1103} 1104 1105/********* 1106 darken and lighten boil down to this. 1107 1108 darken = (1 - Sa) * Dc + min(Sc, Dc) 1109 lighten = (1 - Sa) * Dc + max(Sc, Dc) 1110 1111 if (Sa == 0) these become 1112 darken = Dc + min(0, Dc) = 0 1113 lighten = Dc + max(0, Dc) = Dc 1114 1115 if (Sa == 1) these become 1116 darken = min(Sc, Dc) 1117 lighten = max(Sc, Dc) 1118*/ 1119 1120static uint16_t darken_modeproc16_0(SkPMColor src, uint16_t dst) { 1121 SkASSERT(require_0(src)); 1122 return 0; 1123} 1124 1125static uint16_t darken_modeproc16_255(SkPMColor src, uint16_t dst) { 1126 SkASSERT(require_255(src)); 1127 unsigned r = SkFastMin32(SkPacked32ToR16(src), SkGetPackedR16(dst)); 1128 unsigned g = SkFastMin32(SkPacked32ToG16(src), SkGetPackedG16(dst)); 1129 unsigned b = SkFastMin32(SkPacked32ToB16(src), SkGetPackedB16(dst)); 1130 return SkPackRGB16(r, g, b); 1131} 1132 1133static uint16_t lighten_modeproc16_0(SkPMColor src, uint16_t dst) { 1134 SkASSERT(require_0(src)); 1135 return dst; 1136} 1137 1138static uint16_t lighten_modeproc16_255(SkPMColor src, uint16_t dst) { 1139 SkASSERT(require_255(src)); 1140 unsigned r = SkMax32(SkPacked32ToR16(src), SkGetPackedR16(dst)); 1141 unsigned g = SkMax32(SkPacked32ToG16(src), SkGetPackedG16(dst)); 1142 unsigned b = SkMax32(SkPacked32ToB16(src), SkGetPackedB16(dst)); 1143 return SkPackRGB16(r, g, b); 1144} 1145 1146struct Proc16Rec { 1147 SkXfermodeProc16 fProc16_0; 1148 SkXfermodeProc16 fProc16_255; 1149 SkXfermodeProc16 fProc16_General; 1150}; 1151 1152static const Proc16Rec gModeProcs16[] = { 1153 { NULL, NULL, NULL }, // CLEAR 1154 { NULL, src_modeproc16_255, NULL }, 1155 { dst_modeproc16, dst_modeproc16, dst_modeproc16 }, 1156 { srcover_modeproc16_0, srcover_modeproc16_255, NULL }, 1157 { dstover_modeproc16_0, dstover_modeproc16_255, NULL }, 1158 { NULL, srcin_modeproc16_255, NULL }, 1159 { NULL, dstin_modeproc16_255, NULL }, 1160 { NULL, NULL, NULL },// SRC_OUT 1161 { dstout_modeproc16_0, NULL, NULL }, 1162 { srcatop_modeproc16_0, srcatop_modeproc16_255, srcatop_modeproc16 }, 1163 { NULL, dstatop_modeproc16_255, NULL }, 1164 { NULL, NULL, NULL }, // XOR 1165 1166 { NULL, NULL, NULL }, // plus 1167 { NULL, NULL, NULL }, // multiply 1168 { NULL, NULL, NULL }, // screen 1169 { NULL, NULL, NULL }, // overlay 1170 { darken_modeproc16_0, darken_modeproc16_255, NULL }, // darken 1171 { lighten_modeproc16_0, lighten_modeproc16_255, NULL }, // lighten 1172 { NULL, NULL, NULL }, // colordodge 1173 { NULL, NULL, NULL }, // colorburn 1174 { NULL, NULL, NULL }, // hardlight 1175 { NULL, NULL, NULL }, // softlight 1176 { NULL, NULL, NULL }, // difference 1177 { NULL, NULL, NULL }, // exclusion 1178}; 1179 1180SkXfermodeProc16 SkXfermode::GetProc16(Mode mode, SkColor srcColor) { 1181 SkXfermodeProc16 proc16 = NULL; 1182 if ((unsigned)mode < kModeCount) { 1183 const Proc16Rec& rec = gModeProcs16[mode]; 1184 unsigned a = SkColorGetA(srcColor); 1185 1186 if (0 == a) { 1187 proc16 = rec.fProc16_0; 1188 } else if (255 == a) { 1189 proc16 = rec.fProc16_255; 1190 } else { 1191 proc16 = rec.fProc16_General; 1192 } 1193 } 1194 return proc16; 1195} 1196 1197SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkXfermode) 1198 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkProcCoeffXfermode) 1199 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkClearXfermode) 1200 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSrcXfermode) 1201 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDstInXfermode) 1202 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDstOutXfermode) 1203SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END 1204