Index: src/codec/SkSwizzler.cpp |
diff --git a/src/codec/SkSwizzler.cpp b/src/codec/SkSwizzler.cpp |
index 563933f13a03c16e880c2b8132c7df3657fc4868..782fb2877b59948019c31e1e257365126043e99a 100644 |
--- a/src/codec/SkSwizzler.cpp |
+++ b/src/codec/SkSwizzler.cpp |
@@ -9,101 +9,178 @@ |
#include "SkSwizzler.h" |
#include "SkTemplates.h" |
-// index |
- |
#define A32_MASK_IN_PLACE (SkPMColor)(SK_A32_MASK << SK_A32_SHIFT) |
-static bool swizzle_index_to_n32(void* SK_RESTRICT dstRow, |
- const uint8_t* SK_RESTRICT src, |
- int width, int deltaSrc, int, const SkPMColor ctable[]) { |
+// kIndex1, kIndex2, kIndex4 |
+ |
+static SkSwizzler::ResultAlpha swizzle_small_index_to_n32( |
+ void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width, |
+ int bitsPerPixel, int y, const SkPMColor ctable[]) { |
+ |
+ SkPMColor* SK_RESTRICT dst = (SkPMColor*) dstRow; |
+ SkPMColor maxAlpha = A32_MASK_IN_PLACE; |
+ SkPMColor zeroAlpha = 0; |
+ const uint32_t pixelsPerByte = 8 / bitsPerPixel; |
+ const uint32_t rowBytes = (width + pixelsPerByte - 1) / 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++) { |
+ uint8_t index = (pixelData >> (8 - bitsPerPixel)) & mask; |
+ SkPMColor c = ctable[index]; |
+ dst[x] = c; |
+ maxAlpha &= c; |
+ zeroAlpha |= c & A32_MASK_IN_PLACE; |
+ pixelData <<= bitsPerPixel; |
+ x++; |
+ } |
+ } |
+ return SkSwizzler::GetResult(zeroAlpha, maxAlpha >> SK_A32_SHIFT); |
+} |
+ |
+// kIndex |
+ |
+static SkSwizzler::ResultAlpha swizzle_index_to_n32( |
+ void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width, |
+ int bitsPerPixel, int y, const SkPMColor ctable[]) { |
SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; |
- SkPMColor cc = A32_MASK_IN_PLACE; |
+ SkPMColor maxAlpha = A32_MASK_IN_PLACE; |
+ SkPMColor zeroAlpha = 0; |
for (int x = 0; x < width; x++) { |
SkPMColor c = ctable[*src]; |
- cc &= c; |
+ maxAlpha &= c; |
+ zeroAlpha |= c & A32_MASK_IN_PLACE; |
dst[x] = c; |
- src += deltaSrc; |
+ src++; |
} |
- return cc != A32_MASK_IN_PLACE; |
+ return SkSwizzler::GetResult(zeroAlpha, maxAlpha >> SK_A32_SHIFT); |
} |
-static bool swizzle_index_to_n32_skipZ(void* SK_RESTRICT dstRow, |
- const uint8_t* SK_RESTRICT src, |
- int width, int deltaSrc, int, |
- const SkPMColor ctable[]) { |
+static SkSwizzler::ResultAlpha swizzle_index_to_n32_skipZ( |
+ void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width, |
+ int bitsPerPixel, int y, const SkPMColor ctable[]) { |
SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; |
- SkPMColor cc = A32_MASK_IN_PLACE; |
+ SkPMColor maxAlpha = A32_MASK_IN_PLACE; |
+ SkPMColor zeroAlpha = 0; |
for (int x = 0; x < width; x++) { |
SkPMColor c = ctable[*src]; |
- cc &= c; |
+ maxAlpha &= c; |
+ zeroAlpha |= c & A32_MASK_IN_PLACE; |
if (c != 0) { |
dst[x] = c; |
} |
- src += deltaSrc; |
+ src++; |
} |
- return cc != A32_MASK_IN_PLACE; |
+ return SkSwizzler::GetResult(zeroAlpha, maxAlpha); |
} |
#undef A32_MASK_IN_PLACE |
+static SkSwizzler::ResultAlpha swizzle_bgrx_to_n32( |
+ void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width, |
+ int bitsPerPixel, int y, const SkPMColor ctable[]) { |
+ |
+ SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; |
+ int deltaSrc = bitsPerPixel / 8; |
+ for (int x = 0; x < width; x++) { |
+ dst[x] = SkPackARGB32NoCheck(0xFF, src[2], src[1], src[0]); |
+ src += deltaSrc; |
+ } |
+ return SkSwizzler::kOpaque_ResultAlpha; |
+} |
+ |
+// kBGRA |
+ |
+static SkSwizzler::ResultAlpha swizzle_bgra_to_n32( |
+ void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width, |
+ int bitsPerPixel, int y, const SkPMColor ctable[]) { |
+ |
+ SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; |
+ uint8_t maxAlpha = 0xFF; |
+ uint8_t zeroAlpha = 0; |
+ int deltaSrc = bitsPerPixel / 8; |
+ for (int x = 0; x < width; x++) { |
+ uint8_t alpha = src[3]; |
+ maxAlpha &= alpha; |
+ zeroAlpha |= alpha; |
+ dst[x] = SkPackARGB32NoCheck(alpha, src[2], src[1], src[0]); |
+ src += deltaSrc; |
+ } |
+ return SkSwizzler::GetResult(zeroAlpha, maxAlpha); |
+} |
+ |
// n32 |
-static bool swizzle_rgbx_to_n32(void* SK_RESTRICT dstRow, |
- const uint8_t* SK_RESTRICT src, |
- int width, int deltaSrc, int, const SkPMColor[]) { |
+static SkSwizzler::ResultAlpha swizzle_rgbx_to_n32( |
+ void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width, |
+ int bitsPerPixel, int y, const SkPMColor ctable[]) { |
+ |
SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; |
+ int deltaSrc = bitsPerPixel / 8; |
for (int x = 0; x < width; x++) { |
dst[x] = SkPackARGB32(0xFF, src[0], src[1], src[2]); |
src += deltaSrc; |
} |
- return false; |
+ return SkSwizzler::kOpaque_ResultAlpha; |
} |
-static bool swizzle_rgba_to_n32_premul(void* SK_RESTRICT dstRow, |
- const uint8_t* SK_RESTRICT src, |
- int width, int deltaSrc, int, const SkPMColor[]) { |
+static SkSwizzler::ResultAlpha swizzle_rgba_to_n32_premul( |
+ void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width, |
+ int bitsPerPixel, int y, const SkPMColor ctable[]) { |
+ |
SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; |
- unsigned alphaMask = 0xFF; |
+ int deltaSrc = bitsPerPixel / 8; |
+ uint8_t maxAlpha = 0xFF; |
+ uint8_t zeroAlpha = 0; |
for (int x = 0; x < width; x++) { |
unsigned alpha = src[3]; |
dst[x] = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]); |
src += deltaSrc; |
- alphaMask &= alpha; |
+ maxAlpha &= alpha; |
+ zeroAlpha |= alpha; |
} |
- return alphaMask != 0xFF; |
+ return SkSwizzler::GetResult(zeroAlpha, maxAlpha); |
} |
-static bool swizzle_rgba_to_n32_unpremul(void* SK_RESTRICT dstRow, |
- const uint8_t* SK_RESTRICT src, |
- int width, int deltaSrc, int, |
- const SkPMColor[]) { |
+static SkSwizzler::ResultAlpha swizzle_rgba_to_n32_unpremul( |
+ void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width, |
+ int bitsPerPixel, int y, const SkPMColor ctable[]) { |
+ |
uint32_t* SK_RESTRICT dst = reinterpret_cast<uint32_t*>(dstRow); |
- unsigned alphaMask = 0xFF; |
+ int deltaSrc = bitsPerPixel / 8; |
+ uint8_t maxAlpha = 0xFF; |
+ uint8_t zeroAlpha = 0; |
for (int x = 0; x < width; x++) { |
unsigned alpha = src[3]; |
dst[x] = SkPackARGB32NoCheck(alpha, src[0], src[1], src[2]); |
src += deltaSrc; |
- alphaMask &= alpha; |
+ maxAlpha &= alpha; |
+ zeroAlpha |= alpha; |
} |
- return alphaMask != 0xFF; |
+ return SkSwizzler::GetResult(zeroAlpha, maxAlpha); |
} |
-static bool swizzle_rgba_to_n32_premul_skipZ(void* SK_RESTRICT dstRow, |
- const uint8_t* SK_RESTRICT src, |
- int width, int deltaSrc, int, |
- const SkPMColor[]) { |
+static SkSwizzler::ResultAlpha swizzle_rgba_to_n32_premul_skipZ( |
+ void* SK_RESTRICT dstRow, const uint8_t* SK_RESTRICT src, int width, |
+ int bitsPerPixel, int y, const SkPMColor ctable[]) { |
+ |
SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; |
- unsigned alphaMask = 0xFF; |
+ int deltaSrc = bitsPerPixel / 8; |
+ uint8_t maxAlpha = 0xFF; |
+ uint8_t zeroAlpha = 0; |
for (int x = 0; x < width; x++) { |
unsigned alpha = src[3]; |
if (0 != alpha) { |
dst[x] = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]); |
} |
src += deltaSrc; |
- alphaMask &= alpha; |
+ maxAlpha &= alpha; |
+ zeroAlpha |= alpha; |
} |
- return alphaMask != 0xFF; |
+ return SkSwizzler::GetResult(zeroAlpha, maxAlpha); |
} |
/** |
@@ -114,7 +191,7 @@ static bool swizzle_rgba_to_n32_premul_skipZ(void* SK_RESTRICT dstRow, |
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 deltaSrc, int, |
+ int width, int bitsPerPixel, |
const SkPMColor[]) { |
SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; |
unsigned alphaMask = 0xFF; |
@@ -133,31 +210,68 @@ static bool swizzle_rgba_to_n32_unpremul_skipZ(void* SK_RESTRICT dstRow, |
} |
*/ |
-SkSwizzler* SkSwizzler::CreateSwizzler(SkSwizzler::SrcConfig sc, const SkPMColor* ctable, |
+SkSwizzler::ResultAlpha SkSwizzler::GetResult(uint8_t zeroAlpha, |
+ uint8_t maxAlpha) { |
+ return (maxAlpha == 0xFF) ? SkSwizzler::kOpaque_ResultAlpha : |
+ ((zeroAlpha == 0) ? SkSwizzler::kTransparent_ResultAlpha : |
+ SkSwizzler::kNeither_ResultAlpha); |
+} |
+ |
+SkSwizzler* SkSwizzler::CreateSwizzler(SkSwizzler::SrcConfig sc, |
+ const SkPMColor* ctable, |
const SkImageInfo& info, void* dst, |
size_t dstRowBytes, bool skipZeroes) { |
- if (info.colorType() == kUnknown_SkColorType) { |
+ if (kUnknown_SkColorType == info.colorType()) { |
return NULL; |
} |
if (info.minRowBytes() > dstRowBytes) { |
return NULL; |
} |
- if (kIndex == sc && NULL == ctable) { |
+ if ((kIndex == sc || kIndex4 == sc || kIndex2 == sc || kIndex1 == sc) |
+ && NULL == ctable) { |
return NULL; |
} |
RowProc proc = NULL; |
switch (sc) { |
+ case kIndex1: |
+ case kIndex2: |
+ case kIndex4: |
+ switch (info.colorType()) { |
+ case kN32_SkColorType: |
+ proc = &swizzle_small_index_to_n32; |
+ break; |
+ default: |
+ break; |
+ } |
+ break; |
case kIndex: |
switch (info.colorType()) { |
case kN32_SkColorType: |
- // We assume the color premultiplied ctable (or not) as desired. |
if (skipZeroes) { |
- proc = &swizzle_index_to_n32_skipZ; |
- } else { |
proc = &swizzle_index_to_n32; |
+ } else { |
+ proc = &swizzle_index_to_n32_skipZ; |
} |
break; |
- |
+ default: |
+ break; |
+ } |
+ break; |
+ case kBGR: |
+ case kBGRX: |
+ switch (info.colorType()) { |
+ case kN32_SkColorType: |
+ proc = &swizzle_bgrx_to_n32; |
+ break; |
+ default: |
+ break; |
+ } |
+ break; |
+ case kBGRA: |
+ switch (info.colorType()) { |
+ case kN32_SkColorType: |
+ proc = &swizzle_bgra_to_n32; |
+ break; |
default: |
break; |
} |
@@ -190,32 +304,63 @@ SkSwizzler* SkSwizzler::CreateSwizzler(SkSwizzler::SrcConfig sc, const SkPMColor |
break; |
} |
break; |
+ case kRGB: |
+ switch (info.colorType()) { |
+ case kN32_SkColorType: |
+ proc = &swizzle_rgbx_to_n32; |
+ break; |
+ default: |
+ break; |
+ } |
+ break; |
default: |
break; |
} |
if (NULL == proc) { |
return NULL; |
} |
- return SkNEW_ARGS(SkSwizzler, (proc, ctable, BytesPerPixel(sc), info, dst, dstRowBytes)); |
+ return SkNEW_ARGS(SkSwizzler, (proc, ctable, BitsPerPixel(sc), info, dst, |
+ dstRowBytes)); |
} |
-SkSwizzler::SkSwizzler(RowProc proc, const SkPMColor* ctable, int srcBpp, |
- const SkImageInfo& info, void* dst, size_t rowBytes) |
+SkSwizzler::SkSwizzler(RowProc proc, const SkPMColor* ctable, |
+ int srcBitsPerPixel, const SkImageInfo& info, void* dst, |
+ size_t rowBytes) |
: fRowProc(proc) |
, fColorTable(ctable) |
- , fSrcPixelSize(srcBpp) |
+ , fSrcBitsPerPixel(srcBitsPerPixel) |
, fDstInfo(info) |
, fDstRow(dst) |
, fDstRowBytes(rowBytes) |
, fCurrY(0) |
{ |
+ SkDEBUGCODE(fSwizzleMode = kUninitialized_SwizzleMode); |
} |
-bool SkSwizzler::next(const uint8_t* SK_RESTRICT src) { |
- SkASSERT(fCurrY < fDstInfo.height()); |
- const bool hadAlpha = fRowProc(fDstRow, src, fDstInfo.width(), fSrcPixelSize, |
- fCurrY, fColorTable); |
- fCurrY++; |
+SkSwizzler::ResultAlpha SkSwizzler::next(const uint8_t* SK_RESTRICT src) { |
+ SkASSERT(0 <= fCurrY && fCurrY < fDstInfo.height()); |
+ SkASSERT(kDesignateRow_SwizzleMode != fSwizzleMode); |
+ SkDEBUGCODE(fSwizzleMode = kConsecutive_SwizzleMode); |
+ |
+ // Decode a row |
+ const ResultAlpha result = fRowProc(fDstRow, src, fDstInfo.width(), |
+ fSrcBitsPerPixel, fCurrY, fColorTable); |
+ |
+ // Move to the next row and return the result |
fDstRow = SkTAddOffset<void>(fDstRow, fDstRowBytes); |
- return hadAlpha; |
+ return result; |
+} |
+ |
+SkSwizzler::ResultAlpha SkSwizzler::next(const uint8_t* SK_RESTRICT src, |
+ int y) { |
+ SkASSERT(0 <= y && y < fDstInfo.height()); |
+ SkASSERT(kConsecutive_SwizzleMode != fSwizzleMode); |
+ SkDEBUGCODE(fSwizzleMode = kDesignateRow_SwizzleMode); |
+ |
+ // Choose the row |
+ void* row = SkTAddOffset<void>(fDstRow, y*fDstRowBytes); |
+ |
+ // Decode the row |
+ return fRowProc(row, src, fDstInfo.width(), fSrcBitsPerPixel, fCurrY, |
+ fColorTable); |
} |