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 0 : void SCALE_NOFILTER_NAME(const SkBitmapProcState& s,
31 : uint32_t xy[], int count, int x, int y) {
32 0 : SkASSERT((s.fInvType & ~(SkMatrix::kTranslate_Mask |
33 : SkMatrix::kScale_Mask)) == 0);
34 :
35 0 : PREAMBLE(s);
36 : // we store y, x, x, x, x, x
37 :
38 0 : const unsigned maxX = s.fBitmap->width() - 1;
39 : SkFixed fx;
40 : {
41 : SkPoint pt;
42 0 : s.fInvProc(*s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf,
43 0 : SkIntToScalar(y) + SK_ScalarHalf, &pt);
44 0 : fx = SkScalarToFixed(pt.fY);
45 0 : const unsigned maxY = s.fBitmap->height() - 1;
46 0 : *xy++ = TILEY_PROCF(fx, maxY);
47 0 : fx = SkScalarToFixed(pt.fX);
48 : }
49 :
50 0 : if (0 == maxX) {
51 : // all of the following X values must be 0
52 0 : memset(xy, 0, count * sizeof(uint16_t));
53 0 : return;
54 : }
55 :
56 0 : const SkFixed dx = s.fInvSx;
57 :
58 : #ifdef CHECK_FOR_DECAL
59 : // test if we don't need to apply the tile proc
60 0 : if ((unsigned)(fx >> 16) <= maxX &&
61 : (unsigned)((fx + dx * (count - 1)) >> 16) <= maxX) {
62 0 : decal_nofilter_scale(xy, fx, dx, count);
63 : } else
64 : #endif
65 : {
66 : int i;
67 0 : for (i = (count >> 2); i > 0; --i) {
68 : unsigned a, b;
69 0 : a = TILEX_PROCF(fx, maxX); fx += dx;
70 0 : b = TILEX_PROCF(fx, maxX); fx += dx;
71 : #ifdef SK_CPU_BENDIAN
72 : *xy++ = (a << 16) | b;
73 : #else
74 0 : *xy++ = (b << 16) | a;
75 : #endif
76 0 : a = TILEX_PROCF(fx, maxX); fx += dx;
77 0 : b = TILEX_PROCF(fx, maxX); fx += dx;
78 : #ifdef SK_CPU_BENDIAN
79 : *xy++ = (a << 16) | b;
80 : #else
81 0 : *xy++ = (b << 16) | a;
82 : #endif
83 : }
84 0 : uint16_t* xx = (uint16_t*)xy;
85 0 : for (i = (count & 3); i > 0; --i) {
86 0 : *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 0 : void AFFINE_NOFILTER_NAME(const SkBitmapProcState& s,
96 : uint32_t xy[], int count, int x, int y) {
97 0 : SkASSERT(s.fInvType & SkMatrix::kAffine_Mask);
98 0 : SkASSERT((s.fInvType & ~(SkMatrix::kTranslate_Mask |
99 : SkMatrix::kScale_Mask |
100 : SkMatrix::kAffine_Mask)) == 0);
101 :
102 0 : PREAMBLE(s);
103 : SkPoint srcPt;
104 : s.fInvProc(*s.fInvMatrix,
105 0 : SkIntToScalar(x) + SK_ScalarHalf,
106 0 : SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
107 :
108 0 : SkFixed fx = SkScalarToFixed(srcPt.fX);
109 0 : SkFixed fy = SkScalarToFixed(srcPt.fY);
110 0 : SkFixed dx = s.fInvSx;
111 0 : SkFixed dy = s.fInvKy;
112 0 : int maxX = s.fBitmap->width() - 1;
113 0 : int maxY = s.fBitmap->height() - 1;
114 :
115 0 : for (int i = count; i > 0; --i) {
116 0 : *xy++ = (TILEY_PROCF(fy, maxY) << 16) | TILEX_PROCF(fx, maxX);
117 0 : fx += dx; fy += dy;
118 : }
119 0 : }
120 :
121 0 : void PERSP_NOFILTER_NAME(const SkBitmapProcState& s,
122 : uint32_t* SK_RESTRICT xy,
123 : int count, int x, int y) {
124 0 : SkASSERT(s.fInvType & SkMatrix::kPerspective_Mask);
125 :
126 0 : PREAMBLE(s);
127 0 : int maxX = s.fBitmap->width() - 1;
128 0 : int maxY = s.fBitmap->height() - 1;
129 :
130 : SkPerspIter iter(*s.fInvMatrix,
131 0 : SkIntToScalar(x) + SK_ScalarHalf,
132 0 : SkIntToScalar(y) + SK_ScalarHalf, count);
133 :
134 0 : while ((count = iter.next()) != 0) {
135 0 : const SkFixed* SK_RESTRICT srcXY = iter.getXY();
136 0 : while (--count >= 0) {
137 0 : *xy++ = (TILEY_PROCF(srcXY[1], maxY) << 16) |
138 0 : TILEX_PROCF(srcXY[0], maxX);
139 0 : srcXY += 2;
140 : }
141 : }
142 0 : }
143 :
144 : //////////////////////////////////////////////////////////////////////////////
145 :
146 0 : static inline uint32_t PACK_FILTER_Y_NAME(SkFixed f, unsigned max,
147 : SkFixed one PREAMBLE_PARAM_Y) {
148 0 : unsigned i = TILEY_PROCF(f, max);
149 0 : i = (i << 4) | TILEY_LOW_BITS(f, max);
150 0 : return (i << 14) | (TILEY_PROCF((f + one), max));
151 : }
152 :
153 0 : static inline uint32_t PACK_FILTER_X_NAME(SkFixed f, unsigned max,
154 : SkFixed one PREAMBLE_PARAM_X) {
155 0 : unsigned i = TILEX_PROCF(f, max);
156 0 : i = (i << 4) | TILEX_LOW_BITS(f, max);
157 0 : return (i << 14) | (TILEX_PROCF((f + one), max));
158 : }
159 :
160 0 : void SCALE_FILTER_NAME(const SkBitmapProcState& s,
161 : uint32_t xy[], int count, int x, int y) {
162 0 : SkASSERT((s.fInvType & ~(SkMatrix::kTranslate_Mask |
163 : SkMatrix::kScale_Mask)) == 0);
164 0 : SkASSERT(s.fInvKy == 0);
165 :
166 0 : PREAMBLE(s);
167 :
168 0 : const unsigned maxX = s.fBitmap->width() - 1;
169 0 : const SkFixed one = s.fFilterOneX;
170 0 : const SkFixed dx = s.fInvSx;
171 : SkFixed fx;
172 :
173 : {
174 : SkPoint pt;
175 0 : s.fInvProc(*s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf,
176 0 : SkIntToScalar(y) + SK_ScalarHalf, &pt);
177 0 : const SkFixed fy = SkScalarToFixed(pt.fY) - (s.fFilterOneY >> 1);
178 0 : const unsigned maxY = s.fBitmap->height() - 1;
179 : // compute our two Y values up front
180 0 : *xy++ = PACK_FILTER_Y_NAME(fy, maxY, s.fFilterOneY PREAMBLE_ARG_Y);
181 : // now initialize fx
182 0 : 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 0 : if (dx > 0 &&
188 : (unsigned)(fx >> 16) <= maxX &&
189 : (unsigned)((fx + dx * (count - 1)) >> 16) < maxX) {
190 0 : decal_filter_scale(xy, fx, dx, count);
191 : } else
192 : #endif
193 : {
194 0 : do {
195 0 : *xy++ = PACK_FILTER_X_NAME(fx, maxX, one PREAMBLE_ARG_X);
196 0 : fx += dx;
197 : } while (--count != 0);
198 : }
199 0 : }
200 :
201 0 : void AFFINE_FILTER_NAME(const SkBitmapProcState& s,
202 : uint32_t xy[], int count, int x, int y) {
203 0 : SkASSERT(s.fInvType & SkMatrix::kAffine_Mask);
204 0 : SkASSERT((s.fInvType & ~(SkMatrix::kTranslate_Mask |
205 : SkMatrix::kScale_Mask |
206 : SkMatrix::kAffine_Mask)) == 0);
207 :
208 0 : PREAMBLE(s);
209 : SkPoint srcPt;
210 : s.fInvProc(*s.fInvMatrix,
211 0 : SkIntToScalar(x) + SK_ScalarHalf,
212 0 : SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
213 :
214 0 : SkFixed oneX = s.fFilterOneX;
215 0 : SkFixed oneY = s.fFilterOneY;
216 0 : SkFixed fx = SkScalarToFixed(srcPt.fX) - (oneX >> 1);
217 0 : SkFixed fy = SkScalarToFixed(srcPt.fY) - (oneY >> 1);
218 0 : SkFixed dx = s.fInvSx;
219 0 : SkFixed dy = s.fInvKy;
220 0 : unsigned maxX = s.fBitmap->width() - 1;
221 0 : unsigned maxY = s.fBitmap->height() - 1;
222 :
223 0 : do {
224 0 : *xy++ = PACK_FILTER_Y_NAME(fy, maxY, oneY PREAMBLE_ARG_Y);
225 0 : fy += dy;
226 0 : *xy++ = PACK_FILTER_X_NAME(fx, maxX, oneX PREAMBLE_ARG_X);
227 0 : fx += dx;
228 : } while (--count != 0);
229 0 : }
230 :
231 0 : void PERSP_FILTER_NAME(const SkBitmapProcState& s,
232 : uint32_t* SK_RESTRICT xy, int count,
233 : int x, int y) {
234 0 : SkASSERT(s.fInvType & SkMatrix::kPerspective_Mask);
235 :
236 0 : PREAMBLE(s);
237 0 : unsigned maxX = s.fBitmap->width() - 1;
238 0 : unsigned maxY = s.fBitmap->height() - 1;
239 0 : SkFixed oneX = s.fFilterOneX;
240 0 : SkFixed oneY = s.fFilterOneY;
241 :
242 : SkPerspIter iter(*s.fInvMatrix,
243 0 : SkIntToScalar(x) + SK_ScalarHalf,
244 0 : SkIntToScalar(y) + SK_ScalarHalf, count);
245 :
246 0 : while ((count = iter.next()) != 0) {
247 0 : const SkFixed* SK_RESTRICT srcXY = iter.getXY();
248 0 : do {
249 0 : *xy++ = PACK_FILTER_Y_NAME(srcXY[1] - (oneY >> 1), maxY,
250 0 : oneY PREAMBLE_ARG_Y);
251 0 : *xy++ = PACK_FILTER_X_NAME(srcXY[0] - (oneX >> 1), maxX,
252 0 : oneX PREAMBLE_ARG_X);
253 0 : srcXY += 2;
254 : } while (--count != 0);
255 : }
256 0 : }
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
|