SkXfermode.cpp revision eba9f316916f3381d6a5dd5c1300fea6ec6da8dc
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 22static 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 36static 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 48static 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/////////////////////////////////////////////////////////////////////////////// 59 60bool SkXfermode::asCoeff(Coeff* src, Coeff* dst) { 61 return false; 62} 63 64SkPMColor SkXfermode::xferColor(SkPMColor src, SkPMColor dst) { 65 // no-op. subclasses should override this 66 return dst; 67} 68 69void SkXfermode::xfer32(SK_RESTRICT SkPMColor dst[], 70 const SK_RESTRICT SkPMColor src[], int count, 71 const SK_RESTRICT SkAlpha aa[]) { 72 SkASSERT(dst && src && count >= 0); 73 74 if (NULL == aa) { 75 for (int i = count - 1; i >= 0; --i) { 76 dst[i] = this->xferColor(src[i], dst[i]); 77 } 78 } else { 79 for (int i = count - 1; i >= 0; --i) { 80 unsigned a = aa[i]; 81 if (0 != a) { 82 SkPMColor dstC = dst[i]; 83 SkPMColor C = this->xferColor(src[i], dstC); 84 if (0xFF != a) { 85 C = SkFourByteInterp(C, dstC, a); 86 } 87 dst[i] = C; 88 } 89 } 90 } 91} 92 93void SkXfermode::xfer16(SK_RESTRICT uint16_t dst[], 94 const SK_RESTRICT SkPMColor src[], int count, 95 const SK_RESTRICT SkAlpha aa[]) { 96 SkASSERT(dst && src && count >= 0); 97 98 if (NULL == aa) { 99 for (int i = count - 1; i >= 0; --i) { 100 SkPMColor dstC = SkPixel16ToPixel32(dst[i]); 101 dst[i] = SkPixel32ToPixel16_ToU16(this->xferColor(src[i], dstC)); 102 } 103 } else { 104 for (int i = count - 1; i >= 0; --i) { 105 unsigned a = aa[i]; 106 if (0 != a) { 107 SkPMColor dstC = SkPixel16ToPixel32(dst[i]); 108 SkPMColor C = this->xferColor(src[i], dstC); 109 if (0xFF != a) { 110 C = SkFourByteInterp(C, dstC, a); 111 } 112 dst[i] = SkPixel32ToPixel16_ToU16(C); 113 } 114 } 115 } 116} 117 118void SkXfermode::xfer4444(SK_RESTRICT SkPMColor16 dst[], 119 const SK_RESTRICT SkPMColor src[], int count, 120 const SK_RESTRICT SkAlpha aa[]) 121{ 122 SkASSERT(dst && src && count >= 0); 123 124 if (NULL == aa) { 125 for (int i = count - 1; i >= 0; --i) { 126 SkPMColor dstC = SkPixel4444ToPixel32(dst[i]); 127 dst[i] = SkPixel32ToPixel4444(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 = SkPixel4444ToPixel32(dst[i]); 134 SkPMColor C = this->xferColor(src[i], dstC); 135 if (0xFF != a) { 136 C = SkFourByteInterp(C, dstC, a); 137 } 138 dst[i] = SkPixel32ToPixel4444(C); 139 } 140 } 141 } 142} 143 144void SkXfermode::xferA8(SK_RESTRICT SkAlpha dst[], 145 const 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 res = this->xferColor(src[i], (dst[i] << SK_A32_SHIFT)); 153 dst[i] = SkToU8(SkGetPackedA32(res)); 154 } 155 } else { 156 for (int i = count - 1; i >= 0; --i) { 157 unsigned a = aa[i]; 158 if (0 != a) { 159 SkAlpha dstA = dst[i]; 160 unsigned A = SkGetPackedA32(this->xferColor(src[i], 161 (SkPMColor)(dstA << SK_A32_SHIFT))); 162 if (0xFF != a) { 163 A = SkAlphaBlend(A, dstA, SkAlpha255To256(a)); 164 } 165 dst[i] = SkToU8(A); 166 } 167 } 168 } 169} 170 171/////////////////////////////////////////////////////////////////////////////// 172 173void SkProcXfermode::xfer32(SK_RESTRICT SkPMColor dst[], 174 const SK_RESTRICT SkPMColor src[], int count, 175 const SK_RESTRICT SkAlpha aa[]) { 176 SkASSERT(dst && src && count >= 0); 177 178 SkXfermodeProc proc = fProc; 179 180 if (NULL != proc) { 181 if (NULL == aa) { 182 for (int i = count - 1; i >= 0; --i) { 183 dst[i] = proc(src[i], dst[i]); 184 } 185 } else { 186 for (int i = count - 1; i >= 0; --i) { 187 unsigned a = aa[i]; 188 if (0 != a) { 189 SkPMColor dstC = dst[i]; 190 SkPMColor C = proc(src[i], dstC); 191 if (a != 0xFF) { 192 C = SkFourByteInterp(C, dstC, a); 193 } 194 dst[i] = C; 195 } 196 } 197 } 198 } 199} 200 201void SkProcXfermode::xfer16(SK_RESTRICT uint16_t dst[], 202 const SK_RESTRICT SkPMColor src[], int count, 203 const SK_RESTRICT SkAlpha aa[]) { 204 SkASSERT(dst && src && count >= 0); 205 206 SkXfermodeProc proc = fProc; 207 208 if (NULL != proc) { 209 if (NULL == aa) { 210 for (int i = count - 1; i >= 0; --i) { 211 SkPMColor dstC = SkPixel16ToPixel32(dst[i]); 212 dst[i] = SkPixel32ToPixel16_ToU16(proc(src[i], dstC)); 213 } 214 } else { 215 for (int i = count - 1; i >= 0; --i) { 216 unsigned a = aa[i]; 217 if (0 != a) { 218 SkPMColor dstC = SkPixel16ToPixel32(dst[i]); 219 SkPMColor C = proc(src[i], dstC); 220 if (0xFF != a) { 221 C = SkFourByteInterp(C, dstC, a); 222 } 223 dst[i] = SkPixel32ToPixel16_ToU16(C); 224 } 225 } 226 } 227 } 228} 229 230void SkProcXfermode::xfer4444(SK_RESTRICT SkPMColor16 dst[], 231 const SK_RESTRICT SkPMColor src[], int count, 232 const SK_RESTRICT SkAlpha aa[]) { 233 SkASSERT(dst && src && count >= 0); 234 235 SkXfermodeProc proc = fProc; 236 237 if (NULL != proc) { 238 if (NULL == aa) { 239 for (int i = count - 1; i >= 0; --i) { 240 SkPMColor dstC = SkPixel4444ToPixel32(dst[i]); 241 dst[i] = SkPixel32ToPixel4444(proc(src[i], dstC)); 242 } 243 } else { 244 for (int i = count - 1; i >= 0; --i) { 245 unsigned a = aa[i]; 246 if (0 != a) { 247 SkPMColor dstC = SkPixel4444ToPixel32(dst[i]); 248 SkPMColor C = proc(src[i], dstC); 249 if (0xFF != a) { 250 C = SkFourByteInterp(C, dstC, a); 251 } 252 dst[i] = SkPixel32ToPixel4444(C); 253 } 254 } 255 } 256 } 257} 258 259void SkProcXfermode::xferA8(SK_RESTRICT SkAlpha dst[], 260 const SK_RESTRICT SkPMColor src[], int count, 261 const SK_RESTRICT SkAlpha aa[]) { 262 SkASSERT(dst && src && count >= 0); 263 264 SkXfermodeProc proc = fProc; 265 266 if (NULL != proc) { 267 if (NULL == aa) { 268 for (int i = count - 1; i >= 0; --i) { 269 SkPMColor res = proc(src[i], dst[i] << SK_A32_SHIFT); 270 dst[i] = SkToU8(SkGetPackedA32(res)); 271 } 272 } else { 273 for (int i = count - 1; i >= 0; --i) { 274 unsigned a = aa[i]; 275 if (0 != a) { 276 SkAlpha dstA = dst[i]; 277 SkPMColor res = proc(src[i], dstA << SK_A32_SHIFT); 278 unsigned A = SkGetPackedA32(res); 279 if (0xFF != a) { 280 A = SkAlphaBlend(A, dstA, SkAlpha255To256(a)); 281 } 282 dst[i] = SkToU8(A); 283 } 284 } 285 } 286 } 287} 288 289SkProcXfermode::SkProcXfermode(SkFlattenableReadBuffer& buffer) 290 : SkXfermode(buffer) { 291 fProc = (SkXfermodeProc)buffer.readFunctionPtr(); 292} 293 294void SkProcXfermode::flatten(SkFlattenableWriteBuffer& buffer) { 295 buffer.writeFunctionPtr((void*)fProc); 296} 297 298/////////////////////////////////////////////////////////////////////////////// 299/////////////////////////////////////////////////////////////////////////////// 300 301class SkProcCoeffXfermode : public SkProcXfermode { 302public: 303 SkProcCoeffXfermode(SkXfermodeProc proc, Coeff sc, Coeff dc) 304 : INHERITED(proc), fSrcCoeff(sc), fDstCoeff(dc) { 305 } 306 307 virtual bool asCoeff(Coeff* sc, Coeff* dc) { 308 if (sc) { 309 *sc = fSrcCoeff; 310 } 311 if (dc) { 312 *dc = fDstCoeff; 313 } 314 return true; 315 } 316 317 virtual Factory getFactory() { return CreateProc; } 318 virtual void flatten(SkFlattenableWriteBuffer& buffer) { 319 this->INHERITED::flatten(buffer); 320 buffer.write32(fSrcCoeff); 321 buffer.write32(fDstCoeff); 322 } 323 324protected: 325 SkProcCoeffXfermode(SkFlattenableReadBuffer& buffer) 326 : INHERITED(buffer) { 327 fSrcCoeff = (Coeff)buffer.readU32(); 328 fDstCoeff = (Coeff)buffer.readU32(); 329 } 330 331private: 332 Coeff fSrcCoeff, fDstCoeff; 333 334 static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) { 335 return SkNEW_ARGS(SkProcCoeffXfermode, (buffer)); } 336 337 typedef SkProcXfermode INHERITED; 338}; 339 340/////////////////////////////////////////////////////////////////////////////// 341 342// kClear_Mode, //!< [0, 0] 343static SkPMColor clear_modeproc(SkPMColor src, SkPMColor dst) { 344 return 0; 345} 346 347// kSrc_Mode, //!< [Sa, Sc] 348static SkPMColor src_modeproc(SkPMColor src, SkPMColor dst) { 349 return src; 350} 351 352// kDst_Mode, //!< [Da, Dc] 353static SkPMColor dst_modeproc(SkPMColor src, SkPMColor dst) { 354 return dst; 355} 356 357// kSrcOver_Mode, //!< [Sa + Da - Sa*Da, Sc + (1 - Sa)*Dc] 358static SkPMColor srcover_modeproc(SkPMColor src, SkPMColor dst) { 359#if 0 360 // this is the old, more-correct way, but it doesn't guarantee that dst==255 361 // will always stay opaque 362 return src + SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src))); 363#else 364 // this is slightly faster, but more importantly guarantees that dst==255 365 // will always stay opaque 366 return src + SkAlphaMulQ(dst, 256 - SkGetPackedA32(src)); 367#endif 368} 369 370// kDstOver_Mode, //!< [Sa + Da - Sa*Da, Dc + (1 - Da)*Sc] 371static SkPMColor dstover_modeproc(SkPMColor src, SkPMColor dst) { 372 // this is the reverse of srcover, just flipping src and dst 373 // see srcover's comment about the 256 for opaqueness guarantees 374 return dst + SkAlphaMulQ(src, 256 - SkGetPackedA32(dst)); 375} 376 377// kSrcIn_Mode, //!< [Sa * Da, Sc * Da] 378static SkPMColor srcin_modeproc(SkPMColor src, SkPMColor dst) { 379 return SkAlphaMulQ(src, SkAlpha255To256(SkGetPackedA32(dst))); 380} 381 382// kDstIn_Mode, //!< [Sa * Da, Sa * Dc] 383static SkPMColor dstin_modeproc(SkPMColor src, SkPMColor dst) { 384 return SkAlphaMulQ(dst, SkAlpha255To256(SkGetPackedA32(src))); 385} 386 387// kSrcOut_Mode, //!< [Sa * (1 - Da), Sc * (1 - Da)] 388static SkPMColor srcout_modeproc(SkPMColor src, SkPMColor dst) { 389 return SkAlphaMulQ(src, SkAlpha255To256(255 - SkGetPackedA32(dst))); 390} 391 392// kDstOut_Mode, //!< [Da * (1 - Sa), Dc * (1 - Sa)] 393static SkPMColor dstout_modeproc(SkPMColor src, SkPMColor dst) { 394 return SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src))); 395} 396 397// kSrcATop_Mode, //!< [Da, Sc * Da + (1 - Sa) * Dc] 398static SkPMColor srcatop_modeproc(SkPMColor src, SkPMColor dst) { 399 unsigned sa = SkGetPackedA32(src); 400 unsigned da = SkGetPackedA32(dst); 401 unsigned isa = 255 - sa; 402 403 return SkPackARGB32(da, 404 SkAlphaMulAlpha(da, SkGetPackedR32(src)) + 405 SkAlphaMulAlpha(isa, SkGetPackedR32(dst)), 406 SkAlphaMulAlpha(da, SkGetPackedG32(src)) + 407 SkAlphaMulAlpha(isa, SkGetPackedG32(dst)), 408 SkAlphaMulAlpha(da, SkGetPackedB32(src)) + 409 SkAlphaMulAlpha(isa, SkGetPackedB32(dst))); 410} 411 412// kDstATop_Mode, //!< [Sa, Sa * Dc + Sc * (1 - Da)] 413static SkPMColor dstatop_modeproc(SkPMColor src, SkPMColor dst) { 414 unsigned sa = SkGetPackedA32(src); 415 unsigned da = SkGetPackedA32(dst); 416 unsigned ida = 255 - da; 417 418 return SkPackARGB32(sa, 419 SkAlphaMulAlpha(ida, SkGetPackedR32(src)) + 420 SkAlphaMulAlpha(sa, SkGetPackedR32(dst)), 421 SkAlphaMulAlpha(ida, SkGetPackedG32(src)) + 422 SkAlphaMulAlpha(sa, SkGetPackedG32(dst)), 423 SkAlphaMulAlpha(ida, SkGetPackedB32(src)) + 424 SkAlphaMulAlpha(sa, SkGetPackedB32(dst))); 425} 426 427// kXor_Mode [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + (1 - Sa) * Dc] 428static SkPMColor xor_modeproc(SkPMColor src, SkPMColor dst) { 429 unsigned sa = SkGetPackedA32(src); 430 unsigned da = SkGetPackedA32(dst); 431 unsigned isa = 255 - sa; 432 unsigned ida = 255 - da; 433 434 return SkPackARGB32(sa + da - (SkAlphaMulAlpha(sa, da) << 1), 435 SkAlphaMulAlpha(ida, SkGetPackedR32(src)) + 436 SkAlphaMulAlpha(isa, SkGetPackedR32(dst)), 437 SkAlphaMulAlpha(ida, SkGetPackedG32(src)) + 438 SkAlphaMulAlpha(isa, SkGetPackedG32(dst)), 439 SkAlphaMulAlpha(ida, SkGetPackedB32(src)) + 440 SkAlphaMulAlpha(isa, SkGetPackedB32(dst))); 441} 442 443 444// kDarken_Mode, [Sa + Da - Sa·Da, Sc·(1 - Da) + Dc·(1 - Sa) + min(Sc, Dc)] 445 446static inline unsigned darken_p(unsigned src, unsigned dst, 447 unsigned src_mul, unsigned dst_mul) { 448 return ((dst_mul * src + src_mul * dst) >> 8) + SkMin32(src, dst); 449} 450 451static SkPMColor darken_modeproc(SkPMColor src, SkPMColor dst) { 452 unsigned sa = SkGetPackedA32(src); 453 unsigned da = SkGetPackedA32(dst); 454 unsigned src_scale = SkAlpha255To256(255 - sa); 455 unsigned dst_scale = SkAlpha255To256(255 - da); 456 457 unsigned ra = sa + da - SkAlphaMulAlpha(sa, da); 458 unsigned rr = darken_p(SkGetPackedR32(src), SkGetPackedR32(dst), 459 src_scale, dst_scale); 460 unsigned rg = darken_p(SkGetPackedG32(src), SkGetPackedG32(dst), 461 src_scale, dst_scale); 462 unsigned rb = darken_p(SkGetPackedB32(src), SkGetPackedB32(dst), 463 src_scale, dst_scale); 464 465 return SkPackARGB32(ra, SkFastMin32(rr, ra), 466 SkFastMin32(rg, ra), SkFastMin32(rb, ra)); 467} 468 469// kLighten_Mode, [Sa + Da - Sa·Da, Sc·(1 - Da) + Dc·(1 - Sa) + max(Sc, Dc)] 470static inline unsigned lighten_p(unsigned src, unsigned dst, 471 unsigned src_mul, unsigned dst_mul) { 472 return ((dst_mul * src + src_mul * dst) >> 8) + SkMax32(src, dst); 473} 474 475static SkPMColor lighten_modeproc(SkPMColor src, SkPMColor dst) { 476 unsigned sa = SkGetPackedA32(src); 477 unsigned da = SkGetPackedA32(dst); 478 unsigned src_scale = SkAlpha255To256(255 - sa); 479 unsigned dst_scale = SkAlpha255To256(255 - da); 480 481 unsigned ra = sa + da - SkAlphaMulAlpha(sa, da); 482 unsigned rr = lighten_p(SkGetPackedR32(src), SkGetPackedR32(dst), 483 src_scale, dst_scale); 484 unsigned rg = lighten_p(SkGetPackedG32(src), SkGetPackedG32(dst), 485 src_scale, dst_scale); 486 unsigned rb = lighten_p(SkGetPackedB32(src), SkGetPackedB32(dst), 487 src_scale, dst_scale); 488 489 return SkPackARGB32(ra, SkFastMin32(rr, ra), 490 SkFastMin32(rg, ra), SkFastMin32(rb, ra)); 491} 492 493static SkPMColor mult_modeproc(SkPMColor src, SkPMColor dst) { 494 int a = SkAlphaMulAlpha(SkGetPackedA32(src), SkGetPackedA32(dst)); 495 int r = SkAlphaMulAlpha(SkGetPackedR32(src), SkGetPackedR32(dst)); 496 int g = SkAlphaMulAlpha(SkGetPackedG32(src), SkGetPackedG32(dst)); 497 int b = SkAlphaMulAlpha(SkGetPackedB32(src), SkGetPackedB32(dst)); 498 return SkPackARGB32(a, r, g, b); 499} 500 501static inline int screen_byte(int a, int b) { 502 return a + b - SkAlphaMulAlpha(a, b); 503} 504 505static SkPMColor screen_modeproc(SkPMColor src, SkPMColor dst) { 506 int a = screen_byte(SkGetPackedA32(src), SkGetPackedA32(dst)); 507 int r = screen_byte(SkGetPackedR32(src), SkGetPackedR32(dst)); 508 int g = screen_byte(SkGetPackedG32(src), SkGetPackedG32(dst)); 509 int b = screen_byte(SkGetPackedB32(src), SkGetPackedB32(dst)); 510 return SkPackARGB32(a, r, g, b); 511} 512 513static SkPMColor add_modeproc(SkPMColor src, SkPMColor dst) { 514 unsigned a = saturated_add(SkGetPackedA32(src), SkGetPackedA32(dst)); 515 unsigned r = saturated_add(SkGetPackedR32(src), SkGetPackedR32(dst)); 516 unsigned g = saturated_add(SkGetPackedG32(src), SkGetPackedG32(dst)); 517 unsigned b = saturated_add(SkGetPackedB32(src), SkGetPackedB32(dst)); 518 return SkPackARGB32(a, r, g, b); 519} 520 521/////////////////////////////////////////////////////////////////////////////// 522 523class SkClearXfermode : public SkProcCoeffXfermode { 524public: 525 SkClearXfermode() : SkProcCoeffXfermode(clear_modeproc, 526 kZero_Coeff, kZero_Coeff) {} 527 528 virtual void xfer32(SK_RESTRICT SkPMColor dst[], 529 const SK_RESTRICT SkPMColor[], int count, 530 const SK_RESTRICT SkAlpha aa[]) { 531 SkASSERT(dst && count >= 0); 532 533 if (NULL == aa) { 534 memset(dst, 0, count << 2); 535 } else { 536 for (int i = count - 1; i >= 0; --i) { 537 unsigned a = aa[i]; 538 if (0xFF == a) { 539 dst[i] = 0; 540 } else if (a != 0) { 541 dst[i] = SkAlphaMulQ(dst[i], SkAlpha255To256(255 - a)); 542 } 543 } 544 } 545 } 546 virtual void xferA8(SK_RESTRICT SkAlpha dst[], 547 const SK_RESTRICT SkPMColor[], int count, 548 const SK_RESTRICT SkAlpha aa[]) { 549 SkASSERT(dst && count >= 0); 550 551 if (NULL == aa) { 552 memset(dst, 0, count); 553 } else { 554 for (int i = count - 1; i >= 0; --i) { 555 unsigned a = aa[i]; 556 if (0xFF == a) { 557 dst[i] = 0; 558 } else if (0 != a) { 559 dst[i] = SkAlphaMulAlpha(dst[i], 255 - a); 560 } 561 } 562 } 563 } 564 565 virtual Factory getFactory() { return CreateProc; } 566 567private: 568 SkClearXfermode(SkFlattenableReadBuffer& buffer) 569 : SkProcCoeffXfermode(buffer) {} 570 571 static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) { 572 return SkNEW_ARGS(SkClearXfermode, (buffer)); 573 } 574}; 575 576/////////////////////////////////////////////////////////////////////////////// 577 578class SkSrcXfermode : public SkProcCoeffXfermode { 579public: 580 SkSrcXfermode() : SkProcCoeffXfermode(src_modeproc, 581 kOne_Coeff, kZero_Coeff) {} 582 583 virtual void xfer32(SK_RESTRICT SkPMColor dst[], 584 const SK_RESTRICT SkPMColor src[], int count, 585 const SK_RESTRICT SkAlpha aa[]) { 586 SkASSERT(dst && src && count >= 0); 587 588 if (NULL == aa) { 589 memcpy(dst, src, count << 2); 590 } else { 591 for (int i = count - 1; i >= 0; --i) { 592 unsigned a = aa[i]; 593 if (a == 0xFF) { 594 dst[i] = src[i]; 595 } else if (a != 0) { 596 dst[i] = SkFourByteInterp(src[i], dst[i], a); 597 } 598 } 599 } 600 } 601 602 virtual void xferA8(SK_RESTRICT SkAlpha dst[], 603 const SK_RESTRICT SkPMColor src[], int count, 604 const SK_RESTRICT SkAlpha aa[]) { 605 SkASSERT(dst && src && count >= 0); 606 607 if (NULL == aa) { 608 for (int i = count - 1; i >= 0; --i) { 609 dst[i] = SkToU8(SkGetPackedA32(src[i])); 610 } 611 } else { 612 for (int i = count - 1; i >= 0; --i) { 613 unsigned a = aa[i]; 614 if (0 != a) { 615 unsigned srcA = SkGetPackedA32(src[i]); 616 if (a == 0xFF) { 617 dst[i] = SkToU8(srcA); 618 } else { 619 dst[i] = SkToU8(SkAlphaBlend(srcA, dst[i], a)); 620 } 621 } 622 } 623 } 624 } 625 626 virtual Factory getFactory() { return CreateProc; } 627 628private: 629 SkSrcXfermode(SkFlattenableReadBuffer& buffer) 630 : SkProcCoeffXfermode(buffer) {} 631 632 static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) { 633 return SkNEW_ARGS(SkSrcXfermode, (buffer)); 634 } 635}; 636 637class SkDstInXfermode : public SkProcCoeffXfermode { 638public: 639 SkDstInXfermode() : SkProcCoeffXfermode(dstin_modeproc, 640 kZero_Coeff, kSA_Coeff) {} 641 642 virtual void xfer32(SK_RESTRICT SkPMColor dst[], 643 const SK_RESTRICT SkPMColor src[], int count, 644 const SK_RESTRICT SkAlpha aa[]) { 645 SkASSERT(dst && src); 646 647 if (count <= 0) { 648 return; 649 } 650 if (NULL != aa) { 651 return this->INHERITED::xfer32(dst, src, count, aa); 652 } 653 654 do { 655 unsigned a = SkGetPackedA32(*src); 656 *dst = SkAlphaMulQ(*dst, SkAlpha255To256(a)); 657 dst++; 658 src++; 659 } while (--count != 0); 660 } 661 662 virtual Factory getFactory() { return CreateProc; } 663 664private: 665 SkDstInXfermode(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {} 666 667 static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) { 668 return SkNEW_ARGS(SkDstInXfermode, (buffer)); 669 } 670 671 typedef SkProcCoeffXfermode INHERITED; 672}; 673 674class SkDstOutXfermode : public SkProcCoeffXfermode { 675public: 676 SkDstOutXfermode() : SkProcCoeffXfermode(dstout_modeproc, 677 kZero_Coeff, kISA_Coeff) {} 678 679 virtual void xfer32(SK_RESTRICT SkPMColor dst[], 680 const SK_RESTRICT SkPMColor src[], int count, 681 const SK_RESTRICT SkAlpha aa[]) { 682 SkASSERT(dst && src); 683 684 if (count <= 0) { 685 return; 686 } 687 if (NULL != aa) { 688 return this->INHERITED::xfer32(dst, src, count, aa); 689 } 690 691 do { 692 unsigned a = SkGetPackedA32(*src); 693 *dst = SkAlphaMulQ(*dst, SkAlpha255To256(255 - a)); 694 dst++; 695 src++; 696 } while (--count != 0); 697 } 698 699 virtual Factory getFactory() { return CreateProc; } 700 701private: 702 SkDstOutXfermode(SkFlattenableReadBuffer& buffer) 703 : INHERITED(buffer) {} 704 705 static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) { 706 return SkNEW_ARGS(SkDstOutXfermode, (buffer)); 707 } 708 709 typedef SkProcCoeffXfermode INHERITED; 710}; 711 712/////////////////////////////////////////////////////////////////////////////// 713 714#include "SkPorterDuff.h" 715 716struct ProcCoeff { 717 SkXfermodeProc fProc; 718 SkXfermode::Coeff fSC; 719 SkXfermode::Coeff fDC; 720}; 721 722#define CANNOT_USE_COEFF SkXfermode::Coeff(-1) 723 724static const ProcCoeff gProcCoeffs[] = { 725 { clear_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kZero_Coeff }, 726 { src_modeproc, SkXfermode::kOne_Coeff, SkXfermode::kZero_Coeff }, 727 { dst_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kOne_Coeff }, 728 { srcover_modeproc, SkXfermode::kOne_Coeff, SkXfermode::kISA_Coeff }, 729 { dstover_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kOne_Coeff }, 730 { srcin_modeproc, SkXfermode::kDA_Coeff, SkXfermode::kZero_Coeff }, 731 { dstin_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kSA_Coeff }, 732 { srcout_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kZero_Coeff }, 733 { dstout_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kISA_Coeff }, 734 { srcatop_modeproc, SkXfermode::kDA_Coeff, SkXfermode::kISA_Coeff }, 735 { dstatop_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kSA_Coeff }, 736 { xor_modeproc, SkXfermode::kIDA_Coeff, SkXfermode::kISA_Coeff }, 737 { darken_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, 738 { lighten_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF }, 739 { mult_modeproc, SkXfermode::kZero_Coeff, SkXfermode::kSC_Coeff }, 740 { screen_modeproc, SkXfermode::kOne_Coeff, SkXfermode::kISC_Coeff }, 741 { add_modeproc, CANNOT_USE_COEFF, CANNOT_USE_COEFF } 742}; 743 744SkXfermode* SkPorterDuff::CreateXfermode(SkPorterDuff::Mode mode) { 745 SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == SkPorterDuff::kModeCount); 746 SkASSERT((unsigned)mode < SkPorterDuff::kModeCount); 747 748 switch (mode) { 749 case kClear_Mode: 750 return SkNEW(SkClearXfermode); 751 case kSrc_Mode: 752 return SkNEW(SkSrcXfermode); 753 case kSrcOver_Mode: 754 return NULL; 755 case kDstIn_Mode: 756 return SkNEW(SkDstInXfermode); 757 case kDstOut_Mode: 758 return SkNEW(SkDstOutXfermode); 759 // these two can't be represented with Coeff 760 case kDarken_Mode: 761 return SkNEW_ARGS(SkProcXfermode, (darken_modeproc)); 762 case kLighten_Mode: 763 return SkNEW_ARGS(SkProcXfermode, (lighten_modeproc)); 764 // use the table 765 default: { 766 const ProcCoeff& rec = gProcCoeffs[mode]; 767 SkASSERT((unsigned)rec.fSC < SkXfermode::kCoeffCount); 768 SkASSERT((unsigned)rec.fDC < SkXfermode::kCoeffCount); 769 return SkNEW_ARGS(SkProcCoeffXfermode, (rec.fProc, 770 rec.fSC, rec.fDC)); 771 } 772 } 773} 774 775bool SkPorterDuff::IsMode(SkXfermode* xfer, Mode* mode) { 776 if (NULL == xfer) { 777 if (mode) { 778 *mode = kSrcOver_Mode; 779 } 780 return true; 781 } 782 783 SkXfermode::Coeff sc, dc; 784 if (xfer->asCoeff(&sc, &dc)) { 785 SkASSERT((unsigned)sc < (unsigned)SkXfermode::kCoeffCount); 786 SkASSERT((unsigned)dc < (unsigned)SkXfermode::kCoeffCount); 787 788 const ProcCoeff* rec = gProcCoeffs; 789 for (size_t i = 0; i < SK_ARRAY_COUNT(gProcCoeffs); i++) { 790 if (rec[i].fSC == sc && rec[i].fDC == dc) { 791 if (mode) { 792 *mode = SkPorterDuff::Mode(i); 793 } 794 return true; 795 } 796 } 797 } 798 799 // no coefficients, or not found in our table 800 return false; 801} 802 803/////////////////////////////////////////////////////////////////////////////// 804 805#ifdef SK_DEBUGx 806static void unit_test() { 807 for (unsigned a = 0; a <= 255; a++) { 808 for (unsigned c = 0; c <= a; c++) { 809 SkPMColor pm = SkPackARGB32(a, c, c, c); 810 for (unsigned aa = 0; aa <= 255; aa++) { 811 for (unsigned cc = 0; cc <= aa; cc++) { 812 SkPMColor pm2 = SkPackARGB32(aa, cc, cc, cc); 813 814 const size_t N = SK_ARRAY_COUNT(gProcCoeffs); 815 for (size_t i = 0; i < N; i++) { 816 gProcCoeffs[i].fProc(pm, pm2); 817 } 818 } 819 } 820 } 821 } 822} 823#endif 824 825SkXfermodeProc SkPorterDuff::GetXfermodeProc(Mode mode) { 826#ifdef SK_DEBUGx 827 static bool gUnitTest; 828 if (!gUnitTest) { 829 gUnitTest = true; 830 unit_test(); 831 } 832#endif 833 834 SkXfermodeProc proc = NULL; 835 836 if ((unsigned)mode < SkPorterDuff::kModeCount) { 837 proc = gProcCoeffs[mode].fProc; 838 } 839 return proc; 840} 841 842/////////////////////////////////////////////////////////////////////////////// 843//////////// 16bit xfermode procs 844 845#ifdef SK_DEBUG 846static bool require_255(SkPMColor src) { return SkGetPackedA32(src) == 0xFF; } 847static bool require_0(SkPMColor src) { return SkGetPackedA32(src) == 0; } 848#endif 849 850static uint16_t src_modeproc16_255(SkPMColor src, uint16_t dst) { 851 SkASSERT(require_255(src)); 852 return SkPixel32ToPixel16(src); 853} 854 855static uint16_t dst_modeproc16(SkPMColor src, uint16_t dst) { 856 return dst; 857} 858 859static uint16_t srcover_modeproc16_0(SkPMColor src, uint16_t dst) { 860 SkASSERT(require_0(src)); 861 return dst; 862} 863 864static uint16_t srcover_modeproc16_255(SkPMColor src, uint16_t dst) { 865 SkASSERT(require_255(src)); 866 return SkPixel32ToPixel16(src); 867} 868 869static uint16_t dstover_modeproc16_0(SkPMColor src, uint16_t dst) { 870 SkASSERT(require_0(src)); 871 return dst; 872} 873 874static uint16_t dstover_modeproc16_255(SkPMColor src, uint16_t dst) { 875 SkASSERT(require_255(src)); 876 return dst; 877} 878 879static uint16_t srcin_modeproc16_255(SkPMColor src, uint16_t dst) { 880 SkASSERT(require_255(src)); 881 return SkPixel32ToPixel16(src); 882} 883 884static uint16_t dstin_modeproc16_255(SkPMColor src, uint16_t dst) { 885 SkASSERT(require_255(src)); 886 return dst; 887} 888 889static uint16_t dstout_modeproc16_0(SkPMColor src, uint16_t dst) { 890 SkASSERT(require_0(src)); 891 return dst; 892} 893 894static uint16_t srcatop_modeproc16(SkPMColor src, uint16_t dst) { 895 unsigned isa = 255 - SkGetPackedA32(src); 896 897 return SkPackRGB16( 898 SkPacked32ToR16(src) + SkAlphaMulAlpha(SkGetPackedR16(dst), isa), 899 SkPacked32ToG16(src) + SkAlphaMulAlpha(SkGetPackedG16(dst), isa), 900 SkPacked32ToB16(src) + SkAlphaMulAlpha(SkGetPackedB16(dst), isa)); 901} 902 903static uint16_t srcatop_modeproc16_0(SkPMColor src, uint16_t dst) { 904 SkASSERT(require_0(src)); 905 return dst; 906} 907 908static uint16_t srcatop_modeproc16_255(SkPMColor src, uint16_t dst) { 909 SkASSERT(require_255(src)); 910 return SkPixel32ToPixel16(src); 911} 912 913static uint16_t dstatop_modeproc16_255(SkPMColor src, uint16_t dst) { 914 SkASSERT(require_255(src)); 915 return dst; 916} 917 918/********* 919 darken and lighten boil down to this. 920 921 darken = (1 - Sa) * Dc + min(Sc, Dc) 922 lighten = (1 - Sa) * Dc + max(Sc, Dc) 923 924 if (Sa == 0) these become 925 darken = Dc + min(0, Dc) = 0 926 lighten = Dc + max(0, Dc) = Dc 927 928 if (Sa == 1) these become 929 darken = min(Sc, Dc) 930 lighten = max(Sc, Dc) 931*/ 932 933static uint16_t darken_modeproc16_0(SkPMColor src, uint16_t dst) { 934 SkASSERT(require_0(src)); 935 return 0; 936} 937 938static uint16_t darken_modeproc16_255(SkPMColor src, uint16_t dst) { 939 SkASSERT(require_255(src)); 940 unsigned r = SkFastMin32(SkPacked32ToR16(src), SkGetPackedR16(dst)); 941 unsigned g = SkFastMin32(SkPacked32ToG16(src), SkGetPackedG16(dst)); 942 unsigned b = SkFastMin32(SkPacked32ToB16(src), SkGetPackedB16(dst)); 943 return SkPackRGB16(r, g, b); 944} 945 946static uint16_t lighten_modeproc16_0(SkPMColor src, uint16_t dst) { 947 SkASSERT(require_0(src)); 948 return dst; 949} 950 951static uint16_t lighten_modeproc16_255(SkPMColor src, uint16_t dst) { 952 SkASSERT(require_255(src)); 953 unsigned r = SkMax32(SkPacked32ToR16(src), SkGetPackedR16(dst)); 954 unsigned g = SkMax32(SkPacked32ToG16(src), SkGetPackedG16(dst)); 955 unsigned b = SkMax32(SkPacked32ToB16(src), SkGetPackedB16(dst)); 956 return SkPackRGB16(r, g, b); 957} 958 959struct Proc16Rec { 960 SkXfermodeProc16 fProc16_0; 961 SkXfermodeProc16 fProc16_255; 962 SkXfermodeProc16 fProc16_General; 963}; 964 965static const Proc16Rec gPorterDuffModeProcs16[] = { 966 { NULL, NULL, NULL }, // CLEAR 967 { NULL, src_modeproc16_255, NULL }, 968 { dst_modeproc16, dst_modeproc16, dst_modeproc16 }, 969 { srcover_modeproc16_0, srcover_modeproc16_255, NULL }, 970 { dstover_modeproc16_0, dstover_modeproc16_255, NULL }, 971 { NULL, srcin_modeproc16_255, NULL }, 972 { NULL, dstin_modeproc16_255, NULL }, 973 { NULL, NULL, NULL },// SRC_OUT 974 { dstout_modeproc16_0, NULL, NULL }, 975 { srcatop_modeproc16_0, srcatop_modeproc16_255, srcatop_modeproc16 }, 976 { NULL, dstatop_modeproc16_255, NULL }, 977 { NULL, NULL, NULL }, // XOR 978 { darken_modeproc16_0, darken_modeproc16_255, NULL }, 979 { lighten_modeproc16_0, lighten_modeproc16_255, NULL }, 980 { NULL, NULL, NULL },//multiply 981 { NULL, NULL, NULL }// screen 982}; 983 984SkXfermodeProc16 SkPorterDuff::GetXfermodeProc16(Mode mode, SkColor srcColor) { 985 SkXfermodeProc16 proc16 = NULL; 986 987 if ((unsigned)mode < SkPorterDuff::kModeCount) { 988 const Proc16Rec& rec = gPorterDuffModeProcs16[mode]; 989 990 unsigned a = SkColorGetA(srcColor); 991 992 if (0 == a) { 993 proc16 = rec.fProc16_0; 994 } else if (255 == a) { 995 proc16 = rec.fProc16_255; 996 } else { 997 proc16 = rec.fProc16_General; 998 } 999 } 1000 return proc16; 1001} 1002 1003