SkBitmapProcState_matrix.h revision 4bc0a9db18d58698057b8f38a6f21537aca4ddcf
1 2/* 3 * Copyright 2011 Google Inc. 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9#include "SkMath.h" 10 11#define SCALE_NOFILTER_NAME MAKENAME(_nofilter_scale) 12#define SCALE_FILTER_NAME MAKENAME(_filter_scale) 13#define AFFINE_NOFILTER_NAME MAKENAME(_nofilter_affine) 14#define AFFINE_FILTER_NAME MAKENAME(_filter_affine) 15#define PERSP_NOFILTER_NAME MAKENAME(_nofilter_persp) 16#define PERSP_FILTER_NAME MAKENAME(_filter_persp) 17 18#define PACK_FILTER_X_NAME MAKENAME(_pack_filter_x) 19#define PACK_FILTER_Y_NAME MAKENAME(_pack_filter_y) 20 21#ifndef PREAMBLE 22 #define PREAMBLE(state) 23 #define PREAMBLE_PARAM_X 24 #define PREAMBLE_PARAM_Y 25 #define PREAMBLE_ARG_X 26 #define PREAMBLE_ARG_Y 27#endif 28 29void SCALE_NOFILTER_NAME(const SkBitmapProcState& s, 30 uint32_t xy[], int count, int x, int y) { 31 SkASSERT((s.fInvType & ~(SkMatrix::kTranslate_Mask | 32 SkMatrix::kScale_Mask)) == 0); 33 34 PREAMBLE(s); 35 // we store y, x, x, x, x, x 36 37 const unsigned maxX = s.fBitmap->width() - 1; 38 SkFractionalInt fx; 39 { 40 SkPoint pt; 41 s.fInvProc(*s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf, 42 SkIntToScalar(y) + SK_ScalarHalf, &pt); 43 fx = SkScalarToFractionalInt(pt.fY); 44 const unsigned maxY = s.fBitmap->height() - 1; 45 *xy++ = TILEY_PROCF(SkFractionalIntToFixed(fx), maxY); 46 fx = SkScalarToFractionalInt(pt.fX); 47 } 48 49 if (0 == maxX) { 50 // all of the following X values must be 0 51 memset(xy, 0, count * sizeof(uint16_t)); 52 return; 53 } 54 55 const SkFractionalInt dx = s.fInvSxFractionalInt; 56 57#ifdef CHECK_FOR_DECAL 58 // test if we don't need to apply the tile proc 59 SkFixed tmpFx = SkFractionalIntToFixed(fx); 60 SkFixed tmpDx = SkFractionalIntToFixed(dx); 61 if ((unsigned)(tmpFx >> 16) <= maxX && 62 (unsigned)((tmpFx + tmpDx * (count - 1)) >> 16) <= maxX) { 63 decal_nofilter_scale(xy, tmpFx, tmpDx, count); 64 } else 65#endif 66 { 67 int i; 68 for (i = (count >> 2); i > 0; --i) { 69 unsigned a, b; 70 a = TILEX_PROCF(SkFractionalIntToFixed(fx), maxX); fx += dx; 71 b = TILEX_PROCF(SkFractionalIntToFixed(fx), maxX); fx += dx; 72#ifdef SK_CPU_BENDIAN 73 *xy++ = (a << 16) | b; 74#else 75 *xy++ = (b << 16) | a; 76#endif 77 a = TILEX_PROCF(SkFractionalIntToFixed(fx), maxX); fx += dx; 78 b = TILEX_PROCF(SkFractionalIntToFixed(fx), maxX); fx += dx; 79#ifdef SK_CPU_BENDIAN 80 *xy++ = (a << 16) | b; 81#else 82 *xy++ = (b << 16) | a; 83#endif 84 } 85 uint16_t* xx = (uint16_t*)xy; 86 for (i = (count & 3); i > 0; --i) { 87 *xx++ = TILEX_PROCF(SkFractionalIntToFixed(fx), maxX); fx += dx; 88 } 89 } 90} 91 92// note: we could special-case on a matrix which is skewed in X but not Y. 93// this would require a more general setup thatn SCALE does, but could use 94// SCALE's inner loop that only looks at dx 95 96void AFFINE_NOFILTER_NAME(const SkBitmapProcState& s, 97 uint32_t xy[], int count, int x, int y) { 98 SkASSERT(s.fInvType & SkMatrix::kAffine_Mask); 99 SkASSERT((s.fInvType & ~(SkMatrix::kTranslate_Mask | 100 SkMatrix::kScale_Mask | 101 SkMatrix::kAffine_Mask)) == 0); 102 103 PREAMBLE(s); 104 SkPoint srcPt; 105 s.fInvProc(*s.fInvMatrix, 106 SkIntToScalar(x) + SK_ScalarHalf, 107 SkIntToScalar(y) + SK_ScalarHalf, &srcPt); 108 109 SkFractionalInt fx = SkScalarToFractionalInt(srcPt.fX); 110 SkFractionalInt fy = SkScalarToFractionalInt(srcPt.fY); 111 SkFractionalInt dx = s.fInvSx; 112 SkFractionalInt dy = s.fInvKy; 113 int maxX = s.fBitmap->width() - 1; 114 int maxY = s.fBitmap->height() - 1; 115 116 for (int i = count; i > 0; --i) { 117 *xy++ = (TILEY_PROCF(SkFractionalIntToFixed(fx), maxY) << 16) | 118 TILEX_PROCF(SkFractionalIntToFixed(fx), maxX); 119 fx += dx; fy += dy; 120 } 121} 122 123void PERSP_NOFILTER_NAME(const SkBitmapProcState& s, 124 uint32_t* SK_RESTRICT xy, 125 int count, int x, int y) { 126 SkASSERT(s.fInvType & SkMatrix::kPerspective_Mask); 127 128 PREAMBLE(s); 129 int maxX = s.fBitmap->width() - 1; 130 int maxY = s.fBitmap->height() - 1; 131 132 SkPerspIter iter(*s.fInvMatrix, 133 SkIntToScalar(x) + SK_ScalarHalf, 134 SkIntToScalar(y) + SK_ScalarHalf, count); 135 136 while ((count = iter.next()) != 0) { 137 const SkFixed* SK_RESTRICT srcXY = iter.getXY(); 138 while (--count >= 0) { 139 *xy++ = (TILEY_PROCF(srcXY[1], maxY) << 16) | 140 TILEX_PROCF(srcXY[0], maxX); 141 srcXY += 2; 142 } 143 } 144} 145 146////////////////////////////////////////////////////////////////////////////// 147 148static inline uint32_t PACK_FILTER_Y_NAME(SkFixed f, unsigned max, 149 SkFixed one PREAMBLE_PARAM_Y) { 150 unsigned i = TILEY_PROCF(f, max); 151 i = (i << 4) | TILEY_LOW_BITS(f, max); 152 return (i << 14) | (TILEY_PROCF((f + one), max)); 153} 154 155static inline uint32_t PACK_FILTER_X_NAME(SkFixed f, unsigned max, 156 SkFixed one PREAMBLE_PARAM_X) { 157 unsigned i = TILEX_PROCF(f, max); 158 i = (i << 4) | TILEX_LOW_BITS(f, max); 159 return (i << 14) | (TILEX_PROCF((f + one), max)); 160} 161 162void SCALE_FILTER_NAME(const SkBitmapProcState& s, 163 uint32_t xy[], int count, int x, int y) { 164 SkASSERT((s.fInvType & ~(SkMatrix::kTranslate_Mask | 165 SkMatrix::kScale_Mask)) == 0); 166 SkASSERT(s.fInvKy == 0); 167 168 PREAMBLE(s); 169 170 const unsigned maxX = s.fBitmap->width() - 1; 171 const SkFixed one = s.fFilterOneX; 172 const SkFixed dx = s.fInvSx; 173 SkFixed fx; 174 175 { 176 SkPoint pt; 177 s.fInvProc(*s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf, 178 SkIntToScalar(y) + SK_ScalarHalf, &pt); 179 const SkFixed fy = SkScalarToFixed(pt.fY) - (s.fFilterOneY >> 1); 180 const unsigned maxY = s.fBitmap->height() - 1; 181 // compute our two Y values up front 182 *xy++ = PACK_FILTER_Y_NAME(fy, maxY, s.fFilterOneY PREAMBLE_ARG_Y); 183 // now initialize fx 184 fx = SkScalarToFixed(pt.fX) - (one >> 1); 185 } 186 187#ifdef CHECK_FOR_DECAL 188 // test if we don't need to apply the tile proc 189 if (dx > 0 && 190 (unsigned)(fx >> 16) <= maxX && 191 (unsigned)((fx + dx * (count - 1)) >> 16) < maxX) { 192 decal_filter_scale(xy, fx, dx, count); 193 } else 194#endif 195 { 196 do { 197 *xy++ = PACK_FILTER_X_NAME(fx, maxX, one PREAMBLE_ARG_X); 198 fx += dx; 199 } while (--count != 0); 200 } 201} 202 203void AFFINE_FILTER_NAME(const SkBitmapProcState& s, 204 uint32_t xy[], int count, int x, int y) { 205 SkASSERT(s.fInvType & SkMatrix::kAffine_Mask); 206 SkASSERT((s.fInvType & ~(SkMatrix::kTranslate_Mask | 207 SkMatrix::kScale_Mask | 208 SkMatrix::kAffine_Mask)) == 0); 209 210 PREAMBLE(s); 211 SkPoint srcPt; 212 s.fInvProc(*s.fInvMatrix, 213 SkIntToScalar(x) + SK_ScalarHalf, 214 SkIntToScalar(y) + SK_ScalarHalf, &srcPt); 215 216 SkFixed oneX = s.fFilterOneX; 217 SkFixed oneY = s.fFilterOneY; 218 SkFixed fx = SkScalarToFixed(srcPt.fX) - (oneX >> 1); 219 SkFixed fy = SkScalarToFixed(srcPt.fY) - (oneY >> 1); 220 SkFixed dx = s.fInvSx; 221 SkFixed dy = s.fInvKy; 222 unsigned maxX = s.fBitmap->width() - 1; 223 unsigned maxY = s.fBitmap->height() - 1; 224 225 do { 226 *xy++ = PACK_FILTER_Y_NAME(fy, maxY, oneY PREAMBLE_ARG_Y); 227 fy += dy; 228 *xy++ = PACK_FILTER_X_NAME(fx, maxX, oneX PREAMBLE_ARG_X); 229 fx += dx; 230 } while (--count != 0); 231} 232 233void PERSP_FILTER_NAME(const SkBitmapProcState& s, 234 uint32_t* SK_RESTRICT xy, int count, 235 int x, int y) { 236 SkASSERT(s.fInvType & SkMatrix::kPerspective_Mask); 237 238 PREAMBLE(s); 239 unsigned maxX = s.fBitmap->width() - 1; 240 unsigned maxY = s.fBitmap->height() - 1; 241 SkFixed oneX = s.fFilterOneX; 242 SkFixed oneY = s.fFilterOneY; 243 244 SkPerspIter iter(*s.fInvMatrix, 245 SkIntToScalar(x) + SK_ScalarHalf, 246 SkIntToScalar(y) + SK_ScalarHalf, count); 247 248 while ((count = iter.next()) != 0) { 249 const SkFixed* SK_RESTRICT srcXY = iter.getXY(); 250 do { 251 *xy++ = PACK_FILTER_Y_NAME(srcXY[1] - (oneY >> 1), maxY, 252 oneY PREAMBLE_ARG_Y); 253 *xy++ = PACK_FILTER_X_NAME(srcXY[0] - (oneX >> 1), maxX, 254 oneX PREAMBLE_ARG_X); 255 srcXY += 2; 256 } while (--count != 0); 257 } 258} 259 260static SkBitmapProcState::MatrixProc MAKENAME(_Procs)[] = { 261 SCALE_NOFILTER_NAME, 262 SCALE_FILTER_NAME, 263 AFFINE_NOFILTER_NAME, 264 AFFINE_FILTER_NAME, 265 PERSP_NOFILTER_NAME, 266 PERSP_FILTER_NAME 267}; 268 269#undef MAKENAME 270#undef TILEX_PROCF 271#undef TILEY_PROCF 272#ifdef CHECK_FOR_DECAL 273 #undef CHECK_FOR_DECAL 274#endif 275 276#undef SCALE_NOFILTER_NAME 277#undef SCALE_FILTER_NAME 278#undef AFFINE_NOFILTER_NAME 279#undef AFFINE_FILTER_NAME 280#undef PERSP_NOFILTER_NAME 281#undef PERSP_FILTER_NAME 282 283#undef PREAMBLE 284#undef PREAMBLE_PARAM_X 285#undef PREAMBLE_PARAM_Y 286#undef PREAMBLE_ARG_X 287#undef PREAMBLE_ARG_Y 288 289#undef TILEX_LOW_BITS 290#undef TILEY_LOW_BITS 291