SkShader.cpp revision 8a1c16ff38322f0210116fa7293eb8817c7e477e
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
21SkShader::SkShader() : fLocalMatrix(NULL) {
22    SkDEBUGCODE(fInSession = false;)
23}
24
25SkShader::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
35SkShader::~SkShader() {
36    SkASSERT(!fInSession);
37    sk_free(fLocalMatrix);
38}
39
40void SkShader::beginSession() {
41    SkASSERT(!fInSession);
42    SkDEBUGCODE(fInSession = true;)
43}
44
45void SkShader::endSession() {
46    SkASSERT(fInSession);
47    SkDEBUGCODE(fInSession = false;)
48}
49
50void 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
58bool 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
72void 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
83void SkShader::resetLocalMatrix() {
84    if (fLocalMatrix) {
85        sk_free(fLocalMatrix);
86        fLocalMatrix = NULL;
87    }
88}
89
90bool 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
111void 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
129void 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
183SkShader::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
198bool SkShader::asABitmap(SkBitmap*, SkMatrix*, TileMode*) {
199    return false;
200}
201
202SkShader* 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
212SkColorShader::SkColorShader(SkFlattenableReadBuffer& b) : INHERITED(b) {
213    fInheritColor = b.readU8();
214    if (fInheritColor) {
215        return;
216    }
217    fColor = b.readU32();
218}
219
220void SkColorShader::flatten(SkFlattenableWriteBuffer& buffer) {
221    this->INHERITED::flatten(buffer);
222    buffer.write8(fInheritColor);
223    if (fInheritColor) {
224        return;
225    }
226    buffer.write32(fColor);
227}
228
229uint32_t SkColorShader::getFlags() {
230    return (SkGetPackedA32(fPMColor) == 255 ? kOpaqueAlpha_Flag : 0) |
231            kHasSpan16_Flag;
232}
233
234uint8_t SkColorShader::getSpan16Alpha() const {
235    return SkGetPackedA32(fPMColor);
236}
237
238bool SkColorShader::setContext(const SkBitmap& device, const SkPaint& paint,
239                               const SkMatrix& matrix) {
240    if (!this->INHERITED::setContext(device, paint, matrix)) {
241        return false;
242    }
243
244    SkColor c;
245    unsigned a;
246
247    if (fInheritColor) {
248        c = paint.getColor();
249        a = SkColorGetA(c);
250    } else {
251        c = fColor;
252        a = SkAlphaMul(SkColorGetA(c), SkAlpha255To256(paint.getAlpha()));
253    }
254
255    unsigned r = SkColorGetR(c);
256    unsigned g = SkColorGetG(c);
257    unsigned b = SkColorGetB(c);
258
259    // we want this before we apply any alpha
260    fColor16 = SkPack888ToRGB16(r, g, b);
261
262    if (a != 255) {
263        a = SkAlpha255To256(a);
264        r = SkAlphaMul(r, a);
265        g = SkAlphaMul(g, a);
266        b = SkAlphaMul(b, a);
267    }
268    fPMColor = SkPackARGB32(a, r, g, b);
269
270    return true;
271}
272
273void SkColorShader::shadeSpan(int x, int y, SkPMColor span[], int count) {
274    sk_memset32(span, fPMColor, count);
275}
276
277void SkColorShader::shadeSpan16(int x, int y, uint16_t span[], int count) {
278    sk_memset16(span, fColor16, count);
279}
280
281void SkColorShader::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) {
282    memset(alpha, SkGetPackedA32(fPMColor), count);
283}
284
285