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 Factory getFactory() { return CreateProc; } 733 virtual void flatten(SkFlattenableWriteBuffer& buffer) { 734 this->INHERITED::flatten(buffer); 735 buffer.write32(fMode); 736 } 737 738 static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) { 739 return SkNEW_ARGS(SkProcCoeffXfermode, (buffer)); 740 } 741 742protected: 743 SkProcCoeffXfermode(SkFlattenableReadBuffer& buffer) 744 : INHERITED(buffer) { 745 fMode = (SkXfermode::Mode)buffer.readU32(); 746 747 if (buffer.getPictureVersion() == PICTURE_VERSION_ICS) { 748 fSrcCoeff = (Coeff)buffer.readU32(); 749 fDstCoeff = (Coeff)buffer.readU32(); 750 return; 751 } 752 753 const ProcCoeff& rec = gProcCoeffs[fMode]; 754 // these may be valid, or may be CANNOT_USE_COEFF 755 fSrcCoeff = rec.fSC; 756 fDstCoeff = rec.fDC; 757 // now update our function-ptr in the super class 758 this->INHERITED::setProc(rec.fProc); 759 } 760 761private: 762 Mode fMode; 763 Coeff fSrcCoeff, fDstCoeff; 764 765 766 typedef SkProcXfermode INHERITED; 767}; 768 769/////////////////////////////////////////////////////////////////////////////// 770 771class SkClearXfermode : public SkProcCoeffXfermode { 772public: 773 SkClearXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kClear_Mode) {} 774 775 virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) SK_OVERRIDE; 776 virtual void xferA8(SkAlpha*, const SkPMColor*, int, const SkAlpha*) SK_OVERRIDE; 777 virtual Factory getFactory() SK_OVERRIDE { return CreateProc; } 778 779 static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) { 780 return SkNEW_ARGS(SkClearXfermode, (buffer)); 781 } 782 783private: 784 SkClearXfermode(SkFlattenableReadBuffer& buffer) 785 : SkProcCoeffXfermode(buffer) {} 786 787}; 788 789void SkClearXfermode::xfer32(SkPMColor* SK_RESTRICT dst, 790 const SkPMColor* SK_RESTRICT, int count, 791 const SkAlpha* SK_RESTRICT aa) { 792 SkASSERT(dst && count >= 0); 793 794 if (NULL == aa) { 795 memset(dst, 0, count << 2); 796 } else { 797 for (int i = count - 1; i >= 0; --i) { 798 unsigned a = aa[i]; 799 if (0xFF == a) { 800 dst[i] = 0; 801 } else if (a != 0) { 802 dst[i] = SkAlphaMulQ(dst[i], SkAlpha255To256(255 - a)); 803 } 804 } 805 } 806} 807void SkClearXfermode::xferA8(SkAlpha* SK_RESTRICT dst, 808 const SkPMColor* SK_RESTRICT, int count, 809 const SkAlpha* SK_RESTRICT aa) { 810 SkASSERT(dst && count >= 0); 811 812 if (NULL == aa) { 813 memset(dst, 0, count); 814 } else { 815 for (int i = count - 1; i >= 0; --i) { 816 unsigned a = aa[i]; 817 if (0xFF == a) { 818 dst[i] = 0; 819 } else if (0 != a) { 820 dst[i] = SkAlphaMulAlpha(dst[i], 255 - a); 821 } 822 } 823 } 824} 825 826/////////////////////////////////////////////////////////////////////////////// 827 828class SkSrcXfermode : public SkProcCoeffXfermode { 829public: 830 SkSrcXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kSrc_Mode) {} 831 832 virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) SK_OVERRIDE; 833 virtual void xferA8(SkAlpha*, const SkPMColor*, int, const SkAlpha*) SK_OVERRIDE; 834 virtual Factory getFactory() SK_OVERRIDE { return CreateProc; } 835 836 static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) { 837 return SkNEW_ARGS(SkSrcXfermode, (buffer)); 838 } 839 840private: 841 SkSrcXfermode(SkFlattenableReadBuffer& buffer) 842 : SkProcCoeffXfermode(buffer) {} 843 844}; 845 846void SkSrcXfermode::xfer32(SkPMColor* SK_RESTRICT dst, 847 const SkPMColor* SK_RESTRICT src, int count, 848 const SkAlpha* SK_RESTRICT aa) { 849 SkASSERT(dst && src && count >= 0); 850 851 if (NULL == aa) { 852 memcpy(dst, src, count << 2); 853 } else { 854 for (int i = count - 1; i >= 0; --i) { 855 unsigned a = aa[i]; 856 if (a == 0xFF) { 857 dst[i] = src[i]; 858 } else if (a != 0) { 859 dst[i] = SkFourByteInterp(src[i], dst[i], a); 860 } 861 } 862 } 863} 864 865void SkSrcXfermode::xferA8(SkAlpha* SK_RESTRICT dst, 866 const SkPMColor* SK_RESTRICT src, int count, 867 const SkAlpha* SK_RESTRICT aa) { 868 SkASSERT(dst && src && count >= 0); 869 870 if (NULL == aa) { 871 for (int i = count - 1; i >= 0; --i) { 872 dst[i] = SkToU8(SkGetPackedA32(src[i])); 873 } 874 } else { 875 for (int i = count - 1; i >= 0; --i) { 876 unsigned a = aa[i]; 877 if (0 != a) { 878 unsigned srcA = SkGetPackedA32(src[i]); 879 if (a == 0xFF) { 880 dst[i] = SkToU8(srcA); 881 } else { 882 dst[i] = SkToU8(SkAlphaBlend(srcA, dst[i], a)); 883 } 884 } 885 } 886 } 887} 888 889//////////////////////////////////////////////////////////////////////////////////// 890 891class SkDstInXfermode : public SkProcCoeffXfermode { 892public: 893 SkDstInXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstIn_Mode) {} 894 895 virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) SK_OVERRIDE; 896 virtual Factory getFactory() SK_OVERRIDE { return CreateProc; } 897 898 static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) { 899 return SkNEW_ARGS(SkDstInXfermode, (buffer)); 900 } 901 902private: 903 SkDstInXfermode(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {} 904 905 typedef SkProcCoeffXfermode INHERITED; 906}; 907 908void SkDstInXfermode::xfer32(SkPMColor* SK_RESTRICT dst, 909 const SkPMColor* SK_RESTRICT src, int count, 910 const SkAlpha* SK_RESTRICT aa) { 911 SkASSERT(dst && src); 912 913 if (count <= 0) { 914 return; 915 } 916 if (NULL != aa) { 917 return this->INHERITED::xfer32(dst, src, count, aa); 918 } 919 920 do { 921 unsigned a = SkGetPackedA32(*src); 922 *dst = SkAlphaMulQ(*dst, SkAlpha255To256(a)); 923 dst++; 924 src++; 925 } while (--count != 0); 926} 927 928///////////////////////////////////////////////////////////////////////////////////////// 929 930class SkDstOutXfermode : public SkProcCoeffXfermode { 931public: 932 SkDstOutXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstOut_Mode) {} 933 934 virtual void xfer32(SkPMColor*, const SkPMColor*, int, const SkAlpha*) SK_OVERRIDE; 935 virtual Factory getFactory() SK_OVERRIDE { return CreateProc; } 936 937 static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) { 938 return SkNEW_ARGS(SkDstOutXfermode, (buffer)); 939 } 940 941private: 942 SkDstOutXfermode(SkFlattenableReadBuffer& buffer) 943 : INHERITED(buffer) {} 944 945 typedef SkProcCoeffXfermode INHERITED; 946}; 947 948void SkDstOutXfermode::xfer32(SkPMColor* SK_RESTRICT dst, 949 const SkPMColor* SK_RESTRICT src, int count, 950 const SkAlpha* SK_RESTRICT aa) { 951 SkASSERT(dst && src); 952 953 if (count <= 0) { 954 return; 955 } 956 if (NULL != aa) { 957 return this->INHERITED::xfer32(dst, src, count, aa); 958 } 959 960 do { 961 unsigned a = SkGetPackedA32(*src); 962 *dst = SkAlphaMulQ(*dst, SkAlpha255To256(255 - a)); 963 dst++; 964 src++; 965 } while (--count != 0); 966} 967 968/////////////////////////////////////////////////////////////////////////////// 969 970SkXfermode* SkXfermode::Create(Mode mode) { 971 SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount); 972 SkASSERT((unsigned)mode < kModeCount); 973 974 const ProcCoeff& rec = gProcCoeffs[mode]; 975 976 switch (mode) { 977 case kClear_Mode: 978 return SkNEW_ARGS(SkClearXfermode, (rec)); 979 case kSrc_Mode: 980 return SkNEW_ARGS(SkSrcXfermode, (rec)); 981 case kSrcOver_Mode: 982 return NULL; 983 case kDstIn_Mode: 984 return SkNEW_ARGS(SkDstInXfermode, (rec)); 985 case kDstOut_Mode: 986 return SkNEW_ARGS(SkDstOutXfermode, (rec)); 987 default: 988 return SkNEW_ARGS(SkProcCoeffXfermode, (rec, mode)); 989 } 990} 991 992SkXfermodeProc SkXfermode::GetProc(Mode mode) { 993 SkXfermodeProc proc = NULL; 994 if ((unsigned)mode < kModeCount) { 995 proc = gProcCoeffs[mode].fProc; 996 } 997 return proc; 998} 999 1000bool SkXfermode::ModeAsCoeff(Mode mode, Coeff* src, Coeff* dst) { 1001 SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount); 1002 1003 if ((unsigned)mode >= (unsigned)kModeCount) { 1004 // illegal mode parameter 1005 return false; 1006 } 1007 1008 const ProcCoeff& rec = gProcCoeffs[mode]; 1009 1010 if (CANNOT_USE_COEFF == rec.fSC) { 1011 return false; 1012 } 1013 1014 SkASSERT(CANNOT_USE_COEFF != rec.fDC); 1015 if (src) { 1016 *src = rec.fSC; 1017 } 1018 if (dst) { 1019 *dst = rec.fDC; 1020 } 1021 return true; 1022} 1023 1024bool SkXfermode::AsMode(SkXfermode* xfer, Mode* mode) { 1025 if (NULL == xfer) { 1026 if (mode) { 1027 *mode = kSrcOver_Mode; 1028 } 1029 return true; 1030 } 1031 return xfer->asMode(mode); 1032} 1033 1034bool SkXfermode::AsCoeff(SkXfermode* xfer, Coeff* src, Coeff* dst) { 1035 if (NULL == xfer) { 1036 return ModeAsCoeff(kSrcOver_Mode, src, dst); 1037 } 1038 return xfer->asCoeff(src, dst); 1039} 1040 1041bool SkXfermode::IsMode(SkXfermode* xfer, Mode mode) { 1042 // if xfer==null then the mode is srcover 1043 Mode m = kSrcOver_Mode; 1044 if (xfer && !xfer->asMode(&m)) { 1045 return false; 1046 } 1047 return mode == m; 1048} 1049 1050/////////////////////////////////////////////////////////////////////////////// 1051//////////// 16bit xfermode procs 1052 1053#ifdef SK_DEBUG 1054static bool require_255(SkPMColor src) { return SkGetPackedA32(src) == 0xFF; } 1055static bool require_0(SkPMColor src) { return SkGetPackedA32(src) == 0; } 1056#endif 1057 1058static uint16_t src_modeproc16_255(SkPMColor src, uint16_t dst) { 1059 SkASSERT(require_255(src)); 1060 return SkPixel32ToPixel16(src); 1061} 1062 1063static uint16_t dst_modeproc16(SkPMColor src, uint16_t dst) { 1064 return dst; 1065} 1066 1067static uint16_t srcover_modeproc16_0(SkPMColor src, uint16_t dst) { 1068 SkASSERT(require_0(src)); 1069 return dst; 1070} 1071 1072static uint16_t srcover_modeproc16_255(SkPMColor src, uint16_t dst) { 1073 SkASSERT(require_255(src)); 1074 return SkPixel32ToPixel16(src); 1075} 1076 1077static uint16_t dstover_modeproc16_0(SkPMColor src, uint16_t dst) { 1078 SkASSERT(require_0(src)); 1079 return dst; 1080} 1081 1082static uint16_t dstover_modeproc16_255(SkPMColor src, uint16_t dst) { 1083 SkASSERT(require_255(src)); 1084 return dst; 1085} 1086 1087static uint16_t srcin_modeproc16_255(SkPMColor src, uint16_t dst) { 1088 SkASSERT(require_255(src)); 1089 return SkPixel32ToPixel16(src); 1090} 1091 1092static uint16_t dstin_modeproc16_255(SkPMColor src, uint16_t dst) { 1093 SkASSERT(require_255(src)); 1094 return dst; 1095} 1096 1097static uint16_t dstout_modeproc16_0(SkPMColor src, uint16_t dst) { 1098 SkASSERT(require_0(src)); 1099 return dst; 1100} 1101 1102static uint16_t srcatop_modeproc16(SkPMColor src, uint16_t dst) { 1103 unsigned isa = 255 - SkGetPackedA32(src); 1104 1105 return SkPackRGB16( 1106 SkPacked32ToR16(src) + SkAlphaMulAlpha(SkGetPackedR16(dst), isa), 1107 SkPacked32ToG16(src) + SkAlphaMulAlpha(SkGetPackedG16(dst), isa), 1108 SkPacked32ToB16(src) + SkAlphaMulAlpha(SkGetPackedB16(dst), isa)); 1109} 1110 1111static uint16_t srcatop_modeproc16_0(SkPMColor src, uint16_t dst) { 1112 SkASSERT(require_0(src)); 1113 return dst; 1114} 1115 1116static uint16_t srcatop_modeproc16_255(SkPMColor src, uint16_t dst) { 1117 SkASSERT(require_255(src)); 1118 return SkPixel32ToPixel16(src); 1119} 1120 1121static uint16_t dstatop_modeproc16_255(SkPMColor src, uint16_t dst) { 1122 SkASSERT(require_255(src)); 1123 return dst; 1124} 1125 1126/********* 1127 darken and lighten boil down to this. 1128 1129 darken = (1 - Sa) * Dc + min(Sc, Dc) 1130 lighten = (1 - Sa) * Dc + max(Sc, Dc) 1131 1132 if (Sa == 0) these become 1133 darken = Dc + min(0, Dc) = 0 1134 lighten = Dc + max(0, Dc) = Dc 1135 1136 if (Sa == 1) these become 1137 darken = min(Sc, Dc) 1138 lighten = max(Sc, Dc) 1139*/ 1140 1141static uint16_t darken_modeproc16_0(SkPMColor src, uint16_t dst) { 1142 SkASSERT(require_0(src)); 1143 return 0; 1144} 1145 1146static uint16_t darken_modeproc16_255(SkPMColor src, uint16_t dst) { 1147 SkASSERT(require_255(src)); 1148 unsigned r = SkFastMin32(SkPacked32ToR16(src), SkGetPackedR16(dst)); 1149 unsigned g = SkFastMin32(SkPacked32ToG16(src), SkGetPackedG16(dst)); 1150 unsigned b = SkFastMin32(SkPacked32ToB16(src), SkGetPackedB16(dst)); 1151 return SkPackRGB16(r, g, b); 1152} 1153 1154static uint16_t lighten_modeproc16_0(SkPMColor src, uint16_t dst) { 1155 SkASSERT(require_0(src)); 1156 return dst; 1157} 1158 1159static uint16_t lighten_modeproc16_255(SkPMColor src, uint16_t dst) { 1160 SkASSERT(require_255(src)); 1161 unsigned r = SkMax32(SkPacked32ToR16(src), SkGetPackedR16(dst)); 1162 unsigned g = SkMax32(SkPacked32ToG16(src), SkGetPackedG16(dst)); 1163 unsigned b = SkMax32(SkPacked32ToB16(src), SkGetPackedB16(dst)); 1164 return SkPackRGB16(r, g, b); 1165} 1166 1167struct Proc16Rec { 1168 SkXfermodeProc16 fProc16_0; 1169 SkXfermodeProc16 fProc16_255; 1170 SkXfermodeProc16 fProc16_General; 1171}; 1172 1173static const Proc16Rec gModeProcs16[] = { 1174 { NULL, NULL, NULL }, // CLEAR 1175 { NULL, src_modeproc16_255, NULL }, 1176 { dst_modeproc16, dst_modeproc16, dst_modeproc16 }, 1177 { srcover_modeproc16_0, srcover_modeproc16_255, NULL }, 1178 { dstover_modeproc16_0, dstover_modeproc16_255, NULL }, 1179 { NULL, srcin_modeproc16_255, NULL }, 1180 { NULL, dstin_modeproc16_255, NULL }, 1181 { NULL, NULL, NULL },// SRC_OUT 1182 { dstout_modeproc16_0, NULL, NULL }, 1183 { srcatop_modeproc16_0, srcatop_modeproc16_255, srcatop_modeproc16 }, 1184 { NULL, dstatop_modeproc16_255, NULL }, 1185 { NULL, NULL, NULL }, // XOR 1186 1187 { NULL, NULL, NULL }, // plus 1188 { NULL, NULL, NULL }, // multiply 1189 { NULL, NULL, NULL }, // screen 1190 { NULL, NULL, NULL }, // overlay 1191 { darken_modeproc16_0, darken_modeproc16_255, NULL }, // darken 1192 { lighten_modeproc16_0, lighten_modeproc16_255, NULL }, // lighten 1193 { NULL, NULL, NULL }, // colordodge 1194 { NULL, NULL, NULL }, // colorburn 1195 { NULL, NULL, NULL }, // hardlight 1196 { NULL, NULL, NULL }, // softlight 1197 { NULL, NULL, NULL }, // difference 1198 { NULL, NULL, NULL }, // exclusion 1199}; 1200 1201SkXfermodeProc16 SkXfermode::GetProc16(Mode mode, SkColor srcColor) { 1202 SkXfermodeProc16 proc16 = NULL; 1203 if ((unsigned)mode < kModeCount) { 1204 const Proc16Rec& rec = gModeProcs16[mode]; 1205 unsigned a = SkColorGetA(srcColor); 1206 1207 if (0 == a) { 1208 proc16 = rec.fProc16_0; 1209 } else if (255 == a) { 1210 proc16 = rec.fProc16_255; 1211 } else { 1212 proc16 = rec.fProc16_General; 1213 } 1214 } 1215 return proc16; 1216} 1217 1218SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(SkXfermode) 1219 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkProcCoeffXfermode) 1220 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkClearXfermode) 1221 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkSrcXfermode) 1222 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDstInXfermode) 1223 SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(SkDstOutXfermode) 1224SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END 1225