diff --git a/Graphics/gl2ps.cpp b/Graphics/gl2ps.cpp index b23e4491340418514929fd077ca4ab6cc6479fa3..5c17ec0933a58c2178f78f67182ac5f9bd63778f 100644 --- a/Graphics/gl2ps.cpp +++ b/Graphics/gl2ps.cpp @@ -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 @@ typedef enum { T_VAR_ALPHA = 1<<4 } GL2PS_TRIANGLE_PROPERTY; -typedef GLfloat GL2PSxyz[3]; typedef GLfloat GL2PSplane[4]; typedef struct _GL2PSbsptree2d GL2PSbsptree2d; @@ -142,11 +129,6 @@ struct _GL2PSbsptree { GL2PSbsptree *front, *back; }; -typedef struct { - GL2PSxyz xyz; - GL2PSrgba rgba; -} GL2PSvertex; - typedef struct { GL2PSvertex vertex[3]; int prop; @@ -182,7 +164,7 @@ typedef struct { 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{ 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 @@ typedef struct { FILE *stream; GL2PScompress *compress; GLboolean header; + GL2PSvertex rasterpos; + GLboolean forcerasterpos; /* BSP-specific */ GLint maxbestroot; @@ -878,13 +863,20 @@ static GLint gl2psAddText(GLint type, const char *str, const char *fontname, 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 @@ static GLint gl2psAddText(GLint type, const char *str, const char *fontname, 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 @@ static GLint gl2psAddText(GLint type, const char *str, const char *fontname, 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 @@ static void gl2psInitTriangle(GL2PStriangle *t) /* 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 @@ static GL2PSprimitive *gl2psCopyPrimitive(GL2PSprimitive *p) 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 @@ static void gl2psCreateSplitPrimitive(GL2PSprimitive *parent, GL2PSplane plane, 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 @@ static void gl2psDivideQuad(GL2PSprimitive *quad, (*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 @@ static GL2PSprimitive *gl2psCreateSplitPrimitive2D(GL2PSprimitive *parent, 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 @@ static void gl2psAddBoundaryInList(GL2PSprimitive *prim, GL2PSlist *list) 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 gl2psBuildPolygonBoundary(GL2PSbsptree *tree) * *********************************************************************/ -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 @@ 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->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,7 +2276,8 @@ static void gl2psParseFeedbackBuffer(GLint used) GLushort pattern = 0; GLboolean boundary; GLint i, sizeoffloat, count, v, vtot, offset = 0, factor = 0, auxindex = 0; - GLfloat lwidth = 1.0F, psize = 1.0F, ofactor=1.0F, ounits=1.0F; + GLint lcap = 0, ljoin = 0; + GLfloat lwidth = 1.0F, psize = 1.0F, ofactor, ounits; GLfloat *current; GL2PSvertex vertices[3]; GL2PSprimitive *prim; @@ -2265,7 +2298,7 @@ static void gl2psParseFeedbackBuffer(GLint used) 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 @@ static void gl2psParseFeedbackBuffer(GLint used) 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 @@ static void gl2psParseFeedbackBuffer(GLint used) 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 @@ static void gl2psParseFeedbackBuffer(GLint used) 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 @@ static void gl2psParseFeedbackBuffer(GLint used) 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 @@ static void gl2psPrintPostScriptPixmap(GLfloat x, GLfloat y, GL2PSimage *im) { 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 @@ static void gl2psPrintPostScriptHeader(void) 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 @@ 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"); + "/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 @@ static void gl2psPrintPostScriptPrimitive(void *data) 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 @@ static void gl2psPrintPostScriptPrimitive(void *data) 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 @@ static void gl2psPrintPostScriptBeginViewport(GLint viewport[4]) gl2ps->header = GL_FALSE; } + gl2psResetPostScriptColor(); + gl2psResetLineProperties(); + gl2psPrintf("gsave\n" "1.0 1.0 scale\n"); @@ -3369,6 +3427,8 @@ static void gl2psPrintTeXBeginViewport(GLint viewport[4]) (void) viewport; /* not used */ glRenderMode(GL_FEEDBACK); + gl2psResetLineProperties(); + if(gl2ps->header){ gl2psPrintTeXHeader(); gl2ps->header = GL_FALSE; @@ -3456,6 +3516,22 @@ static int gl2psPrintPDFLineWidth(GLfloat lw) 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 gl2psPutPDFText(GL2PSstring *text, int cnt, GLfloat x, GLfloat y) } } -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 @@ static void gl2psPutPDFImage(GL2PSimage *image, int cnt, GLfloat x, GLfloat y) "%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 @@ static void gl2psPDFgroupListInit(void) 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 @@ static void gl2psPDFgroupListInit(void) 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 @@ static void gl2psPDFgroupListInit(void) 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 gl2psSortOutTrianglePDFgroup(GL2PSpdfgroup *gro) 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 @@ static void gl2psPDFgroupListWriteMainStream(void) 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 @@ static void gl2psPDFgroupListWriteMainStream(void) 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 @@ static void gl2psPDFgroupListWriteMainStream(void) } 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 @@ static int gl2psPDFgroupListWriteShaderResources(void) } /* Images & Mask Shader XObject names */ - static int gl2psPDFgroupListWriteXObjectResources(void) { int i; @@ -4502,8 +4592,8 @@ static int gl2psPrintPDFShaderMask(int obj, int childobj) (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 @@ static void gl2psPrintPDFBeginViewport(GLint viewport[4]) glRenderMode(GL_FEEDBACK); + gl2psResetLineProperties(); + if(gl2ps->header){ gl2psPrintPDFHeader(); gl2ps->header = GL_FALSE; @@ -4978,7 +5070,7 @@ static void gl2psPrintSVGHeader(void) } /* 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 @@ static void gl2psPrintSVGSmoothTriangle(GL2PSxyz xyz[3], GL2PSrgba rgba[3]) 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 @@ static void gl2psPrintSVGPrimitive(void *data) GL2PSxyz xyz[4]; GL2PSrgba rgba[4]; char col[32]; + char lcap[7], ljoin[7]; int newline; prim = *(GL2PSprimitive**)data; @@ -5146,6 +5240,8 @@ static void gl2psPrintSVGPrimitive(void *data) 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 @@ static void gl2psPrintSVGPrimitive(void *data) 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 @@ static void gl2psPrintSVGPrimitive(void *data) -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 @@ static void gl2psPrintSVGBeginViewport(GLint viewport[4]) glRenderMode(GL_FEEDBACK); + gl2psResetLineProperties(); + if(gl2ps->header){ gl2psPrintSVGHeader(); gl2ps->header = GL_FALSE; @@ -5296,11 +5420,12 @@ static void gl2psPrintSVGBeginViewport(GLint viewport[4]) 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 @@ static void gl2psPrintPGFPrimitive(void *data) 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 @@ static void gl2psPrintPGFPrimitive(void *data) 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 @@ static void gl2psPrintPGFBeginViewport(GLint viewport[4]) glRenderMode(GL_FEEDBACK); + gl2psResetLineProperties(); + if(gl2ps->header){ gl2psPrintPGFHeader(); gl2ps->header = GL_FALSE; @@ -5611,9 +5794,11 @@ static GLint gl2psPrintPrimitives(void) { 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 @@ static GLint gl2psPrintPrimitives(void) 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 @@ GL2PSDLL_API GLint gl2psBeginPage(const char *title, const char *producer, 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 @@ GL2PSDLL_API GLint gl2psBeginPage(const char *title, const char *producer, } gl2ps->header = GL_TRUE; + gl2ps->forcerasterpos = GL_FALSE; gl2ps->maxbestroot = 10; gl2ps->options = options; gl2ps->compress = NULL; @@ -5775,6 +5996,8 @@ GL2PSDLL_API GLint gl2psBeginPage(const char *title, const char *producer, 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 @@ GL2PSDLL_API GLint gl2psBeginPage(const char *title, const char *producer, /* 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 @@ GL2PSDLL_API GLint gl2psBeginPage(const char *title, const char *producer, 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 @@ GL2PSDLL_API GLint gl2psEndViewport(void) res = (gl2psbackends[gl2ps->format]->endViewport)(); /* reset last used colors, line widths */ - gl2ps->lastlinewidth = -1.0F; + gl2psResetLineProperties(); return res; } @@ -5929,6 +6167,11 @@ GL2PSDLL_API GLint gl2psSpecial(GLint format, const char *str) 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 @@ GL2PSDLL_API GLint gl2psDrawPixels(GLsizei width, GLsizei height, 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 @@ GL2PSDLL_API GLint gl2psDrawPixels(GLsizei width, GLsizei height, 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 @@ GL2PSDLL_API GLint gl2psDrawPixels(GLsizei width, GLsizei height, 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 @@ GL2PSDLL_API GLint gl2psDrawPixels(GLsizei width, GLsizei height, 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 @@ GL2PSDLL_API GLint gl2psPointSize(GLfloat value) 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 @@ GL2PSDLL_API GLint gl2psSetOptions(GLint options) { 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 @@ GL2PSDLL_API GLint gl2psGetFileFormat() { 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 --git a/Graphics/gl2ps.h b/Graphics/gl2ps.h index 2433465bb9910a9a9eebbbefc389ac4daff87b9f..80edaf87f732f105fcdb51234ba9c37231a0b09b 100644 --- a/Graphics/gl2ps.h +++ b/Graphics/gl2ps.h @@ -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: @@ -45,9 +45,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) @@ -84,15 +87,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!) */ @@ -135,6 +138,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 */ @@ -143,6 +147,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 | | | | | | | | | | | | @@ -160,6 +175,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" { @@ -184,15 +218,27 @@ 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 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],