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