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