• 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 "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