blob: 0f6ba4ce9f65855e9937593dddcf6e61e2dff8f7 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001/*
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
commit-bot@chromium.orga5572e52014-03-07 03:24:41 +00008#include "SkBitmapProcShader.h"
9#include "SkReadBuffer.h"
10#include "SkMallocPixelRef.h"
11#include "SkPaint.h"
commit-bot@chromium.orgc5d9bb02014-04-08 15:19:34 +000012#include "SkPicture.h"
13#include "SkPictureShader.h"
vandebo@chromium.orgd3ae7792011-02-24 00:21:06 +000014#include "SkScalar.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000015#include "SkShader.h"
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +000016#include "SkWriteBuffer.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000017
commit-bot@chromium.org9c9005a2014-04-28 14:55:39 +000018SkShader::SkShader(const SkMatrix* localMatrix) {
19 if (localMatrix) {
20 fLocalMatrix = *localMatrix;
21 } else {
22 fLocalMatrix.reset();
23 }
reed@android.com8a1c16f2008-12-17 15:59:43 +000024}
25
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +000026SkShader::SkShader(SkReadBuffer& buffer)
bsalomon@google.comf94b3a42012-10-31 18:09:01 +000027 : INHERITED(buffer) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000028 if (buffer.readBool()) {
bsalomon@google.comf94b3a42012-10-31 18:09:01 +000029 buffer.readMatrix(&fLocalMatrix);
30 } else {
31 fLocalMatrix.reset();
reed@android.com8a1c16f2008-12-17 15:59:43 +000032 }
reed@android.com8a1c16f2008-12-17 15:59:43 +000033}
34
35SkShader::~SkShader() {
reed@android.com8a1c16f2008-12-17 15:59:43 +000036}
37
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +000038void SkShader::flatten(SkWriteBuffer& buffer) const {
reed@android.com8a1c16f2008-12-17 15:59:43 +000039 this->INHERITED::flatten(buffer);
bsalomon@google.comf94b3a42012-10-31 18:09:01 +000040 bool hasLocalM = this->hasLocalMatrix();
41 buffer.writeBool(hasLocalM);
42 if (hasLocalM) {
43 buffer.writeMatrix(fLocalMatrix);
reed@android.com8a1c16f2008-12-17 15:59:43 +000044 }
45}
46
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +000047bool SkShader::computeTotalInverse(const SkMatrix& matrix, SkMatrix* totalInverse) const {
reed@android.com8a1c16f2008-12-17 15:59:43 +000048 const SkMatrix* m = &matrix;
49 SkMatrix total;
50
bsalomon@google.comf94b3a42012-10-31 18:09:01 +000051 if (this->hasLocalMatrix()) {
52 total.setConcat(matrix, this->getLocalMatrix());
reed@android.com8a1c16f2008-12-17 15:59:43 +000053 m = &total;
54 }
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +000055
56 return m->invert(totalInverse);
reed@android.com8a1c16f2008-12-17 15:59:43 +000057}
58
commit-bot@chromium.orge901b6d2014-05-01 19:31:31 +000059bool SkShader::validContext(const ContextRec& rec, SkMatrix* totalInverse) const {
60 return this->computeTotalInverse(*rec.fMatrix, totalInverse);
reed@google.coma641f3f2012-12-13 22:16:30 +000061}
62
commit-bot@chromium.orge901b6d2014-05-01 19:31:31 +000063SkShader::Context* SkShader::createContext(const ContextRec&, void* storage) const {
commit-bot@chromium.orgf3e50592014-04-30 23:29:02 +000064 return NULL;
65}
66
67size_t SkShader::contextSize() const {
68 return 0;
69}
70
commit-bot@chromium.orge901b6d2014-05-01 19:31:31 +000071SkShader::Context::Context(const SkShader& shader, const ContextRec& rec)
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +000072 : fShader(shader)
73{
commit-bot@chromium.orge901b6d2014-05-01 19:31:31 +000074 SkASSERT(fShader.validContext(rec));
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +000075
76 // Because the context parameters must be valid at this point, we know that the matrix is
77 // invertible.
commit-bot@chromium.orge901b6d2014-05-01 19:31:31 +000078 SkAssertResult(fShader.computeTotalInverse(*rec.fMatrix, &fTotalInverse));
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +000079 fTotalInverseClass = (uint8_t)ComputeMatrixClass(fTotalInverse);
80
commit-bot@chromium.orge901b6d2014-05-01 19:31:31 +000081 fPaintAlpha = rec.fPaint->getAlpha();
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +000082}
83
84SkShader::Context::~Context() {}
85
86SkShader::Context::ShadeProc SkShader::Context::asAShadeProc(void** ctx) {
reed@google.com3bafe742012-10-12 18:56:18 +000087 return NULL;
88}
89
reed@android.com8a1c16f2008-12-17 15:59:43 +000090#include "SkColorPriv.h"
91
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +000092void SkShader::Context::shadeSpan16(int x, int y, uint16_t span16[], int count) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000093 SkASSERT(span16);
94 SkASSERT(count > 0);
95 SkASSERT(this->canCallShadeSpan16());
96
97 // basically, if we get here, the subclass screwed up
tomhudson@google.com0c00f212011-12-28 14:59:50 +000098 SkDEBUGFAIL("kHasSpan16 flag is set, but shadeSpan16() not implemented");
reed@android.com8a1c16f2008-12-17 15:59:43 +000099}
100
101#define kTempColorQuadCount 6 // balance between speed (larger) and saving stack-space
reed@google.com7c2f27d2011-03-07 19:29:00 +0000102#define kTempColorCount (kTempColorQuadCount << 2)
reed@android.com8a1c16f2008-12-17 15:59:43 +0000103
104#ifdef SK_CPU_BENDIAN
105 #define SkU32BitShiftToByteOffset(shift) (3 - ((shift) >> 3))
106#else
107 #define SkU32BitShiftToByteOffset(shift) ((shift) >> 3)
108#endif
109
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000110void SkShader::Context::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000111 SkASSERT(count > 0);
112
113 SkPMColor colors[kTempColorCount];
114
115 while ((count -= kTempColorCount) >= 0) {
116 this->shadeSpan(x, y, colors, kTempColorCount);
117 x += kTempColorCount;
118
119 const uint8_t* srcA = (const uint8_t*)colors + SkU32BitShiftToByteOffset(SK_A32_SHIFT);
120 int quads = kTempColorQuadCount;
121 do {
122 U8CPU a0 = srcA[0];
123 U8CPU a1 = srcA[4];
124 U8CPU a2 = srcA[8];
125 U8CPU a3 = srcA[12];
126 srcA += 4*4;
127 *alpha++ = SkToU8(a0);
128 *alpha++ = SkToU8(a1);
129 *alpha++ = SkToU8(a2);
130 *alpha++ = SkToU8(a3);
131 } while (--quads != 0);
132 }
133 SkASSERT(count < 0);
134 SkASSERT(count + kTempColorCount >= 0);
135 if (count += kTempColorCount) {
136 this->shadeSpan(x, y, colors, count);
137
138 const uint8_t* srcA = (const uint8_t*)colors + SkU32BitShiftToByteOffset(SK_A32_SHIFT);
139 do {
140 *alpha++ = *srcA;
141 srcA += 4;
142 } while (--count != 0);
143 }
144#if 0
145 do {
146 int n = count;
147 if (n > kTempColorCount)
148 n = kTempColorCount;
149 SkASSERT(n > 0);
150
151 this->shadeSpan(x, y, colors, n);
152 x += n;
153 count -= n;
154
155 const uint8_t* srcA = (const uint8_t*)colors + SkU32BitShiftToByteOffset(SK_A32_SHIFT);
156 do {
157 *alpha++ = *srcA;
158 srcA += 4;
159 } while (--n != 0);
160 } while (count > 0);
161#endif
162}
163
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000164SkShader::Context::MatrixClass SkShader::Context::ComputeMatrixClass(const SkMatrix& mat) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000165 MatrixClass mc = kLinear_MatrixClass;
166
tomhudson@google.com8d430182011-06-06 19:11:19 +0000167 if (mat.hasPerspective()) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000168 if (mat.fixedStepInX(0, NULL, NULL)) {
169 mc = kFixedStepInX_MatrixClass;
170 } else {
171 mc = kPerspective_MatrixClass;
172 }
173 }
174 return mc;
175}
176
177//////////////////////////////////////////////////////////////////////////////
178
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000179SkShader::BitmapType SkShader::asABitmap(SkBitmap*, SkMatrix*, TileMode*) const {
reed@android.comf2b98d62010-12-20 18:26:13 +0000180 return kNone_BitmapType;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000181}
182
vandebo@chromium.orgd3ae7792011-02-24 00:21:06 +0000183SkShader::GradientType SkShader::asAGradient(GradientInfo* info) const {
184 return kNone_GradientType;
185}
186
bsalomon@google.com0ac6af42013-01-16 15:16:18 +0000187GrEffectRef* SkShader::asNewEffect(GrContext*, const SkPaint&) const {
humper@google.coma3bdc1a2013-01-14 21:01:28 +0000188 return NULL;
rileya@google.com03c1c352012-07-20 20:02:43 +0000189}
190
commit-bot@chromium.org9c9005a2014-04-28 14:55:39 +0000191SkShader* SkShader::CreateBitmapShader(const SkBitmap& src, TileMode tmx, TileMode tmy,
192 const SkMatrix* localMatrix) {
193 return ::CreateBitmapShader(src, tmx, tmy, localMatrix, NULL);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000194}
195
commit-bot@chromium.orgc5d9bb02014-04-08 15:19:34 +0000196SkShader* SkShader::CreatePictureShader(SkPicture* src, TileMode tmx, TileMode tmy) {
197 return SkPictureShader::Create(src, tmx, tmy);
198}
199
commit-bot@chromium.org0f10f7b2014-03-13 18:02:17 +0000200#ifndef SK_IGNORE_TO_STRING
robertphillips@google.com76f9e932013-01-15 20:17:47 +0000201void SkShader::toString(SkString* str) const {
202 if (this->hasLocalMatrix()) {
203 str->append(" ");
204 this->getLocalMatrix().toString(str);
205 }
206}
207#endif
208
reed@android.com8a1c16f2008-12-17 15:59:43 +0000209//////////////////////////////////////////////////////////////////////////////
210
211#include "SkColorShader.h"
212#include "SkUtils.h"
213
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000214SkColorShader::SkColorShader(SkColor c)
commit-bot@chromium.org76a3b2a2014-04-24 16:54:46 +0000215 : fColor(c) {
reed@android.comf2b98d62010-12-20 18:26:13 +0000216}
217
junov@chromium.orgb6e16192011-12-09 15:48:03 +0000218bool SkColorShader::isOpaque() const {
junov@chromium.orgb6e16192011-12-09 15:48:03 +0000219 return SkColorGetA(fColor) == 255;
220}
221
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +0000222SkColorShader::SkColorShader(SkReadBuffer& b) : INHERITED(b) {
commit-bot@chromium.org76a3b2a2014-04-24 16:54:46 +0000223 // V25_COMPATIBILITY_CODE We had a boolean to make the color shader inherit the paint's
224 // color. We don't support that any more.
225 if (b.pictureVersion() < 26 && 0 != b.pictureVersion()) {
226 if (b.readBool()) {
227 SkDEBUGFAIL("We shouldn't have pictures that recorded the inherited case.");
228 fColor = SK_ColorWHITE;
229 return;
230 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000231 }
djsollen@google.comc73dd5c2012-08-07 15:54:32 +0000232 fColor = b.readColor();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000233}
234
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +0000235void SkColorShader::flatten(SkWriteBuffer& buffer) const {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000236 this->INHERITED::flatten(buffer);
djsollen@google.comc73dd5c2012-08-07 15:54:32 +0000237 buffer.writeColor(fColor);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000238}
239
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000240uint32_t SkColorShader::ColorShaderContext::getFlags() const {
reed@google.com59ccef62011-12-07 14:59:50 +0000241 return fFlags;
242}
243
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000244uint8_t SkColorShader::ColorShaderContext::getSpan16Alpha() const {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000245 return SkGetPackedA32(fPMColor);
246}
247
commit-bot@chromium.orge901b6d2014-05-01 19:31:31 +0000248SkShader::Context* SkColorShader::createContext(const ContextRec& rec, void* storage) const {
249 if (!this->validContext(rec)) {
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000250 return NULL;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000251 }
252
commit-bot@chromium.orge901b6d2014-05-01 19:31:31 +0000253 return SkNEW_PLACEMENT_ARGS(storage, ColorShaderContext, (*this, rec));
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000254}
255
256SkColorShader::ColorShaderContext::ColorShaderContext(const SkColorShader& shader,
commit-bot@chromium.orge901b6d2014-05-01 19:31:31 +0000257 const ContextRec& rec)
258 : INHERITED(shader, rec)
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000259{
commit-bot@chromium.org9c9005a2014-04-28 14:55:39 +0000260 SkColor color = shader.fColor;
commit-bot@chromium.orge901b6d2014-05-01 19:31:31 +0000261 unsigned a = SkAlphaMul(SkColorGetA(color), SkAlpha255To256(rec.fPaint->getAlpha()));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000262
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000263 unsigned r = SkColorGetR(color);
264 unsigned g = SkColorGetG(color);
265 unsigned b = SkColorGetB(color);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000266
267 // we want this before we apply any alpha
268 fColor16 = SkPack888ToRGB16(r, g, b);
269
270 if (a != 255) {
reed@android.com8f073382010-03-11 21:56:16 +0000271 r = SkMulDiv255Round(r, a);
272 g = SkMulDiv255Round(g, a);
273 b = SkMulDiv255Round(b, a);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000274 }
275 fPMColor = SkPackARGB32(a, r, g, b);
276
reed@android.com8f073382010-03-11 21:56:16 +0000277 fFlags = kConstInY32_Flag;
reed@android.com5b815352010-03-11 22:20:43 +0000278 if (255 == a) {
reed@android.com5119bdb2009-06-12 21:27:03 +0000279 fFlags |= kOpaqueAlpha_Flag;
commit-bot@chromium.orge901b6d2014-05-01 19:31:31 +0000280 if (rec.fPaint->isDither() == false) {
reed@android.com5b815352010-03-11 22:20:43 +0000281 fFlags |= kHasSpan16_Flag;
282 }
reed@android.com5119bdb2009-06-12 21:27:03 +0000283 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000284}
285
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000286void SkColorShader::ColorShaderContext::shadeSpan(int x, int y, SkPMColor span[], int count) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000287 sk_memset32(span, fPMColor, count);
288}
289
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000290void SkColorShader::ColorShaderContext::shadeSpan16(int x, int y, uint16_t span[], int count) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000291 sk_memset16(span, fColor16, count);
292}
293
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000294void SkColorShader::ColorShaderContext::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000295 memset(alpha, SkGetPackedA32(fPMColor), count);
296}
297
reed@android.comf2b98d62010-12-20 18:26:13 +0000298// if we had a asAColor method, that would be more efficient...
299SkShader::BitmapType SkColorShader::asABitmap(SkBitmap* bitmap, SkMatrix* matrix,
rileya@google.com91f319c2012-07-25 17:18:31 +0000300 TileMode modes[]) const {
reed@google.com2be9e8b2011-07-06 21:18:09 +0000301 return kNone_BitmapType;
reed@android.comf2b98d62010-12-20 18:26:13 +0000302}
303
vandebo@chromium.orgd3ae7792011-02-24 00:21:06 +0000304SkShader::GradientType SkColorShader::asAGradient(GradientInfo* info) const {
305 if (info) {
306 if (info->fColors && info->fColorCount >= 1) {
307 info->fColors[0] = fColor;
308 }
309 info->fColorCount = 1;
310 info->fTileMode = SkShader::kRepeat_TileMode;
311 }
312 return kColor_GradientType;
313}
reed@google.com37a20122011-07-05 18:54:12 +0000314
commit-bot@chromium.org0f10f7b2014-03-13 18:02:17 +0000315#ifndef SK_IGNORE_TO_STRING
robertphillips@google.com76f9e932013-01-15 20:17:47 +0000316void SkColorShader::toString(SkString* str) const {
317 str->append("SkColorShader: (");
318
commit-bot@chromium.org76a3b2a2014-04-24 16:54:46 +0000319 str->append("Color: ");
320 str->appendHex(fColor);
robertphillips@google.com76f9e932013-01-15 20:17:47 +0000321
322 this->INHERITED::toString(str);
323
324 str->append(")");
325}
326#endif
327
reed@google.com37a20122011-07-05 18:54:12 +0000328///////////////////////////////////////////////////////////////////////////////
329
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000330#ifndef SK_IGNORE_TO_STRING
reed@google.com37a20122011-07-05 18:54:12 +0000331#include "SkEmptyShader.h"
332
robertphillips@google.com76f9e932013-01-15 20:17:47 +0000333void SkEmptyShader::toString(SkString* str) const {
334 str->append("SkEmptyShader: (");
335
336 this->INHERITED::toString(str);
337
338 str->append(")");
339}
340#endif