diff --git a/poppler/SplashOutputDev.cc b/poppler/SplashOutputDev.cc
index 0b3722a..e19cb13 100644
--- a/poppler/SplashOutputDev.cc
+++ b/poppler/SplashOutputDev.cc
@@ -153,6 +153,838 @@ void SplashGouraudPattern::getParameterizedColor(double colorinterp, SplashColor
 }
 
 //------------------------------------------------------------------------
+// SplashRadialPattern
+//------------------------------------------------------------------------
+// Min number of splits along the t axis for a radial shading fill.
+#define radialMinSplits 256
+
+// Max number of splits along the t axis for a radial shading fill.
+#define radialMaxSplits 32768
+
+// Max delta allowed in any color component for a radial shading fill.
+#define radialColorDelta (dblToCol(1.0 / 256.0))
+
+// Max size of pattern bitmap of min (width, height)
+#define radialMaxSize 256
+
+// the value, so that the smallest circle whose 
+// distance to the desired (degenerate) circle within the
+// bounding box does not exceed tolerance.
+#define radialTolerance DBL_EPSILON //0.5
+
+#ifndef DBL_EPSILON
+#define DBL_EPSILON	2.2204460492503131e-16
+#endif
+
+#undef MIN
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+
+#undef MAX
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+
+// test if radial pattern is considered degenerate
+// adapted from  cairo _radial_pattern_is_degenerate
+static GBool
+radialPatternIsDegenerate (GfxRadialShading *shading)
+{
+    double x0, y0, r0, x1, y1, r1;
+	shading->getCoords(&x0, &y0, &r0, &x1, &y1, &r1);
+
+    /* A radial pattern is considered degenerate if it can be
+     * represented as a solid or clear pattern.  This corresponds to
+     * one of the two cases:
+     *
+     * 1) The radii are both very small:
+     *      |dr| < DBL_EPSILON && min (r0, r1) < DBL_EPSILON
+     *
+     * 2) The two circles have about the same radius and are very
+     *    close to each other (approximately a cylinder gradient that
+     *    doesn't move with the parameter):
+     *      |dr| < DBL_EPSILON && max (|dx|, |dy|) < 2 * DBL_EPSILON
+     *
+     * These checks are consistent with the assumptions used in
+     * _cairo_radial_pattern_box_to_parameter ().
+     */
+
+    return fabs (r0 - r1) < DBL_EPSILON &&
+	(MIN (r0, r1) < DBL_EPSILON ||
+	 MAX (fabs (x0 - x1),
+	      fabs (y0 - y1)) < 2 * DBL_EPSILON);
+}
+
+// extend range, adapted from cairo, radialExtendRange
+static GBool
+radialExtendRange (double range[2], double value, GBool valid)
+{
+    if (!valid)
+	range[0] = range[1] = value;
+    else if (value < range[0])
+	range[0] = value;
+    else if (value > range[1])
+	range[1] = value;
+
+    return gTrue;
+}
+
+// calculate extended range, adapted from cairo, _cairo_radial_pattern_box_to_parameter
+static void
+radialGetMaxExtends (GfxRadialShading *shading,
+					double xMin, double yMin,
+					double xMax, double yMax,
+					double tolerance,
+					double range[2])
+{
+    double cx, cy, cr, dx, dy, dr;
+    double a, x_focus, y_focus;
+    double mindr, minx, miny, maxx, maxy;
+    GBool valid;
+    double x0, y0, r0, x1, y1, r1;
+
+	shading->getCoords(&x0, &y0, &r0, &x1, &y1, &r1);
+    if (radialPatternIsDegenerate(shading))
+		return; 
+    assert (tolerance > 0);
+    assert (xMin < xMax);
+    assert (yMin < yMax);
+
+    range[0] = range[1] = 0;
+    valid = FALSE;
+
+    x_focus = y_focus = 0; /* silence gcc */
+
+    cx = x0;
+    cy = y0;
+    cr = r0;
+    dx = x1 - cx;
+    dy = y1 - cy;
+    dr = r1 - cr;
+
+    /* translate by -(cx, cy) to simplify computations */
+    xMin -= cx;
+    yMin -= cy;
+    xMax -= cx;
+    yMax -= cy;
+
+    /* enlarge boundaries slightly to avoid rounding problems in the
+     * parameter range computation */
+    xMin -= DBL_EPSILON;
+    yMin -= DBL_EPSILON;
+    xMax += DBL_EPSILON;
+    yMax += DBL_EPSILON;
+
+    /* enlarge boundaries even more to avoid rounding problems when
+     * testing if a point belongs to the box */
+    minx = xMin - DBL_EPSILON;
+    miny = yMin - DBL_EPSILON;
+    maxx = xMax + DBL_EPSILON;
+    maxy = yMax + DBL_EPSILON;
+
+    /* we dont' allow negative radiuses, so we will be checking that
+     * t*dr >= mindr to consider t valid */
+    mindr = -(cr + DBL_EPSILON);
+
+    /*
+     * After the previous transformations, the start circle is
+     * centered in the origin and has radius cr. A 1-unit change in
+     * the t parameter corresponds to dx,dy,dr changes in the x,y,r of
+     * the circle (center coordinates, radius).
+     *
+     * To compute the minimum range needed to correctly draw the
+     * pattern, we start with an empty range and extend it to include
+     * the circles touching the bounding box or within it.
+     */
+
+    /*
+     * Focus, the point where the circle has radius == 0.
+     *
+     * r = cr + t * dr = 0
+     * t = -cr / dr
+     *
+     * If the radius is constant (dr == 0) there is no focus (the
+     * gradient represents a cylinder instead of a cone).
+     */
+    if (fabs (dr) >= DBL_EPSILON) {
+	double t_focus;
+
+	t_focus = -cr / dr;
+	x_focus = t_focus * dx;
+	y_focus = t_focus * dy;
+	if (minx <= x_focus && x_focus <= maxx &&
+	    miny <= y_focus && y_focus <= maxy)
+	{
+	    valid = radialExtendRange (range, t_focus, valid);
+	}
+    }
+
+    /*
+     * Circles externally tangent to box edges.
+     *
+     * All circles have center in (dx, dy) * t
+     *
+     * If the circle is tangent to the line defined by the edge of the
+     * box, then at least one of the following holds true:
+     *
+     *   (dx*t) + (cr + dr*t) == x0 (left   edge)
+     *   (dx*t) - (cr + dr*t) == x1 (right  edge)
+     *   (dy*t) + (cr + dr*t) == y0 (top    edge)
+     *   (dy*t) - (cr + dr*t) == y1 (bottom edge)
+     *
+     * The solution is only valid if the tangent point is actually on
+     * the edge, i.e. if its y coordinate is in [y0,y1] for left/right
+     * edges and if its x coordinate is in [x0,x1] for top/bottom
+     * edges.
+     *
+     * For the first equation:
+     *
+     *   (dx + dr) * t = x0 - cr
+     *   t = (x0 - cr) / (dx + dr)
+     *   y = dy * t
+     *
+     * in the code this becomes:
+     *
+     *   t_edge = (num) / (den)
+     *   v = (delta) * t_edge
+     *
+     * If the denominator in t is 0, the pattern is tangent to a line
+     * parallel to the edge under examination. The corner-case where
+     * the boundary line is the same as the edge is handled by the
+     * focus point case and/or by the a==0 case.
+     */
+#define T_EDGE(num,den,delta,lower,upper)				\
+    if (fabs (den) >= DBL_EPSILON) {					\
+	double t_edge, v;						\
+									\
+	t_edge = (num) / (den);						\
+	v = t_edge * (delta);						\
+	if (t_edge * dr >= mindr && (lower) <= v && v <= (upper))	\
+	    valid = radialExtendRange (range, t_edge, valid);		\
+    }
+
+    /* circles tangent (externally) to left/right/top/bottom edge */
+    T_EDGE (xMin - cr, dx + dr, dy, miny, maxy);
+    T_EDGE (xMax + cr, dx - dr, dy, miny, maxy);
+    T_EDGE (yMin - cr, dy + dr, dx, minx, maxx);
+    T_EDGE (yMax + cr, dy - dr, dx, minx, maxx);
+
+#undef T_EDGE
+
+    /*
+     * Circles passing through a corner.
+     *
+     * A circle passing through the point (x,y) satisfies:
+     *
+     * (x-t*dx)^2 + (y-t*dy)^2 == (cr + t*dr)^2
+     *
+     * If we set:
+     *   a = dx^2 + dy^2 - dr^2
+     *   b = x*dx + y*dy + cr*dr
+     *   c = x^2 + y^2 - cr^2
+     * we have:
+     *   a*t^2 - 2*b*t + c == 0
+     */
+    a = dx * dx + dy * dy - dr * dr;
+    if (fabs (a) < DBL_EPSILON * DBL_EPSILON) {
+	double b, maxd2;
+
+	/* Ensure that gradients with both a and dr small are
+	 * considered degenerate.
+	 * The floating point version of the degeneracy test implemented
+	 * in _radial_pattern_is_degenerate() is:
+	 *
+	 *  1) The circles are practically the same size:
+	 *     |dr| < DBL_EPSILON
+	 *  AND
+	 *  2a) The circles are both very small:
+	 *      min (r0, r1) < DBL_EPSILON
+	 *   OR
+	 *  2b) The circles are very close to each other:
+	 *      max (|dx|, |dy|) < 2 * DBL_EPSILON
+	 *
+	 * Assuming that the gradient is not degenerate, we want to
+	 * show that |a| < DBL_EPSILON^2 implies |dr| >= DBL_EPSILON.
+	 *
+	 * If the gradient is not degenerate yet it has |dr| <
+	 * DBL_EPSILON, (2b) is false, thus:
+	 *
+	 *   max (|dx|, |dy|) >= 2*DBL_EPSILON
+	 * which implies:
+	 *   4*DBL_EPSILON^2 <= max (|dx|, |dy|)^2 <= dx^2 + dy^2
+	 *
+	 * From the definition of a, we get:
+	 *   a = dx^2 + dy^2 - dr^2 < DBL_EPSILON^2
+	 *   dx^2 + dy^2 - DBL_EPSILON^2 < dr^2
+	 *   3*DBL_EPSILON^2 < dr^2
+	 *
+	 * which is inconsistent with the hypotheses, thus |dr| <
+	 * DBL_EPSILON is false or the gradient is degenerate.
+	 */
+	assert (fabs (dr) >= DBL_EPSILON);
+
+	/*
+	 * If a == 0, all the circles are tangent to a line in the
+	 * focus point. If this line is within the box extents, we
+	 * should add the circle with infinite radius, but this would
+	 * make the range unbounded, so we add the smallest circle whose
+	 * distance to the desired (degenerate) circle within the
+	 * bounding box does not exceed tolerance.
+	 *
+	 * The equation of the line is b==0, i.e.:
+	 *   x*dx + y*dy + cr*dr == 0
+	 *
+	 * We compute the intersection of the line with the box and
+	 * keep the intersection with maximum square distance (maxd2)
+	 * from the focus point.
+	 *
+	 * In the code the intersection is represented in another
+	 * coordinate system, whose origin is the focus point and
+	 * which has a u,v axes, which are respectively orthogonal and
+	 * parallel to the edge being intersected.
+	 *
+	 * The intersection is valid only if it belongs to the box,
+	 * otherwise it is ignored.
+	 *
+	 * For example:
+	 *
+	 *   y = y0
+	 *   x*dx + y0*dy + cr*dr == 0
+	 *   x = -(y0*dy + cr*dr) / dx
+	 *
+	 * which in (u,v) is:
+	 *   u = y0 - y_focus
+	 *   v = -(y0*dy + cr*dr) / dx - x_focus
+	 *
+	 * In the code:
+	 *   u = (edge) - (u_origin)
+	 *   v = -((edge) * (delta) + cr*dr) / (den) - v_focus
+	 */
+#define T_EDGE(edge,delta,den,lower,upper,u_origin,v_origin)	\
+	if (fabs (den) >= DBL_EPSILON) {			\
+	    double v;						\
+								\
+	    v = -((edge) * (delta) + cr * dr) / (den);		\
+	    if ((lower) <= v && v <= (upper)) {			\
+		double u, d2;					\
+								\
+		u = (edge) - (u_origin);			\
+		v -= (v_origin);				\
+		d2 = u*u + v*v;					\
+		if (maxd2 < d2)					\
+		    maxd2 = d2;					\
+	    }							\
+	}
+
+	maxd2 = 0;
+
+	/* degenerate circles (lines) passing through each edge */
+	T_EDGE (yMin, dy, dx, minx, maxx, y_focus, x_focus);
+	T_EDGE (yMax, dy, dx, minx, maxx, y_focus, x_focus);
+	T_EDGE (xMin, dx, dy, miny, maxy, x_focus, y_focus);
+	T_EDGE (xMax, dx, dy, miny, maxy, x_focus, y_focus);
+
+#undef T_EDGE
+
+	/*
+	 * The limit circle can be transformed rigidly to the y=0 line
+	 * and the circles tangent to it in (0,0) are:
+	 *
+	 *   x^2 + (y-r)^2 = r^2  <=>  x^2 + y^2 - 2*y*r = 0
+	 *
+	 * y is the distance from the line, in our case tolerance;
+	 * x is the distance along the line, i.e. sqrt(maxd2),
+	 * so:
+	 *
+	 *   r = cr + dr * t = (maxd2 + tolerance^2) / (2*tolerance)
+	 *   t = (r - cr) / dr =
+	 *       (maxd2 + tolerance^2 - 2*tolerance*cr) / (2*tolerance*dr)
+	 */
+	if (maxd2 > 0) {
+	    double t_limit = maxd2 + tolerance*tolerance - 2*tolerance*cr;
+	    t_limit /= 2 * tolerance * dr;
+	    valid = radialExtendRange (range, t_limit, valid);
+	}
+
+	/*
+	 * Nondegenerate, nonlimit circles passing through the corners.
+	 *
+	 * a == 0 && a*t^2 - 2*b*t + c == 0
+	 *
+	 * t = c / (2*b)
+	 *
+	 * The b == 0 case has just been handled, so we only have to
+	 * compute this if b != 0.
+	 */
+#define T_CORNER(x,y)							\
+	b = (x) * dx + (y) * dy + cr * dr;				\
+	if (fabs (b) >= DBL_EPSILON) {					\
+	    double t_corner;						\
+	    double x2 = (x) * (x);					\
+	    double y2 = (y) * (y);					\
+	    double cr2 = (cr) * (cr);					\
+	    double c = x2 + y2 - cr2;					\
+	    								\
+	    t_corner = 0.5 * c / b;					\
+	    if (t_corner * dr >= mindr)					\
+		valid = radialExtendRange (range, t_corner, valid);		\
+	}
+
+	/* circles touching each corner */
+	T_CORNER (xMin, yMin);
+	T_CORNER (xMin, yMax);
+	T_CORNER (xMax, yMin);
+	T_CORNER (xMax, yMax);
+
+#undef T_CORNER
+    } else {
+	double inva, b, c, d;
+
+	inva = 1 / a;
+
+	/*
+	 * Nondegenerate, nonlimit circles passing through the corners.
+	 *
+	 * a != 0 && a*t^2 - 2*b*t + c == 0
+	 *
+	 * t = (b +- sqrt (b*b - a*c)) / a
+	 *
+	 * If the argument of sqrt() is negative, then no circle
+	 * passes through the corner.
+	 */
+#define T_CORNER(x,y)							\
+	b = (x) * dx + (y) * dy + cr * dr;				\
+	c = (x) * (x) + (y) * (y) - cr * cr;				\
+	d = b * b - a * c;						\
+	if (d >= 0) {							\
+	    double t_corner;						\
+									\
+	    d = sqrt (d);						\
+	    t_corner = (b + d) * inva;					\
+	    if (t_corner * dr >= mindr)					\
+		valid = radialExtendRange (range, t_corner, valid);		\
+	    t_corner = (b - d) * inva;					\
+	    if (t_corner * dr >= mindr)					\
+		valid = radialExtendRange (range, t_corner, valid);		\
+	}
+
+	/* circles touching each corner */
+	T_CORNER (xMin, yMin);
+	T_CORNER (xMin, yMax);
+	T_CORNER (xMax, yMin);
+	T_CORNER (xMax, yMax);
+
+#undef T_CORNER
+    }
+}
+
+
+SplashRadialPattern::SplashRadialPattern(GfxState *stateA, GfxRadialShading *shadingA,
+										 double sMinA, double sMaxA, SplashColorMode colorModeA) {
+  double width, height;
+  Matrix ctm;
+
+  state = stateA;
+  shading = shadingA;
+  // ignore sMin ans sMax from Gfx (they include already extends!):
+  range[1] = 1;
+  range[0] = 0;
+  colorMode = colorModeA;
+  state->getCTM(&ctm);
+  ctm.invertTo(&ictm);
+  splash = NULL;
+  bitmap = NULL;
+  // get the shading info
+  shading->getCoords(&x0, &y0, &r0, &x1, &y1, &r1);
+  t0 = shading->getDomain0();
+  t1 = shading->getDomain1();
+  // calculate sMax for larger extend circle
+  extendedRange[1] = range[1];
+  extendedRange[0] = range[0];
+  maxSplitsExtend = radialMinSplits;
+  if (shading->getHasBBox())
+	  shading->getBBox(&xMin, &yMin, &xMax, &yMax);
+  else
+	  state->getUserClipBBox(&xMin, &yMin, &xMax, &yMax);
+  if (shading->getExtend0() || shading->getExtend1()) {
+		  if (xMin >= xMax)
+			  return;
+		  if (yMin >= yMax)
+			  return;
+		  radialGetMaxExtends(shading, xMin, yMin, xMax, yMax, radialTolerance, extendedRange);
+  }
+
+  if (!shading->getHasBBox()) {
+	  double xMinS, yMinS, xMaxS, yMaxS;
+	  double x, y, r;
+	  // shrink clip box to max area of shading, given by max extends
+	  // first calculate shading bbox:
+	  x = x0 + extendedRange[0] * (x1 - x0);
+	  y = y0 + extendedRange[0] * (y1 - y0);
+	  r = r0 + extendedRange[0] * (r1 - r0);
+	  xMinS = x - r; xMaxS = x + r; yMinS = y - r; yMaxS = y + r;
+	  x = x0 + extendedRange[1] * (x1 - x0);
+	  y = y0 + extendedRange[1] * (y1 - y0);
+	  r = r0 + extendedRange[1] * (r1 - r0);
+	  if (x - r < xMinS) xMinS = x - r;
+	  if (x + r > xMaxS) xMaxS = x + r;
+	  if (y - r < yMinS) yMinS = y - r;
+	  if (y + r > yMaxS) yMaxS = y + r;
+	  // now intersect it with user clip bbox:
+	  if (xMin < xMinS) xMin = xMinS;
+	  if (xMax > xMaxS) xMax = xMaxS;
+	  if (yMin < yMinS) yMin = yMinS;
+	  if (yMax > yMaxS) yMax = yMaxS;
+  }
+  width = xMax - xMin;
+  height = yMax - yMin;
+  if (splashFloor(xMax) - splashFloor(xMin) > width)
+	width = splashFloor(xMax) - splashFloor(xMin);
+  if (splashFloor(yMax) - splashFloor(yMin) > height)
+	height = splashFloor(yMax) - splashFloor(yMin);
+  if (radialMaxSize > 0 && width > 0 && height > 0) {
+	  if ( width > height)
+		  scale = radialMaxSize / height;
+	  else
+		  scale = radialMaxSize / width;
+  } else
+	  scale = 1;
+  xMinScaled = scale * xMin;
+  yMinScaled = scale * yMin;
+  width *= scale;
+  height *= scale;
+  if (width > 0 && height > 0) {
+	  bitmap = new SplashBitmap(splashRound(width), splashRound(height), colorMode != splashModeMono1, colorMode, gTrue);
+	  splash = new Splash(bitmap, gFalse /* AntiAlias in shading Dict! */);
+
+	  // show only what is painted, delete alpha channel
+	  Guchar *bitmapAlpha = bitmap->getAlphaPtr();
+	  int size = bitmap->getWidth() * bitmap->getHeight();
+	  for (int i = 0; i < size; ++i)
+		  bitmapAlpha[i] = 0;
+  }
+
+  // change transfer matrix to fit to scaled bitmap 
+  ictm.m[0] *= scale;
+  ictm.m[1] *= scale;
+  ictm.m[2] *= scale;
+  ictm.m[3] *= scale;
+  ictm.m[4] *= scale;
+  ictm.m[5] *= scale;
+  ictm.m[4] -= xMinScaled;
+  ictm.m[5] -= yMinScaled;
+  if (extendedRange[0] > 0)
+	  range[0] = extendedRange[0];
+  if (extendedRange[1] < 1)
+	  range[1] = extendedRange[1];
+  double rMin, rMax;
+  rMin = r0 + extendedRange[0] * (r1 - r0);
+  rMax = r0 + extendedRange[1] * (r1 - r0);
+  rMin *= scale;
+  rMax *= scale;
+  if (rMin > 65536 && r1 != r0) {
+	  rMin = 65536;
+	  extendedRange[0] = ((double) rMin / scale - r0) / (r1 - r0);
+  }
+  if (rMax > 65536 && r1 != r0) {
+	  rMax = 65536;
+	  extendedRange[1] = ((double) rMax / scale - r0) / (r1 - r0);
+  }
+  maxSplits = splashRound((rMax - rMin)/ 5);
+  if (maxSplits < 0) maxSplits = -maxSplits;
+  if (maxSplits < radialMinSplits)
+	  maxSplits = radialMinSplits;
+  if (maxSplits > radialMaxSplits)
+	  maxSplits = radialMaxSplits;
+}
+
+SplashRadialPattern::~SplashRadialPattern() {
+  if (splash) {
+    delete splash;
+  }
+  if (bitmap) {
+    delete bitmap;
+  }
+}
+
+GBool SplashRadialPattern::getColor(int x, int y, SplashColorPtr c) {
+  double xc, yc;
+  int xs, ys, xMin, yMin, xMax, yMax;
+  Guchar *bitmapAlpha;
+  Gulong superCell[splashMaxColorComps];
+  SplashColor cell;
+  int cp = 0, i, ca = 0;
+
+  for (i = 0; i < splashMaxColorComps; i++)
+	  superCell[i] = 0;
+  bitmapAlpha = bitmap->getAlphaPtr();
+  ictm.transform(x, y, &xc, &yc);
+  xMin = splashFloor(xc);
+  yMin = splashFloor(yc);
+  if (xMin < 0) xMin = 0;
+  if (xMin >= bitmap->getWidth()) xMin = bitmap->getWidth() - 1;
+  if (yMin < 0) yMin = 0;
+  if (yMin >= bitmap->getHeight()) yMin = bitmap->getHeight() - 1;
+  ictm.transform(x + 1, y + 1, &xc, &yc);
+  xMax = splashFloor(xc);
+  yMax = splashFloor(yc);
+  if (xMax < 0) xMax = 0;
+  if (xMax >= bitmap->getWidth()) xMax = bitmap->getWidth() - 1;
+  if (yMax < 0) yMax = 0;
+  if (yMax >= bitmap->getHeight()) yMax = bitmap->getHeight() - 1;
+  if (xMax < xMin) { i = xMax; xMax = xMin; xMin = i; }
+  if (yMax < yMin) { i = yMax; yMax = yMin; yMin = i; }
+  for (ys = yMin; ys <= yMax; ys++) {
+	  for (xs = xMin; xs <= xMax; xs++) {
+		  // Because of rounding problems, coordinates could be 
+		  // outside the bitmap. Reset them on the outer bound now
+		  // and let it up to the alpha channel if they are shown:
+		  cp++;
+		  if (bitmapAlpha[ys * bitmap->getWidth() + xs]) {
+			  bitmap->getPixel(xs, ys, cell);
+			  for (i = 0; i < splashMaxColorComps; i++)
+				  superCell[i] += cell[i];
+		  } else {
+			  ca++;
+		  }
+	  }
+  }
+  if (ca < cp) {
+	  for (i = 0; i < splashMaxColorComps; i++)
+		  c[i] = (Guchar) (superCell[i] / (cp - ca));
+	  return gTrue;
+  }
+  return gFalse;
+}
+
+static inline void getShadingColorRadialHelper(double t0, double t1, double t, GfxRadialShading *shading, GfxColor *color)
+{
+  if (t0 < t1) {
+    if (t < t0) {
+      shading->getColor(t0, color);
+    } else if (t > t1) {
+      shading->getColor(t1, color);
+    } else {
+      shading->getColor(t, color);
+    }
+  } else {
+    if (t > t0) {
+      shading->getColor(t0, color);
+    } else if (t < t1) {
+      shading->getColor(t1, color);
+    } else {
+      shading->getColor(t, color);
+    }
+  }
+}
+
+void SplashRadialPattern::getStartCircle(SplashCoord *xsc, SplashCoord *ysc, 
+										 SplashCoord *radius, 
+										 SplashColorPtr c) {
+  GfxColor colorA;
+  GfxColorSpace* srcColorSpace = shading->getColorSpace();
+  ia = 0;
+  sa = range[0];
+  ta = t0 + sa * (t1 - t0);
+  xa = x0 + sa * (x1 - x0);
+  ya = y0 + sa * (y1 - y0);
+  ra = r0 + sa * (r1 - r0);
+  getShadingColorRadialHelper(t0, t1, ta, shading, &colorA);
+  *radius = splashFloor(ra * scale); 
+  *xsc = splashFloor(xa * scale - xMinScaled); *ysc = splashFloor(ya * scale - yMinScaled); 
+  convertGfxColor(c, colorMode, srcColorSpace, &colorA);
+}
+
+static inline GBool isSameGfxColor(const GfxColor &colorA, const GfxColor &colorB, Guint nComps, double delta) {
+  for (Guint k = 0; k < nComps; ++k) {
+    if (abs(colorA.c[k] - colorB.c[k]) > delta) {
+      return false;
+    }
+  }
+  return true;
+}
+
+GBool SplashRadialPattern::getNextCircle(SplashCoord *xsc, SplashCoord *ysc, 
+										 SplashCoord *radius, 
+										 SplashColorPtr c) {
+  GfxColor colorA, colorB;
+  GfxColorSpace* srcColorSpace = shading->getColorSpace();
+  double sb, tb, factor;
+  int ib, nComps;
+  nComps = shading->getColorSpace()->getNComps();
+  if (ia >= maxSplits)
+	  return gFalse;
+  getShadingColorRadialHelper(t0, t1, ta, shading, &colorA);
+  ib = maxSplits;
+  sb = range[1];
+  tb = t0 + sb * (t1 - t0);
+  getShadingColorRadialHelper(t0, t1, tb, shading, &colorB);
+  while (ib - ia > 1) {
+      if (isSameGfxColor(colorB, colorA, nComps, radialColorDelta)) {
+        // The shading is not necessarily lineal so having two points with the
+        // same color does not mean all the areas in between have the same color too
+		  int ic = ia + 1;
+		  for (; ic <= ib; ic++) {
+			GfxColor colorC;
+			factor = (double)ic / (double)maxSplits; 
+			double sc = range[0] + factor * (range[1] - range[0]);
+			double tc = t0 + sc * (t1 - t0);
+			getShadingColorRadialHelper(t0, t1, tc, shading, &colorC);
+			if (!isSameGfxColor(colorC, colorA, nComps, radialColorDelta)) {
+			  break;
+			}
+		  }
+		  ib = (ic > ia + 1)? ic - 1 : ia + 1;
+		  factor = (double)ib / (double)maxSplits; 
+		  sb = range[0] + factor * (range[1] - range[0]);
+		  tb = t0 + sb * (t1 - t0);
+		  getShadingColorRadialHelper(t0, t1, tb, shading, &colorB);
+		  break;
+      }
+      ib = (ia + ib) / 2;
+	  factor = (double)ib / (double)maxSplits; 
+      sb = range[0] + factor * (range[1] - range[0]);
+      tb = t0 + sb * (t1 - t0);
+      getShadingColorRadialHelper(t0, t1, tb, shading, &colorB);
+  }
+  // compute center and radius of the circle
+  xa = x0 + sb * (x1 - x0);
+  ya = y0 + sb * (y1 - y0);
+  ra = r0 + sb * (r1 - r0);
+  *radius = splashFloor(ra * scale); 
+  *xsc = splashFloor(xa * scale - xMinScaled); *ysc = splashFloor(ya * scale - yMinScaled); 
+  convertGfxColor(c, colorMode, srcColorSpace, &colorB);
+  ia = ib;
+  if (testClip(*xsc, *ysc, *radius) != splashClipPartial && 
+	  maxSplits > 8192 && ib + 32 < maxSplits) 
+	  ia = ib + 32;
+  ta = tb;
+  return gTrue;
+}
+
+GBool SplashRadialPattern::getLargerExtendCircle(SplashCoord *xsc, SplashCoord *ysc, 
+										 SplashCoord *radius, SplashColorPtr c) {
+  GfxColor colorA;
+  GfxColorSpace* srcColorSpace = shading->getColorSpace();
+  if ((shading->getExtend0() && r0 > r1) ||
+	  (shading->getExtend1() && r1 >= r0)) {
+		  if (r0 >= r1) {
+			  ta = t0;
+			  ra = r0;
+			  xa = x0;
+			  ya = y0;
+		  } else {
+			  ta = t1;
+			  ra = r1;
+			  xa = x1;
+			  ya = y1;
+		  }
+		  shading->getColor(ta, &colorA);
+		  *radius = splashFloor(ra * scale); 
+		  *xsc = splashFloor(xa * scale - xMinScaled); *ysc = splashFloor(ya * scale - yMinScaled); 
+		  convertGfxColor(c, colorMode, srcColorSpace, &colorA);
+		  ia = 0;
+		  return gTrue;
+  }
+  return gFalse;
+}
+
+GBool SplashRadialPattern::getNextLargerExtendCircle(SplashCoord *xsc, SplashCoord *ysc, 
+													  SplashCoord *radius, GBool fExtend) {
+  double sb, factor;
+  double sStart, sEnd;
+  if (ia++ + 1 >= maxSplitsExtend)
+	  return gFalse;
+  if (x0 == x1 && y0 == y1)
+	  ia = maxSplitsExtend;
+  sStart = (r0 > r1) ? range[0] : range[1];
+  // buest guess:
+  sEnd = (fExtend) ? extendedRange[1] : extendedRange[0]; 
+  factor = (double)ia / (double)maxSplitsExtend; 
+  sb = sStart + factor * (sEnd - sStart);
+  // compute center and radius of the circle
+  xa = x0 + sb * (x1 - x0);
+  ya = y0 + sb * (y1 - y0);
+  ra = r0 + sb * (r1 - r0);
+  ra = ra * scale;
+  xa = xa * scale - xMinScaled;
+  ya = ya * scale - yMinScaled;
+  *radius = splashFloor(ra); 
+  *xsc = splashFloor(xa); *ysc = splashFloor(ya); 
+  return gTrue;
+}
+
+GBool SplashRadialPattern::getSmallerExtendCircle(SplashCoord *xsc, SplashCoord *ysc, 
+										 SplashCoord *radius, SplashColorPtr c, GBool fExtend) {
+  GfxColor colorA;
+  GfxColorSpace* srcColorSpace = shading->getColorSpace();
+  if ((shading->getExtend0() && r0 <= r1 && r0 > 0) ||
+	  (shading->getExtend1() && r1 < r0 && r1 > 0)) {
+		  double sStart, sEnd;
+		  sEnd = (r1 > r0) ? range[0] : range[1];
+		  sStart = (r1!= r0) ? -r0 / (r1 - r0) : 0; 
+		  double sb = (fExtend) ? sStart : sEnd; 
+		  xa = x0 + sb * (x1 - x0);
+		  ya = y0 + sb * (y1 - y0);
+		  ra = r0 + sb * (r1 - r0);
+		  if (r0 < r1) {
+			  ta = t0;
+		  } else {
+			  ta = t1;
+		  }
+		  shading->getColor(ta, &colorA);
+		  *radius = splashFloor(ra * scale); 
+		  *xsc = splashFloor(xa * scale - xMinScaled); *ysc = splashFloor(ya * scale - yMinScaled); 
+		  convertGfxColor(c, colorMode, srcColorSpace, &colorA);
+		  ia = 0;
+		  return gTrue;
+  }
+  return gFalse;
+}
+
+GBool SplashRadialPattern::getNextSmallerExtendCircle(SplashCoord *xsc, SplashCoord *ysc, 
+													  SplashCoord *radius, GBool fExtend) {
+  double sb, factor;
+  double sStart, sEnd;
+  if (ia++ + 1 >= maxSplits)
+	  return gFalse;
+  sEnd = (r1 > r0) ? range[1] : range[0];
+  sStart = (r1!= r0) ? -r0 / (r1 - r0) : range[1] * 16; 
+  if (!fExtend) {
+	  sEnd = sStart; 
+	  sStart = (r1 > r0) ? range[0] : range[1];
+  }
+  factor = (double)ia / (double)maxSplits; 
+  sb = sStart + factor * (sEnd - sStart);
+  // compute center and radius of the circle
+  xa = x0 + sb * (x1 - x0);
+  ya = y0 + sb * (y1 - y0);
+  ra = r0 + sb * (r1 - r0);
+  *radius = splashFloor(ra * scale); 
+  *xsc = splashFloor(xa * scale - xMinScaled); *ysc = splashFloor(ya * scale - yMinScaled); 
+  return gTrue;
+}
+
+SplashClipResult SplashRadialPattern::testClip(SplashCoord x, SplashCoord y, SplashCoord r) {
+	if (x + r < 0 || y + r < 0 || x - r >= bitmap->getWidth() || y - r >= bitmap->getHeight())
+		return splashClipAllOutside;
+	double rs = r * r;
+	double xls = x * x;
+	double xrs = (x - bitmap->getWidth()) * (x - bitmap->getWidth());
+	double yls = y * y;
+	double yus = (y - bitmap->getHeight()) * (y - bitmap->getHeight());
+	if (xls + yus < rs && xrs + yus < rs &&
+		xls + yls < rs && xrs + yls < rs)
+		return splashClipAllInside;
+	return splashClipPartial;
+}
+
+GBool SplashRadialPattern::encloseCircle(SplashCoord x1, SplashCoord y1, SplashCoord r1,
+										 SplashCoord x2, SplashCoord y2, SplashCoord r2) {
+    if (x1 == x2 && y1 == y2)
+		return r2 < r1;
+	double dist = sqrt((x1 -x2) * (x1 -x2) + (y1 - y2) * (y1 - y2));
+	return dist + r2 < r1;
+}
+
+//------------------------------------------------------------------------
 // SplashAxialPattern
 //------------------------------------------------------------------------
 
@@ -3011,14 +3843,14 @@ void SplashOutputDev::beginTransparencyGroup(GfxState *state, double *bbox,
   tx = (int)floor(xMin);
   if (tx < 0) {
     tx = 0;
-  } else if (tx > bitmap->getWidth()) {
-    tx = bitmap->getWidth();
+  } else if (tx > bitmap->getWidth() - 1) {
+    tx = bitmap->getWidth() - 1;
   }
   ty = (int)floor(yMin);
   if (ty < 0) {
     ty = 0;
-  } else if (ty > bitmap->getHeight()) {
-    ty = bitmap->getHeight();
+  } else if (ty > bitmap->getHeight() - 1) {
+    ty = bitmap->getHeight() - 1;
   }
   w = (int)ceil(xMax) - tx + 1;
   if (tx + w > bitmap->getWidth()) {
@@ -3379,3 +4211,33 @@ GBool SplashOutputDev::axialShadedFill(GfxState *state, GfxAxialShading *shading
 
   return retVal;
 }
+
+GBool SplashOutputDev::radialShadedFill(GfxState *state, GfxRadialShading *shading, double sMin, double sMax) {
+  double xMin, yMin, xMax, yMax;
+  SplashPath *path;
+
+  GBool retVal = gFalse;
+  SplashRadialColor *pattern = new SplashRadialPattern(state, shading, sMin, sMax, colorMode);
+  if (pattern->isOk()) {
+	  // get the clip region bbox
+	  pattern->getClipBBox(&xMin, &yMin, &xMax, &yMax);
+	  // clip this region
+	  state->moveTo(xMin, yMin);
+	  state->lineTo(xMax, yMin);
+	  state->lineTo(xMax, yMax);
+	  state->lineTo(xMin, yMax);
+	  state->closePath();
+	  path = convertPath(state, state->getPath());
+
+	  // first draw the radial shading in its own bitmap
+	  retVal = (pattern->getSplash()->radialShadedFill(pattern) == splashOk);
+	  // now use this bitmap as dynamic pattern:
+	  if (retVal) {
+		  retVal = (splash->shadedFill(path, shading->getHasBBox(), pattern) == splashOk);
+	  }
+	  state->clearPath();
+	  delete path;
+  }
+  delete pattern;
+  return retVal;
+}
diff --git a/poppler/SplashOutputDev.h b/poppler/SplashOutputDev.h
index 570d036..1c50384 100644
--- a/poppler/SplashOutputDev.h
+++ b/poppler/SplashOutputDev.h
@@ -105,6 +105,55 @@ private:
   GBool bDirectColorTranslation;
 };
 
+// see GfxState.h, GfxRadialShading
+class SplashRadialPattern: public SplashRadialColor {
+public:
+
+  SplashRadialPattern(GfxState *state, GfxRadialShading *shading, double sMin, double sMax, SplashColorMode colorMode);
+
+  GBool isOk() { return (bitmap != NULL); }
+
+  Splash *getSplash() { return splash; }
+
+  SplashBitmap *getBitmap() { return bitmap; }
+
+  virtual SplashPattern *copy() { return new SplashRadialPattern(state, shading, range[0], range[1], colorMode); }
+
+  virtual ~SplashRadialPattern();
+
+  virtual GBool getColor(int x, int y, SplashColorPtr c);
+
+  virtual GBool isStatic() { return gFalse; }
+  
+  virtual void getStartCircle(SplashCoord *x0, SplashCoord *y0, SplashCoord *radius, SplashColorPtr c);
+  virtual GBool getNextCircle(SplashCoord *x0, SplashCoord *y0, SplashCoord *radius, SplashColorPtr c);
+  virtual GBool getLargerExtendCircle(SplashCoord *x0, SplashCoord *y0, SplashCoord *radius, SplashColorPtr c);
+  virtual GBool getNextLargerExtendCircle(SplashCoord *x0, SplashCoord *y0, SplashCoord *radius, GBool fExtend); 
+  virtual GBool getSmallerExtendCircle(SplashCoord *x0, SplashCoord *y0, SplashCoord *radius, SplashColorPtr c, GBool fExtend); 
+  virtual GBool getNextSmallerExtendCircle(SplashCoord *x0, SplashCoord *y0, SplashCoord *radius, GBool fExtend); 
+  virtual GBool enlargeCircles() { return r1 > r0; }
+  virtual SplashClipResult testClip(SplashCoord x, SplashCoord y, SplashCoord r);
+  virtual GBool encloseCircle(SplashCoord x0, SplashCoord y0, SplashCoord r0,
+		SplashCoord x1, SplashCoord y1, SplashCoord r1);
+  void getClipBBox(double *clipXMin, double *clipYMin, double *clipXMax, double *clipYMax)
+    { *clipXMin = xMin; *clipYMin = yMin; *clipXMax = xMax; *clipYMax = yMax; }
+private:
+  GfxRadialShading *shading;
+  GfxState *state;
+  Matrix ictm;
+  double range[2], extendedRange[2];
+  double yMinScaled, xMinScaled;
+  double xMin, xMax, yMin, yMax;
+  double scale;
+  double xa, ya, ra, ta, sa;
+  int ia;
+  int maxSplits, maxSplitsExtend;
+  double x0, y0, r0, x1, y1, r1, t0, t1;
+  Splash *splash;
+  SplashBitmap *bitmap;
+  SplashColorMode colorMode;
+};
+
 //------------------------------------------------------------------------
 
 // number of Type 3 fonts to cache
@@ -132,7 +181,7 @@ public:
   // radialShadedFill()?  If this returns false, these shaded fills
   // will be reduced to a series of other drawing operations.
   virtual GBool useShadedFills(int type)
-  { return (type == 2 || type == 4 || type == 5 ) ? gTrue : gFalse; }
+  { return (type >= 2 && type <= 5) ? gTrue : gFalse; }
 
   // Does this device use upside-down coordinates?
   // (Upside-down means (0,0) is the top left corner of the page.)
@@ -186,6 +235,7 @@ public:
   virtual void fill(GfxState *state);
   virtual void eoFill(GfxState *state);
   virtual GBool axialShadedFill(GfxState *state, GfxAxialShading *shading, double tMin, double tMax);
+  virtual GBool radialShadedFill(GfxState *state, GfxRadialShading *shading, double sMin, double sMax);
   virtual GBool gouraudTriangleShadedFill(GfxState *state, GfxGouraudTriangleShading *shading);
 
   //----- path clipping
diff --git a/splash/Splash.cc b/splash/Splash.cc
index bc317a6..71a155c 100644
--- a/splash/Splash.cc
+++ b/splash/Splash.cc
@@ -253,30 +253,8 @@ inline void Splash::pipeRun(SplashPipe *pipe) {
   // dynamic pattern
   if (pipe->pattern) {
     if (!pipe->pattern->getColor(pipe->x, pipe->y, pipe->cSrcVal)) {
-      switch (bitmap->mode) {
-        case splashModeMono1:
-          if (!(pipe->destColorMask >>= 1)) 
-            ++pipe->destColorPtr;
-        break;
-        case splashModeMono8:
-          ++pipe->destColorPtr;
-        break;
-        case splashModeBGR8:
-        case splashModeRGB8:
-          pipe->destColorPtr += 3;
-        break;
-        case splashModeXBGR8:
-#if SPLASH_CMYK
-        case splashModeCMYK8:
-#endif
-          pipe->destColorPtr += 4;
-        break;
-      }
-      if (pipe->destAlphaPtr) {
-        ++pipe->destAlphaPtr;
-      }
-      ++pipe->x;
-      return;
+		pipeIncX(pipe);
+		return;
     }
   }
 
@@ -3531,6 +3509,697 @@ GBool Splash::gouraudTriangleShadedFill(SplashGouraudColor *shading)
   return gTrue;
 }
 
+SplashPath *Splash::getBresenhamPoints(SplashCoord xc, SplashCoord yc, SplashCoord rc) {
+  int radius = splashRound(rc);
+  int x0 = splashRound(xc);
+  int y0 = splashRound(yc);
+  int f = 1 - radius;
+  int ddF_x = 1;
+  int ddF_y = -2 * radius;
+  int x = 0, lastX = x;
+  int y = radius, lastY = y;
+  Guchar dummy;
+  SplashPath *splashPath = new SplashPath();
+  
+  if (radius == 0) {
+	  splashPath->moveTo(lastX, lastY);
+	  return splashPath;
+  }
+ 
+  while(x < y)
+  {
+    if(f >= 0) 
+    {
+      y--;
+      ddF_y += 2;
+      f += ddF_y;
+    }
+    x++;
+    ddF_x += 2;
+    f += ddF_x;   
+	if (lastY != y) {
+		if (splashPath->getLength())
+			splashPath->lineTo(lastX, lastY);
+		else
+			splashPath->moveTo(lastX, lastY);
+		lastY = y;
+	}
+	lastX = x;
+  }
+  for (int i = splashPath->getLength() -1; i >= 0; i--) {
+	  SplashCoord curX, curY;
+	  splashPath->getPoint(i, &curY, &curX, &dummy);
+	  for (SplashCoord j = lastY; j >= curY; j--)
+		  splashPath->lineTo(curX, j);
+	  lastY = splashRound(curY - 1);
+  }
+  while (lastY >= 0)
+	  splashPath->lineTo(rc, lastY--);
+  return splashPath;
+}	
+
+static inline void getBCircleLine(SplashPath *bresPoints, SplashCoord y, SplashCoord y0, SplashCoord r, SplashCoord *x) {
+	SplashCoord curX, curY;
+	Guchar dummy;
+	int i = (y > y0) ? splashRound(r - (y - y0)) : splashRound(r - (y0 - y));
+	if (i < bresPoints->getLength()) {
+		bresPoints->getPoint(i, &curX, &curY, &dummy);
+		*x = curX;
+	}
+}
+
+void Splash::drawPartCircleLine(SplashPipe *pipe, 
+								   SplashCoord y, 
+								   SplashCoord xMin, SplashCoord xMax) {
+	int yI, xmaxI, xminI;
+	int height = bitmap->getHeight();
+	int width = bitmap->getWidth();
+	Guchar *bitmapAlpha = bitmap->getAlphaPtr();
+	yI = splashRound(y);
+	xmaxI = splashRound(xMax);
+	xminI = splashRound(xMin);
+	if (yI >= 0 && yI < height && xMax >= 0) {
+		if (xminI < 0) 
+			xminI = 0;
+		if (xminI < width) {
+			if (xmaxI > width - 1) 
+				xmaxI = width - 1;
+			drawSpan(pipe, xminI, xmaxI, yI, gTrue);
+		}
+	}
+}
+
+void Splash::drawBCircleLine(SplashPipe *pipe, SplashPath *bresInnerPoints,
+								   SplashCoord y, SplashCoord yiMin, SplashCoord yiMax,
+								   SplashCoord yi, SplashCoord xi, SplashCoord iradius,
+								   SplashCoord xMin, SplashCoord xMax, int lineWidth) {
+	if (y > yiMax || y < yiMin)
+		drawPartCircleLine(pipe, y, xMin, xMax);
+	else {
+		SplashCoord xiMin, xiMax;
+		getBCircleLine(bresInnerPoints, y, yi, iradius, &xiMin);
+		xiMax = xi + xiMin;
+		xiMin = xi - xiMin;
+		if (xiMin >= xMin || xiMax <= xMax) {
+			if (xiMax < xMin || xiMin > xMax)
+				drawPartCircleLine(pipe, y, xMin, xMax);
+			else if (xiMin <= xMin && xiMax < xMax) {
+				if (xiMin != xMin)
+					drawPartCircleLine(pipe, y, xMin, xMin + lineWidth);
+				drawPartCircleLine(pipe, y, (xMax - xiMax > lineWidth) ? xiMax : xMax - lineWidth, xMax);
+			} else if (xiMin >= xMin && xiMax <= xMax) {
+				if (xiMin != xMin)
+					drawPartCircleLine(pipe, y, xMin, xiMin - 1);
+				if (xiMax != xMax)
+					drawPartCircleLine(pipe, y, xiMax+ 1, xMax);
+			} else {
+				if (xiMin != xMin)
+					drawPartCircleLine(pipe, y, xMin, (xiMin - xMin > lineWidth) ? xiMin : xMin + lineWidth);
+				drawPartCircleLine(pipe, y, xMax - lineWidth, xMax);
+			}
+		}
+	}
+}
+
+SplashPath *Splash::drawCircle(SplashCoord xo, SplashCoord yo, SplashCoord oradius, SplashColorPtr cur, SplashPath *bresOuterPoints,
+						SplashCoord xi, SplashCoord yi, SplashCoord iradius, SplashColorPtr curNext, GBool fExtend, 
+						SplashPipe *pipe) {
+	SplashPath *bresInnerPoints = getBresenhamPoints(xi, yi, iradius);
+	if (bresInnerPoints == NULL)
+		return bresInnerPoints;
+
+	if (!fExtend) {
+		SplashCoord yiMax = yi + iradius, yiMin = yi - iradius;
+		SplashCoord yoMax = yo + oradius, yoMin = yo - oradius;
+		Guchar dummy;
+		int lineWidth = splashRound(oradius - iradius);
+		if (lineWidth > 3) lineWidth = 3;
+		// draw upper half
+		int startPoint = 0;
+		if (yoMax >= bitmap->getHeight()) {
+			startPoint = splashRound(yoMax - bitmap->getHeight() + 1);
+		}
+		int endPoint = startPoint + bitmap->getHeight();
+		if (endPoint > bresOuterPoints->getLength())
+			endPoint = bresOuterPoints->getLength();
+		for (int i = startPoint; i < endPoint; i++) {
+			SplashCoord curX, curY;
+			SplashCoord xMin, xMax;
+			bresOuterPoints->getPoint(i, &curX, &curY, &dummy);
+			xMax = xo + curX;
+			xMin = xo - curX;
+			curY = yo + curY;
+			drawBCircleLine(pipe, bresInnerPoints,
+				curY, yiMin, yiMax, yi, xi, iradius, xMin, xMax, lineWidth);
+		}
+		// draw lower half
+		endPoint = splashRound(bitmap->getHeight() - yoMin);
+		startPoint = endPoint - bitmap->getHeight();
+		if (endPoint > bresOuterPoints->getLength())
+			endPoint = bresOuterPoints->getLength();
+		if (startPoint < 0)
+			startPoint = 0;
+		for (int i = startPoint; i < endPoint; i++) {
+			SplashCoord curX, curY;
+			SplashCoord xMin, xMax;
+			bresOuterPoints->getPoint(i, &curX, &curY, &dummy);
+			xMax = xo + curX;
+			xMin = xo - curX;
+			curY = yo - curY;
+			drawBCircleLine(pipe, bresInnerPoints,
+				curY, yiMin, yiMax, yi, xi, iradius, xMin, xMax, lineWidth);
+		}
+		splashColorCopy(cur, curNext);
+	} else {
+		SplashCoord yoMax = yo + oradius, yoMin = yo - oradius;
+		SplashCoord yiMax = yi + iradius, yiMin = yi - iradius;
+		Guchar dummy;
+		int lineWidth = splashRound(iradius - oradius);
+		if (lineWidth > 3) lineWidth = 3;
+		splashColorCopy(cur, curNext);
+		// draw upper half
+		int startPoint = 0;
+		if (yiMax >= bitmap->getHeight()) {
+			startPoint = splashRound(yiMax - bitmap->getHeight() + 1);
+		}
+		int endPoint = startPoint + bitmap->getHeight();
+		if (endPoint > bresInnerPoints->getLength())
+			endPoint = bresInnerPoints->getLength();
+		for (int i = startPoint; i < endPoint; i++) {
+			SplashCoord curX, curY;
+			SplashCoord xMin, xMax;
+			bresInnerPoints->getPoint(i, &curX, &curY, &dummy);
+			xMax = xi + curX;
+			xMin = xi - curX;
+			curY = yi + curY;
+			drawBCircleLine(pipe, bresOuterPoints,
+				curY, yoMin, yoMax, yo, xo, oradius, xMin, xMax, lineWidth);
+		}
+		// draw lower half
+		endPoint = splashRound(bitmap->getHeight() - yiMin);
+		startPoint = endPoint - bitmap->getHeight();
+		if (endPoint > bresInnerPoints->getLength())
+			endPoint = bresInnerPoints->getLength();
+		if (startPoint < 0)
+			startPoint = 0;
+		for (int i = startPoint; i < endPoint; i++) {
+			SplashCoord curX, curY;
+			SplashCoord xMin, xMax;
+			bresInnerPoints->getPoint(i, &curX, &curY, &dummy);
+			xMax = xi + curX;
+			xMin = xi - curX;
+			curY = yi - curY;
+			drawBCircleLine(pipe, bresOuterPoints,
+				curY, yoMin, yoMax, yo, xo, oradius, xMin, xMax, lineWidth);
+		}
+	}
+//	fprintf(stderr, "Not drawn: %d\n", notdrawn);
+	return bresInnerPoints;
+}
+
+SplashError Splash::radialShadedFill(SplashRadialColor *shading) {
+	SplashPipe pipe;
+	SplashColor cSrcVal, cNextVal;
+	SplashColorPtr cur = cSrcVal, curNext = cNextVal;
+	SplashCoord xo, yo, oradius;
+	SplashCoord xi, yi, iradius;
+	int tl, tr, tu, td, enclosure;
+	SplashCoord ydl, yul, xll, xrl;
+	GBool fExtend = shading->enlargeCircles();
+	
+	pipeInit(&pipe, 0, 0, NULL, cSrcVal, state->strokeAlpha, gFalse, gFalse);
+	pipe.cSrc = cur;
+	
+	// extend starting circle
+	if (fExtend && shading->getSmallerExtendCircle(&xo, &yo, &oradius, cur, fExtend)) {
+		SplashPath *bresOuterPoints = getBresenhamPoints(xo, yo, oradius);
+		if (bresOuterPoints == NULL)
+			return splashErrEmptyPath;
+		if (oradius == 0)
+			drawPartCircleLine(&pipe, yo, xo, xo);
+		while (shading->getNextSmallerExtendCircle(&xi, &yi, &iradius, fExtend)) {
+			if (xi == xo && yi == yo && iradius == oradius) {
+				continue;
+			}
+			SplashPath *bresInnerPoints = drawCircle(xo, yo, oradius, cur, bresOuterPoints,
+				xi, yi, iradius, cur, fExtend, &pipe);
+			if (bresInnerPoints == NULL)
+				break;
+			delete bresOuterPoints;
+			bresOuterPoints = bresInnerPoints;
+			yo = yi; xo = xi; oradius = iradius;
+		}
+		delete bresOuterPoints;
+	}
+	if (!fExtend && shading->getLargerExtendCircle(&xo, &yo, &oradius, cur)) {
+		SplashPath *bresOuterPoints = getBresenhamPoints(xo, yo, oradius);
+		if (bresOuterPoints == NULL)
+			return splashErrEmptyPath;
+		// start with filling the circle
+		SplashCoord xMin, xMax;
+		Guchar dummy;
+		tl = tr = tu = td = enclosure = 0;
+		ydl = xll = yul = xrl = -1;
+		// draw upper half
+		int startPoint = 0;
+		if (yo + oradius >= bitmap->getHeight()) {
+			startPoint = splashRound(yo + oradius - bitmap->getHeight() + 1);
+		}
+		int endPoint = startPoint + bitmap->getHeight();
+		if (endPoint > bresOuterPoints->getLength())
+			endPoint = bresOuterPoints->getLength();
+		for (int i = startPoint; i < endPoint; i++) {
+			SplashCoord curX, curY;
+			bresOuterPoints->getPoint(i, &curX, &curY, &dummy);
+			curY = yo - curY;
+			xMax = xo + curX;
+			xMin = xo - curX;
+			drawPartCircleLine(&pipe, curY, xMin, xMax);
+		}
+		// draw lower half
+		endPoint = splashRound(bitmap->getHeight() - (yo - oradius));
+		startPoint = endPoint - bitmap->getHeight();
+		if (endPoint > bresOuterPoints->getLength())
+			endPoint = bresOuterPoints->getLength();
+		if (startPoint < 0)
+			startPoint = 0;
+		for (int i = startPoint; i < endPoint; i++) {
+			SplashCoord curX, curY;
+			bresOuterPoints->getPoint(i, &curX, &curY, &dummy);
+			curY += yo;
+			xMax = xo + curX;
+			xMin = xo - curX;
+			drawPartCircleLine(&pipe, curY, xMin, xMax);
+		}
+		while (shading->getNextLargerExtendCircle(&xi, &yi, &iradius, fExtend)) {
+			if (xi == xo && yi == yo && iradius == oradius) {
+				continue;
+			}
+			SplashPath *bresInnerPoints = drawCircle(xo, yo, oradius, cur, bresOuterPoints,
+				xi, yi, iradius, cur, gTrue, &pipe);
+			if (bresInnerPoints == NULL)
+				break;
+			// test for enclosure
+			if (shading->encloseCircle(xi, yi, iradius, xo, yo, oradius))
+				enclosure++;
+			else
+				enclosure = 0;
+			// test for tangents
+			if (yo == yi && abs(xi - xo + oradius - iradius) < 2) {
+				if (xll == -1) 
+					xll = xi - iradius;
+				if (abs(xll - xo + oradius) < 2) 
+					tl++;
+				else {
+					tl = 0;
+					xll = xi - iradius;
+				}
+			}
+			if (yo == yi && abs(xi - xo + iradius - oradius) < 2) {
+				if (xrl == -1) 
+					xrl = xi + iradius;
+				if (abs(xrl - xo - oradius) < 2) 
+					tr++;
+				else {
+					tr = 0;
+					xrl = xi + iradius;
+				}
+			}
+			if (xo == xi && abs(yi - yo + oradius - iradius) < 2) {
+				if (ydl == -1) 
+					ydl = yi - iradius;
+				if (abs(ydl - yo + oradius) < 2) 
+					td++;
+				else {
+					td = 0;
+					ydl = yi - iradius;
+				}
+			}
+			if (xo == xi && abs(yi - yo + iradius - oradius) < 2) {
+				if (yul == -1) 
+					yul = yi + iradius;
+				if (abs(yul - yo - oradius) < 2) 
+					tu++;
+				else {
+					tu = 0;
+					yul = yi + iradius;
+				}
+			}
+			// do enclosure
+			if (enclosure == 256) {
+				SplashCoord curX, curY;
+				SplashCoord xMin, xMax;
+				Guchar dummy;
+				xll = (tl >= 6) ? xi - iradius : 0;
+				xrl = (tr >= 6) ? xi + iradius : bitmap->getWidth() - 1;
+				ydl = (td >= 6) ? yi - iradius : 0;
+				yul = (tu >= 6) ? yi + iradius : bitmap->getHeight() - 1;				
+				bresOuterPoints->getPoint(0, &curX, &curY, &dummy);
+				curY += yo;
+				for (int i = splashRound(curY) + 1; i < bitmap->getHeight(); i++)
+					if (i >= ydl && i <= yul)
+						drawPartCircleLine(&pipe, i, xll, xrl);
+				for (int i = 0; i < bresOuterPoints->getLength(); i++) {
+					bresOuterPoints->getPoint(i, &curX, &curY, &dummy);
+					curY += yo;
+					xMax = xo + curX;
+					xMin = xo - curX;
+					if (curY >= ydl && curY <= yul) {
+						if (xMin > 0)
+							drawPartCircleLine(&pipe, curY, xll, xMin);
+						if (xMax < bitmap->getWidth())
+							drawPartCircleLine(&pipe, curY, xMax, xrl);
+					}
+					curY = 2 * yo - curY;
+					if (curY >= ydl && curY <= yul) {
+						if (xMin > 0)
+							drawPartCircleLine(&pipe, curY, xll, xMin);
+						if (xMax < bitmap->getWidth())
+							drawPartCircleLine(&pipe, curY, xMax, xrl);
+					}
+				}
+				bresOuterPoints->getPoint(0, &curX, &curY, &dummy);
+				curY = yo - curY;
+				for (int i = 0; i < curY; i++)
+					if (i >= ydl && i <= yul)
+						drawPartCircleLine(&pipe, i, xll, xrl);
+				delete bresOuterPoints;
+				bresOuterPoints = bresInnerPoints;
+				break;
+			}
+			// do tangents if other side is completely outside
+			if (tl >= 256) {
+				if (shading->encloseCircle(xi, yi, iradius, bitmap->getWidth() - 1, bitmap->getHeight() - 1, 0) &&
+					shading->encloseCircle(xi, yi, iradius, bitmap->getWidth() - 1, 0, 0)) {
+						for (int i = 0; i < bitmap->getHeight(); i++)
+							drawPartCircleLine(&pipe, i, xi - iradius, xi - iradius);
+						delete bresOuterPoints;
+						bresOuterPoints = bresInnerPoints;
+						break;
+				}
+			}
+			if (tr >= 256) {
+				if (shading->encloseCircle(xi, yi, iradius, 0, bitmap->getHeight() - 1, 0) &&
+					shading->encloseCircle(xi, yi, iradius, 0, 0, 0)) {
+						for (int i = 0; i < bitmap->getHeight(); i++)
+							drawPartCircleLine(&pipe, i, xi + iradius, xi + iradius);
+						delete bresOuterPoints;
+						bresOuterPoints = bresInnerPoints;
+						break;
+				}
+			}
+			if (tu >= 256) {
+				if (shading->encloseCircle(xi, yi, iradius, bitmap->getWidth() - 1, 0, 0) &&
+					shading->encloseCircle(xi, yi, iradius, 0, 0, 0)) {
+						drawPartCircleLine(&pipe, yi + iradius, 0, bitmap->getWidth() - 1);
+						delete bresOuterPoints;
+						bresOuterPoints = bresInnerPoints;
+						break;
+				}
+			}
+			if (td >= 256) {
+				if (shading->encloseCircle(xi, yi, iradius, bitmap->getWidth() - 1, bitmap->getHeight() - 1, 0) &&
+					shading->encloseCircle(xi, yi, iradius, 0, bitmap->getHeight() - 1, 0)) {
+						drawPartCircleLine(&pipe, yi - iradius, 0, bitmap->getWidth() - 1);
+						delete bresOuterPoints;
+						bresOuterPoints = bresInnerPoints;
+						break;
+				}
+			}
+			delete bresOuterPoints;
+			bresOuterPoints = bresInnerPoints;
+			yo = yi; xo = xi; oradius = iradius;
+		}
+		delete bresOuterPoints;
+	}
+
+	shading->getStartCircle(&xo, &yo, &oradius, cur);
+	if (oradius == 0)
+		drawPartCircleLine(&pipe, yo, xo, xo);
+	SplashPath *bresOuterPoints = getBresenhamPoints(xo, yo, oradius);
+	if (bresOuterPoints == NULL)
+		return splashErrEmptyPath;
+	tl = tr = tu = td = 0;
+	ydl = xll = yul = xrl = -1;
+	while (shading->getNextCircle(&xi, &yi, &iradius, curNext)) {
+		if (xi == xo && yi == yo && iradius == oradius) {
+			splashColorCopy(cur, curNext);
+			continue;
+		}
+		// test for tangents
+		if (yo == yi && abs(xi - xo + oradius - iradius) < 2) {
+			if (xll == -1) 
+				xll = xi - iradius;
+			if (abs(xll - xo + oradius) < 2) 
+				tl++;
+			else {
+				tl = 0;
+				xll = xi - iradius;
+			}
+		}
+		if (yo == yi && abs(xi - xo + iradius - oradius) < 2) {
+			if (xrl == -1) 
+				xrl = xi + iradius;
+			if (abs(xrl - xo - oradius) < 2) 
+				tr++;
+			else {
+				tr = 0;
+				xrl = xi + iradius;
+			}
+		}
+		if (xo == xi && abs(yi - yo + oradius - iradius) < 2) {
+			if (ydl == -1) 
+				ydl = yi - iradius;
+			if (abs(ydl - yo + oradius) < 2) 
+				td++;
+			else {
+				td = 0;
+				ydl = yi - iradius;
+			}
+		}
+		if (xo == xi && abs(yi - yo + iradius - oradius) < 2) {
+			if (yul == -1) 
+				yul = yi + iradius;
+			if (abs(yul - yo - oradius) < 2) 
+				tu++;
+			else {
+				tu = 0;
+				yul = yi + iradius;
+			}
+		}
+		if (shading->testClip(xi, yi, iradius) != splashClipAllOutside) {
+			SplashPath *bresInnerPoints = drawCircle(xo, yo, oradius, cur, bresOuterPoints,
+				xi, yi, iradius, curNext, fExtend, &pipe);
+			if (bresInnerPoints == NULL)
+				break;
+			delete bresOuterPoints;
+			bresOuterPoints = bresInnerPoints;
+		}
+		if (shading->testClip(xi, yi, iradius) == splashClipAllInside && iradius >= oradius)
+			break;
+		// do tangents if other side is completely outside
+		if (tl >= 256 && fExtend) {
+			if (shading->encloseCircle(xi, yi, iradius, bitmap->getWidth() - 1, bitmap->getHeight() - 1, 0) &&
+				shading->encloseCircle(xi, yi, iradius, bitmap->getWidth() - 1, 0, 0)) {
+					break;
+			}
+		}
+		if (tr >= 256 && fExtend) {
+			if (shading->encloseCircle(xi, yi, iradius, 0, bitmap->getHeight() - 1, 0) &&
+				shading->encloseCircle(xi, yi, iradius, 0, 0, 0)) {
+					break;
+			}
+		}
+		if (tu >= 256 && fExtend) {
+			if (shading->encloseCircle(xi, yi, iradius, bitmap->getWidth() - 1, 0, 0) &&
+				shading->encloseCircle(xi, yi, iradius, 0, 0, 0)) {
+					break;
+			}
+		}
+		if (td >= 256 && fExtend) {
+			if (shading->encloseCircle(xi, yi, iradius, bitmap->getWidth() - 1, bitmap->getHeight() - 1, 0) &&
+				shading->encloseCircle(xi, yi, iradius, 0, bitmap->getHeight() - 1, 0)) {
+					break;
+			}
+		}
+		yo = yi; xo = xi; oradius = iradius;
+	} 
+	delete bresOuterPoints;
+
+	// extend ending circle
+	if (!fExtend && shading->getSmallerExtendCircle(&xo, &yo, &oradius, cur, fExtend)) {
+		SplashPath *bresOuterPoints = getBresenhamPoints(xo, yo, oradius);
+		if (bresOuterPoints == NULL)
+			return splashErrEmptyPath;
+		while (shading->getNextSmallerExtendCircle(&xi, &yi, &iradius, fExtend)) {
+			if (xi == xo && yi == yo && iradius == oradius) {
+				continue;
+			}
+			if (shading->testClip(xo, yo, oradius) == splashClipAllOutside)
+				break;
+			SplashPath *bresInnerPoints = drawCircle(xo, yo, oradius, cur, bresOuterPoints,
+				xi, yi, iradius, cur, fExtend, &pipe);
+			if (bresInnerPoints == NULL)
+				break;
+			delete bresOuterPoints;
+			bresOuterPoints = bresInnerPoints;
+			yo = yi; xo = xi; oradius = iradius;
+		}
+		delete bresOuterPoints;
+	}
+	if (fExtend && shading->getLargerExtendCircle(&xo, &yo, &oradius, cur)) {
+		tl = tr = tu = td = enclosure = 0;
+		ydl = xll = yul = xrl = -1;
+		SplashPath *bresOuterPoints = getBresenhamPoints(xo, yo, oradius);
+		if (bresOuterPoints == NULL)
+			return splashErrEmptyPath;
+		// don't fill the circle here, just extend:
+		while (shading->getNextLargerExtendCircle(&xi, &yi, &iradius, gTrue)) {
+			if (xi == xo && yi == yo && iradius == oradius) {
+				continue;
+			}
+			if (shading->testClip(xo, yo, oradius) == splashClipAllInside)
+				break;
+			SplashPath *bresInnerPoints = drawCircle(xo, yo, oradius, cur, bresOuterPoints,
+				xi, yi, iradius, cur, gTrue, &pipe);
+			if (bresInnerPoints == NULL)
+				break;
+			// test for enclosure
+			if (shading->encloseCircle(xi, yi, iradius, xo, yo, oradius))
+				enclosure++;
+			else
+				enclosure = 0;
+			// test for tangents
+			if (yo == yi && abs(xi - xo + oradius - iradius) < 2) {
+				if (xll == -1) 
+					xll = xi - iradius;
+				if (abs(xll - xo + oradius) < 2) 
+					tl++;
+				else {
+					tl = 0;
+					xll = xi - iradius;
+				}
+			}
+			if (yo == yi && abs(xi - xo + iradius - oradius) < 2) {
+				if (xrl == -1) 
+					xrl = xi + iradius;
+				if (abs(xrl - xo - oradius) < 2) 
+					tr++;
+				else {
+					tr = 0;
+					xrl = xi + iradius;
+				}
+			}
+			if (xo == xi && abs(yi - yo + oradius - iradius) < 2) {
+				if (ydl == -1) 
+					ydl = yi - iradius;
+				if (abs(ydl - yo + oradius) < 2) 
+					td++;
+				else {
+					td = 0;
+					ydl = yi - iradius;
+				}
+			}
+			if (xo == xi && abs(yi - yo + iradius - oradius) < 2) {
+				if (yul == -1) 
+					yul = yi + iradius;
+				if (abs(yul - yo - oradius) < 2) 
+					tu++;
+				else {
+					tu = 0;
+					yul = yi + iradius;
+				}
+			}
+			// do enclosure
+			if (enclosure == 256) {
+				SplashCoord curX, curY;
+				SplashCoord xMin, xMax;
+				Guchar dummy;
+				xll = (tl >= 6) ? xi - iradius : 0;
+				xrl = (tr >= 6) ? xi + iradius : bitmap->getWidth() - 1;
+				ydl = (td >= 6) ? yi - iradius : 0;
+				yul = (tu >= 6) ? yi + iradius : bitmap->getHeight() - 1;				
+				bresOuterPoints->getPoint(0, &curX, &curY, &dummy);
+				curY += yo;
+				for (int i = splashRound(curY) + 1; i < bitmap->getHeight(); i++)
+					if (i >= ydl && i <= yul)
+						drawPartCircleLine(&pipe, i, xll, xrl);
+				for (int i = 0; i < bresOuterPoints->getLength(); i++) {
+					bresOuterPoints->getPoint(i, &curX, &curY, &dummy);
+					curY += yo;
+					xMax = xo + curX;
+					xMin = xo - curX;
+					if (curY >= ydl && curY <= yul) {
+						if (xMin > 0)
+							drawPartCircleLine(&pipe, curY, xll, xMin);
+						if (xMax < bitmap->getWidth())
+							drawPartCircleLine(&pipe, curY, xMax, xrl);
+					}
+					curY = 2 * yo - curY;
+					if (curY >= ydl && curY <= yul) {
+						if (xMin > 0)
+							drawPartCircleLine(&pipe, curY, xll, xMin);
+						if (xMax < bitmap->getWidth())
+							drawPartCircleLine(&pipe, curY, xMax, xrl);
+					}
+				}
+				bresOuterPoints->getPoint(0, &curX, &curY, &dummy);
+				curY = yo - curY;
+				for (int i = 0; i < curY; i++)
+					if (i >= ydl && i <= yul)
+						drawPartCircleLine(&pipe, i, xll, xrl);
+				delete bresOuterPoints;
+				bresOuterPoints = bresInnerPoints;
+				break;
+			}
+			// do tangents if other side is completely outside
+			if (tl >= 256) {
+				if (shading->encloseCircle(xi, yi, iradius, bitmap->getWidth() - 1, bitmap->getHeight() - 1, 0) &&
+					shading->encloseCircle(xi, yi, iradius, bitmap->getWidth() - 1, 0, 0)) {
+						for (int i = 0; i < bitmap->getHeight(); i++)
+							drawPartCircleLine(&pipe, i, xi - iradius, xi - iradius);
+						delete bresOuterPoints;
+						bresOuterPoints = bresInnerPoints;
+						break;
+				}
+			}
+			if (tr >= 256) {
+				if (shading->encloseCircle(xi, yi, iradius, 0, bitmap->getHeight() - 1, 0) &&
+					shading->encloseCircle(xi, yi, iradius, 0, 0, 0)) {
+						for (int i = 0; i < bitmap->getHeight(); i++)
+							drawPartCircleLine(&pipe, i, xi + iradius, xi + iradius);
+						delete bresOuterPoints;
+						bresOuterPoints = bresInnerPoints;
+						break;
+				}
+			}
+			if (tu >= 256) {
+				if (shading->encloseCircle(xi, yi, iradius, bitmap->getWidth() - 1, 0, 0) &&
+					shading->encloseCircle(xi, yi, iradius, 0, 0, 0)) {
+						drawPartCircleLine(&pipe, yi + iradius, 0, bitmap->getWidth() - 1);
+						delete bresOuterPoints;
+						bresOuterPoints = bresInnerPoints;
+						break;
+				}
+			}
+			if (td >= 256) {
+				if (shading->encloseCircle(xi, yi, iradius, bitmap->getWidth() - 1, bitmap->getHeight() - 1, 0) &&
+					shading->encloseCircle(xi, yi, iradius, 0, bitmap->getHeight() - 1, 0)) {
+						drawPartCircleLine(&pipe, yi - iradius, 0, bitmap->getWidth() - 1);
+						delete bresOuterPoints;
+						bresOuterPoints = bresInnerPoints;
+						break;
+				}
+			}
+			delete bresOuterPoints;
+			bresOuterPoints = bresInnerPoints;
+			yo = yi; xo = xi; oradius = iradius;
+		}
+		delete bresOuterPoints;
+	}
+	return splashOk;
+}
+
 SplashError Splash::blitTransparent(SplashBitmap *src, int xSrc, int ySrc,
 				    int xDest, int yDest, int w, int h) {
   SplashColor pixel;
@@ -3950,19 +4619,25 @@ SplashError Splash::shadedFill(SplashPath *path, GBool hasBBox,
   int xMinI, yMinI, xMaxI, yMaxI, x0, x1, y;
   SplashClipResult clipRes;
 
-  if (aaBuf == NULL) { // should not happen, but to be secure
+  if (vectorAntialias && aaBuf == NULL) { // should not happen, but to be secure
     return splashErrGeneric;
   }
   if (path->length == 0) {
     return splashErrEmptyPath;
   }
   xPath = new SplashXPath(path, state->matrix, state->flatness, gTrue);
-  xPath->aaScale();
+  if (vectorAntialias) {
+    xPath->aaScale();
+  }
   xPath->sort();
   scanner = new SplashXPathScanner(xPath, gFalse);
 
-  // get the min and max x and y values
-  scanner->getBBoxAA(&xMinI, &yMinI, &xMaxI, &yMaxI);
+  // get the min and max x and y values
+  if (vectorAntialias) {
+    scanner->getBBoxAA(&xMinI, &yMinI, &xMaxI, &yMaxI);
+  } else {
+    scanner->getBBox(&xMinI, &yMinI, &xMaxI, &yMaxI);
+  }
 
   // check clipping
   if ((clipRes = state->clip->testRect(xMinI, yMinI, xMaxI, yMaxI)) != splashClipAllOutside) {
@@ -3977,13 +4652,34 @@ SplashError Splash::shadedFill(SplashPath *path, GBool hasBBox,
     pipeInit(&pipe, 0, yMinI, pattern, NULL, state->fillAlpha, vectorAntialias && !hasBBox, gFalse);
 
     // draw the spans
-    for (y = yMinI; y <= yMaxI; ++y) {
-      scanner->renderAALine(aaBuf, &x0, &x1, y);
-      if (clipRes != splashClipAllInside) {
-        state->clip->clipAALine(aaBuf, &x0, &x1, y);
-      }
-      drawAALine(&pipe, x0, x1, y);
-    }
+    if (vectorAntialias) {
+		for (y = yMinI; y <= yMaxI; ++y) {
+			scanner->renderAALine(aaBuf, &x0, &x1, y);
+			if (clipRes != splashClipAllInside) {
+				state->clip->clipAALine(aaBuf, &x0, &x1, y);
+			}
+			drawAALine(&pipe, x0, x1, y);
+		}
+	} else {
+		SplashClipResult clipRes2;
+		for (y = yMinI; y <= yMaxI; ++y) {
+			while (scanner->getNextSpan(y, &x0, &x1)) {
+				if (clipRes == splashClipAllInside) {
+					drawSpan(&pipe, x0, x1, y, gTrue);
+				} else {
+					// limit the x range
+					if (x0 < state->clip->getXMinI()) {
+						x0 = state->clip->getXMinI();
+					}
+					if (x1 > state->clip->getXMaxI()) {
+						x1 = state->clip->getXMaxI();
+					}
+					clipRes2 = state->clip->testSpan(x0, x1, y);
+					drawSpan(&pipe, x0, x1, y, clipRes2 == splashClipAllInside);
+				}
+			}
+		}
+	}
   }
   opClipRes = clipRes;
 
diff --git a/splash/Splash.h b/splash/Splash.h
index a52dc13..a06f694 100644
--- a/splash/Splash.h
+++ b/splash/Splash.h
@@ -255,6 +255,17 @@ public:
                          SplashPattern *pattern);
   // Draw a gouraud triangle shading.
   GBool gouraudTriangleShadedFill(SplashGouraudColor *shading);
+  // Draw a radial shading.
+  void drawPartCircleLine(SplashPipe *pipe, SplashCoord y, SplashCoord xMin, SplashCoord xMax);
+  void drawBCircleLine(SplashPipe *pipe, SplashPath *bresInnerPoints,
+					   SplashCoord y, SplashCoord yiMin, SplashCoord yiMax,
+					   SplashCoord yi, SplashCoord xi, SplashCoord iradius,
+					   SplashCoord xMin, SplashCoord xMax, int lineWidth);
+  SplashPath *getBresenhamPoints(SplashCoord x0, SplashCoord y0, SplashCoord radius);
+  SplashPath *drawCircle(SplashCoord xo, SplashCoord yo, SplashCoord oradius, SplashColorPtr cur, 
+						SplashPath *bresOuterPoints, SplashCoord xi, SplashCoord yi, SplashCoord iradius, 
+						SplashColorPtr curNext, GBool fExtend, SplashPipe *pipe);
+  SplashError radialShadedFill(SplashRadialColor *shading);
 
 private:
 
diff --git a/splash/SplashPattern.h b/splash/SplashPattern.h
index 09e9b1a..0db9ed2 100644
--- a/splash/SplashPattern.h
+++ b/splash/SplashPattern.h
@@ -26,8 +26,11 @@
 #endif
 
 #include "SplashTypes.h"
+#include "SplashClip.h"
 
 class SplashScreen;
+class Splash;
+class SplashBitmap;
 
 //------------------------------------------------------------------------
 // SplashPattern
@@ -92,4 +95,26 @@ public:
   virtual void getParameterizedColor(double t, SplashColorMode mode, SplashColorPtr c) = 0;
 };
 
+//------------------------------------------------------------------------
+// SplashRadialColor (needed for radialShadedFill)
+//------------------------------------------------------------------------
+
+class SplashRadialColor: public SplashPattern {
+public:
+	virtual void getStartCircle(SplashCoord *x0, SplashCoord *y0, SplashCoord *radius, SplashColorPtr c) = 0;
+	virtual GBool getNextCircle(SplashCoord *x0, SplashCoord *y0, SplashCoord *radius, SplashColorPtr c) = 0;
+	virtual GBool getSmallerExtendCircle(SplashCoord *x0, SplashCoord *y0, SplashCoord *radius, SplashColorPtr c, GBool fExtend) = 0;
+	virtual GBool getNextSmallerExtendCircle(SplashCoord *x0, SplashCoord *y0, SplashCoord *radius, GBool fExtend) = 0;
+	virtual GBool getLargerExtendCircle(SplashCoord *x0, SplashCoord *y0, SplashCoord *radius, SplashColorPtr c) = 0;
+	virtual GBool getNextLargerExtendCircle(SplashCoord *x0, SplashCoord *y0, SplashCoord *radius, GBool fExtend) = 0;
+	virtual SplashClipResult testClip(SplashCoord x, SplashCoord y, SplashCoord r) = 0;
+	virtual GBool encloseCircle(SplashCoord x0, SplashCoord y0, SplashCoord r0,
+		SplashCoord x1, SplashCoord y1, SplashCoord r1) = 0;
+	virtual GBool enlargeCircles() = 0;
+	virtual void getClipBBox(double *clipXMin, double *clipYMin, double *clipXMax, double *clipYMax) = 0;
+	virtual GBool isOk() = 0;
+	virtual Splash *getSplash() = 0;
+	virtual SplashBitmap *getBitmap() = 0;
+};
+
 #endif
