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