SkShader.cpp revision 74b8cb15e4fb330e8d10856f6620e8b92b39a9ce
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#include "SkBitmapProcShader.h" 9#include "SkReadBuffer.h" 10#include "SkMallocPixelRef.h" 11#include "SkPaint.h" 12#include "SkPicture.h" 13#include "SkPictureShader.h" 14#include "SkScalar.h" 15#include "SkShader.h" 16#include "SkWriteBuffer.h" 17 18SkShader::SkShader(const SkMatrix* localMatrix) { 19 if (localMatrix) { 20 fLocalMatrix = *localMatrix; 21 } else { 22 fLocalMatrix.reset(); 23 } 24} 25 26SkShader::SkShader(SkReadBuffer& buffer) 27 : INHERITED(buffer) { 28 if (buffer.readBool()) { 29 buffer.readMatrix(&fLocalMatrix); 30 } else { 31 fLocalMatrix.reset(); 32 } 33} 34 35SkShader::~SkShader() { 36} 37 38void SkShader::flatten(SkWriteBuffer& buffer) const { 39 this->INHERITED::flatten(buffer); 40 bool hasLocalM = this->hasLocalMatrix(); 41 buffer.writeBool(hasLocalM); 42 if (hasLocalM) { 43 buffer.writeMatrix(fLocalMatrix); 44 } 45} 46 47bool SkShader::computeTotalInverse(const SkMatrix& matrix, SkMatrix* totalInverse) const { 48 const SkMatrix* m = &matrix; 49 SkMatrix total; 50 51 if (this->hasLocalMatrix()) { 52 total.setConcat(matrix, this->getLocalMatrix()); 53 m = &total; 54 } 55 56 return m->invert(totalInverse); 57} 58 59bool SkShader::validContext(const ContextRec& rec, SkMatrix* totalInverse) const { 60 return this->computeTotalInverse(*rec.fMatrix, totalInverse); 61} 62 63SkShader::Context* SkShader::createContext(const ContextRec&, void* storage) const { 64 return NULL; 65} 66 67size_t SkShader::contextSize() const { 68 return 0; 69} 70 71SkShader::Context::Context(const SkShader& shader, const ContextRec& rec) 72 : fShader(shader) 73{ 74 SkASSERT(fShader.validContext(rec)); 75 76 // Because the context parameters must be valid at this point, we know that the matrix is 77 // invertible. 78 SkAssertResult(fShader.computeTotalInverse(*rec.fMatrix, &fTotalInverse)); 79 fTotalInverseClass = (uint8_t)ComputeMatrixClass(fTotalInverse); 80 81 fPaintAlpha = rec.fPaint->getAlpha(); 82} 83 84SkShader::Context::~Context() {} 85 86SkShader::Context::ShadeProc SkShader::Context::asAShadeProc(void** ctx) { 87 return NULL; 88} 89 90#include "SkColorPriv.h" 91 92void SkShader::Context::shadeSpan16(int x, int y, uint16_t span16[], int count) { 93 SkASSERT(span16); 94 SkASSERT(count > 0); 95 SkASSERT(this->canCallShadeSpan16()); 96 97 // basically, if we get here, the subclass screwed up 98 SkDEBUGFAIL("kHasSpan16 flag is set, but shadeSpan16() not implemented"); 99} 100 101#define kTempColorQuadCount 6 // balance between speed (larger) and saving stack-space 102#define kTempColorCount (kTempColorQuadCount << 2) 103 104#ifdef SK_CPU_BENDIAN 105 #define SkU32BitShiftToByteOffset(shift) (3 - ((shift) >> 3)) 106#else 107 #define SkU32BitShiftToByteOffset(shift) ((shift) >> 3) 108#endif 109 110void SkShader::Context::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) { 111 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 164SkShader::Context::MatrixClass SkShader::Context::ComputeMatrixClass(const SkMatrix& mat) { 165 MatrixClass mc = kLinear_MatrixClass; 166 167 if (mat.hasPerspective()) { 168 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 179SkShader::BitmapType SkShader::asABitmap(SkBitmap*, SkMatrix*, TileMode*) const { 180 return kNone_BitmapType; 181} 182 183SkShader::GradientType SkShader::asAGradient(GradientInfo* info) const { 184 return kNone_GradientType; 185} 186 187GrEffectRef* SkShader::asNewEffect(GrContext*, const SkPaint&) const { 188 return NULL; 189} 190 191SkShader* SkShader::CreateBitmapShader(const SkBitmap& src, TileMode tmx, TileMode tmy, 192 const SkMatrix* localMatrix) { 193 return ::CreateBitmapShader(src, tmx, tmy, localMatrix, NULL); 194} 195 196SkShader* SkShader::CreatePictureShader(SkPicture* src, TileMode tmx, TileMode tmy, 197 const SkMatrix* localMatrix) { 198 return SkPictureShader::Create(src, tmx, tmy, localMatrix); 199} 200 201#ifndef SK_IGNORE_TO_STRING 202void SkShader::toString(SkString* str) const { 203 if (this->hasLocalMatrix()) { 204 str->append(" "); 205 this->getLocalMatrix().toString(str); 206 } 207} 208#endif 209 210////////////////////////////////////////////////////////////////////////////// 211 212#include "SkColorShader.h" 213#include "SkUtils.h" 214 215SkColorShader::SkColorShader(SkColor c) 216 : fColor(c) { 217} 218 219bool SkColorShader::isOpaque() const { 220 return SkColorGetA(fColor) == 255; 221} 222 223SkColorShader::SkColorShader(SkReadBuffer& b) : INHERITED(b) { 224 // 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 } 232 } 233 fColor = b.readColor(); 234} 235 236void SkColorShader::flatten(SkWriteBuffer& buffer) const { 237 this->INHERITED::flatten(buffer); 238 buffer.writeColor(fColor); 239} 240 241uint32_t SkColorShader::ColorShaderContext::getFlags() const { 242 return fFlags; 243} 244 245uint8_t SkColorShader::ColorShaderContext::getSpan16Alpha() const { 246 return SkGetPackedA32(fPMColor); 247} 248 249SkShader::Context* SkColorShader::createContext(const ContextRec& rec, void* storage) const { 250 if (!this->validContext(rec)) { 251 return NULL; 252 } 253 254 return SkNEW_PLACEMENT_ARGS(storage, ColorShaderContext, (*this, rec)); 255} 256 257SkColorShader::ColorShaderContext::ColorShaderContext(const SkColorShader& shader, 258 const ContextRec& rec) 259 : INHERITED(shader, rec) 260{ 261 SkColor color = shader.fColor; 262 unsigned a = SkAlphaMul(SkColorGetA(color), SkAlpha255To256(rec.fPaint->getAlpha())); 263 264 unsigned r = SkColorGetR(color); 265 unsigned g = SkColorGetG(color); 266 unsigned b = SkColorGetB(color); 267 268 // we want this before we apply any alpha 269 fColor16 = SkPack888ToRGB16(r, g, b); 270 271 if (a != 255) { 272 r = SkMulDiv255Round(r, a); 273 g = SkMulDiv255Round(g, a); 274 b = SkMulDiv255Round(b, a); 275 } 276 fPMColor = SkPackARGB32(a, r, g, b); 277 278 fFlags = kConstInY32_Flag; 279 if (255 == a) { 280 fFlags |= kOpaqueAlpha_Flag; 281 if (rec.fPaint->isDither() == false) { 282 fFlags |= kHasSpan16_Flag; 283 } 284 } 285} 286 287void SkColorShader::ColorShaderContext::shadeSpan(int x, int y, SkPMColor span[], int count) { 288 sk_memset32(span, fPMColor, count); 289} 290 291void SkColorShader::ColorShaderContext::shadeSpan16(int x, int y, uint16_t span[], int count) { 292 sk_memset16(span, fColor16, count); 293} 294 295void SkColorShader::ColorShaderContext::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) { 296 memset(alpha, SkGetPackedA32(fPMColor), count); 297} 298 299// if we had a asAColor method, that would be more efficient... 300SkShader::BitmapType SkColorShader::asABitmap(SkBitmap* bitmap, SkMatrix* matrix, 301 TileMode modes[]) const { 302 return kNone_BitmapType; 303} 304 305SkShader::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} 315 316#ifndef SK_IGNORE_TO_STRING 317void SkColorShader::toString(SkString* str) const { 318 str->append("SkColorShader: ("); 319 320 str->append("Color: "); 321 str->appendHex(fColor); 322 323 this->INHERITED::toString(str); 324 325 str->append(")"); 326} 327#endif 328 329/////////////////////////////////////////////////////////////////////////////// 330 331#ifndef SK_IGNORE_TO_STRING 332#include "SkEmptyShader.h" 333 334void SkEmptyShader::toString(SkString* str) const { 335 str->append("SkEmptyShader: ("); 336 337 this->INHERITED::toString(str); 338 339 str->append(")"); 340} 341#endif 342