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_FILTER_NAME       MAKENAME(_filter_scale)
13#define AFFINE_FILTER_NAME      MAKENAME(_filter_affine)
14#define PERSP_FILTER_NAME       MAKENAME(_filter_persp)
15
16#define PACK_FILTER_X_NAME  MAKENAME(_pack_filter_x)
17#define PACK_FILTER_Y_NAME  MAKENAME(_pack_filter_y)
18
19#ifndef PREAMBLE
20    #define PREAMBLE(state)
21    #define PREAMBLE_PARAM_X
22    #define PREAMBLE_PARAM_Y
23    #define PREAMBLE_ARG_X
24    #define PREAMBLE_ARG_Y
25#endif
26
27// declare functions externally to suppress warnings.
28void SCALE_FILTER_NAME(const SkBitmapProcState& s,
29                              uint32_t xy[], int count, int x, int y);
30void AFFINE_FILTER_NAME(const SkBitmapProcState& s,
31                               uint32_t xy[], int count, int x, int y);
32void PERSP_FILTER_NAME(const SkBitmapProcState& s,
33                              uint32_t* SK_RESTRICT xy, int count,
34                              int x, int y);
35
36static inline uint32_t PACK_FILTER_Y_NAME(SkFixed f, unsigned max,
37                                          SkFixed one PREAMBLE_PARAM_Y) {
38    unsigned i = TILEY_PROCF(f, max);
39    i = (i << 4) | TILEY_LOW_BITS(f, max);
40    return (i << 14) | (TILEY_PROCF((f + one), max));
41}
42
43static inline uint32_t PACK_FILTER_X_NAME(SkFixed f, unsigned max,
44                                          SkFixed one PREAMBLE_PARAM_X) {
45    unsigned i = TILEX_PROCF(f, max);
46    i = (i << 4) | TILEX_LOW_BITS(f, max);
47    return (i << 14) | (TILEX_PROCF((f + one), max));
48}
49
50void SCALE_FILTER_NAME(const SkBitmapProcState& s,
51                              uint32_t xy[], int count, int x, int y) {
52    SkASSERT((s.fInvType & ~(SkMatrix::kTranslate_Mask |
53                             SkMatrix::kScale_Mask)) == 0);
54    SkASSERT(s.fInvKy == 0);
55
56    PREAMBLE(s);
57
58    const unsigned maxX = s.fBitmap->width() - 1;
59    const SkFixed one = s.fFilterOneX;
60    const SkFractionalInt dx = s.fInvSxFractionalInt;
61    SkFractionalInt fx;
62
63    {
64        SkPoint pt;
65        s.fInvProc(s.fInvMatrix, SkIntToScalar(x) + SK_ScalarHalf,
66                                  SkIntToScalar(y) + SK_ScalarHalf, &pt);
67        const SkFixed fy = SkScalarToFixed(pt.fY) - (s.fFilterOneY >> 1);
68        const unsigned maxY = s.fBitmap->height() - 1;
69        // compute our two Y values up front
70        *xy++ = PACK_FILTER_Y_NAME(fy, maxY, s.fFilterOneY PREAMBLE_ARG_Y);
71        // now initialize fx
72        fx = SkScalarToFractionalInt(pt.fX) - (SkFixedToFractionalInt(one) >> 1);
73    }
74
75#ifdef CHECK_FOR_DECAL
76    if (can_truncate_to_fixed_for_decal(fx, dx, count, maxX)) {
77        decal_filter_scale(xy, SkFractionalIntToFixed(fx),
78                           SkFractionalIntToFixed(dx), count);
79    } else
80#endif
81    {
82        do {
83            SkFixed fixedFx = SkFractionalIntToFixed(fx);
84            *xy++ = PACK_FILTER_X_NAME(fixedFx, maxX, one PREAMBLE_ARG_X);
85            fx += dx;
86        } while (--count != 0);
87    }
88}
89
90void AFFINE_FILTER_NAME(const SkBitmapProcState& s,
91                               uint32_t xy[], int count, int x, int y) {
92    SkASSERT(s.fInvType & SkMatrix::kAffine_Mask);
93    SkASSERT((s.fInvType & ~(SkMatrix::kTranslate_Mask |
94                             SkMatrix::kScale_Mask |
95                             SkMatrix::kAffine_Mask)) == 0);
96
97    PREAMBLE(s);
98    SkPoint srcPt;
99    s.fInvProc(s.fInvMatrix,
100               SkIntToScalar(x) + SK_ScalarHalf,
101               SkIntToScalar(y) + SK_ScalarHalf, &srcPt);
102
103    SkFixed oneX = s.fFilterOneX;
104    SkFixed oneY = s.fFilterOneY;
105    SkFixed fx = SkScalarToFixed(srcPt.fX) - (oneX >> 1);
106    SkFixed fy = SkScalarToFixed(srcPt.fY) - (oneY >> 1);
107    SkFixed dx = s.fInvSx;
108    SkFixed dy = s.fInvKy;
109    unsigned maxX = s.fBitmap->width() - 1;
110    unsigned maxY = s.fBitmap->height() - 1;
111
112    do {
113        *xy++ = PACK_FILTER_Y_NAME(fy, maxY, oneY PREAMBLE_ARG_Y);
114        fy += dy;
115        *xy++ = PACK_FILTER_X_NAME(fx, maxX, oneX PREAMBLE_ARG_X);
116        fx += dx;
117    } while (--count != 0);
118}
119
120void PERSP_FILTER_NAME(const SkBitmapProcState& s,
121                              uint32_t* SK_RESTRICT xy, int count,
122                              int x, int y) {
123    SkASSERT(s.fInvType & SkMatrix::kPerspective_Mask);
124
125    PREAMBLE(s);
126    unsigned maxX = s.fBitmap->width() - 1;
127    unsigned maxY = s.fBitmap->height() - 1;
128    SkFixed oneX = s.fFilterOneX;
129    SkFixed oneY = s.fFilterOneY;
130
131    SkPerspIter   iter(s.fInvMatrix,
132                       SkIntToScalar(x) + SK_ScalarHalf,
133                       SkIntToScalar(y) + SK_ScalarHalf, count);
134
135    while ((count = iter.next()) != 0) {
136        const SkFixed* SK_RESTRICT srcXY = iter.getXY();
137        do {
138            *xy++ = PACK_FILTER_Y_NAME(srcXY[1] - (oneY >> 1), maxY,
139                                       oneY PREAMBLE_ARG_Y);
140            *xy++ = PACK_FILTER_X_NAME(srcXY[0] - (oneX >> 1), maxX,
141                                       oneX PREAMBLE_ARG_X);
142            srcXY += 2;
143        } while (--count != 0);
144    }
145}
146
147#undef MAKENAME
148#undef TILEX_PROCF
149#undef TILEY_PROCF
150#ifdef CHECK_FOR_DECAL
151    #undef CHECK_FOR_DECAL
152#endif
153
154#undef SCALE_FILTER_NAME
155#undef AFFINE_FILTER_NAME
156#undef PERSP_FILTER_NAME
157
158#undef PREAMBLE
159#undef PREAMBLE_PARAM_X
160#undef PREAMBLE_PARAM_Y
161#undef PREAMBLE_ARG_X
162#undef PREAMBLE_ARG_Y
163
164#undef TILEX_LOW_BITS
165#undef TILEY_LOW_BITS
166