/* * 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 "include/core/SkShader.h" #include "include/private/SkColorData.h" #include "include/private/SkColorData.h" #include "src/core/SkCoreBlitters.h" #include "src/core/SkXfermodePriv.h" #include "src/utils/SkUTF.h" #include "include/private/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.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; } }