1 //========================================================================
5 //========================================================================
7 //========================================================================
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 //========================================================================
24 #include "poppler-config.h"
27 #include "goo/FixedPoint.h"
31 #include "SplashTypes.h"
33 static inline SplashCoord
splashAbs(SplashCoord x
) {
35 return FixedPoint::abs(x
);
43 static inline int splashFloor(SplashCoord x
) {
45 return FixedPoint::floor(x
);
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
;
55 __asm__
volatile("fldl %4\n"
60 "movw %3, %1\n" // round down
64 : "=m" (oldCW
), "=m" (newCW
), "=m" (result
), "=r" (t
)
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
75 __asm fnstcw WORD PTR oldCW
76 __asm mov ax
, WORD PTR oldCW
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
85 if (x
> 0) return (int)x
;
86 else return (int)floor(x
);
90 static inline int splashCeil(SplashCoord x
) {
92 return FixedPoint::ceil(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
;
102 __asm__
volatile("fldl %4\n"
107 "movw %3, %1\n" // round up
111 : "=m" (oldCW
), "=m" (newCW
), "=m" (result
), "=r" (t
)
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
;
121 __asm fld QWORD PTR x
122 __asm fnstcw WORD PTR oldCW
123 __asm mov ax
, WORD PTR oldCW
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
136 static inline int splashRound(SplashCoord x
) {
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
;
147 __asm__
volatile("fldl %4\n"
152 "movw %3, %1\n" // round down
156 : "=m" (oldCW
), "=m" (newCW
), "=m" (result
), "=r" (t
)
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
;
167 __asm fld QWORD PTR x
168 __asm fnstcw WORD PTR oldCW
169 __asm mov ax
, WORD PTR oldCW
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
178 return (int)splashFloor(x
+ 0.5);
182 static inline SplashCoord
splashAvg(SplashCoord x
, SplashCoord y
) {
184 return FixedPoint::avg(x
, y
);
186 return 0.5 * (x
+ y
);
190 static inline SplashCoord
splashSqrt(SplashCoord x
) {
192 return FixedPoint::sqrt(x
);
200 static inline SplashCoord
splashPow(SplashCoord x
, SplashCoord y
) {
202 return FixedPoint::pow(x
, y
);
210 static inline SplashCoord
splashDist(SplashCoord x0
, SplashCoord y0
,
211 SplashCoord x1
, SplashCoord y1
) {
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
;
221 if (dxa
== 0 && dya
== 0) {
223 } else if (dxa
> dya
) {
225 return dxa
* FixedPoint::sqrt(d
*d
+ 1);
228 return dya
* FixedPoint::sqrt(d
*d
+ 1);
231 return splashSqrt(dx
* dx
+ dy
* dy
);
235 static inline GBool
splashCheckDet(SplashCoord m11
, SplashCoord m12
,
236 SplashCoord m21
, SplashCoord m22
,
237 SplashCoord epsilon
) {
239 return FixedPoint::checkDet(m11
, m12
, m21
, m22
, epsilon
);
241 return fabs(m11
* m22
- m12
* m21
) >= epsilon
;