diff --git a/Graphics/gl2ps.cpp b/Graphics/gl2ps.cpp
index 298043d200c2d207f478652475227522bde11e27..a901af87c9025116c47e67841c65796c501e3f82 100644
--- a/Graphics/gl2ps.cpp
+++ b/Graphics/gl2ps.cpp
@@ -1,4 +1,4 @@
-/* $Id: gl2ps.cpp,v 1.100 2005-06-23 07:15:44 geuzaine Exp $ */
+/* $Id: gl2ps.cpp,v 1.101 2005-12-20 21:52:45 geuzaine Exp $ */
 /*
  * GL2PS, an OpenGL to PostScript Printing Library
  * Copyright (C) 1999-2005 Christophe Geuzaine <geuz@geuz.org>
@@ -44,6 +44,9 @@
  *   Guy Barrand <barrand@lal.in2p3.fr>
  *   Prabhu Ramachandran <prabhu@aero.iitm.ernet.in>
  *   Micha Bieber <bieber@traits.de>
+ *   Olivier Couet <couet@mail.cern.ch>
+ *   Shai Ayal <shaiay@gmail.com>
+ *   Fabian Wenzel <wenzel@tu-harburg.de>
  *
  * For the latest info about gl2ps, see http://www.geuz.org/gl2ps/.
  * Please report all bugs and problems to <gl2ps@geuz.org>.
@@ -69,7 +72,7 @@
 
 #define GL2PS_EPSILON       5.0e-3F
 #define GL2PS_ZSCALE        1000.0F
-#define GL2PS_ZOFFSET       1.0F
+#define GL2PS_ZOFFSET       5.0e-2F
 #define GL2PS_ZOFFSET_LARGE 20.0F
 #define GL2PS_ZERO(arg)     (fabs(arg) < 1.e-20)
 
@@ -247,6 +250,16 @@ typedef struct {
   GL2PSimagemap *imagemap_tail;
 } GL2PScontext;
 
+typedef struct {
+  void  (*header)(void);
+  void  (*footer)(void);
+  void  (*beginViewport)(GLint viewport[4]);
+  GLint (*endViewport)(void);
+  void  (*printPrimitive)(void *data);
+  const char *file_extension;
+  const char *description;
+} GL2PSbackend;
+
 /* The gl2ps context. gl2ps is not thread safe (we should create a
    local GL2PScontext during gl2psBeginPage) */
 
@@ -752,6 +765,32 @@ static void gl2psAdaptVertexForBlending(GL2PSvertex *v)
   }
 }
 
+static GLfloat gl2psGetRGB(GL2PSimage *im, GLuint x, GLuint y,
+                           GLfloat *red, GLfloat *green, GLfloat *blue)
+{
+  
+  GLsizei width = im->width;
+  GLsizei height = im->height;
+  GLfloat *pixels = im->pixels;
+  GLfloat *pimag;
+
+  /* OpenGL image is from down to up, PS image is up to down */  
+  switch(im->format){
+  case GL_RGBA:
+    pimag = pixels + 4 * (width * (height - 1 - y) + x);
+    break;
+  case GL_RGB:
+  default:
+    pimag = pixels + 3 * (width * (height - 1 - y) + x);
+    break;
+  }
+  *red = *pimag; pimag++;
+  *green = *pimag; pimag++;
+  *blue = *pimag; pimag++;
+
+  return (im->format == GL_RGBA) ? *pimag : 1.0F;
+}
+
 /********************************************************************* 
  *
  * 3D sorting routines 
@@ -2080,32 +2119,6 @@ static void gl2psParseFeedbackBuffer(GLint used)
  *
  *********************************************************************/
 
-static GLfloat gl2psGetRGB(GL2PSimage *im, GLuint x, GLuint y,
-                           GLfloat *red, GLfloat *green, GLfloat *blue)
-{
-  
-  GLsizei width = im->width;
-  GLsizei height = im->height;
-  GLfloat *pixels = im->pixels;
-  GLfloat *pimag;
-
-  /* OpenGL image is from down to up, PS image is up to down */  
-  switch(im->format){
-  case GL_RGBA:
-    pimag = pixels + 4 * (width * (height - 1 - y) + x);
-    break;
-  case GL_RGB:
-  default:
-    pimag = pixels + 3 * (width * (height - 1 - y) + x);
-    break;
-  }
-  *red = *pimag; pimag++;
-  *green = *pimag; pimag++;
-  *blue = *pimag; pimag++;
-
-  return (im->format == GL_RGBA) ? *pimag : 1.0F;
-}
-
 static void gl2psWriteByte(unsigned char byte)
 {
   unsigned char h = byte / 16;
@@ -2596,7 +2609,7 @@ static void gl2psResetPostScriptColor(void)
   gl2ps->lastrgba[0] = gl2ps->lastrgba[1] = gl2ps->lastrgba[2] = -1.;
 }
 
-static int gl2psPrintDash(GLushort pattern, GLint factor, char *str)
+static int gl2psPrintPostScriptDash(GLushort pattern, GLint factor, char *str)
 {
   int len = 0, i, n, on[5] = {0, 0, 0, 0, 0}, off[5] = {0, 0, 0, 0, 0};
   char tmp[16];
@@ -2712,7 +2725,7 @@ static void gl2psPrintPostScriptPrimitive(void *data)
       gl2ps->lastlinewidth = prim->width;
       gl2psPrintf("%g W\n", gl2ps->lastlinewidth);
     }
-    gl2psPrintDash(prim->pattern, prim->factor, "setdash");
+    gl2psPrintPostScriptDash(prim->pattern, prim->factor, "setdash");
     if(!gl2psVertsSameColor(prim)){
       gl2psResetPostScriptColor();
       gl2psPrintf("%g %g %g %g %g %g %g %g %g %g SL\n",
@@ -2857,6 +2870,28 @@ static GLint gl2psPrintPostScriptEndViewport(void)
   return res;
 }
 
+/* definition of the PostScript and Encapsulated PostScript backends */
+
+static GL2PSbackend gl2psPS = {
+  gl2psPrintPostScriptHeader,
+  gl2psPrintPostScriptFooter,
+  gl2psPrintPostScriptBeginViewport,
+  gl2psPrintPostScriptEndViewport,
+  gl2psPrintPostScriptPrimitive,
+  "ps",
+  "Postscript"
+};
+
+static GL2PSbackend gl2psEPS = {
+  gl2psPrintPostScriptHeader,
+  gl2psPrintPostScriptFooter,
+  gl2psPrintPostScriptBeginViewport,
+  gl2psPrintPostScriptEndViewport,
+  gl2psPrintPostScriptPrimitive,
+  "eps",
+  "Encapsulated Postscript"
+};
+
 /********************************************************************* 
  *
  * LaTeX routines
@@ -2954,6 +2989,27 @@ static void gl2psPrintTeXFooter(void)
           (gl2ps->options & GL2PS_LANDSCAPE) ? "}" : "");
 }
 
+static void gl2psPrintTeXBeginViewport(GLint viewport[4])
+{
+}
+
+static GLint gl2psPrintTeXEndViewport(void)
+{
+  return 0;
+}
+
+/* definition of the LaTeX backend */
+
+static GL2PSbackend gl2psTEX = {
+  gl2psPrintTeXHeader,
+  gl2psPrintTeXFooter,
+  gl2psPrintTeXBeginViewport,
+  gl2psPrintTeXEndViewport,
+  gl2psPrintTeXPrimitive,
+  "tex",
+  "LaTeX text"
+};
+
 /********************************************************************* 
  *
  * PDF routines
@@ -3246,7 +3302,7 @@ static void gl2psPDFgroupListWriteMainStream(void)
     case GL2PS_LINE:
       gl2ps->streamlength += gl2psPrintPDFLineWidth(prim->width);
       gl2ps->streamlength += gl2psPrintPDFStrokeColor(prim->verts[0].rgba);
-      gl2ps->streamlength += gl2psPrintDash(prim->pattern, prim->factor, "d");
+      gl2ps->streamlength += gl2psPrintPostScriptDash(prim->pattern, prim->factor, "d");
       for(j = 0; j <= lastel; ++j){  
         prim = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, j);
         gl2ps->streamlength += 
@@ -4365,12 +4421,419 @@ static GLint gl2psPrintPDFEndViewport(void)
   return res;
 }
 
+/* definition of the PDF backend */
+
+static GL2PSbackend gl2psPDF = {
+  gl2psPrintPDFHeader,
+  gl2psPrintPDFFooter,
+  gl2psPrintPDFBeginViewport,
+  gl2psPrintPDFEndViewport,
+  gl2psPrintPDFPrimitive,
+  "pdf",
+  "Portable Document Format"
+};
+
+/********************************************************************* 
+ *
+ * SVG routines
+ *
+ *********************************************************************/
+
+/* FIXME: this is just a canvas, still far from being usable in any
+   way. One big problem is that it seems like there is no easy way to
+   do Gouraud shading in SVG!? Another is horrible rendering
+   performance (that could be partially fixed by using 'path' instead
+   of 'polygon') */
+
+static void gl2psSVGGetColorString(GL2PSrgba rgba, char str[32])
+{
+  int r = (int)(255. * rgba[0]);
+  int g = (int)(255. * rgba[1]);
+  int b = (int)(255. * rgba[2]);
+  int rc = (r < 0) ? 0 : (r > 255) ? 255 : r;
+  int gc = (g < 0) ? 0 : (g > 255) ? 255 : g;
+  int bc = (b < 0) ? 0 : (b > 255) ? 255 : b;
+  sprintf(str, "#%2.2x%2.2x%2.2x", rc, gc, bc);
+}
+
+static void gl2psSVGGetCoords(int n, GL2PSvertex *verts, GL2PSxyz *xyz)
+{
+  int i;
+
+  for(i = 0; i < n; i++){
+    xyz[i][0] = verts[i].xyz[0];
+    xyz[i][1] = gl2ps->viewport[3] - verts[i].xyz[1];
+  }
+}
+
+static void gl2psPrintSVGHeader(void)
+{
+  time_t now;
+  time(&now);
+
+  fprintf(gl2ps->stream, 
+	  "<svg viewBox=\"%d %d %d %d\" xmlns=\"http://www.w3.org/2000/svg\">\n",
+	  (gl2ps->options & GL2PS_LANDSCAPE) ? (int)gl2ps->viewport[1] : 
+	  (int)gl2ps->viewport[0],
+	  (gl2ps->options & GL2PS_LANDSCAPE) ? (int)gl2ps->viewport[0] :
+	  (int)gl2ps->viewport[1],
+	  (gl2ps->options & GL2PS_LANDSCAPE) ? (int)gl2ps->viewport[3] : 
+	  (int)gl2ps->viewport[2],
+	  (gl2ps->options & GL2PS_LANDSCAPE) ? (int)gl2ps->viewport[2] :
+	  (int)gl2ps->viewport[3]);
+  fprintf(gl2ps->stream, "<title>\n");
+  fprintf(gl2ps->stream, "%s\n",gl2ps->title);
+  fprintf(gl2ps->stream, "</title>\n");
+  fprintf(gl2ps->stream, "<desc>\n");
+  fprintf(gl2ps->stream, 
+	  "Creator: GL2PS %d.%d.%d\n"
+	  "For: %s\n"
+	  "CreationDate: %s",
+	  GL2PS_MAJOR_VERSION, GL2PS_MINOR_VERSION, GL2PS_PATCH_VERSION,
+	  gl2ps->producer, ctime(&now));
+  fprintf(gl2ps->stream, "</desc>\n");
+  fprintf(gl2ps->stream, "<defs>\n");
+  fprintf(gl2ps->stream, "</defs>\n");
+}
+
+static void gl2psPrintSVGPrimitive(void *data)
+{
+  GL2PSprimitive *prim;
+  GL2PSxyz xyz[4];
+  char col[32];
+
+  prim = *(GL2PSprimitive**)data;
+
+  if((gl2ps->options & GL2PS_OCCLUSION_CULL) && prim->culled) return;
+
+  gl2psSVGGetCoords(prim->numverts, prim->verts, xyz);
+
+  switch(prim->type){
+  case GL2PS_PIXMAP :
+    /* FIXME */
+    break;
+  case GL2PS_IMAGEMAP :
+    /* FIXME */
+    break;
+  case GL2PS_TEXT :
+    gl2psSVGGetColorString(prim->verts[0].rgba, col);
+    fprintf(gl2ps->stream,
+	    "<text x=\"%g\" y=\"%g\" fill=\"%s\" "
+	    "font-size=\"%d\" font-family=\"%s\">%s</text>\n",
+	    xyz[0][0], xyz[0][1], col,
+	    prim->data.text->fontsize,
+	    prim->data.text->fontname,
+	    prim->data.text->str);
+    break;
+  case GL2PS_POINT :
+    /* FIXME */
+    break;
+  case GL2PS_LINE :
+    gl2psSVGGetColorString(prim->verts[0].rgba, col);
+    fprintf(gl2ps->stream,
+	    "<line stroke=\"%s\" stroke-width=\"%d\" "
+	    "x1=\"%g\" y1=\"%g\" x2=\"%g\" y2=\"%g\"/>\n",
+	    col, (int)(prim->width),
+	    xyz[0][0], xyz[0][1], xyz[1][0], xyz[1][1]);
+    break;
+  case GL2PS_TRIANGLE :
+    gl2psSVGGetColorString(prim->verts[0].rgba, col);
+    fprintf(gl2ps->stream, 
+	    "<polygon fill=\"%s\" points=\"%g,%g %g,%g %g,%g\"/>\n",
+	    col, xyz[0][0], xyz[0][1], xyz[1][0], xyz[1][1], xyz[2][0], xyz[2][1]);
+    break;
+  case GL2PS_QUADRANGLE :
+    gl2psMsg(GL2PS_WARNING, "There should not be any quad left to print");
+    break;
+  default :
+    gl2psMsg(GL2PS_ERROR, "Unknown type of primitive to print");
+    break;
+  }
+}
+
+static void gl2psPrintSVGFooter(void)
+{
+  fprintf(gl2ps->stream, "</svg>\n");
+}
+
+static void gl2psPrintSVGBeginViewport(GLint viewport[4])
+{
+  /* FIXME */
+}
+
+static GLint gl2psPrintSVGEndViewport(void)
+{
+  /* FIXME */
+  return 0;
+}
+
+/* definition of the SVG backend */
+
+static GL2PSbackend gl2psSVG = {
+  gl2psPrintSVGHeader,
+  gl2psPrintSVGFooter,
+  gl2psPrintSVGBeginViewport,
+  gl2psPrintSVGEndViewport,
+  gl2psPrintSVGPrimitive,
+  "svg",
+  "Scalable Vector Graphics"
+};
+
+/*********************************************************************
+ *
+ * PGF routines
+ *
+ *********************************************************************/
+
+static void gl2psPrintPGFColor(GL2PSrgba rgba)
+{
+  if(!gl2psSameColor(gl2ps->lastrgba, rgba)){
+    gl2psSetLastColor(rgba);
+    fprintf(gl2ps->stream, "\\color[rgb]{%f,%f,%f}\n", rgba[0], rgba[1], rgba[2]);
+  }
+}
+
+static void gl2psPrintPGFHeader(void)
+{
+  char name[256];
+  int i;
+  
+  if(gl2ps->filename && strlen(gl2ps->filename) < 256){
+    for(i = strlen(gl2ps->filename)-1; i >= 0; i--){
+      if(gl2ps->filename[i] == '.'){
+        strncpy(name, gl2ps->filename, i);
+        name[i] = '\0';
+        break;
+      }
+    }
+    if(i <= 0) strcpy(name, gl2ps->filename);
+  }
+  else{
+    strcpy(name, "untitled");
+  }
+  
+  fprintf(gl2ps->stream, "\\begin{pgfpicture}\n");
+  if(gl2ps->options & GL2PS_DRAW_BACKGROUND){
+    gl2psPrintPGFColor(gl2ps->bgcolor);
+    fprintf(gl2ps->stream,
+	    "\\pgfpathrectanglecorners{"
+	    "\\pgfpoint{%dpt}{%dpt}}{\\pgfpoint{%dpt}{%dpt}}\n"
+	    "\\pgfusepath{fill}\n",
+	    (int)gl2ps->viewport[0], (int)gl2ps->viewport[1],
+	    (int)gl2ps->viewport[2], (int)gl2ps->viewport[3]);
+  }
+}
+
+static void gl2psPrintPGFDash(GLushort pattern, GLint factor)
+{
+  int i, n, on[5] = {0, 0, 0, 0, 0}, off[5] = {0, 0, 0, 0, 0};
+  char tmp[16];
+
+  if(pattern == gl2ps->lastpattern && factor == gl2ps->lastfactor)
+    return;
+
+  gl2ps->lastpattern = pattern;
+  gl2ps->lastfactor = factor;
+
+  if(!pattern || !factor){
+    /* solid line */
+    fprintf(gl2ps->stream, "\\pgfsetdash{}{0pt}\n");
+  }
+  else{
+    /* extract the 16 bits from the stipple pattern */
+    for(n = 15; n >= 0; n--){
+      tmp[n] = (char)(pattern & 0x01);
+      pattern >>= 1;
+    }
+    /* compute the on/off pixel sequence (since the PostScript
+       specification allows for at most 11 elements in the on/off
+       array, we limit ourselves to 5 couples of on/off states) */
+    n = 0;
+    for(i = 0; i < 5; i++){
+      while(n < 16 && !tmp[n]){ off[i]++; n++; }
+      while(n < 16 && tmp[n]){ on[i]++; n++; }
+      if(n >= 15) break;
+    }
+    /* print the on/off array from right to left, starting with off
+       pixels (the longest possible array is: [on4 off4 on3 off3 on2
+       off2 on1 off1 on0 off0]) */
+    fprintf(gl2ps->stream, "\\pgfsetdash{");
+    for(n = i; n >= 0; n--){
+      fprintf(gl2ps->stream, "{%dpt}{%dpt}",
+	      (int)(factor * on[n]), (int)(factor * off[n]));
+    }
+    fprintf(gl2ps->stream, "}{0pt}\n");
+  }
+}
+
+static const char *gl2psPGFTextAlignment(int align)
+{
+  switch(align){
+  case GL2PS_TEXT_C  : return "center";
+  case GL2PS_TEXT_CL : return "west";
+  case GL2PS_TEXT_CR : return "east";
+  case GL2PS_TEXT_B  : return "south";
+  case GL2PS_TEXT_BR : return "south east";
+  case GL2PS_TEXT_T  : return "north";
+  case GL2PS_TEXT_TL : return "north west";
+  case GL2PS_TEXT_TR : return "north east";
+  case GL2PS_TEXT_BL : 
+  default            : return "south west";
+  }
+}
+
+static void gl2psPrintPGFPrimitive(void *data)
+{
+  GL2PSprimitive *prim;
+
+  prim = *(GL2PSprimitive**)data;
+
+  switch(prim->type){
+  case GL2PS_TEXT :
+    fprintf(gl2ps->stream, "{\n\\pgftransformshift{\\pgfpoint{%fpt}{%fpt}}\n",
+	    prim->verts[0].xyz[0], prim->verts[0].xyz[1]);
+
+    if(prim->data.text->angle)
+      fprintf(gl2ps->stream, "\\pgftransformrotate{%f}{", prim->data.text->angle);
+
+    fprintf(gl2ps->stream, "\\pgfnode{rectangle}{%s}{\\fontsize{%d}{0}\\selectfont",
+	    gl2psPGFTextAlignment(prim->data.text->alignment),
+	    prim->data.text->fontsize);
+
+    fprintf(gl2ps->stream, "\\textcolor[rgb]{%g,%g,%g}{{%s}}",
+            prim->verts[0].rgba[0], prim->verts[0].rgba[1],
+            prim->verts[0].rgba[2], prim->data.text->str);
+
+    fprintf(gl2ps->stream, "}{}{\\pgfusepath{discard}}}\n");
+    break;
+  case GL2PS_POINT :
+    /* Points in openGL are rectangular */
+    gl2psPrintPGFColor(prim->verts[0].rgba);
+    fprintf(gl2ps->stream, 
+	    "\\pgfpathrectangle{\\pgfpoint{%fpt}{%fpt}}"
+	    "{\\pgfpoint{%fpt}{%fpt}}\n\\pgfusepath{fill}\n",
+	    prim->verts[0].xyz[0]-0.5*prim->width,
+	    prim->verts[0].xyz[1]-0.5*prim->width,
+	    prim->width,prim->width);
+    break;
+  case GL2PS_LINE :
+    gl2psPrintPGFColor(prim->verts[0].rgba);
+    if(gl2ps->lastlinewidth != prim->width){
+      gl2ps->lastlinewidth = prim->width;
+      fprintf(gl2ps->stream, "\\pgfsetlinewidth{%fpt}\n", gl2ps->lastlinewidth);
+    }
+    gl2psPrintPGFDash(prim->pattern, prim->factor);
+    fprintf(gl2ps->stream, 
+	    "\\pgfpathmoveto{\\pgfpoint{%fpt}{%fpt}}\n"
+	    "\\pgflineto{\\pgfpoint{%fpt}{%fpt}}\n"
+	    "\\pgfusepath{stroke}\n",
+	    prim->verts[1].xyz[0], prim->verts[1].xyz[1],
+	    prim->verts[0].xyz[0], prim->verts[0].xyz[1]);
+    break;
+  case GL2PS_TRIANGLE :
+    if(gl2ps->lastlinewidth != 0){
+      gl2ps->lastlinewidth = 0;
+      fprintf(gl2ps->stream, "\\pgfsetlinewidth{0.01pt}\n");
+    }
+    gl2psPrintPGFColor(prim->verts[0].rgba);
+    fprintf(gl2ps->stream, 
+	    "\\pgfpathmoveto{\\pgfpoint{%fpt}{%fpt}}\n"
+	    "\\pgflineto{\\pgfpoint{%fpt}{%fpt}}\n"
+	    "\\pgflineto{\\pgfpoint{%fpt}{%fpt}}\n"
+	    "\\pgfpathclose\n"
+	    "\\pgfusepath{fill,stroke}\n",
+	    prim->verts[2].xyz[0], prim->verts[2].xyz[1],
+	    prim->verts[1].xyz[0], prim->verts[1].xyz[1],
+	    prim->verts[0].xyz[0], prim->verts[0].xyz[1]);
+    break;
+  default :
+    break;
+  }
+}
+
+static void gl2psPrintPGFFooter(void)
+{
+  fprintf(gl2ps->stream, "\\end{pgfpicture}\n");
+}
+
+static void gl2psPrintPGFBeginViewport(GLint viewport[4])
+{
+  GLint index;
+  GLfloat rgba[4];
+  int x = viewport[0], y = viewport[1], w = viewport[2], h = viewport[3];
+
+  glRenderMode(GL_FEEDBACK);
+
+  if(gl2ps->header){
+    gl2psPrintPGFHeader();
+    gl2ps->header = GL_FALSE;
+  }
+
+  fprintf(gl2ps->stream, "\\begin{pgfscope}\n");
+  if(gl2ps->options & GL2PS_DRAW_BACKGROUND){
+    if(gl2ps->colormode == GL_RGBA || gl2ps->colorsize == 0){
+      glGetFloatv(GL_COLOR_CLEAR_VALUE, rgba);
+    }
+    else{
+      glGetIntegerv(GL_INDEX_CLEAR_VALUE, &index);
+      rgba[0] = gl2ps->colormap[index][0];
+      rgba[1] = gl2ps->colormap[index][1];
+      rgba[2] = gl2ps->colormap[index][2];
+      rgba[3] = 0.0F;
+    }
+    gl2psPrintPGFColor(rgba);
+    fprintf(gl2ps->stream, 
+	    "\\pgfpathrectangle{\\pgfpoint{%dpt}{%dpt}}"
+	    "{\\pgfpoint{%dpt}{%dpt}}\n"
+	    "\\pgfusepath{fill}\n",
+	    x, y, w, h);
+  }
+  
+  fprintf(gl2ps->stream, 
+	  "\\pgfpathrectangle{\\pgfpoint{%dpt}{%dpt}}"
+	  "{\\pgfpoint{%dpt}{%dpt}}\n"
+	  "\\pgfusepath{clip}\n",
+	  x, y, w, h);
+}
+
+static GLint gl2psPrintPGFEndViewport(void)
+{
+  GLint res;
+  res = gl2psPrintPrimitives();
+  fprintf(gl2ps->stream, "\\end{pgfscope}\n");
+  return res;
+}
+
+/* definition of the PGF backend */
+
+static GL2PSbackend gl2psPGF = {
+  gl2psPrintPGFHeader,
+  gl2psPrintPGFFooter,
+  gl2psPrintPGFBeginViewport,
+  gl2psPrintPGFEndViewport,
+  gl2psPrintPGFPrimitive,
+  "tex",
+  "PGF Latex Graphics"
+};
+
 /********************************************************************* 
  *
  * General primitive printing routine
  *
  *********************************************************************/
 
+/* Warning: the ordering of the backends must match the format
+   #defines in gl2ps.h */
+
+static GL2PSbackend *gl2psbackends[] = {
+  &gl2psPS,  /* 0 */
+  &gl2psEPS, /* 1 */
+  &gl2psTEX, /* 2 */
+  &gl2psPDF, /* 3 */
+  &gl2psSVG, /* 4 */
+  &gl2psPGF  /* 5 */
+};
+
 static void gl2psComputeTightBoundingBox(void *data)
 {
   GL2PSprimitive *prim;
@@ -4395,7 +4858,6 @@ static GLint gl2psPrintPrimitives(void)
   GL2PSbsptree *root;
   GL2PSxyz eye = {0.0F, 0.0F, 100000.0F};
   GLint used;
-  void (*pprim)(void *data) = NULL;
 
   used = glRenderMode(GL_RENDER);
 
@@ -4418,18 +4880,7 @@ static GLint gl2psPrintPrimitives(void)
       gl2ps->viewport[2] = gl2ps->viewport[3] = -100000;
       gl2psListAction(gl2ps->primitives, gl2psComputeTightBoundingBox);
     }
-    switch(gl2ps->format){
-    case GL2PS_TEX :
-      gl2psPrintTeXHeader();
-      break;
-    case GL2PS_PS :
-    case GL2PS_EPS :
-      gl2psPrintPostScriptHeader();
-      break;
-    case GL2PS_PDF :
-      gl2psPrintPDFHeader();
-      break;
-    }
+    (gl2psbackends[gl2ps->format]->header)();
     gl2ps->header = GL_FALSE;
   }
 
@@ -4438,22 +4889,9 @@ static GLint gl2psPrintPrimitives(void)
     return GL2PS_NO_FEEDBACK;
   }
 
-  switch(gl2ps->format){
-  case GL2PS_TEX :
-    pprim = gl2psPrintTeXPrimitive;
-    break;
-  case GL2PS_PS :
-  case GL2PS_EPS :
-    pprim = gl2psPrintPostScriptPrimitive;
-    break;
-  case GL2PS_PDF :
-    pprim = gl2psPrintPDFPrimitive;
-    break;
-  }
-  
   switch(gl2ps->sort){
   case GL2PS_NO_SORT :
-    gl2psListAction(gl2ps->primitives, pprim);
+    gl2psListAction(gl2ps->primitives, gl2psbackends[gl2ps->format]->printPrimitive);
     gl2psListAction(gl2ps->primitives, gl2psFreePrimitive);
     /* reset the primitive list, waiting for the next viewport */
     gl2psListReset(gl2ps->primitives);
@@ -4464,7 +4902,7 @@ static GLint gl2psPrintPrimitives(void)
       gl2psListAction(gl2ps->primitives, gl2psAddInImageTree);
       gl2psFreeBspImageTree(&gl2ps->imagetree);
     }
-    gl2psListActionInverse(gl2ps->primitives, pprim);
+    gl2psListActionInverse(gl2ps->primitives, gl2psbackends[gl2ps->format]->printPrimitive);
     gl2psListAction(gl2ps->primitives, gl2psFreePrimitive);
     /* reset the primitive list, waiting for the next viewport */
     gl2psListReset(gl2ps->primitives);
@@ -4479,7 +4917,7 @@ static GLint gl2psPrintPrimitives(void)
       gl2psFreeBspImageTree(&gl2ps->imagetree);
     }
     gl2psTraverseBspTree(root, eye, GL2PS_EPSILON, gl2psGreater, 
-                         pprim, 0);
+                         gl2psbackends[gl2ps->format]->printPrimitive, 0);
     gl2psFreeBspTree(&root);
     /* reallocate the primitive list (it's been deleted by
        gl2psBuildBspTree) in case there is another viewport */
@@ -4513,14 +4951,10 @@ GL2PSDLL_API GLint gl2psBeginPage(const char *title, const char *producer,
 
   gl2ps = (GL2PScontext*)gl2psMalloc(sizeof(GL2PScontext));
 
-  switch(format){
-  case GL2PS_TEX :
-  case GL2PS_PS :
-  case GL2PS_EPS :
-  case GL2PS_PDF :
+  if(format >= 0 && format < (GLint)(sizeof(gl2psbackends)/sizeof(gl2psbackends[0]))){
     gl2ps->format = format;
-    break;
-  default :
+  }
+  else {
     gl2psMsg(GL2PS_ERROR, "Unknown output format: %d", format);
     gl2psFree(gl2ps);
     gl2ps = NULL;
@@ -4542,10 +4976,6 @@ GL2PSDLL_API GLint gl2psBeginPage(const char *title, const char *producer,
 
   if(stream){
     gl2ps->stream = stream;
-    /* In case gl2psEndPage failed (e.g. due to a GL2PS_OVERFLOW) and
-       we didn't reopen the stream before calling gl2psBeginPage
-       again, we need to rewind the stream */
-    rewind(gl2ps->stream);
   }
   else{
     gl2psMsg(GL2PS_ERROR, "Bad file pointer");
@@ -4672,21 +5102,9 @@ GL2PSDLL_API GLint gl2psEndPage(void)
 
   res = gl2psPrintPrimitives();
 
-  if(res != GL2PS_OVERFLOW){
-    switch(gl2ps->format){
-    case GL2PS_TEX :
-      gl2psPrintTeXFooter();
-      break;
-    case GL2PS_PS :
-    case GL2PS_EPS :
-      gl2psPrintPostScriptFooter();
-      break;
-    case GL2PS_PDF :
-      gl2psPrintPDFFooter();
-      break;
-    }
-  }
-
+  if(res != GL2PS_OVERFLOW)
+    (gl2psbackends[gl2ps->format]->footer)();
+  
   fflush(gl2ps->stream);
 
   gl2psListDelete(gl2ps->primitives);
@@ -4706,17 +5124,7 @@ GL2PSDLL_API GLint gl2psBeginViewport(GLint viewport[4])
 {
   if(!gl2ps) return GL2PS_UNINITIALIZED;
 
-  switch(gl2ps->format){
-  case GL2PS_PS :
-  case GL2PS_EPS :
-    gl2psPrintPostScriptBeginViewport(viewport);
-    break;
-  case GL2PS_PDF :
-    gl2psPrintPDFBeginViewport(viewport);
-    break;
-  default :
-    break;
-  }
+  (gl2psbackends[gl2ps->format]->beginViewport)(viewport);
   
   return GL2PS_SUCCESS;
 }
@@ -4727,18 +5135,7 @@ GL2PSDLL_API GLint gl2psEndViewport(void)
 
   if(!gl2ps) return GL2PS_UNINITIALIZED;
 
-  switch(gl2ps->format){
-  case GL2PS_PS :
-  case GL2PS_EPS :
-    res = gl2psPrintPostScriptEndViewport();
-    break;
-  case GL2PS_PDF :
-    res = gl2psPrintPDFEndViewport();
-    break;
-  default :
-    res = GL2PS_SUCCESS;
-    break;
-  }
+  res = (gl2psbackends[gl2ps->format]->endViewport)();
 
   return res;
 }
@@ -4999,3 +5396,19 @@ GL2PSDLL_API GLint gl2psSetOptions(GLint options)
 
   return GL2PS_SUCCESS;
 }
+
+GL2PSDLL_API const char *gl2psGetFileExtension(GLint format)
+{
+  if(format >= 0 && format < (GLint)(sizeof(gl2psbackends)/sizeof(gl2psbackends[0])))
+    return gl2psbackends[format]->file_extension;
+  else
+    return "Unknown format";
+}
+
+GL2PSDLL_API const char *gl2psGetFormatDescription(GLint format)
+{
+  if(format >= 0 && format < (GLint)(sizeof(gl2psbackends)/sizeof(gl2psbackends[0])))
+    return gl2psbackends[format]->description;
+  else
+    return "Unknown format";
+}
diff --git a/Graphics/gl2ps.h b/Graphics/gl2ps.h
index cc46824eeb12644e45dfe2b23dba782156615e1b..f900031f005f069809df1c7b89194068313f3cad 100644
--- a/Graphics/gl2ps.h
+++ b/Graphics/gl2ps.h
@@ -1,4 +1,4 @@
-/* $Id: gl2ps.h,v 1.61 2005-06-23 07:15:44 geuzaine Exp $ */
+/* $Id: gl2ps.h,v 1.62 2005-12-20 21:52:45 geuzaine Exp $ */
 /*
  * GL2PS, an OpenGL to PostScript Printing Library
  * Copyright (C) 1999-2005 Christophe Geuzaine <geuz@geuz.org>
@@ -40,7 +40,7 @@
 
 /* Define GL2PSDLL at compile time to build a Windows dll */
 
-#if defined (WIN32) || defined(_WIN32)
+#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
 #  if defined(_MSC_VER)
 #    pragma warning(disable:4115)
 #  endif
@@ -77,18 +77,20 @@
 
 #define GL2PS_MAJOR_VERSION 1
 #define GL2PS_MINOR_VERSION 2
-#define GL2PS_PATCH_VERSION 6
+#define GL2PS_PATCH_VERSION 7
 
 #define GL2PS_VERSION (GL2PS_MAJOR_VERSION + \
                        0.01 * GL2PS_MINOR_VERSION + \
                        0.0001 * GL2PS_PATCH_VERSION)
 
-/* Output file format */
+/* Output file formats (the values and the ordering are important!) */
 
-#define GL2PS_PS  1
-#define GL2PS_EPS 2
-#define GL2PS_TEX 3
-#define GL2PS_PDF 4
+#define GL2PS_PS  0
+#define GL2PS_EPS 1
+#define GL2PS_TEX 2
+#define GL2PS_PDF 3
+#define GL2PS_SVG 4
+#define GL2PS_PGF 5
 
 /* Sorting algorithms */
 
@@ -179,6 +181,8 @@ GL2PSDLL_API GLint gl2psBlendFunc(GLenum sfactor, GLenum dfactor);
 GL2PSDLL_API GLint gl2psDrawImageMap(GLsizei width, GLsizei height,
                                      const GLfloat position[3],
                                      const unsigned char *imagemap);
+GL2PSDLL_API const char *gl2psGetFileExtension(GLint format);
+GL2PSDLL_API const char *gl2psGetFormatDescription(GLint format);
 
 #if defined(__cplusplus)
 }