[poppler] 3 commits - splash/SplashXPathScanner.cc splash/SplashXPathScanner.h

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Sun Oct 14 16:51:12 UTC 2018


 splash/SplashXPathScanner.cc |   53 +++++++++++++++++++++++--------------------
 splash/SplashXPathScanner.h  |    3 --
 2 files changed, 30 insertions(+), 26 deletions(-)

New commits:
commit a32fb958e48ced022a358b5933ae669923f81bb3
Author: Stefan Brüns <stefan.bruens at rwth-aachen.de>
Date:   Sun May 27 06:10:37 2018 +0200

    SplashXPathScanner: Force inlining of addIntersection
    
    The majority of the code in addIntersection can be optimized away for
    vertical (x0 == x1) and horizontal (count == 0) segments, thus the inlined
    code is less than the function call setup alone.
    This leaves diagonal segments as the only remaining call site, i.e.
    inlining here is a net win as well.
    
    Reduces runtime for #57 (fdo#96728, runsforever-poppler.pdf) from 1442 seconds
    to 1239 seconds (86%), and #24 (fdo#78728, surf-types.pdf) from ~ 5.0 seconds
    to 4.7 seconds.

diff --git a/splash/SplashXPathScanner.cc b/splash/SplashXPathScanner.cc
index 51cd2c91..9b6943dd 100644
--- a/splash/SplashXPathScanner.cc
+++ b/splash/SplashXPathScanner.cc
@@ -324,6 +324,7 @@ void SplashXPathScanner::computeIntersections() {
   }
 }
 
+inline
 GBool SplashXPathScanner::addIntersection(double segYMin, double segYMax,
 					 int y, int x0, int x1, int count) {
   SplashIntersect intersect;
commit 97f310b1c5e29e4c323a1688c20b2754e9b36adc
Author: Stefan Brüns <stefan.bruens at rwth-aachen.de>
Date:   Sun May 27 06:10:36 2018 +0200

    SplashXPathScanner: Move more invariant code out of the loop
    
    "seg->x0 - seg->y0 * seg->dxdy" is constant and can be moved out of the
    loop.
    The next start point is the old end point. Thus, only the new x coordinate
    has to clamped (segXMin <= xx1 <= segXMax), also do the 'floor' operation
    just once per loop.
    
    According to valgrind/callgrind, this reduces instruction count in
    computeIntersections() for #24 (fdo#78728) by 6%. No change for fdo#96728.

diff --git a/splash/SplashXPathScanner.cc b/splash/SplashXPathScanner.cc
index d1aedc73..51cd2c91 100644
--- a/splash/SplashXPathScanner.cc
+++ b/splash/SplashXPathScanner.cc
@@ -286,27 +286,33 @@ void SplashXPathScanner::computeIntersections() {
       if (y1 > yMax) {
 	y1 = yMax;
       }
-      // this loop could just add seg->dxdy to xx1 on each iteration,
-      // but that introduces numerical accuracy problems
-      xx1 = seg->x0 + ((SplashCoord)y0 - seg->y0) * seg->dxdy;
       int count = eo || (seg->flags & splashXPathFlip) ? 1 : -1;
+      // Calculate the projected intersection of the segment with the
+      // X-Axis.
+      SplashCoord xbase = seg->x0 - (seg->y0 * seg->dxdy);
+      xx0 = xbase + ((SplashCoord)y0) * seg->dxdy;
+      // the segment may not actually extend to the top and/or bottom edges
+      if (xx0 < segXMin) {
+	xx0 = segXMin;
+      } else if (xx0 > segXMax) {
+	xx0 = segXMax;
+      }
+      int x0 = splashFloor(xx0);
+
       for (y = y0; y <= y1; ++y) {
-	xx0 = xx1;
-	xx1 = seg->x0 + ((SplashCoord)(y + 1) - seg->y0) * seg->dxdy;
-	// the segment may not actually extend to the top and/or bottom edges
-	if (xx0 < segXMin) {
-	  xx0 = segXMin;
-	} else if (xx0 > segXMax) {
-	  xx0 = segXMax;
-	}
+	xx1 = xbase + ((SplashCoord)(y + 1) * seg->dxdy);
+
 	if (xx1 < segXMin) {
 	  xx1 = segXMin;
 	} else if (xx1 > segXMax) {
 	  xx1 = segXMax;
 	}
-	if (!addIntersection(segYMin, segYMax, y, splashFloor(xx0),
-                             splashFloor(xx1), count))
-          break;
+	int x1 = splashFloor(xx1);
+	if (!addIntersection(segYMin, segYMax, y, x0, x1, count))
+	  break;
+
+	xx0 = xx1;
+	x0 = x1;
       }
     }
   }
commit d8ba50c6638ad6720188c0c8237ffb5bbc3af490
Author: Stefan Brüns <stefan.bruens at rwth-aachen.de>
Date:   Sat May 26 21:34:49 2018 +0200

    SplashXPathScanner: Move invariant checks out of addIntersection loop
    
    For horizontal segments, count is always 0. For vertical/diagonal segments,
    the count depends on the winding rule (EvenOdd/NonZero) and the direction,
    but is constant for each segment.
    
    Reduces runtime for #57 (fdo#96728) from 1773 seconds to 1442 seconds (81%).

diff --git a/splash/SplashXPathScanner.cc b/splash/SplashXPathScanner.cc
index 6954a2c8..d1aedc73 100644
--- a/splash/SplashXPathScanner.cc
+++ b/splash/SplashXPathScanner.cc
@@ -251,8 +251,8 @@ void SplashXPathScanner::computeIntersections() {
     if (seg->flags & splashXPathHoriz) {
       y = splashFloor(seg->y0);
       if (y >= yMin && y <= yMax) {
-	if (!addIntersection(segYMin, segYMax, seg->flags,
-			y, splashFloor(seg->x0), splashFloor(seg->x1)))
+	if (!addIntersection(segYMin, segYMax, y, splashFloor(seg->x0),
+                             splashFloor(seg->x1), 0))
           break;
       }
     } else if (seg->flags & splashXPathVert) {
@@ -265,8 +265,9 @@ void SplashXPathScanner::computeIntersections() {
 	y1 = yMax;
       }
       x = splashFloor(seg->x0);
+      int count = eo || (seg->flags & splashXPathFlip) ? 1 : -1;
       for (y = y0; y <= y1; ++y) {
-	if (!addIntersection(segYMin, segYMax, seg->flags, y, x, x))
+	if (!addIntersection(segYMin, segYMax, y, x, x, count))
           break;
       }
     } else {
@@ -288,6 +289,7 @@ void SplashXPathScanner::computeIntersections() {
       // this loop could just add seg->dxdy to xx1 on each iteration,
       // but that introduces numerical accuracy problems
       xx1 = seg->x0 + ((SplashCoord)y0 - seg->y0) * seg->dxdy;
+      int count = eo || (seg->flags & splashXPathFlip) ? 1 : -1;
       for (y = y0; y <= y1; ++y) {
 	xx0 = xx1;
 	xx1 = seg->x0 + ((SplashCoord)(y + 1) - seg->y0) * seg->dxdy;
@@ -302,8 +304,8 @@ void SplashXPathScanner::computeIntersections() {
 	} else if (xx1 > segXMax) {
 	  xx1 = segXMax;
 	}
-	if (!addIntersection(segYMin, segYMax, seg->flags, y,
-			splashFloor(xx0), splashFloor(xx1)))
+	if (!addIntersection(segYMin, segYMax, y, splashFloor(xx0),
+                             splashFloor(xx1), count))
           break;
       }
     }
@@ -317,8 +319,7 @@ void SplashXPathScanner::computeIntersections() {
 }
 
 GBool SplashXPathScanner::addIntersection(double segYMin, double segYMax,
-					 Guint segFlags,
-					 int y, int x0, int x1) {
+					 int y, int x0, int x1, int count) {
   SplashIntersect intersect;
   intersect.y = y;
   if (x0 < x1) {
@@ -328,11 +329,8 @@ GBool SplashXPathScanner::addIntersection(double segYMin, double segYMax,
     intersect.x0 = x1;
     intersect.x1 = x0;
   }
-  if (segYMin <= y &&
-      (SplashCoord)y < segYMax &&
-      !(segFlags & splashXPathHoriz)) {
-    intersect.count = eo ? 1
-                         : (segFlags & splashXPathFlip) ? 1 : -1;
+  if (segYMin <= y && (SplashCoord)y < segYMax) {
+    intersect.count = count;
   } else {
     intersect.count = 0;
   }
diff --git a/splash/SplashXPathScanner.h b/splash/SplashXPathScanner.h
index 66aeb190..979d7786 100644
--- a/splash/SplashXPathScanner.h
+++ b/splash/SplashXPathScanner.h
@@ -86,8 +86,7 @@ private:
 
   void computeIntersections();
   GBool addIntersection(double segYMin, double segYMax,
-		       Guint segFlags,
-		       int y, int x0, int x1);
+		       int y, int x0, int x1, int count);
 
   SplashXPath *xPath;
   GBool eo;


More information about the poppler mailing list