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