diff --git a/Graphics/gl2ps.cpp b/Graphics/gl2ps.cpp index bab87a154bf9bf6466543914cc3cfb5e38028136..9953b9a01136196bfd6e1e6f722e0df0993964c1 100644 --- a/Graphics/gl2ps.cpp +++ b/Graphics/gl2ps.cpp @@ -1,4 +1,4 @@ -/* $Id: gl2ps.cpp,v 1.91 2004-11-22 18:00:30 geuzaine Exp $ */ +/* $Id: gl2ps.cpp,v 1.92 2004-12-21 03:07:00 geuzaine Exp $ */ /* * GL2PS, an OpenGL to PostScript Printing Library * Copyright (C) 1999-2004 Christophe Geuzaine <geuz@geuz.org> @@ -49,12 +49,14 @@ * Please report all bugs and problems to <gl2ps@geuz.org>. */ +#include "gl2ps.h" + +#include <math.h> #include <string.h> #include <sys/types.h> #include <stdarg.h> #include <time.h> #include <float.h> -#include "gl2ps.h" /********************************************************************* * @@ -97,6 +99,22 @@ #define GL2PS_POINT_INFRONT 1 #define GL2PS_POINT_BACK 2 +/* Pass through options */ + +#define GL2PS_BEGIN_POLYGON_OFFSET_FILL 1 +#define GL2PS_END_POLYGON_OFFSET_FILL 2 +#define GL2PS_BEGIN_POLYGON_BOUNDARY 3 +#define GL2PS_END_POLYGON_BOUNDARY 4 +#define GL2PS_BEGIN_LINE_STIPPLE 5 +#define GL2PS_END_LINE_STIPPLE 6 +#define GL2PS_SET_POINT_SIZE 7 +#define GL2PS_SET_LINE_WIDTH 8 +#define GL2PS_BEGIN_BLEND 9 +#define GL2PS_END_BLEND 10 +#define GL2PS_SRC_BLEND 11 +#define GL2PS_DST_BLEND 12 +#define GL2PS_DRAW_IMAGEMAP_TOKEN 13 + typedef enum { T_UNDEFINED = -1, T_CONST_COLOR = 1, @@ -164,7 +182,9 @@ struct _GL2PSimagemap { typedef struct { GLshort type, numverts; - char boundary, offset, dash, culled; + GLushort pattern; + char boundary, offset, culled; + GLint factor; GLfloat width; GL2PSvertex *verts; union { @@ -194,8 +214,9 @@ typedef struct { char *title, *producer, *filename; GLboolean boundary, blending; GLfloat *feedback, offset[2], lastlinewidth; - GLint viewport[4], blendfunc[2]; + GLint viewport[4], blendfunc[2], lastfactor; GL2PSrgba *colormap, lastrgba, threshold; + GLushort lastpattern; GL2PSlist *primitives; FILE *stream; GL2PScompress *compress; @@ -634,7 +655,8 @@ static GL2PSprimitive *gl2psCopyPrimitive(GL2PSprimitive* p) prim->numverts = p->numverts; prim->boundary = p->boundary; prim->offset = p->offset; - prim->dash = p->dash; + prim->pattern = p->pattern; + prim->factor = p->factor; prim->culled = p->culled; prim->width = p->width; prim->verts = (GL2PSvertex*)gl2psMalloc(p->numverts*sizeof(GL2PSvertex)); @@ -880,7 +902,8 @@ static void gl2psCreateSplitPrimitive(GL2PSprimitive *parent, GL2PSplane plane, child->boundary = 0; /* not done! */ child->culled = parent->culled; child->offset = parent->offset; - child->dash = parent->dash; + child->pattern = parent->pattern; + child->factor = parent->factor; child->width = parent->width; child->numverts = numverts; child->verts = (GL2PSvertex*)gl2psMalloc(numverts * sizeof(GL2PSvertex)); @@ -1015,7 +1038,8 @@ static void gl2psDivideQuad(GL2PSprimitive *quad, (*t1)->numverts = (*t2)->numverts = 3; (*t1)->culled = (*t2)->culled = quad->culled; (*t1)->offset = (*t2)->offset = quad->offset; - (*t1)->dash = (*t2)->dash = quad->dash; + (*t1)->pattern = (*t2)->pattern = quad->pattern; + (*t1)->factor = (*t2)->factor = quad->factor; (*t1)->width = (*t2)->width = quad->width; (*t1)->verts = (GL2PSvertex*)gl2psMalloc(3 * sizeof(GL2PSvertex)); (*t2)->verts = (GL2PSvertex*)gl2psMalloc(3 * sizeof(GL2PSvertex)); @@ -1320,32 +1344,32 @@ static void gl2psRescaleAndOffset() if((gl2ps->options & GL2PS_SIMPLE_LINE_OFFSET) && (prim->type == GL2PS_LINE)){ if(gl2ps->sort == GL2PS_SIMPLE_SORT){ - prim->verts[0].xyz[2] -= GL2PS_ZOFFSET_LARGE; - prim->verts[1].xyz[2] -= GL2PS_ZOFFSET_LARGE; + prim->verts[0].xyz[2] -= GL2PS_ZOFFSET_LARGE; + prim->verts[1].xyz[2] -= GL2PS_ZOFFSET_LARGE; } else{ - prim->verts[0].xyz[2] -= GL2PS_ZOFFSET; - prim->verts[1].xyz[2] -= GL2PS_ZOFFSET; + prim->verts[0].xyz[2] -= GL2PS_ZOFFSET; + prim->verts[1].xyz[2] -= GL2PS_ZOFFSET; } } else if(prim->offset && (prim->type == GL2PS_TRIANGLE)){ factor = gl2ps->offset[0]; units = gl2ps->offset[1]; area = - (prim->verts[1].xyz[0] - prim->verts[0].xyz[0]) * - (prim->verts[2].xyz[1] - prim->verts[1].xyz[1]) - - (prim->verts[2].xyz[0] - prim->verts[1].xyz[0]) * - (prim->verts[1].xyz[1] - prim->verts[0].xyz[1]); + (prim->verts[1].xyz[0] - prim->verts[0].xyz[0]) * + (prim->verts[2].xyz[1] - prim->verts[1].xyz[1]) - + (prim->verts[2].xyz[0] - prim->verts[1].xyz[0]) * + (prim->verts[1].xyz[1] - prim->verts[0].xyz[1]); dZdX = - (prim->verts[2].xyz[1] - prim->verts[1].xyz[1]) * - (prim->verts[1].xyz[2] - prim->verts[0].xyz[2]) - - (prim->verts[1].xyz[1] - prim->verts[0].xyz[1]) * - (prim->verts[2].xyz[2] - prim->verts[1].xyz[2]) / area; + (prim->verts[2].xyz[1] - prim->verts[1].xyz[1]) * + (prim->verts[1].xyz[2] - prim->verts[0].xyz[2]) - + (prim->verts[1].xyz[1] - prim->verts[0].xyz[1]) * + (prim->verts[2].xyz[2] - prim->verts[1].xyz[2]) / area; dZdY = - (prim->verts[1].xyz[0] - prim->verts[0].xyz[0]) * - (prim->verts[2].xyz[2] - prim->verts[1].xyz[2]) - - (prim->verts[2].xyz[0] - prim->verts[1].xyz[0]) * - (prim->verts[1].xyz[2] - prim->verts[0].xyz[2]) / area; + (prim->verts[1].xyz[0] - prim->verts[0].xyz[0]) * + (prim->verts[2].xyz[2] - prim->verts[1].xyz[2]) - + (prim->verts[2].xyz[0] - prim->verts[1].xyz[0]) * + (prim->verts[1].xyz[2] - prim->verts[0].xyz[2]) / area; maxdZ = (GLfloat)sqrt(dZdX*dZdX + dZdY*dZdY); dZ = factor * maxdZ + units; prim->verts[0].xyz[2] += dZ; @@ -1540,7 +1564,8 @@ static GL2PSprimitive *gl2psCreateSplitPrimitive2D(GL2PSprimitive *parent, child->boundary = 0; /* not done! */ child->culled = parent->culled; child->offset = parent->offset; - child->dash = parent->dash; + child->pattern = parent->pattern; + child->factor = parent->factor; child->width = parent->width; child->numverts = numverts; child->verts = (GL2PSvertex*)gl2psMalloc(numverts * sizeof(GL2PSvertex)); @@ -1727,7 +1752,8 @@ static void gl2psAddBoundaryInList(GL2PSprimitive *prim, GL2PSlist *list) b = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive)); b->type = GL2PS_LINE; b->offset = prim->offset; - b->dash = prim->dash; + b->pattern = prim->pattern; + b->factor = prim->factor; b->culled = prim->culled; b->width = prim->width; b->boundary = 0; @@ -1797,8 +1823,8 @@ static void gl2psBuildPolygonBoundary(GL2PSbsptree *tree) static void gl2psAddPolyPrimitive(GLshort type, GLshort numverts, GL2PSvertex *verts, GLint offset, - char dash, GLfloat width, - char boundary) + GLushort pattern, GLint factor, + GLfloat width, char boundary) { GL2PSprimitive *prim; @@ -1809,7 +1835,8 @@ static void gl2psAddPolyPrimitive(GLshort type, GLshort numverts, memcpy(prim->verts, verts, numverts * sizeof(GL2PSvertex)); prim->boundary = boundary; prim->offset = offset; - prim->dash = dash; + prim->pattern = pattern; + prim->factor = factor; prim->width = width; prim->culled = 0; gl2psListAdd(gl2ps->primitives, &prim); @@ -1842,9 +1869,10 @@ static GLint gl2psGetVertex(GL2PSvertex *v, GLfloat *p) static void gl2psParseFeedbackBuffer(GLint used) { - char flag, dash = 0; + char flag; + GLushort pattern = 0; GLboolean boundary; - GLint i, sizeoffloat, count, v, vtot, offset = 0; + GLint i, sizeoffloat, count, v, vtot, offset = 0, factor = 0; GLfloat lwidth = 1.0F, psize = 1.0F; GLfloat *current; GL2PSvertex vertices[3]; @@ -1865,7 +1893,8 @@ static void gl2psParseFeedbackBuffer(GLint used) i = gl2psGetVertex(&vertices[0], current); current += i; used -= i; - gl2psAddPolyPrimitive(GL2PS_POINT, 1, vertices, 0, dash, psize, 0); + gl2psAddPolyPrimitive(GL2PS_POINT, 1, vertices, 0, + pattern, factor, psize, 0); break; case GL_LINE_TOKEN : case GL_LINE_RESET_TOKEN : @@ -1877,7 +1906,8 @@ static void gl2psParseFeedbackBuffer(GLint used) i = gl2psGetVertex(&vertices[1], current); current += i; used -= i; - gl2psAddPolyPrimitive(GL2PS_LINE, 2, vertices, 0, dash, lwidth, 0); + gl2psAddPolyPrimitive(GL2PS_LINE, 2, vertices, 0, + pattern, factor, lwidth, 0); break; case GL_POLYGON_TOKEN : count = (GLint)current[1]; @@ -1900,8 +1930,8 @@ static void gl2psParseFeedbackBuffer(GLint used) } else flag = 0; - gl2psAddPolyPrimitive(GL2PS_TRIANGLE, 3, vertices, - offset, dash, 1, flag); + gl2psAddPolyPrimitive(GL2PS_TRIANGLE, 3, vertices, offset, + pattern, factor, 1, flag); vertices[1] = vertices[2]; } else @@ -1923,10 +1953,17 @@ static void gl2psParseFeedbackBuffer(GLint used) case GL2PS_END_POLYGON_OFFSET_FILL : offset = 0; break; case GL2PS_BEGIN_POLYGON_BOUNDARY : boundary = GL_TRUE; break; case GL2PS_END_POLYGON_BOUNDARY : boundary = GL_FALSE; break; - case GL2PS_BEGIN_LINE_STIPPLE : dash = 4; break; - case GL2PS_END_LINE_STIPPLE : dash = 0; break; + case GL2PS_END_LINE_STIPPLE : pattern = factor = 0; break; case GL2PS_BEGIN_BLEND : gl2ps->blending = GL_TRUE; break; case GL2PS_END_BLEND : gl2ps->blending = GL_FALSE; break; + case GL2PS_BEGIN_LINE_STIPPLE : + current += 2; + used -= 2; + pattern = (GLushort)current[1]; + current += 2; + used -= 2; + factor = (GLint)current[1]; + break; case GL2PS_SRC_BLEND : current += 2; used -= 2; @@ -1955,7 +1992,8 @@ static void gl2psParseFeedbackBuffer(GLint used) prim->verts = (GL2PSvertex *)gl2psMalloc(4 * sizeof(GL2PSvertex)); prim->culled = 0; prim->offset = 0; - prim->dash = 0; + prim->pattern = 0; + prim->factor = 0; prim->width = 1; node = (GL2PSimagemap*)gl2psMalloc(sizeof(GL2PSimagemap)); @@ -2543,6 +2581,50 @@ static void gl2psResetPostScriptColor(void) gl2ps->lastrgba[0] = gl2ps->lastrgba[1] = gl2ps->lastrgba[2] = -1.; } +static int gl2psPrintDash(GLushort pattern, GLint factor, char *str) +{ + int len = 0, i, n, on[5] = {0, 0, 0, 0, 0}, off[5] = {0, 0, 0, 0, 0}; + char tmp[16]; + + if(pattern == gl2ps->lastpattern && factor == gl2ps->lastfactor) + return 0; + + gl2ps->lastpattern = pattern; + gl2ps->lastfactor = factor; + + if(!pattern || !factor){ + /* solid line */ + len += gl2psPrintf("[] 0 %s\n", str); + } + else{ + /* extract the 16 bits from the stipple pattern */ + for(n = 15; n >= 0; n--){ + tmp[n] = (char)(pattern & 0x01); + pattern >>= 1; + } + /* compute the on/off pixel sequence (since the PostScript + specification allows for at most 11 elements in the on/off + array, we limit ourselves to 5 couples of on/off states) */ + n = 0; + for(i = 0; i < 5; i++){ + while(n < 16 && !tmp[n]){ off[i]++; n++; } + while(n < 16 && tmp[n]){ on[i]++; n++; } + if(n >= 15) break; + } + /* print the on/off array from right to left, starting with off + pixels (the longest possible array is: [on4 off4 on3 off3 on2 + off2 on1 off1 on0 off0]) */ + len += gl2psPrintf("["); + for(n = i; n >= 0; n--){ + len += gl2psPrintf("%d %d", factor * on[n], factor * off[n]); + if(n) len += gl2psPrintf(" "); + } + len += gl2psPrintf("] 0 %s\n", str); + } + + return len; +} + static void gl2psPrintPostScriptPrimitive(void *data) { GL2PSprimitive *prim; @@ -2613,9 +2695,7 @@ static void gl2psPrintPostScriptPrimitive(void *data) gl2ps->lastlinewidth = prim->width; gl2psPrintf("%g W\n", gl2ps->lastlinewidth); } - if(prim->dash){ - gl2psPrintf("[%d] 0 setdash\n", prim->dash); - } + gl2psPrintDash(prim->pattern, prim->factor, "setdash"); if(!gl2psVertsSameColor(prim)){ gl2psResetPostScriptColor(); gl2psPrintf("%g %g %g %g %g %g %g %g %g %g SL\n", @@ -2631,9 +2711,6 @@ static void gl2psPrintPostScriptPrimitive(void *data) prim->verts[1].xyz[0], prim->verts[1].xyz[1], prim->verts[0].xyz[0], prim->verts[0].xyz[1]); } - if(prim->dash){ - gl2psPrintf("[] 0 setdash\n"); - } break; case GL2PS_TRIANGLE : if(!gl2psVertsSameColor(prim)){ @@ -2964,7 +3041,8 @@ static void gl2psPDFgroupListInit(void) GL2PSpdfgroup gro; int lasttype = GL2PS_NOTYPE; GL2PSrgba lastrgba; - char lastdash = 0; + GLushort lastpattern = 0; + GLint lastfactor = 0; GLfloat lastwidth = 1; GL2PStriangle tmpt, lastt; int lastTriangleWasNotSimpleWithSameColor = 0; @@ -2992,7 +3070,8 @@ static void gl2psPDFgroupListInit(void) gl2psListAdd(gl2ps->pdfgrouplist, &gro); break; case GL2PS_LINE: - if(lasttype != p->type || lastwidth != p->width || lastdash != p->dash || + if(lasttype != p->type || lastwidth != p->width || + lastpattern != p->pattern || lastfactor != p->factor || !gl2psSameColor(p->verts[0].rgba, lastrgba)){ gl2psPDFgroupObjectInit(&gro); gro.ptrlist = gl2psListCreate(1, 2, sizeof(GL2PSprimitive*)); @@ -3002,7 +3081,8 @@ static void gl2psPDFgroupListInit(void) else{ gl2psListAdd(gro.ptrlist, &p); } - lastdash = p->dash; + lastpattern = p->pattern; + lastfactor = p->factor; lastwidth = p->width; lastrgba[0] = p->verts[0].rgba[0]; lastrgba[1] = p->verts[0].rgba[1]; @@ -3141,12 +3221,7 @@ static void gl2psPDFgroupListWriteMainStream(void) case GL2PS_LINE: gl2ps->streamlength += gl2psPrintPDFLineWidth(prim->width); gl2ps->streamlength += gl2psPrintPDFStrokeColor(prim->verts[0].rgba); - if(prim->dash){ - gl2ps->streamlength += gl2psPrintf("[%d] 0 d\n", prim->dash); - } - else{ - gl2ps->streamlength += gl2psPrintf("[] 0 d\n"); - } + gl2ps->streamlength += gl2psPrintDash(prim->pattern, prim->factor, "d"); for(j = 0; j <= lastel; ++j){ prim = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, j); gl2ps->streamlength += @@ -4423,6 +4498,8 @@ GL2PSDLL_API GLint gl2psBeginPage(const char *title, const char *producer, gl2ps->lastrgba[i] = -1.0F; } gl2ps->lastlinewidth = -1.0F; + gl2ps->lastpattern = 0; + gl2ps->lastfactor = 0; gl2ps->imagetree = NULL; gl2ps->primitivetoadd = NULL; gl2ps->zerosurfacearea = GL_FALSE; @@ -4632,7 +4709,8 @@ GL2PSDLL_API GLint gl2psTextOpt(const char *str, const char *fontname, prim->verts[0].xyz[2] = pos[2]; prim->culled = 0; prim->offset = 0; - prim->dash = 0; + prim->pattern = 0; + prim->factor = 0; prim->width = 1; glGetFloatv(GL_CURRENT_RASTER_COLOR, prim->verts[0].rgba); prim->data.text = (GL2PSstring*)gl2psMalloc(sizeof(GL2PSstring)); @@ -4692,7 +4770,8 @@ GL2PSDLL_API GLint gl2psDrawPixels(GLsizei width, GLsizei height, prim->verts[0].xyz[2] = pos[2]; prim->culled = 0; prim->offset = 0; - prim->dash = 0; + prim->pattern = 0; + prim->factor = 0; prim->width = 1; glGetFloatv(GL_CURRENT_RASTER_COLOR, prim->verts[0].rgba); prim->data.image = (GL2PSimage*)gl2psMalloc(sizeof(GL2PSimage)); @@ -4761,6 +4840,8 @@ GL2PSDLL_API GLint gl2psDrawImageMap(GLsizei width, GLsizei height, GL2PSDLL_API GLint gl2psEnable(GLint mode) { + GLint tmp; + if(!gl2ps) return GL2PS_UNINITIALIZED; switch(mode){ @@ -4774,6 +4855,10 @@ GL2PSDLL_API GLint gl2psEnable(GLint mode) break; case GL2PS_LINE_STIPPLE : glPassThrough(GL2PS_BEGIN_LINE_STIPPLE); + glGetIntegerv(GL_LINE_STIPPLE_PATTERN, &tmp); + glPassThrough((GLfloat)tmp); + glGetIntegerv(GL_LINE_STIPPLE_REPEAT, &tmp); + glPassThrough((GLfloat)tmp); break; case GL2PS_BLEND : glPassThrough(GL2PS_BEGIN_BLEND); diff --git a/Graphics/gl2ps.h b/Graphics/gl2ps.h index 59f5951b955fdc5a664fc1a5cd3e002b2a8be67b..63962786e18b587e0f1bdce66169bf0b7a66cff3 100644 --- a/Graphics/gl2ps.h +++ b/Graphics/gl2ps.h @@ -1,4 +1,4 @@ -/* $Id: gl2ps.h,v 1.54 2004-11-22 07:34:35 geuzaine Exp $ */ +/* $Id: gl2ps.h,v 1.55 2004-12-21 03:07:00 geuzaine Exp $ */ /* * GL2PS, an OpenGL to PostScript Printing Library * Copyright (C) 1999-2004 Christophe Geuzaine <geuz@geuz.org> @@ -37,14 +37,11 @@ #include <stdio.h> #include <stdlib.h> -#include <math.h> -/* To generate a Windows dll, you should define GL2PSDLL at compile - time */ +/* Define GL2PSDLL at compile time to build a Windows dll */ #if defined (WIN32) || defined(_WIN32) -/* Shut up warning due to bad windows header file */ -# if defined(_MSC_VER) +# if defined(_MSC_VER) # pragma warning(disable:4115) # endif # include <windows.h> @@ -148,22 +145,6 @@ #define GL2PS_TEXT_TL 8 #define GL2PS_TEXT_TR 9 -/* Pass through options */ - -#define GL2PS_BEGIN_POLYGON_OFFSET_FILL 1 -#define GL2PS_END_POLYGON_OFFSET_FILL 2 -#define GL2PS_BEGIN_POLYGON_BOUNDARY 3 -#define GL2PS_END_POLYGON_BOUNDARY 4 -#define GL2PS_BEGIN_LINE_STIPPLE 5 -#define GL2PS_END_LINE_STIPPLE 6 -#define GL2PS_SET_POINT_SIZE 7 -#define GL2PS_SET_LINE_WIDTH 8 -#define GL2PS_BEGIN_BLEND 9 -#define GL2PS_END_BLEND 10 -#define GL2PS_SRC_BLEND 11 -#define GL2PS_DST_BLEND 12 -#define GL2PS_DRAW_IMAGEMAP_TOKEN 13 - typedef GLfloat GL2PSrgba[4]; #if defined(__cplusplus) @@ -198,7 +179,7 @@ GL2PSDLL_API GLint gl2psDrawImageMap(GLsizei width, GLsizei height, const unsigned char *imagemap); #if defined(__cplusplus) -}; +} #endif #endif /* __GL2PS_H__ */