diff options
author | fmalita <fmalita@chromium.org> | 2015-12-18 07:59:47 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-12-18 07:59:47 -0800 |
commit | 5ae7fdcc3d7712da3193c39a751e88b092aa82db (patch) | |
tree | 85ac81312e756d57b45759feacc33e390ae7666c /src/core | |
parent | a11e5fce33f8d6f38c3324d639ca76ddf12598ba (diff) |
Repeating SkBitmapProcState rounding bias
Observe the bias in repeat matrix procs also.
Introduce a utility class to handle device space -> bitmap space
mapping.
BUG=skia:4680,skia:4649
R=reed@google.com
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1529833003
Review URL: https://codereview.chromium.org/1529833003
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/SkBitmapProcState.cpp | 12 | ||||
-rw-r--r-- | src/core/SkBitmapProcState.h | 39 | ||||
-rw-r--r-- | src/core/SkBitmapProcState_matrix.h | 21 | ||||
-rw-r--r-- | src/core/SkBitmapProcState_matrix_template.h | 20 |
4 files changed, 44 insertions, 48 deletions
diff --git a/src/core/SkBitmapProcState.cpp b/src/core/SkBitmapProcState.cpp index c85a5fb992..1ec47fb602 100644 --- a/src/core/SkBitmapProcState.cpp +++ b/src/core/SkBitmapProcState.cpp @@ -824,15 +824,10 @@ void Clamp_S32_opaque_D32_nofilter_DX_shaderproc(const void* sIn, int x, int y, SkFractionalInt fx; int dstY; { - SkPoint pt; - s.fInvProc(s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf, SkIntToScalar(y) + SK_ScalarHalf, - &pt); - fx = SkScalarToFractionalInt(pt.fY) - + bitmap_sampler_inv_bias(s.fInvMatrix.getScaleY()); + const SkBitmapProcStateAutoMapper mapper(s, x, y); const unsigned maxY = s.fPixmap.height() - 1; - dstY = SkClampMax(SkFractionalIntToInt(fx), maxY); - fx = SkScalarToFractionalInt(pt.fX) - + bitmap_sampler_inv_bias(s.fInvMatrix.getScaleX()); + dstY = SkClampMax(SkFixedFloorToInt(mapper.y()), maxY); + fx = SkFixedToFractionalInt(mapper.x()); } const SkPMColor* SK_RESTRICT src = s.fPixmap.addr32(0, dstY); @@ -868,4 +863,3 @@ void Clamp_S32_opaque_D32_nofilter_DX_shaderproc(const void* sIn, int x, int y, } } } - diff --git a/src/core/SkBitmapProcState.h b/src/core/SkBitmapProcState.h index 4d7e7f32dc..bd2a344eca 100644 --- a/src/core/SkBitmapProcState.h +++ b/src/core/SkBitmapProcState.h @@ -25,17 +25,6 @@ typedef SkFixed3232 SkFractionalInt; #define SkFixedToFractionalInt(x) SkFixedToFixed3232(x) #define SkFractionalIntToInt(x) SkFixed3232ToInt(x) -// Applying a fixed point (SkFixed, SkFractionalInt) epsilon bias ensures that the inverse-mapped -// bitmap coordinates are rounded consistently WRT geometry. Note that we only have to do this -// when the scale is positive - for negative scales we're already rounding in the right direction. -static inline int bitmap_sampler_inv_bias(SkScalar scale) { -#ifndef SK_SUPPORT_LEGACY_BITMAP_SAMPLER_BIAS - return -(scale > 0); -#else - return 0; -#endif -} - class SkPaint; struct SkBitmapProcState { @@ -210,4 +199,32 @@ void S32_D16_filter_DX(const SkBitmapProcState& s, void S32_D16_filter_DXDY(const SkBitmapProcState& s, const uint32_t* xy, int count, uint16_t* colors); +// Helper class for mapping the middle of pixel (x, y) into SkFixed bitmap space. +class SkBitmapProcStateAutoMapper { +public: + SkBitmapProcStateAutoMapper(const SkBitmapProcState& s, int x, int y) { + SkPoint pt; + s.fInvProc(s.fInvMatrix, + SkIntToScalar(x) + SK_ScalarHalf, + SkIntToScalar(y) + SK_ScalarHalf, &pt); + +#ifndef SK_SUPPORT_LEGACY_BITMAP_SAMPLER_BIAS + // SkFixed epsilon bias to ensure inverse-mapped bitmap coordinates are rounded + // consistently WRT geometry. Note that we only need the bias for positive scales: + // for negative scales, the rounding is intrinsically correct. + fX = SkScalarToFixed(pt.x()) - (s.fInvMatrix.getScaleX() > 0); + fY = SkScalarToFixed(pt.y()) - (s.fInvMatrix.getScaleY() > 0); +#else + fX = SkScalarToFixed(pt.x()); + fY = SkScalarToFixed(pt.y()); +#endif + } + + SkFixed x() const { return fX; } + SkFixed y() const { return fY; } + +private: + SkFixed fX, fY; +}; + #endif diff --git a/src/core/SkBitmapProcState_matrix.h b/src/core/SkBitmapProcState_matrix.h index 42a5ab6e22..e4212b60fe 100644 --- a/src/core/SkBitmapProcState_matrix.h +++ b/src/core/SkBitmapProcState_matrix.h @@ -61,17 +61,13 @@ void SCALE_FILTER_NAME(const SkBitmapProcState& s, SkFractionalInt fx; { - SkPoint pt; - s.fInvProc(s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf, - SkIntToScalar(y) + SK_ScalarHalf, &pt); - const SkFixed fy = SkScalarToFixed(pt.fY) - (s.fFilterOneY >> 1) - + bitmap_sampler_inv_bias(s.fInvMatrix.getScaleY()); + const SkBitmapProcStateAutoMapper mapper(s, x ,y); + const SkFixed fy = mapper.y() - (s.fFilterOneY >> 1); const unsigned maxY = s.fPixmap.height() - 1; // compute our two Y values up front *xy++ = PACK_FILTER_Y_NAME(fy, maxY, s.fFilterOneY PREAMBLE_ARG_Y); // now initialize fx - fx = SkScalarToFractionalInt(pt.fX) - (SkFixedToFractionalInt(one) >> 1) - + bitmap_sampler_inv_bias(s.fInvMatrix.getScaleX()); + fx = SkFixedToFractionalInt(mapper.x() - (one >> 1)); } #ifdef CHECK_FOR_DECAL @@ -97,17 +93,12 @@ void AFFINE_FILTER_NAME(const SkBitmapProcState& s, SkMatrix::kAffine_Mask)) == 0); PREAMBLE(s); - SkPoint srcPt; - s.fInvProc(s.fInvMatrix, - SkIntToScalar(x) + SK_ScalarHalf, - SkIntToScalar(y) + SK_ScalarHalf, &srcPt); + const SkBitmapProcStateAutoMapper mapper(s, x ,y); SkFixed oneX = s.fFilterOneX; SkFixed oneY = s.fFilterOneY; - SkFixed fx = SkScalarToFixed(srcPt.fX) - (oneX >> 1) - + bitmap_sampler_inv_bias(s.fInvMatrix.getScaleX()); - SkFixed fy = SkScalarToFixed(srcPt.fY) - (oneY >> 1) - + bitmap_sampler_inv_bias(s.fInvMatrix.getScaleY()); + SkFixed fx = mapper.x() - (oneX >> 1); + SkFixed fy = mapper.y() - (oneY >> 1); SkFixed dx = s.fInvSx; SkFixed dy = s.fInvKy; unsigned maxX = s.fPixmap.width() - 1; diff --git a/src/core/SkBitmapProcState_matrix_template.h b/src/core/SkBitmapProcState_matrix_template.h index 468013c30d..9d639b8a04 100644 --- a/src/core/SkBitmapProcState_matrix_template.h +++ b/src/core/SkBitmapProcState_matrix_template.h @@ -22,13 +22,10 @@ void NoFilterProc_Scale(const SkBitmapProcState& s, uint32_t xy[], const unsigned maxX = s.fPixmap.width() - 1; SkFractionalInt fx; { - SkPoint pt; - s.fInvProc(s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf, - SkIntToScalar(y) + SK_ScalarHalf, &pt); - fx = SkScalarToFractionalInt(pt.fY); + const SkBitmapProcStateAutoMapper mapper(s, x ,y); const unsigned maxY = s.fPixmap.height() - 1; - *xy++ = TileProc::Y(s, SkFractionalIntToFixed(fx), maxY); - fx = SkScalarToFractionalInt(pt.fX); + *xy++ = TileProc::Y(s, mapper.y(), maxY); + fx = SkFixedToFractionalInt(mapper.x()); } if (0 == maxX) { @@ -80,13 +77,9 @@ void NoFilterProc_Affine(const SkBitmapProcState& s, uint32_t xy[], SkMatrix::kScale_Mask | SkMatrix::kAffine_Mask)) == 0); - SkPoint srcPt; - s.fInvProc(s.fInvMatrix, - SkIntToScalar(x) + SK_ScalarHalf, - SkIntToScalar(y) + SK_ScalarHalf, &srcPt); - - SkFractionalInt fx = SkScalarToFractionalInt(srcPt.fX); - SkFractionalInt fy = SkScalarToFractionalInt(srcPt.fY); + const SkBitmapProcStateAutoMapper mapper(s, x ,y); + SkFractionalInt fx = SkFixedToFractionalInt(mapper.x()); + SkFractionalInt fy = SkFixedToFractionalInt(mapper.y()); SkFractionalInt dx = s.fInvSxFractionalInt; SkFractionalInt dy = s.fInvKyFractionalInt; int maxX = s.fPixmap.width() - 1; @@ -107,6 +100,7 @@ void NoFilterProc_Persp(const SkBitmapProcState& s, uint32_t* SK_RESTRICT xy, int maxX = s.fPixmap.width() - 1; int maxY = s.fPixmap.height() - 1; + // TODO: inv bias support SkPerspIter iter(s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf, SkIntToScalar(y) + SK_ScalarHalf, count); |