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
setContext(const SkBitmap & device,const SkPaint & paint,const SkMatrix & matrix)21 bool SkTransparentShader::setContext(const SkBitmap& device,
22 const SkPaint& paint,
23 const SkMatrix& matrix) {
24 fDevice = &device;
25 fAlpha = paint.getAlpha();
26
27 return this->INHERITED::setContext(device, paint, matrix);
28 }
29
getFlags()30 uint32_t SkTransparentShader::getFlags() {
31 uint32_t flags = this->INHERITED::getFlags();
32
33 switch (fDevice->getConfig()) {
34 case SkBitmap::kRGB_565_Config:
35 flags |= kHasSpan16_Flag;
36 if (fAlpha == 255)
37 flags |= kOpaqueAlpha_Flag;
38 break;
39 case SkBitmap::kARGB_8888_Config:
40 case SkBitmap::kARGB_4444_Config:
41 if (fAlpha == 255 && fDevice->isOpaque())
42 flags |= kOpaqueAlpha_Flag;
43 break;
44 default:
45 break;
46 }
47 return flags;
48 }
49
shadeSpan(int x,int y,SkPMColor span[],int count)50 void SkTransparentShader::shadeSpan(int x, int y, SkPMColor span[], int count) {
51 unsigned scale = SkAlpha255To256(fAlpha);
52
53 switch (fDevice->getConfig()) {
54 case SkBitmap::kARGB_8888_Config:
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 SkBitmap::kRGB_565_Config: {
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 = fAlpha;
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 SkBitmap::kARGB_4444_Config: {
90 const uint16_t* src = fDevice->getAddr16(x, y);
91 if (scale == 256) {
92 for (int i = count - 1; i >= 0; --i) {
93 span[i] = SkPixel4444ToPixel32(src[i]);
94 }
95 } else {
96 unsigned scale16 = scale >> 4;
97 for (int i = count - 1; i >= 0; --i) {
98 uint32_t c = SkExpand_4444(src[i]) * scale16;
99 span[i] = SkCompact_8888(c);
100 }
101 }
102 break;
103 }
104 case SkBitmap::kIndex8_Config:
105 SkASSERT(!"index8 not supported as a destination device");
106 break;
107 case SkBitmap::kA8_Config: {
108 const uint8_t* src = fDevice->getAddr8(x, y);
109 if (scale == 256) {
110 for (int i = count - 1; i >= 0; --i) {
111 span[i] = SkPackARGB32(src[i], 0, 0, 0);
112 }
113 } else {
114 for (int i = count - 1; i >= 0; --i) {
115 span[i] = SkPackARGB32(SkAlphaMul(src[i], scale), 0, 0, 0);
116 }
117 }
118 break;
119 }
120 case SkBitmap::kA1_Config:
121 SkASSERT(!"kA1_Config umimplemented at this time");
122 break;
123 default: // to avoid warnings
124 break;
125 }
126 }
127
shadeSpan16(int x,int y,uint16_t span[],int count)128 void SkTransparentShader::shadeSpan16(int x, int y, uint16_t span[], int count) {
129 SkASSERT(fDevice->getConfig() == SkBitmap::kRGB_565_Config);
130
131 uint16_t* src = fDevice->getAddr16(x, y);
132 if (src != span) {
133 memcpy(span, src, count << 1);
134 }
135 }
136
137