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 
onCreateContext(const ContextRec & rec,void * storage) const14 SkShader::Context* SkTransparentShader::onCreateContext(const ContextRec& rec,
15                                                         void* storage) const {
16     return SkNEW_PLACEMENT_ARGS(storage, TransparentShaderContext, (*this, rec));
17 }
18 
contextSize() const19 size_t SkTransparentShader::contextSize() const {
20     return sizeof(TransparentShaderContext);
21 }
22 
TransparentShaderContext(const SkTransparentShader & shader,const ContextRec & rec)23 SkTransparentShader::TransparentShaderContext::TransparentShaderContext(
24         const SkTransparentShader& shader, const ContextRec& rec)
25     : INHERITED(shader, rec)
26     , fDevice(rec.fDevice) {}
27 
~TransparentShaderContext()28 SkTransparentShader::TransparentShaderContext::~TransparentShaderContext() {}
29 
getFlags() const30 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 
shadeSpan(int x,int y,SkPMColor span[],int count)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 
shadeSpan16(int x,int y,uint16_t span[],int count)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 
CreateProc(SkReadBuffer & buffer)118 SkFlattenable* SkTransparentShader::CreateProc(SkReadBuffer& buffer) {
119     return SkNEW(SkTransparentShader);
120 }
121 
122 #ifndef SK_IGNORE_TO_STRING
toString(SkString * str) const123 void SkTransparentShader::toString(SkString* str) const {
124     str->append("SkTransparentShader: (");
125 
126     this->INHERITED::toString(str);
127 
128     str->append(")");
129 }
130 #endif
131