diff --git a/poppler/SplashOutputDev.cc b/poppler/SplashOutputDev.cc
index 0b3722a..81e70a5 100644
--- a/poppler/SplashOutputDev.cc
+++ b/poppler/SplashOutputDev.cc
@@ -153,6 +153,328 @@ 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 2048
+
+// 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
+
+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!):
+  sMax = 1;
+  sMin = 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();
+  if (shading->getHasBBox())
+	  shading->getBBox(&xMin, &yMin, &xMax, &yMax);
+  else 
+	  state->getUserClipBBox(&xMin, &yMin, &xMax, &yMax);
+  width = xMax - xMin;
+  height = yMax - yMin;
+  if (splashRound(xMax) - splashRound(xMin) > width)
+	width = splashRound(xMax) - splashRound(xMin);
+  if (splashRound(yMax) - splashRound(yMin) > height)
+	height = splashRound(yMax) - splashRound(yMin);
+  if (radialMaxSize > 0 && width > 0 && height > 0) {
+	  if ( width > height)
+		  scale = radialMaxSize / height;
+	  else
+		  scale = radialMaxSize / width;
+  } else
+	  scale = 1;
+  xMin *= scale;
+  xMax *= scale;
+  yMin *= scale;
+  yMax *= scale;
+  width *= scale;
+  height *= scale;
+  if (width > 0 && height > 0) {
+	  bitmap = new SplashBitmap(splashRound(width) + 2, splashRound(height) + 2, 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] -= xMin;
+  ictm.m[5] -= yMin;
+  maxSplits = splashRound((r0 - r1) * scale / 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;
+  Guchar *bitmapAlpha;
+
+  bitmapAlpha = bitmap->getAlphaPtr();
+  ictm.transform(x, y, &xc, &yc);
+  xs = splashRound(xc);
+  ys = splashRound(yc);
+  // 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:
+  if (xs < 0) xs = 0;
+  if (xs >= bitmap->getWidth()) xs = bitmap->getWidth() - 1;
+  if (ys < 0) ys = 0;
+  if (ys >= bitmap->getHeight()) ys = bitmap->getHeight() - 1;
+  if (bitmapAlpha[ys * bitmap->getWidth() + xs])
+	  bitmap->getPixel(xs, ys, c);
+  else
+	  return gFalse;
+  return gTrue;
+}
+
+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 = sMin;
+  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 = splashRound(ra * scale); 
+  *xsc = splashRound(xa * scale - xMin); *ysc = splashRound(ya * scale - yMin); 
+  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 + 1 >= maxSplits)
+	  return gFalse;
+  getShadingColorRadialHelper(t0, t1, ta, shading, &colorA);
+  ib = maxSplits;
+  sb = (r0 > r1) ? sMax : sMin;
+  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 = sMin + factor * (sMax - sMin);
+			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 = sMin + factor * (sMax - sMin);
+		  tb = t0 + sb * (t1 - t0);
+		  getShadingColorRadialHelper(t0, t1, tb, shading, &colorB);
+		  break;
+      }
+      ib = (ia + ib) / 2;
+	  factor = (double)ib / (double)maxSplits; 
+      sb = sMin + factor * (sMax - sMin);
+      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 = splashRound(ra * scale); 
+  *xsc = splashRound(xa * scale - xMin); *ysc = splashRound(ya * scale - yMin); 
+  convertGfxColor(c, colorMode, srcColorSpace, &colorB);
+  ia = ib;
+  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 = splashRound(ra * scale); 
+		  *xsc = splashRound(xa * scale - xMin); *ysc = splashRound(ya * scale - yMin); 
+		  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 >= radialMinSplits)
+	  return gFalse;
+  sStart = (r0 > r1) ? sMin : sMax;
+  // buest guess:
+  sEnd = (fExtend) ? sMax * 16 : -sMax * 16; 
+  factor = (double)ia / (double)radialMinSplits; 
+  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 - xMin;
+  ya = ya * scale - yMin;
+  if (ya - ra < yMin && ya + ra > yMax && xa - ra < xMin && xa + ra > xMax)
+	  ia = radialMinSplits;
+  *radius = splashRound(ra); 
+  *xsc = splashRound(xa); *ysc = splashRound(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) ? sMin : sMax;
+		  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 = splashRound(ra * scale); 
+		  *xsc = splashRound(xa * scale - xMin); *ysc = splashRound(ya * scale - yMin); 
+		  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) ? sMax : sMin;
+  sStart = (r1!= r0) ? -r0 / (r1 - r0) : sMax * 16; 
+  if (!fExtend) {
+	  sEnd = sStart; 
+	  sStart = (r1 > r0) ? sMin : sMax;
+  }
+  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 = splashRound(ra * scale); 
+  *xsc = splashRound(xa * scale - xMin); *ysc = splashRound(ya * scale - yMin); 
+  return gTrue;
+}
+
+//------------------------------------------------------------------------
 // SplashAxialPattern
 //------------------------------------------------------------------------
 
@@ -3011,14 +3333,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 +3701,34 @@ 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;
+  // get the clip region bbox
+  state->getUserClipBBox(&xMin, &yMin, &xMax, &yMax);
+  // fill the region
+  state->moveTo(xMin, yMin);
+  state->lineTo(xMax, yMin);
+  state->lineTo(xMax, yMax);
+  state->lineTo(xMin, yMax);
+  state->closePath();
+  path = convertPath(state, state->getPath());
+
+  SplashRadialColor *pattern = new SplashRadialPattern(state, shading, sMin, sMax, colorMode);
+  if (pattern->isOk()) {
+	  // 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 pattern;
+  delete path;
+
+  return retVal;
+}
diff --git a/poppler/SplashOutputDev.h b/poppler/SplashOutputDev.h
index 570d036..85fc130 100644
--- a/poppler/SplashOutputDev.h
+++ b/poppler/SplashOutputDev.h
@@ -105,6 +105,49 @@ 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, sMin, sMax, 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; }
+private:
+  GfxRadialShading *shading;
+  GfxState *state;
+  Matrix ictm;
+  double sMin, sMax;
+  double xMin, xMax, yMin, yMax;
+  double scale;
+  double xa, ya, ra, ta, sa;
+  int ia;
+  int maxSplits;
+  double x0, y0, r0, x1, y1, r1, t0, t1;
+  Splash *splash;
+  SplashBitmap *bitmap;
+  SplashColorMode colorMode;
+};
+
 //------------------------------------------------------------------------
 
 // number of Type 3 fonts to cache
@@ -132,7 +175,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 +229,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..0c906b6 100644
--- a/splash/Splash.cc
+++ b/splash/Splash.cc
@@ -3531,6 +3531,336 @@ 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 - xMin > lineWidth) ? xiMin : xMin + lineWidth);
+				drawPartCircleLine(pipe, y, (xMax - xiMax > lineWidth) ? xiMax : xMax - lineWidth, 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);
+		}
+	}
+	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;
+	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;
+		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;
+		for (int i = 0; i < bresOuterPoints->getLength(); i++) {
+			SplashCoord curX, curY;
+			bresOuterPoints->getPoint(i, &curX, &curY, &dummy);
+			curY += yo;
+			xMax = xo + curX;
+			xMin = xo - curX;
+			if (curY >= 0 && curY < bitmap->getHeight())
+				drawPartCircleLine(&pipe, curY, xMin, xMax);
+			curY = 2 * yo - curY;
+			if (curY >= 0 && curY < bitmap->getHeight())
+				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;
+			delete bresOuterPoints;
+			bresOuterPoints = bresInnerPoints;
+			yo = yi; xo = xi; oradius = iradius;
+		}
+		delete bresOuterPoints;
+	}
+
+	shading->getStartCircle(&xo, &yo, &oradius, cur);
+	SplashPath *bresOuterPoints = getBresenhamPoints(xo, yo, oradius);
+	if (bresOuterPoints == NULL)
+		return splashErrEmptyPath;
+	while (shading->getNextCircle(&xi, &yi, &iradius, curNext)) {
+		if (xi == xo && yi == yo && iradius == oradius) {
+			splashColorCopy(cur, curNext);
+			continue;
+		}
+		SplashPath *bresInnerPoints = drawCircle(xo, yo, oradius, cur, bresOuterPoints,
+			xi, yi, iradius, curNext, fExtend, &pipe);
+		if (bresInnerPoints == NULL)
+			break;
+		delete bresOuterPoints;
+		bresOuterPoints = bresInnerPoints;
+		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;
+			}
+			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;
+		// don't fill the circle here, just extend:
+		while (shading->getNextLargerExtendCircle(&xi, &yi, &iradius, gTrue)) {
+			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;
+			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 +4280,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 +4313,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..02cc18d 100644
--- a/splash/SplashPattern.h
+++ b/splash/SplashPattern.h
@@ -28,6 +28,8 @@
 #include "SplashTypes.h"
 
 class SplashScreen;
+class Splash;
+class SplashBitmap;
 
 //------------------------------------------------------------------------
 // SplashPattern
@@ -92,4 +94,22 @@ 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 GBool enlargeCircles() = 0;
+	virtual GBool isOk() = 0;
+	virtual Splash *getSplash() = 0;
+	virtual SplashBitmap *getBitmap() = 0;
+};
+
 #endif

