• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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