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