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