/* * Copyright 2006 The Android Open Source Project * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "SkTransparentShader.h" #include "SkColorPriv.h" #include "SkString.h" SkShader::Context* SkTransparentShader::onCreateContext(const ContextRec& rec, void* storage) const { return SkNEW_PLACEMENT_ARGS(storage, TransparentShaderContext, (*this, rec)); } size_t SkTransparentShader::contextSize() const { return sizeof(TransparentShaderContext); } SkTransparentShader::TransparentShaderContext::TransparentShaderContext( const SkTransparentShader& shader, const ContextRec& rec) : INHERITED(shader, rec) , fDevice(rec.fDevice) {} SkTransparentShader::TransparentShaderContext::~TransparentShaderContext() {} uint32_t SkTransparentShader::TransparentShaderContext::getFlags() const { uint32_t flags = this->INHERITED::getFlags(); switch (fDevice->colorType()) { case kRGB_565_SkColorType: flags |= kHasSpan16_Flag; if (this->getPaintAlpha() == 255) flags |= kOpaqueAlpha_Flag; break; case kN32_SkColorType: if (this->getPaintAlpha() == 255 && fDevice->isOpaque()) flags |= kOpaqueAlpha_Flag; break; default: break; } return flags; } void SkTransparentShader::TransparentShaderContext::shadeSpan(int x, int y, SkPMColor span[], int count) { unsigned scale = SkAlpha255To256(this->getPaintAlpha()); switch (fDevice->colorType()) { case kN32_SkColorType: if (scale == 256) { SkPMColor* src = fDevice->getAddr32(x, y); if (src != span) { memcpy(span, src, count * sizeof(SkPMColor)); } } else { const SkPMColor* src = fDevice->getAddr32(x, y); for (int i = count - 1; i >= 0; --i) { span[i] = SkAlphaMulQ(src[i], scale); } } break; case kRGB_565_SkColorType: { const uint16_t* src = fDevice->getAddr16(x, y); if (scale == 256) { for (int i = count - 1; i >= 0; --i) { span[i] = SkPixel16ToPixel32(src[i]); } } else { unsigned alpha = this->getPaintAlpha(); for (int i = count - 1; i >= 0; --i) { uint16_t c = src[i]; unsigned r = SkPacked16ToR32(c); unsigned g = SkPacked16ToG32(c); unsigned b = SkPacked16ToB32(c); span[i] = SkPackARGB32( alpha, SkAlphaMul(r, scale), SkAlphaMul(g, scale), SkAlphaMul(b, scale)); } } break; } case kAlpha_8_SkColorType: { const uint8_t* src = fDevice->getAddr8(x, y); if (scale == 256) { for (int i = count - 1; i >= 0; --i) { span[i] = SkPackARGB32(src[i], 0, 0, 0); } } else { for (int i = count - 1; i >= 0; --i) { span[i] = SkPackARGB32(SkAlphaMul(src[i], scale), 0, 0, 0); } } break; } default: SkDEBUGFAIL("colorType not supported as a destination device"); break; } } void SkTransparentShader::TransparentShaderContext::shadeSpan16(int x, int y, uint16_t span[], int count) { SkASSERT(fDevice->colorType() == kRGB_565_SkColorType); uint16_t* src = fDevice->getAddr16(x, y); if (src != span) { memcpy(span, src, count << 1); } } SkFlattenable* SkTransparentShader::CreateProc(SkReadBuffer& buffer) { return SkNEW(SkTransparentShader); } #ifndef SK_IGNORE_TO_STRING void SkTransparentShader::toString(SkString* str) const { str->append("SkTransparentShader: ("); this->INHERITED::toString(str); str->append(")"); } #endif