/* * Copyright 2011 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "SkBlitRow.h" #include "SkColorPriv.h" #include "SkDither.h" /////////////////////////////////////////////////////////////////////////////// static void S32_D4444_Opaque(uint16_t* SK_RESTRICT dst, const SkPMColor* SK_RESTRICT src, int count, U8CPU alpha, int /*x*/, int /*y*/) { SkASSERT(255 == alpha); if (count > 0) { do { SkPMColor c = *src++; SkPMColorAssert(c); SkASSERT(SkGetPackedA32(c) == 255); *dst++ = SkPixel32ToPixel4444(c); } while (--count != 0); } } static void S32_D4444_Blend(uint16_t* SK_RESTRICT dst, const SkPMColor* SK_RESTRICT src, int count, U8CPU alpha, int /*x*/, int /*y*/) { SkASSERT(255 > alpha); if (count > 0) { unsigned scale16 = SkAlpha255To256(alpha) >> 4; do { SkPMColor c = *src++; SkPMColorAssert(c); SkASSERT(SkGetPackedA32(c) == 255); uint32_t src_expand = SkExpand32_4444(c); uint32_t dst_expand = SkExpand_4444(*dst); dst_expand += (src_expand - dst_expand) * scale16 >> 4; *dst++ = SkCompact_4444(dst_expand); } while (--count != 0); } } static void S32A_D4444_Opaque(uint16_t* SK_RESTRICT dst, const SkPMColor* SK_RESTRICT src, int count, U8CPU alpha, int /*x*/, int /*y*/) { SkASSERT(255 == alpha); if (count > 0) { do { SkPMColor c = *src++; SkPMColorAssert(c); // if (__builtin_expect(c!=0, 1)) if (c) { unsigned scale16 = SkAlpha255To256(255 - SkGetPackedA32(c)) >> 4; uint32_t src_expand = SkExpand_8888(c); uint32_t dst_expand = SkExpand_4444(*dst) * scale16; *dst = SkCompact_4444((src_expand + dst_expand) >> 4); } dst += 1; } while (--count != 0); } } static void S32A_D4444_Blend(uint16_t* SK_RESTRICT dst, const SkPMColor* SK_RESTRICT src, int count, U8CPU alpha, int /*x*/, int /*y*/) { SkASSERT(255 > alpha); if (count > 0) { int src_scale = SkAlpha255To256(alpha) >> 4; do { SkPMColor sc = *src++; SkPMColorAssert(sc); if (sc) { unsigned dst_scale = 16 - (SkGetPackedA32(sc) * src_scale >> 8); uint32_t src_expand = SkExpand32_4444(sc) * src_scale; uint32_t dst_expand = SkExpand_4444(*dst) * dst_scale; *dst = SkCompact_4444((src_expand + dst_expand) >> 4); } dst += 1; } while (--count != 0); } } ///////////////////////////////////////////////////////////////////////////// static void S32_D4444_Opaque_Dither(uint16_t* SK_RESTRICT dst, const SkPMColor* SK_RESTRICT src, int count, U8CPU alpha, int x, int y) { SkASSERT(255 == alpha); if (count > 0) { DITHER_4444_SCAN(y); do { SkPMColor c = *src++; SkPMColorAssert(c); SkASSERT(SkGetPackedA32(c) == 255); unsigned dither = DITHER_VALUE(x); *dst++ = SkDitherARGB32To4444(c, dither); DITHER_INC_X(x); } while (--count != 0); } } static void S32_D4444_Blend_Dither(uint16_t* SK_RESTRICT dst, const SkPMColor* SK_RESTRICT src, int count, U8CPU alpha, int x, int y) { SkASSERT(255 > alpha); if (count > 0) { int scale16 = SkAlpha255To256(alpha) >> 4; DITHER_4444_SCAN(y); do { SkPMColor c = *src++; SkPMColorAssert(c); SkASSERT(SkGetPackedA32(c) == 255); uint32_t src_expand = SkExpand32_4444(c) * scale16; uint32_t dst_expand = SkExpand_4444(*dst) * (16 - scale16); c = SkCompact_8888(src_expand + dst_expand); // convert back to SkPMColor *dst++ = SkDitherARGB32To4444(c, DITHER_VALUE(x)); DITHER_INC_X(x); } while (--count != 0); } } static void S32A_D4444_Opaque_Dither(uint16_t* SK_RESTRICT dst, const SkPMColor* SK_RESTRICT src, int count, U8CPU alpha, int x, int y) { SkASSERT(255 == alpha); if (count > 0) { DITHER_4444_SCAN(y); do { SkPMColor c = *src++; SkPMColorAssert(c); if (c) { unsigned a = SkGetPackedA32(c); int d = SkAlphaMul(DITHER_VALUE(x), SkAlpha255To256(a)); unsigned scale16 = SkAlpha255To256(255 - a) >> 4; uint32_t src_expand = SkExpand_8888(c); uint32_t dst_expand = SkExpand_4444(*dst) * scale16; // convert back to SkPMColor c = SkCompact_8888(src_expand + dst_expand); *dst = SkDitherARGB32To4444(c, d); } dst += 1; DITHER_INC_X(x); } while (--count != 0); } } // need DitherExpand888To4444(expand, dither) static void S32A_D4444_Blend_Dither(uint16_t* SK_RESTRICT dst, const SkPMColor* SK_RESTRICT src, int count, U8CPU alpha, int x, int y) { SkASSERT(255 > alpha); if (count > 0) { int src_scale = SkAlpha255To256(alpha) >> 4; DITHER_4444_SCAN(y); do { SkPMColor c = *src++; SkPMColorAssert(c); if (c) { unsigned a = SkAlpha255To256(SkGetPackedA32(c)); int d = SkAlphaMul(DITHER_VALUE(x), a); unsigned dst_scale = 16 - SkAlphaMul(src_scale, a); uint32_t src_expand = SkExpand32_4444(c) * src_scale; uint32_t dst_expand = SkExpand_4444(*dst) * dst_scale; // convert back to SkPMColor c = SkCompact_8888(src_expand + dst_expand); *dst = SkDitherARGB32To4444(c, d); } dst += 1; DITHER_INC_X(x); } while (--count != 0); } } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// static const SkBlitRow::Proc gProcs4444[] = { // no dither S32_D4444_Opaque, S32_D4444_Blend, S32A_D4444_Opaque, S32A_D4444_Blend, // dither S32_D4444_Opaque_Dither, S32_D4444_Blend_Dither, S32A_D4444_Opaque_Dither, S32A_D4444_Blend_Dither }; SkBlitRow::Proc SkBlitRow_Factory_4444(unsigned flags); SkBlitRow::Proc SkBlitRow_Factory_4444(unsigned flags) { SkASSERT(flags < SK_ARRAY_COUNT(gProcs4444)); return gProcs4444[flags]; }