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