1 /* libs/graphics/effects/SkTransparentShader.cpp 2 ** 3 ** Copyright 2006, The Android Open Source Project 4 ** 5 ** Licensed under the Apache License, Version 2.0 (the "License"); 6 ** you may not use this file except in compliance with the License. 7 ** You may obtain a copy of the License at 8 ** 9 ** http://www.apache.org/licenses/LICENSE-2.0 10 ** 11 ** Unless required by applicable law or agreed to in writing, software 12 ** distributed under the License is distributed on an "AS IS" BASIS, 13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 ** See the License for the specific language governing permissions and 15 ** limitations under the License. 16 */ 17 18 #include "SkTransparentShader.h" 19 #include "SkColorPriv.h" 20 21 bool SkTransparentShader::setContext(const SkBitmap& device, 22 const SkPaint& paint, 23 const SkMatrix& matrix) 24 { 25 fDevice = &device; 26 fAlpha = paint.getAlpha(); 27 28 return this->INHERITED::setContext(device, paint, matrix); 29 } 30 31 uint32_t SkTransparentShader::getFlags() 32 { 33 uint32_t flags = this->INHERITED::getFlags(); 34 35 switch (fDevice->getConfig()) { 36 case SkBitmap::kRGB_565_Config: 37 flags |= kHasSpan16_Flag; 38 if (fAlpha == 255) 39 flags |= kOpaqueAlpha_Flag; 40 break; 41 case SkBitmap::kARGB_8888_Config: 42 case SkBitmap::kARGB_4444_Config: 43 if (fAlpha == 255 && fDevice->isOpaque()) 44 flags |= kOpaqueAlpha_Flag; 45 break; 46 default: 47 break; 48 } 49 return flags; 50 } 51 52 void SkTransparentShader::shadeSpan(int x, int y, SkPMColor span[], int count) 53 { 54 unsigned scale = SkAlpha255To256(fAlpha); 55 56 switch (fDevice->getConfig()) { 57 case SkBitmap::kARGB_8888_Config: 58 if (scale == 256) 59 memcpy(span, fDevice->getAddr32(x, y), count * sizeof(SkPMColor)); 60 else 61 { 62 const SkPMColor* src = fDevice->getAddr32(x, y); 63 for (int i = count - 1; i >= 0; --i) 64 span[i] = SkAlphaMulQ(src[i], scale); 65 } 66 break; 67 case SkBitmap::kRGB_565_Config: 68 { 69 const uint16_t* src = fDevice->getAddr16(x, y); 70 if (scale == 256) 71 { 72 for (int i = count - 1; i >= 0; --i) 73 span[i] = SkPixel16ToPixel32(src[i]); 74 } 75 else 76 { 77 unsigned alpha = fAlpha; 78 for (int i = count - 1; i >= 0; --i) 79 { 80 uint16_t c = src[i]; 81 unsigned r = SkPacked16ToR32(c); 82 unsigned g = SkPacked16ToG32(c); 83 unsigned b = SkPacked16ToB32(c); 84 85 span[i] = SkPackARGB32( alpha, 86 SkAlphaMul(r, scale), 87 SkAlphaMul(g, scale), 88 SkAlphaMul(b, scale)); 89 } 90 } 91 } 92 break; 93 case SkBitmap::kARGB_4444_Config: 94 { 95 const uint16_t* src = fDevice->getAddr16(x, y); 96 if (scale == 256) 97 { 98 for (int i = count - 1; i >= 0; --i) 99 span[i] = SkPixel4444ToPixel32(src[i]); 100 } 101 else 102 { 103 unsigned scale16 = scale >> 4; 104 for (int i = count - 1; i >= 0; --i) 105 { 106 uint32_t c = SkExpand_4444(src[i]) * scale16; 107 span[i] = SkCompact_8888(c); 108 } 109 } 110 } 111 break; 112 case SkBitmap::kIndex8_Config: 113 SkASSERT(!"index8 not supported as a destination device"); 114 break; 115 case SkBitmap::kA8_Config: 116 { 117 const uint8_t* src = fDevice->getAddr8(x, y); 118 if (scale == 256) 119 { 120 for (int i = count - 1; i >= 0; --i) 121 span[i] = SkPackARGB32(src[i], 0, 0, 0); 122 } 123 else 124 { 125 for (int i = count - 1; i >= 0; --i) 126 span[i] = SkPackARGB32(SkAlphaMul(src[i], scale), 0, 0, 0); 127 } 128 } 129 break; 130 case SkBitmap::kA1_Config: 131 SkASSERT(!"kA1_Config umimplemented at this time"); 132 break; 133 default: // to avoid warnings 134 break; 135 } 136 } 137 138 void SkTransparentShader::shadeSpan16(int x, int y, uint16_t span[], int count) 139 { 140 SkASSERT(fDevice->getConfig() == SkBitmap::kRGB_565_Config); 141 142 memcpy(span, fDevice->getAddr16(x, y), count << 1); 143 } 144 145