blob: 67dd581543e737970b47b2789df3e16d29509f95 [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.org5aacfe92014-05-02 21:23:52 +0000196SkShader* SkShader::CreatePictureShader(SkPicture* src, TileMode tmx, TileMode tmy,
197 const SkMatrix* localMatrix) {
198 return SkPictureShader::Create(src, tmx, tmy, localMatrix);
commit-bot@chromium.orgc5d9bb02014-04-08 15:19:34 +0000199}
200
commit-bot@chromium.org0f10f7b2014-03-13 18:02:17 +0000201#ifndef SK_IGNORE_TO_STRING
robertphillips@google.com76f9e932013-01-15 20:17:47 +0000202void SkShader::toString(SkString* str) const {
203 if (this->hasLocalMatrix()) {
204 str->append(" ");
205 this->getLocalMatrix().toString(str);
206 }
207}
208#endif
209
reed@android.com8a1c16f2008-12-17 15:59:43 +0000210//////////////////////////////////////////////////////////////////////////////
211
212#include "SkColorShader.h"
213#include "SkUtils.h"
214
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000215SkColorShader::SkColorShader(SkColor c)
commit-bot@chromium.org76a3b2a2014-04-24 16:54:46 +0000216 : fColor(c) {
reed@android.comf2b98d62010-12-20 18:26:13 +0000217}
218
junov@chromium.orgb6e16192011-12-09 15:48:03 +0000219bool SkColorShader::isOpaque() const {
junov@chromium.orgb6e16192011-12-09 15:48:03 +0000220 return SkColorGetA(fColor) == 255;
221}
222
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +0000223SkColorShader::SkColorShader(SkReadBuffer& b) : INHERITED(b) {
commit-bot@chromium.org76a3b2a2014-04-24 16:54:46 +0000224 // V25_COMPATIBILITY_CODE We had a boolean to make the color shader inherit the paint's
225 // color. We don't support that any more.
226 if (b.pictureVersion() < 26 && 0 != b.pictureVersion()) {
227 if (b.readBool()) {
228 SkDEBUGFAIL("We shouldn't have pictures that recorded the inherited case.");
229 fColor = SK_ColorWHITE;
230 return;
231 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000232 }
djsollen@google.comc73dd5c2012-08-07 15:54:32 +0000233 fColor = b.readColor();
reed@android.com8a1c16f2008-12-17 15:59:43 +0000234}
235
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +0000236void SkColorShader::flatten(SkWriteBuffer& buffer) const {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000237 this->INHERITED::flatten(buffer);
djsollen@google.comc73dd5c2012-08-07 15:54:32 +0000238 buffer.writeColor(fColor);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000239}
240
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000241uint32_t SkColorShader::ColorShaderContext::getFlags() const {
reed@google.com59ccef62011-12-07 14:59:50 +0000242 return fFlags;
243}
244
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000245uint8_t SkColorShader::ColorShaderContext::getSpan16Alpha() const {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000246 return SkGetPackedA32(fPMColor);
247}
248
commit-bot@chromium.orge901b6d2014-05-01 19:31:31 +0000249SkShader::Context* SkColorShader::createContext(const ContextRec& rec, void* storage) const {
250 if (!this->validContext(rec)) {
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000251 return NULL;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000252 }
253
commit-bot@chromium.orge901b6d2014-05-01 19:31:31 +0000254 return SkNEW_PLACEMENT_ARGS(storage, ColorShaderContext, (*this, rec));
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000255}
256
257SkColorShader::ColorShaderContext::ColorShaderContext(const SkColorShader& shader,
commit-bot@chromium.orge901b6d2014-05-01 19:31:31 +0000258 const ContextRec& rec)
259 : INHERITED(shader, rec)
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000260{
commit-bot@chromium.org9c9005a2014-04-28 14:55:39 +0000261 SkColor color = shader.fColor;
commit-bot@chromium.orge901b6d2014-05-01 19:31:31 +0000262 unsigned a = SkAlphaMul(SkColorGetA(color), SkAlpha255To256(rec.fPaint->getAlpha()));
reed@android.com8a1c16f2008-12-17 15:59:43 +0000263
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000264 unsigned r = SkColorGetR(color);
265 unsigned g = SkColorGetG(color);
266 unsigned b = SkColorGetB(color);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000267
268 // we want this before we apply any alpha
269 fColor16 = SkPack888ToRGB16(r, g, b);
270
271 if (a != 255) {
reed@android.com8f073382010-03-11 21:56:16 +0000272 r = SkMulDiv255Round(r, a);
273 g = SkMulDiv255Round(g, a);
274 b = SkMulDiv255Round(b, a);
reed@android.com8a1c16f2008-12-17 15:59:43 +0000275 }
276 fPMColor = SkPackARGB32(a, r, g, b);
277
reed@android.com8f073382010-03-11 21:56:16 +0000278 fFlags = kConstInY32_Flag;
reed@android.com5b815352010-03-11 22:20:43 +0000279 if (255 == a) {
reed@android.com5119bdb2009-06-12 21:27:03 +0000280 fFlags |= kOpaqueAlpha_Flag;
commit-bot@chromium.orge901b6d2014-05-01 19:31:31 +0000281 if (rec.fPaint->isDither() == false) {
reed@android.com5b815352010-03-11 22:20:43 +0000282 fFlags |= kHasSpan16_Flag;
283 }
reed@android.com5119bdb2009-06-12 21:27:03 +0000284 }
reed@android.com8a1c16f2008-12-17 15:59:43 +0000285}
286
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000287void SkColorShader::ColorShaderContext::shadeSpan(int x, int y, SkPMColor span[], int count) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000288 sk_memset32(span, fPMColor, count);
289}
290
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000291void SkColorShader::ColorShaderContext::shadeSpan16(int x, int y, uint16_t span[], int count) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000292 sk_memset16(span, fColor16, count);
293}
294
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000295void SkColorShader::ColorShaderContext::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) {
reed@android.com8a1c16f2008-12-17 15:59:43 +0000296 memset(alpha, SkGetPackedA32(fPMColor), count);
297}
298
reed@android.comf2b98d62010-12-20 18:26:13 +0000299// if we had a asAColor method, that would be more efficient...
300SkShader::BitmapType SkColorShader::asABitmap(SkBitmap* bitmap, SkMatrix* matrix,
rileya@google.com91f319c2012-07-25 17:18:31 +0000301 TileMode modes[]) const {
reed@google.com2be9e8b2011-07-06 21:18:09 +0000302 return kNone_BitmapType;
reed@android.comf2b98d62010-12-20 18:26:13 +0000303}
304
vandebo@chromium.orgd3ae7792011-02-24 00:21:06 +0000305SkShader::GradientType SkColorShader::asAGradient(GradientInfo* info) const {
306 if (info) {
307 if (info->fColors && info->fColorCount >= 1) {
308 info->fColors[0] = fColor;
309 }
310 info->fColorCount = 1;
311 info->fTileMode = SkShader::kRepeat_TileMode;
312 }
313 return kColor_GradientType;
314}
reed@google.com37a20122011-07-05 18:54:12 +0000315
commit-bot@chromium.org0f10f7b2014-03-13 18:02:17 +0000316#ifndef SK_IGNORE_TO_STRING
robertphillips@google.com76f9e932013-01-15 20:17:47 +0000317void SkColorShader::toString(SkString* str) const {
318 str->append("SkColorShader: (");
319
commit-bot@chromium.org76a3b2a2014-04-24 16:54:46 +0000320 str->append("Color: ");
321 str->appendHex(fColor);
robertphillips@google.com76f9e932013-01-15 20:17:47 +0000322
323 this->INHERITED::toString(str);
324
325 str->append(")");
326}
327#endif
328
reed@google.com37a20122011-07-05 18:54:12 +0000329///////////////////////////////////////////////////////////////////////////////
330
commit-bot@chromium.org87fcd952014-04-23 19:10:51 +0000331#ifndef SK_IGNORE_TO_STRING
reed@google.com37a20122011-07-05 18:54:12 +0000332#include "SkEmptyShader.h"
333
robertphillips@google.com76f9e932013-01-15 20:17:47 +0000334void SkEmptyShader::toString(SkString* str) const {
335 str->append("SkEmptyShader: (");
336
337 this->INHERITED::toString(str);
338
339 str->append(")");
340}
341#endif