diff options
Diffstat (limited to 'src/core/SkConfig8888.h')
-rw-r--r-- | src/core/SkConfig8888.h | 287 |
1 files changed, 287 insertions, 0 deletions
diff --git a/src/core/SkConfig8888.h b/src/core/SkConfig8888.h new file mode 100644 index 0000000..fe2f2cc --- /dev/null +++ b/src/core/SkConfig8888.h @@ -0,0 +1,287 @@ + +/* + * 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 "SkCanvas.h" +#include "SkColorPriv.h" + +namespace { + +/** + Copies all pixels from a bitmap to a dst ptr with a given rowBytes and + Config8888. The bitmap must have kARGB_8888_Config. + */ +inline void SkCopyBitmapToConfig8888(uint32_t* dstPixels, + size_t dstRowBytes, + SkCanvas::Config8888 dstConfig8888, + const SkBitmap& srcBmp); + +/** + * Copies all pixels in a bitmap to a dst ptr with row bytes. The src bitmap + * is assumed to have pixels and be kARGB_8888_Config. No conversion is applied + */ +inline void SkCopyARGB8888BitmapTo(uint32_t* dstPixels, + size_t dstRowBytes, + const SkBitmap& srcBmp); + +/** + Copies over all pixels in a bitmap from a src ptr with a given rowBytes and + Config8888. The bitmap must have pixels and be kARGB_8888_Config. + */ +inline void SkCopyConfig8888ToBitmap(const SkBitmap& dstBmp, + const uint32_t* srcPixels, + size_t srcRowBytes, + SkCanvas::Config8888 srcConfig8888); + +} + +/////////////////////////////////////////////////////////////////////////////// +// Implementation + +namespace { + +template <int A_IDX, int R_IDX, int G_IDX, int B_IDX> +inline uint32_t pack_config8888(uint32_t a, uint32_t r, + uint32_t g, uint32_t b) { +#ifdef SK_CPU_LENDIAN + return (a << (A_IDX * 8)) | (r << (R_IDX * 8)) | + (g << (G_IDX * 8)) | (b << (B_IDX * 8)); +#else + return (a << ((3-A_IDX) * 8)) | (r << ((3-R_IDX) * 8)) | + (g << ((3-G_IDX) * 8)) | (b << ((3-B_IDX) * 8)); +#endif +} + +template <int A_IDX, int R_IDX, int G_IDX, int B_IDX> +inline void unpack_config8888(uint32_t color, + uint32_t* a, uint32_t* r, + uint32_t* g, uint32_t* b) { +#ifdef SK_CPU_LENDIAN + *a = (color >> (A_IDX * 8)) & 0xff; + *r = (color >> (R_IDX * 8)) & 0xff; + *g = (color >> (G_IDX * 8)) & 0xff; + *b = (color >> (B_IDX * 8)) & 0xff; +#else + *a = (color >> ((3 - A_IDX) * 8)) & 0xff; + *r = (color >> ((3 - R_IDX) * 8)) & 0xff; + *g = (color >> ((3 - G_IDX) * 8)) & 0xff; + *b = (color >> ((3 - B_IDX) * 8)) & 0xff; +#endif +} + +template <bool UNPM, int A_IDX, int R_IDX, int G_IDX, int B_IDX> +inline void bitmap_copy_to_config8888(uint32_t* dstPixels, + size_t dstRowBytes, + const SkBitmap& srcBmp) { + SkASSERT(SkBitmap::kARGB_8888_Config == srcBmp.config()); + SkAutoLockPixels alp(srcBmp); + int w = srcBmp.width(); + int h = srcBmp.height(); + size_t srcRowBytes = srcBmp.rowBytes(); + + intptr_t src = reinterpret_cast<intptr_t>(srcBmp.getPixels()); + intptr_t dst = reinterpret_cast<intptr_t>(dstPixels); + + for (int y = 0; y < h; ++y) { + const SkPMColor* srcRow = reinterpret_cast<SkPMColor*>(src); + uint32_t* dstRow = reinterpret_cast<uint32_t*>(dst); + for (int x = 0; x < w; ++x) { + SkPMColor pmcolor = srcRow[x]; + if (UNPM) { + U8CPU a, r, g, b; + a = SkGetPackedA32(pmcolor); + if (a) { + // We're doing the explicit divide to match WebKit layout + // test expectations. We can modify and rebaseline if there + // it can be shown that there is a more performant way to + // unpremul. + r = SkGetPackedR32(pmcolor) * 0xff / a; + g = SkGetPackedG32(pmcolor) * 0xff / a; + b = SkGetPackedB32(pmcolor) * 0xff / a; + dstRow[x] = pack_config8888<A_IDX, R_IDX, + G_IDX, B_IDX>(a, r, g, b); + } else { + dstRow[x] = 0; + } + } else { + dstRow[x] = pack_config8888<A_IDX, R_IDX, + G_IDX, B_IDX>( + SkGetPackedA32(pmcolor), + SkGetPackedR32(pmcolor), + SkGetPackedG32(pmcolor), + SkGetPackedB32(pmcolor)); + } + } + dst += dstRowBytes; + src += srcRowBytes; + } +} + +template <bool PM, int A_IDX, int R_IDX, int G_IDX, int B_IDX> +inline void config8888_copy_to_bitmap(const SkBitmap& dstBmp, + const uint32_t* srcPixels, + size_t srcRowBytes) { + SkASSERT(SkBitmap::kARGB_8888_Config == dstBmp.config()); + SkAutoLockPixels alp(dstBmp); + int w = dstBmp.width(); + int h = dstBmp.height(); + size_t dstRowBytes = dstBmp.rowBytes(); + + intptr_t src = reinterpret_cast<intptr_t>(srcPixels); + intptr_t dst = reinterpret_cast<intptr_t>(dstBmp.getPixels()); + + for (int y = 0; y < h; ++y) { + const uint32_t* srcRow = reinterpret_cast<uint32_t*>(src); + SkPMColor* dstRow = reinterpret_cast<SkPMColor*>(dst); + for (int x = 0; x < w; ++x) { + uint32_t c8888 = srcRow[x]; + uint32_t a, r, g, b; + unpack_config8888<A_IDX, R_IDX, G_IDX, B_IDX>(c8888, &a, &r, + &g, &b); + if (PM) { + // This matches WebKit's conversion which we are replacing. + // We can consider alternative rounding rules for performance. + r = SkMulDiv255Ceiling(r, a); + g = SkMulDiv255Ceiling(g, a); + b = SkMulDiv255Ceiling(b, a); + } + // NoCheck: https://bugs.webkit.org/show_bug.cgi?id=74025 + dstRow[x] = SkPackARGB32NoCheck(a, r, g, b); + } + src += srcRowBytes; + dst += dstRowBytes; + } +} + +#ifdef SK_CPU_LENDIAN + static const int SK_NATIVE_A_IDX = SK_A32_SHIFT / 8; + static const int SK_NATIVE_R_IDX = SK_R32_SHIFT / 8; + static const int SK_NATIVE_G_IDX = SK_G32_SHIFT / 8; + static const int SK_NATIVE_B_IDX = SK_B32_SHIFT / 8; +#else + static const int SK_NATIVE_A_IDX = 3 - (SK_A32_SHIFT / 8); + static const int SK_NATIVE_R_IDX = 3 - (SK_R32_SHIFT / 8); + static const int SK_NATIVE_G_IDX = 3 - (SK_G32_SHIFT / 8); + static const int SK_NATIVE_B_IDX = 3 - (SK_B32_SHIFT / 8); +#endif + +inline void SkCopyBitmapToConfig8888(uint32_t* dstPixels, + size_t dstRowBytes, + SkCanvas::Config8888 dstConfig8888, + const SkBitmap& srcBmp) { + switch (dstConfig8888) { + case SkCanvas::kNative_Premul_Config8888: + bitmap_copy_to_config8888<false, + SK_NATIVE_A_IDX, SK_NATIVE_R_IDX, + SK_NATIVE_G_IDX, SK_NATIVE_B_IDX>( + dstPixels, + dstRowBytes, + srcBmp); + break; + case SkCanvas::kNative_Unpremul_Config8888: + bitmap_copy_to_config8888<true, + SK_NATIVE_A_IDX, SK_NATIVE_R_IDX, + SK_NATIVE_G_IDX, SK_NATIVE_B_IDX>( + dstPixels, + dstRowBytes, + srcBmp); + break; + case SkCanvas::kBGRA_Premul_Config8888: + bitmap_copy_to_config8888<false, 3, 2, 1, 0> ( + dstPixels, dstRowBytes, srcBmp); + break; + case SkCanvas::kBGRA_Unpremul_Config8888: + bitmap_copy_to_config8888<true, 3, 2, 1, 0> ( + dstPixels, dstRowBytes, srcBmp); + break; + case SkCanvas::kRGBA_Premul_Config8888: + bitmap_copy_to_config8888<false, 3, 0, 1, 2> ( + dstPixels, dstRowBytes, srcBmp); + break; + case SkCanvas::kRGBA_Unpremul_Config8888: + bitmap_copy_to_config8888<true, 3, 0, 1, 2> ( + dstPixels, dstRowBytes, srcBmp); + break; + default: + SkDEBUGFAIL("unexpected Config8888"); + break; + } +} + +inline void SkCopyConfig8888ToBitmap(const SkBitmap& dstBmp, + const uint32_t* srcPixels, + size_t srcRowBytes, + SkCanvas::Config8888 srcConfig8888) { + switch (srcConfig8888) { + case SkCanvas::kNative_Premul_Config8888: + config8888_copy_to_bitmap<false, + SK_NATIVE_A_IDX, SK_NATIVE_R_IDX, + SK_NATIVE_G_IDX, SK_NATIVE_B_IDX>( + dstBmp, + srcPixels, + srcRowBytes); + break; + case SkCanvas::kNative_Unpremul_Config8888: + config8888_copy_to_bitmap<true, + SK_NATIVE_A_IDX, SK_NATIVE_R_IDX, + SK_NATIVE_G_IDX, SK_NATIVE_B_IDX>( + dstBmp, + srcPixels, + srcRowBytes); + break; + case SkCanvas::kBGRA_Premul_Config8888: + config8888_copy_to_bitmap<false, 3, 2, 1, 0> ( + dstBmp, srcPixels, srcRowBytes); + break; + case SkCanvas::kBGRA_Unpremul_Config8888: + config8888_copy_to_bitmap<true, 3, 2, 1, 0> ( + dstBmp, srcPixels, srcRowBytes); + break; + case SkCanvas::kRGBA_Premul_Config8888: + config8888_copy_to_bitmap<false, 3, 0, 1, 2> ( + dstBmp, srcPixels, srcRowBytes); + break; + case SkCanvas::kRGBA_Unpremul_Config8888: + config8888_copy_to_bitmap<true, 3, 0, 1, 2> ( + dstBmp, srcPixels, srcRowBytes); + break; + default: + SkDEBUGFAIL("unexpected Config8888"); + break; + } +} + +inline void SkCopyARGB8888BitmapTo(uint32_t* dstPixels, + size_t dstRowBytes, + const SkBitmap& srcBmp) { + SkASSERT(SkBitmap::kARGB_8888_Config == srcBmp.config()); + + SkAutoLockPixels alp(srcBmp); + + int w = srcBmp.width(); + int h = srcBmp.height(); + size_t srcRowBytes = srcBmp.rowBytes(); + + size_t tightRowBytes = w * 4; + + char* src = reinterpret_cast<char*>(srcBmp.getPixels()); + char* dst = reinterpret_cast<char*>(dstPixels); + + if (tightRowBytes == srcRowBytes && + tightRowBytes == dstRowBytes) { + memcpy(dst, src, tightRowBytes * h); + } else { + for (int y = 0; y < h; ++y) { + memcpy(dst, src, tightRowBytes); + dst += dstRowBytes; + src += srcRowBytes; + } + } +} + +} |