[poppler] poppler/CairoOutputDev.cc poppler/CairoOutputDev.h poppler/Gfx.cc poppler/OutputDev.h poppler/PSOutputDev.cc poppler/PSOutputDev.h

Carlos Garcia Campos carlosgc at kemper.freedesktop.org
Fri Jul 31 09:26:05 PDT 2009


 poppler/CairoOutputDev.cc |   28 +++++++++
 poppler/CairoOutputDev.h  |    2 
 poppler/Gfx.cc            |  141 +++++++++++++++++++++++++++-------------------
 poppler/OutputDev.h       |    2 
 poppler/PSOutputDev.cc    |    3 
 poppler/PSOutputDev.h     |    2 
 6 files changed, 117 insertions(+), 61 deletions(-)

New commits:
commit 53c3d636ad645a350b576160e1498726238a7bd1
Author: Carlos Garcia Campos <carlosgc at gnome.org>
Date:   Fri Jul 31 18:23:57 2009 +0200

    [cairo] Implement radialShadedFill in cairo backend using cairo gradients
    
    Fixes bugs #10942, #14160

diff --git a/poppler/CairoOutputDev.cc b/poppler/CairoOutputDev.cc
index 89335f8..e86ee12 100644
--- a/poppler/CairoOutputDev.cc
+++ b/poppler/CairoOutputDev.cc
@@ -683,6 +683,34 @@ GBool CairoOutputDev::axialShadedSupportExtend(GfxState *state, GfxAxialShading
   return (shading->getExtend0() == shading->getExtend1());
 }
 
+GBool CairoOutputDev::radialShadedFill(GfxState *state, GfxRadialShading *shading, double sMin, double sMax) {
+  double x0, y0, r0, x1, y1, r1;
+  double dx, dy, dr;
+
+  shading->getCoords(&x0, &y0, &r0, &x1, &y1, &r1);
+  dx = x1 - x0;
+  dy = y1 - y0;
+  dr = r1 - r0;
+  cairo_pattern_destroy(fill_pattern);
+  fill_pattern = cairo_pattern_create_radial (x0 + sMin * dx,
+					      y0 + sMin * dy,
+					      r0 + sMin * dr,
+					      x0 + sMax * dx,
+					      y0 + sMax * dy,
+					      r0 + sMax * dr);
+  if (shading->getExtend0() && shading->getExtend1())
+    cairo_pattern_set_extend (fill_pattern, CAIRO_EXTEND_PAD);
+  else
+    cairo_pattern_set_extend (fill_pattern, CAIRO_EXTEND_NONE);
+
+  return gFalse;
+}
+
+GBool CairoOutputDev::radialShadedSupportExtend(GfxState *state, GfxRadialShading *shading)
+{
+  return (shading->getExtend0() == shading->getExtend1());
+}
+
 void CairoOutputDev::clip(GfxState *state) {
   doPath (cairo, state, state->getPath());
   cairo_set_fill_rule (cairo, CAIRO_FILL_RULE_WINDING);
diff --git a/poppler/CairoOutputDev.h b/poppler/CairoOutputDev.h
index f2bcb55..071c171 100644
--- a/poppler/CairoOutputDev.h
+++ b/poppler/CairoOutputDev.h
@@ -153,6 +153,8 @@ public:
   virtual void eoFill(GfxState *state);
   virtual GBool axialShadedFill(GfxState *state, GfxAxialShading *shading, double tMin, double tMax);
   virtual GBool axialShadedSupportExtend(GfxState *state, GfxAxialShading *shading);
+  virtual GBool radialShadedFill(GfxState *state, GfxRadialShading *shading, double sMin, double sMax);
+  virtual GBool radialShadedSupportExtend(GfxState *state, GfxRadialShading *shading);
 
   //----- path clipping
   virtual void clip(GfxState *state);
diff --git a/poppler/Gfx.cc b/poppler/Gfx.cc
index 4b8ff35..e71a0dd 100644
--- a/poppler/Gfx.cc
+++ b/poppler/Gfx.cc
@@ -2652,11 +2652,7 @@ void Gfx::doRadialShFill(GfxRadialShading *shading) {
   int ia, ib, k, n;
   double *ctm;
   double theta, alpha, angle, t;
-
-  if (out->useShadedFills() &&
-      out->radialShadedFill(state, shading)) {
-    return;
-  }
+  GBool needExtend = gTrue;
 
   // get the shading info
   shading->getCoords(&x0, &y0, &r0, &x1, &y1, &r1);
@@ -2753,6 +2749,11 @@ void Gfx::doRadialShFill(GfxRadialShading *shading) {
     }
   }
 
+  if (out->useShadedFills() &&
+      out->radialShadedFill(state, shading, sMin, sMax)) {
+    return;
+  }
+
   // compute the number of steps into which circles must be divided to
   // achieve a curve flatness of 0.1 pixel in device space for the
   // largest circle (note that "device space" is 72 dpi when generating
@@ -2799,6 +2800,8 @@ void Gfx::doRadialShFill(GfxRadialShading *shading) {
     shading->getColor(ta, &colorA);
   }
 
+  needExtend = !out->radialShadedSupportExtend(state, shading);
+
   // fill the circles
   while (ia < radialMaxSplits) {
 
@@ -2849,63 +2852,67 @@ void Gfx::doRadialShFill(GfxRadialShading *shading) {
       colorA.c[k] = (colorA.c[k] + colorB.c[k]) / 2;
     }
     state->setFillColor(&colorA);
-    out->updateFillColor(state);
-
-    if (enclosed) {
-
-      // construct path for first circle (counterclockwise)
-      state->moveTo(xa + ra, ya);
-      for (k = 1; k < n; ++k) {
-	angle = ((double)k / (double)n) * 2 * M_PI;
-	state->lineTo(xa + ra * cos(angle), ya + ra * sin(angle));
-      }
-      state->closePath();
-
-      // construct and append path for second circle (clockwise)
-      state->moveTo(xb + rb, yb);
-      for (k = 1; k < n; ++k) {
-	angle = -((double)k / (double)n) * 2 * M_PI;
-	state->lineTo(xb + rb * cos(angle), yb + rb * sin(angle));
-      }
-      state->closePath();
-
-    } else {
+    if (out->useFillColorStop())
+      out->updateFillColorStop(state, (sa - sMin)/(sMax - sMin));
+    else
+      out->updateFillColor(state);
 
-      // construct the first subpath (clockwise)
-      state->moveTo(xa + ra * cos(alpha + theta + 0.5 * M_PI),
-		    ya + ra * sin(alpha + theta + 0.5 * M_PI));
-      for (k = 0; k < n; ++k) {
-	angle = alpha + theta + 0.5 * M_PI
-	  - ((double)k / (double)n) * (2 * theta + M_PI);
-	state->lineTo(xb + rb * cos(angle), yb + rb * sin(angle));
-      }
-      for (k = 0; k < n; ++k) {
-	angle = alpha - theta - 0.5 * M_PI
-	  + ((double)k / (double)n) * (2 * theta - M_PI);
-	state->lineTo(xa + ra * cos(angle), ya + ra * sin(angle));
-      }
-      state->closePath();
+    if (needExtend) {
+      if (enclosed) {
+        // construct path for first circle (counterclockwise)
+        state->moveTo(xa + ra, ya);
+        for (k = 1; k < n; ++k) {
+	  angle = ((double)k / (double)n) * 2 * M_PI;
+	  state->lineTo(xa + ra * cos(angle), ya + ra * sin(angle));
+        }
+        state->closePath();
 
-      // construct the second subpath (counterclockwise)
-      state->moveTo(xa + ra * cos(alpha + theta + 0.5 * M_PI),
-		    ya + ra * sin(alpha + theta + 0.5 * M_PI));
-      for (k = 0; k < n; ++k) {
-	angle = alpha + theta + 0.5 * M_PI
-	        + ((double)k / (double)n) * (-2 * theta + M_PI);
-	state->lineTo(xb + rb * cos(angle), yb + rb * sin(angle));
-      }
-      for (k = 0; k < n; ++k) {
-	angle = alpha - theta - 0.5 * M_PI
-	        + ((double)k / (double)n) * (2 * theta + M_PI);
-	state->lineTo(xa + ra * cos(angle), ya + ra * sin(angle));
+        // construct and append path for second circle (clockwise)
+        state->moveTo(xb + rb, yb);
+        for (k = 1; k < n; ++k) {
+	  angle = -((double)k / (double)n) * 2 * M_PI;
+	  state->lineTo(xb + rb * cos(angle), yb + rb * sin(angle));
+        }
+        state->closePath();
+      } else {
+        // construct the first subpath (clockwise)
+        state->moveTo(xa + ra * cos(alpha + theta + 0.5 * M_PI),
+		      ya + ra * sin(alpha + theta + 0.5 * M_PI));
+        for (k = 0; k < n; ++k) {
+	  angle = alpha + theta + 0.5 * M_PI
+		  - ((double)k / (double)n) * (2 * theta + M_PI);
+	  state->lineTo(xb + rb * cos(angle), yb + rb * sin(angle));
+        }
+	for (k = 0; k < n; ++k) {
+	  angle = alpha - theta - 0.5 * M_PI
+		  + ((double)k / (double)n) * (2 * theta - M_PI);
+	  state->lineTo(xa + ra * cos(angle), ya + ra * sin(angle));
+	}
+	state->closePath();
+
+        // construct the second subpath (counterclockwise)
+	state->moveTo(xa + ra * cos(alpha + theta + 0.5 * M_PI),
+		      ya + ra * sin(alpha + theta + 0.5 * M_PI));
+	for (k = 0; k < n; ++k) {
+	  angle = alpha + theta + 0.5 * M_PI
+		  + ((double)k / (double)n) * (-2 * theta + M_PI);
+	  state->lineTo(xb + rb * cos(angle), yb + rb * sin(angle));
+	}
+	for (k = 0; k < n; ++k) {
+	  angle = alpha - theta - 0.5 * M_PI
+		  + ((double)k / (double)n) * (2 * theta + M_PI);
+	  state->lineTo(xa + ra * cos(angle), ya + ra * sin(angle));
+	}
+	state->closePath();
       }
-      state->closePath();
     }
 
-    // fill the path
-    if (!contentIsHidden())
-      out->fill(state);
-    state->clearPath();
+    if (!out->useFillColorStop()) {
+      // fill the path
+      if (!contentIsHidden())
+        out->fill(state);
+      state->clearPath();
+    }
 
     // step to the next value of t
     ia = ib;
@@ -2917,6 +2924,26 @@ void Gfx::doRadialShFill(GfxRadialShading *shading) {
     colorA = colorB;
   }
 
+  if (out->useFillColorStop()) {
+    // make sure we add stop color when sb = sMax
+    state->setFillColor(&colorA);
+    out->updateFillColorStop(state, (sb - sMin)/(sMax - sMin));
+
+    // fill the path
+    state->moveTo(xMin, yMin);
+    state->lineTo(xMin, yMax);
+    state->lineTo(xMax, yMax);
+    state->lineTo(xMax, yMin);
+    state->closePath();
+
+    if (!contentIsHidden())
+      out->fill(state);
+    state->clearPath();
+  }
+
+  if (!needExtend)
+    return;
+
   if (enclosed) {
     // extend the smaller circle
     if ((shading->getExtend0() && r0 <= r1) ||
diff --git a/poppler/OutputDev.h b/poppler/OutputDev.h
index d1cb2b0..d7fb10f 100644
--- a/poppler/OutputDev.h
+++ b/poppler/OutputDev.h
@@ -201,7 +201,7 @@ public:
     { return gFalse; }
   virtual GBool axialShadedSupportExtend(GfxState * /*state*/, GfxAxialShading * /*shading*/)
     { return gFalse; }
-  virtual GBool radialShadedFill(GfxState * /*state*/, GfxRadialShading * /*shading*/)
+  virtual GBool radialShadedFill(GfxState * /*state*/, GfxRadialShading * /*shading*/, double /*sMin*/, double /*sMax*/)
     { return gFalse; }
   virtual GBool radialShadedSupportExtend(GfxState * /*state*/, GfxRadialShading * /*shading*/)
     { return gFalse; }
diff --git a/poppler/PSOutputDev.cc b/poppler/PSOutputDev.cc
index 779c5c5..9c72294 100644
--- a/poppler/PSOutputDev.cc
+++ b/poppler/PSOutputDev.cc
@@ -3944,8 +3944,7 @@ GBool PSOutputDev::axialShadedFill(GfxState *state, GfxAxialShading *shading, do
   return gTrue;
 }
 
-GBool PSOutputDev::radialShadedFill(GfxState *state,
-				    GfxRadialShading *shading) {
+GBool PSOutputDev::radialShadedFill(GfxState *state, GfxRadialShading *shading, double /*sMin*/, double /*sMax*/) {
   double xMin, yMin, xMax, yMax;
   double x0, y0, r0, x1, y1, r1, t0, t1;
   double xa, ya, ra;
diff --git a/poppler/PSOutputDev.h b/poppler/PSOutputDev.h
index be4763d..5fc3edd 100644
--- a/poppler/PSOutputDev.h
+++ b/poppler/PSOutputDev.h
@@ -216,7 +216,7 @@ public:
   virtual GBool functionShadedFill(GfxState *state,
 				   GfxFunctionShading *shading);
   virtual GBool axialShadedFill(GfxState *state, GfxAxialShading *shading, double /*tMin*/, double /*tMax*/);
-  virtual GBool radialShadedFill(GfxState *state, GfxRadialShading *shading);
+  virtual GBool radialShadedFill(GfxState *state, GfxRadialShading *shading, double /*sMin*/, double /*sMax*/);
 
   //----- path clipping
   virtual void clip(GfxState *state);


More information about the poppler mailing list