michael@0: 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: michael@0: michael@0: #ifndef NOFILTER_BITMAP_SHADER_PREAMBLE michael@0: #define NOFILTER_BITMAP_SHADER_PREAMBLE(bitmap, rb) michael@0: #endif michael@0: #ifndef NOFILTER_BITMAP_SHADER_POSTAMBLE michael@0: #define NOFILTER_BITMAP_SHADER_POSTAMBLE(bitmap) michael@0: #endif michael@0: #ifndef NOFILTER_BITMAP_SHADER_PREAMBLE16 michael@0: #define NOFILTER_BITMAP_SHADER_PREAMBLE16(bitmap, rb) michael@0: #endif michael@0: #ifndef NOFILTER_BITMAP_SHADER_POSTAMBLE16 michael@0: #define NOFILTER_BITMAP_SHADER_POSTAMBLE16(bitmap) michael@0: #endif michael@0: michael@0: class NOFILTER_BITMAP_SHADER_CLASS : public HasSpan16_Sampler_BitmapShader { michael@0: public: michael@0: NOFILTER_BITMAP_SHADER_CLASS(const SkBitmap& src) michael@0: : HasSpan16_Sampler_BitmapShader(src, false, michael@0: NOFILTER_BITMAP_SHADER_TILEMODE, michael@0: NOFILTER_BITMAP_SHADER_TILEMODE) michael@0: { michael@0: } michael@0: michael@0: virtual bool setContext(const SkBitmap& device, const SkPaint& paint, const SkMatrix& matrix) michael@0: { michael@0: if (!this->INHERITED::setContext(device, paint, matrix)) michael@0: return false; michael@0: michael@0: #ifdef NOFILTER_BITMAP_SHADER_USE_UNITINVERSE michael@0: this->computeUnitInverse(); michael@0: #endif michael@0: return true; michael@0: } michael@0: michael@0: virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count) michael@0: { michael@0: SkASSERT(count > 0); michael@0: michael@0: #ifdef NOFILTER_BITMAP_SHADER_SPRITEPROC32 michael@0: if ((this->getTotalInverse().getType() & ~SkMatrix::kTranslate_Mask) == 0) michael@0: { michael@0: NOFILTER_BITMAP_SHADER_SPRITEPROC32(this, x, y, dstC, count); michael@0: return; michael@0: } michael@0: #endif michael@0: michael@0: unsigned scale = SkAlpha255To256(this->getPaintAlpha()); michael@0: #ifdef NOFILTER_BITMAP_SHADER_USE_UNITINVERSE michael@0: const SkMatrix& inv = this->getUnitInverse(); michael@0: SkMatrix::MapPtProc invProc = this->getUnitInverseProc(); michael@0: #else michael@0: const SkMatrix& inv = this->getTotalInverse(); michael@0: SkMatrix::MapPtProc invProc = this->getInverseMapPtProc(); michael@0: #endif michael@0: const SkBitmap& srcBitmap = this->getSrcBitmap(); michael@0: unsigned srcMaxX = srcBitmap.width() - 1; michael@0: unsigned srcMaxY = srcBitmap.height() - 1; michael@0: unsigned srcRB = srcBitmap.rowBytes(); michael@0: SkFixed fx, fy, dx, dy; michael@0: michael@0: const NOFILTER_BITMAP_SHADER_TYPE* srcPixels = (const NOFILTER_BITMAP_SHADER_TYPE*)srcBitmap.getPixels(); michael@0: NOFILTER_BITMAP_SHADER_PREAMBLE(srcBitmap, srcRB); michael@0: michael@0: if (this->getInverseClass() == kPerspective_MatrixClass) michael@0: { michael@0: SkPerspIter iter(inv, SkIntToScalar(x) + SK_ScalarHalf, michael@0: SkIntToScalar(y) + SK_ScalarHalf, count); michael@0: while ((count = iter.next()) != 0) michael@0: { michael@0: const SkFixed* srcXY = iter.getXY(); michael@0: michael@0: /* Do I need this? michael@0: #ifndef NOFILTER_BITMAP_SHADER_USE_UNITINVERSE michael@0: fx >>= level; michael@0: fy >>= level; michael@0: #endif michael@0: */ michael@0: if (256 == scale) michael@0: { michael@0: while (--count >= 0) michael@0: { michael@0: fx = *srcXY++; michael@0: fy = *srcXY++; michael@0: unsigned x = NOFILTER_BITMAP_SHADER_TILEPROC(fx, srcMaxX); michael@0: unsigned y = NOFILTER_BITMAP_SHADER_TILEPROC(fy, srcMaxY); michael@0: *dstC++ = NOFILTER_BITMAP_SHADER_SAMPLE_XY(srcPixels, x, y, srcRB); michael@0: } michael@0: } michael@0: else michael@0: { michael@0: while (--count >= 0) michael@0: { michael@0: fx = *srcXY++; michael@0: fy = *srcXY++; michael@0: unsigned x = NOFILTER_BITMAP_SHADER_TILEPROC(fx, srcMaxX); michael@0: unsigned y = NOFILTER_BITMAP_SHADER_TILEPROC(fy, srcMaxY); michael@0: uint32_t c = NOFILTER_BITMAP_SHADER_SAMPLE_XY(srcPixels, x, y, srcRB); michael@0: *dstC++ = SkAlphaMulQ(c, scale); michael@0: } michael@0: } michael@0: } michael@0: return; michael@0: } michael@0: michael@0: // now init fx, fy, dx, dy michael@0: { michael@0: SkPoint srcPt; michael@0: invProc(inv, SkIntToScalar(x) + SK_ScalarHalf, michael@0: SkIntToScalar(y) + SK_ScalarHalf, &srcPt); michael@0: michael@0: fx = SkScalarToFixed(srcPt.fX); michael@0: fy = SkScalarToFixed(srcPt.fY); michael@0: michael@0: if (this->getInverseClass() == kFixedStepInX_MatrixClass) michael@0: (void)inv.fixedStepInX(SkIntToScalar(y), &dx, &dy); michael@0: else michael@0: { michael@0: dx = SkScalarToFixed(inv.getScaleX()); michael@0: dy = SkScalarToFixed(inv.getSkewY()); michael@0: } michael@0: } michael@0: michael@0: #ifndef NOFILTER_BITMAP_SHADER_USE_UNITINVERSE michael@0: { int level = this->getMipLevel() >> 16; michael@0: fx >>= level; michael@0: fy >>= level; michael@0: dx >>= level; michael@0: dy >>= level; michael@0: } michael@0: #endif michael@0: michael@0: if (dy == 0) michael@0: { michael@0: int y_index = NOFILTER_BITMAP_SHADER_TILEPROC(fy, srcMaxY); michael@0: // SkDEBUGF(("fy = %g, srcMaxY = %d, y_index = %d\n", SkFixedToFloat(fy), srcMaxY, y_index)); michael@0: srcPixels = (const NOFILTER_BITMAP_SHADER_TYPE*)((const char*)srcPixels + y_index * srcRB); michael@0: if (scale == 256) michael@0: while (--count >= 0) michael@0: { michael@0: unsigned x = NOFILTER_BITMAP_SHADER_TILEPROC(fx, srcMaxX); michael@0: fx += dx; michael@0: *dstC++ = NOFILTER_BITMAP_SHADER_SAMPLE_X(srcPixels, x); michael@0: } michael@0: else michael@0: while (--count >= 0) michael@0: { michael@0: unsigned x = NOFILTER_BITMAP_SHADER_TILEPROC(fx, srcMaxX); michael@0: SkPMColor c = NOFILTER_BITMAP_SHADER_SAMPLE_X(srcPixels, x); michael@0: fx += dx; michael@0: *dstC++ = SkAlphaMulQ(c, scale); michael@0: } michael@0: } michael@0: else // dy != 0 michael@0: { michael@0: if (scale == 256) michael@0: while (--count >= 0) michael@0: { michael@0: unsigned x = NOFILTER_BITMAP_SHADER_TILEPROC(fx, srcMaxX); michael@0: unsigned y = NOFILTER_BITMAP_SHADER_TILEPROC(fy, srcMaxY); michael@0: fx += dx; michael@0: fy += dy; michael@0: *dstC++ = NOFILTER_BITMAP_SHADER_SAMPLE_XY(srcPixels, x, y, srcRB); michael@0: } michael@0: else michael@0: while (--count >= 0) michael@0: { michael@0: unsigned x = NOFILTER_BITMAP_SHADER_TILEPROC(fx, srcMaxX); michael@0: unsigned y = NOFILTER_BITMAP_SHADER_TILEPROC(fy, srcMaxY); michael@0: SkPMColor c = NOFILTER_BITMAP_SHADER_SAMPLE_XY(srcPixels, x, y, srcRB); michael@0: fx += dx; michael@0: fy += dy; michael@0: *dstC++ = SkAlphaMulQ(c, scale); michael@0: } michael@0: } michael@0: michael@0: NOFILTER_BITMAP_SHADER_POSTAMBLE(srcBitmap); michael@0: } michael@0: michael@0: virtual void shadeSpan16(int x, int y, uint16_t dstC[], int count) michael@0: { michael@0: SkASSERT(count > 0); michael@0: SkASSERT(this->getFlags() & SkShader::kHasSpan16_Flag); michael@0: michael@0: #ifdef NOFILTER_BITMAP_SHADER_SPRITEPROC16 michael@0: if ((this->getTotalInverse().getType() & ~SkMatrix::kTranslate_Mask) == 0) michael@0: { michael@0: NOFILTER_BITMAP_SHADER_SPRITEPROC16(this, x, y, dstC, count); michael@0: return; michael@0: } michael@0: #endif michael@0: michael@0: #ifdef NOFILTER_BITMAP_SHADER_USE_UNITINVERSE michael@0: const SkMatrix& inv = this->getUnitInverse(); michael@0: SkMatrix::MapPtProc invProc = this->getUnitInverseProc(); michael@0: #else michael@0: const SkMatrix& inv = this->getTotalInverse(); michael@0: SkMatrix::MapPtProc invProc = this->getInverseMapPtProc(); michael@0: #endif michael@0: const SkBitmap& srcBitmap = this->getSrcBitmap(); michael@0: unsigned srcMaxX = srcBitmap.width() - 1; michael@0: unsigned srcMaxY = srcBitmap.height() - 1; michael@0: unsigned srcRB = srcBitmap.rowBytes(); michael@0: SkFixed fx, fy, dx, dy; michael@0: michael@0: const NOFILTER_BITMAP_SHADER_TYPE* srcPixels = (const NOFILTER_BITMAP_SHADER_TYPE*)srcBitmap.getPixels(); michael@0: NOFILTER_BITMAP_SHADER_PREAMBLE16(srcBitmap, srcRB); michael@0: michael@0: if (this->getInverseClass() == kPerspective_MatrixClass) michael@0: { michael@0: SkPerspIter iter(inv, SkIntToScalar(x) + SK_ScalarHalf, michael@0: SkIntToScalar(y) + SK_ScalarHalf, count); michael@0: while ((count = iter.next()) != 0) michael@0: { michael@0: const SkFixed* srcXY = iter.getXY(); michael@0: michael@0: while (--count >= 0) michael@0: { michael@0: fx = *srcXY++; michael@0: fy = *srcXY++; michael@0: unsigned x = NOFILTER_BITMAP_SHADER_TILEPROC(fx, srcMaxX); michael@0: unsigned y = NOFILTER_BITMAP_SHADER_TILEPROC(fy, srcMaxY); michael@0: *dstC++ = NOFILTER_BITMAP_SHADER_SAMPLE_XY16(srcPixels, x, y, srcRB); michael@0: } michael@0: } michael@0: return; michael@0: } michael@0: michael@0: // now init fx, fy, dx, dy michael@0: { michael@0: SkPoint srcPt; michael@0: invProc(inv, SkIntToScalar(x) + SK_ScalarHalf, michael@0: SkIntToScalar(y) + SK_ScalarHalf, &srcPt); michael@0: michael@0: fx = SkScalarToFixed(srcPt.fX); michael@0: fy = SkScalarToFixed(srcPt.fY); michael@0: michael@0: if (this->getInverseClass() == kFixedStepInX_MatrixClass) michael@0: (void)inv.fixedStepInX(SkIntToScalar(y), &dx, &dy); michael@0: else michael@0: { michael@0: dx = SkScalarToFixed(inv.getScaleX()); michael@0: dy = SkScalarToFixed(inv.getSkewY()); michael@0: } michael@0: } michael@0: michael@0: #ifndef NOFILTER_BITMAP_SHADER_USE_UNITINVERSE michael@0: { int level = this->getMipLevel() >> 16; michael@0: fx >>= level; michael@0: fy >>= level; michael@0: dx >>= level; michael@0: dy >>= level; michael@0: } michael@0: #endif michael@0: michael@0: if (dy == 0) michael@0: { michael@0: srcPixels = (const NOFILTER_BITMAP_SHADER_TYPE*)((const char*)srcPixels + NOFILTER_BITMAP_SHADER_TILEPROC(fy, srcMaxY) * srcRB); michael@0: do { michael@0: unsigned x = NOFILTER_BITMAP_SHADER_TILEPROC(fx, srcMaxX); michael@0: fx += dx; michael@0: *dstC++ = NOFILTER_BITMAP_SHADER_SAMPLE_X16(srcPixels, x); michael@0: } while (--count != 0); michael@0: } michael@0: else // dy != 0 michael@0: { michael@0: do { michael@0: unsigned x = NOFILTER_BITMAP_SHADER_TILEPROC(fx, srcMaxX); michael@0: unsigned y = NOFILTER_BITMAP_SHADER_TILEPROC(fy, srcMaxY); michael@0: fx += dx; michael@0: fy += dy; michael@0: *dstC++ = NOFILTER_BITMAP_SHADER_SAMPLE_XY16(srcPixels, x, y, srcRB); michael@0: } while (--count != 0); michael@0: } michael@0: michael@0: NOFILTER_BITMAP_SHADER_POSTAMBLE16(srcBitmap); michael@0: } michael@0: private: michael@0: typedef HasSpan16_Sampler_BitmapShader INHERITED; michael@0: }; michael@0: michael@0: #undef NOFILTER_BITMAP_SHADER_CLASS michael@0: #undef NOFILTER_BITMAP_SHADER_TYPE michael@0: #undef NOFILTER_BITMAP_SHADER_PREAMBLE michael@0: #undef NOFILTER_BITMAP_SHADER_POSTAMBLE michael@0: #undef NOFILTER_BITMAP_SHADER_SAMPLE_X //(x) michael@0: #undef NOFILTER_BITMAP_SHADER_SAMPLE_XY //(x, y, rowBytes) michael@0: #undef NOFILTER_BITMAP_SHADER_TILEMODE michael@0: #undef NOFILTER_BITMAP_SHADER_TILEPROC michael@0: michael@0: #undef NOFILTER_BITMAP_SHADER_PREAMBLE16 michael@0: #undef NOFILTER_BITMAP_SHADER_POSTAMBLE16 michael@0: #undef NOFILTER_BITMAP_SHADER_SAMPLE_X16 //(x) michael@0: #undef NOFILTER_BITMAP_SHADER_SAMPLE_XY16 //(x, y, rowBytes) michael@0: michael@0: #undef NOFILTER_BITMAP_SHADER_USE_UNITINVERSE michael@0: #undef NOFILTER_BITMAP_SHADER_SPRITEPROC16 michael@0: #undef NOFILTER_BITMAP_SHADER_SPRITEPROC32