| /* | |
| * Copyright 2017 Google Inc. | |
| * | |
| * Use of this source code is governed by a BSD-style license that can be | |
| * found in the LICENSE file. | |
| */ | |
| #include "SkCoreBlitters.h" | |
| #include "SkColorData.h" | |
| #include "SkShader.h" | |
| #include "SkUTF.h" | |
| #include "SkXfermodePriv.h" | |
| #include "SkBlitMask.h" | |
| #include "SkColorData.h" | |
| #include "SkNx.h" | |
| static void D16_S32X_src(uint16_t dst[], const SkPMColor src[], int count, uint8_t coverage) { | |
| SkASSERT(coverage == 0xFF); | |
| for (int i = 0; i < count; ++i) { | |
| dst[i] = SkPixel32ToPixel16(src[i]); | |
| } | |
| } | |
| static void D16_S32X_src_coverage(uint16_t dst[], const SkPMColor src[], int count, | |
| uint8_t coverage) { | |
| switch (coverage) { | |
| case 0: break; | |
| case 0xFF: | |
| for (int i = 0; i < count; ++i) { | |
| dst[i] = SkPixel32ToPixel16(src[i]); | |
| } | |
| break; | |
| default: | |
| unsigned scale = coverage + (coverage >> 7); | |
| for (int i = 0; i < count; ++i) { | |
| dst[i] = SkSrcOver32To16(SkAlphaMulQ(src[i], scale), dst[i]); | |
| } | |
| break; | |
| } | |
| } | |
| static void D16_S32A_srcover(uint16_t dst[], const SkPMColor src[], int count, uint8_t coverage) { | |
| SkASSERT(coverage == 0xFF); | |
| for (int i = 0; i < count; ++i) { | |
| dst[i] = SkSrcOver32To16(src[i], dst[i]); | |
| } | |
| } | |
| static void D16_S32A_srcover_coverage(uint16_t dst[], const SkPMColor src[], int count, | |
| uint8_t coverage) { | |
| switch (coverage) { | |
| case 0: break; | |
| case 0xFF: | |
| for (int i = 0; i < count; ++i) { | |
| dst[i] = SkSrcOver32To16(src[i], dst[i]); | |
| } | |
| break; | |
| default: | |
| unsigned scale = coverage + (coverage >> 7); | |
| for (int i = 0; i < count; ++i) { | |
| dst[i] = SkSrcOver32To16(SkAlphaMulQ(src[i], scale), dst[i]); | |
| } | |
| break; | |
| } | |
| } | |
| bool SkRGB565_Shader_Blitter::Supports(const SkPixmap& device, const SkPaint& paint) { | |
| if (device.colorType() != kRGB_565_SkColorType) { | |
| return false; | |
| } | |
| if (device.colorSpace()) { | |
| return false; | |
| } | |
| if (paint.getBlendMode() != SkBlendMode::kSrcOver && | |
| paint.getBlendMode() != SkBlendMode::kSrc) { | |
| return false; | |
| } | |
| if (paint.isLCDRenderText()) { | |
| return false; | |
| } | |
| if (paint.isDither()) { | |
| return false; | |
| } | |
| return true; | |
| } | |
| SkRGB565_Shader_Blitter::SkRGB565_Shader_Blitter(const SkPixmap& device, | |
| const SkPaint& paint, SkShaderBase::Context* shaderContext) | |
| : INHERITED(device, paint, shaderContext) | |
| { | |
| SkASSERT(shaderContext); | |
| SkASSERT(Supports(device, paint)); | |
| fBuffer = (SkPMColor*)sk_malloc_throw(device.width() * (sizeof(SkPMColor))); | |
| bool isOpaque = SkToBool(shaderContext->getFlags() & SkShaderBase::kOpaqueAlpha_Flag); | |
| if (paint.getBlendMode() == SkBlendMode::kSrc || isOpaque) { | |
| fBlend = D16_S32X_src; | |
| fBlendCoverage = D16_S32X_src_coverage; | |
| } else { // srcover | |
| fBlend = isOpaque ? D16_S32X_src : D16_S32A_srcover; | |
| fBlendCoverage = isOpaque ? D16_S32X_src_coverage : D16_S32A_srcover_coverage; | |
| } | |
| } | |
| SkRGB565_Shader_Blitter::~SkRGB565_Shader_Blitter() { | |
| sk_free(fBuffer); | |
| } | |
| void SkRGB565_Shader_Blitter::blitH(int x, int y, int width) { | |
| SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width()); | |
| uint16_t* device = fDevice.writable_addr16(x, y); | |
| SkPMColor* span = fBuffer; | |
| fShaderContext->shadeSpan(x, y, span, width); | |
| fBlend(device, span, width, 0xFF); | |
| } | |
| void SkRGB565_Shader_Blitter::blitAntiH(int x, int y, const SkAlpha coverage[], | |
| const int16_t runs[]) { | |
| SkPMColor* span = fBuffer; | |
| uint16_t* device = fDevice.writable_addr16(x, y); | |
| auto* shaderContext = fShaderContext; | |
| for (;;) { | |
| int count = *runs; | |
| if (count <= 0) { | |
| break; | |
| } | |
| int aa = *coverage; | |
| if (aa) { | |
| shaderContext->shadeSpan(x, y, span, count); | |
| fBlendCoverage(device, span, count, aa); | |
| } | |
| device += count; | |
| runs += count; | |
| coverage += count; | |
| x += count; | |
| } | |
| } |