1 /* 2 * Copyright (C) 2006 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "SkXfermode.h" 18 #include "SkColorPriv.h" 19 20 #define SkAlphaMulAlpha(a, b) SkMulDiv255Round(a, b) 21 22 static SkPMColor SkFourByteInterp(SkPMColor src, SkPMColor dst, U8CPU alpha) { 23 unsigned scale = SkAlpha255To256(alpha); 24 25 unsigned a = SkAlphaBlend(SkGetPackedA32(src), SkGetPackedA32(dst), scale); 26 unsigned r = SkAlphaBlend(SkGetPackedR32(src), SkGetPackedR32(dst), scale); 27 unsigned g = SkAlphaBlend(SkGetPackedG32(src), SkGetPackedG32(dst), scale); 28 unsigned b = SkAlphaBlend(SkGetPackedB32(src), SkGetPackedB32(dst), scale); 29 30 return SkPackARGB32(a, r, g, b); 31 } 32 33 #if 0 34 // idea for higher precision blends in xfer procs (and slightly faster) 35 // see DstATop as a probable caller 36 static U8CPU mulmuldiv255round(U8CPU a, U8CPU b, U8CPU c, U8CPU d) { 37 SkASSERT(a <= 255); 38 SkASSERT(b <= 255); 39 SkASSERT(c <= 255); 40 SkASSERT(d <= 255); 41 unsigned prod = SkMulS16(a, b) + SkMulS16(c, d) + 128; 42 unsigned result = (prod + (prod >> 8)) >> 8; 43 SkASSERT(result <= 255); 44 return result; 45 } 46 #endif 47 48 static inline unsigned saturated_add(unsigned a, unsigned b) { 49 SkASSERT(a <= 255); 50 SkASSERT(b <= 255); 51 unsigned sum = a + b; 52 if (sum > 255) { 53 sum = 255; 54 } 55 return sum; 56 } 57 58 static inline int clamp_signed_byte(int n) { 59 if (n < 0) { 60 n = 0; 61 } else if (n > 255) { 62 n = 255; 63 } 64 return n; 65 } 66 67 static inline int clamp_div255round(int prod) { 68 if (prod <= 0) { 69 return 0; 70 } else if (prod >= 255*255) { 71 return 255; 72 } else { 73 return SkDiv255Round(prod); 74 } 75 } 76 77 static inline int clamp_max(int value, int max) { 78 if (value > max) { 79 value = max; 80 } 81 return value; 82 } 83 84 /////////////////////////////////////////////////////////////////////////////// 85 86 // kClear_Mode, //!< [0, 0] 87 static SkPMColor clear_modeproc(SkPMColor src, SkPMColor dst) { 88 return 0; 89 } 90 91 // kSrc_Mode, //!< [Sa, Sc] 92 static SkPMColor src_modeproc(SkPMColor src, SkPMColor dst) { 93 return src; 94 } 95 96 // kDst_Mode, //!< [Da, Dc] 97 static SkPMColor dst_modeproc(SkPMColor src, SkPMColor dst) { 98 return dst; 99 } 100 101 // kSrcOver_Mode, //!< [Sa + Da - Sa*Da, Sc + (1 - Sa)*Dc] 102 static 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] 115 static 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] 122 static SkPMColor srcin_modeproc(SkPMColor src, SkPMColor dst) { 123 return SkAlphaMulQ(src, SkAlpha255To256(SkGetPackedA32(dst))); 124 } 125 126 // kDstIn_Mode, //!< [Sa * Da, Sa * Dc] 127 static 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)] 132 static 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)] 137 static 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] 142 static 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)] 157 static 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] 172 static 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 190 static 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 199 static 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 208 static inline int srcover_byte(int a, int b) { 209 return a + b - SkAlphaMulAlpha(a, b); 210 } 211 static 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 220 static 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 } 230 static 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 241 static 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 } 252 static 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 263 static 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 } 274 static 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 285 static 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 } 298 static 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 317 static 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 } 333 static 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 349 static 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 } 358 static 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) 369 static U8CPU sqrt_unit_byte(U8CPU n) { 370 return SkSqrtBits(n, 15+4); 371 } 372 373 // kSoftLight_Mode 374 static 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 } 388 static 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 399 static 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 } 403 static 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 414 static 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 } 419 static 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 429 struct ProcCoeff { 430 SkXfermodeProc fProc; 431 SkXfermode::Coeff fSC; 432 SkXfermode::Coeff fDC; 433 }; 434 435 #define CANNOT_USE_COEFF SkXfermode::Coeff(-1) 436 437 static 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, SkXfermode::kOne_Coeff, SkXfermode::kOne_Coeff }, 452 { multiply_modeproc,SkXfermode::kZero_Coeff, SkXfermode::kSC_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 467 bool SkXfermode::asCoeff(Coeff* src, Coeff* dst) { 468 return false; 469 } 470 471 bool SkXfermode::asMode(Mode* mode) { 472 return false; 473 } 474 475 SkPMColor SkXfermode::xferColor(SkPMColor src, SkPMColor dst) { 476 // no-op. subclasses should override this 477 return dst; 478 } 479 480 void 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 504 void 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 529 void 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 555 void 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 584 void 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 612 void 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 641 void 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 670 void 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 700 SkProcXfermode::SkProcXfermode(SkFlattenableReadBuffer& buffer) 701 : SkXfermode(buffer) { 702 fProc = (SkXfermodeProc)buffer.readFunctionPtr(); 703 } 704 705 void SkProcXfermode::flatten(SkFlattenableWriteBuffer& buffer) { 706 buffer.writeFunctionPtr((void*)fProc); 707 } 708 709 /////////////////////////////////////////////////////////////////////////////// 710 /////////////////////////////////////////////////////////////////////////////// 711 712 class SkProcCoeffXfermode : public SkProcXfermode { 713 public: 714 SkProcCoeffXfermode(const ProcCoeff& rec, Mode mode) 715 : INHERITED(rec.fProc) { 716 fMode = mode; 717 // these may be valid, or may be CANNOT_USE_COEFF 718 fSrcCoeff = rec.fSC; 719 fDstCoeff = rec.fDC; 720 } 721 722 virtual bool asMode(Mode* mode) { 723 if (mode) { 724 *mode = fMode; 725 } 726 return true; 727 } 728 729 virtual bool asCoeff(Coeff* sc, Coeff* dc) { 730 if (CANNOT_USE_COEFF == fSrcCoeff) { 731 return false; 732 } 733 734 if (sc) { 735 *sc = fSrcCoeff; 736 } 737 if (dc) { 738 *dc = fDstCoeff; 739 } 740 return true; 741 } 742 743 virtual Factory getFactory() { return CreateProc; } 744 virtual void flatten(SkFlattenableWriteBuffer& buffer) { 745 this->INHERITED::flatten(buffer); 746 buffer.write32(fMode); 747 buffer.write32(fSrcCoeff); 748 buffer.write32(fDstCoeff); 749 } 750 751 static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) { 752 return SkNEW_ARGS(SkProcCoeffXfermode, (buffer)); 753 } 754 755 protected: 756 SkProcCoeffXfermode(SkFlattenableReadBuffer& buffer) 757 : INHERITED(buffer) { 758 fMode = (SkXfermode::Mode)buffer.readU32(); 759 fSrcCoeff = (Coeff)buffer.readU32(); 760 fDstCoeff = (Coeff)buffer.readU32(); 761 } 762 763 private: 764 Mode fMode; 765 Coeff fSrcCoeff, fDstCoeff; 766 767 768 typedef SkProcXfermode INHERITED; 769 }; 770 771 /////////////////////////////////////////////////////////////////////////////// 772 773 class SkClearXfermode : public SkProcCoeffXfermode { 774 public: 775 SkClearXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kClear_Mode) {} 776 777 virtual void xfer32(SK_RESTRICT SkPMColor dst[], 778 const SK_RESTRICT SkPMColor[], int count, 779 const SK_RESTRICT SkAlpha aa[]) { 780 SkASSERT(dst && count >= 0); 781 782 if (NULL == aa) { 783 memset(dst, 0, count << 2); 784 } else { 785 for (int i = count - 1; i >= 0; --i) { 786 unsigned a = aa[i]; 787 if (0xFF == a) { 788 dst[i] = 0; 789 } else if (a != 0) { 790 dst[i] = SkAlphaMulQ(dst[i], SkAlpha255To256(255 - a)); 791 } 792 } 793 } 794 } 795 virtual void xferA8(SK_RESTRICT SkAlpha dst[], 796 const SK_RESTRICT SkPMColor[], int count, 797 const SK_RESTRICT SkAlpha aa[]) { 798 SkASSERT(dst && count >= 0); 799 800 if (NULL == aa) { 801 memset(dst, 0, count); 802 } else { 803 for (int i = count - 1; i >= 0; --i) { 804 unsigned a = aa[i]; 805 if (0xFF == a) { 806 dst[i] = 0; 807 } else if (0 != a) { 808 dst[i] = SkAlphaMulAlpha(dst[i], 255 - a); 809 } 810 } 811 } 812 } 813 814 virtual Factory getFactory() { return CreateProc; } 815 816 static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) { 817 return SkNEW_ARGS(SkClearXfermode, (buffer)); 818 } 819 820 private: 821 SkClearXfermode(SkFlattenableReadBuffer& buffer) 822 : SkProcCoeffXfermode(buffer) {} 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(SK_RESTRICT SkPMColor dst[], 833 const SK_RESTRICT SkPMColor src[], int count, 834 const SK_RESTRICT SkAlpha aa[]) { 835 SkASSERT(dst && src && count >= 0); 836 837 if (NULL == aa) { 838 memcpy(dst, src, count << 2); 839 } else { 840 for (int i = count - 1; i >= 0; --i) { 841 unsigned a = aa[i]; 842 if (a == 0xFF) { 843 dst[i] = src[i]; 844 } else if (a != 0) { 845 dst[i] = SkFourByteInterp(src[i], dst[i], a); 846 } 847 } 848 } 849 } 850 851 virtual void xferA8(SK_RESTRICT SkAlpha dst[], 852 const SK_RESTRICT SkPMColor src[], int count, 853 const SK_RESTRICT SkAlpha aa[]) { 854 SkASSERT(dst && src && count >= 0); 855 856 if (NULL == aa) { 857 for (int i = count - 1; i >= 0; --i) { 858 dst[i] = SkToU8(SkGetPackedA32(src[i])); 859 } 860 } else { 861 for (int i = count - 1; i >= 0; --i) { 862 unsigned a = aa[i]; 863 if (0 != a) { 864 unsigned srcA = SkGetPackedA32(src[i]); 865 if (a == 0xFF) { 866 dst[i] = SkToU8(srcA); 867 } else { 868 dst[i] = SkToU8(SkAlphaBlend(srcA, dst[i], a)); 869 } 870 } 871 } 872 } 873 } 874 875 virtual Factory getFactory() { return CreateProc; } 876 877 static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) { 878 return SkNEW_ARGS(SkSrcXfermode, (buffer)); 879 } 880 881 private: 882 SkSrcXfermode(SkFlattenableReadBuffer& buffer) 883 : SkProcCoeffXfermode(buffer) {} 884 885 }; 886 887 class SkDstInXfermode : public SkProcCoeffXfermode { 888 public: 889 SkDstInXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstIn_Mode) {} 890 891 virtual void xfer32(SK_RESTRICT SkPMColor dst[], 892 const SK_RESTRICT SkPMColor src[], int count, 893 const SK_RESTRICT SkAlpha aa[]) { 894 SkASSERT(dst && src); 895 896 if (count <= 0) { 897 return; 898 } 899 if (NULL != aa) { 900 return this->INHERITED::xfer32(dst, src, count, aa); 901 } 902 903 do { 904 unsigned a = SkGetPackedA32(*src); 905 *dst = SkAlphaMulQ(*dst, SkAlpha255To256(a)); 906 dst++; 907 src++; 908 } while (--count != 0); 909 } 910 911 virtual Factory getFactory() { return CreateProc; } 912 913 static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) { 914 return SkNEW_ARGS(SkDstInXfermode, (buffer)); 915 } 916 917 private: 918 SkDstInXfermode(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {} 919 920 typedef SkProcCoeffXfermode INHERITED; 921 }; 922 923 class SkDstOutXfermode : public SkProcCoeffXfermode { 924 public: 925 SkDstOutXfermode(const ProcCoeff& rec) : SkProcCoeffXfermode(rec, kDstOut_Mode) {} 926 927 virtual void xfer32(SK_RESTRICT SkPMColor dst[], 928 const SK_RESTRICT SkPMColor src[], int count, 929 const SK_RESTRICT SkAlpha aa[]) { 930 SkASSERT(dst && src); 931 932 if (count <= 0) { 933 return; 934 } 935 if (NULL != aa) { 936 return this->INHERITED::xfer32(dst, src, count, aa); 937 } 938 939 do { 940 unsigned a = SkGetPackedA32(*src); 941 *dst = SkAlphaMulQ(*dst, SkAlpha255To256(255 - a)); 942 dst++; 943 src++; 944 } while (--count != 0); 945 } 946 947 virtual Factory getFactory() { return CreateProc; } 948 949 static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) { 950 return SkNEW_ARGS(SkDstOutXfermode, (buffer)); 951 } 952 953 private: 954 SkDstOutXfermode(SkFlattenableReadBuffer& buffer) 955 : INHERITED(buffer) {} 956 957 typedef SkProcCoeffXfermode INHERITED; 958 }; 959 960 /////////////////////////////////////////////////////////////////////////////// 961 962 SkXfermode* SkXfermode::Create(Mode mode) { 963 SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount); 964 SkASSERT((unsigned)mode < kModeCount); 965 966 const ProcCoeff& rec = gProcCoeffs[mode]; 967 968 switch (mode) { 969 case kClear_Mode: 970 return SkNEW_ARGS(SkClearXfermode, (rec)); 971 case kSrc_Mode: 972 return SkNEW_ARGS(SkSrcXfermode, (rec)); 973 case kSrcOver_Mode: 974 return NULL; 975 case kDstIn_Mode: 976 return SkNEW_ARGS(SkDstInXfermode, (rec)); 977 case kDstOut_Mode: 978 return SkNEW_ARGS(SkDstOutXfermode, (rec)); 979 default: 980 return SkNEW_ARGS(SkProcCoeffXfermode, (rec, mode)); 981 } 982 } 983 984 SkXfermodeProc SkXfermode::GetProc(Mode mode) { 985 SkXfermodeProc proc = NULL; 986 if ((unsigned)mode < kModeCount) { 987 proc = gProcCoeffs[mode].fProc; 988 } 989 return proc; 990 } 991 992 bool SkXfermode::ModeAsCoeff(Mode mode, Coeff* src, Coeff* dst) { 993 SkASSERT(SK_ARRAY_COUNT(gProcCoeffs) == kModeCount); 994 995 if ((unsigned)mode >= (unsigned)kModeCount) { 996 // illegal mode parameter 997 return false; 998 } 999 1000 const ProcCoeff& rec = gProcCoeffs[mode]; 1001 1002 if (CANNOT_USE_COEFF == rec.fSC) { 1003 return false; 1004 } 1005 1006 SkASSERT(CANNOT_USE_COEFF != rec.fDC); 1007 if (src) { 1008 *src = rec.fSC; 1009 } 1010 if (dst) { 1011 *dst = rec.fDC; 1012 } 1013 return true; 1014 } 1015 1016 bool SkXfermode::AsMode(SkXfermode* xfer, Mode* mode) { 1017 if (NULL == xfer) { 1018 if (mode) { 1019 *mode = kSrcOver_Mode; 1020 } 1021 return true; 1022 } 1023 return xfer->asMode(mode); 1024 } 1025 1026 bool SkXfermode::AsCoeff(SkXfermode* xfer, Coeff* src, Coeff* dst) { 1027 if (NULL == xfer) { 1028 return ModeAsCoeff(kSrcOver_Mode, src, dst); 1029 } 1030 return xfer->asCoeff(src, dst); 1031 } 1032 1033 /////////////////////////////////////////////////////////////////////////////// 1034 //////////// 16bit xfermode procs 1035 1036 #ifdef SK_DEBUG 1037 static bool require_255(SkPMColor src) { return SkGetPackedA32(src) == 0xFF; } 1038 static bool require_0(SkPMColor src) { return SkGetPackedA32(src) == 0; } 1039 #endif 1040 1041 static uint16_t src_modeproc16_255(SkPMColor src, uint16_t dst) { 1042 SkASSERT(require_255(src)); 1043 return SkPixel32ToPixel16(src); 1044 } 1045 1046 static uint16_t dst_modeproc16(SkPMColor src, uint16_t dst) { 1047 return dst; 1048 } 1049 1050 static uint16_t srcover_modeproc16_0(SkPMColor src, uint16_t dst) { 1051 SkASSERT(require_0(src)); 1052 return dst; 1053 } 1054 1055 static uint16_t srcover_modeproc16_255(SkPMColor src, uint16_t dst) { 1056 SkASSERT(require_255(src)); 1057 return SkPixel32ToPixel16(src); 1058 } 1059 1060 static uint16_t dstover_modeproc16_0(SkPMColor src, uint16_t dst) { 1061 SkASSERT(require_0(src)); 1062 return dst; 1063 } 1064 1065 static uint16_t dstover_modeproc16_255(SkPMColor src, uint16_t dst) { 1066 SkASSERT(require_255(src)); 1067 return dst; 1068 } 1069 1070 static uint16_t srcin_modeproc16_255(SkPMColor src, uint16_t dst) { 1071 SkASSERT(require_255(src)); 1072 return SkPixel32ToPixel16(src); 1073 } 1074 1075 static uint16_t dstin_modeproc16_255(SkPMColor src, uint16_t dst) { 1076 SkASSERT(require_255(src)); 1077 return dst; 1078 } 1079 1080 static uint16_t dstout_modeproc16_0(SkPMColor src, uint16_t dst) { 1081 SkASSERT(require_0(src)); 1082 return dst; 1083 } 1084 1085 static uint16_t srcatop_modeproc16(SkPMColor src, uint16_t dst) { 1086 unsigned isa = 255 - SkGetPackedA32(src); 1087 1088 return SkPackRGB16( 1089 SkPacked32ToR16(src) + SkAlphaMulAlpha(SkGetPackedR16(dst), isa), 1090 SkPacked32ToG16(src) + SkAlphaMulAlpha(SkGetPackedG16(dst), isa), 1091 SkPacked32ToB16(src) + SkAlphaMulAlpha(SkGetPackedB16(dst), isa)); 1092 } 1093 1094 static uint16_t srcatop_modeproc16_0(SkPMColor src, uint16_t dst) { 1095 SkASSERT(require_0(src)); 1096 return dst; 1097 } 1098 1099 static uint16_t srcatop_modeproc16_255(SkPMColor src, uint16_t dst) { 1100 SkASSERT(require_255(src)); 1101 return SkPixel32ToPixel16(src); 1102 } 1103 1104 static uint16_t dstatop_modeproc16_255(SkPMColor src, uint16_t dst) { 1105 SkASSERT(require_255(src)); 1106 return dst; 1107 } 1108 1109 /********* 1110 darken and lighten boil down to this. 1111 1112 darken = (1 - Sa) * Dc + min(Sc, Dc) 1113 lighten = (1 - Sa) * Dc + max(Sc, Dc) 1114 1115 if (Sa == 0) these become 1116 darken = Dc + min(0, Dc) = 0 1117 lighten = Dc + max(0, Dc) = Dc 1118 1119 if (Sa == 1) these become 1120 darken = min(Sc, Dc) 1121 lighten = max(Sc, Dc) 1122 */ 1123 1124 static uint16_t darken_modeproc16_0(SkPMColor src, uint16_t dst) { 1125 SkASSERT(require_0(src)); 1126 return 0; 1127 } 1128 1129 static uint16_t darken_modeproc16_255(SkPMColor src, uint16_t dst) { 1130 SkASSERT(require_255(src)); 1131 unsigned r = SkFastMin32(SkPacked32ToR16(src), SkGetPackedR16(dst)); 1132 unsigned g = SkFastMin32(SkPacked32ToG16(src), SkGetPackedG16(dst)); 1133 unsigned b = SkFastMin32(SkPacked32ToB16(src), SkGetPackedB16(dst)); 1134 return SkPackRGB16(r, g, b); 1135 } 1136 1137 static uint16_t lighten_modeproc16_0(SkPMColor src, uint16_t dst) { 1138 SkASSERT(require_0(src)); 1139 return dst; 1140 } 1141 1142 static uint16_t lighten_modeproc16_255(SkPMColor src, uint16_t dst) { 1143 SkASSERT(require_255(src)); 1144 unsigned r = SkMax32(SkPacked32ToR16(src), SkGetPackedR16(dst)); 1145 unsigned g = SkMax32(SkPacked32ToG16(src), SkGetPackedG16(dst)); 1146 unsigned b = SkMax32(SkPacked32ToB16(src), SkGetPackedB16(dst)); 1147 return SkPackRGB16(r, g, b); 1148 } 1149 1150 struct Proc16Rec { 1151 SkXfermodeProc16 fProc16_0; 1152 SkXfermodeProc16 fProc16_255; 1153 SkXfermodeProc16 fProc16_General; 1154 }; 1155 1156 static const Proc16Rec gModeProcs16[] = { 1157 { NULL, NULL, NULL }, // CLEAR 1158 { NULL, src_modeproc16_255, NULL }, 1159 { dst_modeproc16, dst_modeproc16, dst_modeproc16 }, 1160 { srcover_modeproc16_0, srcover_modeproc16_255, NULL }, 1161 { dstover_modeproc16_0, dstover_modeproc16_255, NULL }, 1162 { NULL, srcin_modeproc16_255, NULL }, 1163 { NULL, dstin_modeproc16_255, NULL }, 1164 { NULL, NULL, NULL },// SRC_OUT 1165 { dstout_modeproc16_0, NULL, NULL }, 1166 { srcatop_modeproc16_0, srcatop_modeproc16_255, srcatop_modeproc16 }, 1167 { NULL, dstatop_modeproc16_255, NULL }, 1168 { NULL, NULL, NULL }, // XOR 1169 1170 { NULL, NULL, NULL }, // plus 1171 { NULL, NULL, NULL }, // multiply 1172 { NULL, NULL, NULL }, // screen 1173 { NULL, NULL, NULL }, // overlay 1174 { darken_modeproc16_0, darken_modeproc16_255, NULL }, // darken 1175 { lighten_modeproc16_0, lighten_modeproc16_255, NULL }, // lighten 1176 { NULL, NULL, NULL }, // colordodge 1177 { NULL, NULL, NULL }, // colorburn 1178 { NULL, NULL, NULL }, // hardlight 1179 { NULL, NULL, NULL }, // softlight 1180 { NULL, NULL, NULL }, // difference 1181 { NULL, NULL, NULL }, // exclusion 1182 }; 1183 1184 SkXfermodeProc16 SkXfermode::GetProc16(Mode mode, SkColor srcColor) { 1185 SkXfermodeProc16 proc16 = NULL; 1186 if ((unsigned)mode < kModeCount) { 1187 const Proc16Rec& rec = gModeProcs16[mode]; 1188 unsigned a = SkColorGetA(srcColor); 1189 1190 if (0 == a) { 1191 proc16 = rec.fProc16_0; 1192 } else if (255 == a) { 1193 proc16 = rec.fProc16_255; 1194 } else { 1195 proc16 = rec.fProc16_General; 1196 } 1197 } 1198 return proc16; 1199 } 1200 1201 static SkFlattenable::Registrar 1202 gSkProcCoeffXfermodeReg("SkProcCoeffXfermode", 1203 SkProcCoeffXfermode::CreateProc); 1204 1205 static SkFlattenable::Registrar 1206 gSkClearXfermodeReg("SkClearXfermode", SkClearXfermode::CreateProc); 1207 1208 static SkFlattenable::Registrar 1209 gSkSrcXfermodeReg("SkSrcXfermode", SkSrcXfermode::CreateProc); 1210 1211 static SkFlattenable::Registrar 1212 gSkDstInXfermodeReg("SkDstInXfermode", SkDstInXfermode::CreateProc); 1213 1214 static SkFlattenable::Registrar 1215 gSkDstOutXfermodeReg("SkDstOutXfermode", SkDstOutXfermode::CreateProc); 1216