diff options
Diffstat (limited to 'src/codec/SkSwizzler.cpp')
-rw-r--r-- | src/codec/SkSwizzler.cpp | 358 |
1 files changed, 210 insertions, 148 deletions
diff --git a/src/codec/SkSwizzler.cpp b/src/codec/SkSwizzler.cpp index b2b7f927ac..44277614c6 100644 --- a/src/codec/SkSwizzler.cpp +++ b/src/codec/SkSwizzler.cpp @@ -7,6 +7,7 @@ #include "SkCodecPriv.h" #include "SkColorPriv.h" +#include "SkScaledCodec.h" #include "SkSwizzler.h" #include "SkTemplates.h" #include "SkUtils.h" @@ -19,114 +20,116 @@ SkSwizzler::ResultAlpha SkSwizzler::GetResult(uint8_t zeroAlpha, return (((uint16_t) maxAlpha) << 8) | zeroAlpha; } +// samples the row. Does not do anything else but sampling +static SkSwizzler::ResultAlpha sample565(void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, + int width, int deltaSrc, int offset, const SkPMColor ctable[]){ + + src += offset; + uint16_t* SK_RESTRICT dst = (uint16_t*) dstRow; + for (int x = 0; x < width; x++) { + dst[x] = src[1] << 8 | src[0]; + src += deltaSrc; + } + // 565 is always opaque + return SkSwizzler::kOpaque_ResultAlpha; +} + // kBit // These routines exclusively choose between white and black #define GRAYSCALE_BLACK 0 #define GRAYSCALE_WHITE 0xFF + +// same as swizzle_bit_to_index and swizzle_bit_to_n32 except for value assigned to dst[x] static SkSwizzler::ResultAlpha swizzle_bit_to_grayscale( - void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width, - int /*bitsPerPixel*/, const SkPMColor* /*ctable*/) { + void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, + int deltaSrc, int offset, const SkPMColor* /*ctable*/) { + uint8_t* SK_RESTRICT dst = (uint8_t*) dstRow; - // Determine how many full bytes are in the row - int bytesInRow = width >> 3; - int i; - for (i = 0; i < bytesInRow; i++) { - U8CPU currByte = src[i]; - for (int j = 0; j < 8; j++) { - dst[j] = ((currByte >> (7 - j)) & 1) ? GRAYSCALE_WHITE : GRAYSCALE_BLACK; - } - dst += 8; - } + // increment src by byte offset and bitIndex by bit offset + src += offset / 8; + int bitIndex = offset % 8; + uint8_t currByte = *src; - // Finish the remaining bits - width &= 7; - if (width > 0) { - U8CPU currByte = src[i]; - for (int j = 0; j < width; j++) { - dst[j] = ((currByte >> 7) & 1) ? GRAYSCALE_WHITE : GRAYSCALE_BLACK; - currByte <<= 1; - } + dst[0] = ((currByte >> (7-bitIndex)) & 1) ? GRAYSCALE_WHITE : GRAYSCALE_BLACK; + + for (int x = 1; x < dstWidth; x++) { + int bitOffset = bitIndex + deltaSrc; + bitIndex = bitOffset % 8; + currByte = *(src += bitOffset / 8); + dst[x] = ((currByte >> (7-bitIndex)) & 1) ? GRAYSCALE_WHITE : GRAYSCALE_BLACK; } + return SkSwizzler::kOpaque_ResultAlpha; } #undef GRAYSCALE_BLACK #undef GRAYSCALE_WHITE +// same as swizzle_bit_to_grayscale and swizzle_bit_to_n32 except for value assigned to dst[x] static SkSwizzler::ResultAlpha swizzle_bit_to_index( - void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width, - int /*bitsPerPixel*/, const SkPMColor* /*ctable*/) { + void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, + int deltaSrc, int offset, const SkPMColor* /*ctable*/) { uint8_t* SK_RESTRICT dst = (uint8_t*) dstRow; - // Determine how many full bytes are in the row - int bytesInRow = width >> 3; - int i; - for (i = 0; i < bytesInRow; i++) { - U8CPU currByte = src[i]; - for (int j = 0; j < 8; j++) { - dst[j] = (currByte >> (7 - j)) & 1; - } - dst += 8; - } + // increment src by byte offset and bitIndex by bit offset + src += offset / 8; + int bitIndex = offset % 8; + uint8_t currByte = *src; - // Finish the remaining bits - width &= 7; - if (width > 0) { - U8CPU currByte = src[i]; - for (int j = 0; j < width; j++) { - dst[j] = ((currByte >> 7) & 1); - currByte <<= 1; - } + dst[0] = ((currByte >> (7-bitIndex)) & 1); + + for (int x = 1; x < dstWidth; x++) { + int bitOffset = bitIndex + deltaSrc; + bitIndex = bitOffset % 8; + currByte = *(src += bitOffset / 8); + dst[x] = ((currByte >> (7-bitIndex)) & 1); } + return SkSwizzler::kOpaque_ResultAlpha; } +// same as swizzle_bit_to_grayscale and swizzle_bit_to_index except for value assigned to dst[x] static SkSwizzler::ResultAlpha swizzle_bit_to_n32( - void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width, - int /*bitsPerPixel*/, const SkPMColor* /*ctable*/) { + void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, + int deltaSrc, int offset, const SkPMColor* /*ctable*/) { SkPMColor* SK_RESTRICT dst = (SkPMColor*) dstRow; - // Determine how many full bytes are in the row - int bytesInRow = width >> 3; - int i; - for (i = 0; i < bytesInRow; i++) { - U8CPU currByte = src[i]; - for (int j = 0; j < 8; j++) { - dst[j] = ((currByte >> (7 - j)) & 1) ? SK_ColorWHITE : SK_ColorBLACK; - } - dst += 8; - } + // increment src by byte offset and bitIndex by bit offset + src += offset / 8; + int bitIndex = offset % 8; + uint8_t currByte = *src; - // Finish the remaining bits - width &= 7; - if (width > 0) { - U8CPU currByte = src[i]; - for (int j = 0; j < width; j++) { - dst[j] = ((currByte >> 7) & 1) ? SK_ColorWHITE : SK_ColorBLACK; - currByte <<= 1; - } + dst[0] = ((currByte >> (7 - bitIndex)) & 1) ? SK_ColorWHITE : SK_ColorBLACK; + + for (int x = 1; x < dstWidth; x++) { + int bitOffset = bitIndex + deltaSrc; + bitIndex = bitOffset % 8; + currByte = *(src += bitOffset / 8); + dst[x] = ((currByte >> (7 - bitIndex)) & 1) ? SK_ColorWHITE : SK_ColorBLACK; } + return SkSwizzler::kOpaque_ResultAlpha; } // kIndex1, kIndex2, kIndex4 static SkSwizzler::ResultAlpha swizzle_small_index_to_index( - void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width, - int bitsPerPixel, const SkPMColor ctable[]) { + void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, + int bitsPerPixel, int offset, const SkPMColor ctable[]) { + src += offset; uint8_t* SK_RESTRICT dst = (uint8_t*) dstRow; INIT_RESULT_ALPHA; const uint32_t pixelsPerByte = 8 / bitsPerPixel; - const size_t rowBytes = compute_row_bytes_ppb(width, pixelsPerByte); + const size_t rowBytes = compute_row_bytes_ppb(dstWidth, pixelsPerByte); const uint8_t mask = (1 << bitsPerPixel) - 1; int x = 0; for (uint32_t byte = 0; byte < rowBytes; byte++) { uint8_t pixelData = src[byte]; - for (uint32_t p = 0; p < pixelsPerByte && x < width; p++) { + for (uint32_t p = 0; p < pixelsPerByte && x < dstWidth; p++) { uint8_t index = (pixelData >> (8 - bitsPerPixel)) & mask; UPDATE_RESULT_ALPHA(ctable[index] >> SK_A32_SHIFT); dst[x] = index; @@ -138,18 +141,19 @@ static SkSwizzler::ResultAlpha swizzle_small_index_to_index( } static SkSwizzler::ResultAlpha swizzle_small_index_to_n32( - void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width, - int bitsPerPixel, const SkPMColor ctable[]) { + void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, + int bitsPerPixel, int offset, const SkPMColor ctable[]) { + src += offset; SkPMColor* SK_RESTRICT dst = (SkPMColor*) dstRow; INIT_RESULT_ALPHA; const uint32_t pixelsPerByte = 8 / bitsPerPixel; - const size_t rowBytes = compute_row_bytes_ppb(width, pixelsPerByte); + const size_t rowBytes = compute_row_bytes_ppb(dstWidth, pixelsPerByte); const uint8_t mask = (1 << bitsPerPixel) - 1; int x = 0; for (uint32_t byte = 0; byte < rowBytes; byte++) { uint8_t pixelData = src[byte]; - for (uint32_t p = 0; p < pixelsPerByte && x < width; p++) { + for (uint32_t p = 0; p < pixelsPerByte && x < dstWidth; p++) { uint8_t index = (pixelData >> (8 - bitsPerPixel)) & mask; SkPMColor c = ctable[index]; UPDATE_RESULT_ALPHA(c >> SK_A32_SHIFT); @@ -164,58 +168,75 @@ static SkSwizzler::ResultAlpha swizzle_small_index_to_n32( // kIndex static SkSwizzler::ResultAlpha swizzle_index_to_index( - void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width, - int bytesPerPixel, const SkPMColor ctable[]) { + void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, + int deltaSrc, int offset, const SkPMColor ctable[]) { + src += offset; uint8_t* SK_RESTRICT dst = (uint8_t*) dstRow; - memcpy(dst, src, width); + INIT_RESULT_ALPHA; // TODO (msarett): Should we skip the loop here and guess that the row is opaque/not opaque? // SkScaledBitmap sampler just guesses that it is opaque. This is dangerous // and probably wrong since gif and bmp (rarely) may have alpha. - INIT_RESULT_ALPHA; - for (int x = 0; x < width; x++) { - UPDATE_RESULT_ALPHA(ctable[src[x]] >> SK_A32_SHIFT); + if (1 == deltaSrc) { + // A non-zero offset is only used when sampling, meaning that deltaSrc will be + // greater than 1. The below loop relies on the fact that src remains unchanged. + SkASSERT(0 == offset); + memcpy(dst, src, dstWidth); + for (int x = 0; x < dstWidth; x++) { + UPDATE_RESULT_ALPHA(ctable[src[x]] >> SK_A32_SHIFT); + } + } else { + for (int x = 0; x < dstWidth; x++) { + dst[x] = *src; + UPDATE_RESULT_ALPHA(ctable[*src] >> SK_A32_SHIFT); + src += deltaSrc; + } } return COMPUTE_RESULT_ALPHA; } static SkSwizzler::ResultAlpha swizzle_index_to_n32( - void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width, - int bytesPerPixel, const SkPMColor ctable[]) { + void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, + int deltaSrc, int offset, const SkPMColor ctable[]) { + src += offset; SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; INIT_RESULT_ALPHA; - for (int x = 0; x < width; x++) { - SkPMColor c = ctable[src[x]]; + for (int x = 0; x < dstWidth; x++) { + SkPMColor c = ctable[*src]; UPDATE_RESULT_ALPHA(c >> SK_A32_SHIFT); dst[x] = c; + src += deltaSrc; } return COMPUTE_RESULT_ALPHA; } static SkSwizzler::ResultAlpha swizzle_index_to_n32_skipZ( - void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width, - int bytesPerPixel, const SkPMColor ctable[]) { + void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, + int deltaSrc, int offset, const SkPMColor ctable[]) { + src += offset; SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; INIT_RESULT_ALPHA; - for (int x = 0; x < width; x++) { - SkPMColor c = ctable[src[x]]; + for (int x = 0; x < dstWidth; x++) { + SkPMColor c = ctable[*src]; UPDATE_RESULT_ALPHA(c >> SK_A32_SHIFT); if (c != 0) { dst[x] = c; } + src += deltaSrc; } return COMPUTE_RESULT_ALPHA; } static SkSwizzler::ResultAlpha swizzle_index_to_565( - void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width, - int bytesPerPixel, const SkPMColor ctable[]) { + void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, + int bytesPerPixel, int offset, const SkPMColor ctable[]) { // FIXME: Support dithering? Requires knowing y, which I think is a bigger // change. + src += offset; uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow; - for (int x = 0; x < width; x++) { + for (int x = 0; x < dstWidth; x++) { dst[x] = SkPixel32ToPixel16(ctable[*src]); src += bytesPerPixel; } @@ -228,29 +249,42 @@ static SkSwizzler::ResultAlpha swizzle_index_to_565( // kGray static SkSwizzler::ResultAlpha swizzle_gray_to_n32( - void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width, - int bytesPerPixel, const SkPMColor ctable[]) { + void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, + int deltaSrc, int offset, const SkPMColor ctable[]) { + src += offset; SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; - for (int x = 0; x < width; x++) { - dst[x] = SkPackARGB32NoCheck(0xFF, src[x], src[x], src[x]); + for (int x = 0; x < dstWidth; x++) { + dst[x] = SkPackARGB32NoCheck(0xFF, *src, *src, *src); + src += deltaSrc; } return SkSwizzler::kOpaque_ResultAlpha; } static SkSwizzler::ResultAlpha swizzle_gray_to_gray( - void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width, - int bytesPerPixel, const SkPMColor ctable[]) { - memcpy(dstRow, src, width); + void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, + int deltaSrc, int offset, const SkPMColor ctable[]) { + + src += offset; + uint8_t* SK_RESTRICT dst = (uint8_t*) dstRow; + if (1 == deltaSrc) { + memcpy(dstRow, src, dstWidth); + } else { + for (int x = 0; x < dstWidth; x++) { + dst[x] = src[0]; + src += deltaSrc; + } + } return SkSwizzler::kOpaque_ResultAlpha; } static SkSwizzler::ResultAlpha swizzle_gray_to_565( - void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width, - int bytesPerPixel, const SkPMColor ctable[]) { + void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, + int bytesPerPixel, int offset, const SkPMColor ctable[]) { // FIXME: Support dithering? + src += offset; uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow; - for (int x = 0; x < width; x++) { + for (int x = 0; x < dstWidth; x++) { dst[x] = SkPack888ToRGB16(src[0], src[0], src[0]); src += bytesPerPixel; } @@ -260,13 +294,14 @@ static SkSwizzler::ResultAlpha swizzle_gray_to_565( // kBGRX static SkSwizzler::ResultAlpha swizzle_bgrx_to_n32( - void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width, - int bytesPerPixel, const SkPMColor ctable[]) { + void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, + int deltaSrc, int offset, const SkPMColor ctable[]) { + src += offset; SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; - for (int x = 0; x < width; x++) { + for (int x = 0; x < dstWidth; x++) { dst[x] = SkPackARGB32NoCheck(0xFF, src[2], src[1], src[0]); - src += bytesPerPixel; + src += deltaSrc; } return SkSwizzler::kOpaque_ResultAlpha; } @@ -274,54 +309,58 @@ static SkSwizzler::ResultAlpha swizzle_bgrx_to_n32( // kBGRA static SkSwizzler::ResultAlpha swizzle_bgra_to_n32_unpremul( - void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width, - int bytesPerPixel, const SkPMColor ctable[]) { + void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, + int deltaSrc, int offset, const SkPMColor ctable[]) { + src += offset; SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; INIT_RESULT_ALPHA; - for (int x = 0; x < width; x++) { + for (int x = 0; x < dstWidth; x++) { uint8_t alpha = src[3]; UPDATE_RESULT_ALPHA(alpha); dst[x] = SkPackARGB32NoCheck(alpha, src[2], src[1], src[0]); - src += bytesPerPixel; + src += deltaSrc; } return COMPUTE_RESULT_ALPHA; } static SkSwizzler::ResultAlpha swizzle_bgra_to_n32_premul( - void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width, - int bytesPerPixel, const SkPMColor ctable[]) { + void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, + int deltaSrc, int offset, const SkPMColor ctable[]) { + src += offset; SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; INIT_RESULT_ALPHA; - for (int x = 0; x < width; x++) { + for (int x = 0; x < dstWidth; x++) { uint8_t alpha = src[3]; UPDATE_RESULT_ALPHA(alpha); dst[x] = SkPreMultiplyARGB(alpha, src[2], src[1], src[0]); - src += bytesPerPixel; + src += deltaSrc; } return COMPUTE_RESULT_ALPHA; } // kRGBX static SkSwizzler::ResultAlpha swizzle_rgbx_to_n32( - void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width, - int bytesPerPixel, const SkPMColor ctable[]) { + void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, + int deltaSrc, int offset, const SkPMColor ctable[]) { + src += offset; SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; - for (int x = 0; x < width; x++) { + for (int x = 0; x < dstWidth; x++) { dst[x] = SkPackARGB32(0xFF, src[0], src[1], src[2]); - src += bytesPerPixel; + src += deltaSrc; } return SkSwizzler::kOpaque_ResultAlpha; } static SkSwizzler::ResultAlpha swizzle_rgbx_to_565( - void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width, - int bytesPerPixel, const SkPMColor ctable[]) { + void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, + int bytesPerPixel, int offset, const SkPMColor ctable[]) { // FIXME: Support dithering? + src += offset; uint16_t* SK_RESTRICT dst = (uint16_t*)dstRow; - for (int x = 0; x < width; x++) { + for (int x = 0; x < dstWidth; x++) { dst[x] = SkPack888ToRGB16(src[0], src[1], src[2]); src += bytesPerPixel; } @@ -331,48 +370,51 @@ static SkSwizzler::ResultAlpha swizzle_rgbx_to_565( // kRGBA static SkSwizzler::ResultAlpha swizzle_rgba_to_n32_premul( - void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width, - int bytesPerPixel, const SkPMColor ctable[]) { + void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, + int deltaSrc, int offset, const SkPMColor ctable[]) { + src += offset; SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; INIT_RESULT_ALPHA; - for (int x = 0; x < width; x++) { + for (int x = 0; x < dstWidth; x++) { unsigned alpha = src[3]; UPDATE_RESULT_ALPHA(alpha); dst[x] = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]); - src += bytesPerPixel; + src += deltaSrc; } return COMPUTE_RESULT_ALPHA; } static SkSwizzler::ResultAlpha swizzle_rgba_to_n32_unpremul( - void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width, - int bytesPerPixel, const SkPMColor ctable[]) { + void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, + int deltaSrc, int offset, const SkPMColor ctable[]) { + src += offset; uint32_t* SK_RESTRICT dst = reinterpret_cast<uint32_t*>(dstRow); INIT_RESULT_ALPHA; - for (int x = 0; x < width; x++) { + for (int x = 0; x < dstWidth; x++) { unsigned alpha = src[3]; UPDATE_RESULT_ALPHA(alpha); dst[x] = SkPackARGB32NoCheck(alpha, src[0], src[1], src[2]); - src += bytesPerPixel; + src += deltaSrc; } return COMPUTE_RESULT_ALPHA; } static SkSwizzler::ResultAlpha swizzle_rgba_to_n32_premul_skipZ( - void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width, - int bytesPerPixel, const SkPMColor ctable[]) { + void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int dstWidth, + int deltaSrc, int offset, const SkPMColor ctable[]) { + src += offset; SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; INIT_RESULT_ALPHA; - for (int x = 0; x < width; x++) { + for (int x = 0; x < dstWidth; x++) { unsigned alpha = src[3]; UPDATE_RESULT_ALPHA(alpha); if (0 != alpha) { dst[x] = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]); } - src += bytesPerPixel; + src += deltaSrc; } return COMPUTE_RESULT_ALPHA; } @@ -385,11 +427,12 @@ static SkSwizzler::ResultAlpha swizzle_rgba_to_n32_premul_skipZ( decide whether to switch to unpremul default. static bool swizzle_rgba_to_n32_unpremul_skipZ(void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, - int width, int bitsPerPixel, + int dstWidth, int bitsPerPixel, int offset, const SkPMColor[]) { + src += offset; SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; unsigned alphaMask = 0xFF; - for (int x = 0; x < width; x++) { + for (int x = 0; x < dstWidth; x++) { unsigned alpha = src[3]; // NOTE: We cheat here. The caller requested unpremul and skip zeroes. It's possible // the color components are not zero, but we skip them anyway, meaning they'll remain @@ -406,9 +449,10 @@ static bool swizzle_rgba_to_n32_unpremul_skipZ(void* SK_RESTRICT dstRow, SkSwizzler* SkSwizzler::CreateSwizzler(SkSwizzler::SrcConfig sc, const SkPMColor* ctable, - const SkImageInfo& info, - SkCodec::ZeroInitialized zeroInit) { - if (info.colorType() == kUnknown_SkColorType || kUnknown == sc) { + const SkImageInfo& dstInfo, + SkCodec::ZeroInitialized zeroInit, + const SkImageInfo& srcInfo) { + if (dstInfo.colorType() == kUnknown_SkColorType || kUnknown == sc) { return NULL; } if ((kIndex == sc || kIndex4 == sc || kIndex2 == sc || kIndex1 == sc) @@ -416,9 +460,10 @@ SkSwizzler* SkSwizzler::CreateSwizzler(SkSwizzler::SrcConfig sc, return NULL; } RowProc proc = NULL; + switch (sc) { case kBit: - switch (info.colorType()) { + switch (dstInfo.colorType()) { case kN32_SkColorType: proc = &swizzle_bit_to_n32; break; @@ -435,7 +480,7 @@ SkSwizzler* SkSwizzler::CreateSwizzler(SkSwizzler::SrcConfig sc, case kIndex1: case kIndex2: case kIndex4: - switch (info.colorType()) { + switch (dstInfo.colorType()) { case kN32_SkColorType: proc = &swizzle_small_index_to_n32; break; @@ -447,7 +492,7 @@ SkSwizzler* SkSwizzler::CreateSwizzler(SkSwizzler::SrcConfig sc, } break; case kIndex: - switch (info.colorType()) { + switch (dstInfo.colorType()) { case kN32_SkColorType: // We assume the color premultiplied ctable (or not) as desired. if (SkCodec::kYes_ZeroInitialized == zeroInit) { @@ -469,7 +514,7 @@ SkSwizzler* SkSwizzler::CreateSwizzler(SkSwizzler::SrcConfig sc, } break; case kGray: - switch (info.colorType()) { + switch (dstInfo.colorType()) { case kN32_SkColorType: proc = &swizzle_gray_to_n32; break; @@ -485,7 +530,7 @@ SkSwizzler* SkSwizzler::CreateSwizzler(SkSwizzler::SrcConfig sc, break; case kBGR: case kBGRX: - switch (info.colorType()) { + switch (dstInfo.colorType()) { case kN32_SkColorType: proc = &swizzle_bgrx_to_n32; break; @@ -494,9 +539,9 @@ SkSwizzler* SkSwizzler::CreateSwizzler(SkSwizzler::SrcConfig sc, } break; case kBGRA: - switch (info.colorType()) { + switch (dstInfo.colorType()) { case kN32_SkColorType: - switch (info.alphaType()) { + switch (dstInfo.alphaType()) { case kUnpremul_SkAlphaType: proc = &swizzle_bgra_to_n32_unpremul; break; @@ -513,7 +558,7 @@ SkSwizzler* SkSwizzler::CreateSwizzler(SkSwizzler::SrcConfig sc, break; case kRGBX: // TODO: Support other swizzles. - switch (info.colorType()) { + switch (dstInfo.colorType()) { case kN32_SkColorType: proc = &swizzle_rgbx_to_n32; break; @@ -524,9 +569,9 @@ SkSwizzler* SkSwizzler::CreateSwizzler(SkSwizzler::SrcConfig sc, } break; case kRGBA: - switch (info.colorType()) { + switch (dstInfo.colorType()) { case kN32_SkColorType: - if (info.alphaType() == kUnpremul_SkAlphaType) { + if (dstInfo.alphaType() == kUnpremul_SkAlphaType) { // Respect zeroInit? proc = &swizzle_rgba_to_n32_unpremul; } else { @@ -542,7 +587,7 @@ SkSwizzler* SkSwizzler::CreateSwizzler(SkSwizzler::SrcConfig sc, } break; case kRGB: - switch (info.colorType()) { + switch (dstInfo.colorType()) { case kN32_SkColorType: proc = &swizzle_rgbx_to_n32; break; @@ -550,6 +595,14 @@ SkSwizzler* SkSwizzler::CreateSwizzler(SkSwizzler::SrcConfig sc, break; } break; + case kRGB_565: + switch (dstInfo.colorType()) { + case kRGB_565_SkColorType: + proc = &sample565; + break; + default: + break; + } default: break; } @@ -558,22 +611,31 @@ SkSwizzler* SkSwizzler::CreateSwizzler(SkSwizzler::SrcConfig sc, } // Store deltaSrc in bytes if it is an even multiple, otherwise use bits - int deltaSrc = SkIsAlign8(BitsPerPixel(sc)) ? BytesPerPixel(sc) : - BitsPerPixel(sc); - return SkNEW_ARGS(SkSwizzler, (proc, ctable, deltaSrc, info)); + int deltaSrc = SkIsAlign8(BitsPerPixel(sc)) ? BytesPerPixel(sc) : BitsPerPixel(sc); + + // get sampleX based on srcInfo and dstInfo dimensions + int sampleX; + SkScaledCodec::ComputeSampleSize(dstInfo, srcInfo, &sampleX, NULL); + + return SkNEW_ARGS(SkSwizzler, (proc, ctable, deltaSrc, dstInfo, sampleX)); } SkSwizzler::SkSwizzler(RowProc proc, const SkPMColor* ctable, - int deltaSrc, const SkImageInfo& info) + int deltaSrc, const SkImageInfo& info, int sampleX) : fRowProc(proc) , fColorTable(ctable) , fDeltaSrc(deltaSrc) , fDstInfo(info) -{} + , fSampleX(sampleX) + , fX0(sampleX == 1 ? 0 : sampleX >> 1) +{ + // check that fX0 is less than original width + SkASSERT(fX0 >= 0 && fX0 < fDstInfo.width() * fSampleX); +} SkSwizzler::ResultAlpha SkSwizzler::swizzle(void* dst, const uint8_t* SK_RESTRICT src) { SkASSERT(NULL != dst && NULL != src); - return fRowProc(dst, src, fDstInfo.width(), fDeltaSrc, fColorTable); + return fRowProc(dst, src, fDstInfo.width(), fSampleX * fDeltaSrc, fX0 * fDeltaSrc, fColorTable); } void SkSwizzler::Fill(void* dstStartRow, const SkImageInfo& dstInfo, size_t dstRowBytes, |