SkShader.cpp revision 9c9005a347e9996f357bd79591bd34f74f8bbc66
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 SkBitmap& device, 60 const SkPaint& paint, 61 const SkMatrix& matrix, 62 SkMatrix* totalInverse) const { 63 return this->computeTotalInverse(matrix, totalInverse); 64} 65 66SkShader::Context::Context(const SkShader& shader, const SkBitmap& device, 67 const SkPaint& paint, const SkMatrix& matrix) 68 : fShader(shader) 69{ 70 SkASSERT(fShader.validContext(device, paint, matrix)); 71 72 // Because the context parameters must be valid at this point, we know that the matrix is 73 // invertible. 74 SkAssertResult(fShader.computeTotalInverse(matrix, &fTotalInverse)); 75 fTotalInverseClass = (uint8_t)ComputeMatrixClass(fTotalInverse); 76 77 fPaintAlpha = paint.getAlpha(); 78} 79 80SkShader::Context::~Context() {} 81 82SkShader::Context::ShadeProc SkShader::Context::asAShadeProc(void** ctx) { 83 return NULL; 84} 85 86#include "SkColorPriv.h" 87 88void SkShader::Context::shadeSpan16(int x, int y, uint16_t span16[], int count) { 89 SkASSERT(span16); 90 SkASSERT(count > 0); 91 SkASSERT(this->canCallShadeSpan16()); 92 93 // basically, if we get here, the subclass screwed up 94 SkDEBUGFAIL("kHasSpan16 flag is set, but shadeSpan16() not implemented"); 95} 96 97#define kTempColorQuadCount 6 // balance between speed (larger) and saving stack-space 98#define kTempColorCount (kTempColorQuadCount << 2) 99 100#ifdef SK_CPU_BENDIAN 101 #define SkU32BitShiftToByteOffset(shift) (3 - ((shift) >> 3)) 102#else 103 #define SkU32BitShiftToByteOffset(shift) ((shift) >> 3) 104#endif 105 106void SkShader::Context::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) { 107 SkASSERT(count > 0); 108 109 SkPMColor colors[kTempColorCount]; 110 111 while ((count -= kTempColorCount) >= 0) { 112 this->shadeSpan(x, y, colors, kTempColorCount); 113 x += kTempColorCount; 114 115 const uint8_t* srcA = (const uint8_t*)colors + SkU32BitShiftToByteOffset(SK_A32_SHIFT); 116 int quads = kTempColorQuadCount; 117 do { 118 U8CPU a0 = srcA[0]; 119 U8CPU a1 = srcA[4]; 120 U8CPU a2 = srcA[8]; 121 U8CPU a3 = srcA[12]; 122 srcA += 4*4; 123 *alpha++ = SkToU8(a0); 124 *alpha++ = SkToU8(a1); 125 *alpha++ = SkToU8(a2); 126 *alpha++ = SkToU8(a3); 127 } while (--quads != 0); 128 } 129 SkASSERT(count < 0); 130 SkASSERT(count + kTempColorCount >= 0); 131 if (count += kTempColorCount) { 132 this->shadeSpan(x, y, colors, count); 133 134 const uint8_t* srcA = (const uint8_t*)colors + SkU32BitShiftToByteOffset(SK_A32_SHIFT); 135 do { 136 *alpha++ = *srcA; 137 srcA += 4; 138 } while (--count != 0); 139 } 140#if 0 141 do { 142 int n = count; 143 if (n > kTempColorCount) 144 n = kTempColorCount; 145 SkASSERT(n > 0); 146 147 this->shadeSpan(x, y, colors, n); 148 x += n; 149 count -= n; 150 151 const uint8_t* srcA = (const uint8_t*)colors + SkU32BitShiftToByteOffset(SK_A32_SHIFT); 152 do { 153 *alpha++ = *srcA; 154 srcA += 4; 155 } while (--n != 0); 156 } while (count > 0); 157#endif 158} 159 160SkShader::Context::MatrixClass SkShader::Context::ComputeMatrixClass(const SkMatrix& mat) { 161 MatrixClass mc = kLinear_MatrixClass; 162 163 if (mat.hasPerspective()) { 164 if (mat.fixedStepInX(0, NULL, NULL)) { 165 mc = kFixedStepInX_MatrixClass; 166 } else { 167 mc = kPerspective_MatrixClass; 168 } 169 } 170 return mc; 171} 172 173////////////////////////////////////////////////////////////////////////////// 174 175SkShader::BitmapType SkShader::asABitmap(SkBitmap*, SkMatrix*, TileMode*) const { 176 return kNone_BitmapType; 177} 178 179SkShader::GradientType SkShader::asAGradient(GradientInfo* info) const { 180 return kNone_GradientType; 181} 182 183GrEffectRef* SkShader::asNewEffect(GrContext*, const SkPaint&) const { 184 return NULL; 185} 186 187SkShader* SkShader::CreateBitmapShader(const SkBitmap& src, TileMode tmx, TileMode tmy, 188 const SkMatrix* localMatrix) { 189 return ::CreateBitmapShader(src, tmx, tmy, localMatrix, NULL); 190} 191 192SkShader* SkShader::CreatePictureShader(SkPicture* src, TileMode tmx, TileMode tmy) { 193 return SkPictureShader::Create(src, tmx, tmy); 194} 195 196#ifndef SK_IGNORE_TO_STRING 197void SkShader::toString(SkString* str) const { 198 if (this->hasLocalMatrix()) { 199 str->append(" "); 200 this->getLocalMatrix().toString(str); 201 } 202} 203#endif 204 205////////////////////////////////////////////////////////////////////////////// 206 207#include "SkColorShader.h" 208#include "SkUtils.h" 209 210SkColorShader::SkColorShader(SkColor c) 211 : fColor(c) { 212} 213 214bool SkColorShader::isOpaque() const { 215 return SkColorGetA(fColor) == 255; 216} 217 218SkColorShader::SkColorShader(SkReadBuffer& b) : INHERITED(b) { 219 // V25_COMPATIBILITY_CODE We had a boolean to make the color shader inherit the paint's 220 // color. We don't support that any more. 221 if (b.pictureVersion() < 26 && 0 != b.pictureVersion()) { 222 if (b.readBool()) { 223 SkDEBUGFAIL("We shouldn't have pictures that recorded the inherited case."); 224 fColor = SK_ColorWHITE; 225 return; 226 } 227 } 228 fColor = b.readColor(); 229} 230 231void SkColorShader::flatten(SkWriteBuffer& buffer) const { 232 this->INHERITED::flatten(buffer); 233 buffer.writeColor(fColor); 234} 235 236uint32_t SkColorShader::ColorShaderContext::getFlags() const { 237 return fFlags; 238} 239 240uint8_t SkColorShader::ColorShaderContext::getSpan16Alpha() const { 241 return SkGetPackedA32(fPMColor); 242} 243 244SkShader::Context* SkColorShader::createContext(const SkBitmap& device, const SkPaint& paint, 245 const SkMatrix& matrix, void* storage) const { 246 if (!this->validContext(device, paint, matrix)) { 247 return NULL; 248 } 249 250 return SkNEW_PLACEMENT_ARGS(storage, ColorShaderContext, (*this, device, paint, matrix)); 251} 252 253SkColorShader::ColorShaderContext::ColorShaderContext(const SkColorShader& shader, 254 const SkBitmap& device, 255 const SkPaint& paint, 256 const SkMatrix& matrix) 257 : INHERITED(shader, device, paint, matrix) 258{ 259 SkColor color = shader.fColor; 260 unsigned a = SkAlphaMul(SkColorGetA(color), SkAlpha255To256(paint.getAlpha())); 261 262 unsigned r = SkColorGetR(color); 263 unsigned g = SkColorGetG(color); 264 unsigned b = SkColorGetB(color); 265 266 // we want this before we apply any alpha 267 fColor16 = SkPack888ToRGB16(r, g, b); 268 269 if (a != 255) { 270 r = SkMulDiv255Round(r, a); 271 g = SkMulDiv255Round(g, a); 272 b = SkMulDiv255Round(b, a); 273 } 274 fPMColor = SkPackARGB32(a, r, g, b); 275 276 fFlags = kConstInY32_Flag; 277 if (255 == a) { 278 fFlags |= kOpaqueAlpha_Flag; 279 if (paint.isDither() == false) { 280 fFlags |= kHasSpan16_Flag; 281 } 282 } 283} 284 285void SkColorShader::ColorShaderContext::shadeSpan(int x, int y, SkPMColor span[], int count) { 286 sk_memset32(span, fPMColor, count); 287} 288 289void SkColorShader::ColorShaderContext::shadeSpan16(int x, int y, uint16_t span[], int count) { 290 sk_memset16(span, fColor16, count); 291} 292 293void SkColorShader::ColorShaderContext::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) { 294 memset(alpha, SkGetPackedA32(fPMColor), count); 295} 296 297// if we had a asAColor method, that would be more efficient... 298SkShader::BitmapType SkColorShader::asABitmap(SkBitmap* bitmap, SkMatrix* matrix, 299 TileMode modes[]) const { 300 return kNone_BitmapType; 301} 302 303SkShader::GradientType SkColorShader::asAGradient(GradientInfo* info) const { 304 if (info) { 305 if (info->fColors && info->fColorCount >= 1) { 306 info->fColors[0] = fColor; 307 } 308 info->fColorCount = 1; 309 info->fTileMode = SkShader::kRepeat_TileMode; 310 } 311 return kColor_GradientType; 312} 313 314#ifndef SK_IGNORE_TO_STRING 315void SkColorShader::toString(SkString* str) const { 316 str->append("SkColorShader: ("); 317 318 str->append("Color: "); 319 str->appendHex(fColor); 320 321 this->INHERITED::toString(str); 322 323 str->append(")"); 324} 325#endif 326 327/////////////////////////////////////////////////////////////////////////////// 328 329#ifndef SK_IGNORE_TO_STRING 330#include "SkEmptyShader.h" 331 332void SkEmptyShader::toString(SkString* str) const { 333 str->append("SkEmptyShader: ("); 334 335 this->INHERITED::toString(str); 336 337 str->append(")"); 338} 339#endif 340