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