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.
28 void SCALE_FILTER_NAME(const SkBitmapProcState& s,
29 uint32_t xy[], int count, int x, int y);
30 void AFFINE_FILTER_NAME(const SkBitmapProcState& s,
31 uint32_t xy[], int count, int x, int y);
32 void PERSP_FILTER_NAME(const SkBitmapProcState& s,
33 uint32_t* SK_RESTRICT xy, int count,
34 int x, int y);
35
PACK_FILTER_Y_NAME(SkFixed f,unsigned max,SkFixed one PREAMBLE_PARAM_Y)36 static 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
PACK_FILTER_X_NAME(SkFixed f,unsigned max,SkFixed one PREAMBLE_PARAM_X)43 static 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
SCALE_FILTER_NAME(const SkBitmapProcState & s,uint32_t xy[],int count,int x,int y)50 void 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
AFFINE_FILTER_NAME(const SkBitmapProcState & s,uint32_t xy[],int count,int x,int y)90 void 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
PERSP_FILTER_NAME(const SkBitmapProcState & s,uint32_t * SK_RESTRICT xy,int count,int x,int y)120 void 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