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