SkShader.cpp revision 2be9e8b407624fa696854b78b407b97a01dbb703
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
23SkShader::SkShader() : fLocalMatrix(NULL) {
24    SkDEBUGCODE(fInSession = false;)
25}
26
27SkShader::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
37SkShader::~SkShader() {
38    SkASSERT(!fInSession);
39    sk_free(fLocalMatrix);
40}
41
42void SkShader::beginSession() {
43    SkASSERT(!fInSession);
44    SkDEBUGCODE(fInSession = true;)
45}
46
47void SkShader::endSession() {
48    SkASSERT(fInSession);
49    SkDEBUGCODE(fInSession = false;)
50}
51
52void SkShader::flatten(SkFlattenableWriteBuffer& buffer) {
53    this->INHERITED::flatten(buffer);
54    buffer.writeBool(fLocalMatrix != NULL);
55    if (fLocalMatrix) {
56        SkWriteMatrix(&buffer, *fLocalMatrix);
57    }
58}
59
60bool 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
74void 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
85void SkShader::resetLocalMatrix() {
86    if (fLocalMatrix) {
87        sk_free(fLocalMatrix);
88        fLocalMatrix = NULL;
89    }
90}
91
92bool 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
113void 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
131void 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
185SkShader::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
200SkShader::BitmapType SkShader::asABitmap(SkBitmap*, SkMatrix*,
201                                         TileMode*, SkScalar*) const {
202    return kNone_BitmapType;
203}
204
205SkShader::GradientType SkShader::asAGradient(GradientInfo* info) const {
206    return kNone_GradientType;
207}
208
209SkShader* 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
219SkColorShader::SkColorShader() {
220    fFlags = 0;
221    fInheritColor = true;
222}
223
224SkColorShader::SkColorShader(SkColor c) {
225    fFlags = 0;
226    fColor = c;
227    fInheritColor = false;
228}
229
230SkColorShader::~SkColorShader() {}
231
232SkColorShader::SkColorShader(SkFlattenableReadBuffer& b) : INHERITED(b) {
233    fFlags = 0; // computed in setContext
234
235    fInheritColor = b.readU8();
236    if (fInheritColor) {
237        return;
238    }
239    fColor = b.readU32();
240}
241
242void SkColorShader::flatten(SkFlattenableWriteBuffer& buffer) {
243    this->INHERITED::flatten(buffer);
244    buffer.write8(fInheritColor);
245    if (fInheritColor) {
246        return;
247    }
248    buffer.write32(fColor);
249}
250
251uint8_t SkColorShader::getSpan16Alpha() const {
252    return SkGetPackedA32(fPMColor);
253}
254
255bool SkColorShader::setContext(const SkBitmap& device, const SkPaint& paint,
256                               const SkMatrix& matrix) {
257    if (!this->INHERITED::setContext(device, paint, matrix)) {
258        return false;
259    }
260
261    unsigned a;
262
263    if (fInheritColor) {
264        fColor = paint.getColor();
265        a = SkColorGetA(fColor);
266    } else {
267        a = SkAlphaMul(SkColorGetA(fColor), SkAlpha255To256(paint.getAlpha()));
268    }
269
270    unsigned r = SkColorGetR(fColor);
271    unsigned g = SkColorGetG(fColor);
272    unsigned b = SkColorGetB(fColor);
273
274    // we want this before we apply any alpha
275    fColor16 = SkPack888ToRGB16(r, g, b);
276
277    if (a != 255) {
278        r = SkMulDiv255Round(r, a);
279        g = SkMulDiv255Round(g, a);
280        b = SkMulDiv255Round(b, a);
281    }
282    fPMColor = SkPackARGB32(a, r, g, b);
283
284    fFlags = kConstInY32_Flag;
285    if (255 == a) {
286        fFlags |= kOpaqueAlpha_Flag;
287        if (paint.isDither() == false) {
288            fFlags |= kHasSpan16_Flag;
289        }
290    }
291
292    return true;
293}
294
295void SkColorShader::shadeSpan(int x, int y, SkPMColor span[], int count) {
296    sk_memset32(span, fPMColor, count);
297}
298
299void SkColorShader::shadeSpan16(int x, int y, uint16_t span[], int count) {
300    sk_memset16(span, fColor16, count);
301}
302
303void SkColorShader::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) {
304    memset(alpha, SkGetPackedA32(fPMColor), count);
305}
306
307// if we had a asAColor method, that would be more efficient...
308SkShader::BitmapType SkColorShader::asABitmap(SkBitmap* bitmap, SkMatrix* matrix,
309                                              TileMode modes[],
310                                      SkScalar* twoPointRadialParams) const {
311    return kNone_BitmapType;
312}
313
314SkShader::GradientType SkColorShader::asAGradient(GradientInfo* info) const {
315    if (info) {
316        if (info->fColors && info->fColorCount >= 1) {
317            info->fColors[0] = fColor;
318        }
319        info->fColorCount = 1;
320        info->fTileMode = SkShader::kRepeat_TileMode;
321    }
322    return kColor_GradientType;
323}
324
325///////////////////////////////////////////////////////////////////////////////
326
327#include "SkEmptyShader.h"
328
329SkEmptyShader::SkEmptyShader() {}
330SkEmptyShader::SkEmptyShader(SkFlattenableReadBuffer& b) : INHERITED(b) {}
331
332uint32_t SkEmptyShader::getFlags() { return 0; }
333uint8_t SkEmptyShader::getSpan16Alpha() const { return 0; }
334bool SkEmptyShader::setContext(const SkBitmap& device, const SkPaint& paint,
335                               const SkMatrix& matrix) {
336    return false;
337}
338void SkEmptyShader::shadeSpan(int x, int y, SkPMColor span[], int count) {}
339void SkEmptyShader::shadeSpan16(int x, int y, uint16_t span[], int count) {}
340void SkEmptyShader::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) {}
341
342SkFlattenable::Factory SkEmptyShader::getFactory() { return NULL; }
343void SkEmptyShader::flatten(SkFlattenableWriteBuffer& buffer) {
344    this->INHERITED::flatten(buffer);
345}
346
347