blob: 8097a334acfc65b4113d4ec581a9d7b095645d24 [file] [log] [blame]
class ARGB32_Clamp_Bilinear_BitmapShader : public SkBitmapShader {
public:
ARGB32_Clamp_Bilinear_BitmapShader(const SkBitmap& src, bool transferOwnership)
: SkBitmapShader(src, transferOwnership, SkPaint::kBilinear_FilterType,
SkShader::kClamp_TileMode, SkShader::kClamp_TileMode)
{}
virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count);
};
SkPMColor sample_bilerp(SkFixed fx, SkFixed fy, int srcMaxX, int srcMaxY,
const SkPMColor* srcPixels, int srcRB, const SkFilterPtrProc* proc_table);
SkPMColor sample_bilerp(SkFixed fx, SkFixed fy, int srcMaxX, int srcMaxY,
const SkPMColor* srcPixels, int srcRB, const SkFilterPtrProc* proc_table)
{
int x = fx >> 16;
int y = fy >> 16;
if (x < 0) x = 0;
if (x > srcMaxX) x = srcMaxX;
if (y < 0) y = 0;
if (y > srcMaxY) y = srcMaxY;
SkASSERT(x <= srcMaxX);
SkASSERT(y <= srcMaxY);
const SkPMColor *p00, *p01, *p10, *p11;
p00 = p01 = ((const SkPMColor*)((const char*)srcPixels + y * srcRB)) + x;
if (x < srcMaxX)
p01 += 1;
p10 = p00;
p11 = p01;
if (y < 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_bilerp(int x, int srcMaxX, const SkPMColor* srcPixels, int srcRB, SkFilterPtrProc proc)
{
const SkPMColor *p00, *p01, *p10, *p11;
// sure wish I could pull this check out of the loop that calls this function
if ((unsigned)x < (unsigned)srcMaxX)
{
p00 = srcPixels + x;
p01 = p00 + 1;
p10 = (const SkPMColor*)((const char*)p00 + srcRB);
p11 = p10 + 1;
return proc(p00, p01, p10, p11);
}
if (x < 0) x = 0;
if (x > srcMaxX) x = srcMaxX;
p00 = p01 = srcPixels + x;
p10 = p11 = (const SkPMColor*)((const char*)p00 + srcRB);
if (x < srcMaxX)
{
p01 += 1;
p11 += 1;
}
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), SkIntToScalar(y), count);
if (256 == srcScale)
{
while ((count = iter.next()) != 0)
{
const SkFixed* srcXY = iter.getXY();
while (--count >= 0)
{
SkFixed fx = *srcXY++;
SkFixed fy = *srcXY++;
*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++;
SkFixed fy = *srcXY++;
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), SkIntToScalar(y), &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());
}
}
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_bilerp(fx >> 16, srcMaxX, srcPixels, srcRB, SkGetBilinearFilterPtrXProc(proc_table, fx));
fx += dx;
} while (--count != 0);
}
else
{
do {
SkPMColor c = sample_bilerp(fx >> 16, srcMaxX, srcPixels, srcRB, SkGetBilinearFilterPtrXProc(proc_table, fx));
*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);
}
}
}
}