[poppler] poppler/CairoOutputDev.h poppler/Function.cc poppler/Function.h poppler/Gfx.cc poppler/OutputDev.h poppler/PSOutputDev.h poppler/SplashOutputDev.cc poppler/SplashOutputDev.h splash/SplashBitmap.cc splash/SplashBitmap.h splash/Splash.cc splash/Splash.h splash/SplashPattern.cc splash/SplashPattern.h

Albert Astals Cid aacid at kemper.freedesktop.org
Thu Nov 4 14:00:46 PDT 2010


 poppler/CairoOutputDev.h   |    5 
 poppler/Function.cc        |    4 
 poppler/Function.h         |    2 
 poppler/Gfx.cc             |   12 -
 poppler/OutputDev.h        |   16 +
 poppler/PSOutputDev.h      |    4 
 poppler/SplashOutputDev.cc |  182 ++++++++++++++++++++
 poppler/SplashOutputDev.h  |   68 +++++++
 splash/Splash.cc           |  395 ++++++++++++++++++++++++++++++++++++++++++++-
 splash/Splash.h            |   11 +
 splash/SplashBitmap.cc     |    4 
 splash/SplashBitmap.h      |    3 
 splash/SplashPattern.cc    |   17 +
 splash/SplashPattern.h     |   36 +++-
 14 files changed, 735 insertions(+), 24 deletions(-)

New commits:
commit fa7c41cb9c52ecd3d7c574455b1258a3021b8c75
Author: Albert Astals Cid <aacid at kde.org>
Date:   Thu Nov 4 20:55:34 2010 +0000

    Improvements to the splash backend
    
    Antialias and shadings.
    Code by Thomas Freitag <Thomas.Freitag at alfa.de> and Christian Feuersänger <cfeuersaenger at googlemail.com>
    More info at bug 30436

diff --git a/poppler/CairoOutputDev.h b/poppler/CairoOutputDev.h
index e003d83..26efadc 100644
--- a/poppler/CairoOutputDev.h
+++ b/poppler/CairoOutputDev.h
@@ -20,6 +20,7 @@
 // Copyright (C) 2006-2010 Carlos Garcia Campos <carlosgc at gnome.org>
 // Copyright (C) 2008, 2009 Adrian Johnson <ajohnson at redneon.com>
 // Copyright (C) 2008 Michael Vrable <mvrable at cs.ucsd.edu>
+// Copyright (C) 2010 Thomas Freitag <Thomas.Freitag at alfa.de>
 //
 // To see a description of the changes please see the Changelog file that
 // came with your tarball or type make ChangeLog if you are building from git
@@ -106,7 +107,7 @@ public:
   // Does this device use functionShadedFill(), axialShadedFill(), and
   // radialShadedFill()?  If this returns false, these shaded fills
   // will be reduced to a series of other drawing operations.
-  virtual GBool useShadedFills() { return gTrue; }
+  virtual GBool useShadedFills(int type) { return type < 4; }
 
   // Does this device use FillColorStop()?
   virtual GBool useFillColorStop() { return gTrue; }
@@ -360,7 +361,7 @@ public:
   // Does this device use functionShadedFill(), axialShadedFill(), and
   // radialShadedFill()?  If this returns false, these shaded fills
   // will be reduced to a series of other drawing operations.
-  virtual GBool useShadedFills() { return gTrue; }
+  virtual GBool useShadedFills(int type) { return type < 4; }
 
   // Does this device use FillColorStop()?
   virtual GBool useFillColorStop() { return gFalse; }
diff --git a/poppler/Function.cc b/poppler/Function.cc
index 4ab32cb..0a72278 100644
--- a/poppler/Function.cc
+++ b/poppler/Function.cc
@@ -15,6 +15,7 @@
 //
 // Copyright (C) 2006, 2008-2010 Albert Astals Cid <aacid at kde.org>
 // Copyright (C) 2006 Jeff Muizelaar <jeff at infidigm.net>
+// Copyright (C) 2010 Christian Feuersänger <cfeuersaenger at googlemail.com>
 //
 // To see a description of the changes please see the Changelog file that
 // came with your tarball or type make ChangeLog if you are building from git
@@ -528,6 +529,7 @@ ExponentialFunction::ExponentialFunction(Object *funcObj, Dict *dict) {
   e = obj1.getNum();
   obj1.free();
 
+  isLinear = fabs(e-1.) < 1e-10;
   ok = gTrue;
   return;
 
@@ -558,7 +560,7 @@ void ExponentialFunction::transform(double *in, double *out) {
     x = in[0];
   }
   for (i = 0; i < n; ++i) {
-    out[i] = c0[i] + pow(x, e) * (c1[i] - c0[i]);
+    out[i] = c0[i] + (isLinear ? x : pow(x, e)) * (c1[i] - c0[i]);
     if (hasRange) {
       if (out[i] < range[i][0]) {
 	out[i] = range[i][0];
diff --git a/poppler/Function.h b/poppler/Function.h
index 297401c..3541775 100644
--- a/poppler/Function.h
+++ b/poppler/Function.h
@@ -14,6 +14,7 @@
 // under GPL version 2 or later
 //
 // Copyright (C) 2009, 2010 Albert Astals Cid <aacid at kde.org>
+// Copyright (C) 2010 Christian Feuersänger <cfeuersaenger at googlemail.com>
 //
 // To see a description of the changes please see the Changelog file that
 // came with your tarball or type make ChangeLog if you are building from git
@@ -176,6 +177,7 @@ private:
   double c0[funcMaxOutputs];
   double c1[funcMaxOutputs];
   double e;
+  bool isLinear;
   GBool ok;
 };
 
diff --git a/poppler/Gfx.cc b/poppler/Gfx.cc
index d11845c..825d98c 100644
--- a/poppler/Gfx.cc
+++ b/poppler/Gfx.cc
@@ -2307,7 +2307,7 @@ void Gfx::doFunctionShFill(GfxFunctionShading *shading) {
   double x0, y0, x1, y1;
   GfxColor colors[4];
 
-  if (out->useShadedFills() &&
+  if (out->useShadedFills( shading->getType() ) &&
       out->functionShadedFill(state, shading)) {
     return;
   }
@@ -2490,7 +2490,7 @@ void Gfx::doAxialShFill(GfxAxialShading *shading) {
     }
   }
 
-  if (out->useShadedFills() &&
+  if (out->useShadedFills( shading->getType() ) &&
       out->axialShadedFill(state, shading, tMin, tMax)) {
 	  return;
   }
@@ -2764,7 +2764,7 @@ void Gfx::doRadialShFill(GfxRadialShading *shading) {
     theta = 0;
     sz = 0; // make gcc happy
   } else {
-    sz = -r0 / (r1 - r0);
+    sz = (r1 > r0) ? -r0 / (r1 - r0) : -r1 / (r0 - r1);
     xz = x0 + sz * (x1 - x0);
     yz = y0 + sz * (y1 - y0);
     enclosed = (xz - x0) * (xz - x0) + (yz - y0) * (yz - y0) <= r0 * r0;
@@ -2842,7 +2842,7 @@ void Gfx::doRadialShFill(GfxRadialShading *shading) {
     }
   }
 
-  if (out->useShadedFills() &&
+  if (out->useShadedFills( shading->getType() ) &&
       out->radialShadedFill(state, shading, sMin, sMax)) {
     return;
   }
@@ -3115,6 +3115,10 @@ void Gfx::doGouraudTriangleShFill(GfxGouraudTriangleShading *shading) {
   double x0, y0, x1, y1, x2, y2;
   int i;
 
+  if( out->useShadedFills( shading->getType() ) ) {
+    if( out->gouraudTriangleShadedFill( state, shading ) )
+      return;
+  }
   // preallocate a path (speed improvements)
   state->moveTo(0., 0.);
   state->lineTo(1., 0.);
diff --git a/poppler/OutputDev.h b/poppler/OutputDev.h
index cdc74cf..057d84a 100644
--- a/poppler/OutputDev.h
+++ b/poppler/OutputDev.h
@@ -17,9 +17,10 @@
 // Copyright (C) 2006 Thorkild Stray <thorkild at ifi.uio.no>
 // Copyright (C) 2007 Jeff Muizelaar <jeff at infidigm.net>
 // Copyright (C) 2007 Adrian Johnson <ajohnson at redneon.com>
-// Copyright (C) 2009 Thomas Freitag <Thomas.Freitag at alfa.de>
+// Copyright (C) 2009, 2010 Thomas Freitag <Thomas.Freitag at alfa.de>
 // Copyright (C) 2009 Carlos Garcia Campos <carlosgc at gnome.org>
 // Copyright (C) 2009 Albert Astals Cid <aacid at kde.org>
+// Copyright (C) 2010 Christian Feuersänger <cfeuersaenger at googlemail.com>
 //
 // To see a description of the changes please see the Changelog file that
 // came with your tarball or type make ChangeLog if you are building from git
@@ -47,6 +48,8 @@ class GfxColorSpace;
 class GfxImageColorMap;
 class GfxFunctionShading;
 class GfxAxialShading;
+class GfxGouraudTriangleShading;
+class GfxPatchMeshShading;
 class GfxRadialShading;
 class Stream;
 class Links;
@@ -82,10 +85,9 @@ public:
   // operations.
   virtual GBool useTilingPatternFill() { return gFalse; }
 
-  // Does this device use functionShadedFill(), axialShadedFill(), and
-  // radialShadedFill()?  If this returns false, these shaded fills
-  // will be reduced to a series of other drawing operations.
-  virtual GBool useShadedFills() { return gFalse; }
+  // Does this device support specific shading types?
+  // see gouraudTriangleShadedFill() and patchMeshShadedFill()
+  virtual GBool useShadedFills(int type) { return gFalse; }
 
   // Does this device use FillColorStop()?
   virtual GBool useFillColorStop() { return gFalse; }
@@ -208,6 +210,10 @@ public:
     { return gFalse; }
   virtual GBool radialShadedSupportExtend(GfxState * /*state*/, GfxRadialShading * /*shading*/)
     { return gFalse; }
+  virtual GBool gouraudTriangleShadedFill(GfxState *state, GfxGouraudTriangleShading *shading)
+    { return gFalse; }
+  virtual GBool patchMeshShadedFill(GfxState *state, GfxPatchMeshShading *shading)
+    { return gFalse; }
 
   //----- path clipping
   virtual void clip(GfxState * /*state*/) {}
diff --git a/poppler/PSOutputDev.h b/poppler/PSOutputDev.h
index 2ac7b13..02160b7 100644
--- a/poppler/PSOutputDev.h
+++ b/poppler/PSOutputDev.h
@@ -120,8 +120,8 @@ public:
   // Does this device use functionShadedFill(), axialShadedFill(), and
   // radialShadedFill()?  If this returns false, these shaded fills
   // will be reduced to a series of other drawing operations.
-  virtual GBool useShadedFills()
-    { return level >= psLevel2; }
+  virtual GBool useShadedFills(int type)
+    { return type < 4 && level >= psLevel2; }
 
   // Does this device use drawForm()?  If this returns false,
   // form-type XObjects will be interpreted (i.e., unrolled).
diff --git a/poppler/SplashOutputDev.cc b/poppler/SplashOutputDev.cc
index 33cef9e..0b3722a 100644
--- a/poppler/SplashOutputDev.cc
+++ b/poppler/SplashOutputDev.cc
@@ -26,6 +26,7 @@
 // Copyright (C) 2010 Patrick Spendrin <ps_ml at gmx.de>
 // Copyright (C) 2010 Brian Cameron <brian.cameron at oracle.com>
 // Copyright (C) 2010 Paweł Wiejacha <pawel.wiejacha at gmail.com>
+// Copyright (C) 2010 Christian Feuersänger <cfeuersaenger at googlemail.com>
 //
 // To see a description of the changes please see the Changelog file that
 // came with your tarball or type make ChangeLog if you are building from git
@@ -79,6 +80,126 @@ extern "C" int unlink(char *filename);
 #define isfinite(x) finite(x)
 #endif
 
+static inline void convertGfxColor(SplashColorPtr dest,
+                                   SplashColorMode colorMode,
+                                   GfxColorSpace *colorSpace,
+                                   GfxColor *src) {
+  SplashColor color;
+  GfxGray gray;
+  GfxRGB rgb;
+#if SPLASH_CMYK
+  GfxCMYK cmyk;
+#endif
+
+  switch (colorMode) {
+    case splashModeMono1:
+    case splashModeMono8:
+      colorSpace->getGray(src, &gray);
+      color[0] = colToByte(gray);
+    break;
+    case splashModeXBGR8:
+      color[3] = 255;
+    case splashModeBGR8:
+    case splashModeRGB8:
+      colorSpace->getRGB(src, &rgb);
+      color[0] = colToByte(rgb.r);
+      color[1] = colToByte(rgb.g);
+      color[2] = colToByte(rgb.b);
+    break;
+#if SPLASH_CMYK
+    case splashModeCMYK8:
+      colorSpace->getCMYK(src, &cmyk);
+      color[0] = colToByte(cmyk.c);
+      color[1] = colToByte(cmyk.m);
+      color[2] = colToByte(cmyk.y);
+      color[3] = colToByte(cmyk.k);
+    break;
+#endif
+  }
+  splashColorCopy(dest, color);
+}
+
+
+//------------------------------------------------------------------------
+// SplashGouraudPattern
+//------------------------------------------------------------------------
+SplashGouraudPattern::SplashGouraudPattern(GBool bDirectColorTranslationA,
+                                           GfxState *stateA, GfxGouraudTriangleShading *shadingA) {
+  state = stateA;
+  shading = shadingA;
+  bDirectColorTranslation = bDirectColorTranslationA;
+}
+
+SplashGouraudPattern::~SplashGouraudPattern() {
+}
+
+void SplashGouraudPattern::getParameterizedColor(double colorinterp, SplashColorMode mode, SplashColorPtr dest) {
+  GfxColor src;
+  GfxColorSpace* srcColorSpace = shading->getColorSpace();
+  int colorComps = 3;
+#if SPLASH_CMYK
+  if (mode == splashModeCMYK8)
+    colorComps=4;
+#endif
+
+  shading->getParameterizedColor(colorinterp, &src);
+
+  if (bDirectColorTranslation) {
+    for (int m = 0; m < colorComps; ++m)
+      dest[m] = colToByte(src.c[m]);
+  } else {
+    convertGfxColor(dest, mode, srcColorSpace, &src);
+  }
+}
+
+//------------------------------------------------------------------------
+// SplashAxialPattern
+//------------------------------------------------------------------------
+
+SplashAxialPattern::SplashAxialPattern(SplashColorMode colorModeA, GfxState *stateA, GfxAxialShading *shadingA) {
+  Matrix ctm;
+
+  shading = shadingA;
+  state = stateA;
+  colorMode = colorModeA;
+  state->getCTM(&ctm);
+  ctm.invertTo(&ictm);
+
+  shading->getCoords(&x0, &y0, &x1, &y1);
+  dx = x1 - x0;
+  dy = y1 - y0;
+  mul = 1 / (dx * dx + dy * dy);
+
+  // get the function domain
+  t0 = shading->getDomain0();
+  t1 = shading->getDomain1();
+}
+
+SplashAxialPattern::~SplashAxialPattern() {
+}
+
+GBool SplashAxialPattern::getColor(int x, int y, SplashColorPtr c) {
+  GfxColor gfxColor;
+  double tt;
+  double xc, yc, xaxis;
+
+  ictm.transform(x, y, &xc, &yc);
+  xaxis = ((xc - x0) * dx + (yc - y0) * dy) * mul;
+  if (xaxis < 0 && shading->getExtend0()) {
+    tt = t0;
+  } else if (xaxis > 1 && shading->getExtend1()) {
+    tt = t1;
+  } else if (xaxis >= 0 && xaxis <= 1) {
+    tt = t0 + (t1 -t0) * xaxis;
+  } else 
+    return gFalse;
+
+  shading->getColor(tt, &gfxColor);
+  state->setFillColor(&gfxColor);
+  convertGfxColor(c, colorMode, state->getFillColorSpace(), state->getFillColor());
+  return gTrue;
+}
+
 //------------------------------------------------------------------------
 
 // Divide a 16-bit value (in [0, 255*255]) by 255, returning an 8-bit result.
@@ -2048,7 +2169,7 @@ void SplashOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str,
     //~ this ignores the blendingColorSpace arg
     // create the temporary bitmap
     bitmap = new SplashBitmap(bitmap->getWidth(), bitmap->getHeight(), bitmapRowPad, colorMode, gTrue,
-                              bitmapTopDown); 
+                              bitmapTopDown);
     splash = new Splash(bitmap, vectorAntialias,
                         transpGroup->origSplash->getScreen());
     splash->blitTransparent(transpGroup->origBitmap, 0, 0, 0, 0, bitmap->getWidth(), bitmap->getHeight());
@@ -2931,7 +3052,7 @@ void SplashOutputDev::beginTransparencyGroup(GfxState *state, double *bbox,
 
   // create the temporary bitmap
   bitmap = new SplashBitmap(w, h, bitmapRowPad, colorMode, gTrue,
-			    bitmapTopDown); 
+			    bitmapTopDown);
   splash = new Splash(bitmap, vectorAntialias,
 		      transpGroup->origSplash->getScreen());
   if (isolated) {
@@ -3201,3 +3322,60 @@ void SplashOutputDev::setFreeTypeHinting(GBool enable)
 {
   enableFreeTypeHinting = enable;
 }
+
+GBool SplashOutputDev::gouraudTriangleShadedFill(GfxState *state, GfxGouraudTriangleShading *shading)
+{
+  GfxColorSpaceMode shadingMode = shading->getColorSpace()->getMode();
+  GBool bDirectColorTranslation = gFalse; // triggers an optimization.
+  switch (colorMode) {
+    case splashModeRGB8:
+      bDirectColorTranslation = (shadingMode == csDeviceRGB);
+    break;
+#if SPLASH_CMYK
+    case splashModeCMYK8:
+      bDirectColorTranslation = (shadingMode == csDeviceCMYK);
+    break;
+#endif
+    default:
+    break;
+  }
+  SplashGouraudColor *splashShading = new SplashGouraudPattern(bDirectColorTranslation, state, shading);
+  // restore vector antialias because we support it here
+  if (shading->isParameterized()) {
+    GBool vaa = getVectorAntialias();
+    GBool retVal = gFalse;
+    setVectorAntialias(gTrue);
+    retVal = splash->gouraudTriangleShadedFill(splashShading);
+    setVectorAntialias(vaa);
+    return retVal;
+  }
+  return gFalse;
+}
+
+GBool SplashOutputDev::axialShadedFill(GfxState *state, GfxAxialShading *shading, double tMin, double tMax) {
+  double xMin, yMin, xMax, yMax;
+  SplashPath *path;
+
+  GBool vaa = getVectorAntialias();
+  GBool retVal = gFalse;
+  // restore vector antialias because we support it here
+  setVectorAntialias(gTrue);
+  // 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());
+
+  SplashPattern *pattern = new SplashAxialPattern(colorMode, state, shading);
+  retVal = (splash->shadedFill(path, shading->getHasBBox(), pattern) == splashOk);
+  setVectorAntialias(vaa);
+  state->clearPath();
+  delete path;
+
+  return retVal;
+}
diff --git a/poppler/SplashOutputDev.h b/poppler/SplashOutputDev.h
index adbd196..570d036 100644
--- a/poppler/SplashOutputDev.h
+++ b/poppler/SplashOutputDev.h
@@ -16,6 +16,7 @@
 // Copyright (C) 2005 Takashi Iwai <tiwai at suse.de>
 // Copyright (C) 2009, 2010 Thomas Freitag <Thomas.Freitag at alfa.de>
 // Copyright (C) 2009 Carlos Garcia Campos <carlosgc at gnome.org>
+// Copyright (C) 2010 Christian Feuersänger <cfeuersaenger at googlemail.com>
 //
 // To see a description of the changes please see the Changelog file that
 // came with your tarball or type make ChangeLog if you are building from git
@@ -31,6 +32,7 @@
 
 #include "goo/gtypes.h"
 #include "splash/SplashTypes.h"
+#include "splash/SplashPattern.h"
 #include "poppler-config.h"
 #include "OutputDev.h"
 #include "GfxState.h"
@@ -39,7 +41,6 @@ class Gfx8BitFont;
 class SplashBitmap;
 class Splash;
 class SplashPath;
-class SplashPattern;
 class SplashFontEngine;
 class SplashFont;
 class T3FontCache;
@@ -48,6 +49,63 @@ struct T3GlyphStack;
 struct SplashTransparencyGroup;
 
 //------------------------------------------------------------------------
+// Splash dynamic pattern
+//------------------------------------------------------------------------
+
+class SplashAxialPattern: public SplashPattern {
+public:
+
+  SplashAxialPattern(SplashColorMode colorMode, GfxState *state, GfxAxialShading *shading);
+
+  virtual SplashPattern *copy() { return new SplashAxialPattern(colorMode, state, shading); }
+
+  virtual ~SplashAxialPattern();
+
+  virtual GBool getColor(int x, int y, SplashColorPtr c);
+
+  virtual GBool isStatic() { return gFalse; }
+
+private:
+  Matrix ictm;
+  double x0, y0, x1, y1;
+  double dx, dy, mul;
+  double t0, t1;
+  GfxAxialShading *shading;
+  GfxState *state;
+  SplashColorMode colorMode;
+  double *bbox;
+};
+
+// see GfxState.h, GfxGouraudTriangleShading
+class SplashGouraudPattern: public SplashGouraudColor {
+public:
+
+  SplashGouraudPattern(GBool bDirectColorTranslation, GfxState *state, GfxGouraudTriangleShading *shading);
+
+  virtual SplashPattern *copy() { return new SplashGouraudPattern(bDirectColorTranslation, state, shading); }
+
+  virtual ~SplashGouraudPattern();
+
+  virtual GBool getColor(int x, int y, SplashColorPtr c) { return gFalse; }
+
+  virtual GBool isStatic() { return gFalse; }
+
+  virtual GBool isParameterized() { return shading->isParameterized(); }
+  virtual int getNTriangles() { return shading->getNTriangles(); }
+  virtual  void getTriangle(int i, double *x0, double *y0, double *color0,
+                            double *x1, double *y1, double *color1,
+                            double *x2, double *y2, double *color2) 
+  { return shading->getTriangle(i, x0, y0, color0, x1, y1, color1, x2, y2, color2); }
+
+  virtual void getParameterizedColor(double t, SplashColorMode mode, SplashColorPtr c);
+
+private:
+  GfxGouraudTriangleShading *shading;
+  GfxState *state;
+  GBool bDirectColorTranslation;
+};
+
+//------------------------------------------------------------------------
 
 // number of Type 3 fonts to cache
 #define splashOutT3FontCacheSize 8
@@ -70,6 +128,12 @@ public:
 
   //----- get info about output device
 
+  // Does this device use functionShadedFill(), axialShadedFill(), and
+  // 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; }
+
   // Does this device use upside-down coordinates?
   // (Upside-down means (0,0) is the top left corner of the page.)
   virtual GBool upsideDown() { return gTrue; }
@@ -121,6 +185,8 @@ public:
   virtual void stroke(GfxState *state);
   virtual void fill(GfxState *state);
   virtual void eoFill(GfxState *state);
+  virtual GBool axialShadedFill(GfxState *state, GfxAxialShading *shading, double tMin, double tMax);
+  virtual GBool gouraudTriangleShadedFill(GfxState *state, GfxGouraudTriangleShading *shading);
 
   //----- path clipping
   virtual void clip(GfxState *state);
diff --git a/splash/Splash.cc b/splash/Splash.cc
index d3e48fa..f36f616 100644
--- a/splash/Splash.cc
+++ b/splash/Splash.cc
@@ -13,6 +13,8 @@
 //
 // Copyright (C) 2005-2010 Albert Astals Cid <aacid at kde.org>
 // Copyright (C) 2005 Marco Pesenti Gritti <mpg at redhat.com>
+// Copyright (C) 2010 Thomas Freitag <Thomas.Freitag at alfa.de>
+// Copyright (C) 2010 Christian Feuersänger <cfeuersaenger at googlemail.com>
 //
 // To see a description of the changes please see the Changelog file that
 // came with your tarball or type make ChangeLog if you are building from git
@@ -28,6 +30,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <limits.h>
+#include <assert.h>
 #include "goo/gmem.h"
 #include "goo/GooLikely.h"
 #include "poppler/Error.h"
@@ -56,6 +59,9 @@ static inline Guchar div255(int x) {
   return (Guchar)((x + (x >> 8) + 0x80) >> 8);
 }
 
+template<typename T>
+inline void Guswap( T&a, T&b ) { T tmp = a; a=b; b=tmp; }
+
 //------------------------------------------------------------------------
 // SplashPipe
 //------------------------------------------------------------------------
@@ -246,7 +252,32 @@ inline void Splash::pipeRun(SplashPipe *pipe) {
 
   // dynamic pattern
   if (pipe->pattern) {
-    pipe->pattern->getColor(pipe->x, pipe->y, pipe->cSrcVal);
+    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;
+    }
   }
 
   if (pipe->noTransparency && !state->blendFunc) {
@@ -3188,6 +3219,318 @@ void Splash::compositeBackground(SplashColorPtr color) {
   memset(bitmap->alpha, 255, bitmap->width * bitmap->height);
 }
 
+GBool Splash::gouraudTriangleShadedFill(SplashGouraudColor *shading)
+{
+  double xdbl[3] = {0., 0., 0.};
+  double ydbl[3] = {0., 0., 0.};
+  int    x[3] = {0, 0, 0};
+  int    y[3] = {0, 0, 0};
+  double xt=0., xa=0., yt=0.;
+  double ca=0., ct=0.;
+
+  // triangle interpolation:
+  //
+  double scanLimitMapL[2] = {0., 0.};
+  double scanLimitMapR[2] = {0., 0.};
+  double scanColorMapL[2] = {0., 0.};
+  double scanColorMapR[2] = {0., 0.};
+  double scanColorMap[2] = {0., 0.};
+  int scanEdgeL[2] = { 0, 0 };
+  int scanEdgeR[2] = { 0, 0 };
+  GBool hasFurtherSegment = gFalse;
+
+  int scanLineOff = 0;
+  int bitmapOff = 0;
+  int scanLimitR = 0, scanLimitL = 0, Yt = 0;
+
+  int bitmapWidth = bitmap->getWidth();
+  SplashClip* clip = getClip();
+  SplashBitmap *blitTarget = bitmap;
+  SplashColorPtr bitmapData = bitmap->getDataPtr();
+  SplashColorPtr bitmapAlpha = bitmap->getAlphaPtr();
+  SplashColorPtr cur = NULL;
+  SplashCoord* userToCanvasMatrix = getMatrix();
+  SplashColorMode bitmapMode = bitmap->getMode();
+  GBool hasAlpha = (bitmapAlpha != NULL);
+  int rowSize = bitmap->getRowSize();
+  int colorComps = 0;
+  switch (bitmapMode) {
+    case splashModeMono1:
+    break;
+    case splashModeMono8:
+      colorComps=1;
+    break;
+    case splashModeRGB8:
+      colorComps=3;
+    break;
+    case splashModeBGR8:
+      colorComps=3;
+    break;
+    case splashModeXBGR8:
+      colorComps=4;
+    break;
+#if SPLASH_CMYK
+    case splashModeCMYK8:
+      colorComps=4;
+    break;
+#endif
+  }
+
+  SplashPipe pipe;
+  SplashColor cSrcVal;
+
+  pipeInit(&pipe, 0, 0, NULL, cSrcVal, state->strokeAlpha, gFalse, gFalse);
+
+  if (vectorAntialias) {
+    if (aaBuf == NULL) 
+      return gFalse; // fall back to old behaviour
+    drawAAPixelInit();
+  }
+
+  // idea:
+  // 1. If pipe->noTransparency && !state->blendFunc
+  //  -> blit directly into the drawing surface!
+  //  -> disable alpha manually.
+  // 2. Otherwise:
+  // - blit also directly, but into an intermediate surface.
+  // Afterwards, blit the intermediate surface using the drawing pipeline.
+  // This is necessary because triangle elements can be on top of each
+  // other, so the complete shading needs to be drawn before opacity is
+  // applied.
+  // - the final step, is performed using a SplashPipe:
+  // - assign the actual color into cSrcVal: pipe uses cSrcVal by reference
+  // - invoke drawPixel(&pipe,X,Y,bNoClip);
+  GBool bDirectBlit = vectorAntialias ? gFalse : pipe.noTransparency && !state->blendFunc;
+  if (!bDirectBlit) {
+    blitTarget = new SplashBitmap(bitmap->getWidth(),
+                                  bitmap->getHeight(),
+                                  bitmap->getRowPad(),
+                                  bitmap->getMode(),
+                                  gTrue,
+                                  bitmap->getRowSize() >= 0);
+    bitmapData = blitTarget->getDataPtr();
+    bitmapAlpha = blitTarget->getAlphaPtr();
+
+    // initialisation seems to be necessary:
+    int S = bitmap->getWidth() * bitmap->getHeight();
+    for (int i = 0; i < S; ++i)
+      bitmapAlpha[i] = 0;
+    hasAlpha = gTrue;
+  }
+
+  if (shading->isParameterized()) {
+    double color[3];
+    double colorinterp;
+
+    for (int i = 0; i < shading->getNTriangles(); ++i) {
+      shading->getTriangle(i,
+                           xdbl + 0, ydbl + 0, color + 0,
+                           xdbl + 1, ydbl + 1, color + 1,
+                           xdbl + 2, ydbl + 2, color + 2);
+      for (int m = 0; m < 3; ++m) {
+        xt = xdbl[m] * userToCanvasMatrix[0] + ydbl[m] * userToCanvasMatrix[2] + userToCanvasMatrix[4];
+        yt = xdbl[m] * userToCanvasMatrix[1] + ydbl[m] * userToCanvasMatrix[3] + userToCanvasMatrix[5];
+        xdbl[m] = xt;
+        ydbl[m] = yt;
+        // we operate on scanlines which are integer offsets into the
+        // raster image. The double offsets are of no use here.
+        x[m] = splashRound(xt);
+        y[m] = splashRound(yt);
+      }
+      // sort according to y coordinate to simplify sweep through scanlines:
+      // INSERTION SORT.
+      if (y[0] > y[1]) {
+        Guswap(x[0], x[1]);
+        Guswap(y[0], y[1]);
+        Guswap(color[0], color[1]);
+      }
+      // first two are sorted.
+      assert(y[0] <= y[1]);
+      if (y[1] > y[2]) {
+        int tmpX = x[2];
+        int tmpY = y[2];
+        double tmpC = color[2];
+        x[2] = x[1]; y[2] = y[1]; color[2] = color[1];
+
+        if (y[0] > tmpY) {
+          x[1] = x[0]; y[1] = y[0]; color[1] = color[0];
+          x[0] = tmpX; y[0] = tmpY; color[0] = tmpC;
+        } else {
+          x[1] = tmpX; y[1] = tmpY; color[1] = tmpC;
+        }
+      }
+      // first three are sorted
+      assert(y[0] <= y[1]);
+      assert(y[1] <= y[2]);
+      /////
+
+      // this here is det( T ) == 0
+      // where T is the matrix to map to barycentric coordinates.
+      if ((x[0] - x[2]) * (y[1] - y[2]) - (x[1] - x[2]) * (y[0] - y[2]) == 0)
+        continue; // degenerate triangle.
+
+      // this here initialises the scanline generation.
+      // We start with low Y coordinates and sweep up to the large Y
+      // coordinates.
+      //
+      // scanEdgeL[m] in {0,1,2} m=0,1
+      // scanEdgeR[m] in {0,1,2} m=0,1
+      //
+      // are the two edges between which scanlines are (currently)
+      // sweeped. The values {0,1,2} are indices into 'x' and 'y'.
+      // scanEdgeL[0] = 0 means: the left scan edge has (x[0],y[0]) as vertex.
+      //
+      scanEdgeL[0] = 0;
+      scanEdgeR[0] = 0;
+      if (y[0] == y[1]) {
+        scanEdgeL[0] = 1;
+        scanEdgeL[1] = scanEdgeR[1] = 2;
+
+      } else {
+        scanEdgeL[1] = 1; scanEdgeR[1] = 2;
+      }
+      assert(y[scanEdgeL[0]] < y[scanEdgeL[1]]);
+      assert(y[scanEdgeR[0]] < y[scanEdgeR[1]]);
+
+      // Ok. Now prepare the linear maps which map the y coordinate of
+      // the current scanline to the corresponding LEFT and RIGHT x
+      // coordinate (which define the scanline).
+      scanLimitMapL[0] = double(x[scanEdgeL[1]] - x[scanEdgeL[0]]) / (y[scanEdgeL[1]] - y[scanEdgeL[0]]);
+      scanLimitMapL[1] = x[scanEdgeL[0]] - y[scanEdgeL[0]] * scanLimitMapL[0];
+      scanLimitMapR[0] = double(x[scanEdgeR[1]] - x[scanEdgeR[0]]) / (y[scanEdgeR[1]] - y[scanEdgeR[0]]);
+      scanLimitMapR[1] = x[scanEdgeR[0]] - y[scanEdgeR[0]] * scanLimitMapR[0];
+
+      xa = y[1] * scanLimitMapL[0] + scanLimitMapL[1];
+      xt = y[1] * scanLimitMapR[0] + scanLimitMapR[1];
+      if (xa > xt) {
+        // I have "left" is to the right of "right".
+        // Exchange sides!
+        Guswap(scanEdgeL[0], scanEdgeR[0]);
+        Guswap(scanEdgeL[1], scanEdgeR[1]);
+        Guswap(scanLimitMapL[0], scanLimitMapR[0]);
+        Guswap(scanLimitMapL[1], scanLimitMapR[1]);
+        // FIXME I'm sure there is a more efficient way to check this.
+      }
+
+      // Same game: we can linearly interpolate the color based on the
+      // current y coordinate (that's correct for triangle
+      // interpolation due to linearity. We could also have done it in
+      // barycentric coordinates, but that's slightly more involved)
+      scanColorMapL[0] = (color[scanEdgeL[1]] - color[scanEdgeL[0]]) / (y[scanEdgeL[1]] - y[scanEdgeL[0]]);
+      scanColorMapL[1] = color[scanEdgeL[0]] - y[scanEdgeL[0]] * scanColorMapL[0];
+      scanColorMapR[0] = (color[scanEdgeR[1]] - color[scanEdgeR[0]]) / (y[scanEdgeR[1]] - y[scanEdgeR[0]]);
+      scanColorMapR[1] = color[scanEdgeR[0]] - y[scanEdgeR[0]] * scanColorMapR[0];
+
+      Yt = y[2];
+      hasFurtherSegment = (y[1] < y[2]);
+      scanLineOff = y[0] * rowSize;
+
+      for (int Y = y[0]; Y <= y[2]; ++Y, scanLineOff += rowSize) {
+        if (hasFurtherSegment && Y == y[1]) {
+          // SWEEP EVENT: we encountered the next segment.
+          //
+          // switch to next segment, either at left end or at right
+          // end:
+          if (scanEdgeL[1] == 1) {
+            scanEdgeL[0] = 1;
+            scanEdgeL[1] = 2;
+            scanLimitMapL[0] = double(x[scanEdgeL[1]] - x[scanEdgeL[0]]) / (y[scanEdgeL[1]] - y[scanEdgeL[0]]);
+            scanLimitMapL[1] = x[scanEdgeL[0]] - y[scanEdgeL[0]] * scanLimitMapL[0];
+
+            scanColorMapL[0] = (color[scanEdgeL[1]] - color[scanEdgeL[0]]) / (y[scanEdgeL[1]] - y[scanEdgeL[0]]);
+            scanColorMapL[1] = color[scanEdgeL[0]] - y[scanEdgeL[0]] * scanColorMapL[0];
+          } else if (scanEdgeR[1] == 1) {
+            scanEdgeR[0] = 1;
+            scanEdgeR[1] = 2;
+            scanLimitMapR[0] = double(x[scanEdgeR[1]] - x[scanEdgeR[0]]) / (y[scanEdgeR[1]] - y[scanEdgeR[0]]);
+            scanLimitMapR[1] = x[scanEdgeR[0]] - y[scanEdgeR[0]] * scanLimitMapR[0];
+
+            scanColorMapR[0] = (color[scanEdgeR[1]] - color[scanEdgeR[0]]) / (y[scanEdgeR[1]] - y[scanEdgeR[0]]);
+            scanColorMapR[1] = color[scanEdgeR[0]] - y[scanEdgeR[0]] * scanColorMapR[0];
+          }
+          assert( y[scanEdgeL[0]]  <  y[scanEdgeL[1]] );
+          assert( y[scanEdgeR[0]] <  y[scanEdgeR[1]] );
+          hasFurtherSegment = gFalse;
+        }
+
+        yt = Y;
+
+        xa = yt * scanLimitMapL[0] + scanLimitMapL[1];
+        xt = yt * scanLimitMapR[0] + scanLimitMapR[1];
+
+        ca = yt * scanColorMapL[0] + scanColorMapL[1];
+        ct = yt * scanColorMapR[0] + scanColorMapR[1];
+
+        scanLimitL = splashRound(xa);
+        scanLimitR = splashRound(xt);
+
+        // Ok. Now: init the color interpolation depending on the X
+        // coordinate inside of the current scanline:
+        scanColorMap[0] = (scanLimitR == scanLimitL) ? 0. : ((ct - ca) / (scanLimitR - scanLimitL));
+        scanColorMap[1] = ca - scanLimitL * scanColorMap[0];
+
+        // handled by clipping:
+        // assert( scanLimitL >= 0 && scanLimitR < bitmap->getWidth() );
+        assert(scanLimitL <= scanLimitR || abs(scanLimitL - scanLimitR) <= 2); // allow rounding inaccuracies
+        assert(scanLineOff == Y * rowSize);
+
+        colorinterp = scanColorMap[0] * scanLimitL + scanColorMap[1];
+
+        bitmapOff = scanLineOff + scanLimitL * colorComps;
+        for (int X = scanLimitL; X <= scanLimitR; ++X, colorinterp += scanColorMap[0], bitmapOff += colorComps) {
+          // FIXME : standard rectangular clipping can be done for a
+          // complete scanline which is faster
+          // --> see SplashClip and its methods
+          if (!clip->test(X, Y))
+            continue;
+
+          assert(fabs(colorinterp - (scanColorMap[0] * X + scanColorMap[1])) < 1e-10);
+          assert(bitmapOff == Y * rowSize + colorComps * X && scanLineOff == Y * rowSize);
+
+          shading->getParameterizedColor(colorinterp, bitmapMode, &bitmapData[bitmapOff]);
+
+          // make the shading visible.
+          // Note that opacity is handled by the bDirectBlit stuff, see
+          // above for comments and below for implementation.
+          if (hasAlpha)
+            bitmapAlpha[Y * bitmapWidth + X] = 255;
+        }
+      }
+    }
+  } else {
+    return gFalse;
+  }
+
+  if (!bDirectBlit) {
+    // ok. Finalize the stuff by blitting the shading into the final
+    // geometry, this time respecting the rendering pipe.
+    int W = blitTarget->getWidth();
+    int H = blitTarget->getHeight();
+    cur = cSrcVal;
+
+    for (int X = 0; X < W; ++X) {
+      for (int Y = 0; Y < H; ++Y) {
+        if (!bitmapAlpha[Y * bitmapWidth + X])
+          continue; // draw only parts of the shading!
+        bitmapOff = Y * rowSize + colorComps * X;
+
+        for (int m = 0; m < colorComps; ++m)
+          cur[m] = bitmapData[bitmapOff + m];
+        if (vectorAntialias) {
+          drawAAPixel(&pipe, X, Y);
+        } else {
+          drawPixel(&pipe, X, Y, gTrue); // no clipping - has already been done.
+        }
+      }
+    }
+
+    delete blitTarget;
+    blitTarget = NULL;
+  }
+
+  return gTrue;
+}
+
 SplashError Splash::blitTransparent(SplashBitmap *src, int xSrc, int ySrc,
 				    int xDest, int yDest, int w, int h) {
   SplashColor pixel;
@@ -3598,3 +3941,53 @@ void Splash::dumpXPath(SplashXPath *path) {
 	   (path->segs[i].flags	& splashXPathFlip) ? "P" : " ");
   }
 }
+
+SplashError Splash::shadedFill(SplashPath *path, GBool hasBBox,
+                               SplashPattern *pattern) {
+  SplashPipe pipe;
+  SplashXPath *xPath;
+  SplashXPathScanner *scanner;
+  int xMinI, yMinI, xMaxI, yMaxI, x0, x1, y;
+  SplashClipResult clipRes;
+
+  if (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();
+  xPath->sort();
+  scanner = new SplashXPathScanner(xPath, gFalse);
+
+  // get the min and max x and y values
+  scanner->getBBoxAA(&xMinI, &yMinI, &xMaxI, &yMaxI);
+
+  // check clipping
+  if ((clipRes = state->clip->testRect(xMinI, yMinI, xMaxI, yMaxI)) != splashClipAllOutside) {
+    // limit the y range
+    if (yMinI < state->clip->getYMinI()) {
+      yMinI = state->clip->getYMinI();
+    }
+    if (yMaxI > state->clip->getYMaxI()) {
+      yMaxI = state->clip->getYMaxI();
+    }
+
+    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);
+    }
+  }
+  opClipRes = clipRes;
+
+  delete scanner;
+  delete xPath;
+  return splashOk;
+}
diff --git a/splash/Splash.h b/splash/Splash.h
index c9d57cc..a52dc13 100644
--- a/splash/Splash.h
+++ b/splash/Splash.h
@@ -13,6 +13,8 @@
 //
 // Copyright (C) 2005 Marco Pesenti Gritti <mpg at redhat.com>
 // Copyright (C) 2007 Albert Astals Cid <aacid at kde.org>
+// Copyright (C) 2010 Thomas Freitag <Thomas.Freitag at alfa.de>
+// Copyright (C) 2010 Christian Feuersänger <cfeuersaenger at googlemail.com>
 //
 // To see a description of the changes please see the Changelog file that
 // came with your tarball or type make ChangeLog if you are building from git
@@ -28,12 +30,11 @@
 
 #include "SplashTypes.h"
 #include "SplashClip.h"
+#include "SplashPattern.h"
 
-class Splash;
 class SplashBitmap;
 struct SplashGlyphBitmap;
 class SplashState;
-class SplashPattern;
 class SplashScreen;
 class SplashPath;
 class SplashXPath;
@@ -249,6 +250,12 @@ public:
   void setVectorAntialias(GBool vaa) { vectorAntialias = vaa; }
 #endif
 
+  // Do shaded fills with dynamic patterns
+  SplashError shadedFill(SplashPath *path, GBool hasBBox,
+                         SplashPattern *pattern);
+  // Draw a gouraud triangle shading.
+  GBool gouraudTriangleShadedFill(SplashGouraudColor *shading);
+
 private:
 
   void pipeInit(SplashPipe *pipe, int x, int y,
diff --git a/splash/SplashBitmap.cc b/splash/SplashBitmap.cc
index f983439..51e48d3 100644
--- a/splash/SplashBitmap.cc
+++ b/splash/SplashBitmap.cc
@@ -17,6 +17,7 @@
 // Copyright (C) 2009 Stefan Thomas <thomas at eload24.com>
 // Copyright (C) 2010 Adrian Johnson <ajohnson at redneon.com>
 // Copyright (C) 2010 Harry Roberts <harry.roberts at midnight-labs.org>
+// Copyright (C) 2010 Christian Feuersänger <cfeuersaenger at googlemail.com>
 //
 // To see a description of the changes please see the Changelog file that
 // came with your tarball or type make ChangeLog if you are building from git
@@ -44,12 +45,13 @@
 // SplashBitmap
 //------------------------------------------------------------------------
 
-SplashBitmap::SplashBitmap(int widthA, int heightA, int rowPad,
+SplashBitmap::SplashBitmap(int widthA, int heightA, int rowPadA,
 			   SplashColorMode modeA, GBool alphaA,
 			   GBool topDown) {
   width = widthA;
   height = heightA;
   mode = modeA;
+  rowPad = rowPadA;
   switch (mode) {
   case splashModeMono1:
     if (width > 0) {
diff --git a/splash/SplashBitmap.h b/splash/SplashBitmap.h
index e741a91..1c19421 100644
--- a/splash/SplashBitmap.h
+++ b/splash/SplashBitmap.h
@@ -17,6 +17,7 @@
 // Copyright (C) 2009 Stefan Thomas <thomas at eload24.com>
 // Copyright (C) 2010 Adrian Johnson <ajohnson at redneon.com>
 // Copyright (C) 2010 Harry Roberts <harry.roberts at midnight-labs.org>
+// Copyright (C) 2010 Christian Feuersänger <cfeuersaenger at googlemail.com>
 //
 // To see a description of the changes please see the Changelog file that
 // came with your tarball or type make ChangeLog if you are building from git
@@ -56,6 +57,7 @@ public:
   int getHeight() { return height; }
   int getRowSize() { return rowSize; }
   int getAlphaRowSize() { return width; }
+  int getRowPad() { return rowPad; }
   SplashColorMode getMode() { return mode; }
   SplashColorPtr getDataPtr() { return data; }
   Guchar *getAlphaPtr() { return alpha; }
@@ -73,6 +75,7 @@ public:
 private:
 
   int width, height;		// size of bitmap
+  int rowPad;
   int rowSize;			// size of one row of data, in bytes
 				//   - negative for bottom-up bitmaps
   SplashColorMode mode;		// color mode
diff --git a/splash/SplashPattern.cc b/splash/SplashPattern.cc
index ce49078..b42714d 100644
--- a/splash/SplashPattern.cc
+++ b/splash/SplashPattern.cc
@@ -4,6 +4,20 @@
 //
 //========================================================================
 
+//========================================================================
+//
+// Modified under the Poppler project - http://poppler.freedesktop.org
+//
+// All changes made under the Poppler project to this file are licensed
+// under GPL version 2 or later
+//
+// Copyright (C) 2010 Thomas Freitag <Thomas.Freitag at alfa.de>
+//
+// To see a description of the changes please see the Changelog file that
+// came with your tarball or type make ChangeLog if you are building from git
+//
+//========================================================================
+
 #include <config.h>
 
 #ifdef USE_GCC_PRAGMAS
@@ -35,6 +49,7 @@ SplashSolidColor::SplashSolidColor(SplashColorPtr colorA) {
 SplashSolidColor::~SplashSolidColor() {
 }
 
-void SplashSolidColor::getColor(int x, int y, SplashColorPtr c) {
+GBool SplashSolidColor::getColor(int x, int y, SplashColorPtr c) {
   splashColorCopy(c, color);
+  return gTrue;
 }
diff --git a/splash/SplashPattern.h b/splash/SplashPattern.h
index 4e3d9ab..09e9b1a 100644
--- a/splash/SplashPattern.h
+++ b/splash/SplashPattern.h
@@ -4,6 +4,20 @@
 //
 //========================================================================
 
+//========================================================================
+//
+// Modified under the Poppler project - http://poppler.freedesktop.org
+//
+// All changes made under the Poppler project to this file are licensed
+// under GPL version 2 or later
+//
+// Copyright (C) 2010 Thomas Freitag <Thomas.Freitag at alfa.de>
+//
+// To see a description of the changes please see the Changelog file that
+// came with your tarball or type make ChangeLog if you are building from git
+//
+//========================================================================
+
 #ifndef SPLASHPATTERN_H
 #define SPLASHPATTERN_H
 
@@ -29,7 +43,7 @@ public:
   virtual ~SplashPattern();
 
   // Return the color value for a specific pixel.
-  virtual void getColor(int x, int y, SplashColorPtr c) = 0;
+  virtual GBool getColor(int x, int y, SplashColorPtr c) = 0;
 
   // Returns true if this pattern object will return the same color
   // value for all pixels.
@@ -51,7 +65,7 @@ public:
 
   virtual ~SplashSolidColor();
 
-  virtual void getColor(int x, int y, SplashColorPtr c);
+  virtual GBool getColor(int x, int y, SplashColorPtr c);
 
   virtual GBool isStatic() { return gTrue; }
 
@@ -60,4 +74,22 @@ private:
   SplashColor color;
 };
 
+//------------------------------------------------------------------------
+// SplashGouraudColor (needed for gouraudTriangleShadedFill)
+//------------------------------------------------------------------------
+
+class SplashGouraudColor: public SplashPattern {
+public:
+
+  virtual GBool isParameterized() = 0;
+
+  virtual int getNTriangles() = 0;
+
+  virtual  void getTriangle(int i, double *x0, double *y0, double *color0,
+                            double *x1, double *y1, double *color1,
+                            double *x2, double *y2, double *color2) = 0;
+
+  virtual void getParameterizedColor(double t, SplashColorMode mode, SplashColorPtr c) = 0;
+};
+
 #endif


More information about the poppler mailing list