diff --git a/Graphics/gl2ps.cpp b/Graphics/gl2ps.cpp
index 113e9dc4d6e50389bf1ad07e629f259a724d0d21..e0fff4467ba5c5ed43bb7a7cb31f9a3d4556aab1 100644
--- a/Graphics/gl2ps.cpp
+++ b/Graphics/gl2ps.cpp
@@ -1,4 +1,4 @@
-/* $Id: gl2ps.cpp,v 1.85 2004-05-09 19:00:11 geuzaine Exp $ */
+/* $Id: gl2ps.cpp,v 1.86 2004-11-22 07:34:35 geuzaine Exp $ */
 /*
  * GL2PS, an OpenGL to PostScript Printing Library
  * Copyright (C) 1999-2004 Christophe Geuzaine <geuz@geuz.org>
@@ -64,22 +64,20 @@
 
 /* Magic numbers */
 
-#define GL2PS_EPSILON             5.0e-3F
-#define GL2PS_DEPTH_FACT          1000.0F
-#define GL2PS_SIMPLE_OFFSET       0.05F
-#define GL2PS_SIMPLE_OFFSET_LARGE 1.0F
-#define GL2PS_ZERO(arg)           (fabs(arg)<1.e-20)
-#define GL2PS_FIXED_XREF_ENTRIES  7 
+#define GL2PS_ZERO(arg) (fabs(arg) < 1.e-20)
 
 /* Primitive types */
 
-#define GL2PS_NOTYPE     -1
-#define GL2PS_TEXT       1
-#define GL2PS_POINT      2
-#define GL2PS_LINE       3
-#define GL2PS_QUADRANGLE 4
-#define GL2PS_TRIANGLE   5
-#define GL2PS_PIXMAP     6
+#define GL2PS_NOTYPE          -1
+#define GL2PS_TEXT             1
+#define GL2PS_POINT            2
+#define GL2PS_LINE             3
+#define GL2PS_QUADRANGLE       4
+#define GL2PS_TRIANGLE         5
+#define GL2PS_PIXMAP           6
+#define GL2PS_IMAGEMAP         7
+#define GL2PS_IMAGEMAP_WRITTEN 8
+#define GL2PS_IMAGEMAP_VISIBLE 9
 
 /* BSP tree primitive comparison */
 
@@ -140,18 +138,29 @@ typedef struct {
   GLshort fontsize;
   char *str, *fontname;
   GLint alignment;
+  GLfloat angle;
 } GL2PSstring;
 
+/* FIXME: in the case of an image map, "type" indicates if this image
+   map has already been written to the PostScript file or not, and
+   "format" indicates if this image map is visible or not */
 typedef struct {
   GLsizei width, height;
   GLenum format, type;
   GLfloat *pixels;
 } GL2PSimage;
 
+typedef struct _GL2PSimagemap GL2PSimagemap;
+
+struct _GL2PSimagemap {
+  GL2PSimage *image;
+  GL2PSimagemap *next;
+};
+
 typedef struct {
   GLshort type, numverts;
-  char boundary, dash, culled;
-  GLfloat width, depth;
+  char boundary, offset, dash, culled;
+  GLfloat width;
   GL2PSvertex *verts;
   union {
     GL2PSstring *text;
@@ -179,7 +188,7 @@ typedef struct {
   GLint format, sort, options, colorsize, colormode, buffersize;
   char *title, *producer, *filename;
   GLboolean boundary, blending;
-  GLfloat *feedback, offset[2], lastlinewidth;
+  GLfloat epsilon, *feedback, offset[2], lastlinewidth;
   GLint viewport[4], blendfunc[2];
   GL2PSrgba *colormap, lastrgba, threshold;
   GL2PSlist *primitives;
@@ -205,6 +214,10 @@ typedef struct {
   int trgroupobjects_stack; /* xobject numbers */
   int shader_stack; /* shader object numbers */
   int mshader_stack; /* mask shader object numbers */
+
+  /* for image map list */
+  GL2PSimagemap *imagemap_head;
+  GL2PSimagemap *imagemap_tail;
 } GL2PScontext;
 
 /* The gl2ps context. gl2ps is not thread safe (we should create a
@@ -587,6 +600,7 @@ static GL2PSstring *gl2psCopyText(GL2PSstring* t)
   strcpy(text->fontname, t->fontname);
   text->fontsize = t->fontsize;
   text->alignment = t->alignment;
+  text->angle = t->angle;
   
   return text;
 }
@@ -614,10 +628,10 @@ static GL2PSprimitive *gl2psCopyPrimitive(GL2PSprimitive* p)
   prim->type = p->type;
   prim->numverts = p->numverts;
   prim->boundary = p->boundary;
+  prim->offset = p->offset;
   prim->dash = p->dash;
   prim->culled = p->culled;
   prim->width = p->width;
-  prim->depth = p->depth;
   prim->verts = (GL2PSvertex*)gl2psMalloc(p->numverts*sizeof(GL2PSvertex));
   memcpy(prim->verts, p->verts, p->numverts * sizeof(GL2PSvertex));
 
@@ -801,6 +815,7 @@ static void gl2psGetPlane(GL2PSprimitive *prim, GL2PSplane plane)
   case GL2PS_POINT :
   case GL2PS_PIXMAP :
   case GL2PS_TEXT :
+  case GL2PS_IMAGEMAP:
     plane[0] = plane[1] = 0.0F;
     plane[2] = 1.0F;
     plane[3] = -prim->verts[0].xyz[2];
@@ -840,20 +855,26 @@ static void gl2psCreateSplitPrimitive(GL2PSprimitive *parent, GL2PSplane plane,
 {
   GLshort i;
 
-  if(numverts > 4){
-    gl2psMsg(GL2PS_WARNING, "%d vertices in polygon", numverts);
-    numverts = 4;
+  if(parent->type == GL2PS_IMAGEMAP){
+    child->type = GL2PS_IMAGEMAP;
+    child->data.image = parent->data.image;
   }
-
-  switch(numverts){
-  case 1 : child->type = GL2PS_POINT; break; 
-  case 2 : child->type = GL2PS_LINE; break; 
-  case 3 : child->type = GL2PS_TRIANGLE; break; 
-  case 4 : child->type = GL2PS_QUADRANGLE; break;    
+  else{
+    if(numverts > 4){
+      gl2psMsg(GL2PS_WARNING, "%d vertices in polygon", numverts);
+      numverts = 4;
+    }
+    switch(numverts){
+    case 1 : child->type = GL2PS_POINT; break; 
+    case 2 : child->type = GL2PS_LINE; break; 
+    case 3 : child->type = GL2PS_TRIANGLE; break; 
+    case 4 : child->type = GL2PS_QUADRANGLE; break;    
+    }
   }
+
   child->boundary = 0; /* not done! */
-  child->depth = parent->depth; /* should not be used in this case */
   child->culled = parent->culled;
+  child->offset = parent->offset;
   child->dash = parent->dash;
   child->width = parent->width;
   child->numverts = numverts;
@@ -905,15 +926,15 @@ static GLint gl2psTestSplitPrimitive(GL2PSprimitive *prim, GL2PSplane plane)
   else{
     for(i = 0; i < prim->numverts; i++){
       j = gl2psGetIndex(i, prim->numverts);
-      if(d[j] > GL2PS_EPSILON){
+      if(d[j] > gl2ps->epsilon){
         if(type == GL2PS_COINCIDENT)      type = GL2PS_IN_BACK_OF;
         else if(type != GL2PS_IN_BACK_OF) return 1; 
-        if(d[i] < -GL2PS_EPSILON)         return 1;
+        if(d[i] < -gl2ps->epsilon)        return 1;
       }
-      else if(d[j] < -GL2PS_EPSILON){
+      else if(d[j] < -gl2ps->epsilon){
         if(type == GL2PS_COINCIDENT)       type = GL2PS_IN_FRONT_OF;   
         else if(type != GL2PS_IN_FRONT_OF) return 1;
-        if(d[i] > GL2PS_EPSILON)           return 1;
+        if(d[i] > gl2ps->epsilon)          return 1;
       }
     }
   }
@@ -935,27 +956,27 @@ static GLint gl2psSplitPrimitive(GL2PSprimitive *prim, GL2PSplane plane,
 
   switch(prim->type){
   case GL2PS_POINT :
-    if(d[0] > GL2PS_EPSILON)       type = GL2PS_IN_BACK_OF;
-    else if(d[0] < -GL2PS_EPSILON) type = GL2PS_IN_FRONT_OF;
-    else                           type = GL2PS_COINCIDENT;
+    if(d[0] > gl2ps->epsilon)       type = GL2PS_IN_BACK_OF;
+    else if(d[0] < -gl2ps->epsilon) type = GL2PS_IN_FRONT_OF;
+    else                            type = GL2PS_COINCIDENT;
     break;
   default :
     for(i = 0; i < prim->numverts; i++){
       j = gl2psGetIndex(i, prim->numverts);
-      if(d[j] > GL2PS_EPSILON){
+      if(d[j] > gl2ps->epsilon){
         if(type == GL2PS_COINCIDENT)      type = GL2PS_IN_BACK_OF;
         else if(type != GL2PS_IN_BACK_OF) type = GL2PS_SPANNING; 
-        if(d[i] < -GL2PS_EPSILON){
+        if(d[i] < -gl2ps->epsilon){
           gl2psAddIndex(in0, in1, &in, i, j);
           gl2psAddIndex(out0, out1, &out, i, j);
           type = GL2PS_SPANNING;
         }
         gl2psAddIndex(out0, out1, &out, j, -1);
       }
-      else if(d[j] < -GL2PS_EPSILON){
+      else if(d[j] < -gl2ps->epsilon){
         if(type == GL2PS_COINCIDENT)       type = GL2PS_IN_FRONT_OF;   
         else if(type != GL2PS_IN_FRONT_OF) type = GL2PS_SPANNING;
-        if(d[i] > GL2PS_EPSILON){
+        if(d[i] > gl2ps->epsilon){
           gl2psAddIndex(in0, in1, &in, i, j);
           gl2psAddIndex(out0, out1, &out, i, j);
           type = GL2PS_SPANNING;
@@ -987,8 +1008,8 @@ static void gl2psDivideQuad(GL2PSprimitive *quad,
   *t2 = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive));
   (*t1)->type = (*t2)->type = GL2PS_TRIANGLE;
   (*t1)->numverts = (*t2)->numverts = 3;
-  (*t1)->depth = (*t2)->depth = quad->depth;
   (*t1)->culled = (*t2)->culled = quad->culled;
+  (*t1)->offset = (*t2)->offset = quad->offset;
   (*t1)->dash = (*t2)->dash = quad->dash;
   (*t1)->width = (*t2)->width = quad->width;
   (*t1)->verts = (GL2PSvertex*)gl2psMalloc(3 * sizeof(GL2PSvertex));
@@ -1006,11 +1027,23 @@ static void gl2psDivideQuad(GL2PSprimitive *quad,
 static int gl2psCompareDepth(const void *a, const void *b)
 {
   GL2PSprimitive *q, *w;
-  GLfloat diff;
-
+  GLfloat dq = 0.0F, dw = 0.0F, diff;
+  int i;
+  
   q = *(GL2PSprimitive**)a;
   w = *(GL2PSprimitive**)b;
-  diff = q->depth - w->depth;
+
+  for(i = 0; i < q->numverts; i++){
+    dq += q->verts[i].xyz[2]; 
+  }
+  dq /= (GLfloat)q->numverts;
+
+  for(i = 0; i < w->numverts; i++){
+    dw += w->verts[i].xyz[2]; 
+  }
+  dw /= (GLfloat)w->numverts;
+
+  diff = dq - dw;
   if(diff > 0.){
     return 1;
   }
@@ -1076,6 +1109,17 @@ static GLint gl2psFindRoot(GL2PSlist *primitives, GL2PSprimitive **root)
   }
 }
 
+static void gl2psFreeImagemap(GL2PSimagemap *list){
+  GL2PSimagemap *next;
+  while(list != NULL){
+    next = list->next;
+    gl2psFree(list->image->pixels);
+    gl2psFree(list->image);
+    gl2psFree(list);
+    list = next;
+  }
+}
+
 static void gl2psFreePrimitive(void *data)
 {
   GL2PSprimitive *q;
@@ -1232,6 +1276,83 @@ static void gl2psTraverseBspTree(GL2PSbsptree *tree, GL2PSxyz eye, GLfloat epsil
   }
 }
 
+static void gl2psSetPrecisionAndApplyOffsets()
+{
+  GL2PSprimitive *prim;
+  GLfloat minZ, maxZ;
+  GLfloat factor, units, area, dZ, dZdX, dZdY, maxdZ;
+  int i, j, offset = 0;
+
+  if(!gl2psListNbr(gl2ps->primitives))
+    return;
+
+  /* get z-buffer range */
+  prim = *(GL2PSprimitive**)gl2psListPointer(gl2ps->primitives, 0);
+  minZ = maxZ = prim->verts[0].xyz[2];
+  if(prim->offset) offset = 1; 
+  for(i = 1; i < prim->numverts; i++){
+    if(prim->verts[i].xyz[2] < minZ) minZ = prim->verts[i].xyz[2];
+    if(prim->verts[i].xyz[2] > maxZ) maxZ = prim->verts[i].xyz[2];
+  }
+  for(i = 1; i < gl2psListNbr(gl2ps->primitives); i++){
+    prim = *(GL2PSprimitive**)gl2psListPointer(gl2ps->primitives, i);
+    for(j = 0; j < prim->numverts; j++){
+      if(prim->verts[j].xyz[2] < minZ) minZ = prim->verts[j].xyz[2];
+      if(prim->verts[j].xyz[2] > maxZ) maxZ = prim->verts[j].xyz[2];
+    }
+    if(prim->offset) offset = 1; 
+  }
+
+  /* set precision */
+  gl2ps->epsilon = (maxZ - minZ) / 5000.0F;
+
+  /* apply offsets */
+  if(gl2ps->options & GL2PS_SIMPLE_LINE_OFFSET){
+    for(i = 0; i < gl2psListNbr(gl2ps->primitives); i++){
+      prim = *(GL2PSprimitive**)gl2psListPointer(gl2ps->primitives, i);
+      if(prim->type == GL2PS_LINE){
+	if(gl2ps->sort == GL2PS_SIMPLE_SORT){
+	  prim->verts[0].xyz[2] -= (maxZ - minZ) / 25.0F;
+	  prim->verts[1].xyz[2] -= (maxZ - minZ) / 25.0F;
+	}
+	else{
+	  prim->verts[0].xyz[2] -= (maxZ - minZ) / 500.0F;
+	  prim->verts[1].xyz[2] -= (maxZ - minZ) / 500.0F;
+	}
+      }
+    }
+  }
+  else if(offset){ /* at least one primitive needs to be offsetted */
+    factor = gl2ps->offset[0];
+    units = gl2ps->offset[1];
+    for(i = 0; i < gl2psListNbr(gl2ps->primitives); i++){
+      prim = *(GL2PSprimitive**)gl2psListPointer(gl2ps->primitives, i);
+      if(prim->type == GL2PS_TRIANGLE){ /* FIXME: needs more work! */
+    	area = 
+	  (prim->verts[1].xyz[0] - prim->verts[0].xyz[0]) * 
+	  (prim->verts[2].xyz[1] - prim->verts[1].xyz[1]) - 
+	  (prim->verts[2].xyz[0] - prim->verts[1].xyz[0]) * 
+	  (prim->verts[1].xyz[1] - prim->verts[0].xyz[1]);
+	dZdX = 
+	  (prim->verts[2].xyz[1] - prim->verts[1].xyz[1]) *
+	  (prim->verts[1].xyz[2] - prim->verts[0].xyz[2]) -
+	  (prim->verts[1].xyz[1] - prim->verts[0].xyz[1]) *
+	  (prim->verts[2].xyz[2] - prim->verts[1].xyz[2]) / area;
+	dZdY = 
+	  (prim->verts[1].xyz[0] - prim->verts[0].xyz[0]) *
+	  (prim->verts[2].xyz[2] - prim->verts[1].xyz[2]) -
+	  (prim->verts[2].xyz[0] - prim->verts[1].xyz[0]) *
+	  (prim->verts[1].xyz[2] - prim->verts[0].xyz[2]) / area;
+	maxdZ = (GLfloat)sqrt(dZdX*dZdX + dZdY*dZdY);
+	dZ = factor * maxdZ + units;
+	prim->verts[0].xyz[2] += dZ;
+	prim->verts[1].xyz[2] += dZ;
+	prim->verts[2].xyz[2] += dZ;
+      }
+    }
+  }
+}
+
 /********************************************************************* 
  *
  * 2D sorting routines (for occlusion culling) 
@@ -1275,9 +1396,9 @@ static GLint gl2psCheckPoint(GL2PSxyz point, GL2PSplane plane)
   GLfloat pt_dis;
 
   pt_dis = gl2psComparePointPlane(point, plane);
-  if(pt_dis > GL2PS_EPSILON)        return GL2PS_POINT_INFRONT;
-  else if(pt_dis < -GL2PS_EPSILON)  return GL2PS_POINT_BACK;
-  else                              return GL2PS_POINT_COINCIDENT;
+  if(pt_dis > gl2ps->epsilon)        return GL2PS_POINT_INFRONT;
+  else if(pt_dis < -gl2ps->epsilon)  return GL2PS_POINT_BACK;
+  else                               return GL2PS_POINT_COINCIDENT;
 }
 
 static void gl2psAddPlanesInBspTreeImage(GL2PSprimitive *prim,
@@ -1402,15 +1523,21 @@ static GL2PSprimitive *gl2psCreateSplitPrimitive2D(GL2PSprimitive *parent,
   GLint i;
   GL2PSprimitive *child = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive));
 
-  switch(numverts){
-  case 1 : child->type = GL2PS_POINT; break;
-  case 2 : child->type = GL2PS_LINE; break;
-  case 3 : child->type = GL2PS_TRIANGLE; break;
-  case 4 : child->type = GL2PS_QUADRANGLE; break;
+  if(parent->type == GL2PS_IMAGEMAP){
+    child->type = GL2PS_IMAGEMAP;
+    child->data.image = parent->data.image;
+  }
+  else {
+    switch(numverts){
+    case 1 : child->type = GL2PS_POINT; break;
+    case 2 : child->type = GL2PS_LINE; break;
+    case 3 : child->type = GL2PS_TRIANGLE; break;
+    case 4 : child->type = GL2PS_QUADRANGLE; break;
+    }
   }
   child->boundary = 0; /* not done! */
-  child->depth = parent->depth;
   child->culled = parent->culled;
+  child->offset = parent->offset;
   child->dash = parent->dash;
   child->width = parent->width;
   child->numverts = numverts;
@@ -1518,7 +1645,7 @@ static GLint gl2psAddInBspImageTree(GL2PSprimitive *prim, GL2PSbsptree2d **tree)
   }
 
   if(*tree == NULL){
-    if(GL_FALSE == gl2ps->zerosurfacearea){
+    if((prim->type != GL2PS_IMAGEMAP) && (GL_FALSE == gl2ps->zerosurfacearea)){
       gl2psAddPlanesInBspTreeImage(gl2ps->primitivetoadd, tree);
     }
     return 1;
@@ -1566,9 +1693,15 @@ static void gl2psAddInImageTree(void *data)
 {
   GL2PSprimitive *prim = *(GL2PSprimitive **)data;
   gl2ps->primitivetoadd = prim;
-  if(!gl2psAddInBspImageTree(prim, &gl2ps->imagetree)){
+  if(prim->type == GL2PS_IMAGEMAP && prim->data.image->format == GL2PS_IMAGEMAP_VISIBLE){
+    prim->culled = 1;
+  }
+  else if(!gl2psAddInBspImageTree(prim, &gl2ps->imagetree)){
     prim->culled = 1;
   }
+  else if(prim->type == GL2PS_IMAGEMAP){
+    prim->data.image->format = GL2PS_IMAGEMAP_VISIBLE;
+  }
 }
 
 /* Boundary construction */
@@ -1591,8 +1724,8 @@ static void gl2psAddBoundaryInList(GL2PSprimitive *prim, GL2PSlist *list)
     if(prim->boundary & (GLint)pow(2., i)){
       b = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive));
       b->type = GL2PS_LINE;
+      b->offset = prim->offset;
       b->dash = prim->dash;
-      b->depth = prim->depth; /* FIXME: this is wrong */
       b->culled = prim->culled;
       b->width = prim->width;
       b->boundary = 0;
@@ -1665,8 +1798,6 @@ static void gl2psAddPolyPrimitive(GLshort type, GLshort numverts,
                                   char dash, GLfloat width,
                                   char boundary)
 {
-  GLshort i;
-  GLfloat factor, units, area, dZ, dZdX, dZdY, maxdZ;
   GL2PSprimitive *prim;
 
   prim = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive));
@@ -1675,70 +1806,10 @@ static void gl2psAddPolyPrimitive(GLshort type, GLshort numverts,
   prim->verts = (GL2PSvertex*)gl2psMalloc(numverts * sizeof(GL2PSvertex));
   memcpy(prim->verts, verts, numverts * sizeof(GL2PSvertex));
   prim->boundary = boundary;
+  prim->offset = offset;
   prim->dash = dash;
   prim->width = width;
   prim->culled = 0;
-
-  if(gl2ps->options & GL2PS_SIMPLE_LINE_OFFSET){
-
-    if(type == GL2PS_LINE){
-      if(gl2ps->sort == GL2PS_SIMPLE_SORT){
-        prim->verts[0].xyz[2] -= GL2PS_SIMPLE_OFFSET_LARGE;
-        prim->verts[1].xyz[2] -= GL2PS_SIMPLE_OFFSET_LARGE;
-      }
-      else{
-        prim->verts[0].xyz[2] -= GL2PS_SIMPLE_OFFSET;
-        prim->verts[1].xyz[2] -= GL2PS_SIMPLE_OFFSET;
-      }
-    }
-
-  }
-  else if(offset && type == GL2PS_TRIANGLE){
-
-    /* FIXME: this needs some more work... */
-
-    if(gl2ps->sort == GL2PS_SIMPLE_SORT){    
-      factor = gl2ps->offset[0];
-      units = gl2ps->offset[1];
-    }
-    else{
-      factor = gl2ps->offset[0] / 800.0F;
-      units = gl2ps->offset[1] / 800.0F;
-    }
-
-    area = 
-      (prim->verts[1].xyz[0] - prim->verts[0].xyz[0]) * 
-      (prim->verts[2].xyz[1] - prim->verts[1].xyz[1]) - 
-      (prim->verts[2].xyz[0] - prim->verts[1].xyz[0]) * 
-      (prim->verts[1].xyz[1] - prim->verts[0].xyz[1]);
-    dZdX = 
-      (prim->verts[2].xyz[1] - prim->verts[1].xyz[1]) *
-      (prim->verts[1].xyz[2] - prim->verts[0].xyz[2]) -
-      (prim->verts[1].xyz[1] - prim->verts[0].xyz[1]) *
-      (prim->verts[2].xyz[2] - prim->verts[1].xyz[2]) / area;
-    dZdY = 
-      (prim->verts[1].xyz[0] - prim->verts[0].xyz[0]) *
-      (prim->verts[2].xyz[2] - prim->verts[1].xyz[2]) -
-      (prim->verts[2].xyz[0] - prim->verts[1].xyz[0]) *
-      (prim->verts[1].xyz[2] - prim->verts[0].xyz[2]) / area;
-    
-    maxdZ = (GLfloat)sqrt(dZdX*dZdX + dZdY*dZdY);
-
-    dZ = factor * maxdZ + units;
-
-    prim->verts[0].xyz[2] += dZ;
-    prim->verts[1].xyz[2] += dZ;
-    prim->verts[2].xyz[2] += dZ;
-  }
-
-  prim->depth = 0.;
-  if(gl2ps->sort == GL2PS_SIMPLE_SORT){
-    for(i = 0; i < numverts; i++){
-      prim->depth += prim->verts[i].xyz[2]; 
-    }
-    prim->depth /= (GLfloat)numverts;
-  }
-  
   gl2psListAdd(gl2ps->primitives, &prim);
 }
 
@@ -1748,7 +1819,7 @@ static GLint gl2psGetVertex(GL2PSvertex *v, GLfloat *p)
 
   v->xyz[0] = p[0];
   v->xyz[1] = p[1];
-  v->xyz[2] = GL2PS_DEPTH_FACT * p[2];
+  v->xyz[2] = p[2];
 
   if(gl2ps->colormode == GL_COLOR_INDEX && gl2ps->colorsize > 0){
     i = (GLint)(p[3] + 0.5);
@@ -1771,10 +1842,12 @@ static void gl2psParseFeedbackBuffer(GLint used)
 {
   char flag, dash = 0;
   GLboolean boundary;
-  GLint i, count, v, vtot, offset = 0;
+  GLint i, sizeoffloat, count, v, vtot, offset = 0;
   GLfloat lwidth = 1.0F, psize = 1.0F;
   GLfloat *current;
   GL2PSvertex vertices[3];
+  GL2PSprimitive *prim;
+  GL2PSimagemap *node;
 
   current = gl2ps->feedback;
   boundary = gl2ps->boundary = GL_FALSE;
@@ -1872,6 +1945,69 @@ static void gl2psParseFeedbackBuffer(GLint used)
         used -= 2; 
         lwidth = current[1];
         break;
+      case GL2PS_DRAW_IMAGEMAP_TOKEN :
+        prim = (GL2PSprimitive *)gl2psMalloc(sizeof(GL2PSprimitive));
+        prim->type = GL2PS_IMAGEMAP;
+        prim->boundary = 0;
+        prim->numverts = 4;
+        prim->verts = (GL2PSvertex *)gl2psMalloc(4 * sizeof(GL2PSvertex));
+        prim->culled = 0;
+        prim->offset = 0;
+        prim->dash = 0;
+        prim->width = 1;
+        
+        node = (GL2PSimagemap*)gl2psMalloc(sizeof(GL2PSimagemap));
+        node->image = (GL2PSimage*)gl2psMalloc(sizeof(GL2PSimage));
+        node->image->type = 0;
+        node->image->format = 0;
+        node->next = NULL;
+        
+        if(gl2ps->imagemap_head == NULL)
+          gl2ps->imagemap_head = node;
+        else
+          gl2ps->imagemap_tail->next = node;
+        gl2ps->imagemap_tail = node;
+        prim->data.image = node->image;
+        
+        current += 2; used -= 2;
+        i = gl2psGetVertex(&prim->verts[0], &current[1]);
+        current += i; used -= i;
+        
+        node->image->width = (GLint)current[2];
+        current += 2; used -= 2;
+        node->image->height = (GLint)current[2];
+        prim->verts[0].xyz[0] = prim->verts[0].xyz[0] - (int)(node->image->width / 2) + 0.5;
+        prim->verts[0].xyz[1] = prim->verts[0].xyz[1] - (int)(node->image->height / 2) + 0.5;
+        for(i = 1; i < 4; i++){
+          for(v = 0; v < 3; v++){
+            prim->verts[i].xyz[v] = prim->verts[0].xyz[v];
+            prim->verts[i].rgba[v] = prim->verts[0].rgba[v];
+          }
+          prim->verts[i].rgba[v] = prim->verts[0].rgba[v];
+        }
+        prim->verts[1].xyz[0] = prim->verts[1].xyz[0] + node->image->width;
+        prim->verts[2].xyz[0] = prim->verts[1].xyz[0];
+        prim->verts[2].xyz[1] = prim->verts[2].xyz[1] + node->image->height;
+        prim->verts[3].xyz[1] = prim->verts[2].xyz[1];
+
+        sizeoffloat = sizeof(GLfloat);
+        v = 2 * sizeoffloat;
+        vtot = node->image->height + node->image->height * 
+          ((node->image->width-1)/8);
+        node->image->pixels = (GLfloat*)gl2psMalloc(v + vtot);
+        node->image->pixels[0] = prim->verts[0].xyz[0];
+        node->image->pixels[1] = prim->verts[0].xyz[1];
+        
+        for(i = 0; i < vtot; i += sizeoffloat){
+          current += 2; used -= 2;
+          if((vtot - i) >= 4)
+            memcpy(&(((char*)(node->image->pixels))[i + v]), &(current[2]), sizeoffloat);
+          else
+            memcpy(&(((char*)(node->image->pixels))[i + v]), &(current[2]), vtot - i);
+        }
+        current++; used--;
+        gl2psListAdd(gl2ps->primitives, &prim);
+        break;
       }
       current += 2; 
       used -= 2; 
@@ -1926,33 +2062,34 @@ static void gl2psWriteByte(unsigned char byte)
 
 static void gl2psPrintPostScriptPixmap(GLfloat x, GLfloat y, GL2PSimage *im)
 {
-  int nbhex, nbyte2, nbyte4, nbyte8;
-  GLsizei row, col, col_max;
-  GLfloat dr, dg, db;
-  unsigned char red, green, blue, b, grey;
-  GLsizei width = im->width;
-  GLsizei height = im->height;
+  GLuint nbhex, nbyte, nrgb, nbits;
+  GLuint row, col, ibyte, icase;
+  GLfloat dr, dg, db, fgrey;
+  unsigned char red = 0, green = 0, blue = 0, b, grey;
+  GLuint width = (GLuint)im->width;
+  GLuint height = (GLuint)im->height;
 
   /* FIXME: should we define an option for these? */
   int greyscale = 0; /* set to 1 to output greyscale image */
-  int nbits = 8; /* number of bits per color compoment (2, 4 or 8) */
+  int nbit = 8; /* number of bits per color compoment (2, 4 or 8) */
 
   if((width <= 0) || (height <= 0)) return;
 
   gl2psPrintf("gsave\n");
   gl2psPrintf("%.2f %.2f translate\n", x, y); 
-  gl2psPrintf("%d %d scale\n", (int)width, (int)height); 
+  gl2psPrintf("%d %d scale\n", width, height); 
 
-  if(greyscale){ /* greyscale, 8 bits per pixel */
-    gl2psPrintf("/picstr %d string def\n", (int)width); 
-    gl2psPrintf("%d %d %d\n", (int)width, (int)height, 8); 
-    gl2psPrintf("[ %d 0 0 -%d 0 %d ]\n", (int)width, (int)height, (int)height); 
+  if(greyscale){ /* greyscale */
+    gl2psPrintf("/picstr %d string def\n", width); 
+    gl2psPrintf("%d %d %d\n", width, height, 8); 
+    gl2psPrintf("[ %d 0 0 -%d 0 %d ]\n", width, height, height); 
     gl2psPrintf("{ currentfile picstr readhexstring pop }\n");
     gl2psPrintf("image\n");
     for(row = 0; row < height; row++){
       for(col = 0; col < width; col++){ 
         gl2psGetRGB(im, col, row, &dr, &dg, &db);
-        grey = (unsigned char)(255.0 * (0.30 * dr + 0.59 * dg + 0.11 * db));
+        fgrey = (0.30 * dr + 0.59 * dg + 0.11 * db);
+        grey = (unsigned char)(255. * fgrey);
         gl2psWriteByte(grey);
       }
       gl2psPrintf("\n");
@@ -1960,107 +2097,189 @@ static void gl2psPrintPostScriptPixmap(GLfloat x, GLfloat y, GL2PSimage *im)
     nbhex = width * height * 2; 
     gl2psPrintf("%%%% nbhex digit          :%d\n", nbhex); 
   }
-  else if(nbits == 2){ /* color, 2 bits for r and g and b; rgbs following each other */
-    nbyte2 = (width * 3)/4;
-    nbyte2 /=3;
-    nbyte2 *=3;
-    col_max = (nbyte2 * 4)/3;
-    gl2psPrintf("/rgbstr %d string def\n", nbyte2); 
-    gl2psPrintf("%d %d %d\n", (int)col_max, (int)height, 2); 
-    gl2psPrintf("[ %d 0 0 -%d 0 %d ]\n", (int)col_max, (int)height, (int)height); 
-    gl2psPrintf("{ currentfile rgbstr readhexstring pop }\n" );
-    gl2psPrintf("false 3\n" );
-    gl2psPrintf("colorimage\n" );
+  else if(nbit == 2){ /* color, 2 bits for r and g and b; rgbs following each other */
+    nrgb = width  * 3;
+    nbits = nrgb * nbit;
+    nbyte = nbits/8;
+    if((nbyte * 8) != nbits) nbyte++;
+    gl2psPrintf("/rgbstr %d string def\n", nbyte);
+    gl2psPrintf("%d %d %d\n", width, height, nbit);
+    gl2psPrintf("[ %d 0 0 -%d 0 %d ]\n", width, height, height);
+    gl2psPrintf("{ currentfile rgbstr readhexstring pop }\n");
+    gl2psPrintf("false 3\n");
+    gl2psPrintf("colorimage\n");
     for(row = 0; row < height; row++){
-      for(col = 0; col < col_max; col+=4){
-        gl2psGetRGB(im, col, row, &dr, &dg, &db);
-        red = (unsigned char)(3.0 * dr);
-        green = (unsigned char)(3.0 * dg);
-        blue = (unsigned char)(3.0 * db);
-        b = red;
-        b = (b<<2)+green;
-        b = (b<<2)+blue;
-        gl2psGetRGB(im, col+1, row, &dr, &dg, &db);
-        red = (unsigned char)(3.0 * dr);
-        green = (unsigned char)(3.0 * dg);
-        blue = (unsigned char)(3.0 * db);
-        b = (b<<2)+red;
-        gl2psWriteByte(b);
-        b = green;
-        b = (b<<2)+blue;
-        gl2psGetRGB(im, col+2, row, &dr, &dg, &db);
-        red = (unsigned char)(3.0 * dr);
-        green = (unsigned char)(3.0 * dg);
-        blue = (unsigned char)(3.0 * db);
-        b = (b<<2)+red;
-        b = (b<<2)+green;
-        gl2psWriteByte(b);
-        b = blue;
-        gl2psGetRGB(im, col+3, row, &dr, &dg, &db);
-        red = (unsigned char)(3.0 * dr);
-        green = (unsigned char)(3.0 * dg);
-        blue = (unsigned char)(3.0 * db);
-        b = (b<<2)+red;
-        b = (b<<2)+green;
-        b = (b<<2)+blue;
-        gl2psWriteByte(b);
+      icase = 1;
+      col = 0;
+      b = 0;
+      for(ibyte = 0; ibyte < nbyte; ibyte++){
+        if(icase == 1) {
+          if(col < width) {
+            gl2psGetRGB(im, col, row, &dr, &dg, &db);
+          } 
+          else {
+            dr = dg = db = 0;
+          }
+          col++;
+          red = (unsigned char)(3. * dr);
+          green = (unsigned char)(3. * dg);
+          blue = (unsigned char)(3. * db);
+          b = red;
+          b = (b<<2) + green;
+          b = (b<<2) + blue;
+          if(col < width) {
+            gl2psGetRGB(im, col, row, &dr, &dg, &db);
+          } 
+          else {
+            dr = dg = db = 0;
+          }
+          col++;
+          red = (unsigned char)(3. * dr);
+          green = (unsigned char)(3. * dg);
+          blue = (unsigned char)(3. * db);
+          b = (b<<2) + red;
+          gl2psWriteByte(b);
+          b = 0;
+          icase++;
+        } 
+        else if(icase == 2) {
+          b = green;
+          b = (b<<2) + blue;
+          if(col < width) {
+            gl2psGetRGB(im, col, row, &dr, &dg, &db);
+          }
+          else {
+            dr = dg = db = 0;
+          }
+          col++;
+          red = (unsigned char)(3. * dr);
+          green = (unsigned char)(3. * dg);
+          blue = (unsigned char)(3. * db);
+          b = (b<<2) + red;
+          b = (b<<2) + green;
+          gl2psWriteByte(b);
+          b = 0;
+          icase++;
+        } 
+        else if(icase == 3) {
+          b = blue;
+          if(col < width) {
+            gl2psGetRGB(im, col, row, &dr, &dg, &db);
+          }
+          else {
+            dr = dg = db = 0;
+          }
+          col++;
+          red = (unsigned char)(3. * dr);
+          green = (unsigned char)(3. * dg);
+          blue = (unsigned char)(3. * db);
+          b = (b<<2) + red;
+          b = (b<<2) + green;
+          b = (b<<2) + blue;
+          gl2psWriteByte(b);
+          b = 0;
+          icase = 1;
+        }
       }
       gl2psPrintf("\n");
     }
   }
-  else if(nbits == 4){ /* color, 4 bits for r and g and b; rgbs following each other */
-    nbyte4 = (width  * 3)/2;
-    nbyte4 /=3;
-    nbyte4 *=3;
-    col_max = (nbyte4 * 2)/3;
-    gl2psPrintf("/rgbstr %d string def\n", nbyte4);
-    gl2psPrintf("%d %d %d\n", (int)col_max, (int)height, 4);
-    gl2psPrintf("[ %d 0 0 -%d 0 %d ]\n", (int)col_max, (int)height, (int)height);
+  else if(nbit == 4){ /* color, 4 bits for r and g and b; rgbs following each other */
+    nrgb = width  * 3;
+    nbits = nrgb * nbit;
+    nbyte = nbits/8;
+    if((nbyte * 8) != nbits) nbyte++; 
+    gl2psPrintf("/rgbstr %d string def\n", nbyte);
+    gl2psPrintf("%d %d %d\n", width, height, nbit);
+    gl2psPrintf("[ %d 0 0 -%d 0 %d ]\n", width, height, height);
     gl2psPrintf("{ currentfile rgbstr readhexstring pop }\n");
     gl2psPrintf("false 3\n");
     gl2psPrintf("colorimage\n");
     for(row = 0; row < height; row++){
-      for(col = 0; col < col_max; col+=2){
-        gl2psGetRGB(im, col, row, &dr, &dg, &db);
-        red = (unsigned char)(15. * dr);
-        green = (unsigned char)(15. * dg);
-        gl2psPrintf("%x%x", red, green);
-        blue = (unsigned char)(15. * db);
-        gl2psGetRGB(im, col+1, row, &dr, &dg, &db);
-        red = (unsigned char)(15. * dr);
-        gl2psPrintf("%x%x",blue,red);
-        green = (unsigned char)(15. * dg);
-        blue = (unsigned char)(15. * db);
-        gl2psPrintf("%x%x", green, blue);
+      col = 0;
+      icase = 1;
+      for(ibyte = 0; ibyte < nbyte; ibyte++){
+        if(icase == 1) {
+          if(col < width) {
+            gl2psGetRGB(im, col, row, &dr, &dg, &db);
+          } 
+          else {
+            dr = dg = db = 0;
+          }
+          col++;
+          red = (unsigned char)(15. * dr);
+          green = (unsigned char)(15. * dg);
+          gl2psPrintf("%x%x", red, green);
+          icase++;
+        } 
+        else if(icase == 2) {
+          blue = (unsigned char)(15. * db);
+          if(col < width) {
+            gl2psGetRGB(im, col, row, &dr, &dg, &db);
+          } 
+          else {
+            dr = dg = db = 0;
+          }
+          col++;
+          red = (unsigned char)(15. * dr);
+          gl2psPrintf("%x%x", blue, red);
+          icase++;
+        }
+        else if(icase == 3) {
+          green = (unsigned char)(15. * dg);
+          blue = (unsigned char)(15. * db);
+          gl2psPrintf("%x%x", green, blue);
+          icase = 1;
+        }
       }
       gl2psPrintf("\n");
     }
   }
-  else{ /* color, 8 bits for r and g and b; rgbs following each other */
-    nbyte8 = width * 3;
-    gl2psPrintf("/rgbstr %d string def\n", nbyte8);
-    gl2psPrintf("%d %d %d\n", (int)width, (int)height, 8);
-    gl2psPrintf("[ %d 0 0 -%d 0 %d ]\n", (int)width, (int)height, (int)height); 
+  else{ /* 8 bit for r and g and b */
+    nbyte = width * 3;
+    gl2psPrintf("/rgbstr %d string def\n", nbyte);
+    gl2psPrintf("%d %d %d\n", width, height, 8);
+    gl2psPrintf("[ %d 0 0 -%d 0 %d ]\n", width, height, height); 
     gl2psPrintf("{ currentfile rgbstr readhexstring pop }\n");
     gl2psPrintf("false 3\n");
     gl2psPrintf("colorimage\n");
     for(row = 0; row < height; row++){
       for(col = 0; col < width; col++){
         gl2psGetRGB(im, col, row, &dr, &dg, &db);
-        red = (unsigned char)(255.0 * dr);
+        red = (unsigned char)(255. * dr);
         gl2psWriteByte(red);
-        green = (unsigned char)(255.0 * dg);
+        green = (unsigned char)(255. * dg);
         gl2psWriteByte(green);
-        blue = (unsigned char)(255.0 * db);
+        blue = (unsigned char)(255. * db);
         gl2psWriteByte(blue);
       }
       gl2psPrintf("\n");
     }
   }
-
+  
   gl2psPrintf("grestore\n");
 }
 
+static void gl2psPrintPostScriptImagemap(GLfloat x, GLfloat y,
+                                         GLsizei width, GLsizei height,
+                                         const unsigned char *imagemap){
+  int i, size;
+  
+  if((width <= 0) || (height <= 0)) return;
+  
+  size = height + height * (width-1)/8;
+  
+  gl2psPrintf("gsave\n");
+  gl2psPrintf("%.2f %.2f translate\n", x, y);
+  gl2psPrintf("%d %d scale\n%d %d\ntrue\n", width, height,width, height); 
+  gl2psPrintf("[ %d 0 0 -%d 0 %d ] {<", width, height);
+  for(i = 0; i < size; i++){
+    gl2psWriteByte(*imagemap);
+    imagemap++;
+  }
+  gl2psPrintf(">} imagemask\ngrestore\n");
+}
+
 static void gl2psPrintPostScriptHeader(void)
 {
   GLint index;
@@ -2129,7 +2348,7 @@ static void gl2psPrintPostScriptHeader(void)
   /* RGB color: r g b C (replace C by G in output to change from rgb to gray)
      Grayscale: r g b G
      Font choose: size fontname FC
-     String primitive: (string) x y size fontname S
+     Text string: (string) x y size fontname SXX
      Point primitive: x y size P
      Line width: width W
      Flat-shaded line: x2 y2 x1 y1 L
@@ -2150,10 +2369,21 @@ static void gl2psPrintPostScriptHeader(void)
   gl2psPrintf("/BD { bind def } bind def\n"
               "/C  { setrgbcolor } BD\n"
               "/G  { 0.082 mul exch 0.6094 mul add exch 0.3086 mul add neg 1.0 add setgray } BD\n"
-              "/W  { setlinewidth } BD\n"
-              "/FC { findfont exch scalefont setfont } BD\n"
+              "/W  { setlinewidth } BD\n");
+
+  gl2psPrintf("/FC { findfont exch /SH exch def SH scalefont setfont } BD\n"
+              "/SW { dup stringwidth pop } BD\n"
               "/S  { FC moveto show } BD\n"
-              "/P  { newpath 0.0 360.0 arc closepath fill } BD\n"
+              "/SBC{ FC moveto SW -2 div 0 rmoveto show } BD\n"
+              "/SBR{ FC moveto SW neg 0 rmoveto show } BD\n"
+              "/SCL{ FC moveto 0 SH -2 div rmoveto show } BD\n"
+              "/SCC{ FC moveto SW -2 div SH -2 div rmoveto show } BD\n"
+              "/SCR{ FC moveto SW neg SH -2 div rmoveto show } BD\n"
+              "/STL{ FC moveto 0 SH neg rmoveto show } BD\n"
+              "/STC{ FC moveto SW -2 div SH neg rmoveto show } BD\n"
+              "/STR{ FC moveto SW neg SH neg rmoveto show } BD\n");
+
+  gl2psPrintf("/P  { newpath 0.0 360.0 arc closepath fill } BD\n"
               "/L  { newpath moveto lineto stroke } BD\n"
               "/SL { C moveto C lineto stroke } BD\n"
               "/T  { newpath moveto lineto lineto closepath fill } BD\n");
@@ -2324,11 +2554,52 @@ static void gl2psPrintPostScriptPrimitive(void *data)
     gl2psPrintPostScriptPixmap(prim->verts[0].xyz[0], prim->verts[0].xyz[1],
                                prim->data.image);
     break;
+  case GL2PS_IMAGEMAP :
+    if(prim->data.image->type != GL2PS_IMAGEMAP_WRITTEN){
+      gl2psPrintPostScriptColor(prim->verts[0].rgba);
+      gl2psPrintPostScriptImagemap(prim->data.image->pixels[0],
+                                   prim->data.image->pixels[1],
+                                   prim->data.image->width, prim->data.image->height,
+                                   (const unsigned char*)(&(prim->data.image->pixels[2])));
+      prim->data.image->type = GL2PS_IMAGEMAP_WRITTEN;
+    }
+    break;
   case GL2PS_TEXT :
     gl2psPrintPostScriptColor(prim->verts[0].rgba);
-    gl2psPrintf("(%s) %g %g %d /%s S\n",
+    gl2psPrintf("(%s) %g %g %d /%s ",
                 prim->data.text->str, prim->verts[0].xyz[0], prim->verts[0].xyz[1],
                 prim->data.text->fontsize, prim->data.text->fontname);
+
+    switch(prim->data.text->alignment){
+    case GL2PS_TEXT_C:
+      gl2psPrintf("SCC\n");
+      break;
+    case GL2PS_TEXT_CL:
+      gl2psPrintf("SCL\n");
+      break;
+    case GL2PS_TEXT_CR:
+      gl2psPrintf("SCR\n");
+      break;
+    case GL2PS_TEXT_B:
+      gl2psPrintf("SBC\n");
+      break;
+    case GL2PS_TEXT_BR:
+      gl2psPrintf("SBR\n");
+      break;
+    case GL2PS_TEXT_T:
+      gl2psPrintf("STC\n");
+      break;
+    case GL2PS_TEXT_TL:
+      gl2psPrintf("STL\n");
+      break;
+    case GL2PS_TEXT_TR:
+      gl2psPrintf("STR\n");
+      break;
+    case GL2PS_TEXT_BL:
+    default:
+      gl2psPrintf("S\n");
+      break;
+    }
     break;
   case GL2PS_POINT :
     gl2psPrintPostScriptColor(prim->verts[0].rgba);
@@ -2534,35 +2805,40 @@ static void gl2psPrintTeXPrimitive(void *data)
             prim->verts[0].xyz[0], prim->verts[0].xyz[1]);
     switch(prim->data.text->alignment){
     case GL2PS_TEXT_CL:
-      fprintf(gl2ps->stream, "[l]");
+      fprintf(gl2ps->stream, "[l]{");
       break;
     case GL2PS_TEXT_CR:
-      fprintf(gl2ps->stream, "[r]");
+      fprintf(gl2ps->stream, "[r]{");
       break;
     case GL2PS_TEXT_B:
-      fprintf(gl2ps->stream, "[b]");
+      fprintf(gl2ps->stream, "[b]{");
       break;
     case GL2PS_TEXT_BL:
-      fprintf(gl2ps->stream, "[bl]");
+      fprintf(gl2ps->stream, "[bl]{");
       break;
     case GL2PS_TEXT_BR:
-      fprintf(gl2ps->stream, "[br]");
+      fprintf(gl2ps->stream, "[br]{");
       break;
     case GL2PS_TEXT_T:
-      fprintf(gl2ps->stream, "[t]");
+      fprintf(gl2ps->stream, "[t]{");
       break;
     case GL2PS_TEXT_TL:
-      fprintf(gl2ps->stream, "[tl]");
+      fprintf(gl2ps->stream, "[tl]{");
       break;
     case GL2PS_TEXT_TR:
-      fprintf(gl2ps->stream, "[tr]");
+      fprintf(gl2ps->stream, "[tr]{");
       break;
     default:
       break;
     }
-    fprintf(gl2ps->stream, "{\\textcolor[rgb]{%f,%f,%f}{",
-            prim->verts[0].rgba[0], prim->verts[0].rgba[1], prim->verts[0].rgba[2]);
-    fprintf(gl2ps->stream, "{%s}}}}\n", prim->data.text->str);
+    if(prim->data.text->angle)
+      fprintf(gl2ps->stream, "\\rotatebox{%g}{", prim->data.text->angle);
+    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);
+    if(prim->data.text->angle)
+      fprintf(gl2ps->stream, "}");
+    fprintf(gl2ps->stream, "}}\n");
     break;
   default :
     break;
@@ -2657,7 +2933,7 @@ static void gl2psPutPDFImage(GL2PSimage *image, int cnt, GLfloat x, GLfloat y)
 
 static void gl2psPDFstacksInit(void)
 {
-  gl2ps->objects_stack = GL2PS_FIXED_XREF_ENTRIES + 1; 
+  gl2ps->objects_stack = 7 /* FIXED_XREF_ENTRIES */ + 1; 
   gl2ps->extgs_stack = 0;   
   gl2ps->font_stack = 0;    
   gl2ps->im_stack = 0;      
@@ -3686,7 +3962,7 @@ static int gl2psPrintPDFShaderSimpleExtGS(int obj, GLfloat alpha)
   return offs;
 }
 
-/* Similar groups of  functions for pixmaps and text */
+/* Similar groups of functions for pixmaps and text */
 
 static int gl2psPrintPDFPixmapStreamData(GL2PSimage* im,
                                          size_t (*action)(unsigned long data, 
@@ -4027,10 +4303,12 @@ static GLint gl2psPrintPrimitives(void)
   }
 
   if(!gl2psListNbr(gl2ps->primitives)){
-    /* Empty feedback buffer and/or nothing else to print */
+    /* empty feedback buffer and/or nothing else to print */
     return GL2PS_NO_FEEDBACK;
   }
 
+  gl2psSetPrecisionAndApplyOffsets();
+
   switch(gl2ps->format){
   case GL2PS_TEX :
     pprim = gl2psPrintTeXPrimitive;
@@ -4067,11 +4345,11 @@ static GLint gl2psPrintPrimitives(void)
     gl2psBuildBspTree(root, gl2ps->primitives);
     if(GL_TRUE == gl2ps->boundary) gl2psBuildPolygonBoundary(root);
     if(gl2ps->options & GL2PS_OCCLUSION_CULL){
-      gl2psTraverseBspTree(root, eye, -(float)GL2PS_EPSILON, gl2psLess,
+      gl2psTraverseBspTree(root, eye, -gl2ps->epsilon, gl2psLess,
                            gl2psAddInImageTree, 1);
       gl2psFreeBspImageTree(&gl2ps->imagetree);
     }
-    gl2psTraverseBspTree(root, eye, (float)GL2PS_EPSILON, gl2psGreater, 
+    gl2psTraverseBspTree(root, eye, gl2ps->epsilon, gl2psGreater, 
                          pprim, 0);
     gl2psFreeBspTree(&root);
     /* reallocate the primitive list (it's been deleted by
@@ -4114,6 +4392,9 @@ GL2PSDLL_API GLint gl2psBeginPage(const char *title, const char *producer,
   gl2ps->sort = sort;
   gl2ps->options = options;
   gl2ps->compress = NULL;
+  gl2ps->imagemap_head = NULL;
+  gl2ps->imagemap_tail = NULL;
+  gl2ps->epsilon = 0.0F; /* adjusted later according to z-buffer values */
 
   if(gl2ps->options & GL2PS_USE_CURRENT_VIEWPORT){
     glGetIntegerv(GL_VIEWPORT, gl2ps->viewport);
@@ -4123,6 +4404,15 @@ GL2PSDLL_API GLint gl2psBeginPage(const char *title, const char *producer,
       gl2ps->viewport[i] = viewport[i];
     }
   }
+
+  if(!viewport[2] || !viewport[3]){
+    gl2psMsg(GL2PS_ERROR, "Incorrect viewport (x=%d, y=%d, width=%d, height=%d)",
+             viewport[0], viewport[1], viewport[2], viewport[3]);
+    gl2psFree(gl2ps);
+    gl2ps = NULL;
+    return GL2PS_ERROR;
+  }
+
   gl2ps->threshold[0] = nr ? 1.0F/(GLfloat)nr : 0.032F;
   gl2ps->threshold[1] = ng ? 1.0F/(GLfloat)ng : 0.017F;
   gl2ps->threshold[2] = nb ? 1.0F/(GLfloat)nb : 0.050F;
@@ -4179,12 +4469,32 @@ GL2PSDLL_API GLint gl2psBeginPage(const char *title, const char *producer,
     rewind(gl2ps->stream);
   }
 
-  gl2ps->title = (char*)gl2psMalloc((strlen(title)+1)*sizeof(char));
-  strcpy(gl2ps->title, title); 
-  gl2ps->producer = (char*)gl2psMalloc((strlen(producer)+1)*sizeof(char));
-  strcpy(gl2ps->producer, producer); 
-  gl2ps->filename = (char*)gl2psMalloc((strlen(filename)+1)*sizeof(char));
-  strcpy(gl2ps->filename, filename); 
+  if(!title){
+    gl2ps->title = (char*)gl2psMalloc(sizeof(char));
+    gl2ps->title[0] = '\0';
+  }
+  else{
+    gl2ps->title = (char*)gl2psMalloc((strlen(title)+1)*sizeof(char));
+    strcpy(gl2ps->title, title);
+  }
+    
+  if(!producer){
+    gl2ps->producer = (char*)gl2psMalloc(sizeof(char));
+    gl2ps->producer[0] = '\0';
+  }
+  else{
+    gl2ps->producer = (char*)gl2psMalloc((strlen(producer)+1)*sizeof(char));
+    strcpy(gl2ps->producer, producer);
+  }
+  
+  if(!filename){
+    gl2ps->filename = (char*)gl2psMalloc(sizeof(char));
+    gl2ps->filename[0] = '\0';
+  }
+  else{
+    gl2ps->filename = (char*)gl2psMalloc((strlen(filename)+1)*sizeof(char));
+    strcpy(gl2ps->filename, filename);
+  }
 
   switch(gl2ps->format){
   case GL2PS_TEX :
@@ -4242,6 +4552,7 @@ GL2PSDLL_API GLint gl2psEndPage(void)
   fflush(gl2ps->stream);
 
   gl2psListDelete(gl2ps->primitives);
+  gl2psFreeImagemap(gl2ps->imagemap_head);
   gl2psFree(gl2ps->colormap);
   gl2psFree(gl2ps->title);
   gl2psFree(gl2ps->producer);
@@ -4295,8 +4606,7 @@ GL2PSDLL_API GLint gl2psEndViewport(void)
 }
 
 GL2PSDLL_API GLint gl2psTextOpt(const char *str, const char *fontname, 
-                                GLshort fontsize, GLint alignment, 
-                                GL2PSrgba rgba)
+                                GLshort fontsize, GLint alignment, GLfloat angle)
 {
   GLfloat pos[4];
   GL2PSprimitive *prim;
@@ -4318,20 +4628,12 @@ GL2PSDLL_API GLint gl2psTextOpt(const char *str, const char *fontname,
   prim->verts = (GL2PSvertex*)gl2psMalloc(sizeof(GL2PSvertex));
   prim->verts[0].xyz[0] = pos[0];
   prim->verts[0].xyz[1] = pos[1];
-  prim->verts[0].xyz[2] = GL2PS_DEPTH_FACT * pos[2];
-  prim->depth = pos[2];
+  prim->verts[0].xyz[2] = pos[2];
   prim->culled = 0;
+  prim->offset = 0;
   prim->dash = 0;
   prim->width = 1;
-  if(rgba){
-    prim->verts[0].rgba[0] = rgba[0];
-    prim->verts[0].rgba[1] = rgba[1];
-    prim->verts[0].rgba[2] = rgba[2];
-    prim->verts[0].rgba[3] = rgba[3];
-  }
-  else{
-    glGetFloatv(GL_CURRENT_RASTER_COLOR, prim->verts[0].rgba);
-  }
+  glGetFloatv(GL_CURRENT_RASTER_COLOR, prim->verts[0].rgba);
   prim->data.text = (GL2PSstring*)gl2psMalloc(sizeof(GL2PSstring));
   prim->data.text->str = (char*)gl2psMalloc((strlen(str)+1)*sizeof(char));
   strcpy(prim->data.text->str, str); 
@@ -4339,6 +4641,7 @@ GL2PSDLL_API GLint gl2psTextOpt(const char *str, const char *fontname,
   strcpy(prim->data.text->fontname, fontname);
   prim->data.text->fontsize = fontsize;
   prim->data.text->alignment = alignment;
+  prim->data.text->angle = angle;
 
   gl2psListAdd(gl2ps->primitives, &prim);
 
@@ -4348,7 +4651,7 @@ GL2PSDLL_API GLint gl2psTextOpt(const char *str, const char *fontname,
 GL2PSDLL_API GLint gl2psText(const char *str, const char *fontname,
                              GLshort fontsize)
 {
-  return gl2psTextOpt(str, fontname, fontsize, GL2PS_TEXT_BL, NULL);
+  return gl2psTextOpt(str, fontname, fontsize, GL2PS_TEXT_BL, 0.0F);
 }
 
 GL2PSDLL_API GLint gl2psDrawPixels(GLsizei width, GLsizei height,
@@ -4385,9 +4688,9 @@ GL2PSDLL_API GLint gl2psDrawPixels(GLsizei width, GLsizei height,
   prim->verts = (GL2PSvertex*)gl2psMalloc(sizeof(GL2PSvertex));
   prim->verts[0].xyz[0] = pos[0] + xorig;
   prim->verts[0].xyz[1] = pos[1] + yorig;
-  prim->verts[0].xyz[2] = GL2PS_DEPTH_FACT * pos[2];
-  prim->depth = pos[2];
+  prim->verts[0].xyz[2] = pos[2];
   prim->culled = 0;
+  prim->offset = 0;
   prim->dash = 0;
   prim->width = 1;
   glGetFloatv(GL_CURRENT_RASTER_COLOR, prim->verts[0].rgba);
@@ -4430,6 +4733,31 @@ GL2PSDLL_API GLint gl2psDrawPixels(GLsizei width, GLsizei height,
   return GL2PS_SUCCESS;
 }
 
+GL2PSDLL_API GLint gl2psDrawImageMap(GLsizei width, GLsizei height,
+                                     const GLfloat position[3],
+                                     const unsigned char *imagemap){
+  int size, i;
+  int sizeoffloat = sizeof(GLfloat);
+  
+  if(!gl2ps || !imagemap) return GL2PS_UNINITIALIZED;
+
+  if((width <= 0) || (height <= 0)) return GL2PS_ERROR;
+  
+  size = height + height * ((width-1)/8);
+  glPassThrough(GL2PS_DRAW_IMAGEMAP_TOKEN);
+  glBegin(GL_POINTS);
+  glVertex3f(position[0], position[1],position[2]);
+  glEnd();
+  glPassThrough(width);
+  glPassThrough(height);
+  for(i = 0; i < size; i += sizeoffloat){
+    float *value = (float*)imagemap;
+    glPassThrough(*value);
+    imagemap += sizeoffloat;
+  }
+  return GL2PS_SUCCESS;
+}
+
 GL2PSDLL_API GLint gl2psEnable(GLint mode)
 {
   if(!gl2ps) return GL2PS_UNINITIALIZED;
diff --git a/Graphics/gl2ps.h b/Graphics/gl2ps.h
index edb7ff423c21f8eda8f2e8b1b1a7a7dd6e50e944..59f5951b955fdc5a664fc1a5cd3e002b2a8be67b 100644
--- a/Graphics/gl2ps.h
+++ b/Graphics/gl2ps.h
@@ -1,4 +1,4 @@
-/* $Id: gl2ps.h,v 1.53 2004-05-09 19:00:11 geuzaine Exp $ */
+/* $Id: gl2ps.h,v 1.54 2004-11-22 07:34:35 geuzaine Exp $ */
 /*
  * GL2PS, an OpenGL to PostScript Printing Library
  * Copyright (C) 1999-2004 Christophe Geuzaine <geuz@geuz.org>
@@ -80,7 +80,7 @@
 
 #define GL2PS_MAJOR_VERSION 1
 #define GL2PS_MINOR_VERSION 2
-#define GL2PS_PATCH_VERSION 0
+#define GL2PS_PATCH_VERSION 3
 
 #define GL2PS_VERSION (GL2PS_MAJOR_VERSION + \
                        0.01 * GL2PS_MINOR_VERSION + \
@@ -132,7 +132,11 @@
 #define GL2PS_LINE_STIPPLE        3
 #define GL2PS_BLEND               4
 
-/* Text alignment */
+/* Text alignment (o=raster position; default mode is BL):
+   +---+ +---+ +---+ +---+ +---+ +---+ +-o-+ o---+ +---o 
+   | o | o   | |   o |   | |   | |   | |   | |   | |   | 
+   +---+ +---+ +---+ +-o-+ o---+ +---o +---+ +---+ +---+ 
+    C     CL    CR    B     BL    BR    T     TL    TR */
 
 #define GL2PS_TEXT_C  1
 #define GL2PS_TEXT_CL 2
@@ -158,6 +162,7 @@
 #define GL2PS_END_BLEND                10
 #define GL2PS_SRC_BLEND                11
 #define GL2PS_DST_BLEND                12
+#define GL2PS_DRAW_IMAGEMAP_TOKEN      13
 
 typedef GLfloat GL2PSrgba[4];
 
@@ -176,6 +181,8 @@ GL2PSDLL_API GLint gl2psBeginViewport(GLint viewport[4]);
 GL2PSDLL_API GLint gl2psEndViewport(void);
 GL2PSDLL_API GLint gl2psText(const char *str, const char *fontname, 
                              GLshort fontsize);
+GL2PSDLL_API GLint gl2psTextOpt(const char *str, const char *fontname, 
+                                GLshort fontsize, GLint align, GLfloat angle);
 GL2PSDLL_API GLint gl2psDrawPixels(GLsizei width, GLsizei height,
                                    GLint xorig, GLint yorig,
                                    GLenum format, GLenum type, const void *pixels);
@@ -185,9 +192,10 @@ GL2PSDLL_API GLint gl2psPointSize(GLfloat value);
 GL2PSDLL_API GLint gl2psLineWidth(GLfloat value);
 GL2PSDLL_API GLint gl2psBlendFunc(GLenum sfactor, GLenum dfactor);
 
-/* Undocumented */
-GL2PSDLL_API GLint gl2psTextOpt(const char *str, const char *fontname, 
-                                GLshort fontsize, GLint align, GL2PSrgba color);
+/* undocumented */
+GL2PSDLL_API GLint gl2psDrawImageMap(GLsizei width, GLsizei height,
+                                     const GLfloat position[3],
+                                     const unsigned char *imagemap);
 
 #if defined(__cplusplus)
 };