blob: c6caba316529b280268c2ac7ed20a0a223d3e6a8 [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) {
56 memcpy(span, fDevice->getAddr32(x, y), count * sizeof(SkPMColor));
57 } else {
58 const SkPMColor* src = fDevice->getAddr32(x, y);
59 for (int i = count - 1; i >= 0; --i) {
60 span[i] = SkAlphaMulQ(src[i], scale);
61 }
reed@android.com8a1c16f2008-12-17 15:59:43 +000062 }
mike@reedtribe.org3334c3a2011-04-20 11:39:28 +000063 break;
64 case SkBitmap::kRGB_565_Config: {
65 const uint16_t* src = fDevice->getAddr16(x, y);
66 if (scale == 256) {
67 for (int i = count - 1; i >= 0; --i) {
68 span[i] = SkPixel16ToPixel32(src[i]);
69 }
70 } else {
reed@android.com8a1c16f2008-12-17 15:59:43 +000071 unsigned alpha = fAlpha;
mike@reedtribe.org3334c3a2011-04-20 11:39:28 +000072 for (int i = count - 1; i >= 0; --i) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000073 uint16_t c = src[i];
74 unsigned r = SkPacked16ToR32(c);
75 unsigned g = SkPacked16ToG32(c);
76 unsigned b = SkPacked16ToB32(c);
77
78 span[i] = SkPackARGB32( alpha,
79 SkAlphaMul(r, scale),
80 SkAlphaMul(g, scale),
81 SkAlphaMul(b, scale));
82 }
83 }
mike@reedtribe.org3334c3a2011-04-20 11:39:28 +000084 break;
reed@android.com8a1c16f2008-12-17 15:59:43 +000085 }
mike@reedtribe.org3334c3a2011-04-20 11:39:28 +000086 case SkBitmap::kARGB_4444_Config: {
reed@android.com8a1c16f2008-12-17 15:59:43 +000087 const uint16_t* src = fDevice->getAddr16(x, y);
mike@reedtribe.org3334c3a2011-04-20 11:39:28 +000088 if (scale == 256) {
89 for (int i = count - 1; i >= 0; --i) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000090 span[i] = SkPixel4444ToPixel32(src[i]);
mike@reedtribe.org3334c3a2011-04-20 11:39:28 +000091 }
92 } else {
reed@android.com8a1c16f2008-12-17 15:59:43 +000093 unsigned scale16 = scale >> 4;
mike@reedtribe.org3334c3a2011-04-20 11:39:28 +000094 for (int i = count - 1; i >= 0; --i) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000095 uint32_t c = SkExpand_4444(src[i]) * scale16;
96 span[i] = SkCompact_8888(c);
97 }
98 }
reed@android.com8a1c16f2008-12-17 15:59:43 +000099 break;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000100 }
mike@reedtribe.org3334c3a2011-04-20 11:39:28 +0000101 case SkBitmap::kIndex8_Config:
102 SkASSERT(!"index8 not supported as a destination device");
103 break;
104 case SkBitmap::kA8_Config: {
105 const uint8_t* src = fDevice->getAddr8(x, y);
106 if (scale == 256) {
107 for (int i = count - 1; i >= 0; --i) {
108 span[i] = SkPackARGB32(src[i], 0, 0, 0);
109 }
110 } else {
111 for (int i = count - 1; i >= 0; --i) {
112 span[i] = SkPackARGB32(SkAlphaMul(src[i], scale), 0, 0, 0);
113 }
114 }
115 break;
116 }
117 case SkBitmap::kA1_Config:
118 SkASSERT(!"kA1_Config umimplemented at this time");
119 break;
120 default: // to avoid warnings
121 break;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000122 }
123}
124
mike@reedtribe.org3334c3a2011-04-20 11:39:28 +0000125void SkTransparentShader::shadeSpan16(int x, int y, uint16_t span[], int count) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000126 SkASSERT(fDevice->getConfig() == SkBitmap::kRGB_565_Config);
127
128 memcpy(span, fDevice->getAddr16(x, y), count << 1);
129}
130