| 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;
|
| +}
|
|
|