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