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.
31 void SCALE_NOFILTER_NAME(const SkBitmapProcState& s,
32 uint32_t xy[], int count, int x, int y);
33 void AFFINE_NOFILTER_NAME(const SkBitmapProcState& s,
34 uint32_t xy[], int count, int x, int y);
35 void PERSP_NOFILTER_NAME(const SkBitmapProcState& s,
36 uint32_t* SK_RESTRICT xy,
37 int count, int x, int y);
38 void SCALE_FILTER_NAME(const SkBitmapProcState& s,
39 uint32_t xy[], int count, int x, int y);
40 void AFFINE_FILTER_NAME(const SkBitmapProcState& s,
41 uint32_t xy[], int count, int x, int y);
42 void PERSP_FILTER_NAME(const SkBitmapProcState& s,
43 uint32_t* SK_RESTRICT xy, int count,
44 int x, int y);
45
SCALE_NOFILTER_NAME(const SkBitmapProcState & s,uint32_t xy[],int count,int x,int y)46 void 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
AFFINE_NOFILTER_NAME(const SkBitmapProcState & s,uint32_t xy[],int count,int x,int y)110 void 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
PERSP_NOFILTER_NAME(const SkBitmapProcState & s,uint32_t * SK_RESTRICT xy,int count,int x,int y)137 void 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
PACK_FILTER_Y_NAME(SkFixed f,unsigned max,SkFixed one PREAMBLE_PARAM_Y)162 static 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
PACK_FILTER_X_NAME(SkFixed f,unsigned max,SkFixed one PREAMBLE_PARAM_X)169 static 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
SCALE_FILTER_NAME(const SkBitmapProcState & s,uint32_t xy[],int count,int x,int y)176 void 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
AFFINE_FILTER_NAME(const SkBitmapProcState & s,uint32_t xy[],int count,int x,int y)216 void 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
PERSP_FILTER_NAME(const SkBitmapProcState & s,uint32_t * SK_RESTRICT xy,int count,int x,int y)246 void 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
273 static 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