[poppler] poppler/Gfx.cc

Albert Astals Cid aacid at kemper.freedesktop.org
Fri Apr 17 12:05:16 PDT 2009


 poppler/Gfx.cc |  102 ++++++++++++++++++++++++++++++++++-----------------------
 1 file changed, 62 insertions(+), 40 deletions(-)

New commits:
commit b760debea03380280d72cd39d792cbc1a380a87c
Author: Albert Astals Cid <aacid at kde.org>
Date:   Fri Apr 17 21:04:26 2009 +0200

    Fix rendering of axial shadings
    
    Fixes bug #19896

diff --git a/poppler/Gfx.cc b/poppler/Gfx.cc
index 61bd046..0eef5d3 100644
--- a/poppler/Gfx.cc
+++ b/poppler/Gfx.cc
@@ -2263,12 +2263,28 @@ void Gfx::doFunctionShFill1(GfxFunctionShading *shading,
   }
 }
 
+static void bubbleSort(double array[])
+{
+  for (int j = 0; j < 3; ++j) {
+    int kk = j;
+    for (int k = j + 1; k < 4; ++k) {
+      if (array[k] < array[kk]) {
+        kk = k;
+      }
+    }
+    double tmp = array[j];
+    array[j] = array[kk];
+    array[kk] = tmp;
+  }
+}
+
 void Gfx::doAxialShFill(GfxAxialShading *shading) {
   double xMin, yMin, xMax, yMax;
   double x0, y0, x1, y1;
   double dx, dy, mul;
   GBool dxZero, dyZero;
-  double tMin, tMax, t, tx, ty;
+  double bboxIntersections[4];
+  double tMin, tMax, tx, ty;
   double s[4], sMin, sMax, tmp;
   double ux0, uy0, ux1, uy1, vx0, vy0, vx1, vy1;
   double t0, t1, tt;
@@ -2276,7 +2292,7 @@ void Gfx::doAxialShFill(GfxAxialShading *shading) {
   int next[axialMaxSplits + 1];
   GfxColor color0, color1;
   int nComps;
-  int i, j, k, kk;
+  int i, j, k;
 
   if (out->useShadedFills() &&
       out->axialShadedFill(state, shading)) {
@@ -2297,25 +2313,13 @@ void Gfx::doAxialShFill(GfxAxialShading *shading) {
     tMin = tMax = 0;
   } else {
     mul = 1 / (dx * dx + dy * dy);
-    tMin = tMax = ((xMin - x0) * dx + (yMin - y0) * dy) * mul;
-    t = ((xMin - x0) * dx + (yMax - y0) * dy) * mul;
-    if (t < tMin) {
-      tMin = t;
-    } else if (t > tMax) {
-      tMax = t;
-    }
-    t = ((xMax - x0) * dx + (yMin - y0) * dy) * mul;
-    if (t < tMin) {
-      tMin = t;
-    } else if (t > tMax) {
-      tMax = t;
-    }
-    t = ((xMax - x0) * dx + (yMax - y0) * dy) * mul;
-    if (t < tMin) {
-      tMin = t;
-    } else if (t > tMax) {
-      tMax = t;
-    }
+    bboxIntersections[0] = ((xMin - x0) * dx + (yMin - y0) * dy) * mul;
+    bboxIntersections[1] = ((xMin - x0) * dx + (yMax - y0) * dy) * mul;
+    bboxIntersections[2] = ((xMax - x0) * dx + (yMin - y0) * dy) * mul;
+    bboxIntersections[3] = ((xMax - x0) * dx + (yMax - y0) * dy) * mul;
+    bubbleSort(bboxIntersections);
+    tMin = bboxIntersections[0];
+    tMax = bboxIntersections[3];
     if (tMin < 0 && !shading->getExtend0()) {
       tMin = 0;
     }
@@ -2396,15 +2400,7 @@ void Gfx::doAxialShFill(GfxAxialShading *shading) {
     s[1] = (yMax - ty) / dx;
     s[2] = (xMin - tx) / -dy;
     s[3] = (xMax - tx) / -dy;
-    for (j = 0; j < 3; ++j) {
-      kk = j;
-      for (k = j + 1; k < 4; ++k) {
-	if (s[k] < s[kk]) {
-	  kk = k;
-	}
-      }
-      tmp = s[j]; s[j] = s[kk]; s[kk] = tmp;
-    }
+    bubbleSort(s);
     sMin = s[1];
     sMax = s[2];
   }
@@ -2414,6 +2410,13 @@ void Gfx::doAxialShFill(GfxAxialShading *shading) {
   vy0 = ty + sMax * dx;
 
   i = 0;
+  bool doneBBox1, doneBBox2;
+  if (dxZero && dyZero) {
+    doneBBox1 = doneBBox2 = true;
+  } else {
+    doneBBox1 = bboxIntersections[1] < tMin;
+    doneBBox2 = bboxIntersections[2] > tMax;
+  }
   while (i < axialMaxSplits) {
 
     // bisect until color difference is small enough or we hit the
@@ -2434,7 +2437,34 @@ void Gfx::doAxialShFill(GfxAxialShading *shading) {
 	}
       }
       if (k == nComps) {
-	break;
+         // in these two if what we guarantee is that if we are skipping lots of 
+         // positions because the colors are the same, we still create a region
+         // with vertexs passing by bboxIntersections[1] and bboxIntersections[2]
+         // otherwise we can have empty regions that should really be painted 
+         // like happened in bug 19896
+         // What we do to ensure that we pass a line through this points
+         // is making sure use the exact bboxIntersections[] value as one of the used ta[] values
+         if (!doneBBox1 && ta[i] < bboxIntersections[1] && ta[j] > bboxIntersections[1]) {
+           int teoricalj = (bboxIntersections[1] - tMin) * axialMaxSplits / (tMax - tMin);
+           if (teoricalj <= i) teoricalj = i + 1;
+           if (j == teoricalj) j = teoricalj + 1;
+           next[i] = teoricalj;
+           next[teoricalj] = j;
+           ta[teoricalj] = bboxIntersections[1];
+           j = teoricalj;
+           doneBBox1 = true;
+         }
+         if (!doneBBox2 && ta[i] < bboxIntersections[2] && ta[j] > bboxIntersections[2]) {
+           int teoricalj = (bboxIntersections[2] - tMin) * axialMaxSplits / (tMax - tMin);
+           if (teoricalj <= i) teoricalj = i + 1;
+           if (j == teoricalj) j = teoricalj + 1;
+           next[i] = teoricalj;
+           next[teoricalj] = j;
+           ta[teoricalj] = bboxIntersections[2];
+           j = teoricalj;
+           doneBBox2 = true;
+         }
+        break;
       }
       k = (i + j) / 2;
       ta[k] = 0.5 * (ta[i] + ta[j]);
@@ -2468,15 +2498,7 @@ void Gfx::doAxialShFill(GfxAxialShading *shading) {
       s[1] = (yMax - ty) / dx;
       s[2] = (xMin - tx) / -dy;
       s[3] = (xMax - tx) / -dy;
-      for (j = 0; j < 3; ++j) {
-	kk = j;
-	for (k = j + 1; k < 4; ++k) {
-	  if (s[k] < s[kk]) {
-	    kk = k;
-	  }
-	}
-	tmp = s[j]; s[j] = s[kk]; s[kk] = tmp;
-      }
+      bubbleSort(s);
       sMin = s[1];
       sMax = s[2];
     }


More information about the poppler mailing list