1 /* libs/graphics/sgl/SkShader.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 "SkShader.h"
19 #include "SkPaint.h"
20
SkShader()21 SkShader::SkShader() : fLocalMatrix(NULL) {
22 SkDEBUGCODE(fInSession = false;)
23 }
24
SkShader(SkFlattenableReadBuffer & buffer)25 SkShader::SkShader(SkFlattenableReadBuffer& buffer)
26 : INHERITED(buffer), fLocalMatrix(NULL) {
27 if (buffer.readBool()) {
28 SkMatrix matrix;
29 buffer.read(&matrix, sizeof(matrix));
30 setLocalMatrix(matrix);
31 }
32 SkDEBUGCODE(fInSession = false;)
33 }
34
~SkShader()35 SkShader::~SkShader() {
36 SkASSERT(!fInSession);
37 sk_free(fLocalMatrix);
38 }
39
beginSession()40 void SkShader::beginSession() {
41 SkASSERT(!fInSession);
42 SkDEBUGCODE(fInSession = true;)
43 }
44
endSession()45 void SkShader::endSession() {
46 SkASSERT(fInSession);
47 SkDEBUGCODE(fInSession = false;)
48 }
49
flatten(SkFlattenableWriteBuffer & buffer)50 void SkShader::flatten(SkFlattenableWriteBuffer& buffer) {
51 this->INHERITED::flatten(buffer);
52 buffer.writeBool(fLocalMatrix != NULL);
53 if (fLocalMatrix) {
54 buffer.writeMul4(fLocalMatrix, sizeof(SkMatrix));
55 }
56 }
57
getLocalMatrix(SkMatrix * localM) const58 bool SkShader::getLocalMatrix(SkMatrix* localM) const {
59 if (fLocalMatrix) {
60 if (localM) {
61 *localM = *fLocalMatrix;
62 }
63 return true;
64 } else {
65 if (localM) {
66 localM->reset();
67 }
68 return false;
69 }
70 }
71
setLocalMatrix(const SkMatrix & localM)72 void SkShader::setLocalMatrix(const SkMatrix& localM) {
73 if (localM.isIdentity()) {
74 this->resetLocalMatrix();
75 } else {
76 if (fLocalMatrix == NULL) {
77 fLocalMatrix = (SkMatrix*)sk_malloc_throw(sizeof(SkMatrix));
78 }
79 *fLocalMatrix = localM;
80 }
81 }
82
resetLocalMatrix()83 void SkShader::resetLocalMatrix() {
84 if (fLocalMatrix) {
85 sk_free(fLocalMatrix);
86 fLocalMatrix = NULL;
87 }
88 }
89
setContext(const SkBitmap & device,const SkPaint & paint,const SkMatrix & matrix)90 bool SkShader::setContext(const SkBitmap& device,
91 const SkPaint& paint,
92 const SkMatrix& matrix) {
93 const SkMatrix* m = &matrix;
94 SkMatrix total;
95
96 fDeviceConfig = SkToU8(device.getConfig());
97 fPaintAlpha = paint.getAlpha();
98 if (fLocalMatrix) {
99 total.setConcat(matrix, *fLocalMatrix);
100 m = &total;
101 }
102 if (m->invert(&fTotalInverse)) {
103 fTotalInverseClass = (uint8_t)ComputeMatrixClass(fTotalInverse);
104 return true;
105 }
106 return false;
107 }
108
109 #include "SkColorPriv.h"
110
shadeSpan16(int x,int y,uint16_t span16[],int count)111 void SkShader::shadeSpan16(int x, int y, uint16_t span16[], int count) {
112 SkASSERT(span16);
113 SkASSERT(count > 0);
114 SkASSERT(this->canCallShadeSpan16());
115
116 // basically, if we get here, the subclass screwed up
117 SkASSERT(!"kHasSpan16 flag is set, but shadeSpan16() not implemented");
118 }
119
120 #define kTempColorQuadCount 6 // balance between speed (larger) and saving stack-space
121 #define kTempColorCount (kTempColorQuadCount << 2)
122
123 #ifdef SK_CPU_BENDIAN
124 #define SkU32BitShiftToByteOffset(shift) (3 - ((shift) >> 3))
125 #else
126 #define SkU32BitShiftToByteOffset(shift) ((shift) >> 3)
127 #endif
128
shadeSpanAlpha(int x,int y,uint8_t alpha[],int count)129 void SkShader::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) {
130 SkASSERT(count > 0);
131
132 SkPMColor colors[kTempColorCount];
133
134 while ((count -= kTempColorCount) >= 0) {
135 this->shadeSpan(x, y, colors, kTempColorCount);
136 x += kTempColorCount;
137
138 const uint8_t* srcA = (const uint8_t*)colors + SkU32BitShiftToByteOffset(SK_A32_SHIFT);
139 int quads = kTempColorQuadCount;
140 do {
141 U8CPU a0 = srcA[0];
142 U8CPU a1 = srcA[4];
143 U8CPU a2 = srcA[8];
144 U8CPU a3 = srcA[12];
145 srcA += 4*4;
146 *alpha++ = SkToU8(a0);
147 *alpha++ = SkToU8(a1);
148 *alpha++ = SkToU8(a2);
149 *alpha++ = SkToU8(a3);
150 } while (--quads != 0);
151 }
152 SkASSERT(count < 0);
153 SkASSERT(count + kTempColorCount >= 0);
154 if (count += kTempColorCount) {
155 this->shadeSpan(x, y, colors, count);
156
157 const uint8_t* srcA = (const uint8_t*)colors + SkU32BitShiftToByteOffset(SK_A32_SHIFT);
158 do {
159 *alpha++ = *srcA;
160 srcA += 4;
161 } while (--count != 0);
162 }
163 #if 0
164 do {
165 int n = count;
166 if (n > kTempColorCount)
167 n = kTempColorCount;
168 SkASSERT(n > 0);
169
170 this->shadeSpan(x, y, colors, n);
171 x += n;
172 count -= n;
173
174 const uint8_t* srcA = (const uint8_t*)colors + SkU32BitShiftToByteOffset(SK_A32_SHIFT);
175 do {
176 *alpha++ = *srcA;
177 srcA += 4;
178 } while (--n != 0);
179 } while (count > 0);
180 #endif
181 }
182
ComputeMatrixClass(const SkMatrix & mat)183 SkShader::MatrixClass SkShader::ComputeMatrixClass(const SkMatrix& mat) {
184 MatrixClass mc = kLinear_MatrixClass;
185
186 if (mat.getType() & SkMatrix::kPerspective_Mask) {
187 if (mat.fixedStepInX(0, NULL, NULL)) {
188 mc = kFixedStepInX_MatrixClass;
189 } else {
190 mc = kPerspective_MatrixClass;
191 }
192 }
193 return mc;
194 }
195
196 //////////////////////////////////////////////////////////////////////////////
197
asABitmap(SkBitmap *,SkMatrix *,TileMode *)198 bool SkShader::asABitmap(SkBitmap*, SkMatrix*, TileMode*) {
199 return false;
200 }
201
CreateBitmapShader(const SkBitmap & src,TileMode tmx,TileMode tmy)202 SkShader* SkShader::CreateBitmapShader(const SkBitmap& src,
203 TileMode tmx, TileMode tmy) {
204 return SkShader::CreateBitmapShader(src, tmx, tmy, NULL, 0);
205 }
206
207 //////////////////////////////////////////////////////////////////////////////
208
209 #include "SkColorShader.h"
210 #include "SkUtils.h"
211
SkColorShader(SkFlattenableReadBuffer & b)212 SkColorShader::SkColorShader(SkFlattenableReadBuffer& b) : INHERITED(b) {
213 fFlags = 0; // computed in setContext
214 fInheritColor = b.readU8();
215 if (fInheritColor) {
216 return;
217 }
218 fColor = b.readU32();
219 }
220
flatten(SkFlattenableWriteBuffer & buffer)221 void SkColorShader::flatten(SkFlattenableWriteBuffer& buffer) {
222 this->INHERITED::flatten(buffer);
223 buffer.write8(fInheritColor);
224 if (fInheritColor) {
225 return;
226 }
227 buffer.write32(fColor);
228 }
229
getSpan16Alpha() const230 uint8_t SkColorShader::getSpan16Alpha() const {
231 return SkGetPackedA32(fPMColor);
232 }
233
setContext(const SkBitmap & device,const SkPaint & paint,const SkMatrix & matrix)234 bool SkColorShader::setContext(const SkBitmap& device, const SkPaint& paint,
235 const SkMatrix& matrix) {
236 if (!this->INHERITED::setContext(device, paint, matrix)) {
237 return false;
238 }
239
240 SkColor c;
241 unsigned a;
242
243 if (fInheritColor) {
244 c = paint.getColor();
245 a = SkColorGetA(c);
246 } else {
247 c = fColor;
248 a = SkAlphaMul(SkColorGetA(c), SkAlpha255To256(paint.getAlpha()));
249 }
250
251 unsigned r = SkColorGetR(c);
252 unsigned g = SkColorGetG(c);
253 unsigned b = SkColorGetB(c);
254
255 // we want this before we apply any alpha
256 fColor16 = SkPack888ToRGB16(r, g, b);
257
258 if (a != 255) {
259 a = SkAlpha255To256(a);
260 r = SkAlphaMul(r, a);
261 g = SkAlphaMul(g, a);
262 b = SkAlphaMul(b, a);
263 }
264 fPMColor = SkPackARGB32(a, r, g, b);
265
266 fFlags = kHasSpan16_Flag | kConstInY32_Flag;
267 if (SkGetPackedA32(fPMColor) == 255) {
268 fFlags |= kOpaqueAlpha_Flag;
269 }
270
271 return true;
272 }
273
shadeSpan(int x,int y,SkPMColor span[],int count)274 void SkColorShader::shadeSpan(int x, int y, SkPMColor span[], int count) {
275 sk_memset32(span, fPMColor, count);
276 }
277
shadeSpan16(int x,int y,uint16_t span[],int count)278 void SkColorShader::shadeSpan16(int x, int y, uint16_t span[], int count) {
279 sk_memset16(span, fColor16, count);
280 }
281
shadeSpanAlpha(int x,int y,uint8_t alpha[],int count)282 void SkColorShader::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) {
283 memset(alpha, SkGetPackedA32(fPMColor), count);
284 }
285
286