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