Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / src / core / SkShader.cpp
1 /*
2  * Copyright 2006 The Android Open Source Project
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7
8 #include "SkBitmapProcShader.h"
9 #include "SkEmptyShader.h"
10 #include "SkReadBuffer.h"
11 #include "SkMallocPixelRef.h"
12 #include "SkPaint.h"
13 #include "SkPicture.h"
14 #include "SkPictureShader.h"
15 #include "SkScalar.h"
16 #include "SkShader.h"
17 #include "SkWriteBuffer.h"
18
19 SkShader::SkShader(const SkMatrix* localMatrix) {
20     if (localMatrix) {
21         fLocalMatrix = *localMatrix;
22     } else {
23         fLocalMatrix.reset();
24     }
25 }
26
27 SkShader::SkShader(SkReadBuffer& buffer)
28         : INHERITED(buffer) {
29     if (buffer.readBool()) {
30         buffer.readMatrix(&fLocalMatrix);
31     } else {
32         fLocalMatrix.reset();
33     }
34 }
35
36 SkShader::~SkShader() {
37 }
38
39 void SkShader::flatten(SkWriteBuffer& buffer) const {
40     this->INHERITED::flatten(buffer);
41     bool hasLocalM = this->hasLocalMatrix();
42     buffer.writeBool(hasLocalM);
43     if (hasLocalM) {
44         buffer.writeMatrix(fLocalMatrix);
45     }
46 }
47
48 bool SkShader::computeTotalInverse(const ContextRec& rec, SkMatrix* totalInverse) const {
49     const SkMatrix* m = rec.fMatrix;
50     SkMatrix        total;
51
52     if (this->hasLocalMatrix()) {
53         total.setConcat(*m, this->getLocalMatrix());
54         m = &total;
55     }
56     if (rec.fLocalMatrix) {
57         total.setConcat(*m, *rec.fLocalMatrix);
58         m = &total;
59     }
60     return m->invert(totalInverse);
61 }
62
63 SkShader::Context* SkShader::createContext(const ContextRec& rec, void* storage) const {
64     if (!this->computeTotalInverse(rec, NULL)) {
65         return NULL;
66     }
67     return this->onCreateContext(rec, storage);
68 }
69
70 SkShader::Context* SkShader::onCreateContext(const ContextRec& rec, void*) const {
71     return NULL;
72 }
73
74 size_t SkShader::contextSize() const {
75     return 0;
76 }
77
78 SkShader::Context::Context(const SkShader& shader, const ContextRec& rec)
79     : fShader(shader), fCTM(*rec.fMatrix)
80 {
81     // Because the context parameters must be valid at this point, we know that the matrix is
82     // invertible.
83     SkAssertResult(fShader.computeTotalInverse(rec, &fTotalInverse));
84     fTotalInverseClass = (uint8_t)ComputeMatrixClass(fTotalInverse);
85
86     fPaintAlpha = rec.fPaint->getAlpha();
87 }
88
89 SkShader::Context::~Context() {}
90
91 SkShader::Context::ShadeProc SkShader::Context::asAShadeProc(void** ctx) {
92     return NULL;
93 }
94
95 #include "SkColorPriv.h"
96
97 void SkShader::Context::shadeSpan16(int x, int y, uint16_t span16[], int count) {
98     SkASSERT(span16);
99     SkASSERT(count > 0);
100     SkASSERT(this->canCallShadeSpan16());
101
102     // basically, if we get here, the subclass screwed up
103     SkDEBUGFAIL("kHasSpan16 flag is set, but shadeSpan16() not implemented");
104 }
105
106 #define kTempColorQuadCount 6   // balance between speed (larger) and saving stack-space
107 #define kTempColorCount     (kTempColorQuadCount << 2)
108
109 #ifdef SK_CPU_BENDIAN
110     #define SkU32BitShiftToByteOffset(shift)    (3 - ((shift) >> 3))
111 #else
112     #define SkU32BitShiftToByteOffset(shift)    ((shift) >> 3)
113 #endif
114
115 void SkShader::Context::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) {
116     SkASSERT(count > 0);
117
118     SkPMColor   colors[kTempColorCount];
119
120     while ((count -= kTempColorCount) >= 0) {
121         this->shadeSpan(x, y, colors, kTempColorCount);
122         x += kTempColorCount;
123
124         const uint8_t* srcA = (const uint8_t*)colors + SkU32BitShiftToByteOffset(SK_A32_SHIFT);
125         int quads = kTempColorQuadCount;
126         do {
127             U8CPU a0 = srcA[0];
128             U8CPU a1 = srcA[4];
129             U8CPU a2 = srcA[8];
130             U8CPU a3 = srcA[12];
131             srcA += 4*4;
132             *alpha++ = SkToU8(a0);
133             *alpha++ = SkToU8(a1);
134             *alpha++ = SkToU8(a2);
135             *alpha++ = SkToU8(a3);
136         } while (--quads != 0);
137     }
138     SkASSERT(count < 0);
139     SkASSERT(count + kTempColorCount >= 0);
140     if (count += kTempColorCount) {
141         this->shadeSpan(x, y, colors, count);
142
143         const uint8_t* srcA = (const uint8_t*)colors + SkU32BitShiftToByteOffset(SK_A32_SHIFT);
144         do {
145             *alpha++ = *srcA;
146             srcA += 4;
147         } while (--count != 0);
148     }
149 #if 0
150     do {
151         int n = count;
152         if (n > kTempColorCount)
153             n = kTempColorCount;
154         SkASSERT(n > 0);
155
156         this->shadeSpan(x, y, colors, n);
157         x += n;
158         count -= n;
159
160         const uint8_t* srcA = (const uint8_t*)colors + SkU32BitShiftToByteOffset(SK_A32_SHIFT);
161         do {
162             *alpha++ = *srcA;
163             srcA += 4;
164         } while (--n != 0);
165     } while (count > 0);
166 #endif
167 }
168
169 SkShader::Context::MatrixClass SkShader::Context::ComputeMatrixClass(const SkMatrix& mat) {
170     MatrixClass mc = kLinear_MatrixClass;
171
172     if (mat.hasPerspective()) {
173         if (mat.fixedStepInX(0, NULL, NULL)) {
174             mc = kFixedStepInX_MatrixClass;
175         } else {
176             mc = kPerspective_MatrixClass;
177         }
178     }
179     return mc;
180 }
181
182 //////////////////////////////////////////////////////////////////////////////
183
184 SkShader::BitmapType SkShader::asABitmap(SkBitmap*, SkMatrix*, TileMode*) const {
185     return kNone_BitmapType;
186 }
187
188 SkShader::GradientType SkShader::asAGradient(GradientInfo* info) const {
189     return kNone_GradientType;
190 }
191
192 GrEffectRef* SkShader::asNewEffect(GrContext*, const SkPaint&) const {
193     return NULL;
194 }
195
196 SkShader* SkShader::CreateEmptyShader() {
197     return SkNEW(SkEmptyShader);
198 }
199
200 SkShader* SkShader::CreateBitmapShader(const SkBitmap& src, TileMode tmx, TileMode tmy,
201                                        const SkMatrix* localMatrix) {
202     return ::CreateBitmapShader(src, tmx, tmy, localMatrix, NULL);
203 }
204
205 SkShader* SkShader::CreatePictureShader(SkPicture* src, TileMode tmx, TileMode tmy,
206                                        const SkMatrix* localMatrix) {
207     return SkPictureShader::Create(src, tmx, tmy, localMatrix);
208 }
209
210 #ifndef SK_IGNORE_TO_STRING
211 void SkShader::toString(SkString* str) const {
212     if (this->hasLocalMatrix()) {
213         str->append(" ");
214         this->getLocalMatrix().toString(str);
215     }
216 }
217 #endif
218
219 //////////////////////////////////////////////////////////////////////////////
220
221 #include "SkColorShader.h"
222 #include "SkUtils.h"
223
224 SkColorShader::SkColorShader(SkColor c)
225     : fColor(c) {
226 }
227
228 bool SkColorShader::isOpaque() const {
229     return SkColorGetA(fColor) == 255;
230 }
231
232 SkColorShader::SkColorShader(SkReadBuffer& b) : INHERITED(b) {
233     // V25_COMPATIBILITY_CODE We had a boolean to make the color shader inherit the paint's
234     // color. We don't support that any more.
235     if (b.pictureVersion() < 26 && 0 != b.pictureVersion()) {
236         if (b.readBool()) {
237             SkDEBUGFAIL("We shouldn't have pictures that recorded the inherited case.");
238             fColor = SK_ColorWHITE;
239             return;
240         }
241     }
242     fColor = b.readColor();
243 }
244
245 void SkColorShader::flatten(SkWriteBuffer& buffer) const {
246     this->INHERITED::flatten(buffer);
247     buffer.writeColor(fColor);
248 }
249
250 uint32_t SkColorShader::ColorShaderContext::getFlags() const {
251     return fFlags;
252 }
253
254 uint8_t SkColorShader::ColorShaderContext::getSpan16Alpha() const {
255     return SkGetPackedA32(fPMColor);
256 }
257
258 SkShader::Context* SkColorShader::onCreateContext(const ContextRec& rec, void* storage) const {
259     return SkNEW_PLACEMENT_ARGS(storage, ColorShaderContext, (*this, rec));
260 }
261
262 SkColorShader::ColorShaderContext::ColorShaderContext(const SkColorShader& shader,
263                                                       const ContextRec& rec)
264     : INHERITED(shader, rec)
265 {
266     SkColor color = shader.fColor;
267     unsigned a = SkAlphaMul(SkColorGetA(color), SkAlpha255To256(rec.fPaint->getAlpha()));
268
269     unsigned r = SkColorGetR(color);
270     unsigned g = SkColorGetG(color);
271     unsigned b = SkColorGetB(color);
272
273     // we want this before we apply any alpha
274     fColor16 = SkPack888ToRGB16(r, g, b);
275
276     if (a != 255) {
277         r = SkMulDiv255Round(r, a);
278         g = SkMulDiv255Round(g, a);
279         b = SkMulDiv255Round(b, a);
280     }
281     fPMColor = SkPackARGB32(a, r, g, b);
282
283     fFlags = kConstInY32_Flag;
284     if (255 == a) {
285         fFlags |= kOpaqueAlpha_Flag;
286         if (rec.fPaint->isDither() == false) {
287             fFlags |= kHasSpan16_Flag;
288         }
289     }
290 }
291
292 void SkColorShader::ColorShaderContext::shadeSpan(int x, int y, SkPMColor span[], int count) {
293     sk_memset32(span, fPMColor, count);
294 }
295
296 void SkColorShader::ColorShaderContext::shadeSpan16(int x, int y, uint16_t span[], int count) {
297     sk_memset16(span, fColor16, count);
298 }
299
300 void SkColorShader::ColorShaderContext::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) {
301     memset(alpha, SkGetPackedA32(fPMColor), count);
302 }
303
304 // if we had a asAColor method, that would be more efficient...
305 SkShader::BitmapType SkColorShader::asABitmap(SkBitmap* bitmap, SkMatrix* matrix,
306                                               TileMode modes[]) const {
307     return kNone_BitmapType;
308 }
309
310 SkShader::GradientType SkColorShader::asAGradient(GradientInfo* info) const {
311     if (info) {
312         if (info->fColors && info->fColorCount >= 1) {
313             info->fColors[0] = fColor;
314         }
315         info->fColorCount = 1;
316         info->fTileMode = SkShader::kRepeat_TileMode;
317     }
318     return kColor_GradientType;
319 }
320
321 #ifndef SK_IGNORE_TO_STRING
322 void SkColorShader::toString(SkString* str) const {
323     str->append("SkColorShader: (");
324
325     str->append("Color: ");
326     str->appendHex(fColor);
327
328     this->INHERITED::toString(str);
329
330     str->append(")");
331 }
332 #endif
333
334 ///////////////////////////////////////////////////////////////////////////////
335
336 #ifndef SK_IGNORE_TO_STRING
337 #include "SkEmptyShader.h"
338
339 void SkEmptyShader::toString(SkString* str) const {
340     str->append("SkEmptyShader: (");
341
342     this->INHERITED::toString(str);
343
344     str->append(")");
345 }
346 #endif