michael@0: /* michael@0: * Copyright 2006 The Android Open Source Project michael@0: * michael@0: * Use of this source code is governed by a BSD-style license that can be michael@0: * found in the LICENSE file. michael@0: */ michael@0: michael@0: #include "SkBitmapProcShader.h" michael@0: #include "SkReadBuffer.h" michael@0: #include "SkMallocPixelRef.h" michael@0: #include "SkPaint.h" michael@0: #include "SkScalar.h" michael@0: #include "SkShader.h" michael@0: #include "SkWriteBuffer.h" michael@0: michael@0: SkShader::SkShader() { michael@0: fLocalMatrix.reset(); michael@0: SkDEBUGCODE(fInSetContext = false;) michael@0: } michael@0: michael@0: SkShader::SkShader(SkReadBuffer& buffer) michael@0: : INHERITED(buffer) { michael@0: if (buffer.readBool()) { michael@0: buffer.readMatrix(&fLocalMatrix); michael@0: } else { michael@0: fLocalMatrix.reset(); michael@0: } michael@0: michael@0: SkDEBUGCODE(fInSetContext = false;) michael@0: } michael@0: michael@0: SkShader::~SkShader() { michael@0: SkASSERT(!fInSetContext); michael@0: } michael@0: michael@0: void SkShader::flatten(SkWriteBuffer& buffer) const { michael@0: this->INHERITED::flatten(buffer); michael@0: bool hasLocalM = this->hasLocalMatrix(); michael@0: buffer.writeBool(hasLocalM); michael@0: if (hasLocalM) { michael@0: buffer.writeMatrix(fLocalMatrix); michael@0: } michael@0: } michael@0: michael@0: bool SkShader::setContext(const SkBitmap& device, michael@0: const SkPaint& paint, michael@0: const SkMatrix& matrix) { michael@0: SkASSERT(!this->setContextHasBeenCalled()); michael@0: michael@0: const SkMatrix* m = &matrix; michael@0: SkMatrix total; michael@0: michael@0: fPaintAlpha = paint.getAlpha(); michael@0: if (this->hasLocalMatrix()) { michael@0: total.setConcat(matrix, this->getLocalMatrix()); michael@0: m = &total; michael@0: } michael@0: if (m->invert(&fTotalInverse)) { michael@0: fTotalInverseClass = (uint8_t)ComputeMatrixClass(fTotalInverse); michael@0: SkDEBUGCODE(fInSetContext = true;) michael@0: return true; michael@0: } michael@0: return false; michael@0: } michael@0: michael@0: void SkShader::endContext() { michael@0: SkASSERT(fInSetContext); michael@0: SkDEBUGCODE(fInSetContext = false;) michael@0: } michael@0: michael@0: SkShader::ShadeProc SkShader::asAShadeProc(void** ctx) { michael@0: return NULL; michael@0: } michael@0: michael@0: #include "SkColorPriv.h" michael@0: michael@0: void SkShader::shadeSpan16(int x, int y, uint16_t span16[], int count) { michael@0: SkASSERT(span16); michael@0: SkASSERT(count > 0); michael@0: SkASSERT(this->canCallShadeSpan16()); michael@0: michael@0: // basically, if we get here, the subclass screwed up michael@0: SkDEBUGFAIL("kHasSpan16 flag is set, but shadeSpan16() not implemented"); michael@0: } michael@0: michael@0: #define kTempColorQuadCount 6 // balance between speed (larger) and saving stack-space michael@0: #define kTempColorCount (kTempColorQuadCount << 2) michael@0: michael@0: #ifdef SK_CPU_BENDIAN michael@0: #define SkU32BitShiftToByteOffset(shift) (3 - ((shift) >> 3)) michael@0: #else michael@0: #define SkU32BitShiftToByteOffset(shift) ((shift) >> 3) michael@0: #endif michael@0: michael@0: void SkShader::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) { michael@0: SkASSERT(count > 0); michael@0: michael@0: SkPMColor colors[kTempColorCount]; michael@0: michael@0: while ((count -= kTempColorCount) >= 0) { michael@0: this->shadeSpan(x, y, colors, kTempColorCount); michael@0: x += kTempColorCount; michael@0: michael@0: const uint8_t* srcA = (const uint8_t*)colors + SkU32BitShiftToByteOffset(SK_A32_SHIFT); michael@0: int quads = kTempColorQuadCount; michael@0: do { michael@0: U8CPU a0 = srcA[0]; michael@0: U8CPU a1 = srcA[4]; michael@0: U8CPU a2 = srcA[8]; michael@0: U8CPU a3 = srcA[12]; michael@0: srcA += 4*4; michael@0: *alpha++ = SkToU8(a0); michael@0: *alpha++ = SkToU8(a1); michael@0: *alpha++ = SkToU8(a2); michael@0: *alpha++ = SkToU8(a3); michael@0: } while (--quads != 0); michael@0: } michael@0: SkASSERT(count < 0); michael@0: SkASSERT(count + kTempColorCount >= 0); michael@0: if (count += kTempColorCount) { michael@0: this->shadeSpan(x, y, colors, count); michael@0: michael@0: const uint8_t* srcA = (const uint8_t*)colors + SkU32BitShiftToByteOffset(SK_A32_SHIFT); michael@0: do { michael@0: *alpha++ = *srcA; michael@0: srcA += 4; michael@0: } while (--count != 0); michael@0: } michael@0: #if 0 michael@0: do { michael@0: int n = count; michael@0: if (n > kTempColorCount) michael@0: n = kTempColorCount; michael@0: SkASSERT(n > 0); michael@0: michael@0: this->shadeSpan(x, y, colors, n); michael@0: x += n; michael@0: count -= n; michael@0: michael@0: const uint8_t* srcA = (const uint8_t*)colors + SkU32BitShiftToByteOffset(SK_A32_SHIFT); michael@0: do { michael@0: *alpha++ = *srcA; michael@0: srcA += 4; michael@0: } while (--n != 0); michael@0: } while (count > 0); michael@0: #endif michael@0: } michael@0: michael@0: SkShader::MatrixClass SkShader::ComputeMatrixClass(const SkMatrix& mat) { michael@0: MatrixClass mc = kLinear_MatrixClass; michael@0: michael@0: if (mat.hasPerspective()) { michael@0: if (mat.fixedStepInX(0, NULL, NULL)) { michael@0: mc = kFixedStepInX_MatrixClass; michael@0: } else { michael@0: mc = kPerspective_MatrixClass; michael@0: } michael@0: } michael@0: return mc; michael@0: } michael@0: michael@0: ////////////////////////////////////////////////////////////////////////////// michael@0: michael@0: SkShader::BitmapType SkShader::asABitmap(SkBitmap*, SkMatrix*, michael@0: TileMode*) const { michael@0: return kNone_BitmapType; michael@0: } michael@0: michael@0: SkShader::GradientType SkShader::asAGradient(GradientInfo* info) const { michael@0: return kNone_GradientType; michael@0: } michael@0: michael@0: GrEffectRef* SkShader::asNewEffect(GrContext*, const SkPaint&) const { michael@0: return NULL; michael@0: } michael@0: michael@0: SkShader* SkShader::CreateBitmapShader(const SkBitmap& src, michael@0: TileMode tmx, TileMode tmy) { michael@0: return ::CreateBitmapShader(src, tmx, tmy, NULL); michael@0: } michael@0: michael@0: #ifndef SK_IGNORE_TO_STRING michael@0: void SkShader::toString(SkString* str) const { michael@0: if (this->hasLocalMatrix()) { michael@0: str->append(" "); michael@0: this->getLocalMatrix().toString(str); michael@0: } michael@0: } michael@0: #endif michael@0: michael@0: ////////////////////////////////////////////////////////////////////////////// michael@0: michael@0: #include "SkColorShader.h" michael@0: #include "SkUtils.h" michael@0: michael@0: SkColorShader::SkColorShader() { michael@0: fFlags = 0; michael@0: fInheritColor = true; michael@0: } michael@0: michael@0: SkColorShader::SkColorShader(SkColor c) { michael@0: fFlags = 0; michael@0: fColor = c; michael@0: fInheritColor = false; michael@0: } michael@0: michael@0: SkColorShader::~SkColorShader() {} michael@0: michael@0: bool SkColorShader::isOpaque() const { michael@0: if (fInheritColor) { michael@0: return true; // using paint's alpha michael@0: } michael@0: return SkColorGetA(fColor) == 255; michael@0: } michael@0: michael@0: SkColorShader::SkColorShader(SkReadBuffer& b) : INHERITED(b) { michael@0: fFlags = 0; // computed in setContext michael@0: michael@0: fInheritColor = b.readBool(); michael@0: if (fInheritColor) { michael@0: return; michael@0: } michael@0: fColor = b.readColor(); michael@0: } michael@0: michael@0: void SkColorShader::flatten(SkWriteBuffer& buffer) const { michael@0: this->INHERITED::flatten(buffer); michael@0: buffer.writeBool(fInheritColor); michael@0: if (fInheritColor) { michael@0: return; michael@0: } michael@0: buffer.writeColor(fColor); michael@0: } michael@0: michael@0: uint32_t SkColorShader::getFlags() { michael@0: return fFlags; michael@0: } michael@0: michael@0: uint8_t SkColorShader::getSpan16Alpha() const { michael@0: return SkGetPackedA32(fPMColor); michael@0: } michael@0: michael@0: bool SkColorShader::setContext(const SkBitmap& device, const SkPaint& paint, michael@0: const SkMatrix& matrix) { michael@0: if (!this->INHERITED::setContext(device, paint, matrix)) { michael@0: return false; michael@0: } michael@0: michael@0: unsigned a; michael@0: michael@0: if (fInheritColor) { michael@0: fColor = paint.getColor(); michael@0: a = SkColorGetA(fColor); michael@0: } else { michael@0: a = SkAlphaMul(SkColorGetA(fColor), SkAlpha255To256(paint.getAlpha())); michael@0: } michael@0: michael@0: unsigned r = SkColorGetR(fColor); michael@0: unsigned g = SkColorGetG(fColor); michael@0: unsigned b = SkColorGetB(fColor); michael@0: michael@0: // we want this before we apply any alpha michael@0: fColor16 = SkPack888ToRGB16(r, g, b); michael@0: michael@0: if (a != 255) { michael@0: r = SkMulDiv255Round(r, a); michael@0: g = SkMulDiv255Round(g, a); michael@0: b = SkMulDiv255Round(b, a); michael@0: } michael@0: fPMColor = SkPackARGB32(a, r, g, b); michael@0: michael@0: fFlags = kConstInY32_Flag; michael@0: if (255 == a) { michael@0: fFlags |= kOpaqueAlpha_Flag; michael@0: if (paint.isDither() == false) { michael@0: fFlags |= kHasSpan16_Flag; michael@0: } michael@0: } michael@0: michael@0: return true; michael@0: } michael@0: michael@0: void SkColorShader::shadeSpan(int x, int y, SkPMColor span[], int count) { michael@0: sk_memset32(span, fPMColor, count); michael@0: } michael@0: michael@0: void SkColorShader::shadeSpan16(int x, int y, uint16_t span[], int count) { michael@0: sk_memset16(span, fColor16, count); michael@0: } michael@0: michael@0: void SkColorShader::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) { michael@0: memset(alpha, SkGetPackedA32(fPMColor), count); michael@0: } michael@0: michael@0: // if we had a asAColor method, that would be more efficient... michael@0: SkShader::BitmapType SkColorShader::asABitmap(SkBitmap* bitmap, SkMatrix* matrix, michael@0: TileMode modes[]) const { michael@0: return kNone_BitmapType; michael@0: } michael@0: michael@0: SkShader::GradientType SkColorShader::asAGradient(GradientInfo* info) const { michael@0: if (info) { michael@0: if (info->fColors && info->fColorCount >= 1) { michael@0: info->fColors[0] = fColor; michael@0: } michael@0: info->fColorCount = 1; michael@0: info->fTileMode = SkShader::kRepeat_TileMode; michael@0: } michael@0: return kColor_GradientType; michael@0: } michael@0: michael@0: #ifndef SK_IGNORE_TO_STRING michael@0: void SkColorShader::toString(SkString* str) const { michael@0: str->append("SkColorShader: ("); michael@0: michael@0: if (fInheritColor) { michael@0: str->append("Color: inherited from paint"); michael@0: } else { michael@0: str->append("Color: "); michael@0: str->appendHex(fColor); michael@0: } michael@0: michael@0: this->INHERITED::toString(str); michael@0: michael@0: str->append(")"); michael@0: } michael@0: #endif michael@0: michael@0: /////////////////////////////////////////////////////////////////////////////// michael@0: michael@0: #include "SkEmptyShader.h" michael@0: michael@0: uint32_t SkEmptyShader::getFlags() { return 0; } michael@0: uint8_t SkEmptyShader::getSpan16Alpha() const { return 0; } michael@0: michael@0: bool SkEmptyShader::setContext(const SkBitmap&, const SkPaint&, michael@0: const SkMatrix&) { return false; } michael@0: michael@0: void SkEmptyShader::shadeSpan(int x, int y, SkPMColor span[], int count) { michael@0: SkDEBUGFAIL("should never get called, since setContext() returned false"); michael@0: } michael@0: michael@0: void SkEmptyShader::shadeSpan16(int x, int y, uint16_t span[], int count) { michael@0: SkDEBUGFAIL("should never get called, since setContext() returned false"); michael@0: } michael@0: michael@0: void SkEmptyShader::shadeSpanAlpha(int x, int y, uint8_t alpha[], int count) { michael@0: SkDEBUGFAIL("should never get called, since setContext() returned false"); michael@0: } michael@0: michael@0: #ifndef SK_IGNORE_TO_STRING michael@0: void SkEmptyShader::toString(SkString* str) const { michael@0: str->append("SkEmptyShader: ("); michael@0: michael@0: this->INHERITED::toString(str); michael@0: michael@0: str->append(")"); michael@0: } michael@0: #endif