| /* |
| * 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" |
| #include "SkScaledCodec.h" |
| |
| static SkSwizzler::ResultAlpha swizzle_mask16_to_n32_opaque( |
| void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks, |
| uint32_t startX, uint32_t sampleX) { |
| |
| // Use the masks to decode to the destination |
| uint16_t* srcPtr = ((uint16_t*) srcRow) + startX; |
| SkPMColor* dstPtr = (SkPMColor*) dstRow; |
| for (int i = 0; i < width; i++) { |
| uint16_t p = srcPtr[0]; |
| 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); |
| srcPtr += sampleX; |
| } |
| return SkSwizzler::kOpaque_ResultAlpha; |
| } |
| |
| static SkSwizzler::ResultAlpha swizzle_mask16_to_n32_unpremul( |
| void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks, |
| uint32_t startX, uint32_t sampleX) { |
| |
| // Use the masks to decode to the destination |
| uint16_t* srcPtr = ((uint16_t*) srcRow) + startX; |
| SkPMColor* dstPtr = (SkPMColor*) dstRow; |
| INIT_RESULT_ALPHA; |
| for (int i = 0; i < width; i++) { |
| uint16_t p = srcPtr[0]; |
| 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); |
| srcPtr += sampleX; |
| } |
| return COMPUTE_RESULT_ALPHA; |
| } |
| |
| static SkSwizzler::ResultAlpha swizzle_mask16_to_n32_premul( |
| void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks, |
| uint32_t startX, uint32_t sampleX) { |
| |
| // Use the masks to decode to the destination |
| uint16_t* srcPtr = ((uint16_t*) srcRow) + startX; |
| SkPMColor* dstPtr = (SkPMColor*) dstRow; |
| INIT_RESULT_ALPHA; |
| for (int i = 0; i < width; i++) { |
| uint16_t p = srcPtr[0]; |
| 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); |
| srcPtr += sampleX; |
| } |
| return COMPUTE_RESULT_ALPHA; |
| } |
| |
| // TODO (msarett): We have promoted a two byte per pixel image to 8888, only to |
| // convert it back to 565. Instead, we should swizzle to 565 directly. |
| static SkSwizzler::ResultAlpha swizzle_mask16_to_565( |
| void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks, |
| uint32_t startX, uint32_t sampleX) { |
| |
| // Use the masks to decode to the destination |
| uint16_t* srcPtr = ((uint16_t*) srcRow) + startX; |
| uint16_t* dstPtr = (uint16_t*) dstRow; |
| for (int i = 0; i < width; i++) { |
| uint16_t p = srcPtr[0]; |
| uint8_t red = masks->getRed(p); |
| uint8_t green = masks->getGreen(p); |
| uint8_t blue = masks->getBlue(p); |
| dstPtr[i] = SkPack888ToRGB16(red, green, blue); |
| srcPtr += sampleX; |
| } |
| return SkSwizzler::kOpaque_ResultAlpha; |
| } |
| |
| static SkSwizzler::ResultAlpha swizzle_mask24_to_n32_opaque( |
| void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks, |
| uint32_t startX, uint32_t sampleX) { |
| |
| // Use the masks to decode to the destination |
| srcRow += 3 * startX; |
| SkPMColor* dstPtr = (SkPMColor*) dstRow; |
| for (int i = 0; i < width; i++) { |
| uint32_t p = srcRow[0] | (srcRow[1] << 8) | srcRow[2] << 16; |
| 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); |
| srcRow += 3 * sampleX; |
| } |
| return SkSwizzler::kOpaque_ResultAlpha; |
| } |
| |
| static SkSwizzler::ResultAlpha swizzle_mask24_to_n32_unpremul( |
| void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks, |
| uint32_t startX, uint32_t sampleX) { |
| |
| // Use the masks to decode to the destination |
| srcRow += 3 * startX; |
| SkPMColor* dstPtr = (SkPMColor*) dstRow; |
| INIT_RESULT_ALPHA; |
| for (int i = 0; i < width; i++) { |
| uint32_t p = srcRow[0] | (srcRow[1] << 8) | srcRow[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] = SkPackARGB32NoCheck(alpha, red, green, blue); |
| srcRow += 3 * sampleX; |
| } |
| return COMPUTE_RESULT_ALPHA; |
| } |
| |
| static SkSwizzler::ResultAlpha swizzle_mask24_to_n32_premul( |
| void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks, |
| uint32_t startX, uint32_t sampleX) { |
| |
| // Use the masks to decode to the destination |
| srcRow += 3 * startX; |
| SkPMColor* dstPtr = (SkPMColor*) dstRow; |
| INIT_RESULT_ALPHA; |
| for (int i = 0; i < width; i++) { |
| uint32_t p = srcRow[0] | (srcRow[1] << 8) | srcRow[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] = SkPreMultiplyARGB(alpha, red, green, blue); |
| srcRow += 3 * sampleX; |
| } |
| return COMPUTE_RESULT_ALPHA; |
| } |
| |
| static SkSwizzler::ResultAlpha swizzle_mask24_to_565( |
| void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks, |
| uint32_t startX, uint32_t sampleX) { |
| |
| // Use the masks to decode to the destination |
| srcRow += 3 * startX; |
| uint16_t* dstPtr = (uint16_t*) dstRow; |
| for (int i = 0; i < width; i++) { |
| uint32_t p = srcRow[0] | (srcRow[1] << 8) | srcRow[2] << 16; |
| uint8_t red = masks->getRed(p); |
| uint8_t green = masks->getGreen(p); |
| uint8_t blue = masks->getBlue(p); |
| dstPtr[i] = SkPack888ToRGB16(red, green, blue); |
| srcRow += 3 * sampleX; |
| } |
| return SkSwizzler::kOpaque_ResultAlpha; |
| } |
| |
| static SkSwizzler::ResultAlpha swizzle_mask32_to_n32_opaque( |
| void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks, |
| uint32_t startX, uint32_t sampleX) { |
| |
| // Use the masks to decode to the destination |
| uint32_t* srcPtr = ((uint32_t*) srcRow) + startX; |
| SkPMColor* dstPtr = (SkPMColor*) dstRow; |
| for (int i = 0; i < width; i++) { |
| uint32_t p = srcPtr[0]; |
| 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); |
| srcPtr += sampleX; |
| } |
| return SkSwizzler::kOpaque_ResultAlpha; |
| } |
| |
| static SkSwizzler::ResultAlpha swizzle_mask32_to_n32_unpremul( |
| void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks, |
| uint32_t startX, uint32_t sampleX) { |
| |
| // Use the masks to decode to the destination |
| uint32_t* srcPtr = ((uint32_t*) srcRow) + startX; |
| SkPMColor* dstPtr = (SkPMColor*) dstRow; |
| INIT_RESULT_ALPHA; |
| for (int i = 0; i < width; i++) { |
| uint32_t p = srcPtr[0]; |
| 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); |
| srcPtr += sampleX; |
| } |
| return COMPUTE_RESULT_ALPHA; |
| } |
| |
| static SkSwizzler::ResultAlpha swizzle_mask32_to_n32_premul( |
| void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks, |
| uint32_t startX, uint32_t sampleX) { |
| |
| // Use the masks to decode to the destination |
| uint32_t* srcPtr = ((uint32_t*) srcRow) + startX; |
| SkPMColor* dstPtr = (SkPMColor*) dstRow; |
| INIT_RESULT_ALPHA; |
| for (int i = 0; i < width; i++) { |
| uint32_t p = srcPtr[0]; |
| 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); |
| srcPtr += sampleX; |
| } |
| return COMPUTE_RESULT_ALPHA; |
| } |
| |
| static SkSwizzler::ResultAlpha swizzle_mask32_to_565( |
| void* dstRow, const uint8_t* srcRow, int width, SkMasks* masks, |
| uint32_t startX, uint32_t sampleX) { |
| // Use the masks to decode to the destination |
| uint32_t* srcPtr = ((uint32_t*) srcRow) + startX; |
| uint16_t* dstPtr = (uint16_t*) dstRow; |
| for (int i = 0; i < width; i++) { |
| uint32_t p = srcPtr[0]; |
| uint8_t red = masks->getRed(p); |
| uint8_t green = masks->getGreen(p); |
| uint8_t blue = masks->getBlue(p); |
| dstPtr[i] = SkPack888ToRGB16(red, green, blue); |
| srcPtr += sampleX; |
| } |
| return SkSwizzler::kOpaque_ResultAlpha; |
| } |
| |
| /* |
| * |
| * Create a new mask swizzler |
| * |
| */ |
| SkMaskSwizzler* SkMaskSwizzler::CreateMaskSwizzler( |
| const SkImageInfo& dstInfo, const SkImageInfo& srcInfo, SkMasks* masks, |
| uint32_t bitsPerPixel) { |
| |
| // Choose the appropriate row procedure |
| RowProc proc = nullptr; |
| switch (bitsPerPixel) { |
| case 16: |
| switch (dstInfo.colorType()) { |
| case kN32_SkColorType: |
| switch (dstInfo.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; |
| case kRGB_565_SkColorType: |
| switch (dstInfo.alphaType()) { |
| case kOpaque_SkAlphaType: |
| proc = &swizzle_mask16_to_565; |
| break; |
| default: |
| break; |
| } |
| break; |
| default: |
| break; |
| } |
| break; |
| case 24: |
| switch (dstInfo.colorType()) { |
| case kN32_SkColorType: |
| switch (dstInfo.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; |
| case kRGB_565_SkColorType: |
| switch (dstInfo.alphaType()) { |
| case kOpaque_SkAlphaType: |
| proc = &swizzle_mask24_to_565; |
| break; |
| default: |
| break; |
| } |
| break; |
| default: |
| break; |
| } |
| break; |
| case 32: |
| switch (dstInfo.colorType()) { |
| case kN32_SkColorType: |
| switch (dstInfo.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; |
| case kRGB_565_SkColorType: |
| switch (dstInfo.alphaType()) { |
| case kOpaque_SkAlphaType: |
| proc = &swizzle_mask32_to_565; |
| break; |
| default: |
| break; |
| } |
| break; |
| default: |
| break; |
| } |
| break; |
| default: |
| SkASSERT(false); |
| return nullptr; |
| } |
| |
| // Get the sample size |
| int sampleX; |
| SkScaledCodec::ComputeSampleSize(dstInfo, srcInfo, &sampleX, NULL); |
| |
| return new SkMaskSwizzler(dstInfo, masks, proc, sampleX); |
| } |
| |
| /* |
| * |
| * Constructor for mask swizzler |
| * |
| */ |
| SkMaskSwizzler::SkMaskSwizzler(const SkImageInfo& dstInfo, SkMasks* masks, |
| RowProc proc, uint32_t sampleX) |
| : fDstInfo(dstInfo) |
| , fMasks(masks) |
| , fRowProc(proc) |
| , fSampleX(sampleX) |
| , fStartX(get_start_coord(sampleX)) |
| {} |
| |
| /* |
| * |
| * Swizzle the specified row |
| * |
| */ |
| SkSwizzler::ResultAlpha SkMaskSwizzler::swizzle(void* dst, const uint8_t* SK_RESTRICT src) { |
| SkASSERT(nullptr != dst && nullptr != src); |
| return fRowProc(dst, src, fDstInfo.width(), fMasks, fStartX, fSampleX); |
| } |