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