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