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 #include "SkBitmapProcShader.h" 9 #include "SkEmptyShader.h" 10 #include "SkReadBuffer.h" 11 #include "SkMallocPixelRef.h" 12 #include "SkPaint.h" 13 #include "SkPicture.h" 14 #include "SkPictureShader.h" 15 #include "SkScalar.h" 16 #include "SkShader.h" 17 #include "SkThread.h" 18 #include "SkWriteBuffer.h" 19 20 //#define SK_TRACK_SHADER_LIFETIME 21 22 #ifdef SK_TRACK_SHADER_LIFETIME 23 static int32_t gShaderCounter; 24 #endif 25 26 static inline void inc_shader_counter() { 27 #ifdef SK_TRACK_SHADER_LIFETIME 28 int32_t prev = sk_atomic_inc(&gShaderCounter); 29 SkDebugf("+++ shader counter %d\n", prev + 1); 30 #endif 31 } 32 static inline void dec_shader_counter() { 33 #ifdef SK_TRACK_SHADER_LIFETIME 34 int32_t prev = sk_atomic_dec(&gShaderCounter); 35 SkDebugf("--- shader counter %d\n", prev - 1); 36 #endif 37 } 38 39 SkShader::SkShader(const SkMatrix* localMatrix) { 40 inc_shader_counter(); 41 if (localMatrix) { 42 fLocalMatrix = *localMatrix; 43 } else { 44 fLocalMatrix.reset(); 45 } 46 } 47 48 SkShader::SkShader(SkReadBuffer& buffer) : INHERITED(buffer) { 49 inc_shader_counter(); 50 if (buffer.readBool()) { 51 buffer.readMatrix(&fLocalMatrix); 52 } else { 53 fLocalMatrix.reset(); 54 } 55 } 56 57 SkShader::~SkShader() { 58 dec_shader_counter(); 59 } 60 61 void SkShader::flatten(SkWriteBuffer& buffer) const { 62 this->INHERITED::flatten(buffer); 63 bool hasLocalM = !fLocalMatrix.isIdentity(); 64 buffer.writeBool(hasLocalM); 65 if (hasLocalM) { 66 buffer.writeMatrix(fLocalMatrix); 67 } 68 } 69 70 bool SkShader::computeTotalInverse(const ContextRec& rec, SkMatrix* totalInverse) const { 71 SkMatrix total; 72 total.setConcat(*rec.fMatrix, fLocalMatrix); 73 74 const SkMatrix* m = &total; 75 if (rec.fLocalMatrix) { 76 total.setConcat(*m, *rec.fLocalMatrix); 77 m = &total; 78 } 79 return m->invert(totalInverse); 80 } 81 82 SkShader::Context* SkShader::createContext(const ContextRec& rec, void* storage) const { 83 if (!this->computeTotalInverse(rec, NULL)) { 84 return NULL; 85 } 86 return this->onCreateContext(rec, storage); 87 } 88 89 SkShader::Context* SkShader::onCreateContext(const ContextRec& rec, void*) const { 90 return NULL; 91 } 92 93 size_t SkShader::contextSize() const { 94 return 0; 95 } 96 97 SkShader::Context::Context(const SkShader& shader, const ContextRec& rec) 98 : fShader(shader), fCTM(*rec.fMatrix) 99 { 100 // Because the context parameters must be valid at this point, we know that the matrix is 101 // invertible. 102 SkAssertResult(fShader.computeTotalInverse(rec, &fTotalInverse)); 103 fTotalInverseClass = (uint8_t)ComputeMatrixClass(fTotalInverse); 104 105 fPaintAlpha = rec.fPaint->getAlpha(); 106 } 107 108 SkShader::Context::~Context() {} 109 110 SkShader::Context::ShadeProc SkShader::Context::asAShadeProc(void** ctx) { 111 return NULL; 112 } 113 114 #include "SkColorPriv.h" 115 116 void SkShader::Context::shadeSpan16(int x, int y, uint16_t span16[], int count) { 117 SkASSERT(span16); 118 SkASSERT(count > 0); 119 SkASSERT(this->canCallShadeSpan16()); 120 121 // basically, if we get here, the subclass screwed up 122 SkDEBUGFAIL("kHasSpan16 flag is set, but shadeSpan16() not implemented"); 123 } 124 125 #define kTempColorQuadCount 6 // balance between speed (larger) and saving stack-space 126 #define kTempColorCount (kTempColorQuadCount << 2) 127 128 #ifdef SK_CPU_BENDIAN 129 #define SkU32BitShiftToByteOffset(shift) (3 - ((shift) >> 3)) 130 #else 131 #define SkU32BitShiftToByteOffset(shift) ((shift) >> 3) 132 #endif 133 134 void SkShader::Context::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) { 135 SkASSERT(count > 0); 136 137 SkPMColor colors[kTempColorCount]; 138 139 while ((count -= kTempColorCount) >= 0) { 140 this->shadeSpan(x, y, colors, kTempColorCount); 141 x += kTempColorCount; 142 143 const uint8_t* srcA = (const uint8_t*)colors + SkU32BitShiftToByteOffset(SK_A32_SHIFT); 144 int quads = kTempColorQuadCount; 145 do { 146 U8CPU a0 = srcA[0]; 147 U8CPU a1 = srcA[4]; 148 U8CPU a2 = srcA[8]; 149 U8CPU a3 = srcA[12]; 150 srcA += 4*4; 151 *alpha++ = SkToU8(a0); 152 *alpha++ = SkToU8(a1); 153 *alpha++ = SkToU8(a2); 154 *alpha++ = SkToU8(a3); 155 } while (--quads != 0); 156 } 157 SkASSERT(count < 0); 158 SkASSERT(count + kTempColorCount >= 0); 159 if (count += kTempColorCount) { 160 this->shadeSpan(x, y, colors, count); 161 162 const uint8_t* srcA = (const uint8_t*)colors + SkU32BitShiftToByteOffset(SK_A32_SHIFT); 163 do { 164 *alpha++ = *srcA; 165 srcA += 4; 166 } while (--count != 0); 167 } 168 #if 0 169 do { 170 int n = count; 171 if (n > kTempColorCount) 172 n = kTempColorCount; 173 SkASSERT(n > 0); 174 175 this->shadeSpan(x, y, colors, n); 176 x += n; 177 count -= n; 178 179 const uint8_t* srcA = (const uint8_t*)colors + SkU32BitShiftToByteOffset(SK_A32_SHIFT); 180 do { 181 *alpha++ = *srcA; 182 srcA += 4; 183 } while (--n != 0); 184 } while (count > 0); 185 #endif 186 } 187 188 SkShader::Context::MatrixClass SkShader::Context::ComputeMatrixClass(const SkMatrix& mat) { 189 MatrixClass mc = kLinear_MatrixClass; 190 191 if (mat.hasPerspective()) { 192 if (mat.fixedStepInX(0, NULL, NULL)) { 193 mc = kFixedStepInX_MatrixClass; 194 } else { 195 mc = kPerspective_MatrixClass; 196 } 197 } 198 return mc; 199 } 200 201 ////////////////////////////////////////////////////////////////////////////// 202 203 SkShader::BitmapType SkShader::asABitmap(SkBitmap*, SkMatrix*, TileMode*) const { 204 return kNone_BitmapType; 205 } 206 207 SkShader::GradientType SkShader::asAGradient(GradientInfo* info) const { 208 return kNone_GradientType; 209 } 210 211 bool SkShader::asNewEffect(GrContext* context, const SkPaint& paint, 212 const SkMatrix* localMatrixOrNull, GrColor* grColor, 213 GrEffectRef** grEffect) const { 214 return false; 215 } 216 217 SkShader* SkShader::refAsALocalMatrixShader(SkMatrix*) const { 218 return NULL; 219 } 220 221 SkShader* SkShader::CreateEmptyShader() { 222 return SkNEW(SkEmptyShader); 223 } 224 225 SkShader* SkShader::CreateBitmapShader(const SkBitmap& src, TileMode tmx, TileMode tmy, 226 const SkMatrix* localMatrix) { 227 return ::CreateBitmapShader(src, tmx, tmy, localMatrix, NULL); 228 } 229 230 SkShader* SkShader::CreatePictureShader(SkPicture* src, TileMode tmx, TileMode tmy, 231 const SkMatrix* localMatrix) { 232 return SkPictureShader::Create(src, tmx, tmy, localMatrix); 233 } 234 235 #ifndef SK_IGNORE_TO_STRING 236 void SkShader::toString(SkString* str) const { 237 if (!fLocalMatrix.isIdentity()) { 238 str->append(" "); 239 fLocalMatrix.toString(str); 240 } 241 } 242 #endif 243 244 ////////////////////////////////////////////////////////////////////////////// 245 246 #include "SkColorShader.h" 247 #include "SkUtils.h" 248 249 SkColorShader::SkColorShader(SkColor c) 250 : fColor(c) { 251 } 252 253 bool SkColorShader::isOpaque() const { 254 return SkColorGetA(fColor) == 255; 255 } 256 257 SkColorShader::SkColorShader(SkReadBuffer& b) : INHERITED(b) { 258 // V25_COMPATIBILITY_CODE We had a boolean to make the color shader inherit the paint's 259 // color. We don't support that any more. 260 if (b.isVersionLT(SkReadBuffer::kColorShaderNoBool_Version)) { 261 if (b.readBool()) { 262 SkDEBUGFAIL("We shouldn't have pictures that recorded the inherited case."); 263 fColor = SK_ColorWHITE; 264 return; 265 } 266 } 267 fColor = b.readColor(); 268 } 269 270 void SkColorShader::flatten(SkWriteBuffer& buffer) const { 271 this->INHERITED::flatten(buffer); 272 buffer.writeColor(fColor); 273 } 274 275 uint32_t SkColorShader::ColorShaderContext::getFlags() const { 276 return fFlags; 277 } 278 279 uint8_t SkColorShader::ColorShaderContext::getSpan16Alpha() const { 280 return SkGetPackedA32(fPMColor); 281 } 282 283 SkShader::Context* SkColorShader::onCreateContext(const ContextRec& rec, void* storage) const { 284 return SkNEW_PLACEMENT_ARGS(storage, ColorShaderContext, (*this, rec)); 285 } 286 287 SkColorShader::ColorShaderContext::ColorShaderContext(const SkColorShader& shader, 288 const ContextRec& rec) 289 : INHERITED(shader, rec) 290 { 291 SkColor color = shader.fColor; 292 unsigned a = SkAlphaMul(SkColorGetA(color), SkAlpha255To256(rec.fPaint->getAlpha())); 293 294 unsigned r = SkColorGetR(color); 295 unsigned g = SkColorGetG(color); 296 unsigned b = SkColorGetB(color); 297 298 // we want this before we apply any alpha 299 fColor16 = SkPack888ToRGB16(r, g, b); 300 301 if (a != 255) { 302 r = SkMulDiv255Round(r, a); 303 g = SkMulDiv255Round(g, a); 304 b = SkMulDiv255Round(b, a); 305 } 306 fPMColor = SkPackARGB32(a, r, g, b); 307 308 fFlags = kConstInY32_Flag; 309 if (255 == a) { 310 fFlags |= kOpaqueAlpha_Flag; 311 if (rec.fPaint->isDither() == false) { 312 fFlags |= kHasSpan16_Flag; 313 } 314 } 315 } 316 317 void SkColorShader::ColorShaderContext::shadeSpan(int x, int y, SkPMColor span[], int count) { 318 sk_memset32(span, fPMColor, count); 319 } 320 321 void SkColorShader::ColorShaderContext::shadeSpan16(int x, int y, uint16_t span[], int count) { 322 sk_memset16(span, fColor16, count); 323 } 324 325 void SkColorShader::ColorShaderContext::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) { 326 memset(alpha, SkGetPackedA32(fPMColor), count); 327 } 328 329 // if we had a asAColor method, that would be more efficient... 330 SkShader::BitmapType SkColorShader::asABitmap(SkBitmap* bitmap, SkMatrix* matrix, 331 TileMode modes[]) const { 332 return kNone_BitmapType; 333 } 334 335 SkShader::GradientType SkColorShader::asAGradient(GradientInfo* info) const { 336 if (info) { 337 if (info->fColors && info->fColorCount >= 1) { 338 info->fColors[0] = fColor; 339 } 340 info->fColorCount = 1; 341 info->fTileMode = SkShader::kRepeat_TileMode; 342 } 343 return kColor_GradientType; 344 } 345 346 #if SK_SUPPORT_GPU 347 348 #include "SkGr.h" 349 350 bool SkColorShader::asNewEffect(GrContext* context, const SkPaint& paint, 351 const SkMatrix* localMatrix, GrColor* grColor, 352 GrEffectRef** grEffect) const { 353 *grEffect = NULL; 354 SkColor skColor = fColor; 355 U8CPU newA = SkMulDiv255Round(SkColorGetA(fColor), paint.getAlpha()); 356 *grColor = SkColor2GrColor(SkColorSetA(skColor, newA)); 357 return true; 358 } 359 360 #else 361 362 bool SkColorShader::asNewEffect(GrContext* context, const SkPaint& paint, 363 const SkMatrix* localMatrix, GrColor* grColor, 364 GrEffectRef** grEffect) const { 365 SkDEBUGFAIL("Should not call in GPU-less build"); 366 return false; 367 } 368 369 #endif 370 371 #ifndef SK_IGNORE_TO_STRING 372 void SkColorShader::toString(SkString* str) const { 373 str->append("SkColorShader: ("); 374 375 str->append("Color: "); 376 str->appendHex(fColor); 377 378 this->INHERITED::toString(str); 379 380 str->append(")"); 381 } 382 #endif 383 384 /////////////////////////////////////////////////////////////////////////////// 385 386 #ifndef SK_IGNORE_TO_STRING 387 #include "SkEmptyShader.h" 388 389 void SkEmptyShader::toString(SkString* str) const { 390 str->append("SkEmptyShader: ("); 391 392 this->INHERITED::toString(str); 393 394 str->append(")"); 395 } 396 #endif 397