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