blob: a449d0fd9d4e7835c686d25c76cd5b0960846696 [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.org87fcd952014-04-23 19:10:51 +000059bool SkShader::validContext(const SkBitmap& device,
60 const SkPaint& paint,
61 const SkMatrix& matrix,
62 SkMatrix* totalInverse) const {
63 return this->computeTotalInverse(matrix, totalInverse);
reed@google.coma641f3f2012-12-13 22:16:30 +000064}
65
commit-bot@chromium.orgf3e50592014-04-30 23:29:02 +000066SkShader::Context* SkShader::createContext(const SkBitmap&, const SkPaint&, const SkMatrix&,
67 void* storage) const {
68 return NULL;
69}
70
71size_t SkShader::contextSize() const {
72 return 0;
73}
74
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +000075SkShader::Context::Context(const SkShader& shader, const SkBitmap& device,
76 const SkPaint& paint, const SkMatrix& matrix)
77 : fShader(shader)
78{
79 SkASSERT(fShader.validContext(device, paint, matrix));
80
81 // Because the context parameters must be valid at this point, we know that the matrix is
82 // invertible.
83 SkAssertResult(fShader.computeTotalInverse(matrix, &fTotalInverse));
84 fTotalInverseClass = (uint8_t)ComputeMatrixClass(fTotalInverse);
85
86 fPaintAlpha = paint.getAlpha();
87}
88
89SkShader::Context::~Context() {}
90
91SkShader::Context::ShadeProc SkShader::Context::asAShadeProc(void** ctx) {
reed@google.com3bafe742012-10-12 18:56:18 +000092 return NULL;
93}
94
reed@android.com8a1c16f2008-12-17 15:59:43 +000095#include "SkColorPriv.h"
96
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +000097void SkShader::Context::shadeSpan16(int x, int y, uint16_t span16[], int count) {
reed@android.com8a1c16f2008-12-17 15:59:43 +000098 SkASSERT(span16);
99 SkASSERT(count > 0);
100 SkASSERT(this->canCallShadeSpan16());
101
102 // basically, if we get here, the subclass screwed up
tomhudson@google.com0c00f212011-12-28 14:59:50 +0000103 SkDEBUGFAIL("kHasSpan16 flag is set, but shadeSpan16() not implemented");
reed@android.com8a1c16f2008-12-17 15:59:43 +0000104}
105
106#define kTempColorQuadCount 6 // balance between speed (larger) and saving stack-space
reed@google.com7c2f27d2011-03-07 19:29:00 +0000107#define kTempColorCount (kTempColorQuadCount << 2)
reed@android.com8a1c16f2008-12-17 15:59:43 +0000108
109#ifdef SK_CPU_BENDIAN
110 #define SkU32BitShiftToByteOffset(shift) (3 - ((shift) >> 3))
111#else
112 #define SkU32BitShiftToByteOffset(shift) ((shift) >> 3)
113#endif
114
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000115void SkShader::Context::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000116 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
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000169SkShader::Context::MatrixClass SkShader::Context::ComputeMatrixClass(const SkMatrix& mat) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000170 MatrixClass mc = kLinear_MatrixClass;
171
tomhudson@google.com8d430182011-06-06 19:11:19 +0000172 if (mat.hasPerspective()) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000173 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
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000184SkShader::BitmapType SkShader::asABitmap(SkBitmap*, SkMatrix*, TileMode*) const {
reed@android.comf2b98d62010-12-20 18:26:13 +0000185 return kNone_BitmapType;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000186}
187
vandebo@chromium.orgd3ae7792011-02-24 00:21:06 +0000188SkShader::GradientType SkShader::asAGradient(GradientInfo* info) const {
189 return kNone_GradientType;
190}
191
bsalomon@google.com0ac6af42013-01-16 15:16:18 +0000192GrEffectRef* SkShader::asNewEffect(GrContext*, const SkPaint&) const {
humper@google.coma3bdc1a2013-01-14 21:01:28 +0000193 return NULL;
rileya@google.com03c1c352012-07-20 20:02:43 +0000194}
195
commit-bot@chromium.org9c9005a2014-04-28 14:55:39 +0000196SkShader* SkShader::CreateBitmapShader(const SkBitmap& src, TileMode tmx, TileMode tmy,
197 const SkMatrix* localMatrix) {
198 return ::CreateBitmapShader(src, tmx, tmy, localMatrix, NULL);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000199}
200
commit-bot@chromium.orgc5d9bb02014-04-08 15:19:34 +0000201SkShader* SkShader::CreatePictureShader(SkPicture* src, TileMode tmx, TileMode tmy) {
202 return SkPictureShader::Create(src, tmx, tmy);
203}
204
commit-bot@chromium.org0f10f7b2014-03-13 18:02:17 +0000205#ifndef SK_IGNORE_TO_STRING
robertphillips@google.com76f9e932013-01-15 20:17:47 +0000206void SkShader::toString(SkString* str) const {
207 if (this->hasLocalMatrix()) {
208 str->append(" ");
209 this->getLocalMatrix().toString(str);
210 }
211}
212#endif
213
reed@android.com8a1c16f2008-12-17 15:59:43 +0000214//////////////////////////////////////////////////////////////////////////////
215
216#include "SkColorShader.h"
217#include "SkUtils.h"
218
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000219SkColorShader::SkColorShader(SkColor c)
commit-bot@chromium.org76a3b2a2014-04-24 16:54:46 +0000220 : fColor(c) {
reed@android.comf2b98d62010-12-20 18:26:13 +0000221}
222
junov@chromium.orgb6e16192011-12-09 15:48:03 +0000223bool SkColorShader::isOpaque() const {
junov@chromium.orgb6e16192011-12-09 15:48:03 +0000224 return SkColorGetA(fColor) == 255;
225}
226
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +0000227SkColorShader::SkColorShader(SkReadBuffer& b) : INHERITED(b) {
commit-bot@chromium.org76a3b2a2014-04-24 16:54:46 +0000228 // V25_COMPATIBILITY_CODE We had a boolean to make the color shader inherit the paint's
229 // color. We don't support that any more.
230 if (b.pictureVersion() < 26 && 0 != b.pictureVersion()) {
231 if (b.readBool()) {
232 SkDEBUGFAIL("We shouldn't have pictures that recorded the inherited case.");
233 fColor = SK_ColorWHITE;
234 return;
235 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000236 }
djsollen@google.comc73dd5c2012-08-07 15:54:32 +0000237 fColor = b.readColor();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000238}
239
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +0000240void SkColorShader::flatten(SkWriteBuffer& buffer) const {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000241 this->INHERITED::flatten(buffer);
djsollen@google.comc73dd5c2012-08-07 15:54:32 +0000242 buffer.writeColor(fColor);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000243}
244
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000245uint32_t SkColorShader::ColorShaderContext::getFlags() const {
reed@google.com59ccef62011-12-07 14:59:50 +0000246 return fFlags;
247}
248
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000249uint8_t SkColorShader::ColorShaderContext::getSpan16Alpha() const {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000250 return SkGetPackedA32(fPMColor);
251}
252
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000253SkShader::Context* SkColorShader::createContext(const SkBitmap& device, const SkPaint& paint,
254 const SkMatrix& matrix, void* storage) const {
255 if (!this->validContext(device, paint, matrix)) {
256 return NULL;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000257 }
258
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000259 return SkNEW_PLACEMENT_ARGS(storage, ColorShaderContext, (*this, device, paint, matrix));
260}
261
262SkColorShader::ColorShaderContext::ColorShaderContext(const SkColorShader& shader,
263 const SkBitmap& device,
264 const SkPaint& paint,
265 const SkMatrix& matrix)
266 : INHERITED(shader, device, paint, matrix)
267{
commit-bot@chromium.org9c9005a2014-04-28 14:55:39 +0000268 SkColor color = shader.fColor;
269 unsigned a = SkAlphaMul(SkColorGetA(color), SkAlpha255To256(paint.getAlpha()));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000270
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000271 unsigned r = SkColorGetR(color);
272 unsigned g = SkColorGetG(color);
273 unsigned b = SkColorGetB(color);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000274
275 // we want this before we apply any alpha
276 fColor16 = SkPack888ToRGB16(r, g, b);
277
278 if (a != 255) {
reed@android.com8f073382010-03-11 21:56:16 +0000279 r = SkMulDiv255Round(r, a);
280 g = SkMulDiv255Round(g, a);
281 b = SkMulDiv255Round(b, a);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000282 }
283 fPMColor = SkPackARGB32(a, r, g, b);
284
reed@android.com8f073382010-03-11 21:56:16 +0000285 fFlags = kConstInY32_Flag;
reed@android.com5b815352010-03-11 22:20:43 +0000286 if (255 == a) {
reed@android.com5119bdb2009-06-12 21:27:03 +0000287 fFlags |= kOpaqueAlpha_Flag;
reed@android.com5b815352010-03-11 22:20:43 +0000288 if (paint.isDither() == false) {
289 fFlags |= kHasSpan16_Flag;
290 }
reed@android.com5119bdb2009-06-12 21:27:03 +0000291 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000292}
293
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000294void SkColorShader::ColorShaderContext::shadeSpan(int x, int y, SkPMColor span[], int count) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000295 sk_memset32(span, fPMColor, count);
296}
297
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000298void SkColorShader::ColorShaderContext::shadeSpan16(int x, int y, uint16_t span[], int count) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000299 sk_memset16(span, fColor16, count);
300}
301
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000302void SkColorShader::ColorShaderContext::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000303 memset(alpha, SkGetPackedA32(fPMColor), count);
304}
305
reed@android.comf2b98d62010-12-20 18:26:13 +0000306// if we had a asAColor method, that would be more efficient...
307SkShader::BitmapType SkColorShader::asABitmap(SkBitmap* bitmap, SkMatrix* matrix,
rileya@google.com91f319c2012-07-25 17:18:31 +0000308 TileMode modes[]) const {
reed@google.com2be9e8b2011-07-06 21:18:09 +0000309 return kNone_BitmapType;
reed@android.comf2b98d62010-12-20 18:26:13 +0000310}
311
vandebo@chromium.orgd3ae7792011-02-24 00:21:06 +0000312SkShader::GradientType SkColorShader::asAGradient(GradientInfo* info) const {
313 if (info) {
314 if (info->fColors && info->fColorCount >= 1) {
315 info->fColors[0] = fColor;
316 }
317 info->fColorCount = 1;
318 info->fTileMode = SkShader::kRepeat_TileMode;
319 }
320 return kColor_GradientType;
321}
reed@google.com37a20122011-07-05 18:54:12 +0000322
commit-bot@chromium.org0f10f7b2014-03-13 18:02:17 +0000323#ifndef SK_IGNORE_TO_STRING
robertphillips@google.com76f9e932013-01-15 20:17:47 +0000324void SkColorShader::toString(SkString* str) const {
325 str->append("SkColorShader: (");
326
commit-bot@chromium.org76a3b2a2014-04-24 16:54:46 +0000327 str->append("Color: ");
328 str->appendHex(fColor);
robertphillips@google.com76f9e932013-01-15 20:17:47 +0000329
330 this->INHERITED::toString(str);
331
332 str->append(")");
333}
334#endif
335
reed@google.com37a20122011-07-05 18:54:12 +0000336///////////////////////////////////////////////////////////////////////////////
337
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000338#ifndef SK_IGNORE_TO_STRING
reed@google.com37a20122011-07-05 18:54:12 +0000339#include "SkEmptyShader.h"
340
robertphillips@google.com76f9e932013-01-15 20:17:47 +0000341void SkEmptyShader::toString(SkString* str) const {
342 str->append("SkEmptyShader: (");
343
344 this->INHERITED::toString(str);
345
346 str->append(")");
347}
348#endif