Index: src/codec/SkSwizzler.cpp |
diff --git a/src/codec/SkSwizzler.cpp b/src/codec/SkSwizzler.cpp |
new file mode 100644 |
index 0000000000000000000000000000000000000000..563933f13a03c16e880c2b8132c7df3657fc4868 |
--- /dev/null |
+++ b/src/codec/SkSwizzler.cpp |
@@ -0,0 +1,221 @@ |
+/* |
+ * Copyright 2015 Google Inc. |
+ * |
+ * Use of this source code is governed by a BSD-style license that can be |
+ * found in the LICENSE file. |
+ */ |
+ |
+#include "SkColorPriv.h" |
+#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[]) { |
+ |
+ SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; |
+ SkPMColor cc = A32_MASK_IN_PLACE; |
+ for (int x = 0; x < width; x++) { |
+ SkPMColor c = ctable[*src]; |
+ cc &= c; |
+ dst[x] = c; |
+ src += deltaSrc; |
+ } |
+ return cc != A32_MASK_IN_PLACE; |
+} |
+ |
+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[]) { |
+ |
+ SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; |
+ SkPMColor cc = A32_MASK_IN_PLACE; |
+ for (int x = 0; x < width; x++) { |
+ SkPMColor c = ctable[*src]; |
+ cc &= c; |
+ if (c != 0) { |
+ dst[x] = c; |
+ } |
+ src += deltaSrc; |
+ } |
+ return cc != A32_MASK_IN_PLACE; |
+} |
+ |
+#undef A32_MASK_IN_PLACE |
+ |
+// n32 |
+static bool swizzle_rgbx_to_n32(void* SK_RESTRICT dstRow, |
+ const uint8_t* SK_RESTRICT src, |
+ int width, int deltaSrc, int, const SkPMColor[]) { |
+ SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; |
+ for (int x = 0; x < width; x++) { |
+ dst[x] = SkPackARGB32(0xFF, src[0], src[1], src[2]); |
+ src += deltaSrc; |
+ } |
+ return false; |
+} |
+ |
+static bool swizzle_rgba_to_n32_premul(void* SK_RESTRICT dstRow, |
+ const uint8_t* SK_RESTRICT src, |
+ int width, int deltaSrc, int, const SkPMColor[]) { |
+ SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; |
+ unsigned alphaMask = 0xFF; |
+ 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; |
+ } |
+ return alphaMask != 0xFF; |
+} |
+ |
+static bool swizzle_rgba_to_n32_unpremul(void* SK_RESTRICT dstRow, |
+ const uint8_t* SK_RESTRICT src, |
+ int width, int deltaSrc, int, |
+ const SkPMColor[]) { |
+ uint32_t* SK_RESTRICT dst = reinterpret_cast<uint32_t*>(dstRow); |
+ unsigned alphaMask = 0xFF; |
+ 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; |
+ } |
+ return alphaMask != 0xFF; |
+} |
+ |
+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[]) { |
+ SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; |
+ unsigned alphaMask = 0xFF; |
+ 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; |
+ } |
+ return alphaMask != 0xFF; |
+} |
+ |
+/** |
+ FIXME: This was my idea to cheat in order to continue taking advantage of skipping zeroes. |
+ This would be fine for drawing normally, but not for drawing with transfer modes. Being |
+ honest means we can draw correctly with transfer modes, with the cost of not being able |
+ to take advantage of Android's free unwritten pages. Something to keep in mind when we |
+ 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, |
+ const SkPMColor[]) { |
+ SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; |
+ unsigned alphaMask = 0xFF; |
+ for (int x = 0; x < width; 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 |
+ // zero (implied by the request to skip zeroes). |
+ if (0 != alpha) { |
+ dst[x] = SkPackARGB32NoCheck(alpha, src[0], src[1], src[2]); |
+ } |
+ src += deltaSrc; |
+ alphaMask &= alpha; |
+ } |
+ return alphaMask != 0xFF; |
+} |
+*/ |
+ |
+SkSwizzler* SkSwizzler::CreateSwizzler(SkSwizzler::SrcConfig sc, const SkPMColor* ctable, |
+ const SkImageInfo& info, void* dst, |
+ size_t dstRowBytes, bool skipZeroes) { |
+ if (info.colorType() == kUnknown_SkColorType) { |
+ return NULL; |
+ } |
+ if (info.minRowBytes() > dstRowBytes) { |
+ return NULL; |
+ } |
+ if (kIndex == sc && NULL == ctable) { |
+ return NULL; |
+ } |
+ RowProc proc = NULL; |
+ switch (sc) { |
+ 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; |
+ } |
+ break; |
+ |
+ default: |
+ break; |
+ } |
+ break; |
+ case kRGBX: |
+ // TODO: Support other swizzles. |
+ switch (info.colorType()) { |
+ case kN32_SkColorType: |
+ proc = &swizzle_rgbx_to_n32; |
+ break; |
+ default: |
+ break; |
+ } |
+ break; |
+ case kRGBA: |
+ switch (info.colorType()) { |
+ case kN32_SkColorType: |
+ if (info.alphaType() == kUnpremul_SkAlphaType) { |
+ // Respect skipZeroes? |
+ proc = &swizzle_rgba_to_n32_unpremul; |
+ } else { |
+ if (skipZeroes) { |
+ proc = &swizzle_rgba_to_n32_premul_skipZ; |
+ } else { |
+ proc = &swizzle_rgba_to_n32_premul; |
+ } |
+ } |
+ break; |
+ default: |
+ break; |
+ } |
+ break; |
+ default: |
+ break; |
+ } |
+ if (NULL == proc) { |
+ return NULL; |
+ } |
+ return SkNEW_ARGS(SkSwizzler, (proc, ctable, BytesPerPixel(sc), info, dst, dstRowBytes)); |
+} |
+ |
+SkSwizzler::SkSwizzler(RowProc proc, const SkPMColor* ctable, int srcBpp, |
+ const SkImageInfo& info, void* dst, size_t rowBytes) |
+ : fRowProc(proc) |
+ , fColorTable(ctable) |
+ , fSrcPixelSize(srcBpp) |
+ , fDstInfo(info) |
+ , fDstRow(dst) |
+ , fDstRowBytes(rowBytes) |
+ , fCurrY(0) |
+{ |
+} |
+ |
+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++; |
+ fDstRow = SkTAddOffset<void>(fDstRow, fDstRowBytes); |
+ return hadAlpha; |
+} |