2 * Copyright 2006 The Android Open Source Project
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
8 #include "SkBitmapProcShader.h"
9 #include "SkEmptyShader.h"
10 #include "SkReadBuffer.h"
11 #include "SkMallocPixelRef.h"
13 #include "SkPicture.h"
14 #include "SkPictureShader.h"
17 #include "SkWriteBuffer.h"
19 SkShader::SkShader(const SkMatrix* localMatrix) {
21 fLocalMatrix = *localMatrix;
27 SkShader::SkShader(SkReadBuffer& buffer)
29 if (buffer.readBool()) {
30 buffer.readMatrix(&fLocalMatrix);
36 SkShader::~SkShader() {
39 void SkShader::flatten(SkWriteBuffer& buffer) const {
40 this->INHERITED::flatten(buffer);
41 bool hasLocalM = this->hasLocalMatrix();
42 buffer.writeBool(hasLocalM);
44 buffer.writeMatrix(fLocalMatrix);
48 bool SkShader::computeTotalInverse(const ContextRec& rec, SkMatrix* totalInverse) const {
49 const SkMatrix* m = rec.fMatrix;
52 if (this->hasLocalMatrix()) {
53 total.setConcat(*m, this->getLocalMatrix());
56 if (rec.fLocalMatrix) {
57 total.setConcat(*m, *rec.fLocalMatrix);
60 return m->invert(totalInverse);
63 SkShader::Context* SkShader::createContext(const ContextRec& rec, void* storage) const {
64 if (!this->computeTotalInverse(rec, NULL)) {
67 return this->onCreateContext(rec, storage);
70 SkShader::Context* SkShader::onCreateContext(const ContextRec& rec, void*) const {
74 size_t SkShader::contextSize() const {
78 SkShader::Context::Context(const SkShader& shader, const ContextRec& rec)
79 : fShader(shader), fCTM(*rec.fMatrix)
81 // Because the context parameters must be valid at this point, we know that the matrix is
83 SkAssertResult(fShader.computeTotalInverse(rec, &fTotalInverse));
84 fTotalInverseClass = (uint8_t)ComputeMatrixClass(fTotalInverse);
86 fPaintAlpha = rec.fPaint->getAlpha();
89 SkShader::Context::~Context() {}
91 SkShader::Context::ShadeProc SkShader::Context::asAShadeProc(void** ctx) {
95 #include "SkColorPriv.h"
97 void SkShader::Context::shadeSpan16(int x, int y, uint16_t span16[], int count) {
100 SkASSERT(this->canCallShadeSpan16());
102 // basically, if we get here, the subclass screwed up
103 SkDEBUGFAIL("kHasSpan16 flag is set, but shadeSpan16() not implemented");
106 #define kTempColorQuadCount 6 // balance between speed (larger) and saving stack-space
107 #define kTempColorCount (kTempColorQuadCount << 2)
109 #ifdef SK_CPU_BENDIAN
110 #define SkU32BitShiftToByteOffset(shift) (3 - ((shift) >> 3))
112 #define SkU32BitShiftToByteOffset(shift) ((shift) >> 3)
115 void SkShader::Context::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) {
118 SkPMColor colors[kTempColorCount];
120 while ((count -= kTempColorCount) >= 0) {
121 this->shadeSpan(x, y, colors, kTempColorCount);
122 x += kTempColorCount;
124 const uint8_t* srcA = (const uint8_t*)colors + SkU32BitShiftToByteOffset(SK_A32_SHIFT);
125 int quads = kTempColorQuadCount;
132 *alpha++ = SkToU8(a0);
133 *alpha++ = SkToU8(a1);
134 *alpha++ = SkToU8(a2);
135 *alpha++ = SkToU8(a3);
136 } while (--quads != 0);
139 SkASSERT(count + kTempColorCount >= 0);
140 if (count += kTempColorCount) {
141 this->shadeSpan(x, y, colors, count);
143 const uint8_t* srcA = (const uint8_t*)colors + SkU32BitShiftToByteOffset(SK_A32_SHIFT);
147 } while (--count != 0);
152 if (n > kTempColorCount)
156 this->shadeSpan(x, y, colors, n);
160 const uint8_t* srcA = (const uint8_t*)colors + SkU32BitShiftToByteOffset(SK_A32_SHIFT);
169 SkShader::Context::MatrixClass SkShader::Context::ComputeMatrixClass(const SkMatrix& mat) {
170 MatrixClass mc = kLinear_MatrixClass;
172 if (mat.hasPerspective()) {
173 if (mat.fixedStepInX(0, NULL, NULL)) {
174 mc = kFixedStepInX_MatrixClass;
176 mc = kPerspective_MatrixClass;
182 //////////////////////////////////////////////////////////////////////////////
184 SkShader::BitmapType SkShader::asABitmap(SkBitmap*, SkMatrix*, TileMode*) const {
185 return kNone_BitmapType;
188 SkShader::GradientType SkShader::asAGradient(GradientInfo* info) const {
189 return kNone_GradientType;
192 GrEffectRef* SkShader::asNewEffect(GrContext*, const SkPaint&) const {
196 SkShader* SkShader::CreateEmptyShader() {
197 return SkNEW(SkEmptyShader);
200 SkShader* SkShader::CreateBitmapShader(const SkBitmap& src, TileMode tmx, TileMode tmy,
201 const SkMatrix* localMatrix) {
202 return ::CreateBitmapShader(src, tmx, tmy, localMatrix, NULL);
205 SkShader* SkShader::CreatePictureShader(SkPicture* src, TileMode tmx, TileMode tmy,
206 const SkMatrix* localMatrix) {
207 return SkPictureShader::Create(src, tmx, tmy, localMatrix);
210 #ifndef SK_IGNORE_TO_STRING
211 void SkShader::toString(SkString* str) const {
212 if (this->hasLocalMatrix()) {
214 this->getLocalMatrix().toString(str);
219 //////////////////////////////////////////////////////////////////////////////
221 #include "SkColorShader.h"
224 SkColorShader::SkColorShader(SkColor c)
228 bool SkColorShader::isOpaque() const {
229 return SkColorGetA(fColor) == 255;
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()) {
237 SkDEBUGFAIL("We shouldn't have pictures that recorded the inherited case.");
238 fColor = SK_ColorWHITE;
242 fColor = b.readColor();
245 void SkColorShader::flatten(SkWriteBuffer& buffer) const {
246 this->INHERITED::flatten(buffer);
247 buffer.writeColor(fColor);
250 uint32_t SkColorShader::ColorShaderContext::getFlags() const {
254 uint8_t SkColorShader::ColorShaderContext::getSpan16Alpha() const {
255 return SkGetPackedA32(fPMColor);
258 SkShader::Context* SkColorShader::onCreateContext(const ContextRec& rec, void* storage) const {
259 return SkNEW_PLACEMENT_ARGS(storage, ColorShaderContext, (*this, rec));
262 SkColorShader::ColorShaderContext::ColorShaderContext(const SkColorShader& shader,
263 const ContextRec& rec)
264 : INHERITED(shader, rec)
266 SkColor color = shader.fColor;
267 unsigned a = SkAlphaMul(SkColorGetA(color), SkAlpha255To256(rec.fPaint->getAlpha()));
269 unsigned r = SkColorGetR(color);
270 unsigned g = SkColorGetG(color);
271 unsigned b = SkColorGetB(color);
273 // we want this before we apply any alpha
274 fColor16 = SkPack888ToRGB16(r, g, b);
277 r = SkMulDiv255Round(r, a);
278 g = SkMulDiv255Round(g, a);
279 b = SkMulDiv255Round(b, a);
281 fPMColor = SkPackARGB32(a, r, g, b);
283 fFlags = kConstInY32_Flag;
285 fFlags |= kOpaqueAlpha_Flag;
286 if (rec.fPaint->isDither() == false) {
287 fFlags |= kHasSpan16_Flag;
292 void SkColorShader::ColorShaderContext::shadeSpan(int x, int y, SkPMColor span[], int count) {
293 sk_memset32(span, fPMColor, count);
296 void SkColorShader::ColorShaderContext::shadeSpan16(int x, int y, uint16_t span[], int count) {
297 sk_memset16(span, fColor16, count);
300 void SkColorShader::ColorShaderContext::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) {
301 memset(alpha, SkGetPackedA32(fPMColor), count);
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;
310 SkShader::GradientType SkColorShader::asAGradient(GradientInfo* info) const {
312 if (info->fColors && info->fColorCount >= 1) {
313 info->fColors[0] = fColor;
315 info->fColorCount = 1;
316 info->fTileMode = SkShader::kRepeat_TileMode;
318 return kColor_GradientType;
321 #ifndef SK_IGNORE_TO_STRING
322 void SkColorShader::toString(SkString* str) const {
323 str->append("SkColorShader: (");
325 str->append("Color: ");
326 str->appendHex(fColor);
328 this->INHERITED::toString(str);
334 ///////////////////////////////////////////////////////////////////////////////
336 #ifndef SK_IGNORE_TO_STRING
337 #include "SkEmptyShader.h"
339 void SkEmptyShader::toString(SkString* str) const {
340 str->append("SkEmptyShader: (");
342 this->INHERITED::toString(str);