blob: 6e68b5e9efbbbac83efac2e3ec0f94470e77ce2a [file] [log] [blame]
reed@android.com8a1c16f2008-12-17 15:59:43 +00001/* 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
21bool SkTransparentShader::setContext(const SkBitmap& device,
22 const SkPaint& paint,
mike@reedtribe.org3334c3a2011-04-20 11:39:28 +000023 const SkMatrix& matrix) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000024 fDevice = &device;
25 fAlpha = paint.getAlpha();
26
27 return this->INHERITED::setContext(device, paint, matrix);
28}
29
mike@reedtribe.org3334c3a2011-04-20 11:39:28 +000030uint32_t SkTransparentShader::getFlags() {
reed@android.com8a1c16f2008-12-17 15:59:43 +000031 uint32_t flags = this->INHERITED::getFlags();
32
33 switch (fDevice->getConfig()) {
mike@reedtribe.org3334c3a2011-04-20 11:39:28 +000034 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;
reed@android.com8a1c16f2008-12-17 15:59:43 +000046 }
47 return flags;
48}
49
mike@reedtribe.org3334c3a2011-04-20 11:39:28 +000050void SkTransparentShader::shadeSpan(int x, int y, SkPMColor span[], int count) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000051 unsigned scale = SkAlpha255To256(fAlpha);
52
53 switch (fDevice->getConfig()) {
mike@reedtribe.org3334c3a2011-04-20 11:39:28 +000054 case SkBitmap::kARGB_8888_Config:
55 if (scale == 256) {
senorblanco@chromium.orge4c98ff2011-05-20 19:06:10 +000056 SkPMColor* src = fDevice->getAddr32(x, y);
57 if (src != span) {
58 memcpy(span, src, count * sizeof(SkPMColor));
59 }
mike@reedtribe.org3334c3a2011-04-20 11:39:28 +000060 } 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 }
reed@android.com8a1c16f2008-12-17 15:59:43 +000065 }
mike@reedtribe.org3334c3a2011-04-20 11:39:28 +000066 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 {
reed@android.com8a1c16f2008-12-17 15:59:43 +000074 unsigned alpha = fAlpha;
mike@reedtribe.org3334c3a2011-04-20 11:39:28 +000075 for (int i = count - 1; i >= 0; --i) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000076 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 }
mike@reedtribe.org3334c3a2011-04-20 11:39:28 +000087 break;
reed@android.com8a1c16f2008-12-17 15:59:43 +000088 }
mike@reedtribe.org3334c3a2011-04-20 11:39:28 +000089 case SkBitmap::kARGB_4444_Config: {
reed@android.com8a1c16f2008-12-17 15:59:43 +000090 const uint16_t* src = fDevice->getAddr16(x, y);
mike@reedtribe.org3334c3a2011-04-20 11:39:28 +000091 if (scale == 256) {
92 for (int i = count - 1; i >= 0; --i) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000093 span[i] = SkPixel4444ToPixel32(src[i]);
mike@reedtribe.org3334c3a2011-04-20 11:39:28 +000094 }
95 } else {
reed@android.com8a1c16f2008-12-17 15:59:43 +000096 unsigned scale16 = scale >> 4;
mike@reedtribe.org3334c3a2011-04-20 11:39:28 +000097 for (int i = count - 1; i >= 0; --i) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000098 uint32_t c = SkExpand_4444(src[i]) * scale16;
99 span[i] = SkCompact_8888(c);
100 }
101 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000102 break;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000103 }
mike@reedtribe.org3334c3a2011-04-20 11:39:28 +0000104 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;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000125 }
126}
127
mike@reedtribe.org3334c3a2011-04-20 11:39:28 +0000128void SkTransparentShader::shadeSpan16(int x, int y, uint16_t span[], int count) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000129 SkASSERT(fDevice->getConfig() == SkBitmap::kRGB_565_Config);
130
senorblanco@chromium.orge4c98ff2011-05-20 19:06:10 +0000131 uint16_t* src = fDevice->getAddr16(x, y);
132 if (src != span) {
133 memcpy(span, src, count << 1);
134 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000135}
136