Index: include/core/SkColorPriv.h |
diff --git a/include/core/SkColorPriv.h b/include/core/SkColorPriv.h |
index 40e6e15dc8873d823ff863f33196f852190b39b8..694d32472f79040e768bfaaf193aabc52468a30c 100644 |
--- a/include/core/SkColorPriv.h |
+++ b/include/core/SkColorPriv.h |
@@ -200,6 +200,18 @@ static inline unsigned Sk255To256(U8CPU value) { |
*/ |
#define SkAlphaMul(value, alpha256) (((value) * (alpha256)) >> 8) |
+/** Calculates 256 - (value * alpha256) / 255 in range [0,256], |
+ * for [0,255] value and [0,256] alpha256. |
+ */ |
+static inline U16CPU SkAlphaMulInv256(U16CPU value, U16CPU alpha256) { |
+#ifdef SK_SUPPORT_LEGACY_BROKEN_LERP |
+ return SkAlpha255To256(255 - SkAlphaMul(value, alpha256)); |
+#else |
+ unsigned prod = 0xFFFF - value * alpha256; |
+ return (prod + (prod >> 8)) >> 8; |
+#endif |
+} |
+ |
// The caller may want negative values, so keep all params signed (int) |
// so we don't accidentally slip into unsigned math and lose the sign |
// extension when we shift (in SkAlphaMul) |
@@ -568,13 +580,38 @@ static inline SkPMColor SkPMSrcOver(SkPMColor src, SkPMColor dst) { |
return src + SkAlphaMulQ(dst, SkAlpha255To256(255 - SkGetPackedA32(src))); |
} |
+/** |
+ * Interpolates between colors src and dst using [0,256] scale. |
+ */ |
+static inline SkPMColor SkPMLerp(SkPMColor src, SkPMColor dst, unsigned scale) { |
+#ifdef SK_SUPPORT_LEGACY_BROKEN_LERP |
+ return SkAlphaMulQ(src, scale) + SkAlphaMulQ(dst, 256 - scale); |
+#else |
+ return SkFastFourByteInterp256(src, dst, scale); |
+#endif |
+} |
+ |
static inline SkPMColor SkBlendARGB32(SkPMColor src, SkPMColor dst, U8CPU aa) { |
SkASSERT((unsigned)aa <= 255); |
unsigned src_scale = SkAlpha255To256(aa); |
+#ifdef SK_SUPPORT_LEGACY_BROKEN_LERP |
unsigned dst_scale = SkAlpha255To256(255 - SkAlphaMul(SkGetPackedA32(src), src_scale)); |
return SkAlphaMulQ(src, src_scale) + SkAlphaMulQ(dst, dst_scale); |
+#else |
+ unsigned dst_scale = SkAlphaMulInv256(SkGetPackedA32(src), src_scale); |
+ |
+ const uint32_t mask = 0xFF00FF; |
+ |
+ uint32_t src_rb = (src & mask) * src_scale; |
+ uint32_t src_ag = ((src >> 8) & mask) * src_scale; |
+ |
+ uint32_t dst_rb = (dst & mask) * dst_scale; |
+ uint32_t dst_ag = ((dst >> 8) & mask) * dst_scale; |
+ |
+ return (((src_rb + dst_rb) >> 8) & mask) | ((src_ag + dst_ag) & ~mask); |
+#endif |
} |
//////////////////////////////////////////////////////////////////////////////////////////// |