From aa697ff489b1c67730f57af17f80f3feca46a9bb Mon Sep 17 00:00:00 2001 From: Christophe Geuzaine <cgeuzaine@ulg.ac.be> Date: Sat, 25 Oct 2003 03:26:41 +0000 Subject: [PATCH] Add support for compressed PDF output --- Common/Context.h | 2 +- Common/DefaultOptions.h | 2 + Common/Options.cpp | 9 +- Common/Options.h | 1 + Graphics/CreateFile.cpp | 3 +- Graphics/gl2ps.cpp | 330 +++++++++++++++++++++++++++++++--------- Graphics/gl2ps.h | 41 ++++- configure | 1 + configure.in | 3 +- 9 files changed, 308 insertions(+), 84 deletions(-) diff --git a/Common/Context.h b/Common/Context.h index 64c86636cb..503f14b8f9 100644 --- a/Common/Context.h +++ b/Common/Context.h @@ -186,7 +186,7 @@ public : // print options struct{ - int format; + int format, compress; int eps_quality, eps_background, eps_font_size; int eps_occlusion_culling, eps_best_root; char *eps_font; diff --git a/Common/DefaultOptions.h b/Common/DefaultOptions.h index b0ddace736..4c8bf8ca41 100644 --- a/Common/DefaultOptions.h +++ b/Common/DefaultOptions.h @@ -989,6 +989,8 @@ StringXNumber ViewOptions_Number[] = { } ; StringXNumber PrintOptions_Number[] = { + { F|O, "Compress" , opt_print_compress , 0 , + "Compress output using zlib (only for PDF output at the moment)" }, { F|O, "EpsBackground" , opt_print_eps_background , 1 , "Save image background in postscript output" }, { F|O, "EpsFontSize" , opt_print_eps_font_size , 12. , diff --git a/Common/Options.cpp b/Common/Options.cpp index eb2ae45111..5f4e437255 100644 --- a/Common/Options.cpp +++ b/Common/Options.cpp @@ -1,4 +1,4 @@ -// $Id: Options.cpp,v 1.114 2003-09-01 23:50:19 geuzaine Exp $ +// $Id: Options.cpp,v 1.115 2003-10-25 03:26:40 geuzaine Exp $ // // Copyright (C) 1997-2003 C. Geuzaine, J.-F. Remacle // @@ -4513,6 +4513,13 @@ double opt_print_format(OPT_ARGS_NUM) return CTX.print.format; } +double opt_print_compress(OPT_ARGS_NUM) +{ + if(action & GMSH_SET) + CTX.print.compress = (int)val; + return CTX.print.compress; +} + double opt_print_eps_quality(OPT_ARGS_NUM) { if(action & GMSH_SET) diff --git a/Common/Options.h b/Common/Options.h index 2383a3dbc9..5420ac4e6e 100644 --- a/Common/Options.h +++ b/Common/Options.h @@ -462,6 +462,7 @@ double opt_view_line_width(OPT_ARGS_NUM); double opt_view_point_type(OPT_ARGS_NUM); double opt_view_line_type(OPT_ARGS_NUM); double opt_print_format(OPT_ARGS_NUM); +double opt_print_compress(OPT_ARGS_NUM); double opt_print_eps_quality(OPT_ARGS_NUM); double opt_print_eps_occlusion_culling(OPT_ARGS_NUM); double opt_print_eps_best_root(OPT_ARGS_NUM); diff --git a/Graphics/CreateFile.cpp b/Graphics/CreateFile.cpp index 0c39821237..67f146d7cf 100644 --- a/Graphics/CreateFile.cpp +++ b/Graphics/CreateFile.cpp @@ -1,4 +1,4 @@ -// $Id: CreateFile.cpp,v 1.47 2003-09-23 00:54:05 geuzaine Exp $ +// $Id: CreateFile.cpp,v 1.48 2003-10-25 03:26:41 geuzaine Exp $ // // Copyright (C) 1997-2003 C. Geuzaine, J.-F. Remacle // @@ -217,6 +217,7 @@ void CreateOutputFile(char *name, int format) (CTX.print.eps_occlusion_culling ? GL2PS_OCCLUSION_CULL : 0) | (CTX.print.eps_best_root ? GL2PS_BEST_ROOT : 0) | (CTX.print.eps_background ? GL2PS_DRAW_BACKGROUND : 0) | + (CTX.print.compress ? GL2PS_COMPRESS : 0) | (format == FORMAT_PSTEX ? GL2PS_NO_TEXT : 0) | (format == FORMAT_EPSTEX ? GL2PS_NO_TEXT : 0) | (format == FORMAT_PDFTEX ? GL2PS_NO_TEXT : 0); diff --git a/Graphics/gl2ps.cpp b/Graphics/gl2ps.cpp index b3ab2089e0..015e57c7c8 100644 --- a/Graphics/gl2ps.cpp +++ b/Graphics/gl2ps.cpp @@ -1,4 +1,4 @@ -/* $Id: gl2ps.cpp,v 1.72 2003-09-22 07:26:38 geuzaine Exp $ */ +/* $Id: gl2ps.cpp,v 1.73 2003-10-25 03:26:41 geuzaine Exp $ */ /* * GL2PS, an OpenGL to PostScript Printing Library * Copyright (C) 1999-2003 Christophe Geuzaine <geuz@geuz.org> @@ -104,11 +104,111 @@ void gl2psWriteByte(FILE *stream, unsigned char byte){ fprintf(stream, "%x%x", h, l); } -size_t gl2psWriteBigEndian(unsigned long data, size_t bytes, FILE* fp){ + +/* zlib helper */ + +#ifdef GL2PS_HAVE_ZLIB + +void gl2psSetupZstream(){ + gl2ps->zstream = (GL2PSzstream*)gl2psMalloc(sizeof(GL2PSzstream)); + gl2ps->zstream->dest = NULL; + gl2ps->zstream->src = NULL; + gl2ps->zstream->start = NULL; + gl2ps->zstream->destLen = 0; + gl2ps->zstream->srcLen = 0; +} + +void gl2psFreeZstream(){ + if (!gl2ps->zstream) + return; + gl2psFree(gl2ps->zstream->start); + gl2psFree(gl2ps->zstream->dest); + gl2ps->zstream->src = NULL; + gl2ps->zstream->start = NULL; + gl2ps->zstream->dest = NULL; + gl2ps->zstream->srcLen = 0; + gl2ps->zstream->destLen = 0; +} + +int gl2psAllocZstream(unsigned int srcsize){ + gl2psFreeZstream(); + + if (!gl2ps->zstream || srcsize == 0) + return GL2PS_ERROR; + + gl2ps->zstream->srcLen = srcsize; + gl2ps->zstream->destLen = (int)ceil(1.001 * gl2ps->zstream->srcLen + 12); + gl2ps->zstream->src = gl2psMalloc(gl2ps->zstream->srcLen); + gl2ps->zstream->start = gl2ps->zstream->src; + gl2ps->zstream->dest = gl2psMalloc(gl2ps->zstream->destLen); + + return GL2PS_SUCCESS; +} + +void* gl2psReallocZstream(unsigned int srcsize){ + if (!gl2ps->zstream || srcsize == 0) + return NULL; + + if (srcsize < gl2ps->zstream->srcLen) + return gl2ps->zstream->start; + + gl2ps->zstream->srcLen = srcsize; + gl2ps->zstream->destLen = (int)ceil(1.001 * gl2ps->zstream->srcLen + 12); + gl2ps->zstream->src = gl2psRealloc(gl2ps->zstream->src, gl2ps->zstream->srcLen); + gl2ps->zstream->start = gl2ps->zstream->src; + gl2ps->zstream->dest = gl2psRealloc(gl2ps->zstream->dest, gl2ps->zstream->destLen); + + return gl2ps->zstream->start; +} + +size_t gl2psWriteBigEndianZ(unsigned long data, size_t bytes){ + size_t i; + size_t size = sizeof(unsigned long); + for(i = 1; i <= bytes; ++i){ + *gl2ps->zstream->src = 0xff & (data >> (size-i) * 8); + ++gl2ps->zstream->src; + } + return bytes; +} + +int gl2psDeflate(){ + return compress2(gl2ps->zstream->dest, &gl2ps->zstream->destLen, + gl2ps->zstream->start, gl2ps->zstream->srcLen, Z_BEST_COMPRESSION); +} + +#endif + +int zprintf(const char* fmt, ...){ + int ret = 0; + va_list args; + +#ifdef GL2PS_HAVE_ZLIB + unsigned int bufsize = 0; + unsigned int oldsize = 0; + if(gl2ps->options & GL2PS_COMPRESS){ + va_start(args, fmt); + bufsize = vsprintf(gl2ps->zbuf, fmt, args); + va_end(args); + oldsize = gl2ps->zstream->srcLen; + gl2ps->zstream->start = gl2psReallocZstream(oldsize + bufsize); + memcpy(gl2ps->zstream->start+oldsize, gl2ps->zbuf, bufsize); + } + else{ +#endif + va_start(args, fmt); + ret = vfprintf(gl2ps->stream, fmt, args); + va_end(args); +#ifdef GL2PS_HAVE_ZLIB + } +#endif + return ret; +} + +size_t gl2psWriteBigEndian(unsigned long data, size_t bytes){ size_t i; size_t size = sizeof(unsigned long); for(i = 1; i <= bytes; ++i){ - fputc(0xff & (data >> (size-i) * 8), fp); + fputc(0xff & (data >> (size-i) * 8), gl2ps->stream); } return bytes; } @@ -2054,9 +2154,11 @@ GLint gl2psPrintTeXEndViewport(void){ *********************************************************************/ int gl2psPrintPDFCompressorType(){ - if(gl2ps->options & GL2PS_DEFLATE){ +#ifdef GL2PS_HAVE_ZLIB + if(gl2ps->options & GL2PS_COMPRESS){ return fprintf(gl2ps->stream, "/Filter [/FlateDecode]\n"); } +#endif return 0; } @@ -2067,13 +2169,13 @@ int gl2psPrintPDFStrokeColor(GL2PSrgba rgba){ gl2psSetLastColor(rgba); for(i = 0; i < 3; ++i){ if(GL2PS_ZERO(rgba[i])) - offs += fprintf(gl2ps->stream, "%.0f ", 0.); + offs += zprintf("%.0f ", 0.); else if(rgba[i] < 1e-4 || rgba[i] > 1e6) /* avoid %e formatting */ - offs += fprintf(gl2ps->stream, "%f ", rgba[i]); + offs += zprintf("%f ", rgba[i]); else - offs += fprintf(gl2ps->stream, "%g ", rgba[i]); + offs += zprintf("%g ", rgba[i]); } - offs += fprintf(gl2ps->stream, "RG\n"); + offs += zprintf("RG\n"); return offs; } @@ -2083,23 +2185,23 @@ int gl2psPrintPDFFillColor(GL2PSrgba rgba){ for(i = 0; i < 3; ++i){ if(GL2PS_ZERO(rgba[i])) - offs += fprintf(gl2ps->stream, "%.0f ", 0.); + offs += zprintf("%.0f ", 0.); else if(rgba[i] < 1e-4 || rgba[i] > 1e6) /* avoid %e formatting */ - offs += fprintf(gl2ps->stream, "%f ", rgba[i]); + offs += zprintf("%f ", rgba[i]); else - offs += fprintf(gl2ps->stream, "%g ", rgba[i]); + offs += zprintf("%g ", rgba[i]); } - offs += fprintf(gl2ps->stream, "rg\n"); + offs += zprintf("rg\n"); return offs; } int gl2psPrintPDFLineWidth(float lw){ if(GL2PS_ZERO(lw)) - return fprintf(gl2ps->stream, "%.0f w\n", 0.); + return zprintf("%.0f w\n", 0.); else if(lw < 1e-4 || lw > 1e6) /* avoid %e formatting */ - return fprintf(gl2ps->stream, "%f w\n", lw); + return zprintf("%f w\n", lw); else - return fprintf(gl2ps->stream, "%g w\n", lw); + return zprintf("%g w\n", lw); } /* Print 1st PDF object - file info */ @@ -2186,8 +2288,8 @@ int gl2psOpenPDFDataStreamWritePreface(){ int offs; GLint index; GLfloat rgba[4]; - - offs = fprintf(gl2ps->stream, "/GS1 gs\n"); + + offs = zprintf("/GS1 gs\n"); if(gl2ps->options & GL2PS_DRAW_BACKGROUND){ if(gl2ps->colormode == GL_RGBA || gl2ps->colorsize == 0){ @@ -2201,10 +2303,10 @@ int gl2psOpenPDFDataStreamWritePreface(){ rgba[3] = 0.; } offs += gl2psPrintPDFFillColor(rgba); - offs += fprintf(gl2ps->stream, "%d %d %d %d re\n", + offs += zprintf("%d %d %d %d re\n", (int)gl2ps->viewport[0], (int)gl2ps->viewport[1], (int)gl2ps->viewport[2], (int)gl2ps->viewport[3]); - offs += fprintf(gl2ps->stream, "f\n"); + offs += zprintf("f\n"); } return offs; } @@ -2213,7 +2315,13 @@ int gl2psOpenPDFDataStreamWritePreface(){ void gl2psPrintPDFHeader(){ int offs; - + +#ifdef GL2PS_HAVE_ZLIB + if(gl2ps->options & GL2PS_COMPRESS){ + gl2psSetupZstream(); + } +#endif + /* tlist, tidxlist, ilist and slist contain triangles, indexes for consecutive triangles, images and strings */ gl2ps->tlist = gl2psListCreate(100, 100, sizeof(GL2PStriangle)); @@ -2247,7 +2355,7 @@ int gl2psFlushPDFTriangles(){ if(gl2ps->lasttype == GL2PS_TRIANGLE && !gl2ps->last_triangle_finished){ gl2psListAdd(gl2ps->tidxlist, &gl2ps->consec_inner_cnt); - offs = fprintf(gl2ps->stream, "/Sh%d sh\n", gl2ps->consec_cnt++); + offs = zprintf("/Sh%d sh\n", gl2ps->consec_cnt++); gl2ps->consec_inner_cnt = 0; gl2ps->streamlength += offs; gl2ps->last_triangle_finished = 1; @@ -2259,7 +2367,7 @@ int gl2psFlushPDFLines(){ int offs = 0; if(gl2ps->lasttype == GL2PS_LINE && !gl2ps->last_line_finished){ - offs = fprintf(gl2ps->stream, "S\n"); + offs = zprintf("S\n"); gl2ps->streamlength += offs; gl2ps->last_line_finished = 1; } @@ -2287,8 +2395,7 @@ void gl2psPrintPDFPrimitive(void *a, void *b){ case GL2PS_PIXMAP : image = gl2psCopyPixmap(prim->image); gl2psListAdd(gl2ps->ilist, &image); - gl2ps->streamlength += fprintf(gl2ps->stream, - "q\n" + gl2ps->streamlength += zprintf("q\n" "%d 0 0 %d %f %f cm\n" "/Im%d Do\n" "Q\n", @@ -2300,8 +2407,7 @@ void gl2psPrintPDFPrimitive(void *a, void *b){ str = gl2psCopyText(prim->text); gl2psListAdd(gl2ps->slist, &str); gl2ps->streamlength += gl2psPrintPDFFillColor(prim->verts[0].rgba); - gl2ps->streamlength += fprintf(gl2ps->stream, - "BT\n" + gl2ps->streamlength += zprintf("BT\n" "/F%d %d Tf\n" "%f %f Td\n" "(%s) Tj\n" @@ -2315,12 +2421,12 @@ void gl2psPrintPDFPrimitive(void *a, void *b){ gl2ps->lastlinewidth = prim->width; gl2ps->streamlength += gl2psPrintPDFLineWidth(gl2ps->lastlinewidth); } - gl2ps->streamlength += fprintf(gl2ps->stream, "1 J\n"); + gl2ps->streamlength += zprintf("1 J\n"); gl2ps->streamlength += gl2psPrintPDFStrokeColor(prim->verts[0].rgba); - gl2ps->streamlength += fprintf(gl2ps->stream, "%f %f m %f %f l S\n", + gl2ps->streamlength += zprintf("%f %f m %f %f l S\n", prim->verts[0].xyz[0], prim->verts[0].xyz[1], prim->verts[0].xyz[0], prim->verts[0].xyz[1]); - gl2ps->streamlength += fprintf(gl2ps->stream, "0 J\n"); + gl2ps->streamlength += zprintf("0 J\n"); break; case GL2PS_LINE : gl2ps->line_width_diff = gl2ps->lastlinewidth != prim->width; @@ -2337,15 +2443,15 @@ void gl2psPrintPDFPrimitive(void *a, void *b){ gl2ps->streamlength += gl2psPrintPDFStrokeColor(prim->verts[0].rgba); } if(prim->dash){ - gl2ps->streamlength += fprintf(gl2ps->stream, "[%d] 0 d\n", prim->dash); + gl2ps->streamlength += zprintf("[%d] 0 d\n", prim->dash); } - gl2ps->streamlength += fprintf(gl2ps->stream, "%f %f m %f %f l \n", + gl2ps->streamlength += zprintf("%f %f m %f %f l \n", prim->verts[0].xyz[0], prim->verts[0].xyz[1], prim->verts[1].xyz[0], prim->verts[1].xyz[1]); gl2ps->last_line_finished = 0; if(prim->dash){ - gl2ps->streamlength += fprintf(gl2ps->stream, "S\n[] 0 d\n"); + gl2ps->streamlength += zprintf("S\n[] 0 d\n"); gl2ps->last_line_finished = 1; } break; @@ -2372,9 +2478,23 @@ void gl2psPrintPDFPrimitive(void *a, void *b){ int gl2psClosePDFDataStream(){ int offs = 0; - + offs += gl2psFlushPDFTriangles(); offs += gl2psFlushPDFLines(); + +#ifdef GL2PS_HAVE_ZLIB + if(gl2ps->options & GL2PS_COMPRESS){ + if (Z_OK != gl2psDeflate()) + gl2psMsg(GL2PS_ERROR, "gl2ps: zlib deflate error!"); + else + fwrite(gl2ps->zstream->dest, gl2ps->zstream->destLen, 1, gl2ps->stream); + gl2ps->streamlength += gl2ps->zstream->destLen; + + offs += gl2ps->streamlength; + gl2psFreeZstream(); + } +#endif + offs += fprintf(gl2ps->stream, "endstream\n" "endobj\n"); @@ -2501,9 +2621,10 @@ int gl2psPrintPDFExtGState(){ "endobj\n"); } -/* Put a triangles uncompressed raw data in shader stream */ +/* Put a triangles raw data in shader stream */ -int gl2psPrintPDFShaderStreamData(GL2PStriangle triangle){ +int gl2psPrintPDFShaderStreamData(GL2PStriangle triangle, + size_t (*action)(unsigned long data, size_t size)){ int offs = 0; int i; unsigned long imap; @@ -2515,14 +2636,14 @@ int gl2psPrintPDFShaderStreamData(GL2PStriangle triangle){ dy = gl2ps->viewport[3]-gl2ps->viewport[1]; for(i = 0; i < 3; ++i){ - offs += fwrite (&edgeflag, sizeof(char), 1, gl2ps->stream); + offs += (*action)(edgeflag, 1); - /* In unfiltered mode the Shader stream in PDF requires to be in a + /* The Shader stream in PDF requires to be in a 'big-endian' order */ if(fabs(dx*dy) < FLT_MIN){ - offs += gl2psWriteBigEndian(0, 4, gl2ps->stream); - offs += gl2psWriteBigEndian(0, 4, gl2ps->stream); + offs += (*action)(0, 4); + offs += (*action)(0, 4); } else{ diff = (triangle[i].xyz[0] - gl2ps->viewport[0]) / dx; @@ -2531,7 +2652,7 @@ int gl2psPrintPDFShaderStreamData(GL2PStriangle triangle){ else if(diff < 0) diff = 0; imap = (unsigned long)(diff * dmax); - offs += gl2psWriteBigEndian(imap, 4, gl2ps->stream); + offs += (*action)(imap, 4); diff = (triangle[i].xyz[1] - gl2ps->viewport[1]) / dy; if(diff > 1) @@ -2539,28 +2660,29 @@ int gl2psPrintPDFShaderStreamData(GL2PStriangle triangle){ else if(diff < 0) diff = 0; imap = (unsigned long)(diff * dmax); - offs += gl2psWriteBigEndian(imap, 4, gl2ps->stream); + offs += (*action)(imap, 4); } imap = (unsigned long)(triangle[i].rgba[0] * dmax); - offs += gl2psWriteBigEndian(imap, 1, gl2ps->stream); + offs += (*action)(imap, 1); imap = (unsigned long)(triangle[i].rgba[1] * dmax); - offs += gl2psWriteBigEndian(imap, 1, gl2ps->stream); + offs += (*action)(imap, 1); imap = (unsigned long)(triangle[i].rgba[2] * dmax); - offs += gl2psWriteBigEndian(imap, 1, gl2ps->stream); + offs += (*action)(imap, 1); } return offs; } + /* Writes shaded triangle */ int gl2psPrintPDFShader(int obj, GL2PSlist* triangles, int idx, int cnt ){ int offs = 0; int vertexbytes = 1+4+4+1+1+1; - int i; - + int i, done = 0; + offs += fprintf(gl2ps->stream, "%d 0 obj\n" "<< " @@ -2574,19 +2696,46 @@ int gl2psPrintPDFShader(int obj, GL2PSlist* triangles, int idx, int cnt ){ (int)gl2ps->viewport[0], (int)gl2ps->viewport[2], (int)gl2ps->viewport[1], (int)gl2ps->viewport[3]); - offs += gl2psPrintPDFCompressorType(); +#ifdef GL2PS_HAVE_ZLIB + if(gl2ps->options & GL2PS_COMPRESS){ + gl2psAllocZstream(vertexbytes * cnt * 3); - offs += fprintf(gl2ps->stream, - "/Length %d " - ">>\n" - "stream\n", - vertexbytes * 3 * cnt); - for(i = 0; i < cnt; ++i) - offs += gl2psPrintPDFShaderStreamData((GL2PSvertex*)gl2psListPointer(triangles, idx+i)); + for(i = 0; i < cnt; ++i) + gl2psPrintPDFShaderStreamData((GL2PSvertex*)gl2psListPointer(triangles, idx+i), + gl2psWriteBigEndianZ); + + if(Z_OK == gl2psDeflate() && 23 + gl2ps->zstream->destLen < gl2ps->zstream->srcLen){ + offs += gl2psPrintPDFCompressorType(); + offs += fprintf(gl2ps->stream, + "/Length %d " + ">>\n" + "stream\n", + (int)gl2ps->zstream->destLen); + offs += gl2ps->zstream->destLen * fwrite(gl2ps->zstream->dest, gl2ps->zstream->destLen, + 1, gl2ps->stream); + done = 1; + } + gl2psFreeZstream(); + } +#endif + + if(!done){ + /* no compression, or too long after compression, or compress2 error + -> write non-compressed entry */ + offs += fprintf(gl2ps->stream, + "/Length %d " + ">>\n" + "stream\n", + vertexbytes * 3 * cnt); + for(i = 0; i < cnt; ++i) + offs += gl2psPrintPDFShaderStreamData((GL2PSvertex*)gl2psListPointer(triangles, idx+i), + gl2psWriteBigEndian); + } offs += fprintf(gl2ps->stream, "\nendstream\n" "endobj\n"); + return offs; } @@ -2616,22 +2765,23 @@ int* gl2psPrintPDFShaderObjects(int firstObjnumber, int firstOffs){ /* Similar groups of functions for pixmaps and text */ -int gl2psPrintPDFPixmapStreamData(GL2PSimage* im){ +int gl2psPrintPDFPixmapStreamData(GL2PSimage* im, + size_t (*action)(unsigned long data, size_t size)){ int x, y; GLfloat r, g, b; for(y = 0; y < im->height; ++y) for(x = 0; x < im->width; ++x){ gl2psGetRGB(im->pixels, im->width, im->height, x, y, &r, &g, &b); - fputc((int)(r*255),gl2ps->stream); - fputc((int)(g*255),gl2ps->stream); - fputc((int)(b*255),gl2ps->stream); + (*action)((unsigned long)(r*255) << 24,1); + (*action)((unsigned long)(g*255) << 24,1); + (*action)((unsigned long)(b*255) << 24,1); } return 3 * im->width * im->height; } int gl2psPrintPDFPixmap(int obj, GL2PSimage* im){ - int offs = 0; + int offs = 0, done = 0; offs += fprintf(gl2ps->stream, "%d 0 obj\n" @@ -2641,18 +2791,45 @@ int gl2psPrintPDFPixmap(int obj, GL2PSimage* im){ "/Width %d\n" "/Height %d\n" "/ColorSpace /DeviceRGB\n" - "/BitsPerComponent 8\n" - "/Length %d\n" - ">>\n" - "stream\n", - obj, (int)im->width, (int)im->height, - (int)(im->width * im->height * 3)); + "/BitsPerComponent 8\n", + obj, (int)im->width, (int)im->height); + +#ifdef GL2PS_HAVE_ZLIB + if(gl2ps->options & GL2PS_COMPRESS){ + gl2psAllocZstream((int)(im->width * im->height * 3)); + + gl2psPrintPDFPixmapStreamData(im, gl2psWriteBigEndianZ); + + if(Z_OK == gl2psDeflate() && 23 + gl2ps->zstream->destLen < gl2ps->zstream->srcLen){ + offs += gl2psPrintPDFCompressorType(); + offs += fprintf(gl2ps->stream, + "/Length %d " + ">>\n" + "stream\n", + (int)gl2ps->zstream->destLen); + offs += gl2ps->zstream->destLen * fwrite(gl2ps->zstream->dest, gl2ps->zstream->destLen, + 1, gl2ps->stream); + done = 1; + } + gl2psFreeZstream(); + } +#endif - offs += gl2psPrintPDFPixmapStreamData(im); + if(!done){ + /* no compression, or too long after compression, or compress2 error + -> write non-compressed entry */ + offs += fprintf(gl2ps->stream, + "/Length %d " + ">>\n" + "stream\n", + (int)(im->width * im->height * 3)); + offs += gl2psPrintPDFPixmapStreamData(im, gl2psWriteBigEndian); + } offs += fprintf(gl2ps->stream, "\nendstream\n" "endobj\n"); + return offs; } @@ -2788,6 +2965,14 @@ void gl2psPrintPDFFooter(){ for(i = 0; i < gl2psListNbr(gl2ps->slist); ++i) gl2psFreeText(*(GL2PSstring**)gl2psListPointer(gl2ps->slist, i)); gl2psListDelete(gl2ps->slist); + +#ifdef GL2PS_HAVE_ZLIB + if(gl2ps->options & GL2PS_COMPRESS){ + gl2psFreeZstream(); + gl2psFree(gl2ps->zstream); + gl2ps->zstream = NULL; + } +#endif } /* PDF begin viewport */ @@ -2802,7 +2987,7 @@ void gl2psPrintPDFBeginViewport(GLint viewport[4]){ glRenderMode(GL_FEEDBACK); - offs += fprintf(gl2ps->stream, "q\n"); + offs += zprintf("q\n"); if(gl2ps->options & GL2PS_DRAW_BACKGROUND){ if(gl2ps->colormode == GL_RGBA || gl2ps->colorsize == 0){ @@ -2815,16 +3000,14 @@ void gl2psPrintPDFBeginViewport(GLint viewport[4]){ rgba[2] = gl2ps->colormap[index][2]; rgba[3] = 0.; } - offs += fprintf(gl2ps->stream, - "%f %f %f rg\n" + offs += zprintf("%f %f %f rg\n" "%d %d %d %d re\n" "W\n" "f\n", rgba[0], rgba[1], rgba[2], x, y, w, h); } else{ - offs += fprintf(gl2ps->stream, - "%d %d %d %d re\n" + offs += zprintf("%d %d %d %d re\n" "W\n" "n\n", x, y, w, h); @@ -2841,7 +3024,7 @@ GLint gl2psPrintPDFEndViewport(){ res += gl2psFlushPDFTriangles(); res += gl2psFlushPDFLines(); - gl2ps->streamlength += fprintf(gl2ps->stream, "Q\n"); + gl2ps->streamlength += zprintf("Q\n"); return res; } @@ -3024,6 +3207,9 @@ GL2PSDLL_API GLint gl2psBeginPage(const char *title, const char *producer, gl2ps->line_rgb_diff = 1; gl2ps->last_line_finished = 0; gl2ps->last_triangle_finished = 0; +#ifdef GL2PS_HAVE_ZLIB + gl2ps->zstream = NULL; +#endif switch(gl2ps->format){ case GL2PS_TEX : diff --git a/Graphics/gl2ps.h b/Graphics/gl2ps.h index eb1a902c80..1af0c35118 100644 --- a/Graphics/gl2ps.h +++ b/Graphics/gl2ps.h @@ -1,4 +1,4 @@ -/* $Id: gl2ps.h,v 1.44 2003-09-22 07:26:38 geuzaine Exp $ */ +/* $Id: gl2ps.h,v 1.45 2003-10-25 03:26:41 geuzaine Exp $ */ /* * GL2PS, an OpenGL to PostScript Printing Library * Copyright (C) 1999-2003 Christophe Geuzaine <geuz@geuz.org> @@ -50,6 +50,15 @@ # include <GL/gl.h> #endif +/* Support for compressed PDF */ + +#if defined(HAVE_ZLIB) || defined(HAVE_LIBZ) || defined(GL2PS_HAVE_ZLIB) +# include <zlib.h> +# ifndef GL2PS_HAVE_ZLIB +# define GL2PS_HAVE_ZLIB +# endif +#endif + /* Version number */ #define GL2PS_MAJOR_VERSION 1 @@ -62,10 +71,10 @@ /* Output file format */ -#define GL2PS_PS 1 -#define GL2PS_EPS 2 -#define GL2PS_TEX 3 -#define GL2PS_PDF 4 +#define GL2PS_PS 1 +#define GL2PS_EPS 2 +#define GL2PS_TEX 3 +#define GL2PS_PDF 4 /* Sorting algorithms */ @@ -86,7 +95,7 @@ #define GL2PS_NO_PS3_SHADING (1<<7) #define GL2PS_NO_PIXMAP (1<<8) #define GL2PS_USE_CURRENT_VIEWPORT (1<<9) -#define GL2PS_DEFLATE (1<<10) +#define GL2PS_COMPRESS (1<<10) /* Arguments for gl2psEnable/gl2psDisable */ @@ -211,6 +220,13 @@ typedef struct { GL2PSimage *image; } GL2PSprimitive; +#ifdef GL2PS_HAVE_ZLIB +typedef struct { + Bytef* dest, *src, *start; + uLongf destLen, srcLen; +} GL2PSzstream; +#endif + typedef struct { /* general */ GLint format, sort, options, colorsize, colormode, buffersize; @@ -237,6 +253,13 @@ typedef struct { GL2PSlist *tlist, *tidxlist, *ilist, *slist; int lasttype, consec_cnt, consec_inner_cnt; int line_width_diff, line_rgb_diff, last_line_finished, last_triangle_finished; + + /* zlib compression structure */ +#ifdef GL2PS_HAVE_ZLIB + GL2PSzstream *zstream; + char zbuf[1000]; +#endif + } GL2PScontext; /* public functions */ @@ -255,8 +278,6 @@ GL2PSDLL_API GLint gl2psEndPage(void); 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 gl2psTextOpt(const char *str, const char *fontname, GLshort fontsize, - GLint align, GL2PSrgba color); GL2PSDLL_API GLint gl2psDrawPixels(GLsizei width, GLsizei height, GLint xorig, GLint yorig, GLenum format, GLenum type, const void *pixels); @@ -265,6 +286,10 @@ GL2PSDLL_API GLint gl2psDisable(GLint mode); GL2PSDLL_API GLint gl2psPointSize(GLfloat value); GL2PSDLL_API GLint gl2psLineWidth(GLfloat value); +/* Undocumented */ +GL2PSDLL_API GLint gl2psTextOpt(const char *str, const char *fontname, GLshort fontsize, + GLint align, GL2PSrgba color); + #ifdef __cplusplus }; #endif diff --git a/configure b/configure index 45bbf311b7..26b06c7182 100755 --- a/configure +++ b/configure @@ -3219,6 +3219,7 @@ else fi if test "x${Z}" = "xyes"; then + FLAGS="-DHAVE_LIBZ ${FLAGS}" if test "x${PNG_PREFIX}" != "x"; then LDFLAGS="-L${PNG_PREFIX} -L${PNG_PREFIX}/lib ${LDFLAGS}" fi diff --git a/configure.in b/configure.in index 2a3601e10d..156f7b1540 100644 --- a/configure.in +++ b/configure.in @@ -1,4 +1,4 @@ -dnl $Id: configure.in,v 1.40 2003-09-17 18:00:53 geuzaine Exp $ +dnl $Id: configure.in,v 1.41 2003-10-25 03:26:40 geuzaine Exp $ dnl dnl Copyright (C) 1997-2003 C. Geuzaine, J.-F. Remacle dnl @@ -158,6 +158,7 @@ if test "x$enable_gui" != "xno"; then fi AC_CHECK_LIB(z,main,Z="yes",Z="no") if test "x${Z}" = "xyes"; then + FLAGS="-DHAVE_LIBZ ${FLAGS}" dnl Check if libpng is available to enable/disable gl2png if test "x${PNG_PREFIX}" != "x"; then LDFLAGS="-L${PNG_PREFIX} -L${PNG_PREFIX}/lib ${LDFLAGS}" -- GitLab