| /* | |
| * Copyright 2011 Google Inc. | |
| * | |
| * Use of this source code is governed by a BSD-style license that can be | |
| * found in the LICENSE file. | |
| */ | |
| #include "SkMath.h" | |
| #include "SkMathPriv.h" | |
| #define SCALE_FILTER_NAME MAKENAME(_filter_scale) | |
| #define AFFINE_FILTER_NAME MAKENAME(_filter_affine) | |
| #define PERSP_FILTER_NAME MAKENAME(_filter_persp) | |
| #define PACK_FILTER_X_NAME MAKENAME(_pack_filter_x) | |
| #define PACK_FILTER_Y_NAME MAKENAME(_pack_filter_y) | |
| #ifndef PREAMBLE | |
| #define PREAMBLE(state) | |
| #define PREAMBLE_PARAM_X | |
| #define PREAMBLE_PARAM_Y | |
| #define PREAMBLE_ARG_X | |
| #define PREAMBLE_ARG_Y | |
| #endif | |
| // declare functions externally to suppress warnings. | |
| void SCALE_FILTER_NAME(const SkBitmapProcState& s, | |
| uint32_t xy[], int count, int x, int y); | |
| void AFFINE_FILTER_NAME(const SkBitmapProcState& s, | |
| uint32_t xy[], int count, int x, int y); | |
| void PERSP_FILTER_NAME(const SkBitmapProcState& s, | |
| uint32_t* SK_RESTRICT xy, int count, | |
| int x, int y); | |
| static inline uint32_t PACK_FILTER_Y_NAME(SkFixed f, unsigned max, | |
| SkFixed one PREAMBLE_PARAM_Y) { | |
| unsigned i = TILEY_PROCF(f, max); | |
| i = (i << 4) | TILEY_LOW_BITS(f, max); | |
| return (i << 14) | (TILEY_PROCF((f + one), max)); | |
| } | |
| static inline uint32_t PACK_FILTER_X_NAME(SkFixed f, unsigned max, | |
| SkFixed one PREAMBLE_PARAM_X) { | |
| unsigned i = TILEX_PROCF(f, max); | |
| i = (i << 4) | TILEX_LOW_BITS(f, max); | |
| return (i << 14) | (TILEX_PROCF((f + one), max)); | |
| } | |
| void SCALE_FILTER_NAME(const SkBitmapProcState& s, | |
| uint32_t xy[], int count, int x, int y) { | |
| SkASSERT((s.fInvType & ~(SkMatrix::kTranslate_Mask | | |
| SkMatrix::kScale_Mask)) == 0); | |
| SkASSERT(s.fInvKy == 0); | |
| PREAMBLE(s); | |
| const unsigned maxX = s.fBitmap->width() - 1; | |
| const SkFixed one = s.fFilterOneX; | |
| const SkFractionalInt dx = s.fInvSxFractionalInt; | |
| 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); | |
| const unsigned maxY = s.fBitmap->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); | |
| } | |
| #ifdef CHECK_FOR_DECAL | |
| if (can_truncate_to_fixed_for_decal(fx, dx, count, maxX)) { | |
| decal_filter_scale(xy, SkFractionalIntToFixed(fx), | |
| SkFractionalIntToFixed(dx), count); | |
| } else | |
| #endif | |
| { | |
| do { | |
| SkFixed fixedFx = SkFractionalIntToFixed(fx); | |
| *xy++ = PACK_FILTER_X_NAME(fixedFx, maxX, one PREAMBLE_ARG_X); | |
| fx += dx; | |
| } while (--count != 0); | |
| } | |
| } | |
| void AFFINE_FILTER_NAME(const SkBitmapProcState& s, | |
| uint32_t xy[], int count, int x, int y) { | |
| SkASSERT(s.fInvType & SkMatrix::kAffine_Mask); | |
| SkASSERT((s.fInvType & ~(SkMatrix::kTranslate_Mask | | |
| SkMatrix::kScale_Mask | | |
| SkMatrix::kAffine_Mask)) == 0); | |
| PREAMBLE(s); | |
| SkPoint srcPt; | |
| s.fInvProc(s.fInvMatrix, | |
| SkIntToScalar(x) + SK_ScalarHalf, | |
| SkIntToScalar(y) + SK_ScalarHalf, &srcPt); | |
| SkFixed oneX = s.fFilterOneX; | |
| SkFixed oneY = s.fFilterOneY; | |
| SkFixed fx = SkScalarToFixed(srcPt.fX) - (oneX >> 1); | |
| SkFixed fy = SkScalarToFixed(srcPt.fY) - (oneY >> 1); | |
| SkFixed dx = s.fInvSx; | |
| SkFixed dy = s.fInvKy; | |
| unsigned maxX = s.fBitmap->width() - 1; | |
| unsigned maxY = s.fBitmap->height() - 1; | |
| do { | |
| *xy++ = PACK_FILTER_Y_NAME(fy, maxY, oneY PREAMBLE_ARG_Y); | |
| fy += dy; | |
| *xy++ = PACK_FILTER_X_NAME(fx, maxX, oneX PREAMBLE_ARG_X); | |
| fx += dx; | |
| } while (--count != 0); | |
| } | |
| void PERSP_FILTER_NAME(const SkBitmapProcState& s, | |
| uint32_t* SK_RESTRICT xy, int count, | |
| int x, int y) { | |
| SkASSERT(s.fInvType & SkMatrix::kPerspective_Mask); | |
| PREAMBLE(s); | |
| unsigned maxX = s.fBitmap->width() - 1; | |
| unsigned maxY = s.fBitmap->height() - 1; | |
| SkFixed oneX = s.fFilterOneX; | |
| SkFixed oneY = s.fFilterOneY; | |
| SkPerspIter iter(s.fInvMatrix, | |
| SkIntToScalar(x) + SK_ScalarHalf, | |
| SkIntToScalar(y) + SK_ScalarHalf, count); | |
| while ((count = iter.next()) != 0) { | |
| const SkFixed* SK_RESTRICT srcXY = iter.getXY(); | |
| do { | |
| *xy++ = PACK_FILTER_Y_NAME(srcXY[1] - (oneY >> 1), maxY, | |
| oneY PREAMBLE_ARG_Y); | |
| *xy++ = PACK_FILTER_X_NAME(srcXY[0] - (oneX >> 1), maxX, | |
| oneX PREAMBLE_ARG_X); | |
| srcXY += 2; | |
| } while (--count != 0); | |
| } | |
| } | |
| #undef MAKENAME | |
| #undef TILEX_PROCF | |
| #undef TILEY_PROCF | |
| #ifdef CHECK_FOR_DECAL | |
| #undef CHECK_FOR_DECAL | |
| #endif | |
| #undef SCALE_FILTER_NAME | |
| #undef AFFINE_FILTER_NAME | |
| #undef PERSP_FILTER_NAME | |
| #undef PREAMBLE | |
| #undef PREAMBLE_PARAM_X | |
| #undef PREAMBLE_PARAM_Y | |
| #undef PREAMBLE_ARG_X | |
| #undef PREAMBLE_ARG_Y | |
| #undef TILEX_LOW_BITS | |
| #undef TILEY_LOW_BITS |