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
SCALE_NOFILTER_NAME(const SkBitmapProcState & s,uint32_t xy[],int count,int x,int y)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
AFFINE_NOFILTER_NAME(const SkBitmapProcState & s,uint32_t xy[],int count,int x,int y)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
PERSP_NOFILTER_NAME(const SkBitmapProcState & s,uint32_t * SK_RESTRICT xy,int count,int x,int y)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
PACK_FILTER_Y_NAME(SkFixed f,unsigned max,SkFixed one PREAMBLE_PARAM_Y)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
PACK_FILTER_X_NAME(SkFixed f,unsigned max,SkFixed one PREAMBLE_PARAM_X)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
SCALE_FILTER_NAME(const SkBitmapProcState & s,uint32_t xy[],int count,int x,int y)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
AFFINE_FILTER_NAME(const SkBitmapProcState & s,uint32_t xy[],int count,int x,int y)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
PERSP_FILTER_NAME(const SkBitmapProcState & s,uint32_t * SK_RESTRICT xy,int count,int x,int y)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