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