--- /dev/null
+diff -Naur gl2ps-1.3.9-svn-20160620_SRC_orig/gl2ps.c gl2ps-1.3.9-svn-20160620_SRC_modif/gl2ps.c
+--- gl2ps-1.3.9-svn-20160620_SRC_orig/gl2ps.c 2016-06-13 01:01:29.000000000 +0300
++++ gl2ps-1.3.9-svn-20160620_SRC_modif/gl2ps.c 2017-04-03 12:15:38.395464392 +0300
+@@ -42,6 +42,11 @@
+ #include <time.h>
+ #include <float.h>
+
++// not defined until VC8 (VS2005)
++#if _MSC_VER && _MSC_VER < 1400 && !defined(vsnprintf)
++#define vsnprintf _vsnprintf
++#endif
++
+ #if defined(GL2PS_HAVE_ZLIB)
+ #include <zlib.h>
+ #endif
+@@ -163,6 +168,7 @@
+ GLushort pattern;
+ char boundary, offset, culled;
+ GLint factor;
++ GLint sortid; /* Used to stabilize qsort sorting */
+ GLfloat width, ofactor, ounits;
+ GL2PSvertex *verts;
+ union {
+@@ -597,6 +603,15 @@
+ qsort(list->array, list->n, list->size, fcmp);
+ }
+
++/* Must be a list of GL2PSprimitives. */
++static void gl2psListAssignSortIds(GL2PSlist *list)
++{
++ GLint i;
++ for(i = 0; i < gl2psListNbr(list); i++){
++ (*(GL2PSprimitive**)gl2psListPointer(list, i))->sortid = i;
++ }
++}
++
+ static void gl2psListAction(GL2PSlist *list, void (*action)(void *data))
+ {
+ GLint i;
+@@ -850,7 +865,8 @@
+
+ static GLint gl2psAddText(GLint type, const char *str, const char *fontname,
+ GLshort fontsize, GLint alignment, GLfloat angle,
+- GL2PSrgba color)
++ GL2PSrgba color, GLboolean setblpos,
++ GLfloat blx, GLfloat bly)
+ {
+ GLfloat pos[4];
+ GL2PSprimitive *prim;
+@@ -875,11 +891,16 @@
+ prim = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive));
+ prim->type = type;
+ prim->boundary = 0;
+- prim->numverts = 1;
+- prim->verts = (GL2PSvertex*)gl2psMalloc(sizeof(GL2PSvertex));
++ prim->numverts = setblpos ? 2 : 1;
++ prim->verts = (GL2PSvertex*)gl2psMalloc(sizeof(GL2PSvertex) * prim->numverts);
+ prim->verts[0].xyz[0] = pos[0];
+ prim->verts[0].xyz[1] = pos[1];
+ prim->verts[0].xyz[2] = pos[2];
++ if (setblpos) {
++ prim->verts[1].xyz[0] = blx;
++ prim->verts[1].xyz[1] = bly;
++ prim->verts[1].xyz[2] = 0;
++ }
+ prim->culled = 0;
+ prim->offset = 0;
+ prim->ofactor = 0.0;
+@@ -1434,7 +1455,8 @@
+ return 1;
+ }
+ else{
+- return 0;
++ /* Ensure that initial ordering is preserved when depths match. */
++ return q->sortid < w->sortid ? -1 : 1;
+ }
+ }
+
+@@ -3492,8 +3514,47 @@
+ }
+ }
+
+-static void gl2psPutPDFSpecial(GL2PSstring *text)
++/*
++ This is used for producing alligned text in PDF. (x, y) is the anchor for the
++ alligned text, (xbl, ybl) is the bottom left corner. Rotation happens
++ around (x, y).*/
++static void gl2psPutPDFTextBL(GL2PSstring *text, int cnt, GLfloat x, GLfloat y,
++ GLfloat xbl, GLfloat ybl)
+ {
++ if(text->angle == 0.0F){
++ gl2ps->streamlength += gl2psPrintf
++ ("BT\n"
++ "/F%d %d Tf\n"
++ "%f %f Td\n"
++ "(%s) Tj\n"
++ "ET\n",
++ cnt, text->fontsize, xbl, ybl, text->str);
++ }
++ else{
++ GLfloat a, ca, sa;
++ GLfloat pi = 3.141593F;
++ GLfloat i = atan2(y - ybl, x - xbl);
++ GLfloat r = sqrt((y - ybl) * (y - ybl) + (x - xbl) * (x - xbl));
++
++ a = (GLfloat)(pi * text->angle / 180.0F);
++ sa = (GLfloat)sin(a);
++ ca = (GLfloat)cos(a);
++ gl2ps->streamlength += gl2psPrintf
++ ("BT\n"
++ "/F%d %d Tf\n"
++ "%f %f %f %f %f %f Tm\n"
++ "(%s) Tj\n"
++ "ET\n",
++ cnt, text->fontsize,
++ ca, sa, -sa, ca,
++ xbl + r * (cos(i) - cos(i + a)), ybl + r * (sin(i) - sin(i+a)), text->str);
++ }
++}
++
++
++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);
+ }
+
+@@ -3689,7 +3750,7 @@
+
+ static void gl2psPDFgroupListWriteMainStream(void)
+ {
+- int i, j, lastel;
++ int i, j, lastel, count;
+ GL2PSprimitive *prim = NULL, *prev = NULL;
+ GL2PSpdfgroup *gro;
+ GL2PStriangle t;
+@@ -3697,7 +3758,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;
+@@ -3863,14 +3926,26 @@
+ for(j = 0; j <= lastel; ++j){
+ prim = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, j);
+ gl2ps->streamlength += gl2psPrintPDFFillColor(prim->verts[0].rgba);
+- gl2psPutPDFText(prim->data.text, gro->fontno, prim->verts[0].xyz[0],
+- prim->verts[0].xyz[1]);
++ if (prim->numverts == 2) {
++ gl2psPutPDFTextBL(prim->data.text, gro->fontno, prim->verts[0].xyz[0],
++ prim->verts[0].xyz[1],
++ prim->verts[1].xyz[0],
++ prim->verts[1].xyz[1]);
++ }
++ else {
++ gl2psPutPDFText(prim->data.text, gro->fontno, prim->verts[0].xyz[0],
++ prim->verts[0].xyz[1]);
++ }
+ }
+ 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;
+@@ -3883,17 +3958,39 @@
+ static int gl2psPDFgroupListWriteGStateResources(void)
+ {
+ GL2PSpdfgroup *gro;
++ GL2PSprimitive* prim;
++ float op = 1;
+ int offs = 0;
+- int i;
++ int i, j;
++ int index = 0;
++ int lastel;
+
+ offs += fprintf(gl2ps->stream,
+ "/ExtGState\n"
+ "<<\n"
+ "/GSa 7 0 R\n");
++
+ for(i = 0; i < gl2psListNbr(gl2ps->pdfgrouplist); ++i){
+ gro = (GL2PSpdfgroup*)gl2psListPointer(gl2ps->pdfgrouplist, i);
+ if(gro->gsno >= 0)
++ {
+ offs += fprintf(gl2ps->stream, "/GS%d %d 0 R\n", gro->gsno, gro->gsobjno);
++ index = gro->gsno;
++ }
++
++ lastel = gl2psListNbr(gro->ptrlist) - 1;
++ if(lastel < 0)
++ continue;
++
++ for(j = 0; j <= lastel; ++j)
++ {
++ prim = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, j);
++ if (prim->type == GL2PS_SPECIAL)
++ {
++ op = prim->verts[0].rgba[3];
++ offs += fprintf(gl2ps->stream, "/GS%d%d <<\n /CA %f\n /ca %f\n >>\n", i, j, op, op);
++ }
++ }
+ }
+ offs += fprintf(gl2ps->stream, ">>\n");
+ return offs;
+@@ -5659,6 +5756,7 @@
+ gl2psListReset(gl2ps->primitives);
+ break;
+ case GL2PS_SIMPLE_SORT :
++ gl2psListAssignSortIds(gl2ps->primitives);
+ gl2psListSort(gl2ps->primitives, gl2psCompareDepth);
+ if(gl2ps->options & GL2PS_OCCLUSION_CULL){
+ gl2psListActionInverse(gl2ps->primitives, gl2psAddInImageTree);
+@@ -5970,24 +6068,39 @@
+ GL2PSrgba color)
+ {
+ return gl2psAddText(GL2PS_TEXT, str, fontname, fontsize, alignment, angle,
+- color);
++ color, GL_FALSE, 0, 0);
++}
++
++/**
++ * This version of gl2psTextOptColor is used to go around the
++ * fact that PDF does not support text allignment. The extra parameters
++ * (blx, bly) represent the bottom left corner of the text bounding box.
++ */
++GL2PSDLL_API GLint gl2psTextOptColorBL(const char *str, const char *fontname,
++ GLshort fontsize, GLint alignment, GLfloat angle,
++ GL2PSrgba color, GLfloat blx, GLfloat bly)
++{
++ return gl2psAddText(GL2PS_TEXT, str, fontname, fontsize, alignment, angle,
++ color, GL_TRUE, blx, bly);
+ }
+
++
+ GL2PSDLL_API GLint gl2psTextOpt(const char *str, const char *fontname,
+ GLshort fontsize, GLint alignment, GLfloat angle)
+ {
+- return gl2psAddText(GL2PS_TEXT, str, fontname, fontsize, alignment, angle, NULL);
++ return gl2psAddText(GL2PS_TEXT, str, fontname, fontsize, alignment, angle, NULL,
++ GL_FALSE, 0, 0);
+ }
+
+ GL2PSDLL_API GLint gl2psText(const char *str, const char *fontname, GLshort fontsize)
+ {
+ return gl2psAddText(GL2PS_TEXT, str, fontname, fontsize, GL2PS_TEXT_BL, 0.0F,
+- NULL);
++ NULL, GL_FALSE, 0, 0);
+ }
+
+-GL2PSDLL_API GLint gl2psSpecial(GLint format, const char *str)
++GL2PSDLL_API GLint gl2psSpecial(GLint format, const char *str, GL2PSrgba rgba)
+ {
+- return gl2psAddText(GL2PS_SPECIAL, str, "", 0, format, 0.0F, NULL);
++ return gl2psAddText(GL2PS_SPECIAL, str, "", 0, format, 0.0F, rgba, GL_FALSE, 0, 0);
+ }
+
+ GL2PSDLL_API GLint gl2psDrawPixels(GLsizei width, GLsizei height,
+diff -Naur gl2ps-1.3.9-svn-20160620_SRC_orig/gl2ps.h gl2ps-1.3.9-svn-20160620_SRC_modif/gl2ps.h
+--- gl2ps-1.3.9-svn-20160620_SRC_orig/gl2ps.h 2016-01-17 02:01:36.000000000 +0300
++++ gl2ps-1.3.9-svn-20160620_SRC_modif/gl2ps.h 2017-04-03 12:37:34.712023470 +0300
+@@ -202,7 +202,10 @@
+ GL2PSDLL_API GLint gl2psTextOptColor(const char *str, const char *fontname,
+ GLshort fontsize, GLint align, GLfloat angle,
+ GL2PSrgba color);
+-GL2PSDLL_API GLint gl2psSpecial(GLint format, const char *str);
++GL2PSDLL_API GLint gl2psTextOptColorBL(const char *str, const char *fontname,
++ GLshort fontsize, GLint alignment, GLfloat angle,
++ GL2PSrgba color, GLfloat blx, GLfloat bly);
++GL2PSDLL_API GLint gl2psSpecial(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);
+diff -Naur gl2ps-1.3.9-svn-20160620_SRC_orig/gl2psTest.c gl2ps-1.3.9-svn-20160620_SRC_modif/gl2psTest.c
+--- gl2ps-1.3.9-svn-20160620_SRC_orig/gl2psTest.c 2015-10-18 01:02:00.000000000 +0300
++++ gl2ps-1.3.9-svn-20160620_SRC_modif/gl2psTest.c 2017-04-03 12:39:08.752428106 +0300
+@@ -292,8 +292,8 @@
+
+ glRasterPos2d(x, 1.15);
+ printstring(format_string, 0.);
+-
+- gl2psSpecial(GL2PS_TEX, "% This should only be printed in LaTeX output!");
++ GL2PSrgba rgba = {-1.0F, -1.0F, -1.0F, -1.0F};
++ gl2psSpecial(GL2PS_TEX, "% This should only be printed in LaTeX output!", rgba);
+ }
+
+ void cube()