beta-0.89.2
[luatex.git] / source / libs / poppler / poppler-src / splash / SplashMath.h
blobca73c2bd1f3169ed854d2a97da8008ca3168e68b
1 //========================================================================
2 //
3 // SplashMath.h
4 //
5 //========================================================================
7 //========================================================================
8 //
9 // Modified under the Poppler project - http://poppler.freedesktop.org
11 // All changes made under the Poppler project to this file are licensed
12 // under GPL version 2 or later
14 // Copyright (C) 2009-2011 Albert Astals Cid <aacid@kde.org>
16 // To see a description of the changes please see the Changelog file that
17 // came with your tarball or type make ChangeLog if you are building from git
19 //========================================================================
21 #ifndef SPLASHMATH_H
22 #define SPLASHMATH_H
24 #include "poppler-config.h"
26 #if USE_FIXEDPOINT
27 #include "goo/FixedPoint.h"
28 #else
29 #include <math.h>
30 #endif
31 #include "SplashTypes.h"
33 static inline SplashCoord splashAbs(SplashCoord x) {
34 #if USE_FIXEDPOINT
35 return FixedPoint::abs(x);
36 #elif USE_FLOAT
37 return fabsf(x);
38 #else
39 return fabs(x);
40 #endif
43 static inline int splashFloor(SplashCoord x) {
44 #if USE_FIXEDPOINT
45 return FixedPoint::floor(x);
46 #elif USE_FLOAT
47 return (int)floorf(x);
48 #elif __GNUC__ && __i386__
49 // floor() and (int)() are implemented separately, which results
50 // in changing the FPCW multiple times - so we optimize it with
51 // some inline assembly
52 Gushort oldCW, newCW, t;
53 int result;
55 __asm__ volatile("fldl %4\n"
56 "fnstcw %0\n"
57 "movw %0, %3\n"
58 "andw $0xf3ff, %3\n"
59 "orw $0x0400, %3\n"
60 "movw %3, %1\n" // round down
61 "fldcw %1\n"
62 "fistpl %2\n"
63 "fldcw %0\n"
64 : "=m" (oldCW), "=m" (newCW), "=m" (result), "=r" (t)
65 : "m" (x));
66 return result;
67 #elif defined(WIN32) && defined(_M_IX86)
68 // floor() and (int)() are implemented separately, which results
69 // in changing the FPCW multiple times - so we optimize it with
70 // some inline assembly
71 Gushort oldCW, newCW;
72 int result;
74 __asm fld QWORD PTR x
75 __asm fnstcw WORD PTR oldCW
76 __asm mov ax, WORD PTR oldCW
77 __asm and ax, 0xf3ff
78 __asm or ax, 0x0400
79 __asm mov WORD PTR newCW, ax // round down
80 __asm fldcw WORD PTR newCW
81 __asm fistp DWORD PTR result
82 __asm fldcw WORD PTR oldCW
83 return result;
84 #else
85 if (x > 0) return (int)x;
86 else return (int)floor(x);
87 #endif
90 static inline int splashCeil(SplashCoord x) {
91 #if USE_FIXEDPOINT
92 return FixedPoint::ceil(x);
93 #elif USE_FLOAT
94 return (int)ceilf(x);
95 #elif __GNUC__ && __i386__
96 // ceil() and (int)() are implemented separately, which results
97 // in changing the FPCW multiple times - so we optimize it with
98 // some inline assembly
99 Gushort oldCW, newCW, t;
100 int result;
102 __asm__ volatile("fldl %4\n"
103 "fnstcw %0\n"
104 "movw %0, %3\n"
105 "andw $0xf3ff, %3\n"
106 "orw $0x0800, %3\n"
107 "movw %3, %1\n" // round up
108 "fldcw %1\n"
109 "fistpl %2\n"
110 "fldcw %0\n"
111 : "=m" (oldCW), "=m" (newCW), "=m" (result), "=r" (t)
112 : "m" (x));
113 return result;
114 #elif defined(WIN32) && defined(_M_IX86)
115 // ceil() and (int)() are implemented separately, which results
116 // in changing the FPCW multiple times - so we optimize it with
117 // some inline assembly
118 Gushort oldCW, newCW;
119 int result;
121 __asm fld QWORD PTR x
122 __asm fnstcw WORD PTR oldCW
123 __asm mov ax, WORD PTR oldCW
124 __asm and ax, 0xf3ff
125 __asm or ax, 0x0800
126 __asm mov WORD PTR newCW, ax // round up
127 __asm fldcw WORD PTR newCW
128 __asm fistp DWORD PTR result
129 __asm fldcw WORD PTR oldCW
130 return result;
131 #else
132 return (int)ceil(x);
133 #endif
136 static inline int splashRound(SplashCoord x) {
137 #if USE_FIXEDPOINT
138 return FixedPoint::round(x);
139 #elif __GNUC__ && __i386__
140 // this could use round-to-nearest mode and avoid the "+0.5",
141 // but that produces slightly different results (because i+0.5
142 // sometimes rounds up and sometimes down using the even rule)
143 Gushort oldCW, newCW, t;
144 int result;
146 x += 0.5;
147 __asm__ volatile("fldl %4\n"
148 "fnstcw %0\n"
149 "movw %0, %3\n"
150 "andw $0xf3ff, %3\n"
151 "orw $0x0400, %3\n"
152 "movw %3, %1\n" // round down
153 "fldcw %1\n"
154 "fistpl %2\n"
155 "fldcw %0\n"
156 : "=m" (oldCW), "=m" (newCW), "=m" (result), "=r" (t)
157 : "m" (x));
158 return result;
159 #elif defined(WIN32) && defined(_M_IX86)
160 // this could use round-to-nearest mode and avoid the "+0.5",
161 // but that produces slightly different results (because i+0.5
162 // sometimes rounds up and sometimes down using the even rule)
163 Gushort oldCW, newCW;
164 int result;
166 x += 0.5;
167 __asm fld QWORD PTR x
168 __asm fnstcw WORD PTR oldCW
169 __asm mov ax, WORD PTR oldCW
170 __asm and ax, 0xf3ff
171 __asm or ax, 0x0400
172 __asm mov WORD PTR newCW, ax // round down
173 __asm fldcw WORD PTR newCW
174 __asm fistp DWORD PTR result
175 __asm fldcw WORD PTR oldCW
176 return result;
177 #else
178 return (int)splashFloor(x + 0.5);
179 #endif
182 static inline SplashCoord splashAvg(SplashCoord x, SplashCoord y) {
183 #if USE_FIXEDPOINT
184 return FixedPoint::avg(x, y);
185 #else
186 return 0.5 * (x + y);
187 #endif
190 static inline SplashCoord splashSqrt(SplashCoord x) {
191 #if USE_FIXEDPOINT
192 return FixedPoint::sqrt(x);
193 #elif USE_FLOAT
194 return sqrtf(x);
195 #else
196 return sqrt(x);
197 #endif
200 static inline SplashCoord splashPow(SplashCoord x, SplashCoord y) {
201 #if USE_FIXEDPOINT
202 return FixedPoint::pow(x, y);
203 #elif USE_FLOAT
204 return powf(x, y);
205 #else
206 return pow(x, y);
207 #endif
210 static inline SplashCoord splashDist(SplashCoord x0, SplashCoord y0,
211 SplashCoord x1, SplashCoord y1) {
212 SplashCoord dx, dy;
213 dx = x1 - x0;
214 dy = y1 - y0;
215 #if USE_FIXEDPOINT
216 // this handles the situation where dx*dx or dy*dy is too large to
217 // fit in the 16.16 fixed point format
218 SplashCoord dxa, dya, d;
219 dxa = splashAbs(dx);
220 dya = splashAbs(dy);
221 if (dxa == 0 && dya == 0) {
222 return 0;
223 } else if (dxa > dya) {
224 d = dya / dxa;
225 return dxa * FixedPoint::sqrt(d*d + 1);
226 } else {
227 d = dxa / dya;
228 return dya * FixedPoint::sqrt(d*d + 1);
230 #else
231 return splashSqrt(dx * dx + dy * dy);
232 #endif
235 static inline GBool splashCheckDet(SplashCoord m11, SplashCoord m12,
236 SplashCoord m21, SplashCoord m22,
237 SplashCoord epsilon) {
238 #if USE_FIXEDPOINT
239 return FixedPoint::checkDet(m11, m12, m21, m22, epsilon);
240 #else
241 return fabs(m11 * m22 - m12 * m21) >= epsilon;
242 #endif
245 #endif