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