/** We take the original colors, not our premultiplied PMColors, since we can build a 16bit table as long as the original colors are opaque, even if the paint specifies a non-opaque alpha. */ void SkGradientShaderBase::GradientShaderCache::Build16bitCache( uint16_t cache[], SkColor c0, SkColor c1, int count, bool dither) { SkASSERT(count > 1); SkASSERT(SkColorGetA(c0) == 0xFF); SkASSERT(SkColorGetA(c1) == 0xFF); SkFixed r = SkColorGetR(c0); SkFixed g = SkColorGetG(c0); SkFixed b = SkColorGetB(c0); SkFixed dr = SkIntToFixed(SkColorGetR(c1) - r) / (count - 1); SkFixed dg = SkIntToFixed(SkColorGetG(c1) - g) / (count - 1); SkFixed db = SkIntToFixed(SkColorGetB(c1) - b) / (count - 1); r = SkIntToFixed(r) + 0x8000; g = SkIntToFixed(g) + 0x8000; b = SkIntToFixed(b) + 0x8000; if (dither) { do { unsigned rr = r >> 16; unsigned gg = g >> 16; unsigned bb = b >> 16; cache[0] = SkPackRGB16(SkR32ToR16(rr), SkG32ToG16(gg), SkB32ToB16(bb)); cache[kCache16Count] = SkDitherPack888ToRGB16(rr, gg, bb); cache += 1; r += dr; g += dg; b += db; } while (--count != 0); } else { do {
static uint16_t lighten_modeproc16_255(SkPMColor src, uint16_t dst) { SkASSERT(require_255(src)); unsigned r = SkMax32(SkPacked32ToR16(src), SkGetPackedR16(dst)); unsigned g = SkMax32(SkPacked32ToG16(src), SkGetPackedG16(dst)); unsigned b = SkMax32(SkPacked32ToB16(src), SkGetPackedB16(dst)); return SkPackRGB16(r, g, b); }
static uint16_t srcatop_modeproc16(SkPMColor src, uint16_t dst) { unsigned isa = 255 - SkGetPackedA32(src); return SkPackRGB16( SkPacked32ToR16(src) + SkAlphaMulAlpha(SkGetPackedR16(dst), isa), SkPacked32ToG16(src) + SkAlphaMulAlpha(SkGetPackedG16(dst), isa), SkPacked32ToB16(src) + SkAlphaMulAlpha(SkGetPackedB16(dst), isa)); }
static inline U16CPU SkBlend3216(SkPMColor src, U16CPU dst, unsigned scale) { SkASSERT(scale <= 32); scale <<= 3; return SkPackRGB16(SkAlphaBlend(SkPacked32ToR16(src), SkGetPackedR16(dst), scale), SkAlphaBlend(SkPacked32ToG16(src), SkGetPackedG16(dst), scale), SkAlphaBlend(SkPacked32ToB16(src), SkGetPackedB16(dst), scale)); }
static inline void D16_S32A_Blend_Pixel_helper(uint16_t* dst, SkPMColor sc, unsigned src_scale) { uint16_t dc = *dst; unsigned sa = SkGetPackedA32(sc); unsigned dr, dg, db; if (255 == sa) { dr = SkAlphaBlend(SkPacked32ToR16(sc), SkGetPackedR16(dc), src_scale); dg = SkAlphaBlend(SkPacked32ToG16(sc), SkGetPackedG16(dc), src_scale); db = SkAlphaBlend(SkPacked32ToB16(sc), SkGetPackedB16(dc), src_scale); } else { unsigned dst_scale = 255 - SkAlphaMul(sa, src_scale); dr = (SkPacked32ToR16(sc) * src_scale + SkGetPackedR16(dc) * dst_scale) >> 8; dg = (SkPacked32ToG16(sc) * src_scale + SkGetPackedG16(dc) * dst_scale) >> 8; db = (SkPacked32ToB16(sc) * src_scale + SkGetPackedB16(dc) * dst_scale) >> 8; } *dst = SkPackRGB16(dr, dg, db); }
static inline void test_565blend() { int total_failures = 0; for (int global_alpha = 0; global_alpha <= 255; ++global_alpha) { int failures = 0; int total = 0; for (int src_a = 0; src_a <= 255; ++src_a) { for (int src_c = 0; src_c <= src_a; ++src_c) { SkPMColor sc = SkPackARGB32(src_a, src_c, src_c, src_c); for (int dst_r = 0; dst_r <= 31; ++dst_r) { for (int dst_g = 0; dst_g <= 63; ++dst_g) { uint16_t dc = SkPackRGB16(dst_r, dst_g, dst_r); failures += !S32A_D565_Blend_0(sc, dc, global_alpha); total += 1; } } } } SkDebugf("global_alpha=%d failures=%d total=%d %g\n", global_alpha, failures, total, failures * 100.0 / total); total_failures += failures; } SkDebugf("total failures %d\n", total_failures); }
unsigned rr = r >> 16; unsigned gg = g >> 16; unsigned bb = b >> 16; cache[0] = SkPackRGB16(SkR32ToR16(rr), SkG32ToG16(gg), SkB32ToB16(bb)); cache[kCache16Count] = SkDitherPack888ToRGB16(rr, gg, bb); cache += 1; r += dr; g += dg; b += db; } while (--count != 0); } else { do { unsigned rr = r >> 16; unsigned gg = g >> 16; unsigned bb = b >> 16; cache[0] = SkPackRGB16(SkR32ToR16(rr), SkG32ToG16(gg), SkB32ToB16(bb)); cache[kCache16Count] = cache[0]; cache += 1; r += dr; g += dg; b += db; } while (--count != 0); } } /* * r,g,b used to be SkFixed, but on gcc (4.2.1 mac and 4.6.3 goobuntu) in * release builds, we saw a compiler error where the 0xFF parameter in * SkPackARGB32() was being totally ignored whenever it was called with * a non-zero add (e.g. 0x8000). *