Hello community,

here is the log from the commit of package gl2ps for openSUSE:Factory checked 
in at 2017-07-06 00:04:08
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/gl2ps (Old)
 and      /work/SRC/openSUSE:Factory/.gl2ps.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "gl2ps"

Thu Jul  6 00:04:08 2017 rev:11 rq:508199 version:1.4.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/gl2ps/gl2ps.changes      2015-12-24 
12:15:49.000000000 +0100
+++ /work/SRC/openSUSE:Factory/.gl2ps.new/gl2ps.changes 2017-07-06 
00:04:10.219783595 +0200
@@ -1,0 +2,11 @@
+Tue Jul  4 09:37:14 UTC 2017 - [email protected]
+
+- Update to version 1.4.0:
+  * Make it possible to add primitives directly, without parsing
+    the OpenGL feedback buffer, using gl2psAddPolyPrimitive.
+  * gl2psBeginPage now accepts a buffersize of 0.
+  * New gl2psForceRasterPos, gl2psLineCap and gl2psLineJoin.
+  * Fixed scaling of images in PDF output.
+  * Fixed bug leading to corrupted PDF output.
+
+-------------------------------------------------------------------

Old:
----
  gl2ps-1.3.9.tgz

New:
----
  gl2ps-1.4.0.tgz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ gl2ps.spec ++++++
--- /var/tmp/diff_new_pack.4Vesih/_old  2017-07-06 00:04:10.727712038 +0200
+++ /var/tmp/diff_new_pack.4Vesih/_new  2017-07-06 00:04:10.731711475 +0200
@@ -1,7 +1,7 @@
 #
 # spec file for package gl2ps
 #
-# Copyright (c) 2015 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2017 SUSE LINUX GmbH, Nuernberg, Germany.
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -18,7 +18,7 @@
 
 %define so_ver 1
 Name:           gl2ps
-Version:        1.3.9
+Version:        1.4.0
 Release:        0
 Summary:        OpenGL to PostScript Printing Library
 License:        LGPL-2.0+ or SUSE-GL2PS-2.0

++++++ gl2ps-1.3.9.tgz -> gl2ps-1.4.0.tgz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gl2ps-1.3.9-source/CMakeLists.txt 
new/gl2ps-1.4.0-source/CMakeLists.txt
--- old/gl2ps-1.3.9-source/CMakeLists.txt       2015-10-17 19:56:38.000000000 
+0200
+++ new/gl2ps-1.4.0-source/CMakeLists.txt       2017-04-04 01:09:28.000000000 
+0200
@@ -1,5 +1,5 @@
 #  GL2PS, an OpenGL to PostScript Printing Library
-#  Copyright (C) 1999-2015 C. Geuzaine
+#  Copyright (C) 1999-2017 C. Geuzaine
 # 
 #  This program is free software; you can redistribute it and/or
 #  modify it under the terms of either:
@@ -48,8 +48,8 @@
 option(ENABLE_PNG "Enable PNG support" ON)
 
 set(GL2PS_MAJOR_VERSION 1)
-set(GL2PS_MINOR_VERSION 3)
-set(GL2PS_PATCH_VERSION 9)
+set(GL2PS_MINOR_VERSION 4)
+set(GL2PS_PATCH_VERSION 0)
 set(GL2PS_EXTRA_VERSION "" CACHE STRING "GL2PS extra version string")
 
 set(GL2PS_VERSION "${GL2PS_MAJOR_VERSION}.${GL2PS_MINOR_VERSION}")
@@ -186,7 +186,7 @@
 set(CPACK_SOURCE_PACKAGE_FILE_NAME gl2ps-${GL2PS_VERSION}-source)
 set(CPACK_SOURCE_GENERATOR TGZ)
 set(CPACK_SOURCE_IGNORE_FILES "TODO.txt" "${CMAKE_BINARY_DIR}" "/CVS/"
-    "/.svn" "~$" "DS_Store$" "/tmp/" "/bin/" "/lib/")
+    "/.svn" "/.git" "~$" "DS_Store$" "/tmp/" "/bin/" "/lib/")
 if(WIN32)
   set(CPACK_GENERATOR ZIP)
 else(WIN32)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gl2ps-1.3.9-source/gl2ps.c 
new/gl2ps-1.4.0-source/gl2ps.c
--- old/gl2ps-1.3.9-source/gl2ps.c      2015-10-17 18:26:03.000000000 +0200
+++ new/gl2ps-1.4.0-source/gl2ps.c      2017-04-04 00:48:30.000000000 +0200
@@ -1,6 +1,6 @@
 /*
  * GL2PS, an OpenGL to PostScript Printing Library
- * Copyright (C) 1999-2015 C. Geuzaine
+ * Copyright (C) 1999-2017 C. Geuzaine
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of either:
@@ -65,20 +65,6 @@
 #define GL2PS_ZOFFSET_LARGE 20.0F
 #define GL2PS_ZERO(arg)     (fabs(arg) < 1.e-20)
 
-/* Primitive types */
-
-#define GL2PS_NO_TYPE          -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
-#define GL2PS_SPECIAL          10
-
 /* BSP tree primitive comparison */
 
 #define GL2PS_COINCIDENT  1
@@ -101,14 +87,16 @@
 #define GL2PS_BEGIN_STIPPLE_TOKEN  5
 #define GL2PS_END_STIPPLE_TOKEN    6
 #define GL2PS_POINT_SIZE_TOKEN     7
-#define GL2PS_LINE_WIDTH_TOKEN     8
-#define GL2PS_BEGIN_BLEND_TOKEN    9
-#define GL2PS_END_BLEND_TOKEN      10
-#define GL2PS_SRC_BLEND_TOKEN      11
-#define GL2PS_DST_BLEND_TOKEN      12
-#define GL2PS_IMAGEMAP_TOKEN       13
-#define GL2PS_DRAW_PIXELS_TOKEN    14
-#define GL2PS_TEXT_TOKEN           15
+#define GL2PS_LINE_CAP_TOKEN       8
+#define GL2PS_LINE_JOIN_TOKEN      9
+#define GL2PS_LINE_WIDTH_TOKEN     10
+#define GL2PS_BEGIN_BLEND_TOKEN    11
+#define GL2PS_END_BLEND_TOKEN      12
+#define GL2PS_SRC_BLEND_TOKEN      13
+#define GL2PS_DST_BLEND_TOKEN      14
+#define GL2PS_IMAGEMAP_TOKEN       15
+#define GL2PS_DRAW_PIXELS_TOKEN    16
+#define GL2PS_TEXT_TOKEN           17
 
 typedef enum {
   T_UNDEFINED    = -1,
@@ -119,7 +107,6 @@
   T_VAR_ALPHA    = 1<<4
 } GL2PS_TRIANGLE_PROPERTY;
 
-typedef GLfloat GL2PSxyz[3];
 typedef GLfloat GL2PSplane[4];
 
 typedef struct _GL2PSbsptree2d GL2PSbsptree2d;
@@ -143,11 +130,6 @@
 };
 
 typedef struct {
-  GL2PSxyz xyz;
-  GL2PSrgba rgba;
-} GL2PSvertex;
-
-typedef struct {
   GL2PSvertex vertex[3];
   int prop;
 } GL2PStriangle;
@@ -182,7 +164,7 @@
   GLshort type, numverts;
   GLushort pattern;
   char boundary, offset, culled;
-  GLint factor;
+  GLint factor, linecap, linejoin;
   GLfloat width, ofactor, ounits;
   GL2PSvertex *verts;
   union {
@@ -209,6 +191,7 @@
 typedef struct {
   /* General */
   GLint format, sort, options, colorsize, colormode, buffersize;
+  GLint lastlinecap, lastlinejoin;
   char *title, *producer, *filename;
   GLboolean boundary, blending;
   GLfloat *feedback, lastlinewidth;
@@ -220,6 +203,8 @@
   FILE *stream;
   GL2PScompress *compress;
   GLboolean header;
+  GL2PSvertex rasterpos;
+  GLboolean forcerasterpos;
 
   /* BSP-specific */
   GLint maxbestroot;
@@ -878,13 +863,20 @@
 
   if(gl2ps->options & GL2PS_NO_TEXT) return GL2PS_SUCCESS;
 
-  glGetBooleanv(GL_CURRENT_RASTER_POSITION_VALID, &valid);
-  if(GL_FALSE == valid) return GL2PS_SUCCESS; /* the primitive is culled */
-
-  glGetFloatv(GL_CURRENT_RASTER_POSITION, pos);
+  if (gl2ps->forcerasterpos) {
+    pos[0] = gl2ps->rasterpos.xyz[0];
+    pos[1] = gl2ps->rasterpos.xyz[1];
+    pos[2] = gl2ps->rasterpos.xyz[2];
+    pos[3] = 1.f;
+  }
+  else {
+    glGetBooleanv(GL_CURRENT_RASTER_POSITION_VALID, &valid);
+    if(GL_FALSE == valid) return GL2PS_SUCCESS; /* the primitive is culled */
+    glGetFloatv(GL_CURRENT_RASTER_POSITION, pos);
+  }
 
   prim = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive));
-  prim->type = type;
+  prim->type = (GLshort)type;
   prim->boundary = 0;
   prim->numverts = 1;
   prim->verts = (GL2PSvertex*)gl2psMalloc(sizeof(GL2PSvertex));
@@ -898,10 +890,23 @@
   prim->pattern = 0;
   prim->factor = 0;
   prim->width = 1;
-  if (color)
+  prim->linecap = 0;
+  prim->linejoin = 0;
+
+  if (color) {
     memcpy(prim->verts[0].rgba, color, 4 * sizeof(float));
-  else
-    glGetFloatv(GL_CURRENT_RASTER_COLOR, prim->verts[0].rgba);
+  }
+  else {
+    if (gl2ps->forcerasterpos) {
+      prim->verts[0].rgba[0] = gl2ps->rasterpos.rgba[0];
+      prim->verts[0].rgba[1] = gl2ps->rasterpos.rgba[1];
+      prim->verts[0].rgba[2] = gl2ps->rasterpos.rgba[2];
+      prim->verts[0].rgba[3] = gl2ps->rasterpos.rgba[3];
+    }
+    else {
+      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);
@@ -911,8 +916,16 @@
   prim->data.text->alignment = alignment;
   prim->data.text->angle = angle;
 
-  gl2psListAdd(gl2ps->auxprimitives, &prim);
-  glPassThrough(GL2PS_TEXT_TOKEN);
+  gl2ps->forcerasterpos = GL_FALSE;
+
+  /* If no OpenGL context, just add directly to primitives */
+  if (gl2ps->options & GL2PS_NO_OPENGL_CONTEXT) {
+    gl2psListAdd(gl2ps->primitives, &prim);
+  }
+  else {
+    gl2psListAdd(gl2ps->auxprimitives, &prim);
+    glPassThrough(GL2PS_TEXT_TOKEN);
+  }
 
   return GL2PS_SUCCESS;
 }
@@ -1031,6 +1044,12 @@
 
 /* Miscellaneous helper routines */
 
+static void gl2psResetLineProperties(void)
+{
+  gl2ps->lastlinewidth = 0.;
+  gl2ps->lastlinecap = gl2ps->lastlinejoin = 0;
+}
+
 static GL2PSprimitive *gl2psCopyPrimitive(GL2PSprimitive *p)
 {
   GL2PSprimitive *prim;
@@ -1052,6 +1071,8 @@
   prim->factor = p->factor;
   prim->culled = p->culled;
   prim->width = p->width;
+  prim->linecap = p->linecap;
+  prim->linejoin = p->linejoin;
   prim->verts = (GL2PSvertex*)gl2psMalloc(p->numverts*sizeof(GL2PSvertex));
   memcpy(prim->verts, p->verts, p->numverts * sizeof(GL2PSvertex));
 
@@ -1250,6 +1271,8 @@
   child->pattern = parent->pattern;
   child->factor = parent->factor;
   child->width = parent->width;
+  child->linecap = parent->linecap;
+  child->linejoin = parent->linejoin;
   child->numverts = numverts;
   child->verts = (GL2PSvertex*)gl2psMalloc(numverts * sizeof(GL2PSvertex));
 
@@ -1388,6 +1411,8 @@
   (*t1)->pattern = (*t2)->pattern = quad->pattern;
   (*t1)->factor = (*t2)->factor = quad->factor;
   (*t1)->width = (*t2)->width = quad->width;
+  (*t1)->linecap = (*t2)->linecap = quad->linecap;
+  (*t1)->linejoin = (*t2)->linejoin = quad->linejoin;
   (*t1)->verts = (GL2PSvertex*)gl2psMalloc(3 * sizeof(GL2PSvertex));
   (*t2)->verts = (GL2PSvertex*)gl2psMalloc(3 * sizeof(GL2PSvertex));
   (*t1)->verts[0] = quad->verts[0];
@@ -1929,6 +1954,8 @@
   child->pattern = parent->pattern;
   child->factor = parent->factor;
   child->width = parent->width;
+  child->linecap = parent->linecap;
+  child->linejoin = parent->linejoin;
   child->numverts = numverts;
   child->verts = (GL2PSvertex*)gl2psMalloc(numverts * sizeof(GL2PSvertex));
   for(i = 0; i < numverts; i++){
@@ -2120,6 +2147,8 @@
       b->factor = prim->factor;
       b->culled = prim->culled;
       b->width = prim->width;
+      b->linecap = prim->linecap;
+      b->linejoin = prim->linejoin;
       b->boundary = 0;
       b->numverts = 2;
       b->verts = (GL2PSvertex*)gl2psMalloc(2 * sizeof(GL2PSvertex));
@@ -2185,11 +2214,12 @@
  *
  *********************************************************************/
 
-static void gl2psAddPolyPrimitive(GLshort type, GLshort numverts,
-                                  GL2PSvertex *verts, GLint offset,
-                                  GLfloat ofactor, GLfloat ounits,
-                                  GLushort pattern, GLint factor,
-                                  GLfloat width, char boundary)
+GL2PSDLL_API void gl2psAddPolyPrimitive(GLshort type, GLshort numverts,
+                                        GL2PSvertex *verts, GLint offset,
+                                        GLfloat ofactor, GLfloat ounits,
+                                        GLushort pattern, GLint factor,
+                                        GLfloat width, GLint linecap,
+                                        GLint linejoin,char boundary)
 {
   GL2PSprimitive *prim;
 
@@ -2199,12 +2229,14 @@
   prim->verts = (GL2PSvertex*)gl2psMalloc(numverts * sizeof(GL2PSvertex));
   memcpy(prim->verts, verts, numverts * sizeof(GL2PSvertex));
   prim->boundary = boundary;
-  prim->offset = offset;
+  prim->offset = (char)offset;
   prim->ofactor = ofactor;
   prim->ounits = ounits;
   prim->pattern = pattern;
   prim->factor = factor;
   prim->width = width;
+  prim->linecap = linecap;
+  prim->linejoin = linejoin;
   prim->culled = 0;
 
   /* FIXME: here we should have an option to split stretched
@@ -2244,6 +2276,7 @@
   GLushort pattern = 0;
   GLboolean boundary;
   GLint i, sizeoffloat, count, v, vtot, offset = 0, factor = 0, auxindex = 0;
+  GLint lcap = 0, ljoin = 0;
   GLfloat lwidth = 1.0F, psize = 1.0F, ofactor, ounits;
   GLfloat *current;
   GL2PSvertex vertices[3];
@@ -2265,7 +2298,7 @@
       current += i;
       used    -= i;
       gl2psAddPolyPrimitive(GL2PS_POINT, 1, vertices, 0, 0.0, 0.0,
-                            pattern, factor, psize, 0);
+                            pattern, factor, psize, lcap, ljoin, 0);
       break;
     case GL_LINE_TOKEN :
     case GL_LINE_RESET_TOKEN :
@@ -2278,7 +2311,7 @@
       current += i;
       used    -= i;
       gl2psAddPolyPrimitive(GL2PS_LINE, 2, vertices, 0, 0.0, 0.0,
-                            pattern, factor, lwidth, 0);
+                            pattern, factor, lwidth, lcap, ljoin, 0);
       break;
     case GL_POLYGON_TOKEN :
       count = (GLint)current[1];
@@ -2302,7 +2335,8 @@
           else
             flag = 0;
           gl2psAddPolyPrimitive(GL2PS_TRIANGLE, 3, vertices, offset, ofactor,
-                                ounits, pattern, factor, 1, flag);
+                                ounits, pattern, factor, 1, lcap, ljoin,
+                                flag);
           vertices[1] = vertices[2];
         }
         else
@@ -2336,7 +2370,7 @@
         break;
       case GL2PS_BEGIN_BOUNDARY_TOKEN : boundary = GL_TRUE; break;
       case GL2PS_END_BOUNDARY_TOKEN : boundary = GL_FALSE; break;
-      case GL2PS_END_STIPPLE_TOKEN : pattern = factor = 0; break;
+      case GL2PS_END_STIPPLE_TOKEN : pattern = 0; factor = 0; break;
       case GL2PS_BEGIN_BLEND_TOKEN : gl2ps->blending = GL_TRUE; break;
       case GL2PS_END_BLEND_TOKEN : gl2ps->blending = GL_FALSE; break;
       case GL2PS_BEGIN_STIPPLE_TOKEN :
@@ -2362,6 +2396,16 @@
         used -= 2;
         psize = current[1];
         break;
+      case GL2PS_LINE_CAP_TOKEN :
+        current += 2;
+        used -= 2;
+        lcap = current[1];
+        break;
+      case GL2PS_LINE_JOIN_TOKEN :
+        current += 2;
+        used -= 2;
+        ljoin = current[1];
+        break;
       case GL2PS_LINE_WIDTH_TOKEN :
         current += 2;
         used -= 2;
@@ -2475,7 +2519,7 @@
 {
   GLuint nbhex, nbyte, nrgb, nbits;
   GLuint row, col, ibyte, icase;
-  GLfloat dr, dg, db, fgrey;
+  GLfloat dr = 0., dg = 0., db = 0., fgrey;
   unsigned char red = 0, green = 0, blue = 0, b, grey;
   GLuint width = (GLuint)im->width;
   GLuint height = (GLuint)im->height;
@@ -2757,7 +2801,6 @@
 
   gl2psPrintf("%%%%BeginProlog\n"
               "/gl2psdict 64 dict def gl2psdict begin\n"
-              "0 setlinecap 0 setlinejoin\n"
               "/tryPS3shading %s def %% set to false to force subdivision\n"
               "/rThreshold %g def %% red component subdivision threshold\n"
               "/gThreshold %g def %% green component subdivision threshold\n"
@@ -2768,7 +2811,9 @@
   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");
+              "/W  { setlinewidth } BD\n"
+              "/LC  { setlinecap } BD\n"
+              "/LJ  { setlinejoin } BD\n");
 
   gl2psPrintf("/FC { findfont exch /SH exch def SH scalefont setfont } BD\n"
               "/SW { dup stringwidth pop } BD\n"
@@ -3043,6 +3088,8 @@
     if(!gl2psSamePosition(gl2ps->lastvertex.xyz, prim->verts[0].xyz) ||
        !gl2psSameColor(gl2ps->lastrgba, prim->verts[0].rgba) ||
        gl2ps->lastlinewidth != prim->width ||
+       gl2ps->lastlinecap != prim->linecap ||
+       gl2ps->lastlinejoin != prim->linejoin ||
        gl2ps->lastpattern != prim->pattern ||
        gl2ps->lastfactor != prim->factor){
       /* End the current line if the new segment does not start where
@@ -3061,6 +3108,14 @@
       gl2ps->lastlinewidth = prim->width;
       gl2psPrintf("%g W\n", gl2ps->lastlinewidth);
     }
+    if(gl2ps->lastlinecap != prim->linecap){
+      gl2ps->lastlinecap = prim->linecap;
+      gl2psPrintf("%d LC\n", gl2ps->lastlinecap);
+    }
+    if(gl2ps->lastlinejoin != prim->linejoin){
+      gl2ps->lastlinejoin = prim->linejoin;
+      gl2psPrintf("%d LJ\n", gl2ps->lastlinejoin);
+    }
     gl2psPrintPostScriptDash(prim->pattern, prim->factor, "setdash");
     gl2psPrintPostScriptColor(prim->verts[0].rgba);
     gl2psPrintf("%g %g %s\n", prim->verts[0].xyz[0], prim->verts[0].xyz[1],
@@ -3182,6 +3237,9 @@
     gl2ps->header = GL_FALSE;
   }
 
+  gl2psResetPostScriptColor();
+  gl2psResetLineProperties();
+
   gl2psPrintf("gsave\n"
               "1.0 1.0 scale\n");
 
@@ -3369,6 +3427,8 @@
   (void) viewport;  /* not used */
   glRenderMode(GL_FEEDBACK);
 
+  gl2psResetLineProperties();
+
   if(gl2ps->header){
     gl2psPrintTeXHeader();
     gl2ps->header = GL_FALSE;
@@ -3456,6 +3516,22 @@
     return gl2psPrintf("%g w\n", lw);
 }
 
+static int gl2psPrintPDFLineCap(GLint lc)
+{
+  if(gl2ps->lastlinecap == lc)
+    return 0;
+  else
+    return gl2psPrintf("%d J\n", lc);
+}
+
+static int gl2psPrintPDFLineJoin(GLint lj)
+{
+  if(gl2ps->lastlinejoin == lj)
+    return 0;
+  else
+    return gl2psPrintf("%d j\n", lj);
+}
+
 static void gl2psPutPDFText(GL2PSstring *text, int cnt, GLfloat x, GLfloat y)
 {
   GLfloat rad, crad, srad;
@@ -3483,8 +3559,9 @@
   }
 }
 
-static void gl2psPutPDFSpecial(GL2PSstring *text)
+static void gl2psPutPDFSpecial(int prim, int sec, GL2PSstring *text)
 {
+  gl2ps->streamlength += gl2psPrintf("/GS%d%d gs\n", prim, sec);
   gl2ps->streamlength += gl2psPrintf("%s\n", text->str);
 }
 
@@ -3495,7 +3572,8 @@
      "%d 0 0 %d %f %f cm\n"
      "/Im%d Do\n"
      "Q\n",
-     (int)image->width, (int)image->height, x, y, cnt);
+     (int)(image->zoom_x * image->width), (int)(image->zoom_y * image->height),
+     x, y, cnt);
 }
 
 static void gl2psPDFstacksInit(void)
@@ -3532,6 +3610,8 @@
   GLushort lastpattern = 0;
   GLint lastfactor = 0;
   GLfloat lastwidth = 1;
+  GLint lastlinecap = 0;
+  GLint lastlinejoin = 0;
   GL2PStriangle lastt, tmpt;
   int lastTriangleWasNotSimpleWithSameColor = 0;
 
@@ -3560,6 +3640,7 @@
       break;
     case GL2PS_LINE:
       if(lasttype != p->type || lastwidth != p->width ||
+         lastlinecap != p->linecap || lastlinejoin != p->linejoin ||
          lastpattern != p->pattern || lastfactor != p->factor ||
          !gl2psSameColor(p->verts[0].rgba, lastrgba)){
         gl2psPDFgroupObjectInit(&gro);
@@ -3573,6 +3654,8 @@
       lastpattern = p->pattern;
       lastfactor = p->factor;
       lastwidth = p->width;
+      lastlinecap = p->linecap;
+      lastlinejoin = p->linejoin;
       lastrgba[0] = p->verts[0].rgba[0];
       lastrgba[1] = p->verts[0].rgba[1];
       lastrgba[2] = p->verts[0].rgba[2];
@@ -3680,7 +3763,7 @@
 
 static void gl2psPDFgroupListWriteMainStream(void)
 {
-  int i, j, lastel;
+  int i, j, lastel, count;
   GL2PSprimitive *prim = NULL, *prev = NULL;
   GL2PSpdfgroup *gro;
   GL2PStriangle t;
@@ -3688,7 +3771,9 @@
   if(!gl2ps->pdfgrouplist)
     return;
 
-  for(i = 0; i < gl2psListNbr(gl2ps->pdfgrouplist); ++i){
+  count = gl2psListNbr(gl2ps->pdfgrouplist);
+
+  for(i = 0; i < count; ++i){
     gro = (GL2PSpdfgroup*)gl2psListPointer(gl2ps->pdfgrouplist, i);
 
     lastel = gl2psListNbr(gro->ptrlist) - 1;
@@ -3717,6 +3802,8 @@
          order to get nice stippling even when the individual segments
          are smaller than the stipple */
       gl2ps->streamlength += gl2psPrintPDFLineWidth(prim->width);
+      gl2ps->streamlength += gl2psPrintPDFLineCap(prim->linecap);
+      gl2ps->streamlength += gl2psPrintPDFLineJoin(prim->linejoin);
       gl2ps->streamlength += gl2psPrintPDFStrokeColor(prim->verts[0].rgba);
       gl2ps->streamlength += gl2psPrintPostScriptDash(prim->pattern, 
prim->factor, "d");
       /* start new path */
@@ -3859,9 +3946,13 @@
       }
       break;
     case GL2PS_SPECIAL:
+      lastel = gl2psListNbr(gro->ptrlist) - 1;
+      if(lastel < 0)
+        continue;
+
       for(j = 0; j <= lastel; ++j){
         prim = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, j);
-        gl2psPutPDFSpecial(prim->data.text);
+        gl2psPutPDFSpecial(i, j, prim->data.text);
       }
     default:
       break;
@@ -3913,7 +4004,6 @@
 }
 
 /* Images & Mask Shader XObject names */
-
 static int gl2psPDFgroupListWriteXObjectResources(void)
 {
   int i;
@@ -4502,8 +4592,8 @@
                   (int)gl2ps->viewport[2], (int)gl2ps->viewport[3]);
 
   len = (childobj>0)
-    ? strlen("/TrSh sh\n") + (int)log10((double)childobj)+1
-    : strlen("/TrSh0 sh\n");
+    ? (int)strlen("/TrSh sh\n") + (int)log10((double)childobj)+1
+    : (int)strlen("/TrSh0 sh\n");
 
   offs += fprintf(gl2ps->stream,
                   "/Length %d\n"
@@ -4837,6 +4927,8 @@
 
   glRenderMode(GL_FEEDBACK);
 
+  gl2psResetLineProperties();
+
   if(gl2ps->header){
     gl2psPrintPDFHeader();
     gl2ps->header = GL_FALSE;
@@ -4978,7 +5070,7 @@
   }
 
   /* group all the primitives and disable antialiasing */
-  gl2psPrintf("<g shape-rendering=\"crispEdges\">\n");
+  gl2psPrintf("<g>\n");
 }
 
 static void gl2psPrintSVGSmoothTriangle(GL2PSxyz xyz[3], GL2PSrgba rgba[3])
@@ -4996,6 +5088,7 @@
     gl2psSVGGetColorString(rgba[0], col);
     gl2psPrintf("<polygon fill=\"%s\" ", col);
     if(rgba[0][3] < 1.0F) gl2psPrintf("fill-opacity=\"%g\" ", rgba[0][3]);
+    gl2psPrintf("shape-rendering=\"crispEdges\" ");
     gl2psPrintf("points=\"%g,%g %g,%g %g,%g\"/>\n", xyz[0][0], xyz[0][1],
                 xyz[1][0], xyz[1][1], xyz[2][0], xyz[2][1]);
   }
@@ -5121,6 +5214,7 @@
   GL2PSxyz xyz[4];
   GL2PSrgba rgba[4];
   char col[32];
+  char lcap[7], ljoin[7];
   int newline;
 
   prim = *(GL2PSprimitive**)data;
@@ -5146,6 +5240,8 @@
     if(!gl2psSamePosition(gl2ps->lastvertex.xyz, prim->verts[0].xyz) ||
        !gl2psSameColor(gl2ps->lastrgba, prim->verts[0].rgba) ||
        gl2ps->lastlinewidth != prim->width ||
+       gl2ps->lastlinecap != prim->linecap ||
+       gl2ps->lastlinejoin != prim->linejoin ||
        gl2ps->lastpattern != prim->pattern ||
        gl2ps->lastfactor != prim->factor){
       /* End the current line if the new segment does not start where
@@ -5161,12 +5257,38 @@
     gl2ps->lastvertex = prim->verts[1];
     gl2psSetLastColor(prim->verts[0].rgba);
     gl2ps->lastlinewidth = prim->width;
+    gl2ps->lastlinecap = prim->linecap;
+    gl2ps->lastlinejoin = prim->linejoin;
     gl2ps->lastpattern = prim->pattern;
     gl2ps->lastfactor = prim->factor;
     if(newline){
       gl2psSVGGetColorString(rgba[0], col);
       gl2psPrintf("<polyline fill=\"none\" stroke=\"%s\" stroke-width=\"%g\" ",
                   col, prim->width);
+      switch (prim->linecap){
+      case GL2PS_LINE_CAP_BUTT:
+        sprintf (lcap, "%s", "butt");
+        break;
+      case GL2PS_LINE_CAP_ROUND:
+        sprintf (lcap, "%s", "round");
+        break;
+      case GL2PS_LINE_CAP_SQUARE:
+        sprintf (lcap, "%s", "square");
+        break;
+      }
+      switch (prim->linejoin){
+      case GL2PS_LINE_JOIN_MITER:
+        sprintf (ljoin, "%s", "miter");
+        break;
+      case GL2PS_LINE_JOIN_ROUND:
+        sprintf (ljoin, "%s", "round");
+        break;
+      case GL2PS_LINE_JOIN_BEVEL:
+        sprintf (ljoin, "%s", "bevel");
+        break;
+      }
+      gl2psPrintf("stroke-linecap=\"%s\" stroke-linejoin=\"%s\" ",
+                  lcap, ljoin);
       if(rgba[0][3] < 1.0F) gl2psPrintf("stroke-opacity=\"%g\" ", rgba[0][3]);
       gl2psPrintSVGDash(prim->pattern, prim->factor);
       gl2psPrintf("points=\"%g,%g ", xyz[0][0], xyz[0][1]);
@@ -5193,38 +5315,38 @@
                   -prim->data.text->angle, xyz[0][0], xyz[0][1]);
     switch(prim->data.text->alignment){
     case GL2PS_TEXT_C:
-      gl2psPrintf("text-anchor=\"middle\" baseline-shift=\"%d\" ",
-                  -prim->data.text->fontsize / 2);
+      gl2psPrintf("text-anchor=\"middle\" dy=\"%d\" ",
+                  prim->data.text->fontsize / 2);
       break;
     case GL2PS_TEXT_CL:
-      gl2psPrintf("text-anchor=\"start\" baseline-shift=\"%d\" ",
-                  -prim->data.text->fontsize / 2);
+      gl2psPrintf("text-anchor=\"start\" dy=\"%d\" ",
+                  prim->data.text->fontsize / 2);
       break;
     case GL2PS_TEXT_CR:
-      gl2psPrintf("text-anchor=\"end\" baseline-shift=\"%d\" ",
-                  -prim->data.text->fontsize / 2);
+      gl2psPrintf("text-anchor=\"end\" dy=\"%d\" ",
+                  prim->data.text->fontsize / 2);
       break;
     case GL2PS_TEXT_B:
-      gl2psPrintf("text-anchor=\"middle\" baseline-shift=\"0\" ");
+      gl2psPrintf("text-anchor=\"middle\" dy=\"0\" ");
       break;
     case GL2PS_TEXT_BR:
-      gl2psPrintf("text-anchor=\"end\" baseline-shift=\"0\" ");
+      gl2psPrintf("text-anchor=\"end\" dy=\"0\" ");
       break;
     case GL2PS_TEXT_T:
-      gl2psPrintf("text-anchor=\"middle\" baseline-shift=\"%d\" ",
-                  -prim->data.text->fontsize);
+      gl2psPrintf("text-anchor=\"middle\" dy=\"%d\" ",
+                  prim->data.text->fontsize);
       break;
     case GL2PS_TEXT_TL:
-      gl2psPrintf("text-anchor=\"start\" baseline-shift=\"%d\" ",
-                  -prim->data.text->fontsize);
+      gl2psPrintf("text-anchor=\"start\" dy=\"%d\" ",
+                  prim->data.text->fontsize);
       break;
     case GL2PS_TEXT_TR:
-      gl2psPrintf("text-anchor=\"end\" baseline-shift=\"%d\" ",
-                  -prim->data.text->fontsize);
+      gl2psPrintf("text-anchor=\"end\" dy=\"%d\" ",
+                  prim->data.text->fontsize);
       break;
     case GL2PS_TEXT_BL:
     default: /* same as GL2PS_TEXT_BL */
-      gl2psPrintf("text-anchor=\"start\" baseline-shift=\"0\" ");
+      gl2psPrintf("text-anchor=\"start\" dy=\"0\" ");
       break;
     }
     if(!strcmp(prim->data.text->fontname, "Times-Roman"))
@@ -5279,6 +5401,8 @@
 
   glRenderMode(GL_FEEDBACK);
 
+  gl2psResetLineProperties();
+
   if(gl2ps->header){
     gl2psPrintSVGHeader();
     gl2ps->header = GL_FALSE;
@@ -5296,11 +5420,12 @@
       rgba[3] = 1.0F;
     }
     gl2psSVGGetColorString(rgba, col);
-    gl2psPrintf("<polygon fill=\"%s\" points=\"%d,%d %d,%d %d,%d %d,%d\"/>\n", 
col,
+    gl2psPrintf("<polygon fill=\"%s\" points=\"%d,%d %d,%d %d,%d %d,%d\" ", 
col,
                 x, gl2ps->viewport[3] - y,
                 x + w, gl2ps->viewport[3] - y,
                 x + w, gl2ps->viewport[3] - (y + h),
                 x, gl2ps->viewport[3] - (y + h));
+    gl2psPrintf("shape-rendering=\"crispEdges\"/>\n");
   }
 
   gl2psPrintf("<clipPath id=\"cp%d%d%d%d\">\n", x, y, w, h);
@@ -5443,6 +5568,34 @@
       gl2ps->lastlinewidth = prim->width;
       fprintf(gl2ps->stream, "\\pgfsetlinewidth{%fpt}\n", 
gl2ps->lastlinewidth);
     }
+    if(gl2ps->lastlinecap != prim->linecap){
+      gl2ps->lastlinecap = prim->linecap;
+      switch (prim->linecap){
+      case GL2PS_LINE_CAP_BUTT:
+        fprintf(gl2ps->stream, "\\pgfset%s\n", "buttcap");
+        break;
+      case GL2PS_LINE_CAP_ROUND:
+        fprintf(gl2ps->stream, "\\pgfset%s\n", "roundcap");
+        break;
+      case GL2PS_LINE_CAP_SQUARE:
+        fprintf(gl2ps->stream, "\\pgfset%s\n", "rectcap");
+        break;
+      }
+    }
+    if(gl2ps->lastlinejoin != prim->linejoin){
+      gl2ps->lastlinejoin = prim->linejoin;
+      switch (prim->linejoin){
+      case GL2PS_LINE_JOIN_MITER:
+        fprintf(gl2ps->stream, "\\pgfset%s\n", "miterjoin");
+        break;
+      case GL2PS_LINE_JOIN_ROUND:
+        fprintf(gl2ps->stream, "\\pgfset%s\n", "roundjoin");
+        break;
+      case GL2PS_LINE_JOIN_BEVEL:
+        fprintf(gl2ps->stream, "\\pgfset%s\n", "beveljoin");
+        break;
+      }
+    }
     gl2psPrintPGFDash(prim->pattern, prim->factor);
     fprintf(gl2ps->stream,
             "\\pgfpathmoveto{\\pgfpoint{%fpt}{%fpt}}\n"
@@ -5456,6 +5609,34 @@
       gl2ps->lastlinewidth = 0;
       fprintf(gl2ps->stream, "\\pgfsetlinewidth{0.01pt}\n");
     }
+    if(gl2ps->lastlinecap != prim->linecap){
+      gl2ps->lastlinecap = prim->linecap;
+      switch (prim->linecap){
+      case GL2PS_LINE_CAP_BUTT:
+        fprintf(gl2ps->stream, "\\pgfset%s\n", "buttcap");
+        break;
+      case GL2PS_LINE_CAP_ROUND:
+        fprintf(gl2ps->stream, "\\pgfset%s\n", "roundcap");
+        break;
+      case GL2PS_LINE_CAP_SQUARE:
+        fprintf(gl2ps->stream, "\\pgfset%s\n", "rectcap");
+        break;
+      }
+    }
+    if(gl2ps->lastlinejoin != prim->linejoin){
+      gl2ps->lastlinejoin = prim->linejoin;
+      switch (prim->linejoin){
+      case GL2PS_LINE_JOIN_MITER:
+        fprintf(gl2ps->stream, "\\pgfset%s\n", "miterjoin");
+        break;
+      case GL2PS_LINE_JOIN_ROUND:
+        fprintf(gl2ps->stream, "\\pgfset%s\n", "roundjoin");
+        break;
+      case GL2PS_LINE_JOIN_BEVEL:
+        fprintf(gl2ps->stream, "\\pgfset%s\n", "beveljoin");
+        break;
+      }
+    }
     gl2psPrintPGFColor(prim->verts[0].rgba);
     fprintf(gl2ps->stream,
             "\\pgfpathmoveto{\\pgfpoint{%fpt}{%fpt}}\n"
@@ -5513,6 +5694,8 @@
 
   glRenderMode(GL_FEEDBACK);
 
+  gl2psResetLineProperties();
+
   if(gl2ps->header){
     gl2psPrintPGFHeader();
     gl2ps->header = GL_FALSE;
@@ -5611,9 +5794,11 @@
 {
   GL2PSbsptree *root;
   GL2PSxyz eye = {0.0F, 0.0F, 100.0F * GL2PS_ZSCALE};
-  GLint used;
+  GLint used = 0;
 
-  used = glRenderMode(GL_RENDER);
+  if ((gl2ps->options & GL2PS_NO_OPENGL_CONTEXT) == GL2PS_NONE) {
+    used = glRenderMode(GL_RENDER);
+  }
 
   if(used < 0){
     gl2psMsg(GL2PS_INFO, "OpenGL feedback buffer overflow");
@@ -5681,6 +5866,34 @@
   return GL2PS_SUCCESS;
 }
 
+static GLboolean gl2psCheckOptions(GLint options, GLint colormode)
+{
+  if (options & GL2PS_NO_OPENGL_CONTEXT) {
+    if (options & GL2PS_DRAW_BACKGROUND) {
+      gl2psMsg(GL2PS_ERROR, "Options GL2PS_NO_OPENGL_CONTEXT and "
+                            "GL2PS_DRAW_BACKGROUND are incompatible.");
+      return GL_FALSE;
+    }
+    if (options & GL2PS_USE_CURRENT_VIEWPORT) {
+      gl2psMsg(GL2PS_ERROR, "Options GL2PS_NO_OPENGL_CONTEXT and "
+                            "GL2PS_USE_CURRENT_VIEWPORT are incompatible.");
+      return GL_FALSE;
+    }
+    if ((options & GL2PS_NO_BLENDING) == GL2PS_NONE) {
+      gl2psMsg(GL2PS_ERROR, "Option GL2PS_NO_OPENGL_CONTEXT requires "
+                            "option GL2PS_NO_BLENDING.");
+      return GL_FALSE;
+    }
+    if (colormode != GL_RGBA) {
+      gl2psMsg(GL2PS_ERROR, "Option GL2PS_NO_OPENGL_CONTEXT requires colormode 
"
+                            "to be GL_RGBA.");
+      return GL_FALSE;
+    }
+  }
+
+  return GL_TRUE;
+}
+
 /*********************************************************************
  *
  * Public routines
@@ -5704,6 +5917,13 @@
 
   gl2ps = (GL2PScontext*)gl2psMalloc(sizeof(GL2PScontext));
 
+  /* Validate options */
+  if (gl2psCheckOptions(options, colormode) == GL_FALSE) {
+    gl2psFree(gl2ps);
+    gl2ps = NULL;
+    return GL2PS_ERROR;
+  }
+
   if(format >= 0 && format < (GLint)(sizeof(gl2psbackends) / 
sizeof(gl2psbackends[0]))){
     gl2ps->format = format;
   }
@@ -5738,6 +5958,7 @@
   }
 
   gl2ps->header = GL_TRUE;
+  gl2ps->forcerasterpos = GL_FALSE;
   gl2ps->maxbestroot = 10;
   gl2ps->options = options;
   gl2ps->compress = NULL;
@@ -5775,6 +5996,8 @@
     gl2ps->lastrgba[i] = -1.0F;
   }
   gl2ps->lastlinewidth = -1.0F;
+  gl2ps->lastlinecap = 0;
+  gl2ps->lastlinejoin = 0;
   gl2ps->lastpattern = 0;
   gl2ps->lastfactor = 0;
   gl2ps->imagetree = NULL;
@@ -5786,14 +6009,22 @@
 
   /* get default blending mode from current OpenGL state (enabled by
      default for SVG) */
-  gl2ps->blending = (gl2ps->format == GL2PS_SVG) ? GL_TRUE : 
glIsEnabled(GL_BLEND);
-  glGetIntegerv(GL_BLEND_SRC, &gl2ps->blendfunc[0]);
-  glGetIntegerv(GL_BLEND_DST, &gl2ps->blendfunc[1]);
+  if ((gl2ps->options & GL2PS_NO_BLENDING) == GL2PS_NONE) {
+    gl2ps->blending = (gl2ps->format == GL2PS_SVG) ? GL_TRUE
+                                                   : glIsEnabled(GL_BLEND);
+    glGetIntegerv(GL_BLEND_SRC, &gl2ps->blendfunc[0]);
+    glGetIntegerv(GL_BLEND_DST, &gl2ps->blendfunc[1]);
+  }
+  else {
+    gl2ps->blending = GL_FALSE;
+  }
 
   if(gl2ps->colormode == GL_RGBA){
     gl2ps->colorsize = 0;
     gl2ps->colormap = NULL;
-    glGetFloatv(GL_COLOR_CLEAR_VALUE, gl2ps->bgcolor);
+    if ((gl2ps->options & GL2PS_NO_OPENGL_CONTEXT) == GL2PS_NONE) {
+      glGetFloatv(GL_COLOR_CLEAR_VALUE, gl2ps->bgcolor);
+    }
   }
   else if(gl2ps->colormode == GL_COLOR_INDEX){
     if(!colorsize || !colormap){
@@ -5847,9 +6078,16 @@
 
   gl2ps->primitives = gl2psListCreate(500, 500, sizeof(GL2PSprimitive*));
   gl2ps->auxprimitives = gl2psListCreate(100, 100, sizeof(GL2PSprimitive*));
-  gl2ps->feedback = (GLfloat*)gl2psMalloc(gl2ps->buffersize * sizeof(GLfloat));
-  glFeedbackBuffer(gl2ps->buffersize, GL_3D_COLOR, gl2ps->feedback);
-  glRenderMode(GL_FEEDBACK);
+
+  if ((gl2ps->options & GL2PS_NO_OPENGL_CONTEXT) == GL2PS_NONE) {
+    gl2ps->feedback = (GLfloat*)gl2psMalloc(gl2ps->buffersize * 
sizeof(GLfloat));
+    glFeedbackBuffer(gl2ps->buffersize, GL_3D_COLOR, gl2ps->feedback);
+    glRenderMode(GL_FEEDBACK);
+  }
+  else {
+    gl2ps->feedback = NULL;
+    gl2ps->buffersize = 0;
+  }
 
   return GL2PS_SUCCESS;
 }
@@ -5899,7 +6137,7 @@
   res = (gl2psbackends[gl2ps->format]->endViewport)();
 
   /* reset last used colors, line widths */
-  gl2ps->lastlinewidth = -1.0F;
+  gl2psResetLineProperties();
 
   return res;
 }
@@ -5929,6 +6167,11 @@
   return gl2psAddText(GL2PS_SPECIAL, str, "", 0, format, 0.0F, NULL);
 }
 
+GL2PSDLL_API GLint gl2psSpecialColor(GLint format, const char *str, GL2PSrgba 
rgba)
+{
+  return gl2psAddText(GL2PS_SPECIAL, str, "", 0, format, 0.0F, rgba);
+}
+
 GL2PSDLL_API GLint gl2psDrawPixels(GLsizei width, GLsizei height,
                                    GLint xorig, GLint yorig,
                                    GLenum format, GLenum type,
@@ -5952,12 +6195,22 @@
     return GL2PS_ERROR;
   }
 
-  glGetBooleanv(GL_CURRENT_RASTER_POSITION_VALID, &valid);
-  if(GL_FALSE == valid) return GL2PS_SUCCESS; /* the primitive is culled */
-
-  glGetFloatv(GL_CURRENT_RASTER_POSITION, pos);
-  glGetFloatv(GL_ZOOM_X, &zoom_x);
-  glGetFloatv(GL_ZOOM_Y, &zoom_y);
+  if (gl2ps->forcerasterpos) {
+    pos[0] = gl2ps->rasterpos.xyz[0];
+    pos[1] = gl2ps->rasterpos.xyz[1];
+    pos[2] = gl2ps->rasterpos.xyz[2];
+    pos[3] = 1.f;
+    /* Hardcode zoom factors (for now?) */
+    zoom_x = 1.f;
+    zoom_y = 1.f;
+  }
+  else {
+    glGetBooleanv(GL_CURRENT_RASTER_POSITION_VALID, &valid);
+    if(GL_FALSE == valid) return GL2PS_SUCCESS; /* the primitive is culled */
+    glGetFloatv(GL_CURRENT_RASTER_POSITION, pos);
+    glGetFloatv(GL_ZOOM_X, &zoom_x);
+    glGetFloatv(GL_ZOOM_Y, &zoom_y);
+  }
 
   prim = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive));
   prim->type = GL2PS_PIXMAP;
@@ -5974,7 +6227,15 @@
   prim->pattern = 0;
   prim->factor = 0;
   prim->width = 1;
-  glGetFloatv(GL_CURRENT_RASTER_COLOR, prim->verts[0].rgba);
+  if (gl2ps->forcerasterpos) {
+    prim->verts[0].rgba[0] = gl2ps->rasterpos.rgba[0];
+    prim->verts[0].rgba[1] = gl2ps->rasterpos.rgba[1];
+    prim->verts[0].rgba[2] = gl2ps->rasterpos.rgba[2];
+    prim->verts[0].rgba[3] = gl2ps->rasterpos.rgba[3];
+  }
+  else {
+    glGetFloatv(GL_CURRENT_RASTER_COLOR, prim->verts[0].rgba);
+  }
   prim->data.image = (GL2PSimage*)gl2psMalloc(sizeof(GL2PSimage));
   prim->data.image->width = width;
   prim->data.image->height = height;
@@ -5983,6 +6244,8 @@
   prim->data.image->format = format;
   prim->data.image->type = type;
 
+  gl2ps->forcerasterpos = GL_FALSE;
+
   switch(format){
   case GL_RGBA:
     if(gl2ps->options & GL2PS_NO_BLENDING || !gl2ps->blending){
@@ -6011,8 +6274,14 @@
     break;
   }
 
-  gl2psListAdd(gl2ps->auxprimitives, &prim);
-  glPassThrough(GL2PS_DRAW_PIXELS_TOKEN);
+  /* If no OpenGL context, just add directly to primitives */
+  if ((gl2ps->options & GL2PS_NO_OPENGL_CONTEXT) == GL2PS_NONE) {
+    gl2psListAdd(gl2ps->auxprimitives, &prim);
+    glPassThrough(GL2PS_DRAW_PIXELS_TOKEN);
+  }
+  else {
+    gl2psListAdd(gl2ps->primitives, &prim);
+  }
 
   return GL2PS_SUCCESS;
 }
@@ -6113,6 +6382,26 @@
   return GL2PS_SUCCESS;
 }
 
+GL2PSDLL_API GLint gl2psLineCap(GLint value)
+{
+  if(!gl2ps) return GL2PS_UNINITIALIZED;
+
+  glPassThrough(GL2PS_LINE_CAP_TOKEN);
+  glPassThrough(value);
+
+  return GL2PS_SUCCESS;
+}
+
+GL2PSDLL_API GLint gl2psLineJoin(GLint value)
+{
+  if(!gl2ps) return GL2PS_UNINITIALIZED;
+
+  glPassThrough(GL2PS_LINE_JOIN_TOKEN);
+  glPassThrough(value);
+
+  return GL2PS_SUCCESS;
+}
+
 GL2PSDLL_API GLint gl2psLineWidth(GLfloat value)
 {
   if(!gl2ps) return GL2PS_UNINITIALIZED;
@@ -6142,6 +6431,10 @@
 {
   if(!gl2ps) return GL2PS_UNINITIALIZED;
 
+  if(gl2psCheckOptions(options, gl2ps->colormode) == GL_FALSE) {
+    return GL2PS_ERROR;
+  }
+
   gl2ps->options = options;
 
   return GL2PS_SUCCESS;
@@ -6179,3 +6472,22 @@
 {
   return gl2ps->format;
 }
+
+GL2PSDLL_API GLint gl2psForceRasterPos(GL2PSvertex *vert)
+{
+
+  if(!gl2ps) {
+    return GL2PS_UNINITIALIZED;
+  }
+
+  gl2ps->forcerasterpos = GL_TRUE;
+  gl2ps->rasterpos.xyz[0] = vert->xyz[0];
+  gl2ps->rasterpos.xyz[1] = vert->xyz[1];
+  gl2ps->rasterpos.xyz[2] = vert->xyz[2];
+  gl2ps->rasterpos.rgba[0] = vert->rgba[0];
+  gl2ps->rasterpos.rgba[1] = vert->rgba[1];
+  gl2ps->rasterpos.rgba[2] = vert->rgba[2];
+  gl2ps->rasterpos.rgba[3] = vert->rgba[3];
+
+  return GL2PS_SUCCESS;
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gl2ps-1.3.9-source/gl2ps.h 
new/gl2ps-1.4.0-source/gl2ps.h
--- old/gl2ps-1.3.9-source/gl2ps.h      2015-10-17 18:25:24.000000000 +0200
+++ new/gl2ps-1.4.0-source/gl2ps.h      2017-04-04 00:48:26.000000000 +0200
@@ -1,6 +1,6 @@
 /*
  * GL2PS, an OpenGL to PostScript Printing Library
- * Copyright (C) 1999-2015 C. Geuzaine
+ * Copyright (C) 1999-2017 C. Geuzaine
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of either:
@@ -44,9 +44,12 @@
 #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
 #  if defined(_MSC_VER)
 #    pragma warning(disable:4115)
+#    pragma warning(disable:4127)
 #    pragma warning(disable:4996)
 #  endif
+#  define NOMINMAX
 #  include <windows.h>
+#  undef NOMINMAX
 #  if defined(GL2PSDLL)
 #    if defined(GL2PSDLL_EXPORTS)
 #      define GL2PSDLL_API __declspec(dllexport)
@@ -83,15 +86,15 @@
 /* Version number */
 
 #define GL2PS_MAJOR_VERSION 1
-#define GL2PS_MINOR_VERSION 3
-#define GL2PS_PATCH_VERSION 9
+#define GL2PS_MINOR_VERSION 4
+#define GL2PS_PATCH_VERSION 0
 #define GL2PS_EXTRA_VERSION ""
 
 #define GL2PS_VERSION (GL2PS_MAJOR_VERSION + \
                        0.01 * GL2PS_MINOR_VERSION + \
                        0.0001 * GL2PS_PATCH_VERSION)
 
-#define GL2PS_COPYRIGHT "(C) 1999-2015 C. Geuzaine"
+#define GL2PS_COPYRIGHT "(C) 1999-2017 C. Geuzaine"
 
 /* Output file formats (the values and the ordering are important!) */
 
@@ -134,6 +137,7 @@
 #define GL2PS_COMPRESS             (1<<10)
 #define GL2PS_NO_BLENDING          (1<<11)
 #define GL2PS_TIGHT_BOUNDING_BOX   (1<<12)
+#define GL2PS_NO_OPENGL_CONTEXT    (1<<13)
 
 /* Arguments for gl2psEnable/gl2psDisable */
 
@@ -142,6 +146,17 @@
 #define GL2PS_LINE_STIPPLE        3
 #define GL2PS_BLEND               4
 
+
+/* Arguments for gl2psLineCap/Join */
+
+#define GL2PS_LINE_CAP_BUTT       0
+#define GL2PS_LINE_CAP_ROUND      1
+#define GL2PS_LINE_CAP_SQUARE     2
+
+#define GL2PS_LINE_JOIN_MITER     0
+#define GL2PS_LINE_JOIN_ROUND     1
+#define GL2PS_LINE_JOIN_BEVEL     2
+
 /* Text alignment (o=raster position; default mode is BL):
    +---+ +---+ +---+ +---+ +---+ +---+ +-o-+ o---+ +---o
    | o | o   | |   o |   | |   | |   | |   | |   | |   |
@@ -159,6 +174,25 @@
 #define GL2PS_TEXT_TR 9
 
 typedef GLfloat GL2PSrgba[4];
+typedef GLfloat GL2PSxyz[3];
+
+typedef struct {
+  GL2PSxyz xyz;
+  GL2PSrgba rgba;
+} GL2PSvertex;
+
+/* Primitive types */
+#define GL2PS_NO_TYPE          -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
+#define GL2PS_SPECIAL          10
 
 #if defined(__cplusplus)
 extern "C" {
@@ -183,15 +217,27 @@
                                      GLshort fontsize, GLint align, GLfloat 
angle,
                                      GL2PSrgba color);
 GL2PSDLL_API GLint gl2psSpecial(GLint format, const char *str);
+GL2PSDLL_API GLint gl2psSpecialColor(GLint format, const char *str, GL2PSrgba 
rgba);
 GL2PSDLL_API GLint gl2psDrawPixels(GLsizei width, GLsizei height,
                                    GLint xorig, GLint yorig,
                                    GLenum format, GLenum type, const void 
*pixels);
 GL2PSDLL_API GLint gl2psEnable(GLint mode);
 GL2PSDLL_API GLint gl2psDisable(GLint mode);
 GL2PSDLL_API GLint gl2psPointSize(GLfloat value);
+GL2PSDLL_API GLint gl2psLineCap(GLint value);
+GL2PSDLL_API GLint gl2psLineJoin(GLint value);
 GL2PSDLL_API GLint gl2psLineWidth(GLfloat value);
 GL2PSDLL_API GLint gl2psBlendFunc(GLenum sfactor, GLenum dfactor);
 
+/* referenced in the documentation, but not fully documented */
+GL2PSDLL_API GLint gl2psForceRasterPos(GL2PSvertex *vert);
+GL2PSDLL_API void gl2psAddPolyPrimitive(GLshort type, GLshort numverts,
+                                        GL2PSvertex *verts, GLint offset,
+                                        GLfloat ofactor, GLfloat ounits,
+                                        GLushort pattern, GLint factor,
+                                        GLfloat width, GLint linecap,
+                                        GLint linejoin, char boundary);
+
 /* undocumented */
 GL2PSDLL_API GLint gl2psDrawImageMap(GLsizei width, GLsizei height,
                                      const GLfloat position[3],
Binary files old/gl2ps-1.3.9-source/gl2ps.pdf and 
new/gl2ps-1.4.0-source/gl2ps.pdf differ
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gl2ps-1.3.9-source/gl2ps.tex 
new/gl2ps-1.4.0-source/gl2ps.tex
--- old/gl2ps-1.3.9-source/gl2ps.tex    2015-10-17 18:46:44.000000000 +0200
+++ new/gl2ps-1.4.0-source/gl2ps.tex    2017-04-04 01:15:27.000000000 +0200
@@ -1,6 +1,6 @@
 %
 %  GL2PS, an OpenGL to PostScript Printing Library
-%  Copyright (C) 1999-2015 C. Geuzaine
+%  Copyright (C) 1999-2017 C. Geuzaine
 %
 %  This program is free software; you can redistribute it and/or
 %  modify it under the terms of either:
@@ -91,17 +91,17 @@
 </center>
 <h2>Download</h2>
 The latest stable version of GL2PS is <a
-href="http://geuz.org/gl2ps/src/gl2ps-1.3.9.tgz";>gl2ps-1.3.9.tgz</a>.  Older
+href="http://geuz.org/gl2ps/src/gl2ps-1.4.0.tgz";>gl2ps-1.4.0.tgz</a>.  Older
 versions and nightly source snapshots are available <a
-href="http://geuz.org/gl2ps/src/";>here</a>.  For read-only svn access use:
-'<code>svn co https://geuz.org/svn/gl2ps/trunk gl2ps</code>' (username:
-gl2ps, password: gl2ps).
+href="http://geuz.org/gl2ps/src/";>here</a>.  For access to the Git repository 
use:
+'<code>git clone <a href="http://gitlab.onelab.info/gl2ps/gl2ps.git";
+>http://gitlab.onelab.info/gl2ps/gl2ps.git</a></code>'.
 <p>
 For questions and discussions about GL2PS see the <a
-href="http://geuz.org/mailman/listinfo/gl2ps/";>gl2ps mailing list</a>.  If
-you think you have found a bug you can also file a report directly <a
-href="https://geuz.org/trac/gl2ps/newticket";>here</a> (username: gl2ps,
-password: gl2ps). You can also subscribe to the <a
+href="http://geuz.org/mailman/listinfo/gl2ps/";>gl2ps mailing list</a>. If you
+think you have found a bug you can also file a report directly <a
+href="http://gitlab.onelab.info/gl2ps/gl2ps/issues";>here</a>. 
+You can also subscribe to the <a
 href="http://geuz.org/mailman/listinfo/gl2ps-announce/";>gl2ps-announce</a>
 mailing list to be notified automatically when a new version of GL2PS is
 released.
@@ -149,7 +149,7 @@
 corrections, questions or suggestions should be e-mailed to the GL2PS
 mailing list \email{[email protected]}{[email protected]}.
 
-The interface consists of fifteen functions, all beginning with the
+The interface consists of seventeen functions, all beginning with the
 prefix \dd{gl2ps}. All the data structures and the symbolic constants
 peculiar to GL2PS begin with \dd{GL2PS}.
 
@@ -293,6 +293,23 @@
   program. For PDF files the compression is done ``locally'' for each
   group of primitives, in accordance with the official PDF
   specification.
+\item[\dd{GL2PS_NO_OPENGL_CONTEXT}] GL2PS will not query an OpenGL
+  context for information, nor will it create/parse a feedback
+  buffer. This is required for newer OpenGL versions that have
+  deprecated the feedback render mode. Using GL2PS in this mode
+  requires all geometry to be added manually using
+  \dd{gl2psAddPolyPrimitive} (see \url{https://open.gl/feedback} for a
+  replacement to the deprecated OpenGL feedback
+  buffers). \dd{gl2psText}, \dd{gl2psTextOpt}, \dd{gl2psDrawPixels},
+  and \dd{gl2psSpecial} are still usable, but require the use of
+  \dd{gl2psForceRasterPos} to set the raster position.
+
+  This option is incompatible with \dd{GL2PS_DRAW_BACKGROUND} and
+  \dd{GL2PS_USE_CURRENT_VIEWPORT}, and requires \dd{GL2PS_NO_BLENDING}
+  to be set. The \dd{gl2psBeginPage} \dd{colormode} must be set to
+  \dd{GL_RGBA} if this option is enabled. If these restrictions are
+  not met, a runtime error will be reported and \dd{gl2psBeginPage} /
+  \dd{gl2psSetOptions} will return \dd{GL2PS_ERROR}.
 \end{description}
 
 \item[\dd{colormode}] Specifies the color mode: \dd{GL_RGBA} or
@@ -550,7 +567,8 @@
 
 % -------------------------------------------------------------------------
 
-\subsection{\texttt{gl2psPointSize} and \texttt{gl2psLineWidth}}
+\subsection{\texttt{gl2psPointSize}, \texttt{gl2psLineWidth},
+  \texttt{gl2psLineCap} and \texttt{gl2psLineJoin}}
 \label{sec:gl2psPointSize}
 
 \subsubsection{Specification}
@@ -563,22 +581,42 @@
 GLint gl2psLineWidth( GLfloat value )
 \end{verbatim}
 
+\begin{verbatim}
+GLint gl2psLineCap( GLint value )
+\end{verbatim}
+
+\begin{verbatim}
+GLint gl2psLineJoin( GLint value )
+\end{verbatim}
+
 \subsubsection{Description and arguments}
 
-\dd{gl2psPointSize} and \dd{gl2psLineSize} emulate the standard
+\dd{gl2psPointSize} and \dd{gl2psLineWidth} emulate the standard
 \dd{glPointSize} and the \dd{glLineWidth} functions. They are necessary
 since the point sizes and line widths are not saved in the OpenGL feedback
 buffer.
 
+\dd{gl2psLineCap} and \dd{gl2psLineJoin} let you choose respectively
+the shape of the lines ending and intersections (for line
+strips). As those features are not part of OpenGL line options, the
+output will look different from the corresponding OpenGL scene.
+
+For \dd{gl2psLineCap} allowed values are \dd{GL2PS_LINE_CAP_BUTT}
+(the default), \dd{GL2PS_LINE_CAP_ROUND} and \dd{GL2PS_LINE_CAP_SQUARE}. For
+\dd{gl2psLineJoin} allowed values are \dd{GL2PS_LINE_JOIN_MITER} 
+(the default), \dd{GL2PS_LINE_JOIN_ROUND} and \dd{GL2PS_LINE_JOIN_BEVEL}.
+
 \subsubsection{Return value}
 
-\noindent\dd{gl2psPointSize} and \dd{gl2psLineWidth} return:
+\noindent\dd{gl2psPointSize}, \dd{gl2psLineWidth}, \dd{gl2psLineCap}
+and \dd{gl2psLineJoin} return: 
 \begin{description}
 \item[\dd{GL2PS_UNINITIALIZED}] if the library is not initialized;
 \item[\dd{GL2PS_ERROR}] if an error occurred;
 \item[\dd{GL2PS_SUCCESS}] otherwise.
 \end{description}
 
+
 % -------------------------------------------------------------------------
 
 \subsection{\texttt{gl2psBlendFunc}}
@@ -675,6 +713,7 @@
 \noindent\dd{gl2psSetOptions} and \dd{gl2psGetOptions} return:
 \begin{description}
 \item[\dd{GL2PS_UNINITIALIZED}] if the library is not initialized;
+\item[\dd{GL2PS_ERROR}] if an error occurs;
 \item[\dd{GL2PS_SUCCESS}] otherwise.
 \end{description}
 
@@ -899,7 +938,13 @@
 \noemail{David Lonie}{[email protected]} for VTK patches;
 %
 \noemail{Pantxo Diribarne}{[email protected]} for polygon offset
-improvement and image scaling fix for SVG output.
+improvement, image scaling fix for SVG and PDF output, PostScript viewport 
color
+bug fix, \dd{gl2psLineCap} and \dd{gl2psLineJoin};
+%
+\noemail{David Lonie}{[email protected]} for direct addition of 
promitives
+(for newer OpenGL APIs without feedback buffer);
+%
+\noemail{Dan Lipsa}{[email protected]} for bug fixes in PDF output.
 
 \section{Links}
 \label{sec:links}
@@ -1049,6 +1094,11 @@
   gl2psPrintf; added \dd{gl2psTextOptColor}; minor fixes.
 \item[1.3.9] (Oct 17, 2015) Improved \dd{GL_POLYGON_OFFSET_FILL}; fixed scaling
   of images in SVG output.
+\item[1.4.0] (Apr 4, 2017) Make it possible to add primitives directly, without
+  parsing the OpenGL feedback buffer, using \dd{gl2psAddPolyPrimitive};
+  \dd{gl2psBeginPage} now accepts a buffersize of 0; new
+  \dd{gl2psForceRasterPos}, \dd{gl2psLineCap} and \dd{gl2psLineJoin}; fixed
+  scaling of images in PDF output; fixed bug leading to corrupted PDF output.
 \end{description}
 
 \end{document}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gl2ps-1.3.9-source/gl2psTest.c 
new/gl2ps-1.4.0-source/gl2psTest.c
--- old/gl2ps-1.3.9-source/gl2psTest.c  2015-10-17 18:25:49.000000000 +0200
+++ new/gl2ps-1.4.0-source/gl2psTest.c  2017-04-04 00:48:43.000000000 +0200
@@ -1,6 +1,6 @@
 /*
  * GL2PS, an OpenGL to PostScript Printing Library
- * Copyright (C) 1999-2015 Christophe Geuzaine <[email protected]>
+ * Copyright (C) 1999-2017 Christophe Geuzaine <[email protected]>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of either:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/gl2ps-1.3.9-source/gl2psTestSimple.c 
new/gl2ps-1.4.0-source/gl2psTestSimple.c
--- old/gl2ps-1.3.9-source/gl2psTestSimple.c    2015-10-17 18:25:44.000000000 
+0200
+++ new/gl2ps-1.4.0-source/gl2psTestSimple.c    2017-04-04 00:48:48.000000000 
+0200
@@ -1,6 +1,6 @@
 /*
  * GL2PS, an OpenGL to PostScript Printing Library
- * Copyright (C) 1999-2015 Christophe Geuzaine <[email protected]>
+ * Copyright (C) 1999-2017 Christophe Geuzaine <[email protected]>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of either:
@@ -104,9 +104,40 @@
 
   glColor3f(0.1,0.1,0.1);
 
+  /* Draw 3 broken lines to show line cap an line join features (which have
+     no opengl counterpart) */
+  glLineWidth(6.);
+  gl2psLineWidth (6.);
+
+  gl2psLineCap (GL2PS_LINE_CAP_BUTT);
+  gl2psLineJoin (GL2PS_LINE_JOIN_MITER);
+  glBegin(GL_LINE_STRIP);
+  glVertex3f(-0.9, 0.8, 0);
+  glVertex3f(-0.75, 0.98, 0);
+  glVertex3f(-0.6, 0.8, 0);
+  glEnd();
+
+  gl2psLineCap (GL2PS_LINE_CAP_ROUND);
+  gl2psLineJoin (GL2PS_LINE_JOIN_ROUND);
+  glBegin(GL_LINE_STRIP);
+  glVertex3f(-0.5, 0.8, 0);
+  glVertex3f(-0.35, 0.98, 0);
+  glVertex3f(-0.2, 0.8, 0);
+  glEnd();
+
+  gl2psLineCap (GL2PS_LINE_CAP_SQUARE);
+  gl2psLineJoin (GL2PS_LINE_JOIN_BEVEL);
+  glBegin(GL_LINE_STRIP);
+  glVertex3f(0.2, 0.8, 0);
+  glVertex3f(0.35, 0.98, 0);
+  glVertex3f(0.5, 0.8, 0);
+  glEnd();
+
   /* draw a stippled line with many small segments (this tests the
      ability of gl2ps to render lines using as few strokes as
      possible) */
+  glLineWidth(1.);
+  gl2psLineWidth(1.);
   glEnable(GL_LINE_STIPPLE);
   glLineStipple(1, 0x087F);
   gl2psEnable(GL2PS_LINE_STIPPLE);


Reply via email to