/* * Copyright 2011 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ class ARGB32_Clamp_Bilinear_BitmapShader : public SkBitmapShader { public: ARGB32_Clamp_Bilinear_BitmapShader(const SkBitmap& src) : SkBitmapShader(src, true, SkShader::kClamp_TileMode, SkShader::kClamp_TileMode) {} virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count); }; SkPMColor sample_bilerp(SkFixed fx, SkFixed fy, unsigned srcMaxX, unsigned srcMaxY, const SkPMColor* srcPixels, int srcRB, const SkFilterPtrProc* proc_table); SkPMColor sample_bilerp(SkFixed fx, SkFixed fy, unsigned srcMaxX, unsigned srcMaxY, const SkPMColor* srcPixels, int srcRB, const SkFilterPtrProc* proc_table) { int ix = fx >> 16; int iy = fy >> 16; const SkPMColor *p00, *p01, *p10, *p11; p00 = p01 = ((const SkPMColor*)((const char*)srcPixels + SkClampMax(iy, srcMaxY) * srcRB)) + SkClampMax(ix, srcMaxX); if ((unsigned)ix < srcMaxX) p01 += 1; p10 = p00; p11 = p01; if ((unsigned)iy < srcMaxY) { p10 = (const SkPMColor*)((const char*)p10 + srcRB); p11 = (const SkPMColor*)((const char*)p11 + srcRB); } SkFilterPtrProc proc = SkGetBilinearFilterPtrProc(proc_table, fx, fy); return proc(p00, p01, p10, p11); } static inline SkPMColor sample_bilerpx(SkFixed fx, unsigned srcMaxX, const SkPMColor* srcPixels, int srcRB, const SkFilterPtrProc* proc_table) { int ix = fx >> 16; const SkPMColor *p00, *p01, *p10, *p11; p00 = p01 = srcPixels + SkClampMax(ix, srcMaxX); if ((unsigned)ix < srcMaxX) p01 += 1; p10 = (const SkPMColor*)((const char*)p00 + srcRB); p11 = (const SkPMColor*)((const char*)p01 + srcRB); SkFilterPtrProc proc = SkGetBilinearFilterPtrXProc(proc_table, fx); return proc(p00, p01, p10, p11); } void ARGB32_Clamp_Bilinear_BitmapShader::shadeSpan(int x, int y, SkPMColor dstC[], int count) { SkASSERT(count > 0); unsigned srcScale = SkAlpha255To256(this->getPaintAlpha()); const SkMatrix& inv = this->getTotalInverse(); const SkBitmap& srcBitmap = this->getSrcBitmap(); unsigned srcMaxX = srcBitmap.width() - 1; unsigned srcMaxY = srcBitmap.height() - 1; unsigned srcRB = srcBitmap.rowBytes(); const SkFilterPtrProc* proc_table = SkGetBilinearFilterPtrProcTable(); const SkPMColor* srcPixels = (const SkPMColor*)srcBitmap.getPixels(); if (this->getInverseClass() == kPerspective_MatrixClass) { SkPerspIter iter(inv, SkIntToScalar(x) + SK_ScalarHalf, SkIntToScalar(y) + SK_ScalarHalf, count); if (256 == srcScale) { while ((count = iter.next()) != 0) { const SkFixed* srcXY = iter.getXY(); while (--count >= 0) { SkFixed fx = *srcXY++ - SK_FixedHalf; SkFixed fy = *srcXY++ - SK_FixedHalf; *dstC++ = sample_bilerp(fx, fy, srcMaxX, srcMaxY, srcPixels, srcRB, proc_table); } } } else // scale by srcScale { while ((count = iter.next()) != 0) { const SkFixed* srcXY = iter.getXY(); while (--count >= 0) { SkFixed fx = *srcXY++ - SK_FixedHalf; SkFixed fy = *srcXY++ - SK_FixedHalf; SkPMColor c = sample_bilerp(fx, fy, srcMaxX, srcMaxY, srcPixels, srcRB, proc_table); *dstC++ = SkAlphaMulQ(c, srcScale); } } } } else // linear case { SkFixed fx, fy, dx, dy; // now init fx, fy, dx, dy { SkPoint srcPt; this->getInverseMapPtProc()(inv, SkIntToScalar(x) + SK_ScalarHalf, SkIntToScalar(y) + SK_ScalarHalf, &srcPt); fx = SkScalarToFixed(srcPt.fX) - SK_FixedHalf; fy = SkScalarToFixed(srcPt.fY) - SK_FixedHalf; if (this->getInverseClass() == kFixedStepInX_MatrixClass) (void)inv.fixedStepInX(SkIntToScalar(y), &dx, &dy); else { dx = SkScalarToFixed(inv.getScaleX()); dy = SkScalarToFixed(inv.getSkewY()); } } if (dy == 0 && (unsigned)(fy >> 16) < srcMaxY) { srcPixels = (const SkPMColor*)((const char*)srcPixels + (fy >> 16) * srcRB); proc_table = SkGetBilinearFilterPtrProcYTable(proc_table, fy); if (256 == srcScale) { do { *dstC++ = sample_bilerpx(fx, srcMaxX, srcPixels, srcRB, proc_table); fx += dx; } while (--count != 0); } else { do { SkPMColor c = sample_bilerpx(fx, srcMaxX, srcPixels, srcRB, proc_table); *dstC++ = SkAlphaMulQ(c, srcScale); fx += dx; } while (--count != 0); } } else // dy is != 0 { if (256 == srcScale) { do { *dstC++ = sample_bilerp(fx, fy, srcMaxX, srcMaxY, srcPixels, srcRB, proc_table); fx += dx; fy += dy; } while (--count != 0); } else { do { SkPMColor c = sample_bilerp(fx, fy, srcMaxX, srcMaxY, srcPixels, srcRB, proc_table); *dstC++ = SkAlphaMulQ(c, srcScale); fx += dx; fy += dy; } while (--count != 0); } } } }