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