diff options
Diffstat (limited to 'src/core/SkShader.cpp')
-rw-r--r-- | src/core/SkShader.cpp | 284 |
1 files changed, 284 insertions, 0 deletions
diff --git a/src/core/SkShader.cpp b/src/core/SkShader.cpp new file mode 100644 index 0000000..dd9c859 --- /dev/null +++ b/src/core/SkShader.cpp @@ -0,0 +1,284 @@ +/* libs/graphics/sgl/SkShader.cpp +** +** Copyright 2006, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +#include "SkShader.h" +#include "SkPaint.h" + +SkShader::SkShader() : fLocalMatrix(NULL) { + SkDEBUGCODE(fInSession = false;) +} + +SkShader::SkShader(SkFlattenableReadBuffer& buffer) + : INHERITED(buffer), fLocalMatrix(NULL) { + if (buffer.readBool()) { + SkMatrix matrix; + buffer.read(&matrix, sizeof(matrix)); + setLocalMatrix(matrix); + } + SkDEBUGCODE(fInSession = false;) +} + +SkShader::~SkShader() { + SkASSERT(!fInSession); + sk_free(fLocalMatrix); +} + +void SkShader::beginSession() { + SkASSERT(!fInSession); + SkDEBUGCODE(fInSession = true;) +} + +void SkShader::endSession() { + SkASSERT(fInSession); + SkDEBUGCODE(fInSession = false;) +} + +void SkShader::flatten(SkFlattenableWriteBuffer& buffer) { + this->INHERITED::flatten(buffer); + buffer.writeBool(fLocalMatrix != NULL); + if (fLocalMatrix) { + buffer.writeMul4(fLocalMatrix, sizeof(SkMatrix)); + } +} + +bool SkShader::getLocalMatrix(SkMatrix* localM) const { + if (fLocalMatrix) { + if (localM) { + *localM = *fLocalMatrix; + } + return true; + } else { + if (localM) { + localM->reset(); + } + return false; + } +} + +void SkShader::setLocalMatrix(const SkMatrix& localM) { + if (localM.isIdentity()) { + this->resetLocalMatrix(); + } else { + if (fLocalMatrix == NULL) { + fLocalMatrix = (SkMatrix*)sk_malloc_throw(sizeof(SkMatrix)); + } + *fLocalMatrix = localM; + } +} + +void SkShader::resetLocalMatrix() { + if (fLocalMatrix) { + sk_free(fLocalMatrix); + fLocalMatrix = NULL; + } +} + +bool SkShader::setContext(const SkBitmap& device, + const SkPaint& paint, + const SkMatrix& matrix) { + const SkMatrix* m = &matrix; + SkMatrix total; + + fDeviceConfig = SkToU8(device.getConfig()); + fPaintAlpha = paint.getAlpha(); + if (fLocalMatrix) { + total.setConcat(matrix, *fLocalMatrix); + m = &total; + } + if (m->invert(&fTotalInverse)) { + fTotalInverseClass = (uint8_t)ComputeMatrixClass(fTotalInverse); + return true; + } + return false; +} + +#include "SkColorPriv.h" + +void SkShader::shadeSpan16(int x, int y, uint16_t span16[], int count) { + SkASSERT(span16); + SkASSERT(count > 0); + SkASSERT(this->canCallShadeSpan16()); + + // basically, if we get here, the subclass screwed up + SkASSERT(!"kHasSpan16 flag is set, but shadeSpan16() not implemented"); +} + +#define kTempColorQuadCount 6 // balance between speed (larger) and saving stack-space +#define kTempColorCount (kTempColorQuadCount << 2) + +#ifdef SK_CPU_BENDIAN + #define SkU32BitShiftToByteOffset(shift) (3 - ((shift) >> 3)) +#else + #define SkU32BitShiftToByteOffset(shift) ((shift) >> 3) +#endif + +void SkShader::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) { + SkASSERT(count > 0); + + SkPMColor colors[kTempColorCount]; + + while ((count -= kTempColorCount) >= 0) { + this->shadeSpan(x, y, colors, kTempColorCount); + x += kTempColorCount; + + const uint8_t* srcA = (const uint8_t*)colors + SkU32BitShiftToByteOffset(SK_A32_SHIFT); + int quads = kTempColorQuadCount; + do { + U8CPU a0 = srcA[0]; + U8CPU a1 = srcA[4]; + U8CPU a2 = srcA[8]; + U8CPU a3 = srcA[12]; + srcA += 4*4; + *alpha++ = SkToU8(a0); + *alpha++ = SkToU8(a1); + *alpha++ = SkToU8(a2); + *alpha++ = SkToU8(a3); + } while (--quads != 0); + } + SkASSERT(count < 0); + SkASSERT(count + kTempColorCount >= 0); + if (count += kTempColorCount) { + this->shadeSpan(x, y, colors, count); + + const uint8_t* srcA = (const uint8_t*)colors + SkU32BitShiftToByteOffset(SK_A32_SHIFT); + do { + *alpha++ = *srcA; + srcA += 4; + } while (--count != 0); + } +#if 0 + do { + int n = count; + if (n > kTempColorCount) + n = kTempColorCount; + SkASSERT(n > 0); + + this->shadeSpan(x, y, colors, n); + x += n; + count -= n; + + const uint8_t* srcA = (const uint8_t*)colors + SkU32BitShiftToByteOffset(SK_A32_SHIFT); + do { + *alpha++ = *srcA; + srcA += 4; + } while (--n != 0); + } while (count > 0); +#endif +} + +SkShader::MatrixClass SkShader::ComputeMatrixClass(const SkMatrix& mat) { + MatrixClass mc = kLinear_MatrixClass; + + if (mat.getType() & SkMatrix::kPerspective_Mask) { + if (mat.fixedStepInX(0, NULL, NULL)) { + mc = kFixedStepInX_MatrixClass; + } else { + mc = kPerspective_MatrixClass; + } + } + return mc; +} + +////////////////////////////////////////////////////////////////////////////// + +bool SkShader::asABitmap(SkBitmap*, SkMatrix*, TileMode*) { + return false; +} + +SkShader* SkShader::CreateBitmapShader(const SkBitmap& src, + TileMode tmx, TileMode tmy) { + return SkShader::CreateBitmapShader(src, tmx, tmy, NULL, 0); +} + +////////////////////////////////////////////////////////////////////////////// + +#include "SkColorShader.h" +#include "SkUtils.h" + +SkColorShader::SkColorShader(SkFlattenableReadBuffer& b) : INHERITED(b) { + fInheritColor = b.readU8(); + if (fInheritColor) { + return; + } + fColor = b.readU32(); +} + +void SkColorShader::flatten(SkFlattenableWriteBuffer& buffer) { + this->INHERITED::flatten(buffer); + buffer.write8(fInheritColor); + if (fInheritColor) { + return; + } + buffer.write32(fColor); +} + +uint32_t SkColorShader::getFlags() { + return (SkGetPackedA32(fPMColor) == 255 ? kOpaqueAlpha_Flag : 0) | + kHasSpan16_Flag; +} + +uint8_t SkColorShader::getSpan16Alpha() const { + return SkGetPackedA32(fPMColor); +} + +bool SkColorShader::setContext(const SkBitmap& device, const SkPaint& paint, + const SkMatrix& matrix) { + if (!this->INHERITED::setContext(device, paint, matrix)) { + return false; + } + + SkColor c; + unsigned a; + + if (fInheritColor) { + c = paint.getColor(); + a = SkColorGetA(c); + } else { + c = fColor; + a = SkAlphaMul(SkColorGetA(c), SkAlpha255To256(paint.getAlpha())); + } + + unsigned r = SkColorGetR(c); + unsigned g = SkColorGetG(c); + unsigned b = SkColorGetB(c); + + // we want this before we apply any alpha + fColor16 = SkPack888ToRGB16(r, g, b); + + if (a != 255) { + a = SkAlpha255To256(a); + r = SkAlphaMul(r, a); + g = SkAlphaMul(g, a); + b = SkAlphaMul(b, a); + } + fPMColor = SkPackARGB32(a, r, g, b); + + return true; +} + +void SkColorShader::shadeSpan(int x, int y, SkPMColor span[], int count) { + sk_memset32(span, fPMColor, count); +} + +void SkColorShader::shadeSpan16(int x, int y, uint16_t span[], int count) { + sk_memset16(span, fColor16, count); +} + +void SkColorShader::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) { + memset(alpha, SkGetPackedA32(fPMColor), count); +} + |