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 #include "SkString.h" 13 14 bool SkTransparentShader::setContext(const SkBitmap& device, 15 const SkPaint& paint, 16 const SkMatrix& matrix) { 17 fDevice = &device; 18 fAlpha = paint.getAlpha(); 19 20 return this->INHERITED::setContext(device, paint, matrix); 21 } 22 23 uint32_t SkTransparentShader::getFlags() { 24 uint32_t flags = this->INHERITED::getFlags(); 25 26 switch (fDevice->config()) { 27 case SkBitmap::kRGB_565_Config: 28 flags |= kHasSpan16_Flag; 29 if (fAlpha == 255) 30 flags |= kOpaqueAlpha_Flag; 31 break; 32 case SkBitmap::kARGB_8888_Config: 33 if (fAlpha == 255 && fDevice->isOpaque()) 34 flags |= kOpaqueAlpha_Flag; 35 break; 36 default: 37 break; 38 } 39 return flags; 40 } 41 42 void SkTransparentShader::shadeSpan(int x, int y, SkPMColor span[], int count) { 43 unsigned scale = SkAlpha255To256(fAlpha); 44 45 switch (fDevice->config()) { 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::kIndex8_Config: 82 SkDEBUGFAIL("index8 not supported as a destination device"); 83 break; 84 case SkBitmap::kA8_Config: { 85 const uint8_t* src = fDevice->getAddr8(x, y); 86 if (scale == 256) { 87 for (int i = count - 1; i >= 0; --i) { 88 span[i] = SkPackARGB32(src[i], 0, 0, 0); 89 } 90 } else { 91 for (int i = count - 1; i >= 0; --i) { 92 span[i] = SkPackARGB32(SkAlphaMul(src[i], scale), 0, 0, 0); 93 } 94 } 95 break; 96 } 97 default: // to avoid warnings 98 break; 99 } 100 } 101 102 void SkTransparentShader::shadeSpan16(int x, int y, uint16_t span[], int count) { 103 SkASSERT(fDevice->config() == SkBitmap::kRGB_565_Config); 104 105 uint16_t* src = fDevice->getAddr16(x, y); 106 if (src != span) { 107 memcpy(span, src, count << 1); 108 } 109 } 110 111 #ifdef SK_DEVELOPER 112 void SkTransparentShader::toString(SkString* str) const { 113 str->append("SkTransparentShader: ("); 114 115 this->INHERITED::toString(str); 116 117 str->append(")"); 118 } 119 #endif 120