[poppler] Branch 'xpdf303merge' - goo/FixedPoint.cc goo/FixedPoint.h splash/Splash.cc splash/SplashFTFont.cc splash/SplashMath.h splash/SplashXPath.cc

Albert Astals Cid aacid at kemper.freedesktop.org
Tue Aug 30 07:40:39 PDT 2011


 goo/FixedPoint.cc      |   51 +++++++++++++++++++++++++++++++------------------
 goo/FixedPoint.h       |   15 ++++++++++++--
 splash/Splash.cc       |   12 +++++++++++
 splash/SplashFTFont.cc |   16 +++++++--------
 splash/SplashMath.h    |    8 ++++---
 splash/SplashXPath.cc  |    9 ++++++++
 6 files changed, 80 insertions(+), 31 deletions(-)

New commits:
commit faaba717046ba87ef5ded614e2bcab6260a9f7c2
Author: Albert Astals Cid <aacid at kde.org>
Date:   Tue Aug 30 16:36:24 2011 +0200

    xpdf303: FixedPoint improvements

diff --git a/goo/FixedPoint.cc b/goo/FixedPoint.cc
index 79a6a9a..26b2f0f 100644
--- a/goo/FixedPoint.cc
+++ b/goo/FixedPoint.cc
@@ -82,28 +82,32 @@ FixedPoint FixedPoint::pow(FixedPoint x, FixedPoint y) {
 }
 
 int FixedPoint::mul(int x, int y) {
-#if 1 //~tmp
-  return ((FixPtInt64)x * y) >> fixptShift;
-#else
-  int ah0, ah, bh, al, bl;
-  ah0 = x & fixptMaskH;
-  ah = x >> fixptShift;
-  al = x - ah0;
-  bh = y >> fixptShift;
-  bl = y - (bh << fixptShift);
-  return ah0 * bh + ah * bl + al * bh + ((al * bl) >> fixptShift);
-#endif
+  FixPtInt64 z;
+
+  z = ((FixPtInt64)x * y) >> fixptShift;
+  if (z > 0x7fffffffLL) {
+    return 0x7fffffff;
+  } else if (z < -0x80000000LL) {
+    return 0x80000000;
+  } else {
+    return (int)z;
+  }
 }
 
 int FixedPoint::div(int x, int y) {
-#if 1 //~tmp
-  return ((FixPtInt64)x << fixptShift) / y;
-#else
-#endif
+  FixPtInt64 z;
+
+  z = ((FixPtInt64)x << fixptShift) / y;
+  if (z > 0x7fffffffLL) {
+    return 0x7fffffff;
+  } else if (z < -0x80000000LL) {
+    return 0x80000000;
+  } else {
+    return (int)z;
+  }
 }
 
 GBool FixedPoint::divCheck(FixedPoint x, FixedPoint y, FixedPoint *result) {
-#if 1 //~tmp
   FixPtInt64 z;
 
   z = ((FixPtInt64)x.val << fixptShift) / y.val;
@@ -113,8 +117,19 @@ GBool FixedPoint::divCheck(FixedPoint x, FixedPoint y, FixedPoint *result) {
   }
   result->val = z;
   return gTrue;
-#else
-#endif
+}
+
+GBool FixedPoint::checkDet(FixedPoint m11, FixedPoint m12,
+                          FixedPoint m21, FixedPoint m22,
+                          FixedPoint epsilon) {
+  FixPtInt64 det, e;
+
+  det = (FixPtInt64)m11.val * (FixPtInt64)m22.val
+        - (FixPtInt64)m12.val * (FixPtInt64)m21.val;
+  e = (FixPtInt64)epsilon.val << fixptShift;
+  // NB: this comparison has to be >= not > because epsilon can be
+  // truncated to zero as a fixed point value.
+  return det >= e || det <= -e;
 }
 
 #endif // USE_FIXEDPOINT
diff --git a/goo/FixedPoint.h b/goo/FixedPoint.h
index 08936bc..afe21d9 100644
--- a/goo/FixedPoint.h
+++ b/goo/FixedPoint.h
@@ -45,7 +45,7 @@ public:
   operator int()
     { return val >> fixptShift; }
 
-  int getRaw() { return val; }
+  int get16Dot16() { return val; }
 
   FixedPoint operator =(FixedPoint x) { val = x.val; return *this; }
 
@@ -132,6 +132,11 @@ public:
   static int round(FixedPoint x)
     { return (x.val + (1 << (fixptShift - 1))) >> fixptShift; }
 
+  // Computes (x+y)/2 avoiding overflow and LSbit accuracy issues.
+  static FixedPoint avg(FixedPoint x, FixedPoint y)
+    { return make((x.val >> 1) + (y.val >> 1) + ((x.val | y.val) & 1)); }
+
+
   static FixedPoint sqrt(FixedPoint x);
 
   static FixedPoint pow(FixedPoint x, FixedPoint y);
@@ -140,6 +145,12 @@ public:
   // overflow.
   static GBool divCheck(FixedPoint x, FixedPoint y, FixedPoint *result);
 
+  // Compute abs(m11*m22 - m12*m21) >= epsilon, handling the case
+  // where the multiplications overflow.
+  static GBool checkDet(FixedPoint m11, FixedPoint m12,
+                       FixedPoint m21, FixedPoint m22,
+                       FixedPoint epsilon);
+
 private:
 
   static FixedPoint make(int valA) { FixedPoint x; x.val = valA; return x; }
@@ -147,7 +158,7 @@ private:
   static int mul(int x, int y);
   static int div(int x, int y);
 
-  int val;			// 16.16 fixed point
+  int val;                // fixed point: (n-fixptShift).(fixptShift)
 };
 
 #endif // USE_FIXEDPOINT
diff --git a/splash/Splash.cc b/splash/Splash.cc
index 9deec10..c385409 100644
--- a/splash/Splash.cc
+++ b/splash/Splash.cc
@@ -1397,7 +1397,11 @@ SplashPath *Splash::flattenPath(SplashPath *path, SplashCoord *matrix,
   int i;
 
   fPath = new SplashPath();
+#if USE_FIXEDPOINT
+  flatness2 = flatness;
+#else
   flatness2 = flatness * flatness;
+#endif
   i = 0;
   while (i < path->length) {
     flag = path->flags[i];
@@ -1462,13 +1466,21 @@ void Splash::flattenCurve(SplashCoord x0, SplashCoord y0,
     // line)
     transform(matrix, (xl0 + xr3) * 0.5, (yl0 + yr3) * 0.5, &mx, &my);
     transform(matrix, xx1, yy1, &tx, &ty);
+#if USE_FIXEDPOINT
+    d1 = splashDist(tx, ty, mx, my);
+#else
     dx = tx - mx;
     dy = ty - my;
     d1 = dx*dx + dy*dy;
+#endif
     transform(matrix, xx2, yy2, &tx, &ty);
+#if USE_FIXEDPOINT
+    d2 = splashDist(tx, ty, mx, my);
+#else
     dx = tx - mx;
     dy = ty - my;
     d2 = dx*dx + dy*dy;
+#endif
 
     // if the curve is flat enough, or no more subdivisions are
     // allowed, add the straight line segment
diff --git a/splash/SplashFTFont.cc b/splash/SplashFTFont.cc
index eea3d64..55a4957 100644
--- a/splash/SplashFTFont.cc
+++ b/splash/SplashFTFont.cc
@@ -146,14 +146,14 @@ SplashFTFont::SplashFTFont(SplashFTFontFile *fontFileA, SplashCoord *matA,
 
   // compute the transform matrix
 #if USE_FIXEDPOINT
-  matrix.xx = (FT_Fixed)((mat[0] / size).getRaw());
-  matrix.yx = (FT_Fixed)((mat[1] / size).getRaw());
-  matrix.xy = (FT_Fixed)((mat[2] / size).getRaw());
-  matrix.yy = (FT_Fixed)((mat[3] / size).getRaw());
-  textMatrix.xx = (FT_Fixed)((textMat[0] / (textScale * size)).getRaw());
-  textMatrix.yx = (FT_Fixed)((textMat[1] / (textScale * size)).getRaw());
-  textMatrix.xy = (FT_Fixed)((textMat[2] / (textScale * size)).getRaw());
-  textMatrix.yy = (FT_Fixed)((textMat[3] / (textScale * size)).getRaw());
+  matrix.xx = (FT_Fixed)((mat[0] / size).get16Dot16());
+  matrix.yx = (FT_Fixed)((mat[1] / size).get16Dot16());
+  matrix.xy = (FT_Fixed)((mat[2] / size).get16Dot16());
+  matrix.yy = (FT_Fixed)((mat[3] / size).get16Dot16());
+  textMatrix.xx = (FT_Fixed)((textMat[0] / (textScale * size)).get16Dot16());
+  textMatrix.yx = (FT_Fixed)((textMat[1] / (textScale * size)).get16Dot16());
+  textMatrix.xy = (FT_Fixed)((textMat[2] / (textScale * size)).get16Dot16());
+  textMatrix.yy = (FT_Fixed)((textMat[3] / (textScale * size)).get16Dot16());
 #else
   matrix.xx = (FT_Fixed)((mat[0] / size) * 65536);
   matrix.yx = (FT_Fixed)((mat[1] / size) * 65536);
diff --git a/splash/SplashMath.h b/splash/SplashMath.h
index 924af6a..272c90c 100644
--- a/splash/SplashMath.h
+++ b/splash/SplashMath.h
@@ -97,15 +97,17 @@ static inline SplashCoord splashDist(SplashCoord x0, SplashCoord y0,
 #if USE_FIXEDPOINT
   // this handles the situation where dx*dx or dy*dy is too large to
   // fit in the 16.16 fixed point format
-  SplashCoord dxa, dya;
+  SplashCoord dxa, dya, d;
   dxa = splashAbs(dx);
   dya = splashAbs(dy);
   if (dxa == 0 && dya == 0) {
     return 0;
   } else if (dxa > dya) {
-    return dxa * FixedPoint::sqrt(dya / dxa + 1);
+    d = dya / dxa;
+    return dxa * FixedPoint::sqrt(d*d + 1);
   } else {
-    return dya * FixedPoint::sqrt(dxa / dya + 1);
+    d = dxa / dya;
+    return dya * FixedPoint::sqrt(d*d + 1);
   }
 #else
   return splashSqrt(dx * dx + dy * dy);
diff --git a/splash/SplashXPath.cc b/splash/SplashXPath.cc
index 37d164d..c51c908 100644
--- a/splash/SplashXPath.cc
+++ b/splash/SplashXPath.cc
@@ -289,7 +289,11 @@ void SplashXPath::addCurve(SplashCoord x0, SplashCoord y0,
   SplashCoord dx, dy, mx, my, d1, d2, flatness2;
   int p1, p2, p3;
 
+#if USE_FIXEDPOINT
+  flatness2 = flatness;
+#else
   flatness2 = flatness * flatness;
+#endif
 
   // initial segment
   p1 = 0;
@@ -315,12 +319,17 @@ void SplashXPath::addCurve(SplashCoord x0, SplashCoord y0,
     // line)
     mx = (xl0 + xr3) * 0.5;
     my = (yl0 + yr3) * 0.5;
+#if USE_FIXEDPOINT
+    d1 = splashDist(xx1, yy1, mx, my);
+    d2 = splashDist(xx2, yy2, mx, my);
+#else
     dx = xx1 - mx;
     dy = yy1 - my;
     d1 = dx*dx + dy*dy;
     dx = xx2 - mx;
     dy = yy2 - my;
     d2 = dx*dx + dy*dy;
+#endif    
 
     // if the curve is flat enough, or no more subdivisions are
     // allowed, add the straight line segment


More information about the poppler mailing list