|
1 /* |
|
2 * Copyright 2006 The Android Open Source Project |
|
3 * |
|
4 * Use of this source code is governed by a BSD-style license that can be |
|
5 * found in the LICENSE file. |
|
6 */ |
|
7 |
|
8 #include "SkBitmapProcShader.h" |
|
9 #include "SkReadBuffer.h" |
|
10 #include "SkMallocPixelRef.h" |
|
11 #include "SkPaint.h" |
|
12 #include "SkScalar.h" |
|
13 #include "SkShader.h" |
|
14 #include "SkWriteBuffer.h" |
|
15 |
|
16 SkShader::SkShader() { |
|
17 fLocalMatrix.reset(); |
|
18 SkDEBUGCODE(fInSetContext = false;) |
|
19 } |
|
20 |
|
21 SkShader::SkShader(SkReadBuffer& buffer) |
|
22 : INHERITED(buffer) { |
|
23 if (buffer.readBool()) { |
|
24 buffer.readMatrix(&fLocalMatrix); |
|
25 } else { |
|
26 fLocalMatrix.reset(); |
|
27 } |
|
28 |
|
29 SkDEBUGCODE(fInSetContext = false;) |
|
30 } |
|
31 |
|
32 SkShader::~SkShader() { |
|
33 SkASSERT(!fInSetContext); |
|
34 } |
|
35 |
|
36 void SkShader::flatten(SkWriteBuffer& buffer) const { |
|
37 this->INHERITED::flatten(buffer); |
|
38 bool hasLocalM = this->hasLocalMatrix(); |
|
39 buffer.writeBool(hasLocalM); |
|
40 if (hasLocalM) { |
|
41 buffer.writeMatrix(fLocalMatrix); |
|
42 } |
|
43 } |
|
44 |
|
45 bool SkShader::setContext(const SkBitmap& device, |
|
46 const SkPaint& paint, |
|
47 const SkMatrix& matrix) { |
|
48 SkASSERT(!this->setContextHasBeenCalled()); |
|
49 |
|
50 const SkMatrix* m = &matrix; |
|
51 SkMatrix total; |
|
52 |
|
53 fPaintAlpha = paint.getAlpha(); |
|
54 if (this->hasLocalMatrix()) { |
|
55 total.setConcat(matrix, this->getLocalMatrix()); |
|
56 m = &total; |
|
57 } |
|
58 if (m->invert(&fTotalInverse)) { |
|
59 fTotalInverseClass = (uint8_t)ComputeMatrixClass(fTotalInverse); |
|
60 SkDEBUGCODE(fInSetContext = true;) |
|
61 return true; |
|
62 } |
|
63 return false; |
|
64 } |
|
65 |
|
66 void SkShader::endContext() { |
|
67 SkASSERT(fInSetContext); |
|
68 SkDEBUGCODE(fInSetContext = false;) |
|
69 } |
|
70 |
|
71 SkShader::ShadeProc SkShader::asAShadeProc(void** ctx) { |
|
72 return NULL; |
|
73 } |
|
74 |
|
75 #include "SkColorPriv.h" |
|
76 |
|
77 void SkShader::shadeSpan16(int x, int y, uint16_t span16[], int count) { |
|
78 SkASSERT(span16); |
|
79 SkASSERT(count > 0); |
|
80 SkASSERT(this->canCallShadeSpan16()); |
|
81 |
|
82 // basically, if we get here, the subclass screwed up |
|
83 SkDEBUGFAIL("kHasSpan16 flag is set, but shadeSpan16() not implemented"); |
|
84 } |
|
85 |
|
86 #define kTempColorQuadCount 6 // balance between speed (larger) and saving stack-space |
|
87 #define kTempColorCount (kTempColorQuadCount << 2) |
|
88 |
|
89 #ifdef SK_CPU_BENDIAN |
|
90 #define SkU32BitShiftToByteOffset(shift) (3 - ((shift) >> 3)) |
|
91 #else |
|
92 #define SkU32BitShiftToByteOffset(shift) ((shift) >> 3) |
|
93 #endif |
|
94 |
|
95 void SkShader::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) { |
|
96 SkASSERT(count > 0); |
|
97 |
|
98 SkPMColor colors[kTempColorCount]; |
|
99 |
|
100 while ((count -= kTempColorCount) >= 0) { |
|
101 this->shadeSpan(x, y, colors, kTempColorCount); |
|
102 x += kTempColorCount; |
|
103 |
|
104 const uint8_t* srcA = (const uint8_t*)colors + SkU32BitShiftToByteOffset(SK_A32_SHIFT); |
|
105 int quads = kTempColorQuadCount; |
|
106 do { |
|
107 U8CPU a0 = srcA[0]; |
|
108 U8CPU a1 = srcA[4]; |
|
109 U8CPU a2 = srcA[8]; |
|
110 U8CPU a3 = srcA[12]; |
|
111 srcA += 4*4; |
|
112 *alpha++ = SkToU8(a0); |
|
113 *alpha++ = SkToU8(a1); |
|
114 *alpha++ = SkToU8(a2); |
|
115 *alpha++ = SkToU8(a3); |
|
116 } while (--quads != 0); |
|
117 } |
|
118 SkASSERT(count < 0); |
|
119 SkASSERT(count + kTempColorCount >= 0); |
|
120 if (count += kTempColorCount) { |
|
121 this->shadeSpan(x, y, colors, count); |
|
122 |
|
123 const uint8_t* srcA = (const uint8_t*)colors + SkU32BitShiftToByteOffset(SK_A32_SHIFT); |
|
124 do { |
|
125 *alpha++ = *srcA; |
|
126 srcA += 4; |
|
127 } while (--count != 0); |
|
128 } |
|
129 #if 0 |
|
130 do { |
|
131 int n = count; |
|
132 if (n > kTempColorCount) |
|
133 n = kTempColorCount; |
|
134 SkASSERT(n > 0); |
|
135 |
|
136 this->shadeSpan(x, y, colors, n); |
|
137 x += n; |
|
138 count -= n; |
|
139 |
|
140 const uint8_t* srcA = (const uint8_t*)colors + SkU32BitShiftToByteOffset(SK_A32_SHIFT); |
|
141 do { |
|
142 *alpha++ = *srcA; |
|
143 srcA += 4; |
|
144 } while (--n != 0); |
|
145 } while (count > 0); |
|
146 #endif |
|
147 } |
|
148 |
|
149 SkShader::MatrixClass SkShader::ComputeMatrixClass(const SkMatrix& mat) { |
|
150 MatrixClass mc = kLinear_MatrixClass; |
|
151 |
|
152 if (mat.hasPerspective()) { |
|
153 if (mat.fixedStepInX(0, NULL, NULL)) { |
|
154 mc = kFixedStepInX_MatrixClass; |
|
155 } else { |
|
156 mc = kPerspective_MatrixClass; |
|
157 } |
|
158 } |
|
159 return mc; |
|
160 } |
|
161 |
|
162 ////////////////////////////////////////////////////////////////////////////// |
|
163 |
|
164 SkShader::BitmapType SkShader::asABitmap(SkBitmap*, SkMatrix*, |
|
165 TileMode*) const { |
|
166 return kNone_BitmapType; |
|
167 } |
|
168 |
|
169 SkShader::GradientType SkShader::asAGradient(GradientInfo* info) const { |
|
170 return kNone_GradientType; |
|
171 } |
|
172 |
|
173 GrEffectRef* SkShader::asNewEffect(GrContext*, const SkPaint&) const { |
|
174 return NULL; |
|
175 } |
|
176 |
|
177 SkShader* SkShader::CreateBitmapShader(const SkBitmap& src, |
|
178 TileMode tmx, TileMode tmy) { |
|
179 return ::CreateBitmapShader(src, tmx, tmy, NULL); |
|
180 } |
|
181 |
|
182 #ifndef SK_IGNORE_TO_STRING |
|
183 void SkShader::toString(SkString* str) const { |
|
184 if (this->hasLocalMatrix()) { |
|
185 str->append(" "); |
|
186 this->getLocalMatrix().toString(str); |
|
187 } |
|
188 } |
|
189 #endif |
|
190 |
|
191 ////////////////////////////////////////////////////////////////////////////// |
|
192 |
|
193 #include "SkColorShader.h" |
|
194 #include "SkUtils.h" |
|
195 |
|
196 SkColorShader::SkColorShader() { |
|
197 fFlags = 0; |
|
198 fInheritColor = true; |
|
199 } |
|
200 |
|
201 SkColorShader::SkColorShader(SkColor c) { |
|
202 fFlags = 0; |
|
203 fColor = c; |
|
204 fInheritColor = false; |
|
205 } |
|
206 |
|
207 SkColorShader::~SkColorShader() {} |
|
208 |
|
209 bool SkColorShader::isOpaque() const { |
|
210 if (fInheritColor) { |
|
211 return true; // using paint's alpha |
|
212 } |
|
213 return SkColorGetA(fColor) == 255; |
|
214 } |
|
215 |
|
216 SkColorShader::SkColorShader(SkReadBuffer& b) : INHERITED(b) { |
|
217 fFlags = 0; // computed in setContext |
|
218 |
|
219 fInheritColor = b.readBool(); |
|
220 if (fInheritColor) { |
|
221 return; |
|
222 } |
|
223 fColor = b.readColor(); |
|
224 } |
|
225 |
|
226 void SkColorShader::flatten(SkWriteBuffer& buffer) const { |
|
227 this->INHERITED::flatten(buffer); |
|
228 buffer.writeBool(fInheritColor); |
|
229 if (fInheritColor) { |
|
230 return; |
|
231 } |
|
232 buffer.writeColor(fColor); |
|
233 } |
|
234 |
|
235 uint32_t SkColorShader::getFlags() { |
|
236 return fFlags; |
|
237 } |
|
238 |
|
239 uint8_t SkColorShader::getSpan16Alpha() const { |
|
240 return SkGetPackedA32(fPMColor); |
|
241 } |
|
242 |
|
243 bool SkColorShader::setContext(const SkBitmap& device, const SkPaint& paint, |
|
244 const SkMatrix& matrix) { |
|
245 if (!this->INHERITED::setContext(device, paint, matrix)) { |
|
246 return false; |
|
247 } |
|
248 |
|
249 unsigned a; |
|
250 |
|
251 if (fInheritColor) { |
|
252 fColor = paint.getColor(); |
|
253 a = SkColorGetA(fColor); |
|
254 } else { |
|
255 a = SkAlphaMul(SkColorGetA(fColor), SkAlpha255To256(paint.getAlpha())); |
|
256 } |
|
257 |
|
258 unsigned r = SkColorGetR(fColor); |
|
259 unsigned g = SkColorGetG(fColor); |
|
260 unsigned b = SkColorGetB(fColor); |
|
261 |
|
262 // we want this before we apply any alpha |
|
263 fColor16 = SkPack888ToRGB16(r, g, b); |
|
264 |
|
265 if (a != 255) { |
|
266 r = SkMulDiv255Round(r, a); |
|
267 g = SkMulDiv255Round(g, a); |
|
268 b = SkMulDiv255Round(b, a); |
|
269 } |
|
270 fPMColor = SkPackARGB32(a, r, g, b); |
|
271 |
|
272 fFlags = kConstInY32_Flag; |
|
273 if (255 == a) { |
|
274 fFlags |= kOpaqueAlpha_Flag; |
|
275 if (paint.isDither() == false) { |
|
276 fFlags |= kHasSpan16_Flag; |
|
277 } |
|
278 } |
|
279 |
|
280 return true; |
|
281 } |
|
282 |
|
283 void SkColorShader::shadeSpan(int x, int y, SkPMColor span[], int count) { |
|
284 sk_memset32(span, fPMColor, count); |
|
285 } |
|
286 |
|
287 void SkColorShader::shadeSpan16(int x, int y, uint16_t span[], int count) { |
|
288 sk_memset16(span, fColor16, count); |
|
289 } |
|
290 |
|
291 void SkColorShader::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) { |
|
292 memset(alpha, SkGetPackedA32(fPMColor), count); |
|
293 } |
|
294 |
|
295 // if we had a asAColor method, that would be more efficient... |
|
296 SkShader::BitmapType SkColorShader::asABitmap(SkBitmap* bitmap, SkMatrix* matrix, |
|
297 TileMode modes[]) const { |
|
298 return kNone_BitmapType; |
|
299 } |
|
300 |
|
301 SkShader::GradientType SkColorShader::asAGradient(GradientInfo* info) const { |
|
302 if (info) { |
|
303 if (info->fColors && info->fColorCount >= 1) { |
|
304 info->fColors[0] = fColor; |
|
305 } |
|
306 info->fColorCount = 1; |
|
307 info->fTileMode = SkShader::kRepeat_TileMode; |
|
308 } |
|
309 return kColor_GradientType; |
|
310 } |
|
311 |
|
312 #ifndef SK_IGNORE_TO_STRING |
|
313 void SkColorShader::toString(SkString* str) const { |
|
314 str->append("SkColorShader: ("); |
|
315 |
|
316 if (fInheritColor) { |
|
317 str->append("Color: inherited from paint"); |
|
318 } else { |
|
319 str->append("Color: "); |
|
320 str->appendHex(fColor); |
|
321 } |
|
322 |
|
323 this->INHERITED::toString(str); |
|
324 |
|
325 str->append(")"); |
|
326 } |
|
327 #endif |
|
328 |
|
329 /////////////////////////////////////////////////////////////////////////////// |
|
330 |
|
331 #include "SkEmptyShader.h" |
|
332 |
|
333 uint32_t SkEmptyShader::getFlags() { return 0; } |
|
334 uint8_t SkEmptyShader::getSpan16Alpha() const { return 0; } |
|
335 |
|
336 bool SkEmptyShader::setContext(const SkBitmap&, const SkPaint&, |
|
337 const SkMatrix&) { return false; } |
|
338 |
|
339 void SkEmptyShader::shadeSpan(int x, int y, SkPMColor span[], int count) { |
|
340 SkDEBUGFAIL("should never get called, since setContext() returned false"); |
|
341 } |
|
342 |
|
343 void SkEmptyShader::shadeSpan16(int x, int y, uint16_t span[], int count) { |
|
344 SkDEBUGFAIL("should never get called, since setContext() returned false"); |
|
345 } |
|
346 |
|
347 void SkEmptyShader::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) { |
|
348 SkDEBUGFAIL("should never get called, since setContext() returned false"); |
|
349 } |
|
350 |
|
351 #ifndef SK_IGNORE_TO_STRING |
|
352 void SkEmptyShader::toString(SkString* str) const { |
|
353 str->append("SkEmptyShader: ("); |
|
354 |
|
355 this->INHERITED::toString(str); |
|
356 |
|
357 str->append(")"); |
|
358 } |
|
359 #endif |