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