SkShader.cpp revision b022177777c3602c47bb71c07920e63a261c5038
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 106SkShader::ShadeProc SkShader::asAShadeProc(void** ctx) { 107 return NULL; 108} 109 110#include "SkColorPriv.h" 111 112void SkShader::shadeSpan16(int x, int y, uint16_t span16[], int count) { 113 SkASSERT(span16); 114 SkASSERT(count > 0); 115 SkASSERT(this->canCallShadeSpan16()); 116 117 // basically, if we get here, the subclass screwed up 118 SkDEBUGFAIL("kHasSpan16 flag is set, but shadeSpan16() not implemented"); 119} 120 121#define kTempColorQuadCount 6 // balance between speed (larger) and saving stack-space 122#define kTempColorCount (kTempColorQuadCount << 2) 123 124#ifdef SK_CPU_BENDIAN 125 #define SkU32BitShiftToByteOffset(shift) (3 - ((shift) >> 3)) 126#else 127 #define SkU32BitShiftToByteOffset(shift) ((shift) >> 3) 128#endif 129 130void SkShader::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) { 131 SkASSERT(count > 0); 132 133 SkPMColor colors[kTempColorCount]; 134 135 while ((count -= kTempColorCount) >= 0) { 136 this->shadeSpan(x, y, colors, kTempColorCount); 137 x += kTempColorCount; 138 139 const uint8_t* srcA = (const uint8_t*)colors + SkU32BitShiftToByteOffset(SK_A32_SHIFT); 140 int quads = kTempColorQuadCount; 141 do { 142 U8CPU a0 = srcA[0]; 143 U8CPU a1 = srcA[4]; 144 U8CPU a2 = srcA[8]; 145 U8CPU a3 = srcA[12]; 146 srcA += 4*4; 147 *alpha++ = SkToU8(a0); 148 *alpha++ = SkToU8(a1); 149 *alpha++ = SkToU8(a2); 150 *alpha++ = SkToU8(a3); 151 } while (--quads != 0); 152 } 153 SkASSERT(count < 0); 154 SkASSERT(count + kTempColorCount >= 0); 155 if (count += kTempColorCount) { 156 this->shadeSpan(x, y, colors, count); 157 158 const uint8_t* srcA = (const uint8_t*)colors + SkU32BitShiftToByteOffset(SK_A32_SHIFT); 159 do { 160 *alpha++ = *srcA; 161 srcA += 4; 162 } while (--count != 0); 163 } 164#if 0 165 do { 166 int n = count; 167 if (n > kTempColorCount) 168 n = kTempColorCount; 169 SkASSERT(n > 0); 170 171 this->shadeSpan(x, y, colors, n); 172 x += n; 173 count -= n; 174 175 const uint8_t* srcA = (const uint8_t*)colors + SkU32BitShiftToByteOffset(SK_A32_SHIFT); 176 do { 177 *alpha++ = *srcA; 178 srcA += 4; 179 } while (--n != 0); 180 } while (count > 0); 181#endif 182} 183 184SkShader::MatrixClass SkShader::ComputeMatrixClass(const SkMatrix& mat) { 185 MatrixClass mc = kLinear_MatrixClass; 186 187 if (mat.hasPerspective()) { 188 if (mat.fixedStepInX(0, NULL, NULL)) { 189 mc = kFixedStepInX_MatrixClass; 190 } else { 191 mc = kPerspective_MatrixClass; 192 } 193 } 194 return mc; 195} 196 197////////////////////////////////////////////////////////////////////////////// 198 199SkShader::BitmapType SkShader::asABitmap(SkBitmap*, SkMatrix*, 200 TileMode*) const { 201 return kNone_BitmapType; 202} 203 204SkShader::GradientType SkShader::asAGradient(GradientInfo* info) const { 205 return kNone_GradientType; 206} 207 208bool SkShader::asNewCustomStage(GrContext*, GrSamplerState*) const { 209 return false; 210} 211 212SkShader* SkShader::CreateBitmapShader(const SkBitmap& src, 213 TileMode tmx, TileMode tmy) { 214 return SkShader::CreateBitmapShader(src, tmx, tmy, NULL, 0); 215} 216 217////////////////////////////////////////////////////////////////////////////// 218 219#include "SkColorShader.h" 220#include "SkUtils.h" 221 222SkColorShader::SkColorShader() { 223 fFlags = 0; 224 fInheritColor = true; 225} 226 227SkColorShader::SkColorShader(SkColor c) { 228 fFlags = 0; 229 fColor = c; 230 fInheritColor = false; 231} 232 233SkColorShader::~SkColorShader() {} 234 235bool SkColorShader::isOpaque() const { 236 if (fInheritColor) { 237 return true; // using paint's alpha 238 } 239 return SkColorGetA(fColor) == 255; 240} 241 242SkColorShader::SkColorShader(SkFlattenableReadBuffer& b) : INHERITED(b) { 243 fFlags = 0; // computed in setContext 244 245 fInheritColor = b.readBool(); 246 if (fInheritColor) { 247 return; 248 } 249 fColor = b.readColor(); 250} 251 252void SkColorShader::flatten(SkFlattenableWriteBuffer& buffer) const { 253 this->INHERITED::flatten(buffer); 254 buffer.writeBool(fInheritColor); 255 if (fInheritColor) { 256 return; 257 } 258 buffer.writeColor(fColor); 259} 260 261uint32_t SkColorShader::getFlags() { 262 return fFlags; 263} 264 265uint8_t SkColorShader::getSpan16Alpha() const { 266 return SkGetPackedA32(fPMColor); 267} 268 269bool SkColorShader::setContext(const SkBitmap& device, const SkPaint& paint, 270 const SkMatrix& matrix) { 271 if (!this->INHERITED::setContext(device, paint, matrix)) { 272 return false; 273 } 274 275 unsigned a; 276 277 if (fInheritColor) { 278 fColor = paint.getColor(); 279 a = SkColorGetA(fColor); 280 } else { 281 a = SkAlphaMul(SkColorGetA(fColor), SkAlpha255To256(paint.getAlpha())); 282 } 283 284 unsigned r = SkColorGetR(fColor); 285 unsigned g = SkColorGetG(fColor); 286 unsigned b = SkColorGetB(fColor); 287 288 // we want this before we apply any alpha 289 fColor16 = SkPack888ToRGB16(r, g, b); 290 291 if (a != 255) { 292 r = SkMulDiv255Round(r, a); 293 g = SkMulDiv255Round(g, a); 294 b = SkMulDiv255Round(b, a); 295 } 296 fPMColor = SkPackARGB32(a, r, g, b); 297 298 fFlags = kConstInY32_Flag; 299 if (255 == a) { 300 fFlags |= kOpaqueAlpha_Flag; 301 if (paint.isDither() == false) { 302 fFlags |= kHasSpan16_Flag; 303 } 304 } 305 306 return true; 307} 308 309void SkColorShader::shadeSpan(int x, int y, SkPMColor span[], int count) { 310 sk_memset32(span, fPMColor, count); 311} 312 313void SkColorShader::shadeSpan16(int x, int y, uint16_t span[], int count) { 314 sk_memset16(span, fColor16, count); 315} 316 317void SkColorShader::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) { 318 memset(alpha, SkGetPackedA32(fPMColor), count); 319} 320 321// if we had a asAColor method, that would be more efficient... 322SkShader::BitmapType SkColorShader::asABitmap(SkBitmap* bitmap, SkMatrix* matrix, 323 TileMode modes[]) const { 324 return kNone_BitmapType; 325} 326 327SkShader::GradientType SkColorShader::asAGradient(GradientInfo* info) const { 328 if (info) { 329 if (info->fColors && info->fColorCount >= 1) { 330 info->fColors[0] = fColor; 331 } 332 info->fColorCount = 1; 333 info->fTileMode = SkShader::kRepeat_TileMode; 334 } 335 return kColor_GradientType; 336} 337 338/////////////////////////////////////////////////////////////////////////////// 339 340#include "SkEmptyShader.h" 341 342uint32_t SkEmptyShader::getFlags() { return 0; } 343uint8_t SkEmptyShader::getSpan16Alpha() const { return 0; } 344 345bool SkEmptyShader::setContext(const SkBitmap&, const SkPaint&, 346 const SkMatrix&) { return false; } 347 348void SkEmptyShader::shadeSpan(int x, int y, SkPMColor span[], int count) { 349 SkDEBUGFAIL("should never get called, since setContext() returned false"); 350} 351 352void SkEmptyShader::shadeSpan16(int x, int y, uint16_t span[], int count) { 353 SkDEBUGFAIL("should never get called, since setContext() returned false"); 354} 355 356void SkEmptyShader::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) { 357 SkDEBUGFAIL("should never get called, since setContext() returned false"); 358} 359