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 SkShader::Context* SkTransparentShader::onCreateContext(const ContextRec& rec, 15 void* storage) const { 16 return SkNEW_PLACEMENT_ARGS(storage, TransparentShaderContext, (*this, rec)); 17 } 18 19 size_t SkTransparentShader::contextSize() const { 20 return sizeof(TransparentShaderContext); 21 } 22 23 SkTransparentShader::TransparentShaderContext::TransparentShaderContext( 24 const SkTransparentShader& shader, const ContextRec& rec) 25 : INHERITED(shader, rec) 26 , fDevice(rec.fDevice) {} 27 28 SkTransparentShader::TransparentShaderContext::~TransparentShaderContext() {} 29 30 uint32_t SkTransparentShader::TransparentShaderContext::getFlags() const { 31 uint32_t flags = this->INHERITED::getFlags(); 32 33 switch (fDevice->colorType()) { 34 case kRGB_565_SkColorType: 35 flags |= kHasSpan16_Flag; 36 if (this->getPaintAlpha() == 255) 37 flags |= kOpaqueAlpha_Flag; 38 break; 39 case kN32_SkColorType: 40 if (this->getPaintAlpha() == 255 && fDevice->isOpaque()) 41 flags |= kOpaqueAlpha_Flag; 42 break; 43 default: 44 break; 45 } 46 return flags; 47 } 48 49 void SkTransparentShader::TransparentShaderContext::shadeSpan(int x, int y, SkPMColor span[], 50 int count) { 51 unsigned scale = SkAlpha255To256(this->getPaintAlpha()); 52 53 switch (fDevice->colorType()) { 54 case kN32_SkColorType: 55 if (scale == 256) { 56 SkPMColor* src = fDevice->getAddr32(x, y); 57 if (src != span) { 58 memcpy(span, src, count * sizeof(SkPMColor)); 59 } 60 } else { 61 const SkPMColor* src = fDevice->getAddr32(x, y); 62 for (int i = count - 1; i >= 0; --i) { 63 span[i] = SkAlphaMulQ(src[i], scale); 64 } 65 } 66 break; 67 case kRGB_565_SkColorType: { 68 const uint16_t* src = fDevice->getAddr16(x, y); 69 if (scale == 256) { 70 for (int i = count - 1; i >= 0; --i) { 71 span[i] = SkPixel16ToPixel32(src[i]); 72 } 73 } else { 74 unsigned alpha = this->getPaintAlpha(); 75 for (int i = count - 1; i >= 0; --i) { 76 uint16_t c = src[i]; 77 unsigned r = SkPacked16ToR32(c); 78 unsigned g = SkPacked16ToG32(c); 79 unsigned b = SkPacked16ToB32(c); 80 81 span[i] = SkPackARGB32( alpha, 82 SkAlphaMul(r, scale), 83 SkAlphaMul(g, scale), 84 SkAlphaMul(b, scale)); 85 } 86 } 87 break; 88 } 89 case kAlpha_8_SkColorType: { 90 const uint8_t* src = fDevice->getAddr8(x, y); 91 if (scale == 256) { 92 for (int i = count - 1; i >= 0; --i) { 93 span[i] = SkPackARGB32(src[i], 0, 0, 0); 94 } 95 } else { 96 for (int i = count - 1; i >= 0; --i) { 97 span[i] = SkPackARGB32(SkAlphaMul(src[i], scale), 0, 0, 0); 98 } 99 } 100 break; 101 } 102 default: 103 SkDEBUGFAIL("colorType not supported as a destination device"); 104 break; 105 } 106 } 107 108 void SkTransparentShader::TransparentShaderContext::shadeSpan16(int x, int y, uint16_t span[], 109 int count) { 110 SkASSERT(fDevice->colorType() == kRGB_565_SkColorType); 111 112 uint16_t* src = fDevice->getAddr16(x, y); 113 if (src != span) { 114 memcpy(span, src, count << 1); 115 } 116 } 117 118 #ifndef SK_IGNORE_TO_STRING 119 void SkTransparentShader::toString(SkString* str) const { 120 str->append("SkTransparentShader: ("); 121 122 this->INHERITED::toString(str); 123 124 str->append(")"); 125 } 126 #endif 127