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