Index: src/core/SkBitmapProcBicubic.cpp |
diff --git a/src/core/SkBitmapProcBicubic.cpp b/src/core/SkBitmapProcBicubic.cpp |
index 1c415fdadfa6937c2a4335710cc50c235eae5153..1616808484c265be13bd7dd362f7f3cb7cfa71e9 100644 |
--- a/src/core/SkBitmapProcBicubic.cpp |
+++ b/src/core/SkBitmapProcBicubic.cpp |
@@ -35,22 +35,49 @@ static float poly_eval(const float cc[4], float t) { |
return cc[0] + t * (cc[1] + t * (cc[2] + t * cc[3])); |
} |
-static void build_coeff4(SkFixed dst[4], const float src[16], float t) { |
- dst[0] = SkFloatToFixed(poly_eval(&src[ 0], t)); |
- dst[1] = SkFloatToFixed(poly_eval(&src[ 4], t)); |
- dst[2] = SkFloatToFixed(poly_eval(&src[ 8], t)); |
- dst[3] = SkFloatToFixed(poly_eval(&src[12], t)); |
-} |
- |
-static void bicubicFilter(const SkBitmapProcState& s, int x, int y, |
- SkPMColor* SK_RESTRICT colors, int count) { |
- |
+static void build_coeff4(SkFixed dst[4], float t) { |
static const SkScalar coefficients[16] = { |
DS( 1.0 / 18.0), DS(-9.0 / 18.0), DS( 15.0 / 18.0), DS( -7.0 / 18.0), |
DS(16.0 / 18.0), DS( 0.0 / 18.0), DS(-36.0 / 18.0), DS( 21.0 / 18.0), |
DS( 1.0 / 18.0), DS( 9.0 / 18.0), DS( 27.0 / 18.0), DS(-21.0 / 18.0), |
DS( 0.0 / 18.0), DS( 0.0 / 18.0), DS( -6.0 / 18.0), DS( 7.0 / 18.0), |
}; |
+ |
+ dst[0] = SkFloatToFixed(poly_eval(&coefficients[ 0], t)); |
+ dst[1] = SkFloatToFixed(poly_eval(&coefficients[ 4], t)); |
+ dst[2] = SkFloatToFixed(poly_eval(&coefficients[ 8], t)); |
+ dst[3] = SkFloatToFixed(poly_eval(&coefficients[12], t)); |
+} |
+ |
+static SkPMColor doBicubicFilter(const SkBitmap *bm, SkFixed coeffX[4], SkFixed coeffY[4], |
+ int x0, int x1, int x2, int x3, |
+ int y0, int y1, int y2, int y3 ) |
+{ |
+ SkPMColor s00 = *bm->getAddr32(x0, y0); |
+ SkPMColor s10 = *bm->getAddr32(x1, y0); |
+ SkPMColor s20 = *bm->getAddr32(x2, y0); |
+ SkPMColor s30 = *bm->getAddr32(x3, y0); |
+ SkPMColor s0 = cubicBlend(coeffX, s00, s10, s20, s30); |
+ SkPMColor s01 = *bm->getAddr32(x0, y1); |
+ SkPMColor s11 = *bm->getAddr32(x1, y1); |
+ SkPMColor s21 = *bm->getAddr32(x2, y1); |
+ SkPMColor s31 = *bm->getAddr32(x3, y1); |
+ SkPMColor s1 = cubicBlend(coeffX, s01, s11, s21, s31); |
+ SkPMColor s02 = *bm->getAddr32(x0, y2); |
+ SkPMColor s12 = *bm->getAddr32(x1, y2); |
+ SkPMColor s22 = *bm->getAddr32(x2, y2); |
+ SkPMColor s32 = *bm->getAddr32(x3, y2); |
+ SkPMColor s2 = cubicBlend(coeffX, s02, s12, s22, s32); |
+ SkPMColor s03 = *bm->getAddr32(x0, y3); |
+ SkPMColor s13 = *bm->getAddr32(x1, y3); |
+ SkPMColor s23 = *bm->getAddr32(x2, y3); |
+ SkPMColor s33 = *bm->getAddr32(x3, y3); |
+ SkPMColor s3 = cubicBlend(coeffX, s03, s13, s23, s33); |
+ return cubicBlend(coeffY, s0, s1, s2, s3); |
+} |
+ |
+static void bicubicFilter(const SkBitmapProcState& s, int x, int y, |
+ SkPMColor* SK_RESTRICT colors, int count) { |
const int maxX = s.fBitmap->width() - 1; |
const int maxY = s.fBitmap->height() - 1; |
@@ -65,8 +92,8 @@ static void bicubicFilter(const SkBitmapProcState& s, int x, int y, |
SkScalar fracty = srcPt.fY - SkScalarFloorToScalar(srcPt.fY); |
SkFixed coeffX[4], coeffY[4]; |
- build_coeff4(coeffX, coefficients, fractx); |
- build_coeff4(coeffY, coefficients, fracty); |
+ build_coeff4(coeffX, fractx); |
+ build_coeff4(coeffY, fracty); |
int sx = SkScalarFloorToInt(srcPt.fX); |
int sy = SkScalarFloorToInt(srcPt.fY); |
@@ -80,28 +107,47 @@ static void bicubicFilter(const SkBitmapProcState& s, int x, int y, |
int y1 = SkClampMax(sy , maxY); |
int y2 = SkClampMax(sy + 1, maxY); |
int y3 = SkClampMax(sy + 2, maxY); |
+ |
+ *colors++ = doBicubicFilter( s.fBitmap, coeffX, coeffY, x0, x1, x2, x3, y0, y1, y2, y3 ); |
+ |
+ x++; |
+ } |
+} |
+ |
+static void bicubicFilter_ScaleOnly(const SkBitmapProcState &s, int x, int y, |
+ SkPMColor *SK_RESTRICT colors, int count) { |
+ const int maxX = s.fBitmap->width() - 1; |
+ const int maxY = s.fBitmap->height() - 1; |
+ |
+ SkPoint srcPt; |
+ s.fInvProc(*s.fInvMatrix, SkIntToScalar(x), SkIntToScalar(y), &srcPt); |
+ srcPt.fY -= SK_ScalarHalf; |
+ SkScalar fracty = srcPt.fY - SkScalarFloorToScalar(srcPt.fY); |
+ SkFixed coeffX[4], coeffY[4]; |
+ build_coeff4(coeffY, fracty); |
+ int sy = SkScalarFloorToInt(srcPt.fY); |
+ int y0 = SkClampMax(sy - 1, maxY); |
+ int y1 = SkClampMax(sy , maxY); |
+ int y2 = SkClampMax(sy + 1, maxY); |
+ int y3 = SkClampMax(sy + 2, maxY); |
+ |
+ while (count-- > 0) { |
+ s.fInvProc(*s.fInvMatrix, SkIntToScalar(x), SkIntToScalar(y), &srcPt); |
+ srcPt.fX -= SK_ScalarHalf; |
+ SkScalar fractx = srcPt.fX - SkScalarFloorToScalar(srcPt.fX); |
+ |
+ build_coeff4(coeffX, fractx); |
+ |
+ int sx = SkScalarFloorToInt(srcPt.fX); |
+ |
+ // Here is where we can support other tile modes (e.g. repeat or mirror) |
+ int x0 = SkClampMax(sx - 1, maxX); |
+ int x1 = SkClampMax(sx , maxX); |
+ int x2 = SkClampMax(sx + 1, maxX); |
+ int x3 = SkClampMax(sx + 2, maxX); |
+ |
+ *colors++ = doBicubicFilter( s.fBitmap, coeffX, coeffY, x0, x1, x2, x3, y0, y1, y2, y3 ); |
- SkPMColor s00 = *s.fBitmap->getAddr32(x0, y0); |
- SkPMColor s10 = *s.fBitmap->getAddr32(x1, y0); |
- SkPMColor s20 = *s.fBitmap->getAddr32(x2, y0); |
- SkPMColor s30 = *s.fBitmap->getAddr32(x3, y0); |
- SkPMColor s0 = cubicBlend(coeffX, s00, s10, s20, s30); |
- SkPMColor s01 = *s.fBitmap->getAddr32(x0, y1); |
- SkPMColor s11 = *s.fBitmap->getAddr32(x1, y1); |
- SkPMColor s21 = *s.fBitmap->getAddr32(x2, y1); |
- SkPMColor s31 = *s.fBitmap->getAddr32(x3, y1); |
- SkPMColor s1 = cubicBlend(coeffX, s01, s11, s21, s31); |
- SkPMColor s02 = *s.fBitmap->getAddr32(x0, y2); |
- SkPMColor s12 = *s.fBitmap->getAddr32(x1, y2); |
- SkPMColor s22 = *s.fBitmap->getAddr32(x2, y2); |
- SkPMColor s32 = *s.fBitmap->getAddr32(x3, y2); |
- SkPMColor s2 = cubicBlend(coeffX, s02, s12, s22, s32); |
- SkPMColor s03 = *s.fBitmap->getAddr32(x0, y3); |
- SkPMColor s13 = *s.fBitmap->getAddr32(x1, y3); |
- SkPMColor s23 = *s.fBitmap->getAddr32(x2, y3); |
- SkPMColor s33 = *s.fBitmap->getAddr32(x3, y3); |
- SkPMColor s3 = cubicBlend(coeffX, s03, s13, s23, s33); |
- *colors++ = cubicBlend(coeffY, s0, s1, s2, s3); |
x++; |
} |
} |
@@ -130,6 +176,12 @@ SkBitmapProcState::chooseBicubicFilterProc(const SkPaint& paint) { |
if (0xFF != paint.getAlpha()) { |
return NULL; |
} |
- |
- return bicubicFilter; |
+ |
+ if (fInvType & SkMatrix::kAffine_Mask) { |
+ return bicubicFilter; |
+ } else if (fInvType & SkMatrix::kScale_Mask) { |
+ return bicubicFilter_ScaleOnly; |
+ } else { |
+ return NULL; |
+ } |
} |