From 7e95e72b693cf55d004bd152bb296eb4e49d2fcb Mon Sep 17 00:00:00 2001 From: Christophe Geuzaine <cgeuzaine@ulg.ac.be> Date: Fri, 7 Mar 2003 18:53:21 +0000 Subject: [PATCH] Upgrade to latest gl2ps version --- Graphics/CreateFile.cpp | 14 +- Graphics/gl2ps.cpp | 679 +++++++++++++++++++++++++++++++--------- Graphics/gl2ps.h | 54 ++-- 3 files changed, 570 insertions(+), 177 deletions(-) diff --git a/Graphics/CreateFile.cpp b/Graphics/CreateFile.cpp index 2df138f8f3..df5dae1c0d 100644 --- a/Graphics/CreateFile.cpp +++ b/Graphics/CreateFile.cpp @@ -1,4 +1,4 @@ -// $Id: CreateFile.cpp,v 1.39 2003-03-02 05:31:45 geuzaine Exp $ +// $Id: CreateFile.cpp,v 1.40 2003-03-07 18:53:21 geuzaine Exp $ // // Copyright (C) 1997 - 2003 C. Geuzaine, J.-F. Remacle // @@ -216,11 +216,11 @@ void CreateOutputFile(char *name, int format) size3d = 0; res = GL2PS_OVERFLOW; - while(res == GL2PS_OVERFLOW) { size3d += 2048 * 2048; - gl2psBeginPage(CTX.base_filename, "Gmsh", psformat, pssort, psoptions, - GL_RGBA, 0, NULL, size3d, fp, name); + gl2psBeginPage(CTX.base_filename, "Gmsh", CTX.viewport, + psformat, pssort, psoptions, GL_RGBA, 0, NULL, + 0, 0, 0, size3d, fp, name); CTX.print.gl_fonts = 0; FillBuffer(); CTX.print.gl_fonts = 1; @@ -236,9 +236,9 @@ void CreateOutputFile(char *name, int format) Msg(GERROR, "Unable to open file '%s'", name); return; } - gl2psBeginPage(CTX.base_filename, "Gmsh", - GL2PS_TEX, GL2PS_NO_SORT, 0, - GL_RGBA, 0, NULL, 1, fp, name); + gl2psBeginPage(CTX.base_filename, "Gmsh", CTX.viewport, + GL2PS_TEX, GL2PS_NO_SORT, GL2PS_NONE, GL_RGBA, 0, NULL, + 0, 0, 0, 1, fp, name); CTX.print.gl_fonts = 0; FillBuffer(); CTX.print.gl_fonts = 1; diff --git a/Graphics/gl2ps.cpp b/Graphics/gl2ps.cpp index 2d9af8e95e..95155c0279 100644 --- a/Graphics/gl2ps.cpp +++ b/Graphics/gl2ps.cpp @@ -2,7 +2,7 @@ * GL2PS, an OpenGL to PostScript Printing Library * Copyright (C) 1999-2003 Christophe Geuzaine * - * $Id: gl2ps.cpp,v 1.61 2003-03-01 22:34:18 geuzaine Exp $ + * $Id: gl2ps.cpp,v 1.62 2003-03-07 18:53:21 geuzaine Exp $ * * E-mail: geuz@geuz.org * URL: http://www.geuz.org/gl2ps/ @@ -25,7 +25,6 @@ #include <string.h> #include <sys/types.h> -#include <malloc.h> #include <stdarg.h> #include <time.h> #include "gl2ps.h" @@ -51,7 +50,9 @@ void gl2psMsg(GLint level, char *fmt, ...){ va_end(args); fprintf(stderr, "\n"); } - if(level == GL2PS_ERROR) exit(1); + /* + if(level == GL2PS_ERROR) exit(1); + */ } void *gl2psMalloc(size_t size){ @@ -59,14 +60,20 @@ void *gl2psMalloc(size_t size){ if(!size) return(NULL); ptr = malloc(size); - if(!ptr) gl2psMsg(GL2PS_ERROR, "Couldn't allocate requested memory"); + if(!ptr){ + gl2psMsg(GL2PS_ERROR, "Couldn't allocate requested memory"); + exit(1); + } return(ptr); } void *gl2psRealloc(void *ptr, size_t size){ if(!size) return(NULL); ptr = realloc(ptr, size); - if(!ptr) gl2psMsg(GL2PS_ERROR, "Couldn't reallocate requested memory"); + if(!ptr){ + gl2psMsg(GL2PS_ERROR, "Couldn't reallocate requested memory"); + exit(1); + } return(ptr); } @@ -107,6 +114,10 @@ GL2PSlist *gl2psListCreate(GLint n, GLint incr, GLint size){ return(list); } +void gl2psListReset(GL2PSlist *list){ + list->n = 0; +} + void gl2psListDelete(GL2PSlist *list){ gl2psFree(list->array); gl2psFree(list); @@ -125,6 +136,7 @@ GLint gl2psListNbr(GL2PSlist *list){ void *gl2psListPointer(GL2PSlist *list, GLint index){ if((index < 0) || (index >= list->n)){ gl2psMsg(GL2PS_ERROR, "Wrong list index in gl2psListPointer"); + return(&list->array[0]); } return(&list->array[index * list->size]); } @@ -240,6 +252,7 @@ void gl2psGetPlane(GL2PSprimitive *prim, GL2PSplane plane){ } break; case GL2PS_POINT : + case GL2PS_PIXMAP : case GL2PS_TEXT : plane[0] = plane[1] = 0.; plane[2] = 1.; @@ -247,6 +260,9 @@ void gl2psGetPlane(GL2PSprimitive *prim, GL2PSplane plane){ break; default : gl2psMsg(GL2PS_ERROR, "Unknown primitive type in BSP tree"); + plane[0] = plane[1] = plane[3] = 0.; + plane[2] = 1.; + break; } } @@ -331,7 +347,7 @@ GLint gl2psTestSplitPrimitive(GL2PSprimitive *prim, GL2PSplane plane){ d[i] = gl2psComparePointPlane(prim->verts[i].xyz, plane); } - if(prim->type == GL2PS_POINT){ + if(prim->numverts < 2){ return 0; } else{ @@ -489,7 +505,7 @@ GLint gl2psFindRoot(GL2PSlist *primitives, GL2PSprimitive **root){ if(!count) return index; } } - if(index) gl2psMsg(GL2PS_INFO, "GL2PS_BEST_ROOT was worth it: %d", index); + /* if(index) gl2psMsg(GL2PS_INFO, "GL2PS_BEST_ROOT was worth it: %d", index); */ return index; } else{ @@ -508,6 +524,10 @@ void gl2psFreePrimitive(void *a, void *b){ gl2psFree(q->text->fontname); gl2psFree(q->text); } + if(q->type == GL2PS_PIXMAP){ + gl2psFree(q->image->pixels); + gl2psFree(q->image); + } gl2psFree(q); } @@ -690,7 +710,7 @@ void gl2psAddPlanesInBspTreeImage(GL2PSprimitive *prim, if(!gl2psGetPlaneFromPoints(prim->verts[i].xyz, prim->verts[i+1].xyz, head->plane)){ - if(prim->numverts-i > 3) { + if(prim->numverts-i > 3){ offset++; } else{ @@ -899,7 +919,7 @@ void gl2psSplitPrimitive2D(GL2PSprimitive *prim, gl2psFree(back_list); } -GLint gl2psAddInImageTree(GL2PSprimitive *prim, GL2PSbsptree2d **tree){ +GLint gl2psAddInBspImageTree(GL2PSprimitive *prim, GL2PSbsptree2d **tree){ GLint ret = 0; GL2PSprimitive *frontprim = NULL, *backprim = NULL; @@ -909,15 +929,15 @@ GLint gl2psAddInImageTree(GL2PSprimitive *prim, GL2PSbsptree2d **tree){ } else{ switch(gl2psCheckPrimitive(prim, (*tree)->plane)){ - case GL2PS_IN_BACK_OF: return gl2psAddInImageTree(prim, &(*tree)->back); + case GL2PS_IN_BACK_OF: return gl2psAddInBspImageTree(prim, &(*tree)->back); case GL2PS_IN_FRONT_OF: - if((*tree)->front != NULL) return gl2psAddInImageTree(prim, &(*tree)->front); + if((*tree)->front != NULL) return gl2psAddInBspImageTree(prim, &(*tree)->front); else return 0; case GL2PS_SPANNING: gl2psSplitPrimitive2D(prim, (*tree)->plane, &frontprim, &backprim); - ret = gl2psAddInImageTree(backprim, &(*tree)->back); + ret = gl2psAddInBspImageTree(backprim, &(*tree)->back); if((*tree)->front != NULL){ - if(gl2psAddInImageTree(frontprim, &(*tree)->front)){ + if(gl2psAddInBspImageTree(frontprim, &(*tree)->front)){ ret = 1; } } @@ -934,10 +954,10 @@ GLint gl2psAddInImageTree(GL2PSprimitive *prim, GL2PSbsptree2d **tree){ return 0; } -void gl2psAddInImage(void *a, void *b){ +void gl2psAddInImageTree(void *a, void *b){ GL2PSprimitive *prim = *(GL2PSprimitive **)a; - if(!gl2psAddInImageTree(prim, &gl2ps->image)){ + if(!gl2psAddInBspImageTree(prim, &gl2ps->imagetree)){ prim->culled = 1; } } @@ -969,8 +989,7 @@ void gl2psAddBoundaryInList(GL2PSprimitive *prim, GL2PSlist *list){ b->numverts = 2; b->verts = (GL2PSvertex *)gl2psMalloc(2 * sizeof(GL2PSvertex)); -#define GL2PS_BOUNDARY_OFFSET 0 -#if GL2PS_BOUNDARY_OFFSET +#if 0 /* need to work on boundary offset... */ v[0] = c[0] - prim->verts[i].xyz[0]; v[1] = c[1] - prim->verts[i].xyz[1]; v[2] = 0.; @@ -1143,12 +1162,12 @@ GLint gl2psParseFeedbackBuffer(void){ used = glRenderMode(GL_RENDER); if(used < 0){ - gl2psMsg(GL2PS_INFO, "OpenGL feedback buffer reallocation"); + gl2psMsg(GL2PS_INFO, "OpenGL feedback buffer overflow"); return GL2PS_OVERFLOW; } if(used == 0){ - gl2psMsg(GL2PS_WARNING, "Empty feedback buffer"); + /* gl2psMsg(GL2PS_INFO, "Empty feedback buffer"); */ return GL2PS_NO_FEEDBACK; } @@ -1267,28 +1286,201 @@ GLboolean gl2psVertsSameColor(const GL2PSprimitive *prim){ return 1; } +GLint gl2psPrintPrimitives(void); + /* The PostScript routines. Other (vector) image formats should be easy to generate by creating the three corresponding routines - (gl2psPrintXXXHeader, gl2psPrintXXXPrimitive and - gl2psPrintXXXFooter) for the new format. */ + (gl2psPrintXXXHeader, gl2psPrintXXXPrimitive, gl2psPrintXXXFooter, + gl2psPrintXXXBeginViewport and gl2psPrintXXXEndViewport) for the + new format. */ + +void gl2psWriteByte(FILE *stream, unsigned char byte){ + unsigned char h = byte / 16; + unsigned char l = byte % 16; + fprintf(stream, "%x%x", h, l); +} + +int gl2psGetRGB(GLfloat *pixels, GLsizei width, GLsizei height, GLuint x, GLuint y, + GLfloat *red, GLfloat *green, GLfloat *blue){ + /* OpenGL image is from down to up, PS image is up to down */ + GLfloat *pimag; + pimag = pixels + 3 * (width * (height - 1 - y) + x); + *red = *pimag; pimag++; + *green = *pimag; pimag++; + *blue = *pimag; pimag++; + return 1; +} + +void gl2psPrintPostScriptPixmap(GLfloat x, GLfloat y, GLsizei width, GLsizei height, + GLenum format, GLenum type, GLfloat *pixels, + FILE *stream){ + typedef unsigned char Uchar; + int status = 1, nbhex, nbyte2, nbyte4, nbyte8; + unsigned int row, col, col_max; + float dr, dg, db, fgrey; + Uchar red, green, blue, b, grey; + /* Options */ + int shade = 0; + int nbit = 4; + + if((width <= 0) || (height <= 0)) return; + + /* Msg(INFO, "gl2psPrintPostScriptPixmap: x %g y %g w %d h %d", x, y, width, height); */ + + fprintf(stream, "gsave\n"); + fprintf(stream, "%.2f %.2f translate\n", x, y); + fprintf(stream, "%d %d scale\n", width, height); + + if(shade != 0){ /* grey */ + fprintf(stream, "/picstr %d string def\n", width); + fprintf(stream, "%d %d %d\n", width, height, 8); + fprintf(stream, "[ %d 0 0 -%d 0 %d ]\n", width, height, height); + fprintf(stream, "{ currentfile picstr readhexstring pop }\n"); + fprintf(stream, "image\n"); + for(row = 0; row < height; row++){ + for(col = 0; col < width; col++){ + status = gl2psGetRGB(pixels, width, height, + col, row, &dr, &dg, &db) == 0 ? 0 : status; + fgrey = (0.30 * dr + 0.59 * dg + 0.11 * db); + grey = (Uchar)(255. * fgrey); + gl2psWriteByte(stream, grey); + } + fprintf(stream, "\n"); + } + nbhex = width * height * 2; + fprintf(stream, "%%%% nbhex digit :%d\n", nbhex); + } + else if(nbit == 2){ + nbyte2 = (width * 3)/4; + nbyte2 /=3; + nbyte2 *=3; + col_max = (nbyte2 * 4)/3; + /* 2 bit for r and g and b */ + /* rgbs following each other */ + fprintf(stream, "/rgbstr %d string def\n", nbyte2); + fprintf(stream, "%d %d %d\n", col_max, height, 2); + fprintf(stream, "[ %d 0 0 -%d 0 %d ]\n", col_max, height, height); + fprintf(stream, "{ currentfile rgbstr readhexstring pop }\n" ); + fprintf(stream, "false 3\n" ); + fprintf(stream, "colorimage\n" ); + for(row = 0; row < height; row++){ + for(col = 0; col < col_max; col+=4){ + status = gl2psGetRGB(pixels, width, height, + col, row, &dr, &dg, &db) == 0 ? 0 : status; + red = (Uchar)(3. * dr); + green = (Uchar)(3. * dg); + blue = (Uchar)(3. * db); + b = red; + b = (b<<2)+green; + b = (b<<2)+blue; + status = gl2psGetRGB(pixels, width, height, + col+1, row, &dr, &dg, &db) == 0 ? 0 : status; + red = (Uchar)(3. * dr); + green = (Uchar)(3. * dg); + blue = (Uchar)(3. * db); + b = (b<<2)+red; + gl2psWriteByte(stream, b); + + b = green; + b = (b<<2)+blue; + status = gl2psGetRGB(pixels, width, height, + col+2, row, &dr, &dg, &db) == 0 ? 0 : status; + red = (Uchar)(3. * dr); + green = (Uchar)(3. * dg); + blue = (Uchar)(3. * db); + b = (b<<2)+red; + b = (b<<2)+green; + gl2psWriteByte(stream, b); + + b = blue; + status = gl2psGetRGB(pixels,width,height, + col+3, row, &dr, &dg, &db) == 0 ? 0 : status; + red = (Uchar)(3. * dr); + green = (Uchar)(3. * dg); + blue = (Uchar)(3. * db); + b = (b<<2)+red; + b = (b<<2)+green; + b = (b<<2)+blue; + gl2psWriteByte(stream, b); + } + fprintf(stream, "\n"); + } + } + else if(nbit == 4){ + nbyte4 = (width * 3)/2; + nbyte4 /=3; + nbyte4 *=3; + col_max = (nbyte4 * 2)/3; + /* 4 bit for r and g and b */ + /* rgbs following each other */ + fprintf(stream, "/rgbstr %d string def\n", nbyte4); + fprintf(stream, "%d %d %d\n", col_max, height,4); + fprintf(stream, "[ %d 0 0 -%d 0 %d ]\n", col_max, height, height); + fprintf(stream, "{ currentfile rgbstr readhexstring pop }\n"); + fprintf(stream, "false 3\n"); + fprintf(stream, "colorimage\n"); + for(row = 0; row < height; row++){ + for(col = 0; col < col_max; col+=2){ + status = gl2psGetRGB(pixels, width, height, + col, row, &dr, &dg, &db) == 0 ? 0 : status; + red = (Uchar)(15. * dr); + green = (Uchar)(15. * dg); + fprintf(stream, "%x%x", red, green); + blue = (Uchar)(15. * db); + + status = gl2psGetRGB(pixels, width, height, + col+1, row, &dr, &dg, &db) == 0 ? 0 : status; + red = (Uchar)(15. * dr); + fprintf(stream,"%x%x",blue,red); + green = (Uchar)(15. * dg); + blue = (Uchar)(15. * db); + fprintf(stream, "%x%x", green, blue); + } + fprintf(stream, "\n"); + } + } + else{ + nbyte8 = width * 3; + /* 8 bit for r and g and b */ + fprintf(stream, "/rgbstr %d string def\n", nbyte8); + fprintf(stream, "%d %d %d\n", width, height, 8); + fprintf(stream, "[ %d 0 0 -%d 0 %d ]\n", width, height, height); + fprintf(stream, "{ currentfile rgbstr readhexstring pop }\n"); + fprintf(stream, "false 3\n"); + fprintf(stream, "colorimage\n"); + for(row = 0; row < height; row++){ + for(col = 0; col < width; col++){ + status = gl2psGetRGB(pixels, width, height, + col, row, &dr, &dg, &db) == 0 ? 0 : status; + red = (Uchar)(255. * dr); + gl2psWriteByte(stream, red); + green = (Uchar)(255. * dg); + gl2psWriteByte(stream, green); + blue = (Uchar)(255. * db); + gl2psWriteByte(stream, blue); + } + fprintf(stream, "\n"); + } + } + + if(status == 0){ + gl2psMsg(GL2PS_ERROR, "Problem to retreive some pixel rgb"); + } + fprintf(stream, "grestore\n"); +} void gl2psPrintPostScriptHeader(void){ - GLint viewport[4], index; + GLint index; GLfloat rgba[4]; time_t now; time(&now); - glGetIntegerv(GL_VIEWPORT, viewport); - if(gl2ps->format == GL2PS_PS){ fprintf(gl2ps->stream, "%%!PS-Adobe-3.0\n"); } - else if(gl2ps->format == GL2PS_EPS){ - fprintf(gl2ps->stream, "%%!PS-Adobe-3.0 EPSF-3.0\n"); - } else{ - gl2psMsg(GL2PS_ERROR, "Unknown PostScript format"); + fprintf(gl2ps->stream, "%%!PS-Adobe-3.0 EPSF-3.0\n"); } fprintf(gl2ps->stream, @@ -1306,18 +1498,18 @@ void gl2psPrintPostScriptHeader(void){ "%%%%Orientation: %s\n" "%%%%DocumentMedia: Default %d %d 0 () ()\n", (gl2ps->options & GL2PS_LANDSCAPE) ? "Landscape" : "Portrait", - (gl2ps->options & GL2PS_LANDSCAPE) ? viewport[3] : viewport[2], - (gl2ps->options & GL2PS_LANDSCAPE) ? viewport[2] : viewport[3]); + (gl2ps->options & GL2PS_LANDSCAPE) ? gl2ps->viewport[3] : gl2ps->viewport[2], + (gl2ps->options & GL2PS_LANDSCAPE) ? gl2ps->viewport[2] : gl2ps->viewport[3]); } fprintf(gl2ps->stream, "%%%%BoundingBox: %d %d %d %d\n" "%%%%Copyright: GNU LGPL (C) 1999-2003 Christophe Geuzaine <geuz@geuz.org>\n" "%%%%EndComments\n", - (gl2ps->options & GL2PS_LANDSCAPE) ? viewport[1] : viewport[0], - (gl2ps->options & GL2PS_LANDSCAPE) ? viewport[0] : viewport[1], - (gl2ps->options & GL2PS_LANDSCAPE) ? viewport[3] : viewport[2], - (gl2ps->options & GL2PS_LANDSCAPE) ? viewport[2] : viewport[3]); + (gl2ps->options & GL2PS_LANDSCAPE) ? gl2ps->viewport[1] : gl2ps->viewport[0], + (gl2ps->options & GL2PS_LANDSCAPE) ? gl2ps->viewport[0] : gl2ps->viewport[1], + (gl2ps->options & GL2PS_LANDSCAPE) ? gl2ps->viewport[3] : gl2ps->viewport[2], + (gl2ps->options & GL2PS_LANDSCAPE) ? gl2ps->viewport[2] : gl2ps->viewport[3]); /* RGB color: r g b C (replace C by G in output to change from rgb to gray) Grayscale: r g b G @@ -1463,7 +1655,7 @@ void gl2psPrintPostScriptHeader(void){ if(gl2ps->options & GL2PS_LANDSCAPE){ fprintf(gl2ps->stream, "%d 0 translate 90 rotate\n", - viewport[3]); + gl2ps->viewport[3]); } fprintf(gl2ps->stream, @@ -1488,8 +1680,9 @@ void gl2psPrintPostScriptHeader(void){ "newpath %d %d moveto %d %d lineto %d %d lineto %d %d lineto\n" "closepath fill\n", rgba[0], rgba[1], rgba[2], - viewport[0], viewport[1], viewport[2], viewport[1], - viewport[2], viewport[3], viewport[0], viewport[3]); + gl2ps->viewport[0], gl2ps->viewport[1], gl2ps->viewport[2], + gl2ps->viewport[1], gl2ps->viewport[2], gl2ps->viewport[3], + gl2ps->viewport[0], gl2ps->viewport[3]); } } @@ -1514,6 +1707,12 @@ void gl2psPrintPostScriptPrimitive(void *a, void *b){ if(gl2ps->options & GL2PS_OCCLUSION_CULL && prim->culled) return; switch(prim->type){ + case GL2PS_PIXMAP : + gl2psPrintPostScriptPixmap(prim->verts[0].xyz[0], prim->verts[0].xyz[1], + prim->image->width, prim->image->height, + prim->image->format, prim->image->type, + prim->image->pixels, gl2ps->stream); + break; case GL2PS_TEXT : gl2psPrintPostScriptColor(prim->verts[0].rgba); fprintf(gl2ps->stream, "(%s) %g %g %d /%s S\n", @@ -1593,15 +1792,56 @@ void gl2psPrintPostScriptFooter(void){ "%%%%EOF\n"); } +void gl2psPrintPostScriptBeginViewport(GLint viewport[4]){ + GLint index; + GLfloat rgba[4]; + int x = viewport[0], y = viewport[1], w = viewport[2], h = viewport[3]; + + glRenderMode(GL_FEEDBACK); + + fprintf(gl2ps->stream, + "gsave\n" + "1.0 1.0 scale\n"); + + if(gl2ps->options & GL2PS_DRAW_BACKGROUND){ + if(gl2ps->colormode == GL_RGBA || gl2ps->colorsize == 0){ + glGetFloatv(GL_COLOR_CLEAR_VALUE, rgba); + } + else{ + glGetIntegerv(GL_INDEX_CLEAR_VALUE, &index); + rgba[0] = gl2ps->colormap[index][0]; + rgba[1] = gl2ps->colormap[index][1]; + rgba[2] = gl2ps->colormap[index][2]; + rgba[3] = 0.; + } + fprintf(gl2ps->stream, + "%g %g %g C\n" + "newpath %d %d moveto %d %d lineto %d %d lineto %d %d lineto\n" + "closepath fill\n", + rgba[0], rgba[1], rgba[2], + x, y, x+w, y, x+w, y+h, x, y+h); + fprintf(gl2ps->stream, + "newpath %d %d moveto %d %d lineto %d %d lineto %d %d lineto\n" + "closepath clip\n", + x, y, x+w, y, x+w, y+h, x, y+h); + } + +} + +GLint gl2psPrintPostScriptEndViewport(void){ + GLint res; + + res = gl2psPrintPrimitives(); + fprintf(gl2ps->stream, "grestore\n"); + return res; +} + /* The LaTeX routines */ void gl2psPrintTeXHeader(void){ - GLint viewport[4]; char name[256]; int i; - glGetIntegerv(GL_VIEWPORT, viewport); - if(gl2ps->filename && strlen(gl2ps->filename) < 256){ for(i = strlen(gl2ps->filename)-1; i >= 0; i--){ if(gl2ps->filename[i] == '.'){ @@ -1623,7 +1863,7 @@ void gl2psPrintTeXHeader(void){ "\\end{picture}%%\n" "%s\\begin{picture}(%d,%d)(0,0)\n", name, (gl2ps->options & GL2PS_LANDSCAPE) ? "\\rotatebox{90}{" : "", - viewport[2],viewport[3]); + gl2ps->viewport[2], gl2ps->viewport[3]); } void gl2psPrintTeXPrimitive(void *a, void *b){ @@ -1646,73 +1886,20 @@ void gl2psPrintTeXFooter(void){ (gl2ps->options & GL2PS_LANDSCAPE) ? "}" : ""); } +void gl2psPrintTeXBeginViewport(GLint viewport[4]){ +} -/* The public routines */ - -GL2PSDLL_API void gl2psBeginPage(const char *title, const char *producer, - GLint format, GLint sort, GLint options, - GLint colormode, GLint colorsize, - GL2PSrgba *colormap, GLint buffersize, - FILE *stream, const char *filename){ - gl2ps = (GL2PScontext*)gl2psMalloc(sizeof(GL2PScontext)); - gl2ps->maxbestroot = 10; - gl2ps->format = format; - gl2ps->title = title; - gl2ps->producer = producer; - gl2ps->filename = filename; - gl2ps->sort = sort; - gl2ps->options = options; - gl2ps->threshold[0] = 0.032; - gl2ps->threshold[1] = 0.017; - gl2ps->threshold[2] = 0.05; - gl2ps->colormode = colormode; - gl2ps->buffersize = buffersize > 0 ? buffersize : 2048 * 2048; - gl2ps->feedback = (GLfloat*)gl2psMalloc(gl2ps->buffersize * sizeof(GLfloat)); - gl2ps->lastrgba[0] = -1.; - gl2ps->lastrgba[1] = -1.; - gl2ps->lastrgba[2] = -1.; - gl2ps->lastrgba[3] = -1.; - gl2ps->lastlinewidth = -1.; - gl2ps->image = NULL; - gl2ps->primitives = gl2psListCreate(500, 500, sizeof(GL2PSprimitive*)); - - if(gl2ps->colormode == GL_RGBA){ - gl2ps->colorsize = 0; - gl2ps->colormap = NULL; - } - else if(gl2ps->colormode == GL_COLOR_INDEX){ - if(!colorsize || !colormap){ - gl2psMsg(GL2PS_ERROR, "Missing colormap for GL_COLOR_INDEX rendering"); - } - gl2ps->colorsize = colorsize; - gl2ps->colormap = (GL2PSrgba*)gl2psMalloc(gl2ps->colorsize * sizeof(GL2PSrgba)); - memcpy(gl2ps->colormap, colormap, gl2ps->colorsize * sizeof(GL2PSrgba)); - } - else - gl2psMsg(GL2PS_ERROR, "Unknown color mode in gl2psBeginPage"); - - if(stream){ - gl2ps->stream = stream; - } - else{ - gl2psMsg(GL2PS_ERROR, "Bad file pointer"); - } - - glFeedbackBuffer(gl2ps->buffersize, GL_3D_COLOR, gl2ps->feedback); - glRenderMode(GL_FEEDBACK); +GLint gl2psPrintTeXEndViewport(void){ + return GL2PS_SUCCESS; } -GL2PSDLL_API GLint gl2psEndPage(void){ +/* The general primitive printing routine */ + +GLint gl2psPrintPrimitives(void){ GL2PSbsptree *root; GL2PSxyz eye = {0., 0., 100000.}; GLint shademodel, res; - void (*phead)(void) = 0; void (*pprim)(void *a, void *b) = 0; - void (*pfoot)(void) = 0; - - if(!gl2ps){ - gl2psMsg(GL2PS_ERROR, "Uninitialized gl2ps context"); - } glGetIntegerv(GL_SHADE_MODEL, &shademodel); gl2ps->shade = (shademodel == GL_SMOOTH); @@ -1724,45 +1911,35 @@ GL2PSDLL_API GLint gl2psEndPage(void){ res = gl2psParseFeedbackBuffer(); } - if(gl2ps->feedback) gl2psFree(gl2ps->feedback); - if(res == GL2PS_SUCCESS){ switch(gl2ps->format){ case GL2PS_TEX : - phead = gl2psPrintTeXHeader; pprim = gl2psPrintTeXPrimitive; - pfoot = gl2psPrintTeXFooter; break; case GL2PS_PS : case GL2PS_EPS : - phead = gl2psPrintPostScriptHeader; pprim = gl2psPrintPostScriptPrimitive; - pfoot = gl2psPrintPostScriptFooter; - break; - default : - gl2psMsg(GL2PS_ERROR, "Unknown format"); break; } - phead(); switch(gl2ps->sort){ case GL2PS_NO_SORT : gl2psListAction(gl2ps->primitives, pprim); gl2psListAction(gl2ps->primitives, gl2psFreePrimitive); - gl2psListDelete(gl2ps->primitives); - res = GL2PS_SUCCESS; + /* reset the primitive list, waiting for the next viewport */ + gl2psListReset(gl2ps->primitives); break; case GL2PS_SIMPLE_SORT : gl2psListSort(gl2ps->primitives, gl2psCompareDepth); if(gl2ps->options & GL2PS_OCCLUSION_CULL){ - gl2psListAction(gl2ps->primitives,gl2psAddInImage); - gl2psFreeBspImageTree(&gl2ps->image); + gl2psListAction(gl2ps->primitives, gl2psAddInImageTree); + gl2psFreeBspImageTree(&gl2ps->imagetree); } gl2psListActionInverse(gl2ps->primitives, pprim); gl2psListAction(gl2ps->primitives, gl2psFreePrimitive); - gl2psListDelete(gl2ps->primitives); - res = GL2PS_SUCCESS; + /* reset the primitive list, waiting for the next viewport */ + gl2psListReset(gl2ps->primitives); break; case GL2PS_BSP_SORT : root = (GL2PSbsptree*)gl2psMalloc(sizeof(GL2PSbsptree)); @@ -1770,42 +1947,193 @@ GL2PSDLL_API GLint gl2psEndPage(void){ if(gl2ps->boundary) gl2psBuildPolygonBoundary(root); if(gl2ps->options & GL2PS_OCCLUSION_CULL){ gl2psTraverseBspTree(root, eye, -(float)GL2PS_EPSILON, gl2psLess, - gl2psAddInImage); - gl2psFreeBspImageTree(&gl2ps->image); + gl2psAddInImageTree); + gl2psFreeBspImageTree(&gl2ps->imagetree); } gl2psTraverseBspTree(root, eye, (float)GL2PS_EPSILON, gl2psGreater, pprim); gl2psFreeBspTree(&root); - res = GL2PS_SUCCESS; + /* reallocate the primitive list (it's been deleted by + gl2psBuildBspTree) in case there is another viewport */ + gl2ps->primitives = gl2psListCreate(500, 500, sizeof(GL2PSprimitive*)); break; default : - gl2psMsg(GL2PS_ERROR, "Unknown sorting algorithm"); + gl2psMsg(GL2PS_ERROR, "Unknown sorting algorithm: %d", gl2ps->sort); + res = GL2PS_ERROR; + break; } - pfoot(); fflush(gl2ps->stream); - + } - - if(gl2ps->colormap) gl2psFree(gl2ps->colormap); + return res; +} + +/* The public routines */ + +GL2PSDLL_API GLint gl2psBeginPage(const char *title, const char *producer, + GLint viewport[4], GLint format, GLint sort, + GLint options, GLint colormode, + GLint colorsize, GL2PSrgba *colormap, + GLint nr, GLint ng, GLint nb, GLint buffersize, + FILE *stream, const char *filename){ + int i; + gl2ps = (GL2PScontext*)gl2psMalloc(sizeof(GL2PScontext)); + gl2ps->maxbestroot = 10; + gl2ps->format = format; + gl2ps->title = title; + gl2ps->producer = producer; + gl2ps->filename = filename; + gl2ps->sort = sort; + gl2ps->options = options; + for(i = 0; i < 4; i++){ + gl2ps->viewport[i] = viewport[i]; + } + gl2ps->threshold[0] = nr ? 1./(GLfloat)nr : 0.032; + gl2ps->threshold[1] = ng ? 1./(GLfloat)ng : 0.017; + gl2ps->threshold[2] = nb ? 1./(GLfloat)nb : 0.05; + gl2ps->colormode = colormode; + gl2ps->buffersize = buffersize > 0 ? buffersize : 2048 * 2048; + for(i = 0; i < 4; i++){ + gl2ps->lastrgba[i] = -1.; + } + gl2ps->lastlinewidth = -1.; + gl2ps->imagetree = NULL; + + if(gl2ps->colormode == GL_RGBA){ + gl2ps->colorsize = 0; + gl2ps->colormap = NULL; + } + else if(gl2ps->colormode == GL_COLOR_INDEX){ + if(!colorsize || !colormap){ + gl2psMsg(GL2PS_ERROR, "Missing colormap for GL_COLOR_INDEX rendering"); + gl2psFree(gl2ps); + gl2ps = NULL; + return GL2PS_ERROR; + } + gl2ps->colorsize = colorsize; + gl2ps->colormap = (GL2PSrgba*)gl2psMalloc(gl2ps->colorsize * sizeof(GL2PSrgba)); + memcpy(gl2ps->colormap, colormap, gl2ps->colorsize * sizeof(GL2PSrgba)); + } + else{ + gl2psMsg(GL2PS_ERROR, "Unknown color mode in gl2psBeginPage"); + gl2psFree(gl2ps); + gl2ps = NULL; + return GL2PS_ERROR; + } + + if(!stream){ + gl2psMsg(GL2PS_ERROR, "Bad file pointer"); + gl2psFree(gl2ps); + gl2ps = NULL; + return GL2PS_ERROR; + } + else{ + gl2ps->stream = stream; + /* In case gl2psEndPage failed (e.g. due to a GL2PS_OVERFLOW) and + we didn't reopen the stream before calling gl2psBeginPage + again, we need to rewind the stream */ + rewind(gl2ps->stream); + } + + switch(gl2ps->format){ + case GL2PS_TEX : + gl2psPrintTeXHeader(); + break; + case GL2PS_PS : + case GL2PS_EPS : + gl2psPrintPostScriptHeader(); + break; + default : + gl2psMsg(GL2PS_ERROR, "Unknown output format: %d", gl2ps->format); + gl2psFree(gl2ps); + gl2ps = NULL; + return GL2PS_ERROR; + } + + gl2ps->primitives = gl2psListCreate(500, 500, sizeof(GL2PSprimitive*)); + gl2ps->feedback = (GLfloat*)gl2psMalloc(gl2ps->buffersize * sizeof(GLfloat)); + glFeedbackBuffer(gl2ps->buffersize, GL_3D_COLOR, gl2ps->feedback); + glRenderMode(GL_FEEDBACK); + + return GL2PS_SUCCESS; +} + +GL2PSDLL_API GLint gl2psEndPage(void){ + GLint res; + + if(!gl2ps) return GL2PS_UNINITIALIZED; + + res = gl2psPrintPrimitives(); + + /* print the footer even if gl2psPrintPrimitives didn't succeed, so + that we end up with a valid file */ + switch(gl2ps->format){ + case GL2PS_TEX : + gl2psPrintTeXFooter(); + break; + case GL2PS_PS : + case GL2PS_EPS : + gl2psPrintPostScriptFooter(); + break; + } + + fflush(gl2ps->stream); + + gl2psListDelete(gl2ps->primitives); + gl2psFree(gl2ps->colormap); + gl2psFree(gl2ps->feedback); gl2psFree(gl2ps); gl2ps = NULL; return res; } -GL2PSDLL_API void gl2psText(const char *str, const char *fontname, GLshort fontsize){ +GL2PSDLL_API GLint gl2psBeginViewport(GLint viewport[4]){ + if(!gl2ps) return GL2PS_UNINITIALIZED; + + switch(gl2ps->format){ + case GL2PS_EPS : + gl2psPrintPostScriptBeginViewport(viewport); + break; + default : + /* FIXME: handle other formats */ + break; + } + + return GL2PS_SUCCESS; +} + +GL2PSDLL_API GLint gl2psEndViewport(void){ + GLint res; + + if(!gl2ps) return GL2PS_UNINITIALIZED; + + switch(gl2ps->format){ + case GL2PS_EPS : + res = gl2psPrintPostScriptEndViewport(); + break; + default : + /* FIXME: handle other formats */ + res = GL2PS_SUCCESS; + break; + } + + return res; +} + +GL2PSDLL_API GLint gl2psText(const char *str, const char *fontname, GLshort fontsize){ GLfloat pos[4]; GL2PSprimitive *prim; GLboolean valid; - if(!gl2ps || !str) return; + if(!gl2ps || !str) return GL2PS_UNINITIALIZED; - if(gl2ps->options & GL2PS_NO_TEXT) return; + if(gl2ps->options & GL2PS_NO_TEXT) return GL2PS_SUCCESS; glGetBooleanv(GL_CURRENT_RASTER_POSITION_VALID, &valid); - if(!valid) return; /* the primitive is culled */ + if(!valid) return GL2PS_SUCCESS; /* the primitive is culled */ glGetFloatv(GL_CURRENT_RASTER_POSITION, pos); @@ -1830,10 +2158,64 @@ GL2PSDLL_API void gl2psText(const char *str, const char *fontname, GLshort fonts prim->text->fontsize = fontsize; gl2psListAdd(gl2ps->primitives, &prim); + + return GL2PS_SUCCESS; +} + +GL2PSDLL_API GLint gl2psDrawPixels(GLsizei width, GLsizei height, + GLint xorig, GLint yorig, + GLenum format, GLenum type, + const void *pixels){ + int size; + GLfloat pos[4]; + GL2PSprimitive *prim; + GLboolean valid; + + if(!gl2ps || !pixels) return GL2PS_UNINITIALIZED; + + if((width <= 0) || (height <= 0)) return GL2PS_ERROR; + + if(gl2ps->options & GL2PS_NO_PIXMAP) return GL2PS_SUCCESS; + + if(format != GL_RGB || type != GL_FLOAT){ + gl2psMsg(GL2PS_ERROR, "gl2psDrawPixels only implemented for GL_RGB, GL_FLOAT pixels"); + return GL2PS_ERROR; + } + + glGetBooleanv(GL_CURRENT_RASTER_POSITION_VALID, &valid); + if(!valid) return GL2PS_SUCCESS; /* the primitive is culled */ + + glGetFloatv(GL_CURRENT_RASTER_POSITION, pos); + + prim = (GL2PSprimitive *)gl2psMalloc(sizeof(GL2PSprimitive)); + prim->type = GL2PS_PIXMAP; + prim->boundary = 0; + prim->numverts = 1; + prim->verts = (GL2PSvertex *)gl2psMalloc(sizeof(GL2PSvertex)); + prim->verts[0].xyz[0] = pos[0] + xorig; + prim->verts[0].xyz[1] = pos[1] + yorig; + prim->verts[0].xyz[2] = GL2PS_DEPTH_FACT * pos[2]; + prim->depth = pos[2]; + prim->culled = 0; + prim->dash = 0; + prim->width = 1; + glGetFloatv(GL_CURRENT_RASTER_COLOR, prim->verts[0].rgba); + prim->image = (GL2PSimage*)gl2psMalloc(sizeof(GL2PSimage)); + prim->image->width = width; + prim->image->height = height; + prim->image->format = format; + prim->image->type = type; + size = height*width*3*sizeof(GLfloat); /* FIXME: generalize to other types/formats */ + prim->image->pixels = (GLfloat*)gl2psMalloc(size); + memcpy(prim->image->pixels, pixels, size); + + gl2psListAdd(gl2ps->primitives, &prim); + + return GL2PS_SUCCESS; } -GL2PSDLL_API void gl2psEnable(GLint mode){ - if(!gl2ps) return; +GL2PSDLL_API GLint gl2psEnable(GLint mode){ + if(!gl2ps) return GL2PS_UNINITIALIZED; switch(mode){ case GL2PS_POLYGON_OFFSET_FILL : @@ -1848,13 +2230,15 @@ GL2PSDLL_API void gl2psEnable(GLint mode){ glPassThrough(GL2PS_BEGIN_LINE_STIPPLE); break; default : - gl2psMsg(GL2PS_WARNING, "Unknown mode in gl2psEnable"); - break; + gl2psMsg(GL2PS_WARNING, "Unknown mode in gl2psEnable: %d", mode); + return GL2PS_WARNING; } + + return GL2PS_SUCCESS; } -GL2PSDLL_API void gl2psDisable(GLint mode){ - if(!gl2ps) return; +GL2PSDLL_API GLint gl2psDisable(GLint mode){ + if(!gl2ps) return GL2PS_UNINITIALIZED; switch(mode){ case GL2PS_POLYGON_OFFSET_FILL : @@ -1867,30 +2251,27 @@ GL2PSDLL_API void gl2psDisable(GLint mode){ glPassThrough(GL2PS_END_LINE_STIPPLE); break; default : - gl2psMsg(GL2PS_WARNING, "Unknown mode in gl2psDisable"); - break; + gl2psMsg(GL2PS_WARNING, "Unknown mode in gl2psDisable: %d", mode); + return GL2PS_WARNING; } + + return GL2PS_SUCCESS; } -GL2PSDLL_API void gl2psPointSize(GLfloat value){ - if(!gl2ps) return; +GL2PSDLL_API GLint gl2psPointSize(GLfloat value){ + if(!gl2ps) return GL2PS_UNINITIALIZED; glPassThrough(GL2PS_SET_POINT_SIZE); glPassThrough(value); + + return GL2PS_SUCCESS; } -GL2PSDLL_API void gl2psLineWidth(GLfloat value){ - if(!gl2ps) return; +GL2PSDLL_API GLint gl2psLineWidth(GLfloat value){ + if(!gl2ps) return GL2PS_UNINITIALIZED; glPassThrough(GL2PS_SET_LINE_WIDTH); glPassThrough(value); -} -GL2PSDLL_API void gl2psNumShadeColors(GLint nr, GLint ng, GLint nb){ - if(!gl2ps) return; - - gl2ps->threshold[0] = nr ? 1./(GLfloat)nr : 1.; - gl2ps->threshold[1] = ng ? 1./(GLfloat)ng : 1.; - gl2ps->threshold[2] = nb ? 1./(GLfloat)nb : 1.; + return GL2PS_SUCCESS; } - diff --git a/Graphics/gl2ps.h b/Graphics/gl2ps.h index d72b7799c1..d7d5d46fc4 100644 --- a/Graphics/gl2ps.h +++ b/Graphics/gl2ps.h @@ -2,7 +2,7 @@ * GL2PS, an OpenGL to PostScript Printing Library * Copyright (C) 1999-2003 Christophe Geuzaine * - * $Id: gl2ps.h,v 1.36 2003-03-01 22:34:18 geuzaine Exp $ + * $Id: gl2ps.h,v 1.37 2003-03-07 18:53:21 geuzaine Exp $ * * E-mail: geuz@geuz.org * URL: http://www.geuz.org/gl2ps/ @@ -55,7 +55,7 @@ #endif -#define GL2PS_VERSION 0.74 +#define GL2PS_VERSION 0.8 #define GL2PS_NONE 0 /* Output file format */ @@ -80,6 +80,7 @@ #define GL2PS_NO_TEXT (1<<5) #define GL2PS_LANDSCAPE (1<<6) #define GL2PS_NO_PS3_SHADING (1<<7) +#define GL2PS_NO_PIXMAP (1<<8) /* Arguments for gl2psEnable/gl2psDisable */ @@ -96,17 +97,15 @@ #define GL2PS_ZERO(arg) (fabs(arg)<1.e-20) /*#define GL2PS_ZERO(arg) ((arg)==0.0)*/ -/* Message levels */ +/* Message levels and error codes */ +#define GL2PS_SUCCESS 0 #define GL2PS_INFO 1 #define GL2PS_WARNING 2 #define GL2PS_ERROR 3 - -/* Error codes */ - -#define GL2PS_SUCCESS 0 -#define GL2PS_NO_FEEDBACK -1 -#define GL2PS_OVERFLOW -2 +#define GL2PS_NO_FEEDBACK 4 +#define GL2PS_OVERFLOW 5 +#define GL2PS_UNINITIALIZED 6 /* Primitive types */ @@ -115,6 +114,7 @@ #define GL2PS_LINE 3 #define GL2PS_QUADRANGLE 4 #define GL2PS_TRIANGLE 5 +#define GL2PS_PIXMAP 6 /* BSP tree primitive comparison */ @@ -174,12 +174,19 @@ typedef struct { char *str, *fontname; } GL2PSstring; +typedef struct { + GLsizei width, height; + GLenum format, type; + GLfloat *pixels; +} GL2PSimage; + typedef struct { GLshort type, numverts; char boundary, dash, culled; GLfloat width, depth; GL2PSvertex *verts; GL2PSstring *text; + GL2PSimage *image; } GL2PSprimitive; typedef struct { @@ -187,32 +194,37 @@ typedef struct { const char *title, *producer, *filename; GLboolean shade, boundary; GLfloat *feedback, offset[2]; + GLint viewport[4]; GL2PSrgba *colormap, lastrgba, threshold; float lastlinewidth; GL2PSlist *primitives; - GL2PSbsptree2d *image; + GL2PSbsptree2d *imagetree; FILE *stream; } GL2PScontext; - /* public functions */ #ifdef __cplusplus extern "C" { #endif -GL2PSDLL_API void gl2psBeginPage(const char *title, const char *producer, - GLint format, GLint sort, GLint options, - GLint colormode, GLint colorsize, - GL2PSrgba *colormap, GLint buffersize, +GL2PSDLL_API GLint gl2psBeginPage(const char *title, const char *producer, + GLint viewport[4], GLint format, GLint sort, + GLint options, GLint colormode, + GLint colorsize, GL2PSrgba *colormap, + GLint nr, GLint ng, GLint nb, GLint buffersize, FILE *stream, const char *filename); GL2PSDLL_API GLint gl2psEndPage(void); -GL2PSDLL_API void gl2psText(const char *str, const char *fontname, GLshort fontsize); -GL2PSDLL_API void gl2psEnable(GLint mode); -GL2PSDLL_API void gl2psDisable(GLint mode); -GL2PSDLL_API void gl2psPointSize(GLfloat value); -GL2PSDLL_API void gl2psLineWidth(GLfloat value); -GL2PSDLL_API void gl2psNumShadeColors(GLint nr, GLint ng, GLint nb); +GL2PSDLL_API GLint gl2psBeginViewport(GLint viewport[4]); +GL2PSDLL_API GLint gl2psEndViewport(void); +GL2PSDLL_API GLint gl2psText(const char *str, const char *fontname, GLshort fontsize); +GL2PSDLL_API GLint 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 gl2psLineWidth(GLfloat value); #ifdef __cplusplus }; -- GitLab