/* * 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 "SkCodecPriv.h" #include "SkColorPriv.h" #include "SkMaskSwizzler.h" static SkSwizzler::ResultAlpha swizzle_mask16_to_n32_opaque( void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks) { // Use the masks to decode to the destination uint16_t* srcPtr = (uint16_t*) srcRow; SkPMColor* dstPtr = (SkPMColor*) dstRow; for (int i = 0; i < width; i++) { uint16_t p = srcPtr[i]; uint8_t red = masks->getRed(p); uint8_t green = masks->getGreen(p); uint8_t blue = masks->getBlue(p); dstPtr[i] = SkPackARGB32NoCheck(0xFF, red, green, blue); } return SkSwizzler::kOpaque_ResultAlpha; } static SkSwizzler::ResultAlpha swizzle_mask16_to_n32_unpremul( void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks) { // Use the masks to decode to the destination uint16_t* srcPtr = (uint16_t*) srcRow; SkPMColor* dstPtr = (SkPMColor*) dstRow; INIT_RESULT_ALPHA; for (int i = 0; i < width; i++) { uint16_t p = srcPtr[i]; uint8_t red = masks->getRed(p); uint8_t green = masks->getGreen(p); uint8_t blue = masks->getBlue(p); uint8_t alpha = masks->getAlpha(p); UPDATE_RESULT_ALPHA(alpha); dstPtr[i] = SkPackARGB32NoCheck(alpha, red, green, blue); } return COMPUTE_RESULT_ALPHA; } static SkSwizzler::ResultAlpha swizzle_mask16_to_n32_premul( void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks) { // Use the masks to decode to the destination uint16_t* srcPtr = (uint16_t*) srcRow; SkPMColor* dstPtr = (SkPMColor*) dstRow; INIT_RESULT_ALPHA; for (int i = 0; i < width; i++) { uint16_t p = srcPtr[i]; uint8_t red = masks->getRed(p); uint8_t green = masks->getGreen(p); uint8_t blue = masks->getBlue(p); uint8_t alpha = masks->getAlpha(p); UPDATE_RESULT_ALPHA(alpha); dstPtr[i] = SkPreMultiplyARGB(alpha, red, green, blue); } return COMPUTE_RESULT_ALPHA; } static SkSwizzler::ResultAlpha swizzle_mask24_to_n32_opaque( void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks) { // Use the masks to decode to the destination SkPMColor* dstPtr = (SkPMColor*) dstRow; for (int i = 0; i < 3*width; i += 3) { uint32_t p = srcRow[i] | (srcRow[i + 1] << 8) | srcRow[i + 2] << 16; uint8_t red = masks->getRed(p); uint8_t green = masks->getGreen(p); uint8_t blue = masks->getBlue(p); dstPtr[i/3] = SkPackARGB32NoCheck(0xFF, red, green, blue); } return SkSwizzler::kOpaque_ResultAlpha; } static SkSwizzler::ResultAlpha swizzle_mask24_to_n32_unpremul( void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks) { // Use the masks to decode to the destination SkPMColor* dstPtr = (SkPMColor*) dstRow; INIT_RESULT_ALPHA; for (int i = 0; i < 3*width; i += 3) { uint32_t p = srcRow[i] | (srcRow[i + 1] << 8) | srcRow[i + 2] << 16; uint8_t red = masks->getRed(p); uint8_t green = masks->getGreen(p); uint8_t blue = masks->getBlue(p); uint8_t alpha = masks->getAlpha(p); UPDATE_RESULT_ALPHA(alpha); dstPtr[i/3] = SkPackARGB32NoCheck(alpha, red, green, blue); } return COMPUTE_RESULT_ALPHA; } static SkSwizzler::ResultAlpha swizzle_mask24_to_n32_premul( void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks) { // Use the masks to decode to the destination SkPMColor* dstPtr = (SkPMColor*) dstRow; INIT_RESULT_ALPHA; for (int i = 0; i < 3*width; i += 3) { uint32_t p = srcRow[i] | (srcRow[i + 1] << 8) | srcRow[i + 2] << 16; uint8_t red = masks->getRed(p); uint8_t green = masks->getGreen(p); uint8_t blue = masks->getBlue(p); uint8_t alpha = masks->getAlpha(p); UPDATE_RESULT_ALPHA(alpha); dstPtr[i/3] = SkPreMultiplyARGB(alpha, red, green, blue); } return COMPUTE_RESULT_ALPHA; } static SkSwizzler::ResultAlpha swizzle_mask32_to_n32_opaque( void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks) { // Use the masks to decode to the destination uint32_t* srcPtr = (uint32_t*) srcRow; SkPMColor* dstPtr = (SkPMColor*) dstRow; for (int i = 0; i < width; i++) { uint32_t p = srcPtr[i]; uint8_t red = masks->getRed(p); uint8_t green = masks->getGreen(p); uint8_t blue = masks->getBlue(p); dstPtr[i] = SkPackARGB32NoCheck(0xFF, red, green, blue); } return SkSwizzler::kOpaque_ResultAlpha; } static SkSwizzler::ResultAlpha swizzle_mask32_to_n32_unpremul( void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks) { // Use the masks to decode to the destination uint32_t* srcPtr = (uint32_t*) srcRow; SkPMColor* dstPtr = (SkPMColor*) dstRow; INIT_RESULT_ALPHA; for (int i = 0; i < width; i++) { uint32_t p = srcPtr[i]; uint8_t red = masks->getRed(p); uint8_t green = masks->getGreen(p); uint8_t blue = masks->getBlue(p); uint8_t alpha = masks->getAlpha(p); UPDATE_RESULT_ALPHA(alpha); dstPtr[i] = SkPackARGB32NoCheck(alpha, red, green, blue); } return COMPUTE_RESULT_ALPHA; } static SkSwizzler::ResultAlpha swizzle_mask32_to_n32_premul( void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks) { // Use the masks to decode to the destination uint32_t* srcPtr = (uint32_t*) srcRow; SkPMColor* dstPtr = (SkPMColor*) dstRow; INIT_RESULT_ALPHA; for (int i = 0; i < width; i++) { uint32_t p = srcPtr[i]; uint8_t red = masks->getRed(p); uint8_t green = masks->getGreen(p); uint8_t blue = masks->getBlue(p); uint8_t alpha = masks->getAlpha(p); UPDATE_RESULT_ALPHA(alpha); dstPtr[i] = SkPreMultiplyARGB(alpha, red, green, blue); } return COMPUTE_RESULT_ALPHA; } /* * * Create a new mask swizzler * */ SkMaskSwizzler* SkMaskSwizzler::CreateMaskSwizzler( const SkImageInfo& info, void* dst, size_t dstRowBytes, SkMasks* masks, uint32_t bitsPerPixel) { // Choose the appropriate row procedure RowProc proc = NULL; switch (bitsPerPixel) { case 16: switch (info.colorType()) { case kN32_SkColorType: switch (info.alphaType()) { case kUnpremul_SkAlphaType: proc = &swizzle_mask16_to_n32_unpremul; break; case kPremul_SkAlphaType: proc = &swizzle_mask16_to_n32_premul; break; case kOpaque_SkAlphaType: proc = &swizzle_mask16_to_n32_opaque; break; default: break; } break; default: break; } break; case 24: switch (info.colorType()) { case kN32_SkColorType: switch (info.alphaType()) { case kUnpremul_SkAlphaType: proc = &swizzle_mask24_to_n32_unpremul; break; case kPremul_SkAlphaType: proc = &swizzle_mask24_to_n32_premul; break; case kOpaque_SkAlphaType: proc = &swizzle_mask24_to_n32_opaque; break; default: break; } break; default: break; } break; case 32: switch (info.colorType()) { case kN32_SkColorType: switch (info.alphaType()) { case kUnpremul_SkAlphaType: proc = &swizzle_mask32_to_n32_unpremul; break; case kPremul_SkAlphaType: proc = &swizzle_mask32_to_n32_premul; break; case kOpaque_SkAlphaType: proc = &swizzle_mask32_to_n32_opaque; break; default: break; } break; default: break; } break; default: SkASSERT(false); return NULL; } return SkNEW_ARGS(SkMaskSwizzler, (info, dst, dstRowBytes, masks, proc)); } /* * * Constructor for mask swizzler * */ SkMaskSwizzler::SkMaskSwizzler(const SkImageInfo& dstInfo, void* dst, size_t dstRowBytes, SkMasks* masks, RowProc proc) : fDstInfo(dstInfo) , fDst(dst) , fDstRowBytes(dstRowBytes) , fMasks(masks) , fRowProc(proc) {} /* * * Swizzle the specified row * */ SkSwizzler::ResultAlpha SkMaskSwizzler::next(const uint8_t* SK_RESTRICT src, int y) { // Choose the row void* row = SkTAddOffset(fDst, y*fDstRowBytes); // Decode the row return fRowProc(row, src, fDstInfo.width(), fMasks); }