SkShader.cpp revision 91f319c5dc4493384f0a52aaeef3dcc311ef6ed0
1 2/* 3 * Copyright 2006 The Android Open Source Project 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9 10#include "SkScalar.h" 11#include "SkShader.h" 12#include "SkPaint.h" 13#include "SkMallocPixelRef.h" 14 15SK_DEFINE_INST_COUNT(SkShader) 16 17SkShader::SkShader() : fLocalMatrix(NULL) { 18 SkDEBUGCODE(fInSession = false;) 19} 20 21SkShader::SkShader(SkFlattenableReadBuffer& buffer) 22 : INHERITED(buffer), fLocalMatrix(NULL) { 23 if (buffer.readBool()) { 24 SkMatrix matrix; 25 buffer.readMatrix(&matrix); 26 setLocalMatrix(matrix); 27 } 28 SkDEBUGCODE(fInSession = false;) 29} 30 31SkShader::~SkShader() { 32 SkASSERT(!fInSession); 33 sk_free(fLocalMatrix); 34} 35 36void SkShader::beginSession() { 37 SkASSERT(!fInSession); 38 SkDEBUGCODE(fInSession = true;) 39} 40 41void SkShader::endSession() { 42 SkASSERT(fInSession); 43 SkDEBUGCODE(fInSession = false;) 44} 45 46void SkShader::flatten(SkFlattenableWriteBuffer& buffer) const { 47 this->INHERITED::flatten(buffer); 48 buffer.writeBool(fLocalMatrix != NULL); 49 if (fLocalMatrix) { 50 buffer.writeMatrix(*fLocalMatrix); 51 } 52} 53 54bool SkShader::getLocalMatrix(SkMatrix* localM) const { 55 if (fLocalMatrix) { 56 if (localM) { 57 *localM = *fLocalMatrix; 58 } 59 return true; 60 } else { 61 if (localM) { 62 localM->reset(); 63 } 64 return false; 65 } 66} 67 68void SkShader::setLocalMatrix(const SkMatrix& localM) { 69 if (localM.isIdentity()) { 70 this->resetLocalMatrix(); 71 } else { 72 if (fLocalMatrix == NULL) { 73 fLocalMatrix = (SkMatrix*)sk_malloc_throw(sizeof(SkMatrix)); 74 } 75 *fLocalMatrix = localM; 76 } 77} 78 79void SkShader::resetLocalMatrix() { 80 if (fLocalMatrix) { 81 sk_free(fLocalMatrix); 82 fLocalMatrix = NULL; 83 } 84} 85 86bool SkShader::setContext(const SkBitmap& device, 87 const SkPaint& paint, 88 const SkMatrix& matrix) { 89 const SkMatrix* m = &matrix; 90 SkMatrix total; 91 92 fDeviceConfig = SkToU8(device.getConfig()); 93 fPaintAlpha = paint.getAlpha(); 94 if (fLocalMatrix) { 95 total.setConcat(matrix, *fLocalMatrix); 96 m = &total; 97 } 98 if (m->invert(&fTotalInverse)) { 99 fTotalInverseClass = (uint8_t)ComputeMatrixClass(fTotalInverse); 100 return true; 101 } 102 return false; 103} 104 105#include "SkColorPriv.h" 106 107void SkShader::shadeSpan16(int x, int y, uint16_t span16[], int count) { 108 SkASSERT(span16); 109 SkASSERT(count > 0); 110 SkASSERT(this->canCallShadeSpan16()); 111 112 // basically, if we get here, the subclass screwed up 113 SkDEBUGFAIL("kHasSpan16 flag is set, but shadeSpan16() not implemented"); 114} 115 116#define kTempColorQuadCount 6 // balance between speed (larger) and saving stack-space 117#define kTempColorCount (kTempColorQuadCount << 2) 118 119#ifdef SK_CPU_BENDIAN 120 #define SkU32BitShiftToByteOffset(shift) (3 - ((shift) >> 3)) 121#else 122 #define SkU32BitShiftToByteOffset(shift) ((shift) >> 3) 123#endif 124 125void SkShader::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) { 126 SkASSERT(count > 0); 127 128 SkPMColor colors[kTempColorCount]; 129 130 while ((count -= kTempColorCount) >= 0) { 131 this->shadeSpan(x, y, colors, kTempColorCount); 132 x += kTempColorCount; 133 134 const uint8_t* srcA = (const uint8_t*)colors + SkU32BitShiftToByteOffset(SK_A32_SHIFT); 135 int quads = kTempColorQuadCount; 136 do { 137 U8CPU a0 = srcA[0]; 138 U8CPU a1 = srcA[4]; 139 U8CPU a2 = srcA[8]; 140 U8CPU a3 = srcA[12]; 141 srcA += 4*4; 142 *alpha++ = SkToU8(a0); 143 *alpha++ = SkToU8(a1); 144 *alpha++ = SkToU8(a2); 145 *alpha++ = SkToU8(a3); 146 } while (--quads != 0); 147 } 148 SkASSERT(count < 0); 149 SkASSERT(count + kTempColorCount >= 0); 150 if (count += kTempColorCount) { 151 this->shadeSpan(x, y, colors, count); 152 153 const uint8_t* srcA = (const uint8_t*)colors + SkU32BitShiftToByteOffset(SK_A32_SHIFT); 154 do { 155 *alpha++ = *srcA; 156 srcA += 4; 157 } while (--count != 0); 158 } 159#if 0 160 do { 161 int n = count; 162 if (n > kTempColorCount) 163 n = kTempColorCount; 164 SkASSERT(n > 0); 165 166 this->shadeSpan(x, y, colors, n); 167 x += n; 168 count -= n; 169 170 const uint8_t* srcA = (const uint8_t*)colors + SkU32BitShiftToByteOffset(SK_A32_SHIFT); 171 do { 172 *alpha++ = *srcA; 173 srcA += 4; 174 } while (--n != 0); 175 } while (count > 0); 176#endif 177} 178 179SkShader::MatrixClass SkShader::ComputeMatrixClass(const SkMatrix& mat) { 180 MatrixClass mc = kLinear_MatrixClass; 181 182 if (mat.hasPerspective()) { 183 if (mat.fixedStepInX(0, NULL, NULL)) { 184 mc = kFixedStepInX_MatrixClass; 185 } else { 186 mc = kPerspective_MatrixClass; 187 } 188 } 189 return mc; 190} 191 192////////////////////////////////////////////////////////////////////////////// 193 194SkShader::BitmapType SkShader::asABitmap(SkBitmap*, SkMatrix*, 195 TileMode*) const { 196 return kNone_BitmapType; 197} 198 199SkShader::GradientType SkShader::asAGradient(GradientInfo* info) const { 200 return kNone_GradientType; 201} 202 203GrCustomStage* SkShader::asNewCustomStage(GrContext* context, 204 GrSamplerState* sampler) const { 205 return NULL; 206} 207 208SkShader* SkShader::CreateBitmapShader(const SkBitmap& src, 209 TileMode tmx, TileMode tmy) { 210 return SkShader::CreateBitmapShader(src, tmx, tmy, NULL, 0); 211} 212 213////////////////////////////////////////////////////////////////////////////// 214 215#include "SkColorShader.h" 216#include "SkUtils.h" 217 218SkColorShader::SkColorShader() { 219 fFlags = 0; 220 fInheritColor = true; 221} 222 223SkColorShader::SkColorShader(SkColor c) { 224 fFlags = 0; 225 fColor = c; 226 fInheritColor = false; 227} 228 229SkColorShader::~SkColorShader() {} 230 231bool SkColorShader::isOpaque() const { 232 if (fInheritColor) { 233 return true; // using paint's alpha 234 } 235 return SkColorGetA(fColor) == 255; 236} 237 238SkColorShader::SkColorShader(SkFlattenableReadBuffer& b) : INHERITED(b) { 239 fFlags = 0; // computed in setContext 240 241 fInheritColor = b.readU8(); 242 if (fInheritColor) { 243 return; 244 } 245 fColor = b.readU32(); 246} 247 248void SkColorShader::flatten(SkFlattenableWriteBuffer& buffer) const { 249 this->INHERITED::flatten(buffer); 250 buffer.write8(fInheritColor); 251 if (fInheritColor) { 252 return; 253 } 254 buffer.write32(fColor); 255} 256 257uint32_t SkColorShader::getFlags() { 258 return fFlags; 259} 260 261uint8_t SkColorShader::getSpan16Alpha() const { 262 return SkGetPackedA32(fPMColor); 263} 264 265bool SkColorShader::setContext(const SkBitmap& device, const SkPaint& paint, 266 const SkMatrix& matrix) { 267 if (!this->INHERITED::setContext(device, paint, matrix)) { 268 return false; 269 } 270 271 unsigned a; 272 273 if (fInheritColor) { 274 fColor = paint.getColor(); 275 a = SkColorGetA(fColor); 276 } else { 277 a = SkAlphaMul(SkColorGetA(fColor), SkAlpha255To256(paint.getAlpha())); 278 } 279 280 unsigned r = SkColorGetR(fColor); 281 unsigned g = SkColorGetG(fColor); 282 unsigned b = SkColorGetB(fColor); 283 284 // we want this before we apply any alpha 285 fColor16 = SkPack888ToRGB16(r, g, b); 286 287 if (a != 255) { 288 r = SkMulDiv255Round(r, a); 289 g = SkMulDiv255Round(g, a); 290 b = SkMulDiv255Round(b, a); 291 } 292 fPMColor = SkPackARGB32(a, r, g, b); 293 294 fFlags = kConstInY32_Flag; 295 if (255 == a) { 296 fFlags |= kOpaqueAlpha_Flag; 297 if (paint.isDither() == false) { 298 fFlags |= kHasSpan16_Flag; 299 } 300 } 301 302 return true; 303} 304 305void SkColorShader::shadeSpan(int x, int y, SkPMColor span[], int count) { 306 sk_memset32(span, fPMColor, count); 307} 308 309void SkColorShader::shadeSpan16(int x, int y, uint16_t span[], int count) { 310 sk_memset16(span, fColor16, count); 311} 312 313void SkColorShader::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) { 314 memset(alpha, SkGetPackedA32(fPMColor), count); 315} 316 317// if we had a asAColor method, that would be more efficient... 318SkShader::BitmapType SkColorShader::asABitmap(SkBitmap* bitmap, SkMatrix* matrix, 319 TileMode modes[]) const { 320 return kNone_BitmapType; 321} 322 323SkShader::GradientType SkColorShader::asAGradient(GradientInfo* info) const { 324 if (info) { 325 if (info->fColors && info->fColorCount >= 1) { 326 info->fColors[0] = fColor; 327 } 328 info->fColorCount = 1; 329 info->fTileMode = SkShader::kRepeat_TileMode; 330 } 331 return kColor_GradientType; 332} 333 334SK_DEFINE_FLATTENABLE_REGISTRAR(SkColorShader) 335 336/////////////////////////////////////////////////////////////////////////////// 337 338#include "SkEmptyShader.h" 339 340uint32_t SkEmptyShader::getFlags() { return 0; } 341uint8_t SkEmptyShader::getSpan16Alpha() const { return 0; } 342 343bool SkEmptyShader::setContext(const SkBitmap&, const SkPaint&, 344 const SkMatrix&) { return false; } 345 346void SkEmptyShader::shadeSpan(int x, int y, SkPMColor span[], int count) { 347 SkDEBUGFAIL("should never get called, since setContext() returned false"); 348} 349 350void SkEmptyShader::shadeSpan16(int x, int y, uint16_t span[], int count) { 351 SkDEBUGFAIL("should never get called, since setContext() returned false"); 352} 353 354void SkEmptyShader::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) { 355 SkDEBUGFAIL("should never get called, since setContext() returned false"); 356} 357 358SK_DEFINE_FLATTENABLE_REGISTRAR(SkEmptyShader) 359