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