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