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