1 2/* 3 * Copyright 2006 The Android Open Source Project 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9 10#include "SkTransparentShader.h" 11#include "SkColorPriv.h" 12 13bool SkTransparentShader::setContext(const SkBitmap& device, 14 const SkPaint& paint, 15 const SkMatrix& matrix) { 16 fDevice = &device; 17 fAlpha = paint.getAlpha(); 18 19 return this->INHERITED::setContext(device, paint, matrix); 20} 21 22uint32_t SkTransparentShader::getFlags() { 23 uint32_t flags = this->INHERITED::getFlags(); 24 25 switch (fDevice->getConfig()) { 26 case SkBitmap::kRGB_565_Config: 27 flags |= kHasSpan16_Flag; 28 if (fAlpha == 255) 29 flags |= kOpaqueAlpha_Flag; 30 break; 31 case SkBitmap::kARGB_8888_Config: 32 case SkBitmap::kARGB_4444_Config: 33 if (fAlpha == 255 && fDevice->isOpaque()) 34 flags |= kOpaqueAlpha_Flag; 35 break; 36 default: 37 break; 38 } 39 return flags; 40} 41 42void SkTransparentShader::shadeSpan(int x, int y, SkPMColor span[], int count) { 43 unsigned scale = SkAlpha255To256(fAlpha); 44 45 switch (fDevice->getConfig()) { 46 case SkBitmap::kARGB_8888_Config: 47 if (scale == 256) { 48 SkPMColor* src = fDevice->getAddr32(x, y); 49 if (src != span) { 50 memcpy(span, src, count * sizeof(SkPMColor)); 51 } 52 } else { 53 const SkPMColor* src = fDevice->getAddr32(x, y); 54 for (int i = count - 1; i >= 0; --i) { 55 span[i] = SkAlphaMulQ(src[i], scale); 56 } 57 } 58 break; 59 case SkBitmap::kRGB_565_Config: { 60 const uint16_t* src = fDevice->getAddr16(x, y); 61 if (scale == 256) { 62 for (int i = count - 1; i >= 0; --i) { 63 span[i] = SkPixel16ToPixel32(src[i]); 64 } 65 } else { 66 unsigned alpha = fAlpha; 67 for (int i = count - 1; i >= 0; --i) { 68 uint16_t c = src[i]; 69 unsigned r = SkPacked16ToR32(c); 70 unsigned g = SkPacked16ToG32(c); 71 unsigned b = SkPacked16ToB32(c); 72 73 span[i] = SkPackARGB32( alpha, 74 SkAlphaMul(r, scale), 75 SkAlphaMul(g, scale), 76 SkAlphaMul(b, scale)); 77 } 78 } 79 break; 80 } 81 case SkBitmap::kARGB_4444_Config: { 82 const uint16_t* src = fDevice->getAddr16(x, y); 83 if (scale == 256) { 84 for (int i = count - 1; i >= 0; --i) { 85 span[i] = SkPixel4444ToPixel32(src[i]); 86 } 87 } else { 88 unsigned scale16 = scale >> 4; 89 for (int i = count - 1; i >= 0; --i) { 90 uint32_t c = SkExpand_4444(src[i]) * scale16; 91 span[i] = SkCompact_8888(c); 92 } 93 } 94 break; 95 } 96 case SkBitmap::kIndex8_Config: 97 SkDEBUGFAIL("index8 not supported as a destination device"); 98 break; 99 case SkBitmap::kA8_Config: { 100 const uint8_t* src = fDevice->getAddr8(x, y); 101 if (scale == 256) { 102 for (int i = count - 1; i >= 0; --i) { 103 span[i] = SkPackARGB32(src[i], 0, 0, 0); 104 } 105 } else { 106 for (int i = count - 1; i >= 0; --i) { 107 span[i] = SkPackARGB32(SkAlphaMul(src[i], scale), 0, 0, 0); 108 } 109 } 110 break; 111 } 112 case SkBitmap::kA1_Config: 113 SkDEBUGFAIL("kA1_Config umimplemented at this time"); 114 break; 115 default: // to avoid warnings 116 break; 117 } 118} 119 120void SkTransparentShader::shadeSpan16(int x, int y, uint16_t span[], int count) { 121 SkASSERT(fDevice->getConfig() == SkBitmap::kRGB_565_Config); 122 123 uint16_t* src = fDevice->getAddr16(x, y); 124 if (src != span) { 125 memcpy(span, src, count << 1); 126 } 127} 128 129SkFlattenable::Factory SkTransparentShader::getFactory() { 130 return Create; 131} 132 133void SkTransparentShader::flatten(SkFlattenableWriteBuffer& buffer) { 134 this->INHERITED::flatten(buffer); 135} 136 137