SkShader.cpp revision 5119bdb952025a30f115b9c6a187173956e55097
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 "SkShader.h" 19#include "SkPaint.h" 20 21SkShader::SkShader() : fLocalMatrix(NULL) { 22 SkDEBUGCODE(fInSession = false;) 23} 24 25SkShader::SkShader(SkFlattenableReadBuffer& buffer) 26 : INHERITED(buffer), fLocalMatrix(NULL) { 27 if (buffer.readBool()) { 28 SkMatrix matrix; 29 buffer.read(&matrix, sizeof(matrix)); 30 setLocalMatrix(matrix); 31 } 32 SkDEBUGCODE(fInSession = false;) 33} 34 35SkShader::~SkShader() { 36 SkASSERT(!fInSession); 37 sk_free(fLocalMatrix); 38} 39 40void SkShader::beginSession() { 41 SkASSERT(!fInSession); 42 SkDEBUGCODE(fInSession = true;) 43} 44 45void SkShader::endSession() { 46 SkASSERT(fInSession); 47 SkDEBUGCODE(fInSession = false;) 48} 49 50void SkShader::flatten(SkFlattenableWriteBuffer& buffer) { 51 this->INHERITED::flatten(buffer); 52 buffer.writeBool(fLocalMatrix != NULL); 53 if (fLocalMatrix) { 54 buffer.writeMul4(fLocalMatrix, sizeof(SkMatrix)); 55 } 56} 57 58bool SkShader::getLocalMatrix(SkMatrix* localM) const { 59 if (fLocalMatrix) { 60 if (localM) { 61 *localM = *fLocalMatrix; 62 } 63 return true; 64 } else { 65 if (localM) { 66 localM->reset(); 67 } 68 return false; 69 } 70} 71 72void SkShader::setLocalMatrix(const SkMatrix& localM) { 73 if (localM.isIdentity()) { 74 this->resetLocalMatrix(); 75 } else { 76 if (fLocalMatrix == NULL) { 77 fLocalMatrix = (SkMatrix*)sk_malloc_throw(sizeof(SkMatrix)); 78 } 79 *fLocalMatrix = localM; 80 } 81} 82 83void SkShader::resetLocalMatrix() { 84 if (fLocalMatrix) { 85 sk_free(fLocalMatrix); 86 fLocalMatrix = NULL; 87 } 88} 89 90bool SkShader::setContext(const SkBitmap& device, 91 const SkPaint& paint, 92 const SkMatrix& matrix) { 93 const SkMatrix* m = &matrix; 94 SkMatrix total; 95 96 fDeviceConfig = SkToU8(device.getConfig()); 97 fPaintAlpha = paint.getAlpha(); 98 if (fLocalMatrix) { 99 total.setConcat(matrix, *fLocalMatrix); 100 m = &total; 101 } 102 if (m->invert(&fTotalInverse)) { 103 fTotalInverseClass = (uint8_t)ComputeMatrixClass(fTotalInverse); 104 return true; 105 } 106 return false; 107} 108 109#include "SkColorPriv.h" 110 111void SkShader::shadeSpan16(int x, int y, uint16_t span16[], int count) { 112 SkASSERT(span16); 113 SkASSERT(count > 0); 114 SkASSERT(this->canCallShadeSpan16()); 115 116 // basically, if we get here, the subclass screwed up 117 SkASSERT(!"kHasSpan16 flag is set, but shadeSpan16() not implemented"); 118} 119 120#define kTempColorQuadCount 6 // balance between speed (larger) and saving stack-space 121#define kTempColorCount (kTempColorQuadCount << 2) 122 123#ifdef SK_CPU_BENDIAN 124 #define SkU32BitShiftToByteOffset(shift) (3 - ((shift) >> 3)) 125#else 126 #define SkU32BitShiftToByteOffset(shift) ((shift) >> 3) 127#endif 128 129void SkShader::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) { 130 SkASSERT(count > 0); 131 132 SkPMColor colors[kTempColorCount]; 133 134 while ((count -= kTempColorCount) >= 0) { 135 this->shadeSpan(x, y, colors, kTempColorCount); 136 x += kTempColorCount; 137 138 const uint8_t* srcA = (const uint8_t*)colors + SkU32BitShiftToByteOffset(SK_A32_SHIFT); 139 int quads = kTempColorQuadCount; 140 do { 141 U8CPU a0 = srcA[0]; 142 U8CPU a1 = srcA[4]; 143 U8CPU a2 = srcA[8]; 144 U8CPU a3 = srcA[12]; 145 srcA += 4*4; 146 *alpha++ = SkToU8(a0); 147 *alpha++ = SkToU8(a1); 148 *alpha++ = SkToU8(a2); 149 *alpha++ = SkToU8(a3); 150 } while (--quads != 0); 151 } 152 SkASSERT(count < 0); 153 SkASSERT(count + kTempColorCount >= 0); 154 if (count += kTempColorCount) { 155 this->shadeSpan(x, y, colors, count); 156 157 const uint8_t* srcA = (const uint8_t*)colors + SkU32BitShiftToByteOffset(SK_A32_SHIFT); 158 do { 159 *alpha++ = *srcA; 160 srcA += 4; 161 } while (--count != 0); 162 } 163#if 0 164 do { 165 int n = count; 166 if (n > kTempColorCount) 167 n = kTempColorCount; 168 SkASSERT(n > 0); 169 170 this->shadeSpan(x, y, colors, n); 171 x += n; 172 count -= n; 173 174 const uint8_t* srcA = (const uint8_t*)colors + SkU32BitShiftToByteOffset(SK_A32_SHIFT); 175 do { 176 *alpha++ = *srcA; 177 srcA += 4; 178 } while (--n != 0); 179 } while (count > 0); 180#endif 181} 182 183SkShader::MatrixClass SkShader::ComputeMatrixClass(const SkMatrix& mat) { 184 MatrixClass mc = kLinear_MatrixClass; 185 186 if (mat.getType() & SkMatrix::kPerspective_Mask) { 187 if (mat.fixedStepInX(0, NULL, NULL)) { 188 mc = kFixedStepInX_MatrixClass; 189 } else { 190 mc = kPerspective_MatrixClass; 191 } 192 } 193 return mc; 194} 195 196////////////////////////////////////////////////////////////////////////////// 197 198bool SkShader::asABitmap(SkBitmap*, SkMatrix*, TileMode*) { 199 return false; 200} 201 202SkShader* SkShader::CreateBitmapShader(const SkBitmap& src, 203 TileMode tmx, TileMode tmy) { 204 return SkShader::CreateBitmapShader(src, tmx, tmy, NULL, 0); 205} 206 207////////////////////////////////////////////////////////////////////////////// 208 209#include "SkColorShader.h" 210#include "SkUtils.h" 211 212SkColorShader::SkColorShader(SkFlattenableReadBuffer& b) : INHERITED(b) { 213 fFlags = 0; // computed in setContext 214 fInheritColor = b.readU8(); 215 if (fInheritColor) { 216 return; 217 } 218 fColor = b.readU32(); 219} 220 221void SkColorShader::flatten(SkFlattenableWriteBuffer& buffer) { 222 this->INHERITED::flatten(buffer); 223 buffer.write8(fInheritColor); 224 if (fInheritColor) { 225 return; 226 } 227 buffer.write32(fColor); 228} 229 230uint8_t SkColorShader::getSpan16Alpha() const { 231 return SkGetPackedA32(fPMColor); 232} 233 234bool SkColorShader::setContext(const SkBitmap& device, const SkPaint& paint, 235 const SkMatrix& matrix) { 236 if (!this->INHERITED::setContext(device, paint, matrix)) { 237 return false; 238 } 239 240 SkColor c; 241 unsigned a; 242 243 if (fInheritColor) { 244 c = paint.getColor(); 245 a = SkColorGetA(c); 246 } else { 247 c = fColor; 248 a = SkAlphaMul(SkColorGetA(c), SkAlpha255To256(paint.getAlpha())); 249 } 250 251 unsigned r = SkColorGetR(c); 252 unsigned g = SkColorGetG(c); 253 unsigned b = SkColorGetB(c); 254 255 // we want this before we apply any alpha 256 fColor16 = SkPack888ToRGB16(r, g, b); 257 258 if (a != 255) { 259 a = SkAlpha255To256(a); 260 r = SkAlphaMul(r, a); 261 g = SkAlphaMul(g, a); 262 b = SkAlphaMul(b, a); 263 } 264 fPMColor = SkPackARGB32(a, r, g, b); 265 266 fFlags = kHasSpan16_Flag | kConstInY_Flag; 267 if (SkGetPackedA32(fPMColor) == 255) { 268 fFlags |= kOpaqueAlpha_Flag; 269 } 270 271 return true; 272} 273 274void SkColorShader::shadeSpan(int x, int y, SkPMColor span[], int count) { 275 sk_memset32(span, fPMColor, count); 276} 277 278void SkColorShader::shadeSpan16(int x, int y, uint16_t span[], int count) { 279 sk_memset16(span, fColor16, count); 280} 281 282void SkColorShader::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) { 283 memset(alpha, SkGetPackedA32(fPMColor), count); 284} 285 286