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