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->getConfig()) { 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 case SkBitmap::kARGB_4444_Config: 34 if (fAlpha == 255 && fDevice->isOpaque()) 35 flags |= kOpaqueAlpha_Flag; 36 break; 37 default: 38 break; 39 } 40 return flags; 41 } 42 43 void SkTransparentShader::shadeSpan(int x, int y, SkPMColor span[], int count) { 44 unsigned scale = SkAlpha255To256(fAlpha); 45 46 switch (fDevice->getConfig()) { 47 case SkBitmap::kARGB_8888_Config: 48 if (scale == 256) { 49 SkPMColor* src = fDevice->getAddr32(x, y); 50 if (src != span) { 51 memcpy(span, src, count * sizeof(SkPMColor)); 52 } 53 } else { 54 const SkPMColor* src = fDevice->getAddr32(x, y); 55 for (int i = count - 1; i >= 0; --i) { 56 span[i] = SkAlphaMulQ(src[i], scale); 57 } 58 } 59 break; 60 case SkBitmap::kRGB_565_Config: { 61 const uint16_t* src = fDevice->getAddr16(x, y); 62 if (scale == 256) { 63 for (int i = count - 1; i >= 0; --i) { 64 span[i] = SkPixel16ToPixel32(src[i]); 65 } 66 } else { 67 unsigned alpha = fAlpha; 68 for (int i = count - 1; i >= 0; --i) { 69 uint16_t c = src[i]; 70 unsigned r = SkPacked16ToR32(c); 71 unsigned g = SkPacked16ToG32(c); 72 unsigned b = SkPacked16ToB32(c); 73 74 span[i] = SkPackARGB32( alpha, 75 SkAlphaMul(r, scale), 76 SkAlphaMul(g, scale), 77 SkAlphaMul(b, scale)); 78 } 79 } 80 break; 81 } 82 case SkBitmap::kARGB_4444_Config: { 83 const uint16_t* src = fDevice->getAddr16(x, y); 84 if (scale == 256) { 85 for (int i = count - 1; i >= 0; --i) { 86 span[i] = SkPixel4444ToPixel32(src[i]); 87 } 88 } else { 89 unsigned scale16 = scale >> 4; 90 for (int i = count - 1; i >= 0; --i) { 91 uint32_t c = SkExpand_4444(src[i]) * scale16; 92 span[i] = SkCompact_8888(c); 93 } 94 } 95 break; 96 } 97 case SkBitmap::kIndex8_Config: 98 SkDEBUGFAIL("index8 not supported as a destination device"); 99 break; 100 case SkBitmap::kA8_Config: { 101 const uint8_t* src = fDevice->getAddr8(x, y); 102 if (scale == 256) { 103 for (int i = count - 1; i >= 0; --i) { 104 span[i] = SkPackARGB32(src[i], 0, 0, 0); 105 } 106 } else { 107 for (int i = count - 1; i >= 0; --i) { 108 span[i] = SkPackARGB32(SkAlphaMul(src[i], scale), 0, 0, 0); 109 } 110 } 111 break; 112 } 113 case SkBitmap::kA1_Config: 114 SkDEBUGFAIL("kA1_Config umimplemented at this time"); 115 break; 116 default: // to avoid warnings 117 break; 118 } 119 } 120 121 void SkTransparentShader::shadeSpan16(int x, int y, uint16_t span[], int count) { 122 SkASSERT(fDevice->getConfig() == SkBitmap::kRGB_565_Config); 123 124 uint16_t* src = fDevice->getAddr16(x, y); 125 if (src != span) { 126 memcpy(span, src, count << 1); 127 } 128 } 129 130 #ifdef SK_DEVELOPER 131 void SkTransparentShader::toString(SkString* str) const { 132 str->append("SkTransparentShader: ("); 133 134 this->INHERITED::toString(str); 135 136 str->append(")"); 137 } 138 #endif 139