/* libs/graphics/effects/SkTransparentShader.cpp ** ** Copyright 2006, The Android Open Source Project ** ** Licensed under the Apache License, Version 2.0 (the "License"); ** you may not use this file except in compliance with the License. ** You may obtain a copy of the License at ** ** http://www.apache.org/licenses/LICENSE-2.0 ** ** Unless required by applicable law or agreed to in writing, software ** distributed under the License is distributed on an "AS IS" BASIS, ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ** See the License for the specific language governing permissions and ** limitations under the License. */ #include "SkTransparentShader.h" #include "SkColorPriv.h" bool SkTransparentShader::setContext(const SkBitmap& device, const SkPaint& paint, const SkMatrix& matrix) { fDevice = &device; fAlpha = paint.getAlpha(); return this->INHERITED::setContext(device, paint, matrix); } uint32_t SkTransparentShader::getFlags() { uint32_t flags = this->INHERITED::getFlags(); switch (fDevice->getConfig()) { case SkBitmap::kRGB_565_Config: flags |= kHasSpan16_Flag; if (fAlpha == 255) flags |= kOpaqueAlpha_Flag; break; case SkBitmap::kARGB_8888_Config: case SkBitmap::kARGB_4444_Config: if (fAlpha == 255 && fDevice->isOpaque()) flags |= kOpaqueAlpha_Flag; break; default: break; } return flags; } void SkTransparentShader::shadeSpan(int x, int y, SkPMColor span[], int count) { unsigned scale = SkAlpha255To256(fAlpha); switch (fDevice->getConfig()) { case SkBitmap::kARGB_8888_Config: if (scale == 256) memcpy(span, fDevice->getAddr32(x, y), 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 SkBitmap::kRGB_565_Config: { 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 = fAlpha; 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 SkBitmap::kARGB_4444_Config: { const uint16_t* src = fDevice->getAddr16(x, y); if (scale == 256) { for (int i = count - 1; i >= 0; --i) span[i] = SkPixel4444ToPixel32(src[i]); } else { unsigned scale16 = scale >> 4; for (int i = count - 1; i >= 0; --i) { uint32_t c = SkExpand_4444(src[i]) * scale16; span[i] = SkCompact_8888(c); } } } break; case SkBitmap::kIndex8_Config: SkASSERT(!"index8 not supported as a destination device"); break; case SkBitmap::kA8_Config: { 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; case SkBitmap::kA1_Config: SkASSERT(!"kA1_Config umimplemented at this time"); break; default: // to avoid warnings break; } } void SkTransparentShader::shadeSpan16(int x, int y, uint16_t span[], int count) { SkASSERT(fDevice->getConfig() == SkBitmap::kRGB_565_Config); memcpy(span, fDevice->getAddr16(x, y), count << 1); }