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 18 static 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 30 static 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 40 static 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 49 static 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 59 static 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] 69 static SkPMColor clear_modeproc(SkPMColor src, SkPMColor dst) { 70 return 0; 71 } 72 73 // kSrc_Mode, //!< [Sa, Sc] 74 static SkPMColor src_modeproc(SkPMColor src, SkPMColor dst) { 75 return src; 76 } 77 78 // kDst_Mode, //!< [Da, Dc] 79 static SkPMColor dst_modeproc(SkPMColor src, SkPMColor dst) { 80 return dst; 81 } 82 83 // kSrcOver_Mode, //!< [Sa + Da - Sa*Da, Sc + (1 - Sa)*Dc] 84 static 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] 97 static 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] 104 static SkPMColor srcin_modeproc(SkPMColor src, SkPMColor dst) { 105 return SkAlphaMulQ(src, SkAlpha255To256(SkGetPackedA32(dst))); 106 } 107 108 // kDstIn_Mode, //!< [Sa * Da, Sa * Dc] 109 static 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)] 114 static 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)] 119 static 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] 124 static 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)] 139 static 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] 154 static 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 172 static 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 181 static 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 190 static inline int srcover_byte(int a, int b) { 191 return a + b - SkAlphaMulAlpha(a, b); 192 } 193 static 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 202 static 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 } 212 static 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 223 static 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 } 234 static 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 245 static 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 } 256 static 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 267 static 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 } 280 static 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 299 static 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 } 315 static 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 331 static 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 } 340 static 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) 351 static U8CPU sqrt_unit_byte(U8CPU n) { 352 return SkSqrtBits(n, 15+4); 353 } 354 355 // kSoftLight_Mode 356 static 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 } 370 static 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 381 static 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 } 385 static 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 396 static 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 } 401 static 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 411 struct ProcCoeff { 412 SkXfermodeProc fProc; 413 SkXfermode::Coeff fSC; 414 SkXfermode::Coeff fDC; 415 }; 416 417 #define CANNOT_USE_COEFF SkXfermode::Coeff(-1) 418 419 static 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 449 bool SkXfermode::asCoeff(Coeff* src, Coeff* dst) { 450 return false; 451 } 452 453 bool SkXfermode::asMode(Mode* mode) { 454 return false; 455 } 456 457 SkPMColor SkXfermode::xferColor(SkPMColor src, SkPMColor dst) { 458 // no-op. subclasses should override this 459 return dst; 460 } 461 462 void 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 486 void 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 511 void 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 537 void 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 566 void 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 594 void 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 623 void 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 652 void 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 682 SkProcXfermode::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 688 void 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 701 class SkProcCoeffXfermode : public SkProcXfermode { 702 public: 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 742 protected: 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 761 private: 762 Mode fMode; 763 Coeff fSrcCoeff, fDstCoeff; 764 765 766 typedef SkProcXfermode INHERITED; 767 }; 768 769 /////////////////////////////////////////////////////////////////////////////// 770 771 class SkClearXfermode : public SkProcCoeffXfermode { 772 public: 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 783 private: 784 SkClearXfermode(SkFlattenableReadBuffer& buffer) 785 : SkProcCoeffXfermode(buffer) {} 786 787 }; 788 789 void 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 } 807 void 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 828 class SkSrcXfermode : public SkProcCoeffXfermode { 829 public: 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 840 private: 841 SkSrcXfermode(SkFlattenableReadBuffer& buffer) 842 : SkProcCoeffXfermode(buffer) {} 843 844 }; 845 846 void 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 865 void 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 891 class SkDstInXfermode : public SkProcCoeffXfermode { 892 public: 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 902 private: 903 SkDstInXfermode(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {} 904 905 typedef SkProcCoeffXfermode INHERITED; 906 }; 907 908 void 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 930 class SkDstOutXfermode : public SkProcCoeffXfermode { 931 public: 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 941 private: 942 SkDstOutXfermode(SkFlattenableReadBuffer& buffer) 943 : INHERITED(buffer) {} 944 945 typedef SkProcCoeffXfermode INHERITED; 946 }; 947 948 void 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 970 SkXfermode* 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 992 SkXfermodeProc SkXfermode::GetProc(Mode mode) { 993 SkXfermodeProc proc = NULL; 994 if ((unsigned)mode < kModeCount) { 995 proc = gProcCoeffs[mode].fProc; 996 } 997 return proc; 998 } 999 1000 bool 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 1024 bool 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 1034 bool 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 1041 bool 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 1054 static bool require_255(SkPMColor src) { return SkGetPackedA32(src) == 0xFF; } 1055 static bool require_0(SkPMColor src) { return SkGetPackedA32(src) == 0; } 1056 #endif 1057 1058 static uint16_t src_modeproc16_255(SkPMColor src, uint16_t dst) { 1059 SkASSERT(require_255(src)); 1060 return SkPixel32ToPixel16(src); 1061 } 1062 1063 static uint16_t dst_modeproc16(SkPMColor src, uint16_t dst) { 1064 return dst; 1065 } 1066 1067 static uint16_t srcover_modeproc16_0(SkPMColor src, uint16_t dst) { 1068 SkASSERT(require_0(src)); 1069 return dst; 1070 } 1071 1072 static uint16_t srcover_modeproc16_255(SkPMColor src, uint16_t dst) { 1073 SkASSERT(require_255(src)); 1074 return SkPixel32ToPixel16(src); 1075 } 1076 1077 static uint16_t dstover_modeproc16_0(SkPMColor src, uint16_t dst) { 1078 SkASSERT(require_0(src)); 1079 return dst; 1080 } 1081 1082 static uint16_t dstover_modeproc16_255(SkPMColor src, uint16_t dst) { 1083 SkASSERT(require_255(src)); 1084 return dst; 1085 } 1086 1087 static uint16_t srcin_modeproc16_255(SkPMColor src, uint16_t dst) { 1088 SkASSERT(require_255(src)); 1089 return SkPixel32ToPixel16(src); 1090 } 1091 1092 static uint16_t dstin_modeproc16_255(SkPMColor src, uint16_t dst) { 1093 SkASSERT(require_255(src)); 1094 return dst; 1095 } 1096 1097 static uint16_t dstout_modeproc16_0(SkPMColor src, uint16_t dst) { 1098 SkASSERT(require_0(src)); 1099 return dst; 1100 } 1101 1102 static 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 1111 static uint16_t srcatop_modeproc16_0(SkPMColor src, uint16_t dst) { 1112 SkASSERT(require_0(src)); 1113 return dst; 1114 } 1115 1116 static uint16_t srcatop_modeproc16_255(SkPMColor src, uint16_t dst) { 1117 SkASSERT(require_255(src)); 1118 return SkPixel32ToPixel16(src); 1119 } 1120 1121 static 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 1141 static uint16_t darken_modeproc16_0(SkPMColor src, uint16_t dst) { 1142 SkASSERT(require_0(src)); 1143 return 0; 1144 } 1145 1146 static 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 1154 static uint16_t lighten_modeproc16_0(SkPMColor src, uint16_t dst) { 1155 SkASSERT(require_0(src)); 1156 return dst; 1157 } 1158 1159 static 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 1167 struct Proc16Rec { 1168 SkXfermodeProc16 fProc16_0; 1169 SkXfermodeProc16 fProc16_255; 1170 SkXfermodeProc16 fProc16_General; 1171 }; 1172 1173 static 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 1201 SkXfermodeProc16 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 1218 SK_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) 1224 SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END 1225