summaryrefslogtreecommitdiff
path: root/splash/SplashMath.h
diff options
context:
space:
mode:
Diffstat (limited to 'splash/SplashMath.h')
-rw-r--r--splash/SplashMath.h93
1 files changed, 78 insertions, 15 deletions
diff --git a/splash/SplashMath.h b/splash/SplashMath.h
index 3b82e7a..4b7ab1f 100644
--- a/splash/SplashMath.h
+++ b/splash/SplashMath.h
@@ -2,6 +2,8 @@
//
// SplashMath.h
//
+// Copyright 2003-2013 Glyph & Cog, LLC
+//
//========================================================================
#ifndef SPLASHMATH_H
@@ -35,19 +37,18 @@ static inline int splashFloor(SplashCoord x) {
Gushort oldCW, newCW, t;
int result;
- __asm__ volatile("fldl %4\n"
- "fnstcw %0\n"
+ __asm__ volatile("fnstcw %0\n"
"movw %0, %3\n"
"andw $0xf3ff, %3\n"
"orw $0x0400, %3\n"
"movw %3, %1\n" // round down
"fldcw %1\n"
- "fistpl %2\n"
+ "fistl %2\n"
"fldcw %0\n"
: "=m" (oldCW), "=m" (newCW), "=m" (result), "=r" (t)
- : "m" (x));
+ : "t" (x));
return result;
-#elif defined(WIN32) && defined(_M_IX86)
+#elif defined(_WIN32) && defined(_M_IX86)
// floor() and (int)() are implemented separately, which results
// in changing the FPCW multiple times - so we optimize it with
// some inline assembly
@@ -81,19 +82,18 @@ static inline int splashCeil(SplashCoord x) {
Gushort oldCW, newCW, t;
int result;
- __asm__ volatile("fldl %4\n"
- "fnstcw %0\n"
+ __asm__ volatile("fnstcw %0\n"
"movw %0, %3\n"
"andw $0xf3ff, %3\n"
"orw $0x0800, %3\n"
"movw %3, %1\n" // round up
"fldcw %1\n"
- "fistpl %2\n"
+ "fistl %2\n"
"fldcw %0\n"
: "=m" (oldCW), "=m" (newCW), "=m" (result), "=r" (t)
- : "m" (x));
+ : "t" (x));
return result;
-#elif defined(WIN32) && defined(_M_IX86)
+#elif defined(_WIN32) && defined(_M_IX86)
// ceil() and (int)() are implemented separately, which results
// in changing the FPCW multiple times - so we optimize it with
// some inline assembly
@@ -128,19 +128,18 @@ static inline int splashRound(SplashCoord x) {
int result;
x += 0.5;
- __asm__ volatile("fldl %4\n"
- "fnstcw %0\n"
+ __asm__ volatile("fnstcw %0\n"
"movw %0, %3\n"
"andw $0xf3ff, %3\n"
"orw $0x0400, %3\n"
"movw %3, %1\n" // round down
"fldcw %1\n"
- "fistpl %2\n"
+ "fistl %2\n"
"fldcw %0\n"
: "=m" (oldCW), "=m" (newCW), "=m" (result), "=r" (t)
- : "m" (x));
+ : "t" (x));
return result;
-#elif defined(WIN32) && defined(_M_IX86)
+#elif defined(_WIN32) && defined(_M_IX86)
// this could use round-to-nearest mode and avoid the "+0.5",
// but that produces slightly different results (because i+0.5
// sometimes rounds up and sometimes down using the even rule)
@@ -223,4 +222,68 @@ static inline GBool splashCheckDet(SplashCoord m11, SplashCoord m12,
#endif
}
+// Perform stroke adjustment on a SplashCoord range [xMin, xMax),
+// resulting in an int range [*xMinI, *xMaxI).
+//
+// There are several options:
+//
+// 1. Round both edge coordinates.
+// Pro: adjacent strokes/fills line up without any gaps or
+// overlaps
+// Con: lines with the same original floating point width can
+// end up with different integer widths, e.g.:
+// xMin = 10.1 xMax = 11.3 (width = 1.2)
+// --> xMinI = 10 xMaxI = 11 (width = 1)
+// but
+// xMin = 10.4 xMax = 11.6 (width = 1.2)
+// --> xMinI = 10 xMaxI = 12 (width = 2)
+//
+// 2. Round the min coordinate; add the ceiling of the width.
+// Pro: lines with the same original floating point width will
+// always end up with the same integer width
+// Con: adjacent strokes/fills can have overlaps (which is
+// problematic with transparency)
+// (This could use floor on the min coordinate, instead of
+// rounding, with similar results.)
+// (If the width is rounded instead of using ceiling, the results
+// Are similar, except that adjacent strokes/fills can have gaps
+// as well as overlaps.)
+//
+// 3. Use floor on the min coordinate and ceiling on the max
+// coordinate.
+// Pro: lines always end up at least as wide as the original
+// floating point width
+// Con: adjacent strokes/fills can have overlaps, and lines with
+// the same original floating point width can end up with
+// different integer widths; the integer width can be more
+// than one pixel wider than the original width, e.g.:
+// xMin = 10.9 xMax = 12.1 (width = 1.2)
+// --> xMinI = 10 xMaxI = 13 (width = 3)
+// but
+// xMin = 10.1 xMax = 11.3 (width = 1.2)
+// --> xMinI = 10 xMaxI = 12 (width = 2)
+static inline void splashStrokeAdjust(SplashCoord xMin, SplashCoord xMax,
+ int *xMinI, int *xMaxI) {
+ int x0, x1;
+
+ // NB: enable exactly one of these.
+#if 1 // 1. Round both edge coordinates.
+ x0 = splashRound(xMin);
+ x1 = splashRound(xMax);
+#endif
+#if 0 // 2. Round the min coordinate; add the ceiling of the width.
+ x0 = splashRound(xMin);
+ x1 = x0 + splashCeil(xMax - xMin);
+#endif
+#if 0 // 3. Use floor on the min coord and ceiling on the max coord.
+ x0 = splashFloor(xMin);
+ x1 = splashCeil(xMax);
+#endif
+ if (x1 == x0) {
+ ++x1;
+ }
+ *xMinI = x0;
+ *xMaxI = x1;
+}
+
#endif