[poppler] [PATCH 6/6] SplashXPathScanner: Move invariant checks out of addIntersection loop

Stefan BrĂ¼ns stefan.bruens at rwth-aachen.de
Sat May 26 19:34:49 UTC 2018


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 fdo#96728 from 1773 seconds to 1442 seconds (81%).
---
This is labeled Patch 6/6 as it goes on top of the previous 5 patches.

 splash/SplashXPathScanner.cc | 22 ++++++++++------------
 splash/SplashXPathScanner.h  |  3 +--
 2 files changed, 11 insertions(+), 14 deletions(-)

diff --git a/splash/SplashXPathScanner.cc b/splash/SplashXPathScanner.cc
index 7107586d..ee370817 100644
--- a/splash/SplashXPathScanner.cc
+++ b/splash/SplashXPathScanner.cc
@@ -250,8 +250,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) {
@@ -264,8 +264,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 {
@@ -287,6 +288,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;
@@ -301,8 +303,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;
       }
     }
@@ -316,8 +318,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) {
@@ -327,11 +328,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 7405dbd8..2a64aa31 100644
--- a/splash/SplashXPathScanner.h
+++ b/splash/SplashXPathScanner.h
@@ -102,8 +102,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;
-- 
2.16.3



More information about the poppler mailing list