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