26 #ifdef G4VIS_BUILD_OPENGL_DRIVER
27 #define G4VIS_BUILD_OPENGL_GL2PS
29 #ifdef G4VIS_BUILD_OI_DRIVER
30 #define G4VIS_BUILD_OPENGL_GL2PS
33 #ifdef G4VIS_BUILD_OPENGL_GL2PS
70 #include "Geant4_gl2ps.h"
74 #include <sys/types.h>
79 #define GL2PS_HAVE_ZLIB
82 #if defined(GL2PS_HAVE_LIBPNG)
95 #define GL2PS_EPSILON 5.0e-3F
96 #define GL2PS_ZSCALE 1000.0F
97 #define GL2PS_ZOFFSET 5.0e-2F
98 #define GL2PS_ZOFFSET_LARGE 20.0F
99 #define GL2PS_ZERO(arg) (std::fabs(arg) < 1.e-20)
103 #define GL2PS_NO_TYPE -1
105 #define GL2PS_POINT 2
107 #define GL2PS_QUADRANGLE 4
108 #define GL2PS_TRIANGLE 5
109 #define GL2PS_PIXMAP 6
110 #define GL2PS_IMAGEMAP 7
111 #define GL2PS_IMAGEMAP_WRITTEN 8
112 #define GL2PS_IMAGEMAP_VISIBLE 9
113 #define GL2PS_SPECIAL 10
117 #define GL2PS_COINCIDENT 1
118 #define GL2PS_IN_FRONT_OF 2
119 #define GL2PS_IN_BACK_OF 3
120 #define GL2PS_SPANNING 4
124 #define GL2PS_POINT_COINCIDENT 0
125 #define GL2PS_POINT_INFRONT 1
126 #define GL2PS_POINT_BACK 2
130 #define GL2PS_BEGIN_OFFSET_TOKEN 1
131 #define GL2PS_END_OFFSET_TOKEN 2
132 #define GL2PS_BEGIN_BOUNDARY_TOKEN 3
133 #define GL2PS_END_BOUNDARY_TOKEN 4
134 #define GL2PS_BEGIN_STIPPLE_TOKEN 5
135 #define GL2PS_END_STIPPLE_TOKEN 6
136 #define GL2PS_POINT_SIZE_TOKEN 7
137 #define GL2PS_LINE_WIDTH_TOKEN 8
138 #define GL2PS_BEGIN_BLEND_TOKEN 9
139 #define GL2PS_END_BLEND_TOKEN 10
140 #define GL2PS_SRC_BLEND_TOKEN 11
141 #define GL2PS_DST_BLEND_TOKEN 12
142 #define GL2PS_IMAGEMAP_TOKEN 13
143 #define GL2PS_DRAW_PIXELS_TOKEN 14
144 #define GL2PS_TEXT_TOKEN 15
151 T_ALPHA_LESS_1 = 1<<3,
153 } GL2PS_TRIANGLE_PROPERTY;
155 typedef GLfloat GL2PSxyz[3];
156 typedef GLfloat GL2PSplane[4];
158 typedef struct _GL2PSbsptree2d GL2PSbsptree2d;
160 struct _GL2PSbsptree2d {
162 GL2PSbsptree2d *front, *back;
166 GLint
nmax, size, incr,
n;
170 typedef struct _GL2PSbsptree GL2PSbsptree;
172 struct _GL2PSbsptree {
174 GL2PSlist *primitives;
175 GL2PSbsptree *front, *back;
184 GL2PSvertex vertex[3];
190 char *str, *fontname;
198 GLsizei
width, height;
206 typedef struct _GL2PSimagemap GL2PSimagemap;
208 struct _GL2PSimagemap {
214 GLshort type, numverts;
216 char boundary, offset, culled;
227 #if defined(GL2PS_HAVE_ZLIB)
228 Bytef *dest, *src, *start;
229 uLongf destLen, srcLen;
237 int gsno, fontno, imno, shno, maskshno, trgroupno;
238 int gsobjno, fontobjno, imobjno, shobjno, maskshobjno, trgroupobjno;
243 GLint format, sort, options, colorsize, colormode, buffersize;
244 char *title, *producer, *filename;
245 GLboolean boundary, blending;
246 GLfloat *feedback, offset[2], lastlinewidth;
247 GLint viewport[4], blendfunc[2], lastfactor;
248 GL2PSrgba *colormap, lastrgba, threshold, bgcolor;
249 GLushort lastpattern;
250 GL2PSvertex lastvertex;
251 GL2PSlist *primitives, *auxprimitives;
260 GLboolean zerosurfacearea;
261 GL2PSbsptree2d *imagetree;
262 GL2PSprimitive *primitivetoadd;
266 GL2PSlist *pdfprimlist, *pdfgrouplist;
272 int trgroupobjects_stack;
277 GL2PSimagemap *imagemap_head;
278 GL2PSimagemap *imagemap_tail;
282 void (*printHeader)(void);
283 void (*printFooter)(void);
284 void (*beginViewport)(GLint viewport[4]);
285 GLint (*endViewport)(void);
286 void (*printPrimitive)(
void *data);
287 void (*printFinalPrimitive)(void);
288 const char *file_extension;
289 const char *description;
295 static GL2PScontext *gl2ps = NULL;
299 static GLint gl2psPrintPrimitives(
void);
307 static void gl2psMsg(GLint level,
const char *fmt, ...)
311 if(!(gl2ps->options & GL2PS_SILENT)){
313 case GL2PS_INFO : fprintf(stderr,
"GL2PS info: ");
break;
314 case GL2PS_WARNING : fprintf(stderr,
"GL2PS warning: ");
break;
315 case GL2PS_ERROR : fprintf(stderr,
"GL2PS error: ");
break;
318 vfprintf(stderr, fmt, args);
320 fprintf(stderr,
"\n");
325 static void *gl2psMalloc(
size_t size)
329 if(!size)
return NULL;
332 gl2psMsg(GL2PS_ERROR,
"Couldn't allocate requested memory");
338 static void *gl2psRealloc(
void *ptr,
size_t size)
340 if(!size)
return NULL;
341 ptr = realloc(ptr, size);
343 gl2psMsg(GL2PS_ERROR,
"Couldn't reallocate requested memory");
349 static void gl2psFree(
void *ptr)
355 static size_t gl2psWriteBigEndian(
unsigned long data,
size_t bytes)
358 size_t size =
sizeof(
unsigned long);
359 for(i = 1; i <= bytes; ++i){
360 fputc(0xff & (data >> (size-i) * 8), gl2ps->stream);
367 #if defined(GL2PS_HAVE_ZLIB)
369 static void gl2psSetupCompress(
void)
371 gl2ps->compress = (GL2PScompress*)gl2psMalloc(
sizeof(GL2PScompress));
372 gl2ps->compress->src = NULL;
373 gl2ps->compress->start = NULL;
374 gl2ps->compress->dest = NULL;
375 gl2ps->compress->srcLen = 0;
376 gl2ps->compress->destLen = 0;
379 static void gl2psFreeCompress(
void)
383 gl2psFree(gl2ps->compress->start);
384 gl2psFree(gl2ps->compress->dest);
385 gl2ps->compress->src = NULL;
386 gl2ps->compress->start = NULL;
387 gl2ps->compress->dest = NULL;
388 gl2ps->compress->srcLen = 0;
389 gl2ps->compress->destLen = 0;
392 static int gl2psAllocCompress(
unsigned int srcsize)
396 if(!gl2ps->compress || !srcsize)
399 gl2ps->compress->srcLen = srcsize;
400 gl2ps->compress->destLen = (int)ceil(1.001 * gl2ps->compress->srcLen + 12);
401 gl2ps->compress->src = (Bytef*)gl2psMalloc(gl2ps->compress->srcLen);
402 gl2ps->compress->start = gl2ps->compress->src;
403 gl2ps->compress->dest = (Bytef*)gl2psMalloc(gl2ps->compress->destLen);
405 return GL2PS_SUCCESS;
408 static void *gl2psReallocCompress(
unsigned int srcsize)
410 if(!gl2ps->compress || !srcsize)
413 if(srcsize < gl2ps->
compress->srcLen)
414 return gl2ps->compress->start;
416 gl2ps->compress->srcLen = srcsize;
417 gl2ps->compress->destLen = (int)ceil(1.001 * gl2ps->compress->srcLen + 12);
418 gl2ps->compress->src = (Bytef*)gl2psRealloc(gl2ps->compress->src,
419 gl2ps->compress->srcLen);
420 gl2ps->compress->start = gl2ps->compress->src;
421 gl2ps->compress->dest = (Bytef*)gl2psRealloc(gl2ps->compress->dest,
422 gl2ps->compress->destLen);
424 return gl2ps->compress->start;
427 static size_t gl2psWriteBigEndianCompress(
unsigned long data,
size_t bytes)
430 size_t size =
sizeof(
unsigned long);
431 for(i = 1; i <= bytes; ++i){
432 *gl2ps->compress->src = (Bytef)(0xff & (data >> (size-i) * 8));
433 ++gl2ps->compress->src;
438 static int gl2psDeflate(
void)
442 return compress(gl2ps->compress->dest, &gl2ps->compress->destLen,
443 gl2ps->compress->start, gl2ps->compress->srcLen);
448 static int gl2psPrintf(
const char* fmt, ...)
453 #if defined(GL2PS_HAVE_ZLIB)
454 unsigned int oldsize = 0;
455 static char buf[1000];
456 if(gl2ps->options & GL2PS_COMPRESS){
458 ret = vsprintf(buf, fmt, args);
460 oldsize = gl2ps->compress->srcLen;
461 gl2ps->compress->start = (Bytef*)gl2psReallocCompress(oldsize + ret);
462 memcpy(gl2ps->compress->start+oldsize, buf, ret);
468 ret = vfprintf(gl2ps->stream, fmt, args);
470 #if defined(GL2PS_HAVE_ZLIB)
476 static void gl2psPrintGzipHeader()
478 #if defined(GL2PS_HAVE_ZLIB)
479 char tmp[10] = {
'\x1f',
'\x8b',
486 if(gl2ps->options & GL2PS_COMPRESS){
487 gl2psSetupCompress();
489 fwrite(tmp, 10, 1, gl2ps->stream);
494 static void gl2psPrintGzipFooter()
496 #if defined(GL2PS_HAVE_ZLIB)
501 if(gl2ps->options & GL2PS_COMPRESS){
502 if(Z_OK != gl2psDeflate()){
503 gl2psMsg(GL2PS_ERROR,
"Zlib deflate error");
508 if(gl2ps->compress->dest[1] & (1<<5)){
512 fwrite(gl2ps->compress->dest+n, gl2ps->compress->destLen-(n+4),
515 crc =
crc32(0
L, gl2ps->compress->start, gl2ps->compress->srcLen);
516 for(n = 0; n < 4; ++
n){
517 tmp[
n] = (char)(crc & 0xff);
520 len = gl2ps->compress->srcLen;
521 for(n = 4; n < 8; ++
n){
522 tmp[
n] = (char)(len & 0xff);
525 fwrite(tmp, 8, 1, gl2ps->stream);
528 gl2psFree(gl2ps->compress);
529 gl2ps->compress = NULL;
536 static void gl2psListRealloc(GL2PSlist *list, GLint n)
539 gl2psMsg(GL2PS_ERROR,
"Cannot reallocate NULL list");
545 list->array = (
char*)gl2psMalloc(list->nmax * list->size);
549 list->nmax = ((n - 1) / list->incr + 1) * list->incr;
550 list->array = (
char*)gl2psRealloc(list->array,
551 list->nmax * list->size);
556 static GL2PSlist *gl2psListCreate(GLint n, GLint incr, GLint size)
561 if(incr <= 0) incr = 1;
562 list = (GL2PSlist*)gl2psMalloc(
sizeof(GL2PSlist));
568 gl2psListRealloc(list, n);
572 static void gl2psListReset(GL2PSlist *list)
578 static void gl2psListDelete(GL2PSlist *list)
581 gl2psFree(list->array);
585 static void gl2psListAdd(GL2PSlist *list,
void *data)
588 gl2psMsg(GL2PS_ERROR,
"Cannot add into unallocated list");
592 gl2psListRealloc(list, list->n);
593 memcpy(&list->array[(list->n - 1) * list->size], data, list->size);
596 static int gl2psListNbr(GL2PSlist *list)
603 static void *gl2psListPointer(GL2PSlist *list, GLint index)
606 gl2psMsg(GL2PS_ERROR,
"Cannot point into unallocated list");
609 if((index < 0) || (index >= list->n)){
610 gl2psMsg(GL2PS_ERROR,
"Wrong list index in gl2psListPointer");
613 return &list->array[index * list->size];
616 static void gl2psListSort(GL2PSlist *list,
617 int (*fcmp)(
const void *
a,
const void *b))
621 qsort(list->array, list->n, list->size, fcmp);
624 static void gl2psListAction(GL2PSlist *list,
void (*action)(
void *data))
628 for(i = 0; i < gl2psListNbr(list); i++){
629 (*action)(gl2psListPointer(list, i));
633 static void gl2psListActionInverse(GL2PSlist *list,
void (*action)(
void *data))
637 for(i = gl2psListNbr(list); i > 0; i--){
638 (*action)(gl2psListPointer(list, i-1));
642 #if defined(GL2PS_HAVE_LIBPNG)
644 static void gl2psListRead(GL2PSlist *list,
int index,
void *data)
646 if((index < 0) || (index >= list->n))
647 gl2psMsg(GL2PS_ERROR,
"Wrong list index in gl2psListRead");
648 memcpy(data, &list->array[index * list->size], list->size);
651 static void gl2psEncodeBase64Block(
unsigned char in[3],
unsigned char out[4],
int len)
653 static const char cb64[] =
654 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
656 out[0] = cb64[ in[0] >> 2 ];
657 out[1] = cb64[ ((in[0] & 0x03) << 4) | ((in[1] & 0xf0) >> 4) ];
658 out[2] = (len > 1) ? cb64[ ((in[1] & 0x0f) << 2) | ((in[2] & 0xc0) >> 6) ] :
'=';
659 out[3] = (len > 2) ? cb64[ in[2] & 0x3f ] :
'=';
662 static void gl2psListEncodeBase64(GL2PSlist *list)
664 unsigned char *
buffer, in[3], out[4];
665 int i,
n, index, len;
667 n = list->n * list->size;
668 buffer = (
unsigned char*)gl2psMalloc(n *
sizeof(
unsigned char));
669 memcpy(buffer, list->array, n *
sizeof(
unsigned char));
670 gl2psListReset(list);
675 for(i = 0; i < 3; i++) {
677 in[i] = buffer[index];
686 gl2psEncodeBase64Block(in, out, len);
687 for(i = 0; i < 4; i++)
688 gl2psListAdd(list, &out[i]);
698 static GLboolean gl2psSameColor(GL2PSrgba rgba1, GL2PSrgba rgba2)
700 if(!GL2PS_ZERO(rgba1[0] - rgba2[0]) ||
701 !GL2PS_ZERO(rgba1[1] - rgba2[1]) ||
702 !GL2PS_ZERO(rgba1[2] - rgba2[2]))
707 static GLboolean gl2psVertsSameColor(
const GL2PSprimitive *prim)
711 for(i = 1; i < prim->numverts; i++){
712 if(!gl2psSameColor(prim->verts[0].rgba, prim->verts[i].rgba)){
719 static GLboolean gl2psSameColorThreshold(
int n, GL2PSrgba rgba[],
724 if(n < 2)
return GL_TRUE;
726 for(i = 1; i <
n; i++){
727 if(std::fabs(rgba[0][0] - rgba[i][0]) > threshold[0] ||
728 std::fabs(rgba[0][1] - rgba[i][1]) > threshold[1] ||
729 std::fabs(rgba[0][2] - rgba[i][2]) > threshold[2])
736 static void gl2psSetLastColor(GL2PSrgba rgba)
739 for(i = 0; i < 3; ++i){
740 gl2ps->lastrgba[i] = rgba[i];
744 static GLfloat gl2psGetRGB(GL2PSimage *im, GLuint x, GLuint y,
745 GLfloat *
red, GLfloat *green, GLfloat *
blue)
748 GLsizei
width = im->width;
749 GLsizei height = im->height;
750 GLfloat *pixels = im->pixels;
756 pimag = pixels + 4 * (width * (height - 1 - y) + x);
760 pimag = pixels + 3 * (width * (height - 1 - y) + x);
763 *
red = *pimag; pimag++;
764 *green = *pimag; pimag++;
765 *
blue = *pimag; pimag++;
767 return (im->format == GL_RGBA) ? *pimag : 1.0F;
772 static GL2PSimage *gl2psCopyPixmap(GL2PSimage *im)
775 GL2PSimage *image = (GL2PSimage*)gl2psMalloc(
sizeof(GL2PSimage));
777 image->width = im->width;
778 image->height = im->height;
779 image->format = im->format;
780 image->type = im->type;
782 switch(image->format){
784 size = image->height * image->width * 4 *
sizeof(GLfloat);
788 size = image->height * image->width * 3 *
sizeof(GLfloat);
792 image->pixels = (GLfloat*)gl2psMalloc(size);
793 memcpy(image->pixels, im->pixels, size);
798 static void gl2psFreePixmap(GL2PSimage *im)
802 gl2psFree(im->pixels);
806 #if defined(GL2PS_HAVE_LIBPNG)
808 #if !defined(png_jmpbuf)
809 # define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf)
812 static void gl2psUserWritePNG(png_structp png_ptr, png_bytep data, png_size_t length)
815 GL2PSlist *png = (GL2PSlist*)png_get_io_ptr(png_ptr);
816 for(i = 0; i < length; i++)
817 gl2psListAdd(png, &data[i]);
820 static void gl2psUserFlushPNG(png_structp png_ptr)
824 static void gl2psConvertPixmapToPNG(GL2PSimage *pixmap, GL2PSlist *png)
828 unsigned char *row_data;
832 if(!(png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL)))
835 if(!(info_ptr = png_create_info_struct(png_ptr))){
836 png_destroy_write_struct(&png_ptr, NULL);
840 if(setjmp(png_jmpbuf(png_ptr))) {
841 png_destroy_write_struct(&png_ptr, &info_ptr);
845 png_set_write_fn(png_ptr, (
void *)png, gl2psUserWritePNG, gl2psUserFlushPNG);
846 png_set_compression_level(png_ptr, Z_DEFAULT_COMPRESSION);
847 png_set_IHDR(png_ptr, info_ptr, pixmap->width, pixmap->height, 8,
848 PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE,
849 PNG_FILTER_TYPE_BASE);
850 png_write_info(png_ptr, info_ptr);
852 row_data = (
unsigned char*)gl2psMalloc(3 * pixmap->width *
sizeof(
unsigned char));
853 for(row = 0; row < pixmap->height; row++){
854 for(col = 0; col < pixmap->width; col++){
855 gl2psGetRGB(pixmap, col, row, &dr, &dg, &db);
856 row_data[3*col] = (
unsigned char)(255. * dr);
857 row_data[3*col+1] = (
unsigned char)(255. * dg);
858 row_data[3*col+2] = (
unsigned char)(255. * db);
860 png_write_row(png_ptr, (png_bytep)row_data);
864 png_write_end(png_ptr, info_ptr);
865 png_destroy_write_struct(&png_ptr, &info_ptr);
872 static GLint gl2psAddText(GLint type,
const char *str,
const char *fontname,
873 GLshort fontsize, GLint alignment, GLfloat angle)
876 GL2PSprimitive *prim;
879 if(!gl2ps || !str || !fontname)
return GL2PS_UNINITIALIZED;
881 if(gl2ps->options & GL2PS_NO_TEXT)
return GL2PS_SUCCESS;
883 glGetBooleanv(GL_CURRENT_RASTER_POSITION_VALID, &valid);
884 if(GL_FALSE == valid)
return GL2PS_SUCCESS;
886 glGetFloatv(GL_CURRENT_RASTER_POSITION, pos);
888 prim = (GL2PSprimitive*)gl2psMalloc(
sizeof(GL2PSprimitive));
892 prim->verts = (GL2PSvertex*)gl2psMalloc(
sizeof(GL2PSvertex));
893 prim->verts[0].xyz[0] = pos[0];
894 prim->verts[0].xyz[1] = pos[1];
895 prim->verts[0].xyz[2] = pos[2];
901 glGetFloatv(GL_CURRENT_RASTER_COLOR, prim->verts[0].rgba);
902 prim->data.text = (GL2PSstring*)gl2psMalloc(
sizeof(GL2PSstring));
903 prim->data.text->str = (
char*)gl2psMalloc((strlen(str)+1)*
sizeof(
char));
904 strcpy(prim->data.text->str, str);
905 prim->data.text->fontname = (
char*)gl2psMalloc((strlen(fontname)+1)*
sizeof(char));
906 strcpy(prim->data.text->fontname, fontname);
907 prim->data.text->fontsize = fontsize;
908 prim->data.text->alignment = alignment;
909 prim->data.text->angle = angle;
911 gl2psListAdd(gl2ps->auxprimitives, &prim);
912 glPassThrough(GL2PS_TEXT_TOKEN);
914 return GL2PS_SUCCESS;
917 static GL2PSstring *gl2psCopyText(GL2PSstring *t)
919 GL2PSstring *text = (GL2PSstring*)gl2psMalloc(
sizeof(GL2PSstring));
920 text->str = (
char*)gl2psMalloc((strlen(t->str)+1)*
sizeof(
char));
921 strcpy(text->str, t->str);
922 text->fontname = (
char*)gl2psMalloc((strlen(t->fontname)+1)*
sizeof(char));
923 strcpy(text->fontname, t->fontname);
924 text->fontsize = t->fontsize;
925 text->alignment = t->alignment;
926 text->angle = t->angle;
931 static void gl2psFreeText(GL2PSstring *text)
935 gl2psFree(text->str);
936 gl2psFree(text->fontname);
942 static GLboolean gl2psSupportedBlendMode(GLenum sfactor, GLenum dfactor)
947 if( (sfactor == GL_SRC_ALPHA && dfactor == GL_ONE_MINUS_SRC_ALPHA) ||
948 (sfactor == GL_ONE && dfactor == GL_ZERO) )
953 static void gl2psAdaptVertexForBlending(GL2PSvertex *v)
963 if(gl2ps->options & GL2PS_NO_BLENDING || !gl2ps->blending){
968 switch(gl2ps->blendfunc[0]){
977 static void gl2psAssignTriangleProperties(GL2PStriangle *t)
981 t->prop = T_VAR_COLOR;
998 if(!GL2PS_ZERO(t->vertex[0].rgba[3] - t->vertex[1].rgba[3]) ||
999 !GL2PS_ZERO(t->vertex[1].rgba[3] - t->vertex[2].rgba[3])){
1000 t->prop |= T_VAR_ALPHA;
1003 if(t->vertex[0].rgba[3] < 1)
1004 t->prop |= T_ALPHA_LESS_1;
1006 t->prop |= T_ALPHA_1;
1010 static void gl2psFillTriangleFromPrimitive(GL2PStriangle *t, GL2PSprimitive *p,
1011 GLboolean assignprops)
1013 t->vertex[0] = p->verts[0];
1014 t->vertex[1] = p->verts[1];
1015 t->vertex[2] = p->verts[2];
1016 if(GL_TRUE == assignprops)
1017 gl2psAssignTriangleProperties(t);
1020 static void gl2psInitTriangle(GL2PStriangle *t)
1023 GL2PSvertex vertex = { {-1.0F, -1.0F, -1.0F}, {-1.0F, -1.0F, -1.0F, -1.0F} };
1024 for(i = 0; i < 3; i++)
1025 t->vertex[i] = vertex;
1026 t->prop = T_UNDEFINED;
1031 static GL2PSprimitive *gl2psCopyPrimitive(GL2PSprimitive *p)
1033 GL2PSprimitive *prim;
1036 gl2psMsg(GL2PS_ERROR,
"Trying to copy an empty primitive");
1040 prim = (GL2PSprimitive*)gl2psMalloc(
sizeof(GL2PSprimitive));
1042 prim->type = p->type;
1043 prim->numverts = p->numverts;
1044 prim->boundary = p->boundary;
1045 prim->offset = p->offset;
1046 prim->pattern = p->pattern;
1047 prim->factor = p->factor;
1048 prim->culled = p->culled;
1049 prim->width = p->width;
1050 prim->verts = (GL2PSvertex*)gl2psMalloc(p->numverts*
sizeof(GL2PSvertex));
1051 memcpy(prim->verts, p->verts, p->numverts *
sizeof(GL2PSvertex));
1055 prim->data.image = gl2psCopyPixmap(p->data.image);
1058 case GL2PS_SPECIAL :
1059 prim->data.text = gl2psCopyText(p->data.text);
1068 static GLboolean gl2psSamePosition(GL2PSxyz p1, GL2PSxyz p2)
1070 if(!GL2PS_ZERO(p1[0] - p2[0]) ||
1071 !GL2PS_ZERO(p1[1] - p2[1]) ||
1072 !GL2PS_ZERO(p1[2] - p2[2]))
1083 static GLfloat gl2psComparePointPlane(GL2PSxyz point, GL2PSplane plane)
1085 return (plane[0] * point[0] +
1086 plane[1] * point[1] +
1087 plane[2] * point[2] +
1091 static GLfloat gl2psPsca(GLfloat *a, GLfloat *b)
1093 return (a[0]*b[0] + a[1]*b[1] + a[2]*b[2]);
1096 static void gl2psPvec(GLfloat *a, GLfloat *b, GLfloat *c)
1098 c[0] = a[1]*b[2] - a[2]*b[1];
1099 c[1] = a[2]*b[0] - a[0]*b[2];
1100 c[2] = a[0]*b[1] - a[1]*b[0];
1103 static GLfloat gl2psNorm(GLfloat *a)
1105 return (GLfloat)sqrt(a[0]*a[0] + a[1]*a[1] + a[2]*a[2]);
1108 static void gl2psGetNormal(GLfloat *a, GLfloat *b, GLfloat *c)
1113 if(!GL2PS_ZERO(norm = gl2psNorm(c))){
1127 static void gl2psGetPlane(GL2PSprimitive *prim, GL2PSplane plane)
1129 GL2PSxyz v = {0.0F, 0.0F, 0.0F}, w = {0.0F, 0.0F, 0.0F};
1132 case GL2PS_TRIANGLE :
1133 case GL2PS_QUADRANGLE :
1134 v[0] = prim->verts[1].xyz[0] - prim->verts[0].xyz[0];
1135 v[1] = prim->verts[1].xyz[1] - prim->verts[0].xyz[1];
1136 v[2] = prim->verts[1].xyz[2] - prim->verts[0].xyz[2];
1137 w[0] = prim->verts[2].xyz[0] - prim->verts[0].xyz[0];
1138 w[1] = prim->verts[2].xyz[1] - prim->verts[0].xyz[1];
1139 w[2] = prim->verts[2].xyz[2] - prim->verts[0].xyz[2];
1140 if((GL2PS_ZERO(v[0]) && GL2PS_ZERO(v[1]) && GL2PS_ZERO(v[2])) ||
1141 (GL2PS_ZERO(w[0]) && GL2PS_ZERO(w[1]) && GL2PS_ZERO(w[2]))){
1142 plane[0] = plane[1] = 0.0F;
1144 plane[3] = -prim->verts[0].xyz[2];
1147 gl2psGetNormal(v, w, plane);
1149 - plane[0] * prim->verts[0].xyz[0]
1150 - plane[1] * prim->verts[0].xyz[1]
1151 - plane[2] * prim->verts[0].xyz[2];
1155 v[0] = prim->verts[1].xyz[0] - prim->verts[0].xyz[0];
1156 v[1] = prim->verts[1].xyz[1] - prim->verts[0].xyz[1];
1157 v[2] = prim->verts[1].xyz[2] - prim->verts[0].xyz[2];
1158 if(GL2PS_ZERO(v[0]) && GL2PS_ZERO(v[1]) && GL2PS_ZERO(v[2])){
1159 plane[0] = plane[1] = 0.0F;
1161 plane[3] = -prim->verts[0].xyz[2];
1164 if(GL2PS_ZERO(v[0])) w[0] = 1.0F;
1165 else if(GL2PS_ZERO(v[1])) w[1] = 1.0F;
1167 gl2psGetNormal(v, w, plane);
1169 - plane[0] * prim->verts[0].xyz[0]
1170 - plane[1] * prim->verts[0].xyz[1]
1171 - plane[2] * prim->verts[0].xyz[2];
1177 case GL2PS_SPECIAL :
1178 case GL2PS_IMAGEMAP:
1179 plane[0] = plane[1] = 0.0F;
1181 plane[3] = -prim->verts[0].xyz[2];
1184 gl2psMsg(GL2PS_ERROR,
"Unknown primitive type in BSP tree");
1185 plane[0] = plane[1] = plane[3] = 0.0F;
1191 static void gl2psCutEdge(GL2PSvertex *a, GL2PSvertex *b, GL2PSplane plane,
1197 v[0] = b->xyz[0] - a->xyz[0];
1198 v[1] = b->xyz[1] - a->xyz[1];
1199 v[2] = b->xyz[2] - a->xyz[2];
1201 if(!GL2PS_ZERO(psca = gl2psPsca(plane, v)))
1202 sect = -gl2psComparePointPlane(a->xyz, plane) / psca;
1206 c->xyz[0] = a->xyz[0] + v[0] * sect;
1207 c->xyz[1] = a->xyz[1] + v[1] * sect;
1208 c->xyz[2] = a->xyz[2] + v[2] * sect;
1210 c->rgba[0] = (1 - sect) * a->rgba[0] + sect * b->rgba[0];
1211 c->rgba[1] = (1 - sect) * a->rgba[1] + sect * b->rgba[1];
1212 c->rgba[2] = (1 - sect) * a->rgba[2] + sect * b->rgba[2];
1213 c->rgba[3] = (1 - sect) * a->rgba[3] + sect * b->rgba[3];
1216 static void gl2psCreateSplitPrimitive(GL2PSprimitive *parent, GL2PSplane plane,
1217 GL2PSprimitive *child, GLshort numverts,
1218 GLshort *index0, GLshort *index1)
1222 if(parent->type == GL2PS_IMAGEMAP){
1223 child->type = GL2PS_IMAGEMAP;
1224 child->data.image = parent->data.image;
1228 gl2psMsg(GL2PS_WARNING,
"%d vertices in polygon", numverts);
1232 case 1 : child->type = GL2PS_POINT;
break;
1233 case 2 : child->type = GL2PS_LINE;
break;
1234 case 3 : child->type = GL2PS_TRIANGLE;
break;
1235 case 4 : child->type = GL2PS_QUADRANGLE;
break;
1236 default: child->type = GL2PS_NO_TYPE;
break;
1240 child->boundary = 0;
1241 child->culled = parent->culled;
1242 child->offset = parent->offset;
1243 child->pattern = parent->pattern;
1244 child->factor = parent->factor;
1245 child->width = parent->width;
1246 child->numverts = numverts;
1247 child->verts = (GL2PSvertex*)gl2psMalloc(numverts *
sizeof(GL2PSvertex));
1249 for(i = 0; i < numverts; i++){
1251 child->verts[i] = parent->verts[index0[i]];
1254 gl2psCutEdge(&parent->verts[index0[i]], &parent->verts[index1[i]],
1255 plane, &child->verts[i]);
1260 static void gl2psAddIndex(GLshort *index0, GLshort *index1, GLshort *nb,
1261 GLshort i, GLshort j)
1265 for(k = 0; k < *nb; k++){
1266 if((index0[k] == i && index1[k] == j) ||
1267 (index1[k] == i && index0[k] == j))
return;
1274 static GLshort gl2psGetIndex(GLshort i, GLshort num)
1276 return (i < num - 1) ? i + 1 : 0;
1279 static GLint gl2psTestSplitPrimitive(GL2PSprimitive *prim, GL2PSplane plane)
1281 GLint type = GL2PS_COINCIDENT;
1285 for(i = 0; i < prim->numverts; i++){
1286 d[i] = gl2psComparePointPlane(prim->verts[i].xyz, plane);
1289 if(prim->numverts < 2){
1293 for(i = 0; i < prim->numverts; i++){
1294 j = gl2psGetIndex(i, prim->numverts);
1295 if(d[j] > GL2PS_EPSILON){
1296 if(type == GL2PS_COINCIDENT) type = GL2PS_IN_BACK_OF;
1297 else if(type != GL2PS_IN_BACK_OF)
return 1;
1298 if(d[i] < -GL2PS_EPSILON)
return 1;
1300 else if(d[j] < -GL2PS_EPSILON){
1301 if(type == GL2PS_COINCIDENT) type = GL2PS_IN_FRONT_OF;
1302 else if(type != GL2PS_IN_FRONT_OF)
return 1;
1303 if(d[i] > GL2PS_EPSILON)
return 1;
1310 static GLint gl2psSplitPrimitive(GL2PSprimitive *prim, GL2PSplane plane,
1311 GL2PSprimitive **front, GL2PSprimitive **back)
1313 GLshort i, j, in = 0, out = 0, in0[5], in1[5], out0[5], out1[5];
1317 type = GL2PS_COINCIDENT;
1319 for(i = 0; i < prim->numverts; i++){
1320 d[i] = gl2psComparePointPlane(prim->verts[i].xyz, plane);
1325 if(d[0] > GL2PS_EPSILON) type = GL2PS_IN_BACK_OF;
1326 else if(d[0] < -GL2PS_EPSILON) type = GL2PS_IN_FRONT_OF;
1327 else type = GL2PS_COINCIDENT;
1330 for(i = 0; i < prim->numverts; i++){
1331 j = gl2psGetIndex(i, prim->numverts);
1332 if(d[j] > GL2PS_EPSILON){
1333 if(type == GL2PS_COINCIDENT) type = GL2PS_IN_BACK_OF;
1334 else if(type != GL2PS_IN_BACK_OF) type = GL2PS_SPANNING;
1335 if(d[i] < -GL2PS_EPSILON){
1336 gl2psAddIndex(in0, in1, &in, i, j);
1337 gl2psAddIndex(out0, out1, &out, i, j);
1338 type = GL2PS_SPANNING;
1340 gl2psAddIndex(out0, out1, &out, j, -1);
1342 else if(d[j] < -GL2PS_EPSILON){
1343 if(type == GL2PS_COINCIDENT) type = GL2PS_IN_FRONT_OF;
1344 else if(type != GL2PS_IN_FRONT_OF) type = GL2PS_SPANNING;
1345 if(d[i] > GL2PS_EPSILON){
1346 gl2psAddIndex(in0, in1, &in, i, j);
1347 gl2psAddIndex(out0, out1, &out, i, j);
1348 type = GL2PS_SPANNING;
1350 gl2psAddIndex(in0, in1, &in, j, -1);
1353 gl2psAddIndex(in0, in1, &in, j, -1);
1354 gl2psAddIndex(out0, out1, &out, j, -1);
1360 if(type == GL2PS_SPANNING){
1361 *back = (GL2PSprimitive*)gl2psMalloc(
sizeof(GL2PSprimitive));
1362 *front = (GL2PSprimitive*)gl2psMalloc(
sizeof(GL2PSprimitive));
1363 gl2psCreateSplitPrimitive(prim, plane, *back, out, out0, out1);
1364 gl2psCreateSplitPrimitive(prim, plane, *front, in, in0, in1);
1370 static void gl2psDivideQuad(GL2PSprimitive *quad,
1371 GL2PSprimitive **t1, GL2PSprimitive **t2)
1373 *t1 = (GL2PSprimitive*)gl2psMalloc(
sizeof(GL2PSprimitive));
1374 *t2 = (GL2PSprimitive*)gl2psMalloc(
sizeof(GL2PSprimitive));
1375 (*t1)->type = (*t2)->type = GL2PS_TRIANGLE;
1376 (*t1)->numverts = (*t2)->numverts = 3;
1377 (*t1)->culled = (*t2)->culled = quad->culled;
1378 (*t1)->offset = (*t2)->offset = quad->offset;
1379 (*t1)->pattern = (*t2)->pattern = quad->pattern;
1380 (*t1)->factor = (*t2)->factor = quad->factor;
1381 (*t1)->width = (*t2)->width = quad->width;
1382 (*t1)->verts = (GL2PSvertex*)gl2psMalloc(3 *
sizeof(GL2PSvertex));
1383 (*t2)->verts = (GL2PSvertex*)gl2psMalloc(3 *
sizeof(GL2PSvertex));
1384 (*t1)->verts[0] = quad->verts[0];
1385 (*t1)->verts[1] = quad->verts[1];
1386 (*t1)->verts[2] = quad->verts[2];
1387 (*t1)->boundary = ((quad->boundary & 1) ? 1 : 0) | ((quad->boundary & 2) ? 2 : 0);
1388 (*t2)->verts[0] = quad->verts[0];
1389 (*t2)->verts[1] = quad->verts[2];
1390 (*t2)->verts[2] = quad->verts[3];
1391 (*t2)->boundary = ((quad->boundary & 4) ? 2 : 0) | ((quad->boundary & 4) ? 2 : 0);
1394 static int gl2psCompareDepth(
const void *a,
const void *b)
1396 GL2PSprimitive *q, *w;
1397 GLfloat dq = 0.0F, dw = 0.0F, diff;
1400 q = *(GL2PSprimitive**)a;
1401 w = *(GL2PSprimitive**)b;
1403 for(i = 0; i < q->numverts; i++){
1404 dq += q->verts[i].xyz[2];
1406 dq /= (GLfloat)q->numverts;
1408 for(i = 0; i < w->numverts; i++){
1409 dw += w->verts[i].xyz[2];
1411 dw /= (GLfloat)w->numverts;
1425 static int gl2psTrianglesFirst(
const void *a,
const void *b)
1427 GL2PSprimitive *q, *w;
1429 q = *(GL2PSprimitive**)a;
1430 w = *(GL2PSprimitive**)b;
1431 return (q->type < w->type ? 1 : -1);
1434 static GLint gl2psFindRoot(GL2PSlist *primitives, GL2PSprimitive **root)
1436 GLint i, j, count, best = 1000000, index = 0;
1437 GL2PSprimitive *prim1, *prim2;
1441 if(!gl2psListNbr(primitives)){
1442 gl2psMsg(GL2PS_ERROR,
"Cannot fint root in empty primitive list");
1446 *root = *(GL2PSprimitive**)gl2psListPointer(primitives, 0);
1448 if(gl2ps->options & GL2PS_BEST_ROOT){
1449 maxp = gl2psListNbr(primitives);
1450 if(maxp > gl2ps->maxbestroot){
1451 maxp = gl2ps->maxbestroot;
1453 for(i = 0; i < maxp; i++){
1454 prim1 = *(GL2PSprimitive**)gl2psListPointer(primitives, i);
1455 gl2psGetPlane(prim1, plane);
1457 for(j = 0; j < gl2psListNbr(primitives); j++){
1459 prim2 = *(GL2PSprimitive**)gl2psListPointer(primitives, j);
1460 count += gl2psTestSplitPrimitive(prim2, plane);
1462 if(count > best)
break;
1468 if(!count)
return index;
1479 static void gl2psFreeImagemap(GL2PSimagemap *list)
1481 GL2PSimagemap *next;
1482 while(list != NULL){
1484 gl2psFree(list->image->pixels);
1485 gl2psFree(list->image);
1491 static void gl2psFreePrimitive(
void *data)
1495 q = *(GL2PSprimitive**)data;
1496 gl2psFree(q->verts);
1497 if(q->type == GL2PS_TEXT || q->type == GL2PS_SPECIAL){
1498 gl2psFreeText(q->data.text);
1500 else if(q->type == GL2PS_PIXMAP){
1501 gl2psFreePixmap(q->data.image);
1506 static void gl2psAddPrimitiveInList(GL2PSprimitive *prim, GL2PSlist *list)
1508 GL2PSprimitive *t1, *t2;
1510 if(prim->type != GL2PS_QUADRANGLE){
1511 gl2psListAdd(list, &prim);
1514 gl2psDivideQuad(prim, &t1, &t2);
1515 gl2psListAdd(list, &t1);
1516 gl2psListAdd(list, &t2);
1517 gl2psFreePrimitive(&prim);
1522 static void gl2psFreeBspTree(GL2PSbsptree **tree)
1525 if((*tree)->back) gl2psFreeBspTree(&(*tree)->back);
1526 if((*tree)->primitives){
1527 gl2psListAction((*tree)->primitives, gl2psFreePrimitive);
1528 gl2psListDelete((*tree)->primitives);
1530 if((*tree)->front) gl2psFreeBspTree(&(*tree)->front);
1536 static GLboolean gl2psGreater(GLfloat
f1, GLfloat
f2)
1538 if(f1 > f2)
return GL_TRUE;
1539 else return GL_FALSE;
1542 static GLboolean gl2psLess(GLfloat f1, GLfloat f2)
1544 if(f1 < f2)
return GL_TRUE;
1545 else return GL_FALSE;
1548 static void gl2psBuildBspTree(GL2PSbsptree *tree, GL2PSlist *primitives)
1550 GL2PSprimitive *prim, *frontprim = NULL, *backprim = NULL;
1551 GL2PSlist *frontlist, *backlist;
1556 tree->primitives = gl2psListCreate(1, 2,
sizeof(GL2PSprimitive*));
1557 index = gl2psFindRoot(primitives, &prim);
1558 gl2psGetPlane(prim, tree->plane);
1559 gl2psAddPrimitiveInList(prim, tree->primitives);
1561 frontlist = gl2psListCreate(1, 2,
sizeof(GL2PSprimitive*));
1562 backlist = gl2psListCreate(1, 2,
sizeof(GL2PSprimitive*));
1564 for(i = 0; i < gl2psListNbr(primitives); i++){
1566 prim = *(GL2PSprimitive**)gl2psListPointer(primitives,i);
1567 switch(gl2psSplitPrimitive(prim, tree->plane, &frontprim, &backprim)){
1568 case GL2PS_COINCIDENT:
1569 gl2psAddPrimitiveInList(prim, tree->primitives);
1571 case GL2PS_IN_BACK_OF:
1572 gl2psAddPrimitiveInList(prim, backlist);
1574 case GL2PS_IN_FRONT_OF:
1575 gl2psAddPrimitiveInList(prim, frontlist);
1577 case GL2PS_SPANNING:
1578 gl2psAddPrimitiveInList(backprim, backlist);
1579 gl2psAddPrimitiveInList(frontprim, frontlist);
1580 gl2psFreePrimitive(&prim);
1586 if(gl2psListNbr(tree->primitives)){
1587 gl2psListSort(tree->primitives, gl2psTrianglesFirst);
1590 if(gl2psListNbr(frontlist)){
1591 gl2psListSort(frontlist, gl2psTrianglesFirst);
1592 tree->front = (GL2PSbsptree*)gl2psMalloc(
sizeof(GL2PSbsptree));
1593 gl2psBuildBspTree(tree->front, frontlist);
1596 gl2psListDelete(frontlist);
1599 if(gl2psListNbr(backlist)){
1600 gl2psListSort(backlist, gl2psTrianglesFirst);
1601 tree->back = (GL2PSbsptree*)gl2psMalloc(
sizeof(GL2PSbsptree));
1602 gl2psBuildBspTree(tree->back, backlist);
1605 gl2psListDelete(backlist);
1608 gl2psListDelete(primitives);
1611 static void gl2psTraverseBspTree(GL2PSbsptree *tree, GL2PSxyz eye, GLfloat epsilon,
1612 GLboolean (*compare)(GLfloat f1, GLfloat f2),
1613 void (*action)(
void *data),
int inverse)
1619 result = gl2psComparePointPlane(eye, tree->plane);
1621 if(GL_TRUE == compare(result, epsilon)){
1622 gl2psTraverseBspTree(tree->back, eye, epsilon, compare, action, inverse);
1624 gl2psListActionInverse(tree->primitives, action);
1627 gl2psListAction(tree->primitives, action);
1629 gl2psTraverseBspTree(tree->front, eye, epsilon, compare, action, inverse);
1631 else if(GL_TRUE == compare(-epsilon, result)){
1632 gl2psTraverseBspTree(tree->front, eye, epsilon, compare, action, inverse);
1634 gl2psListActionInverse(tree->primitives, action);
1637 gl2psListAction(tree->primitives, action);
1639 gl2psTraverseBspTree(tree->back, eye, epsilon, compare, action, inverse);
1642 gl2psTraverseBspTree(tree->front, eye, epsilon, compare, action, inverse);
1643 gl2psTraverseBspTree(tree->back, eye, epsilon, compare, action, inverse);
1647 static void gl2psRescaleAndOffset()
1649 GL2PSprimitive *prim;
1650 GLfloat minZ, maxZ, rangeZ, scaleZ;
1651 GLfloat
factor, units, area, dZ, dZdX, dZdY, maxdZ;
1654 if(!gl2psListNbr(gl2ps->primitives))
1658 prim = *(GL2PSprimitive**)gl2psListPointer(gl2ps->primitives, 0);
1659 minZ = maxZ = prim->verts[0].xyz[2];
1660 for(i = 1; i < prim->numverts; i++){
1661 if(prim->verts[i].xyz[2] < minZ) minZ = prim->verts[i].xyz[2];
1662 if(prim->verts[i].xyz[2] > maxZ) maxZ = prim->verts[i].xyz[2];
1664 for(i = 1; i < gl2psListNbr(gl2ps->primitives); i++){
1665 prim = *(GL2PSprimitive**)gl2psListPointer(gl2ps->primitives, i);
1666 for(j = 0; j < prim->numverts; j++){
1667 if(prim->verts[j].xyz[2] < minZ) minZ = prim->verts[j].xyz[2];
1668 if(prim->verts[j].xyz[2] > maxZ) maxZ = prim->verts[j].xyz[2];
1671 rangeZ = (maxZ - minZ);
1675 scaleZ = GL2PS_ZERO(rangeZ) ? GL2PS_ZSCALE : (GL2PS_ZSCALE / rangeZ);
1677 if(scaleZ > 100000.F) scaleZ = 100000.F;
1680 for(i = 0; i < gl2psListNbr(gl2ps->primitives); i++){
1681 prim = *(GL2PSprimitive**)gl2psListPointer(gl2ps->primitives, i);
1682 for(j = 0; j < prim->numverts; j++){
1683 prim->verts[j].xyz[2] = (prim->verts[j].xyz[2] - minZ) * scaleZ;
1685 if((gl2ps->options & GL2PS_SIMPLE_LINE_OFFSET) &&
1686 (prim->type == GL2PS_LINE)){
1687 if(gl2ps->sort == GL2PS_SIMPLE_SORT){
1688 prim->verts[0].xyz[2] -= GL2PS_ZOFFSET_LARGE;
1689 prim->verts[1].xyz[2] -= GL2PS_ZOFFSET_LARGE;
1692 prim->verts[0].xyz[2] -= GL2PS_ZOFFSET;
1693 prim->verts[1].xyz[2] -= GL2PS_ZOFFSET;
1696 else if(prim->offset && (prim->type == GL2PS_TRIANGLE)){
1697 factor = gl2ps->offset[0];
1698 units = gl2ps->offset[1];
1700 (prim->verts[1].xyz[0] - prim->verts[0].xyz[0]) *
1701 (prim->verts[2].xyz[1] - prim->verts[1].xyz[1]) -
1702 (prim->verts[2].xyz[0] - prim->verts[1].xyz[0]) *
1703 (prim->verts[1].xyz[1] - prim->verts[0].xyz[1]);
1704 if(!GL2PS_ZERO(area)){
1706 ((prim->verts[2].xyz[1] - prim->verts[1].xyz[1]) *
1707 (prim->verts[1].xyz[2] - prim->verts[0].xyz[2]) -
1708 (prim->verts[1].xyz[1] - prim->verts[0].xyz[1]) *
1709 (prim->verts[2].xyz[2] - prim->verts[1].xyz[2])) / area;
1711 ((prim->verts[1].xyz[0] - prim->verts[0].xyz[0]) *
1712 (prim->verts[2].xyz[2] - prim->verts[1].xyz[2]) -
1713 (prim->verts[2].xyz[0] - prim->verts[1].xyz[0]) *
1714 (prim->verts[1].xyz[2] - prim->verts[0].xyz[2])) / area;
1715 maxdZ = (GLfloat)sqrt(dZdX * dZdX + dZdY * dZdY);
1720 dZ = factor * maxdZ + units;
1721 prim->verts[0].xyz[2] += dZ;
1722 prim->verts[1].xyz[2] += dZ;
1723 prim->verts[2].xyz[2] += dZ;
1734 static GLint gl2psGetPlaneFromPoints(GL2PSxyz a, GL2PSxyz b, GL2PSplane plane)
1738 plane[0] = b[1] - a[1];
1739 plane[1] = a[0] - b[0];
1740 n = (GLfloat)sqrt(plane[0]*plane[0] + plane[1]*plane[1]);
1745 plane[3] = -plane[0]*a[0]-plane[1]*a[1];
1756 static void gl2psFreeBspImageTree(GL2PSbsptree2d **tree)
1759 if((*tree)->back) gl2psFreeBspImageTree(&(*tree)->back);
1760 if((*tree)->front) gl2psFreeBspImageTree(&(*tree)->front);
1766 static GLint gl2psCheckPoint(GL2PSxyz point, GL2PSplane plane)
1770 pt_dis = gl2psComparePointPlane(point, plane);
1771 if(pt_dis > GL2PS_EPSILON)
return GL2PS_POINT_INFRONT;
1772 else if(pt_dis < -GL2PS_EPSILON)
return GL2PS_POINT_BACK;
1773 else return GL2PS_POINT_COINCIDENT;
1776 static void gl2psAddPlanesInBspTreeImage(GL2PSprimitive *prim,
1777 GL2PSbsptree2d **tree)
1782 GL2PSbsptree2d *head = NULL, *cur = NULL;
1784 if((*tree == NULL) && (prim->numverts > 2)){
1789 head = (GL2PSbsptree2d*)gl2psMalloc(
sizeof(GL2PSbsptree2d));
1790 for(i = 0; i < prim->numverts-1; i++){
1791 if(!gl2psGetPlaneFromPoints(prim->verts[i].xyz,
1792 prim->verts[i+1].xyz,
1794 if(prim->numverts-i > 3){
1808 for(i = 2+offset; i < prim->numverts; i++){
1809 ret = gl2psCheckPoint(prim->verts[i].xyz, head->plane);
1810 if(ret != GL2PS_POINT_COINCIDENT)
break;
1813 case GL2PS_POINT_INFRONT :
1815 for(i = 1+offset; i < prim->numverts-1; i++){
1816 if(cur->front == NULL){
1817 cur->front = (GL2PSbsptree2d*)gl2psMalloc(
sizeof(GL2PSbsptree2d));
1819 if(gl2psGetPlaneFromPoints(prim->verts[i].xyz,
1820 prim->verts[i+1].xyz,
1821 cur->front->plane)){
1827 if(cur->front == NULL){
1828 cur->front = (GL2PSbsptree2d*)gl2psMalloc(
sizeof(GL2PSbsptree2d));
1830 if(gl2psGetPlaneFromPoints(prim->verts[i].xyz,
1831 prim->verts[offset].xyz,
1832 cur->front->plane)){
1833 cur->front->front = NULL;
1834 cur->front->back = NULL;
1837 gl2psFree(cur->front);
1841 case GL2PS_POINT_BACK :
1842 for(i = 0; i < 4; i++){
1843 head->plane[i] = -head->plane[i];
1846 for(i = 1+offset; i < prim->numverts-1; i++){
1847 if(cur->front == NULL){
1848 cur->front = (GL2PSbsptree2d*)gl2psMalloc(
sizeof(GL2PSbsptree2d));
1850 if(gl2psGetPlaneFromPoints(prim->verts[i+1].xyz,
1852 cur->front->plane)){
1858 if(cur->front == NULL){
1859 cur->front = (GL2PSbsptree2d*)gl2psMalloc(
sizeof(GL2PSbsptree2d));
1861 if(gl2psGetPlaneFromPoints(prim->verts[offset].xyz,
1863 cur->front->plane)){
1864 cur->front->front = NULL;
1865 cur->front->back = NULL;
1868 gl2psFree(cur->front);
1880 static GLint gl2psCheckPrimitive(GL2PSprimitive *prim, GL2PSplane plane)
1885 pos = gl2psCheckPoint(prim->verts[0].xyz, plane);
1886 for(i = 1; i < prim->numverts; i++){
1887 pos |= gl2psCheckPoint(prim->verts[i].xyz, plane);
1888 if(pos == (GL2PS_POINT_INFRONT | GL2PS_POINT_BACK))
return GL2PS_SPANNING;
1890 if(pos & GL2PS_POINT_INFRONT)
return GL2PS_IN_FRONT_OF;
1891 else if(pos & GL2PS_POINT_BACK)
return GL2PS_IN_BACK_OF;
1892 else return GL2PS_COINCIDENT;
1895 static GL2PSprimitive *gl2psCreateSplitPrimitive2D(GL2PSprimitive *parent,
1900 GL2PSprimitive *child = (GL2PSprimitive*)gl2psMalloc(
sizeof(GL2PSprimitive));
1902 if(parent->type == GL2PS_IMAGEMAP){
1903 child->type = GL2PS_IMAGEMAP;
1904 child->data.image = parent->data.image;
1908 case 1 : child->type = GL2PS_POINT;
break;
1909 case 2 : child->type = GL2PS_LINE;
break;
1910 case 3 : child->type = GL2PS_TRIANGLE;
break;
1911 case 4 : child->type = GL2PS_QUADRANGLE;
break;
1912 default: child->type = GL2PS_NO_TYPE;
break;
1915 child->boundary = 0;
1916 child->culled = parent->culled;
1917 child->offset = parent->offset;
1918 child->pattern = parent->pattern;
1919 child->factor = parent->factor;
1920 child->width = parent->width;
1921 child->numverts = numverts;
1922 child->verts = (GL2PSvertex*)gl2psMalloc(numverts *
sizeof(GL2PSvertex));
1923 for(i = 0; i < numverts; i++){
1924 child->verts[i] = vertx[i];
1929 static void gl2psSplitPrimitive2D(GL2PSprimitive *prim,
1931 GL2PSprimitive **front,
1932 GL2PSprimitive **back)
1939 GLint cur = -1, prev = -1, i, v1 = 0, v2 = 0, flag = 1, prev0 = -1;
1942 GL2PSvertex *front_list = NULL, *back_list = NULL;
1945 GLshort front_count = 0, back_count = 0;
1947 for(i = 0; i <= prim->numverts; i++){
1949 if(v1 == prim->numverts){
1950 if(prim->numverts < 3)
break;
1952 v2 = prim->numverts - 1;
1956 cur = gl2psCheckPoint(prim->verts[v1].xyz, plane);
1961 if(((prev == -1) || (prev == cur) || (prev == 0) || (cur == 0)) &&
1962 (i < prim->numverts)){
1963 if(cur == GL2PS_POINT_INFRONT){
1965 front_list = (GL2PSvertex*)gl2psRealloc(front_list,
1966 sizeof(GL2PSvertex)*front_count);
1967 front_list[front_count-1] = prim->verts[v1];
1969 else if(cur == GL2PS_POINT_BACK){
1971 back_list = (GL2PSvertex*)gl2psRealloc(back_list,
1972 sizeof(GL2PSvertex)*back_count);
1973 back_list[back_count-1] = prim->verts[v1];
1977 front_list = (GL2PSvertex*)gl2psRealloc(front_list,
1978 sizeof(GL2PSvertex)*front_count);
1979 front_list[front_count-1] = prim->verts[v1];
1981 back_list = (GL2PSvertex*)gl2psRealloc(back_list,
1982 sizeof(GL2PSvertex)*back_count);
1983 back_list[back_count-1] = prim->verts[v1];
1987 else if((prev != cur) && (cur != 0) && (prev != 0)){
1993 front_list = (GL2PSvertex*)gl2psRealloc(front_list,
1994 sizeof(GL2PSvertex)*front_count);
1995 gl2psCutEdge(&prim->verts[v2], &prim->verts[v1],
1996 plane, &front_list[front_count-1]);
1998 back_list = (GL2PSvertex*)gl2psRealloc(back_list,
1999 sizeof(GL2PSvertex)*back_count);
2000 back_list[back_count-1] = front_list[front_count-1];
2005 *front = gl2psCreateSplitPrimitive2D(prim, front_count, front_list);
2006 *back = gl2psCreateSplitPrimitive2D(prim, back_count, back_list);
2007 gl2psFree(front_list);
2008 gl2psFree(back_list);
2011 static GLint gl2psAddInBspImageTree(GL2PSprimitive *prim, GL2PSbsptree2d **tree)
2014 GL2PSprimitive *frontprim = NULL, *backprim = NULL;
2019 if(prim->type == GL2PS_PIXMAP ||
2020 prim->type == GL2PS_TEXT ||
2021 prim->type == GL2PS_SPECIAL){
2026 if((prim->type != GL2PS_IMAGEMAP) && (GL_FALSE == gl2ps->zerosurfacearea)){
2027 gl2psAddPlanesInBspTreeImage(gl2ps->primitivetoadd, tree);
2032 switch(gl2psCheckPrimitive(prim, (*tree)->plane)){
2033 case GL2PS_IN_BACK_OF:
return gl2psAddInBspImageTree(prim, &(*tree)->back);
2034 case GL2PS_IN_FRONT_OF:
2035 if((*tree)->front != NULL)
return gl2psAddInBspImageTree(prim, &(*tree)->front);
2037 case GL2PS_SPANNING:
2038 gl2psSplitPrimitive2D(prim, (*tree)->plane, &frontprim, &backprim);
2039 ret = gl2psAddInBspImageTree(backprim, &(*tree)->back);
2040 if((*tree)->front != NULL){
2041 if(gl2psAddInBspImageTree(frontprim, &(*tree)->front)){
2045 gl2psFree(frontprim->verts);
2046 gl2psFree(frontprim);
2047 gl2psFree(backprim->verts);
2048 gl2psFree(backprim);
2050 case GL2PS_COINCIDENT:
2051 if((*tree)->back != NULL){
2052 gl2ps->zerosurfacearea = GL_TRUE;
2053 ret = gl2psAddInBspImageTree(prim, &(*tree)->back);
2054 gl2ps->zerosurfacearea = GL_FALSE;
2057 if((*tree)->front != NULL){
2058 gl2ps->zerosurfacearea = GL_TRUE;
2059 ret = gl2psAddInBspImageTree(prim, &(*tree)->front);
2060 gl2ps->zerosurfacearea = GL_FALSE;
2063 if(prim->type == GL2PS_LINE)
return 1;
2070 static void gl2psAddInImageTree(
void *data)
2072 GL2PSprimitive *prim = *(GL2PSprimitive **)data;
2073 gl2ps->primitivetoadd = prim;
2074 if(prim->type == GL2PS_IMAGEMAP && prim->data.image->format == GL2PS_IMAGEMAP_VISIBLE){
2077 else if(!gl2psAddInBspImageTree(prim, &gl2ps->imagetree)){
2080 else if(prim->type == GL2PS_IMAGEMAP){
2081 prim->data.image->format = GL2PS_IMAGEMAP_VISIBLE;
2087 static void gl2psAddBoundaryInList(GL2PSprimitive *prim, GL2PSlist *list)
2093 c[0] = c[1] = c[2] = 0.0F;
2094 for(i = 0; i < prim->numverts; i++){
2095 c[0] += prim->verts[i].xyz[0];
2096 c[1] += prim->verts[i].xyz[1];
2098 c[0] /= prim->numverts;
2099 c[1] /= prim->numverts;
2101 for(i = 0; i < prim->numverts; i++){
2102 if(prim->boundary & (GLint)pow(2., i)){
2103 b = (GL2PSprimitive*)gl2psMalloc(
sizeof(GL2PSprimitive));
2104 b->type = GL2PS_LINE;
2105 b->offset = prim->offset;
2106 b->pattern = prim->pattern;
2107 b->factor = prim->factor;
2108 b->culled = prim->culled;
2109 b->width = prim->width;
2112 b->verts = (GL2PSvertex*)gl2psMalloc(2 *
sizeof(GL2PSvertex));
2115 v[0] = c[0] - prim->verts[i].xyz[0];
2116 v[1] = c[1] - prim->verts[i].xyz[1];
2118 norm = gl2psNorm(v);
2121 b->verts[0].xyz[0] = prim->verts[i].xyz[0] +0.1*v[0];
2122 b->verts[0].xyz[1] = prim->verts[i].xyz[1] +0.1*v[1];
2123 b->verts[0].xyz[2] = prim->verts[i].xyz[2];
2124 v[0] = c[0] - prim->verts[gl2psGetIndex(i, prim->numverts)].xyz[0];
2125 v[1] = c[1] - prim->verts[gl2psGetIndex(i, prim->numverts)].xyz[1];
2126 norm = gl2psNorm(v);
2129 b->verts[1].xyz[0] = prim->verts[gl2psGetIndex(i, prim->numverts)].xyz[0] +0.1*v[0];
2130 b->verts[1].xyz[1] = prim->verts[gl2psGetIndex(i, prim->numverts)].xyz[1] +0.1*v[1];
2131 b->verts[1].xyz[2] = prim->verts[gl2psGetIndex(i, prim->numverts)].xyz[2];
2133 b->verts[0].xyz[0] = prim->verts[i].xyz[0];
2134 b->verts[0].xyz[1] = prim->verts[i].xyz[1];
2135 b->verts[0].xyz[2] = prim->verts[i].xyz[2];
2136 b->verts[1].xyz[0] = prim->verts[gl2psGetIndex(i, prim->numverts)].xyz[0];
2137 b->verts[1].xyz[1] = prim->verts[gl2psGetIndex(i, prim->numverts)].xyz[1];
2138 b->verts[1].xyz[2] = prim->verts[gl2psGetIndex(i, prim->numverts)].xyz[2];
2141 b->verts[0].rgba[0] = 0.0F;
2142 b->verts[0].rgba[1] = 0.0F;
2143 b->verts[0].rgba[2] = 0.0F;
2144 b->verts[0].rgba[3] = 0.0F;
2145 b->verts[1].rgba[0] = 0.0F;
2146 b->verts[1].rgba[1] = 0.0F;
2147 b->verts[1].rgba[2] = 0.0F;
2148 b->verts[1].rgba[3] = 0.0F;
2149 gl2psListAdd(list, &b);
2155 static void gl2psBuildPolygonBoundary(GL2PSbsptree *tree)
2158 GL2PSprimitive *prim;
2161 gl2psBuildPolygonBoundary(tree->back);
2162 for(i = 0; i < gl2psListNbr(tree->primitives); i++){
2163 prim = *(GL2PSprimitive**)gl2psListPointer(tree->primitives, i);
2164 if(prim->boundary) gl2psAddBoundaryInList(prim, tree->primitives);
2166 gl2psBuildPolygonBoundary(tree->front);
2175 static void gl2psAddPolyPrimitive(GLshort type, GLshort numverts,
2176 GL2PSvertex *verts, GLint offset,
2177 GLushort pattern, GLint factor,
2178 GLfloat
width,
char boundary)
2180 GL2PSprimitive *prim;
2182 prim = (GL2PSprimitive*)gl2psMalloc(
sizeof(GL2PSprimitive));
2184 prim->numverts = numverts;
2185 prim->verts = (GL2PSvertex*)gl2psMalloc(numverts *
sizeof(GL2PSvertex));
2186 memcpy(prim->verts, verts, numverts *
sizeof(GL2PSvertex));
2187 prim->boundary = boundary;
2188 prim->offset = offset;
2189 prim->pattern = pattern;
2191 prim->width =
width;
2197 gl2psListAdd(gl2ps->primitives, &prim);
2200 static GLint gl2psGetVertex(GL2PSvertex *v, GLfloat *p)
2208 if(gl2ps->colormode == GL_COLOR_INDEX && gl2ps->colorsize > 0){
2209 i = (GLint)(p[3] + 0.5);
2210 v->rgba[0] = gl2ps->colormap[i][0];
2211 v->rgba[1] = gl2ps->colormap[i][1];
2212 v->rgba[2] = gl2ps->colormap[i][2];
2213 v->rgba[3] = gl2ps->colormap[i][3];
2225 static void gl2psParseFeedbackBuffer(GLint used)
2228 GLushort pattern = 0;
2230 GLint i, sizeoffloat, count, v, vtot, offset = 0, factor = 0, auxindex = 0;
2231 GLfloat lwidth = 1.0F, psize = 1.0F;
2233 GL2PSvertex vertices[3];
2234 GL2PSprimitive *prim;
2235 GL2PSimagemap *node;
2237 current = gl2ps->feedback;
2238 boundary = gl2ps->boundary = GL_FALSE;
2242 if(GL_TRUE == boundary) gl2ps->boundary = GL_TRUE;
2244 switch((GLint)*current){
2245 case GL_POINT_TOKEN :
2248 i = gl2psGetVertex(&vertices[0], current);
2251 gl2psAddPolyPrimitive(GL2PS_POINT, 1, vertices, 0,
2252 pattern, factor, psize, 0);
2254 case GL_LINE_TOKEN :
2255 case GL_LINE_RESET_TOKEN :
2258 i = gl2psGetVertex(&vertices[0], current);
2261 i = gl2psGetVertex(&vertices[1], current);
2264 gl2psAddPolyPrimitive(GL2PS_LINE, 2, vertices, 0,
2265 pattern, factor, lwidth, 0);
2267 case GL_POLYGON_TOKEN :
2268 count = (GLint)current[1];
2272 while(count > 0 && used > 0){
2273 i = gl2psGetVertex(&vertices[v], current);
2274 gl2psAdaptVertexForBlending(&vertices[v]);
2280 if(GL_TRUE == boundary){
2281 if(!count && vtot == 2) flag = 1|2|4;
2282 else if(!count) flag = 2|4;
2283 else if(vtot == 2) flag = 1|2;
2288 gl2psAddPolyPrimitive(GL2PS_TRIANGLE, 3, vertices, offset,
2289 pattern, factor, 1, flag);
2290 vertices[1] = vertices[2];
2296 case GL_BITMAP_TOKEN :
2297 case GL_DRAW_PIXEL_TOKEN :
2298 case GL_COPY_PIXEL_TOKEN :
2301 i = gl2psGetVertex(&vertices[0], current);
2305 case GL_PASS_THROUGH_TOKEN :
2306 switch((GLint)current[1]){
2307 case GL2PS_BEGIN_OFFSET_TOKEN : offset = 1;
break;
2308 case GL2PS_END_OFFSET_TOKEN : offset = 0;
break;
2309 case GL2PS_BEGIN_BOUNDARY_TOKEN : boundary = GL_TRUE;
break;
2310 case GL2PS_END_BOUNDARY_TOKEN : boundary = GL_FALSE;
break;
2311 case GL2PS_END_STIPPLE_TOKEN : pattern = factor = 0;
break;
2312 case GL2PS_BEGIN_BLEND_TOKEN : gl2ps->blending = GL_TRUE;
break;
2313 case GL2PS_END_BLEND_TOKEN : gl2ps->blending = GL_FALSE;
break;
2314 case GL2PS_BEGIN_STIPPLE_TOKEN :
2317 pattern = (GLushort)current[1];
2320 factor = (GLint)current[1];
2322 case GL2PS_SRC_BLEND_TOKEN :
2325 gl2ps->blendfunc[0] = (GLint)current[1];
2327 case GL2PS_DST_BLEND_TOKEN :
2330 gl2ps->blendfunc[1] = (GLint)current[1];
2332 case GL2PS_POINT_SIZE_TOKEN :
2337 case GL2PS_LINE_WIDTH_TOKEN :
2340 lwidth = current[1];
2342 case GL2PS_IMAGEMAP_TOKEN :
2343 prim = (GL2PSprimitive *)gl2psMalloc(
sizeof(GL2PSprimitive));
2344 prim->type = GL2PS_IMAGEMAP;
2347 prim->verts = (GL2PSvertex *)gl2psMalloc(4 *
sizeof(GL2PSvertex));
2354 node = (GL2PSimagemap*)gl2psMalloc(
sizeof(GL2PSimagemap));
2355 node->image = (GL2PSimage*)gl2psMalloc(
sizeof(GL2PSimage));
2356 node->image->type = 0;
2357 node->image->format = 0;
2360 if(gl2ps->imagemap_head == NULL)
2361 gl2ps->imagemap_head = node;
2363 gl2ps->imagemap_tail->next = node;
2364 gl2ps->imagemap_tail = node;
2365 prim->data.image = node->image;
2367 current += 2; used -= 2;
2368 i = gl2psGetVertex(&prim->verts[0], ¤t[1]);
2369 current += i; used -= i;
2371 node->image->width = (GLint)current[2];
2372 current += 2; used -= 2;
2373 node->image->height = (GLint)current[2];
2374 prim->verts[0].xyz[0] = prim->verts[0].xyz[0] - (int)(node->image->width / 2) + 0.5F;
2375 prim->verts[0].xyz[1] = prim->verts[0].xyz[1] - (int)(node->image->height / 2) + 0.5F;
2376 for(i = 1; i < 4; i++){
2377 for(v = 0; v < 3; v++){
2378 prim->verts[i].xyz[v] = prim->verts[0].xyz[v];
2379 prim->verts[i].rgba[v] = prim->verts[0].rgba[v];
2381 prim->verts[i].rgba[v] = prim->verts[0].rgba[v];
2383 prim->verts[1].xyz[0] = prim->verts[1].xyz[0] + node->image->width;
2384 prim->verts[2].xyz[0] = prim->verts[1].xyz[0];
2385 prim->verts[2].xyz[1] = prim->verts[2].xyz[1] + node->image->height;
2386 prim->verts[3].xyz[1] = prim->verts[2].xyz[1];
2388 sizeoffloat =
sizeof(GLfloat);
2389 v = 2 * sizeoffloat;
2390 vtot = node->image->height + node->image->height *
2391 ((node->image->width - 1) / 8);
2392 node->image->pixels = (GLfloat*)gl2psMalloc(v + vtot);
2393 node->image->pixels[0] = prim->verts[0].xyz[0];
2394 node->image->pixels[1] = prim->verts[0].xyz[1];
2396 for(i = 0; i < vtot; i += sizeoffloat){
2397 current += 2; used -= 2;
2399 memcpy(&(((
char*)(node->image->pixels))[i + v]), &(current[2]), sizeoffloat);
2401 memcpy(&(((
char*)(node->image->pixels))[i + v]), &(current[2]), vtot - i);
2404 gl2psListAdd(gl2ps->primitives, &prim);
2406 case GL2PS_DRAW_PIXELS_TOKEN :
2407 case GL2PS_TEXT_TOKEN :
2408 if(auxindex < gl2psListNbr(gl2ps->auxprimitives))
2409 gl2psListAdd(gl2ps->primitives,
2410 gl2psListPointer(gl2ps->auxprimitives, auxindex++));
2412 gl2psMsg(GL2PS_ERROR,
"Wrong number of auxiliary tokens in buffer");
2419 gl2psMsg(GL2PS_WARNING,
"Unknown token in buffer");
2426 gl2psListReset(gl2ps->auxprimitives);
2435 static void gl2psWriteByte(
unsigned char byte)
2437 unsigned char h = byte / 16;
2438 unsigned char l = byte % 16;
2439 gl2psPrintf(
"%x%x", h, l);
2442 static void gl2psPrintPostScriptPixmap(GLfloat x, GLfloat y, GL2PSimage *im)
2444 GLuint nbhex, nbyte, nrgb, nbits;
2445 GLuint row, col, ibyte, icase;
2446 GLfloat dr, dg, db, fgrey;
2447 unsigned char red = 0, green = 0,
blue = 0, b, grey;
2448 GLuint width = (GLuint)im->width;
2449 GLuint height = (GLuint)im->height;
2456 if((width <= 0) || (height <= 0))
return;
2458 gl2psPrintf(
"gsave\n");
2459 gl2psPrintf(
"%.2f %.2f translate\n", x, y);
2460 gl2psPrintf(
"%d %d scale\n", width, height);
2463 gl2psPrintf(
"/picstr %d string def\n", width);
2464 gl2psPrintf(
"%d %d %d\n", width, height, 8);
2465 gl2psPrintf(
"[ %d 0 0 -%d 0 %d ]\n", width, height, height);
2466 gl2psPrintf(
"{ currentfile picstr readhexstring pop }\n");
2467 gl2psPrintf(
"image\n");
2468 for(row = 0; row < height; row++){
2469 for(col = 0; col <
width; col++){
2470 gl2psGetRGB(im, col, row, &dr, &dg, &db);
2471 fgrey = (0.30F * dr + 0.59F * dg + 0.11F * db);
2472 grey = (
unsigned char)(255. * fgrey);
2473 gl2psWriteByte(grey);
2477 nbhex = width * height * 2;
2478 gl2psPrintf(
"%%%% nbhex digit :%d\n", nbhex);
2482 nbits = nrgb * nbit;
2484 if((nbyte * 8) != nbits) nbyte++;
2485 gl2psPrintf(
"/rgbstr %d string def\n", nbyte);
2486 gl2psPrintf(
"%d %d %d\n", width, height, nbit);
2487 gl2psPrintf(
"[ %d 0 0 -%d 0 %d ]\n", width, height, height);
2488 gl2psPrintf(
"{ currentfile rgbstr readhexstring pop }\n");
2489 gl2psPrintf(
"false 3\n");
2490 gl2psPrintf(
"colorimage\n");
2491 for(row = 0; row < height; row++){
2495 for(ibyte = 0; ibyte < nbyte; ibyte++){
2498 gl2psGetRGB(im, col, row, &dr, &dg, &db);
2504 red = (
unsigned char)(3. * dr);
2505 green = (
unsigned char)(3. * dg);
2506 blue = (
unsigned char)(3. * db);
2511 gl2psGetRGB(im, col, row, &dr, &dg, &db);
2517 red = (
unsigned char)(3. * dr);
2518 green = (
unsigned char)(3. * dg);
2519 blue = (
unsigned char)(3. * db);
2525 else if(icase == 2) {
2529 gl2psGetRGB(im, col, row, &dr, &dg, &db);
2535 red = (
unsigned char)(3. * dr);
2536 green = (
unsigned char)(3. * dg);
2537 blue = (
unsigned char)(3. * db);
2544 else if(icase == 3) {
2547 gl2psGetRGB(im, col, row, &dr, &dg, &db);
2553 red = (
unsigned char)(3. * dr);
2554 green = (
unsigned char)(3. * dg);
2555 blue = (
unsigned char)(3. * db);
2569 nbits = nrgb * nbit;
2571 if((nbyte * 8) != nbits) nbyte++;
2572 gl2psPrintf(
"/rgbstr %d string def\n", nbyte);
2573 gl2psPrintf(
"%d %d %d\n", width, height, nbit);
2574 gl2psPrintf(
"[ %d 0 0 -%d 0 %d ]\n", width, height, height);
2575 gl2psPrintf(
"{ currentfile rgbstr readhexstring pop }\n");
2576 gl2psPrintf(
"false 3\n");
2577 gl2psPrintf(
"colorimage\n");
2578 for(row = 0; row < height; row++){
2581 for(ibyte = 0; ibyte < nbyte; ibyte++){
2584 gl2psGetRGB(im, col, row, &dr, &dg, &db);
2590 red = (
unsigned char)(15. * dr);
2591 green = (
unsigned char)(15. * dg);
2592 gl2psPrintf(
"%x%x", red, green);
2595 else if(icase == 2) {
2596 blue = (
unsigned char)(15. * db);
2598 gl2psGetRGB(im, col, row, &dr, &dg, &db);
2604 red = (
unsigned char)(15. * dr);
2605 gl2psPrintf(
"%x%x",
blue, red);
2608 else if(icase == 3) {
2609 green = (
unsigned char)(15. * dg);
2610 blue = (
unsigned char)(15. * db);
2611 gl2psPrintf(
"%x%x", green,
blue);
2620 gl2psPrintf(
"/rgbstr %d string def\n", nbyte);
2621 gl2psPrintf(
"%d %d %d\n", width, height, 8);
2622 gl2psPrintf(
"[ %d 0 0 -%d 0 %d ]\n", width, height, height);
2623 gl2psPrintf(
"{ currentfile rgbstr readhexstring pop }\n");
2624 gl2psPrintf(
"false 3\n");
2625 gl2psPrintf(
"colorimage\n");
2626 for(row = 0; row < height; row++){
2627 for(col = 0; col <
width; col++){
2628 gl2psGetRGB(im, col, row, &dr, &dg, &db);
2629 red = (
unsigned char)(255. * dr);
2630 gl2psWriteByte(red);
2631 green = (
unsigned char)(255. * dg);
2632 gl2psWriteByte(green);
2633 blue = (
unsigned char)(255. * db);
2634 gl2psWriteByte(
blue);
2640 gl2psPrintf(
"grestore\n");
2643 static void gl2psPrintPostScriptImagemap(GLfloat x, GLfloat y,
2644 GLsizei width, GLsizei height,
2645 const unsigned char *imagemap){
2648 if((width <= 0) || (height <= 0))
return;
2650 size = height + height * (width - 1) / 8;
2652 gl2psPrintf(
"gsave\n");
2653 gl2psPrintf(
"%.2f %.2f translate\n", x, y);
2654 gl2psPrintf(
"%d %d scale\n%d %d\ntrue\n", width, height,width, height);
2655 gl2psPrintf(
"[ %d 0 0 -%d 0 %d ] {<", width, height);
2656 for(i = 0; i < size; i++){
2657 gl2psWriteByte(*imagemap);
2660 gl2psPrintf(
">} imagemask\ngrestore\n");
2663 static void gl2psPrintPostScriptHeader(
void)
2670 gl2psPrintGzipHeader();
2674 if(gl2ps->format == GL2PS_PS){
2675 gl2psPrintf(
"%%!PS-Adobe-3.0\n");
2678 gl2psPrintf(
"%%!PS-Adobe-3.0 EPSF-3.0\n");
2681 gl2psPrintf(
"%%%%Title: %s\n"
2682 "%%%%Creator: GL2PS %d.%d.%d%s, %s\n"
2684 "%%%%CreationDate:\n"
2685 "%%%%LanguageLevel: 3\n"
2686 "%%%%DocumentData: Clean7Bit\n"
2688 gl2ps->title, GL2PS_MAJOR_VERSION, GL2PS_MINOR_VERSION,
2689 GL2PS_PATCH_VERSION, GL2PS_EXTRA_VERSION, GL2PS_COPYRIGHT,
2692 if(gl2ps->format == GL2PS_PS){
2693 gl2psPrintf(
"%%%%Orientation: %s\n"
2694 "%%%%DocumentMedia: Default %d %d 0 () ()\n",
2695 (gl2ps->options & GL2PS_LANDSCAPE) ?
"Landscape" :
"Portrait",
2696 (gl2ps->options & GL2PS_LANDSCAPE) ? (
int)gl2ps->viewport[3] :
2697 (
int)gl2ps->viewport[2],
2698 (gl2ps->options & GL2PS_LANDSCAPE) ? (
int)gl2ps->viewport[2] :
2699 (
int)gl2ps->viewport[3]);
2702 gl2psPrintf(
"%%%%BoundingBox: %d %d %d %d\n"
2703 "%%%%EndComments\n",
2704 (gl2ps->options & GL2PS_LANDSCAPE) ? (
int)gl2ps->viewport[1] :
2705 (
int)gl2ps->viewport[0],
2706 (gl2ps->options & GL2PS_LANDSCAPE) ? (
int)gl2ps->viewport[0] :
2707 (
int)gl2ps->viewport[1],
2708 (gl2ps->options & GL2PS_LANDSCAPE) ? (
int)gl2ps->viewport[3] :
2709 (
int)gl2ps->viewport[2],
2710 (gl2ps->options & GL2PS_LANDSCAPE) ? (
int)gl2ps->viewport[2] :
2711 (
int)gl2ps->viewport[3]);
2726 gl2psPrintf(
"%%%%BeginProlog\n"
2727 "/gl2psdict 64 dict def gl2psdict begin\n"
2728 "0 setlinecap 0 setlinejoin\n"
2729 "/tryPS3shading %s def %% set to false to force subdivision\n"
2730 "/rThreshold %g def %% red component subdivision threshold\n"
2731 "/gThreshold %g def %% green component subdivision threshold\n"
2732 "/bThreshold %g def %% blue component subdivision threshold\n",
2733 (gl2ps->options & GL2PS_NO_PS3_SHADING) ?
"false" :
"true",
2734 gl2ps->threshold[0], gl2ps->threshold[1], gl2ps->threshold[2]);
2736 gl2psPrintf(
"/BD { bind def } bind def\n"
2737 "/C { setrgbcolor } BD\n"
2738 "/G { 0.082 mul exch 0.6094 mul add exch 0.3086 mul add neg 1.0 add setgray } BD\n"
2739 "/W { setlinewidth } BD\n");
2741 gl2psPrintf(
"/FC { findfont exch /SH exch def SH scalefont setfont } BD\n"
2742 "/SW { dup stringwidth pop } BD\n"
2743 "/S { FC moveto show } BD\n"
2744 "/SBC{ FC moveto SW -2 div 0 rmoveto show } BD\n"
2745 "/SBR{ FC moveto SW neg 0 rmoveto show } BD\n"
2746 "/SCL{ FC moveto 0 SH -2 div rmoveto show } BD\n"
2747 "/SCC{ FC moveto SW -2 div SH -2 div rmoveto show } BD\n"
2748 "/SCR{ FC moveto SW neg SH -2 div rmoveto show } BD\n"
2749 "/STL{ FC moveto 0 SH neg rmoveto show } BD\n"
2750 "/STC{ FC moveto SW -2 div SH neg rmoveto show } BD\n"
2751 "/STR{ FC moveto SW neg SH neg rmoveto show } BD\n");
2755 gl2psPrintf(
"/FCT { FC translate 0 0 } BD\n"
2756 "/SR { gsave FCT moveto rotate show grestore } BD\n"
2757 "/SBCR{ gsave FCT moveto rotate SW -2 div 0 rmoveto show grestore } BD\n"
2758 "/SBRR{ gsave FCT moveto rotate SW neg 0 rmoveto show grestore } BD\n"
2759 "/SCLR{ gsave FCT moveto rotate 0 SH -2 div rmoveto show grestore} BD\n");
2760 gl2psPrintf(
"/SCCR{ gsave FCT moveto rotate SW -2 div SH -2 div rmoveto show grestore} BD\n"
2761 "/SCRR{ gsave FCT moveto rotate SW neg SH -2 div rmoveto show grestore} BD\n"
2762 "/STLR{ gsave FCT moveto rotate 0 SH neg rmoveto show grestore } BD\n"
2763 "/STCR{ gsave FCT moveto rotate SW -2 div SH neg rmoveto show grestore } BD\n"
2764 "/STRR{ gsave FCT moveto rotate SW neg SH neg rmoveto show grestore } BD\n");
2766 gl2psPrintf(
"/P { newpath 0.0 360.0 arc closepath fill } BD\n"
2767 "/LS { newpath moveto } BD\n"
2768 "/L { lineto } BD\n"
2769 "/LE { lineto stroke } BD\n"
2770 "/T { newpath moveto lineto lineto closepath fill } BD\n");
2775 gl2psPrintf(
"/STshfill {\n"
2776 " /b1 exch def /g1 exch def /r1 exch def /y1 exch def /x1 exch def\n"
2777 " /b2 exch def /g2 exch def /r2 exch def /y2 exch def /x2 exch def\n"
2778 " /b3 exch def /g3 exch def /r3 exch def /y3 exch def /x3 exch def\n"
2779 " gsave << /ShadingType 4 /ColorSpace [/DeviceRGB]\n"
2780 " /DataSource [ 0 x1 y1 r1 g1 b1 0 x2 y2 r2 g2 b2 0 x3 y3 r3 g3 b3 ] >>\n"
2781 " shfill grestore } BD\n");
2787 "/Tm { 3 -1 roll 8 -1 roll 13 -1 roll add add 3 div\n"
2789 " 3 -1 roll 7 -1 roll 11 -1 roll add add 3 div\n"
2791 " 3 -1 roll 6 -1 roll 9 -1 roll add add 3 div"
2800 gl2psPrintf(
"/STsplit {\n"
2801 " 4 index 15 index add 0.5 mul\n"
2802 " 4 index 15 index add 0.5 mul\n"
2803 " 4 index 15 index add 0.5 mul\n"
2804 " 4 index 15 index add 0.5 mul\n"
2805 " 4 index 15 index add 0.5 mul\n"
2806 " 5 copy 5 copy 25 15 roll\n");
2810 gl2psPrintf(
" 9 index 30 index add 0.5 mul\n"
2811 " 9 index 30 index add 0.5 mul\n"
2812 " 9 index 30 index add 0.5 mul\n"
2813 " 9 index 30 index add 0.5 mul\n"
2814 " 9 index 30 index add 0.5 mul\n"
2815 " 5 copy 5 copy 35 5 roll 25 5 roll 15 5 roll\n");
2819 gl2psPrintf(
" 4 index 10 index add 0.5 mul\n"
2820 " 4 index 10 index add 0.5 mul\n"
2821 " 4 index 10 index add 0.5 mul\n"
2822 " 4 index 10 index add 0.5 mul\n"
2823 " 4 index 10 index add 0.5 mul\n"
2824 " 5 copy 5 copy 40 5 roll 25 5 roll 15 5 roll 25 5 roll\n");
2828 gl2psPrintf(
" STnoshfill STnoshfill STnoshfill STnoshfill } BD\n");
2834 gl2psPrintf(
"/STnoshfill {\n"
2835 " 2 index 8 index sub abs rThreshold gt\n"
2837 " { 1 index 7 index sub abs gThreshold gt\n"
2839 " { dup 6 index sub abs bThreshold gt\n"
2841 " { 2 index 13 index sub abs rThreshold gt\n"
2843 " { 1 index 12 index sub abs gThreshold gt\n"
2845 " { dup 11 index sub abs bThreshold gt\n"
2847 " { 7 index 13 index sub abs rThreshold gt\n");
2848 gl2psPrintf(
" { STsplit }\n"
2849 " { 6 index 12 index sub abs gThreshold gt\n"
2851 " { 5 index 11 index sub abs bThreshold gt\n"
2864 gl2psPrintf(
"tryPS3shading\n"
2866 " { /ST { STshfill } BD }\n"
2867 " { /ST { STnoshfill } BD }\n"
2869 "{ /ST { STnoshfill } BD }\n"
2875 "/DeviceRGB setcolorspace\n"
2879 "%%%%BeginPageSetup\n");
2881 if(gl2ps->options & GL2PS_LANDSCAPE){
2882 gl2psPrintf(
"%d 0 translate 90 rotate\n",
2883 (
int)gl2ps->viewport[3]);
2886 gl2psPrintf(
"%%%%EndPageSetup\n"
2891 if(gl2ps->options & GL2PS_DRAW_BACKGROUND){
2892 gl2psPrintf(
"%g %g %g C\n"
2893 "newpath %d %d moveto %d %d lineto %d %d lineto %d %d lineto\n"
2895 gl2ps->bgcolor[0], gl2ps->bgcolor[1], gl2ps->bgcolor[2],
2896 (
int)gl2ps->viewport[0], (
int)gl2ps->viewport[1], (
int)gl2ps->viewport[2],
2897 (
int)gl2ps->viewport[1], (
int)gl2ps->viewport[2], (
int)gl2ps->viewport[3],
2898 (
int)gl2ps->viewport[0], (
int)gl2ps->viewport[3]);
2902 static void gl2psPrintPostScriptColor(GL2PSrgba rgba)
2904 if(!gl2psSameColor(gl2ps->lastrgba, rgba)){
2905 gl2psSetLastColor(rgba);
2906 gl2psPrintf(
"%g %g %g C\n", rgba[0], rgba[1], rgba[2]);
2910 static void gl2psResetPostScriptColor(
void)
2912 gl2ps->lastrgba[0] = gl2ps->lastrgba[1] = gl2ps->lastrgba[2] = -1.;
2915 static void gl2psEndPostScriptLine(
void)
2918 if(gl2ps->lastvertex.rgba[0] >= 0.){
2919 gl2psPrintf(
"%g %g LE\n", gl2ps->lastvertex.xyz[0], gl2ps->lastvertex.xyz[1]);
2920 for(i = 0; i < 3; i++)
2921 gl2ps->lastvertex.xyz[i] = -1.;
2922 for(i = 0; i < 4; i++)
2923 gl2ps->lastvertex.rgba[i] = -1.;
2927 static void gl2psParseStipplePattern(GLushort pattern, GLint factor,
2928 int *nb,
int array[10])
2931 int on[8] = {0, 0, 0, 0, 0, 0, 0, 0};
2932 int off[8] = {0, 0, 0, 0, 0, 0, 0, 0};
2936 for(n = 15; n >= 0; n--){
2937 tmp[
n] = (char)(pattern & 0x01);
2942 for(i = 0; i < 8; i++){
2943 while(n < 16 && !tmp[n]){ off[i]++; n++; }
2944 while(n < 16 && tmp[n]){ on[i]++; n++; }
2945 if(n >= 15){ i++;
break; }
2954 for(n = i - 1; n >= 0; n--){
2955 array[(*nb)++] = factor * on[
n];
2956 array[(*nb)++] = factor * off[
n];
2957 if(*nb == 10)
break;
2961 static int gl2psPrintPostScriptDash(GLushort pattern, GLint factor,
const char *str)
2963 int len = 0, i,
n, array[10];
2965 if(pattern == gl2ps->lastpattern && factor == gl2ps->lastfactor)
2968 gl2ps->lastpattern = pattern;
2969 gl2ps->lastfactor =
factor;
2971 if(!pattern || !factor){
2973 len += gl2psPrintf(
"[] 0 %s\n", str);
2976 gl2psParseStipplePattern(pattern, factor, &n, array);
2977 len += gl2psPrintf(
"[");
2978 for(i = 0; i <
n; i++){
2979 if(i) len += gl2psPrintf(
" ");
2980 len += gl2psPrintf(
"%d", array[i]);
2982 len += gl2psPrintf(
"] 0 %s\n", str);
2988 static void gl2psPrintPostScriptPrimitive(
void *data)
2991 GL2PSprimitive *prim;
2993 prim = *(GL2PSprimitive**)data;
2995 if((gl2ps->options & GL2PS_OCCLUSION_CULL) && prim->culled)
return;
3002 if(prim->type != GL2PS_LINE) gl2psEndPostScriptLine();
3006 gl2psPrintPostScriptColor(prim->verts[0].rgba);
3007 gl2psPrintf(
"%g %g %g P\n",
3008 prim->verts[0].xyz[0], prim->verts[0].xyz[1], 0.5 * prim->width);
3011 if(!gl2psSamePosition(gl2ps->lastvertex.xyz, prim->verts[0].xyz) ||
3012 !gl2psSameColor(gl2ps->lastrgba, prim->verts[0].rgba) ||
3013 gl2ps->lastlinewidth != prim->width ||
3014 gl2ps->lastpattern != prim->pattern ||
3015 gl2ps->lastfactor != prim->factor){
3022 gl2psEndPostScriptLine();
3028 if(gl2ps->lastlinewidth != prim->width){
3029 gl2ps->lastlinewidth = prim->width;
3030 gl2psPrintf(
"%g W\n", gl2ps->lastlinewidth);
3032 gl2psPrintPostScriptDash(prim->pattern, prim->factor,
"setdash");
3033 gl2psPrintPostScriptColor(prim->verts[0].rgba);
3034 gl2psPrintf(
"%g %g %s\n", prim->verts[0].xyz[0], prim->verts[0].xyz[1],
3035 newline ?
"LS" :
"L");
3036 gl2ps->lastvertex = prim->verts[1];
3038 case GL2PS_TRIANGLE :
3039 if(!gl2psVertsSameColor(prim)){
3040 gl2psResetPostScriptColor();
3041 gl2psPrintf(
"%g %g %g %g %g %g %g %g %g %g %g %g %g %g %g ST\n",
3042 prim->verts[2].xyz[0], prim->verts[2].xyz[1],
3043 prim->verts[2].rgba[0], prim->verts[2].rgba[1],
3044 prim->verts[2].rgba[2], prim->verts[1].xyz[0],
3045 prim->verts[1].xyz[1], prim->verts[1].rgba[0],
3046 prim->verts[1].rgba[1], prim->verts[1].rgba[2],
3047 prim->verts[0].xyz[0], prim->verts[0].xyz[1],
3048 prim->verts[0].rgba[0], prim->verts[0].rgba[1],
3049 prim->verts[0].rgba[2]);
3052 gl2psPrintPostScriptColor(prim->verts[0].rgba);
3053 gl2psPrintf(
"%g %g %g %g %g %g T\n",
3054 prim->verts[2].xyz[0], prim->verts[2].xyz[1],
3055 prim->verts[1].xyz[0], prim->verts[1].xyz[1],
3056 prim->verts[0].xyz[0], prim->verts[0].xyz[1]);
3059 case GL2PS_QUADRANGLE :
3060 gl2psMsg(GL2PS_WARNING,
"There should not be any quad left to print");
3063 gl2psPrintPostScriptPixmap(prim->verts[0].xyz[0], prim->verts[0].xyz[1],
3066 case GL2PS_IMAGEMAP :
3067 if(prim->data.image->type != GL2PS_IMAGEMAP_WRITTEN){
3068 gl2psPrintPostScriptColor(prim->verts[0].rgba);
3069 gl2psPrintPostScriptImagemap(prim->data.image->pixels[0],
3070 prim->data.image->pixels[1],
3071 prim->data.image->width, prim->data.image->height,
3072 (
const unsigned char*)(&(prim->data.image->pixels[2])));
3073 prim->data.image->type = GL2PS_IMAGEMAP_WRITTEN;
3077 gl2psPrintPostScriptColor(prim->verts[0].rgba);
3078 gl2psPrintf(
"(%s) ", prim->data.text->str);
3079 if(prim->data.text->angle)
3080 gl2psPrintf(
"%g ", prim->data.text->angle);
3081 gl2psPrintf(
"%g %g %d /%s ",
3082 prim->verts[0].xyz[0], prim->verts[0].xyz[1],
3083 prim->data.text->fontsize, prim->data.text->fontname);
3084 switch(prim->data.text->alignment){
3086 gl2psPrintf(prim->data.text->angle ?
"SCCR\n" :
"SCC\n");
3089 gl2psPrintf(prim->data.text->angle ?
"SCLR\n" :
"SCL\n");
3092 gl2psPrintf(prim->data.text->angle ?
"SCRR\n" :
"SCR\n");
3095 gl2psPrintf(prim->data.text->angle ?
"SBCR\n" :
"SBC\n");
3098 gl2psPrintf(prim->data.text->angle ?
"SBRR\n" :
"SBR\n");
3101 gl2psPrintf(prim->data.text->angle ?
"STCR\n" :
"STC\n");
3104 gl2psPrintf(prim->data.text->angle ?
"STLR\n" :
"STL\n");
3107 gl2psPrintf(prim->data.text->angle ?
"STRR\n" :
"STR\n");
3111 gl2psPrintf(prim->data.text->angle ?
"SR\n" :
"S\n");
3115 case GL2PS_SPECIAL :
3118 if(prim->data.text->alignment == GL2PS_PS ||
3119 prim->data.text->alignment == GL2PS_EPS)
3120 gl2psPrintf(
"%s\n", prim->data.text->str);
3127 static void gl2psPrintPostScriptFooter(
void)
3129 gl2psPrintf(
"grestore\n"
3137 gl2psPrintGzipFooter();
3140 static void gl2psPrintPostScriptBeginViewport(GLint viewport[4])
3144 int x = viewport[0], y = viewport[1], w = viewport[2], h = viewport[3];
3146 glRenderMode(GL_FEEDBACK);
3149 gl2psPrintPostScriptHeader();
3150 gl2ps->header = GL_FALSE;
3153 gl2psPrintf(
"gsave\n"
3156 if(gl2ps->options & GL2PS_DRAW_BACKGROUND){
3157 if(gl2ps->colormode == GL_RGBA || gl2ps->colorsize == 0){
3158 glGetFloatv(GL_COLOR_CLEAR_VALUE, rgba);
3161 glGetIntegerv(GL_INDEX_CLEAR_VALUE, &index);
3162 rgba[0] = gl2ps->colormap[index][0];
3163 rgba[1] = gl2ps->colormap[index][1];
3164 rgba[2] = gl2ps->colormap[index][2];
3167 gl2psPrintf(
"%g %g %g C\n"
3168 "newpath %d %d moveto %d %d lineto %d %d lineto %d %d lineto\n"
3170 rgba[0], rgba[1], rgba[2],
3171 x, y, x+w, y, x+w, y+h, x, y+h);
3174 gl2psPrintf(
"newpath %d %d moveto %d %d lineto %d %d lineto %d %d lineto\n"
3176 x, y, x+w, y, x+w, y+h, x, y+h);
3180 static GLint gl2psPrintPostScriptEndViewport(
void)
3184 res = gl2psPrintPrimitives();
3185 gl2psPrintf(
"grestore\n");
3189 static void gl2psPrintPostScriptFinalPrimitive(
void)
3192 gl2psEndPostScriptLine();
3197 static GL2PSbackend gl2psPS = {
3198 gl2psPrintPostScriptHeader,
3199 gl2psPrintPostScriptFooter,
3200 gl2psPrintPostScriptBeginViewport,
3201 gl2psPrintPostScriptEndViewport,
3202 gl2psPrintPostScriptPrimitive,
3203 gl2psPrintPostScriptFinalPrimitive,
3208 static GL2PSbackend gl2psEPS = {
3209 gl2psPrintPostScriptHeader,
3210 gl2psPrintPostScriptFooter,
3211 gl2psPrintPostScriptBeginViewport,
3212 gl2psPrintPostScriptEndViewport,
3213 gl2psPrintPostScriptPrimitive,
3214 gl2psPrintPostScriptFinalPrimitive,
3216 "Encapsulated Postscript"
3225 static void gl2psPrintTeXHeader(
void)
3231 if(gl2ps->filename && strlen(gl2ps->filename) < 256){
3232 for(i = strlen(gl2ps->filename)-1; i >= 0; i--){
3233 if(gl2ps->filename[i] ==
'.'){
3234 strncpy(name, gl2ps->filename, i);
3239 if(i <= 0) strcpy(name, gl2ps->filename);
3242 strcpy(name,
"untitled");
3247 fprintf(gl2ps->stream,
3249 "%% Creator: GL2PS %d.%d.%d%s, %s\n"
3251 "%% CreationDate:\n",
3252 gl2ps->title, GL2PS_MAJOR_VERSION, GL2PS_MINOR_VERSION,
3253 GL2PS_PATCH_VERSION, GL2PS_EXTRA_VERSION, GL2PS_COPYRIGHT,
3256 fprintf(gl2ps->stream,
3257 "\\setlength{\\unitlength}{1pt}\n"
3258 "\\begin{picture}(0,0)\n"
3259 "\\includegraphics{%s}\n"
3260 "\\end{picture}%%\n"
3261 "%s\\begin{picture}(%d,%d)(0,0)\n",
3262 name, (gl2ps->options & GL2PS_LANDSCAPE) ?
"\\rotatebox{90}{" :
"",
3263 (
int)gl2ps->viewport[2], (
int)gl2ps->viewport[3]);
3266 static void gl2psPrintTeXPrimitive(
void *data)
3268 GL2PSprimitive *prim;
3270 prim = *(GL2PSprimitive**)data;
3274 fprintf(gl2ps->stream,
"\\fontsize{%d}{0}\n\\selectfont",
3275 prim->data.text->fontsize);
3276 fprintf(gl2ps->stream,
"\\put(%g,%g){\\makebox(0,0)",
3277 prim->verts[0].xyz[0], prim->verts[0].xyz[1]);
3278 switch(prim->data.text->alignment){
3280 fprintf(gl2ps->stream,
"{");
3283 fprintf(gl2ps->stream,
"[l]{");
3286 fprintf(gl2ps->stream,
"[r]{");
3289 fprintf(gl2ps->stream,
"[b]{");
3292 fprintf(gl2ps->stream,
"[br]{");
3295 fprintf(gl2ps->stream,
"[t]{");
3298 fprintf(gl2ps->stream,
"[tl]{");
3301 fprintf(gl2ps->stream,
"[tr]{");
3305 fprintf(gl2ps->stream,
"[bl]{");
3308 if(prim->data.text->angle)
3309 fprintf(gl2ps->stream,
"\\rotatebox{%g}{", prim->data.text->angle);
3310 fprintf(gl2ps->stream,
"\\textcolor[rgb]{%g,%g,%g}{{%s}}",
3311 prim->verts[0].rgba[0], prim->verts[0].rgba[1], prim->verts[0].rgba[2],
3312 prim->data.text->str);
3313 if(prim->data.text->angle)
3314 fprintf(gl2ps->stream,
"}");
3315 fprintf(gl2ps->stream,
"}}\n");
3317 case GL2PS_SPECIAL :
3320 if (prim->data.text->alignment == GL2PS_TEX)
3321 fprintf(gl2ps->stream,
"%s\n", prim->data.text->str);
3328 static void gl2psPrintTeXFooter(
void)
3330 fprintf(gl2ps->stream,
"\\end{picture}%s\n",
3331 (gl2ps->options & GL2PS_LANDSCAPE) ?
"}" :
"");
3334 static void gl2psPrintTeXBeginViewport(GLint[4])
3336 glRenderMode(GL_FEEDBACK);
3339 gl2psPrintTeXHeader();
3340 gl2ps->header = GL_FALSE;
3344 static GLint gl2psPrintTeXEndViewport(
void)
3346 return gl2psPrintPrimitives();
3349 static void gl2psPrintTeXFinalPrimitive(
void)
3355 static GL2PSbackend gl2psTEX = {
3356 gl2psPrintTeXHeader,
3357 gl2psPrintTeXFooter,
3358 gl2psPrintTeXBeginViewport,
3359 gl2psPrintTeXEndViewport,
3360 gl2psPrintTeXPrimitive,
3361 gl2psPrintTeXFinalPrimitive,
3372 static int gl2psPrintPDFCompressorType(
void)
3374 #if defined(GL2PS_HAVE_ZLIB)
3375 if(gl2ps->options & GL2PS_COMPRESS){
3376 return fprintf(gl2ps->stream,
"/Filter [/FlateDecode]\n");
3382 static int gl2psPrintPDFStrokeColor(GL2PSrgba rgba)
3386 gl2psSetLastColor(rgba);
3387 for(i = 0; i < 3; ++i){
3388 if(GL2PS_ZERO(rgba[i]))
3389 offs += gl2psPrintf(
"%.0f ", 0.);
3390 else if(rgba[i] < 1e-4 || rgba[i] > 1e6)
3391 offs += gl2psPrintf(
"%f ", rgba[i]);
3393 offs += gl2psPrintf(
"%g ", rgba[i]);
3395 offs += gl2psPrintf(
"RG\n");
3399 static int gl2psPrintPDFFillColor(GL2PSrgba rgba)
3403 for(i = 0; i < 3; ++i){
3404 if(GL2PS_ZERO(rgba[i]))
3405 offs += gl2psPrintf(
"%.0f ", 0.);
3406 else if(rgba[i] < 1e-4 || rgba[i] > 1e6)
3407 offs += gl2psPrintf(
"%f ", rgba[i]);
3409 offs += gl2psPrintf(
"%g ", rgba[i]);
3411 offs += gl2psPrintf(
"rg\n");
3415 static int gl2psPrintPDFLineWidth(GLfloat lw)
3418 return gl2psPrintf(
"%.0f w\n", 0.);
3419 else if(lw < 1e-4 || lw > 1e6)
3420 return gl2psPrintf(
"%f w\n", lw);
3422 return gl2psPrintf(
"%g w\n", lw);
3425 static void gl2psPutPDFText(GL2PSstring *text,
int cnt, GLfloat x, GLfloat y)
3427 GLfloat
rad, crad, srad;
3429 if(text->angle == 0.0F){
3430 gl2ps->streamlength += gl2psPrintf
3436 cnt, text->fontsize, x, y, text->str);
3439 rad = M_PI * text->angle / 180.0F;
3440 srad = (GLfloat)sin(rad);
3441 crad = (GLfloat)cos(rad);
3442 gl2ps->streamlength += gl2psPrintf
3445 "%f %f %f %f %f %f Tm\n"
3448 cnt, text->fontsize, crad, srad, -srad, crad, x, y, text->str);
3452 static void gl2psPutPDFImage(GL2PSimage *image,
int cnt, GLfloat x, GLfloat y)
3454 gl2ps->streamlength += gl2psPrintf
3456 "%d 0 0 %d %f %f cm\n"
3459 (
int)image->width, (
int)image->height, x, y, cnt);
3462 static void gl2psPDFstacksInit(
void)
3464 gl2ps->objects_stack = 7 + 1;
3465 gl2ps->extgs_stack = 0;
3466 gl2ps->font_stack = 0;
3467 gl2ps->im_stack = 0;
3468 gl2ps->trgroupobjects_stack = 0;
3469 gl2ps->shader_stack = 0;
3470 gl2ps->mshader_stack = 0;
3473 static void gl2psPDFgroupObjectInit(GL2PSpdfgroup *gro)
3478 gro->ptrlist = NULL;
3479 gro->fontno = gro->gsno = gro->imno = gro->maskshno = gro->shno
3480 = gro->trgroupno = gro->fontobjno = gro->imobjno = gro->shobjno
3481 = gro->maskshobjno = gro->gsobjno = gro->trgroupobjno = -1;
3486 static void gl2psPDFgroupListInit(
void)
3489 GL2PSprimitive *p = NULL;
3491 int lasttype = GL2PS_NO_TYPE;
3492 GL2PSrgba lastrgba = {-1.0F, -1.0F, -1.0F, -1.0F};
3493 GLushort lastpattern = 0;
3494 GLint lastfactor = 0;
3495 GLfloat lastwidth = 1;
3496 GL2PStriangle lastt, tmpt;
3497 int lastTriangleWasNotSimpleWithSameColor = 0;
3499 if(!gl2ps->pdfprimlist)
3502 gl2ps->pdfgrouplist = gl2psListCreate(500, 500,
sizeof(GL2PSpdfgroup));
3503 gl2psInitTriangle(&lastt);
3505 for(i = 0; i < gl2psListNbr(gl2ps->pdfprimlist); ++i){
3506 p = *(GL2PSprimitive**)gl2psListPointer(gl2ps->pdfprimlist, i);
3509 gl2psPDFgroupObjectInit(&gro);
3510 gro.ptrlist = gl2psListCreate(1, 2,
sizeof(GL2PSprimitive*));
3511 gro.imno = gl2ps->im_stack++;
3512 gl2psListAdd(gro.ptrlist, &p);
3513 gl2psListAdd(gl2ps->pdfgrouplist, &gro);
3516 gl2psPDFgroupObjectInit(&gro);
3517 gro.ptrlist = gl2psListCreate(1, 2,
sizeof(GL2PSprimitive*));
3518 gro.fontno = gl2ps->font_stack++;
3519 gl2psListAdd(gro.ptrlist, &p);
3520 gl2psListAdd(gl2ps->pdfgrouplist, &gro);
3523 if(lasttype != p->type || lastwidth != p->width ||
3524 lastpattern != p->pattern || lastfactor != p->factor ||
3525 !gl2psSameColor(p->verts[0].rgba, lastrgba)){
3526 gl2psPDFgroupObjectInit(&gro);
3527 gro.ptrlist = gl2psListCreate(1, 2,
sizeof(GL2PSprimitive*));
3528 gl2psListAdd(gro.ptrlist, &p);
3529 gl2psListAdd(gl2ps->pdfgrouplist, &gro);
3532 gl2psListAdd(gro.ptrlist, &p);
3534 lastpattern = p->pattern;
3535 lastfactor = p->factor;
3536 lastwidth = p->width;
3537 lastrgba[0] = p->verts[0].rgba[0];
3538 lastrgba[1] = p->verts[0].rgba[1];
3539 lastrgba[2] = p->verts[0].rgba[2];
3542 if(lasttype != p->type || lastwidth != p->width ||
3543 !gl2psSameColor(p->verts[0].rgba, lastrgba)){
3544 gl2psPDFgroupObjectInit(&gro);
3545 gro.ptrlist = gl2psListCreate(1,2,
sizeof(GL2PSprimitive*));
3546 gl2psListAdd(gro.ptrlist, &p);
3547 gl2psListAdd(gl2ps->pdfgrouplist, &gro);
3550 gl2psListAdd(gro.ptrlist, &p);
3552 lastwidth = p->width;
3553 lastrgba[0] = p->verts[0].rgba[0];
3554 lastrgba[1] = p->verts[0].rgba[1];
3555 lastrgba[2] = p->verts[0].rgba[2];
3557 case GL2PS_TRIANGLE:
3558 gl2psFillTriangleFromPrimitive(&tmpt, p, GL_TRUE);
3559 lastTriangleWasNotSimpleWithSameColor =
3560 !(tmpt.prop & T_CONST_COLOR && tmpt.prop & T_ALPHA_1) ||
3561 !gl2psSameColor(tmpt.vertex[0].rgba, lastt.vertex[0].rgba);
3562 if(lasttype == p->type && tmpt.prop == lastt.prop &&
3563 lastTriangleWasNotSimpleWithSameColor){
3565 gl2psListAdd(gro.ptrlist, &p);
3568 gl2psPDFgroupObjectInit(&gro);
3569 gro.ptrlist = gl2psListCreate(1, 2,
sizeof(GL2PSprimitive*));
3570 gl2psListAdd(gro.ptrlist, &p);
3571 gl2psListAdd(gl2ps->pdfgrouplist, &gro);
3582 static void gl2psSortOutTrianglePDFgroup(GL2PSpdfgroup *gro)
3585 GL2PSprimitive *prim = NULL;
3590 if(!gl2psListNbr(gro->ptrlist))
3593 prim = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, 0);
3595 if(prim->type != GL2PS_TRIANGLE)
3598 gl2psFillTriangleFromPrimitive(&t, prim, GL_TRUE);
3600 if(t.prop & T_CONST_COLOR && t.prop & T_ALPHA_LESS_1){
3601 gro->gsno = gl2ps->extgs_stack++;
3602 gro->gsobjno = gl2ps->objects_stack ++;
3604 else if(t.prop & T_CONST_COLOR && t.prop & T_VAR_ALPHA){
3605 gro->gsno = gl2ps->extgs_stack++;
3606 gro->gsobjno = gl2ps->objects_stack++;
3607 gro->trgroupno = gl2ps->trgroupobjects_stack++;
3608 gro->trgroupobjno = gl2ps->objects_stack++;
3609 gro->maskshno = gl2ps->mshader_stack++;
3610 gro->maskshobjno = gl2ps->objects_stack++;
3612 else if(t.prop & T_VAR_COLOR && t.prop & T_ALPHA_1){
3613 gro->shno = gl2ps->shader_stack++;
3614 gro->shobjno = gl2ps->objects_stack++;
3616 else if(t.prop & T_VAR_COLOR && t.prop & T_ALPHA_LESS_1){
3617 gro->gsno = gl2ps->extgs_stack++;
3618 gro->gsobjno = gl2ps->objects_stack++;
3619 gro->shno = gl2ps->shader_stack++;
3620 gro->shobjno = gl2ps->objects_stack++;
3622 else if(t.prop & T_VAR_COLOR && t.prop & T_VAR_ALPHA){
3623 gro->gsno = gl2ps->extgs_stack++;
3624 gro->gsobjno = gl2ps->objects_stack++;
3625 gro->shno = gl2ps->shader_stack++;
3626 gro->shobjno = gl2ps->objects_stack++;
3627 gro->trgroupno = gl2ps->trgroupobjects_stack++;
3628 gro->trgroupobjno = gl2ps->objects_stack++;
3629 gro->maskshno = gl2ps->mshader_stack++;
3630 gro->maskshobjno = gl2ps->objects_stack++;
3636 static void gl2psPDFgroupListWriteMainStream(
void)
3639 GL2PSprimitive *prim = NULL, *prev = NULL;
3643 if(!gl2ps->pdfgrouplist)
3646 for(i = 0; i < gl2psListNbr(gl2ps->pdfgrouplist); ++i){
3647 gro = (GL2PSpdfgroup*)gl2psListPointer(gl2ps->pdfgrouplist, i);
3649 lastel = gl2psListNbr(gro->ptrlist) - 1;
3653 prim = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, 0);
3657 gl2ps->streamlength += gl2psPrintf(
"1 J\n");
3658 gl2ps->streamlength += gl2psPrintPDFLineWidth(prim->width);
3659 gl2ps->streamlength += gl2psPrintPDFStrokeColor(prim->verts[0].rgba);
3660 for(j = 0; j <= lastel; ++j){
3661 prim = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, j);
3662 gl2ps->streamlength +=
3663 gl2psPrintf(
"%f %f m %f %f l\n",
3664 prim->verts[0].xyz[0], prim->verts[0].xyz[1],
3665 prim->verts[0].xyz[0], prim->verts[0].xyz[1]);
3667 gl2ps->streamlength += gl2psPrintf(
"S\n");
3668 gl2ps->streamlength += gl2psPrintf(
"0 J\n");
3674 gl2ps->streamlength += gl2psPrintPDFLineWidth(prim->width);
3675 gl2ps->streamlength += gl2psPrintPDFStrokeColor(prim->verts[0].rgba);
3676 gl2ps->streamlength += gl2psPrintPostScriptDash(prim->pattern, prim->factor,
"d");
3678 gl2ps->streamlength +=
3679 gl2psPrintf(
"%f %f m\n",
3680 prim->verts[0].xyz[0], prim->verts[0].xyz[1]);
3682 for(j = 1; j <= lastel; ++j){
3684 prim = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, j);
3685 if(!gl2psSamePosition(prim->verts[0].xyz, prev->verts[1].xyz)){
3689 gl2ps->streamlength +=
3690 gl2psPrintf(
"%f %f l\n",
3691 prev->verts[1].xyz[0], prev->verts[1].xyz[1]);
3692 gl2ps->streamlength +=
3693 gl2psPrintf(
"%f %f m\n",
3694 prim->verts[0].xyz[0], prim->verts[0].xyz[1]);
3699 gl2ps->streamlength +=
3700 gl2psPrintf(
"%f %f l\n",
3701 prim->verts[0].xyz[0], prim->verts[0].xyz[1]);
3705 gl2ps->streamlength +=
3706 gl2psPrintf(
"%f %f l\n",
3707 prim->verts[1].xyz[0], prim->verts[1].xyz[1]);
3708 gl2ps->streamlength += gl2psPrintf(
"S\n");
3710 case GL2PS_TRIANGLE:
3711 gl2psFillTriangleFromPrimitive(&t, prim, GL_TRUE);
3712 gl2psSortOutTrianglePDFgroup(gro);
3715 if(t.prop & T_CONST_COLOR && t.prop & T_ALPHA_1){
3716 gl2ps->streamlength += gl2psPrintPDFFillColor(t.vertex[0].rgba);
3717 for(j = 0; j <= lastel; ++j){
3718 prim = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, j);
3719 gl2psFillTriangleFromPrimitive(&t, prim, GL_FALSE);
3721 += gl2psPrintf(
"%f %f m\n"
3725 t.vertex[0].xyz[0], t.vertex[0].xyz[1],
3726 t.vertex[1].xyz[0], t.vertex[1].xyz[1],
3727 t.vertex[2].xyz[0], t.vertex[2].xyz[1]);
3732 else if(t.prop & T_CONST_COLOR && t.prop & T_ALPHA_LESS_1){
3733 gl2ps->streamlength += gl2psPrintf(
"q\n"
3736 gl2ps->streamlength += gl2psPrintPDFFillColor(prim->verts[0].rgba);
3737 for(j = 0; j <= lastel; ++j){
3738 prim = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, j);
3739 gl2psFillTriangleFromPrimitive(&t, prim, GL_FALSE);
3741 += gl2psPrintf(
"%f %f m\n"
3745 t.vertex[0].xyz[0], t.vertex[0].xyz[1],
3746 t.vertex[1].xyz[0], t.vertex[1].xyz[1],
3747 t.vertex[2].xyz[0], t.vertex[2].xyz[1]);
3749 gl2ps->streamlength += gl2psPrintf(
"Q\n");
3754 else if(t.prop & T_CONST_COLOR && t.prop & T_VAR_ALPHA){
3755 gl2ps->streamlength += gl2psPrintf(
"q\n"
3758 gro->gsno, gro->trgroupno);
3759 gl2ps->streamlength += gl2psPrintPDFFillColor(prim->verts[0].rgba);
3760 for(j = 0; j <= lastel; ++j){
3761 prim = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, j);
3762 gl2psFillTriangleFromPrimitive(&t, prim, GL_FALSE);
3764 += gl2psPrintf(
"%f %f m\n"
3768 t.vertex[0].xyz[0], t.vertex[0].xyz[1],
3769 t.vertex[1].xyz[0], t.vertex[1].xyz[1],
3770 t.vertex[2].xyz[0], t.vertex[2].xyz[1]);
3772 gl2ps->streamlength += gl2psPrintf(
"Q\n");
3776 else if(t.prop & T_VAR_COLOR && t.prop & T_ALPHA_1){
3777 gl2ps->streamlength += gl2psPrintf(
"/Sh%d sh\n", gro->shno);
3782 else if(t.prop & T_VAR_COLOR && t.prop & T_ALPHA_LESS_1){
3783 gl2ps->streamlength += gl2psPrintf(
"q\n"
3787 gro->gsno, gro->shno);
3792 else if(t.prop & T_VAR_COLOR && t.prop & T_VAR_ALPHA){
3793 gl2ps->streamlength += gl2psPrintf(
"q\n"
3798 gro->gsno, gro->trgroupno, gro->shno);
3802 for(j = 0; j <= lastel; ++j){
3803 prim = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, j);
3804 gl2psPutPDFImage(prim->data.image, gro->imno, prim->verts[0].xyz[0],
3805 prim->verts[0].xyz[1]);
3809 for(j = 0; j <= lastel; ++j){
3810 prim = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, j);
3811 gl2ps->streamlength += gl2psPrintPDFFillColor(prim->verts[0].rgba);
3812 gl2psPutPDFText(prim->data.text, gro->fontno, prim->verts[0].xyz[0],
3813 prim->verts[0].xyz[1]);
3824 static int gl2psPDFgroupListWriteGStateResources(
void)
3830 offs += fprintf(gl2ps->stream,
3834 for(i = 0; i < gl2psListNbr(gl2ps->pdfgrouplist); ++i){
3835 gro = (GL2PSpdfgroup*)gl2psListPointer(gl2ps->pdfgrouplist, i);
3837 offs += fprintf(gl2ps->stream,
"/GS%d %d 0 R\n", gro->gsno, gro->gsobjno);
3839 offs += fprintf(gl2ps->stream,
">>\n");
3845 static int gl2psPDFgroupListWriteShaderResources(
void)
3851 offs += fprintf(gl2ps->stream,
3854 for(i = 0; i < gl2psListNbr(gl2ps->pdfgrouplist); ++i){
3855 gro = (GL2PSpdfgroup*)gl2psListPointer(gl2ps->pdfgrouplist, i);
3857 offs += fprintf(gl2ps->stream,
"/Sh%d %d 0 R\n", gro->shno, gro->shobjno);
3858 if(gro->maskshno >= 0)
3859 offs += fprintf(gl2ps->stream,
"/TrSh%d %d 0 R\n", gro->maskshno, gro->maskshobjno);
3861 offs += fprintf(gl2ps->stream,
">>\n");
3867 static int gl2psPDFgroupListWriteXObjectResources(
void)
3870 GL2PSprimitive *p = NULL;
3874 offs += fprintf(gl2ps->stream,
3878 for(i = 0; i < gl2psListNbr(gl2ps->pdfgrouplist); ++i){
3879 gro = (GL2PSpdfgroup*)gl2psListPointer(gl2ps->pdfgrouplist, i);
3880 if(!gl2psListNbr(gro->ptrlist))
3882 p = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, 0);
3885 gro->imobjno = gl2ps->objects_stack++;
3886 if(GL_RGBA == p->data.image->format)
3887 gl2ps->objects_stack++;
3888 offs += fprintf(gl2ps->stream,
"/Im%d %d 0 R\n", gro->imno, gro->imobjno);
3889 case GL2PS_TRIANGLE:
3890 if(gro->trgroupno >=0)
3891 offs += fprintf(gl2ps->stream,
"/TrG%d %d 0 R\n", gro->trgroupno, gro->trgroupobjno);
3897 offs += fprintf(gl2ps->stream,
">>\n");
3903 static int gl2psPDFgroupListWriteFontResources(
void)
3909 offs += fprintf(gl2ps->stream,
"/Font\n<<\n");
3911 for(i = 0; i < gl2psListNbr(gl2ps->pdfgrouplist); ++i){
3912 gro = (GL2PSpdfgroup*)gl2psListPointer(gl2ps->pdfgrouplist, i);
3915 gro->fontobjno = gl2ps->objects_stack++;
3916 offs += fprintf(gl2ps->stream,
"/F%d %d 0 R\n", gro->fontno, gro->fontobjno);
3918 offs += fprintf(gl2ps->stream,
">>\n");
3923 static void gl2psPDFgroupListDelete(
void)
3926 GL2PSpdfgroup *gro = NULL;
3928 if(!gl2ps->pdfgrouplist)
3931 for(i = 0; i < gl2psListNbr(gl2ps->pdfgrouplist); ++i){
3932 gro = (GL2PSpdfgroup*)gl2psListPointer(gl2ps->pdfgrouplist,i);
3933 gl2psListDelete(gro->ptrlist);
3936 gl2psListDelete(gl2ps->pdfgrouplist);
3937 gl2ps->pdfgrouplist = NULL;
3942 static int gl2psPrintPDFInfo(
void)
3949 newtime = gmtime(&now);
3951 offs = fprintf(gl2ps->stream,
3955 "/Creator (GL2PS %d.%d.%d%s, %s)\n"
3957 gl2ps->title, GL2PS_MAJOR_VERSION, GL2PS_MINOR_VERSION,
3958 GL2PS_PATCH_VERSION, GL2PS_EXTRA_VERSION, GL2PS_COPYRIGHT,
3962 offs += fprintf(gl2ps->stream,
3968 offs += fprintf(gl2ps->stream,
3977 static int gl2psPrintPDFCatalog(
void)
3979 return fprintf(gl2ps->stream,
3988 static int gl2psPrintPDFPages(
void)
3990 return fprintf(gl2ps->stream,
4002 static int gl2psOpenPDFDataStream(
void)
4006 offs += fprintf(gl2ps->stream,
4009 "/Length 5 0 R\n" );
4010 offs += gl2psPrintPDFCompressorType();
4011 offs += fprintf(gl2ps->stream,
4019 static int gl2psOpenPDFDataStreamWritePreface(
void)
4023 offs = gl2psPrintf(
"/GSa gs\n");
4025 if(gl2ps->options & GL2PS_DRAW_BACKGROUND){
4026 offs += gl2psPrintPDFFillColor(gl2ps->bgcolor);
4027 offs += gl2psPrintf(
"%d %d %d %d re\n",
4028 (
int)gl2ps->viewport[0], (
int)gl2ps->viewport[1],
4029 (
int)gl2ps->viewport[2], (
int)gl2ps->viewport[3]);
4030 offs += gl2psPrintf(
"f\n");
4037 static void gl2psPrintPDFHeader(
void)
4040 gl2ps->pdfprimlist = gl2psListCreate(500, 500,
sizeof(GL2PSprimitive*));
4041 gl2psPDFstacksInit();
4043 gl2ps->xreflist = (
int*)gl2psMalloc(
sizeof(
int) * gl2ps->objects_stack);
4045 #if defined(GL2PS_HAVE_ZLIB)
4046 if(gl2ps->options & GL2PS_COMPRESS){
4047 gl2psSetupCompress();
4050 gl2ps->xreflist[0] = 0;
4051 offs += fprintf(gl2ps->stream,
"%%PDF-1.4\n");
4052 gl2ps->xreflist[1] = offs;
4054 offs += gl2psPrintPDFInfo();
4055 gl2ps->xreflist[2] = offs;
4057 offs += gl2psPrintPDFCatalog();
4058 gl2ps->xreflist[3] = offs;
4060 offs += gl2psPrintPDFPages();
4061 gl2ps->xreflist[4] = offs;
4063 offs += gl2psOpenPDFDataStream();
4064 gl2ps->xreflist[5] = offs;
4065 gl2ps->streamlength = gl2psOpenPDFDataStreamWritePreface();
4070 static void gl2psPrintPDFPrimitive(
void *data)
4072 GL2PSprimitive *prim = *(GL2PSprimitive**)data;
4074 if((gl2ps->options & GL2PS_OCCLUSION_CULL) && prim->culled)
4077 prim = gl2psCopyPrimitive(prim);
4078 gl2psListAdd(gl2ps->pdfprimlist, &prim);
4083 static int gl2psClosePDFDataStream(
void)
4087 #if defined(GL2PS_HAVE_ZLIB)
4088 if(gl2ps->options & GL2PS_COMPRESS){
4089 if(Z_OK != gl2psDeflate())
4090 gl2psMsg(GL2PS_ERROR,
"Zlib deflate error");
4092 fwrite(gl2ps->compress->dest, gl2ps->compress->destLen, 1, gl2ps->stream);
4093 gl2ps->streamlength += gl2ps->compress->destLen;
4095 offs += gl2ps->streamlength;
4096 gl2psFreeCompress();
4100 offs += fprintf(gl2ps->stream,
4108 static int gl2psPrintPDFDataStreamLength(
int val)
4110 return fprintf(gl2ps->stream,
4118 static int gl2psPrintPDFOpenPage(
void)
4124 offs = fprintf(gl2ps->stream,
4129 "/MediaBox [%d %d %d %d]\n",
4130 (
int)gl2ps->viewport[0], (
int)gl2ps->viewport[1],
4131 (
int)gl2ps->viewport[2], (
int)gl2ps->viewport[3]);
4133 if(gl2ps->options & GL2PS_LANDSCAPE)
4134 offs += fprintf(gl2ps->stream,
"/Rotate -90\n");
4136 offs += fprintf(gl2ps->stream,
4140 "/ProcSet [/PDF /Text /ImageB /ImageC] %%/ImageI\n");
4147 static int gl2psPDFgroupListWriteVariableResources(
void)
4152 offs += gl2psPDFgroupListWriteGStateResources();
4155 offs += gl2psPDFgroupListWriteShaderResources();
4158 offs += gl2psPDFgroupListWriteXObjectResources();
4161 offs += gl2psPDFgroupListWriteFontResources();
4164 offs += fprintf(gl2ps->stream,
4173 static int gl2psPrintPDFGSObject(
void)
4175 return fprintf(gl2ps->stream,
4178 "/Type /ExtGState\n"
4193 static int gl2psPrintPDFShaderStreamDataCoord(GL2PSvertex *vertex,
4194 size_t (*action)(
unsigned long data,
4196 GLfloat dx, GLfloat dy,
4197 GLfloat xmin, GLfloat ymin)
4206 if(
sizeof(
unsigned long) == 8) dmax = dmax - 2048.;
4208 offs += (*action)(edgeflag, 1);
4213 if(GL2PS_ZERO(dx * dy)){
4214 offs += (*action)(0, 4);
4215 offs += (*action)(0, 4);
4218 diff = (vertex->xyz[0] - xmin) / dx;
4223 imap = (
unsigned long)(diff * dmax);
4224 offs += (*action)(imap, 4);
4226 diff = (vertex->xyz[1] - ymin) / dy;
4231 imap = (
unsigned long)(diff * dmax);
4232 offs += (*action)(imap, 4);
4240 static int gl2psPrintPDFShaderStreamDataRGB(GL2PSvertex *vertex,
4241 size_t (*action)(
unsigned long data,
4249 if(
sizeof(
unsigned long) == 8) dmax = dmax - 2048.;
4251 imap = (
unsigned long)((vertex->rgba[0]) * dmax);
4252 offs += (*action)(imap, 1);
4254 imap = (
unsigned long)((vertex->rgba[1]) * dmax);
4255 offs += (*action)(imap, 1);
4257 imap = (
unsigned long)((vertex->rgba[2]) * dmax);
4258 offs += (*action)(imap, 1);
4265 static int gl2psPrintPDFShaderStreamDataAlpha(GL2PSvertex *vertex,
4266 size_t (*action)(
unsigned long data,
4275 if(
sizeof(
unsigned long) == 8) dmax = dmax - 2048.;
4277 if(sigbyte != 8 && sigbyte != 16)
4282 imap = (
unsigned long)((vertex->rgba[3]) * dmax);
4284 offs += (*action)(imap, sigbyte);
4291 static int gl2psPrintPDFShaderStreamData(GL2PStriangle *triangle,
4292 GLfloat dx, GLfloat dy,
4293 GLfloat xmin, GLfloat ymin,
4294 size_t (*action)(
unsigned long data,
4301 if(gray && gray != 8 && gray != 16)
4304 for(i = 0; i < 3; ++i){
4305 offs += gl2psPrintPDFShaderStreamDataCoord(&triangle->vertex[i], action,
4306 dx, dy, xmin, ymin);
4308 v = triangle->vertex[i];
4309 offs += gl2psPrintPDFShaderStreamDataAlpha(&v, action, gray);
4312 offs += gl2psPrintPDFShaderStreamDataRGB(&triangle->vertex[i], action);
4319 static void gl2psPDFRectHull(GLfloat *xmin, GLfloat *xmax,
4320 GLfloat *ymin, GLfloat *ymax,
4321 GL2PStriangle *triangles,
int cnt)
4325 *xmin = triangles[0].vertex[0].xyz[0];
4326 *xmax = triangles[0].vertex[0].xyz[0];
4327 *ymin = triangles[0].vertex[0].xyz[1];
4328 *ymax = triangles[0].vertex[0].xyz[1];
4330 for(i = 0; i < cnt; ++i){
4331 for(j = 0; j < 3; ++j){
4332 if(*xmin > triangles[i].vertex[j].xyz[0])
4333 *xmin = triangles[i].vertex[j].xyz[0];
4334 if(*xmax < triangles[i].vertex[j].xyz[0])
4335 *xmax = triangles[i].vertex[j].xyz[0];
4336 if(*ymin > triangles[i].vertex[j].xyz[1])
4337 *ymin = triangles[i].vertex[j].xyz[1];
4338 if(*ymax < triangles[i].vertex[j].xyz[1])
4339 *ymax = triangles[i].vertex[j].xyz[1];
4349 static int gl2psPrintPDFShader(
int obj, GL2PStriangle *triangles,
4352 int i, offs = 0, vertexbytes, done = 0;
4353 GLfloat xmin, xmax, ymin, ymax;
4357 vertexbytes = 1+4+4+1+1+1;
4360 vertexbytes = 1+4+4+1;
4363 vertexbytes = 1+4+4+2;
4367 vertexbytes = 1+4+4+1;
4371 gl2psPDFRectHull(&xmin, &xmax, &ymin, &ymax, triangles, size);
4373 offs += fprintf(gl2ps->stream,
4378 "/BitsPerCoordinate 32 "
4379 "/BitsPerComponent %d "
4381 "/Decode [%f %f %f %f 0 1 %s] ",
4383 (gray) ?
"/DeviceGray" :
"/DeviceRGB",
4385 xmin, xmax, ymin, ymax,
4386 (gray) ?
"" :
"0 1 0 1");
4388 #if defined(GL2PS_HAVE_ZLIB)
4389 if(gl2ps->options & GL2PS_COMPRESS){
4390 gl2psAllocCompress(vertexbytes * size * 3);
4392 for(i = 0; i < size; ++i)
4393 gl2psPrintPDFShaderStreamData(&triangles[i],
4394 xmax-xmin, ymax-ymin, xmin, ymin,
4395 gl2psWriteBigEndianCompress, gray);
4397 if(Z_OK == gl2psDeflate() && 23 + gl2ps->compress->destLen < gl2ps->compress->srcLen){
4398 offs += gl2psPrintPDFCompressorType();
4399 offs += fprintf(gl2ps->stream,
4403 (
int)gl2ps->compress->destLen);
4404 offs += gl2ps->compress->destLen * fwrite(gl2ps->compress->dest,
4405 gl2ps->compress->destLen,
4409 gl2psFreeCompress();
4416 offs += fprintf(gl2ps->stream,
4420 vertexbytes * 3 * size);
4421 for(i = 0; i < size; ++i)
4422 offs += gl2psPrintPDFShaderStreamData(&triangles[i],
4423 xmax-xmin, ymax-ymin, xmin, ymin,
4424 gl2psWriteBigEndian, gray);
4427 offs += fprintf(gl2ps->stream,
4436 static int gl2psPrintPDFShaderMask(
int obj,
int childobj)
4440 offs += fprintf(gl2ps->stream,
4445 "/BBox [ %d %d %d %d ]\n"
4446 "/Group \n<<\n/S /Transparency /CS /DeviceRGB\n"
4449 (
int)gl2ps->viewport[0], (
int)gl2ps->viewport[1],
4450 (
int)gl2ps->viewport[2], (
int)gl2ps->viewport[3]);
4453 ? strlen(
"/TrSh sh\n") + (int)log10((
double)childobj)+1
4454 : strlen(
"/TrSh0 sh\n");
4456 offs += fprintf(gl2ps->stream,
4461 offs += fprintf(gl2ps->stream,
4464 offs += fprintf(gl2ps->stream,
4475 static int gl2psPrintPDFShaderExtGS(
int obj,
int childobj)
4479 offs += fprintf(gl2ps->stream,
4484 offs += fprintf(gl2ps->stream,
4485 "/SMask << /S /Alpha /G %d 0 R >> ",
4488 offs += fprintf(gl2ps->stream,
4496 static int gl2psPrintPDFShaderSimpleExtGS(
int obj, GLfloat
alpha)
4500 offs += fprintf(gl2ps->stream,
4512 static int gl2psPrintPDFPixmapStreamData(GL2PSimage *im,
4513 size_t (*action)(
unsigned long data,
4520 if(im->format != GL_RGBA && gray)
4523 if(gray && gray != 8 && gray != 16)
4528 shift = (
sizeof(
unsigned long) - 1) * 8;
4530 for(y = 0; y < im->height; ++y){
4531 for(x = 0; x < im->width; ++x){
4532 a = gl2psGetRGB(im, x, y, &r, &g, &b);
4533 if(im->format == GL_RGBA && gray){
4534 (*action)((
unsigned long)(a * 255) << shift,
gray);
4537 (*action)((
unsigned long)(r * 255) << shift, 1);
4538 (*action)((
unsigned long)(g * 255) << shift, 1);
4539 (*action)((
unsigned long)(b * 255) << shift, 1);
4545 case 0:
return 3 * im->width * im->height;
4546 case 1:
return im->width * im->height;
4547 case 2:
return 2 * im->width * im->height;
4548 default:
return 3 * im->width * im->height;
4552 static int gl2psPrintPDFPixmap(
int obj,
int childobj, GL2PSimage *im,
int gray)
4554 int offs = 0, done = 0, sigbytes = 3;
4556 if(gray && gray !=8 && gray != 16)
4560 sigbytes = gray / 8;
4562 offs += fprintf(gl2ps->stream,
4570 "/BitsPerComponent 8\n",
4572 (
int)im->width, (
int)im->height,
4573 (gray) ?
"/DeviceGray" :
"/DeviceRGB" );
4574 if(GL_RGBA == im->format && gray == 0){
4575 offs += fprintf(gl2ps->stream,
4580 #if defined(GL2PS_HAVE_ZLIB)
4581 if(gl2ps->options & GL2PS_COMPRESS){
4582 gl2psAllocCompress((
int)(im->width * im->height * sigbytes));
4584 gl2psPrintPDFPixmapStreamData(im, gl2psWriteBigEndianCompress, gray);
4586 if(Z_OK == gl2psDeflate() && 23 + gl2ps->compress->destLen < gl2ps->compress->srcLen){
4587 offs += gl2psPrintPDFCompressorType();
4588 offs += fprintf(gl2ps->stream,
4592 (
int)gl2ps->compress->destLen);
4593 offs += gl2ps->compress->destLen * fwrite(gl2ps->compress->dest, gl2ps->compress->destLen,
4597 gl2psFreeCompress();
4604 offs += fprintf(gl2ps->stream,
4608 (
int)(im->width * im->height * sigbytes));
4609 offs += gl2psPrintPDFPixmapStreamData(im, gl2psWriteBigEndian, gray);
4612 offs += fprintf(gl2ps->stream,
4619 static int gl2psPrintPDFText(
int obj, GL2PSstring *
s,
int fontnumber)
4623 offs += fprintf(gl2ps->stream,
4630 "/Encoding /MacRomanEncoding\n"
4633 obj, fontnumber, s->fontname);
4639 static int gl2psPDFgroupListWriteObjects(
int entryoffs)
4642 GL2PSprimitive *p = NULL;
4644 int offs = entryoffs;
4645 GL2PStriangle *triangles;
4648 if(!gl2ps->pdfgrouplist)
4651 for(i = 0; i < gl2psListNbr(gl2ps->pdfgrouplist); ++i){
4652 gro = (GL2PSpdfgroup*)gl2psListPointer(gl2ps->pdfgrouplist, i);
4653 if(!gl2psListNbr(gro->ptrlist))
4655 p = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, 0);
4661 case GL2PS_TRIANGLE:
4662 size = gl2psListNbr(gro->ptrlist);
4663 triangles = (GL2PStriangle*)gl2psMalloc(
sizeof(GL2PStriangle) * size);
4664 for(j = 0; j < size; ++j){
4665 p = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, j);
4666 gl2psFillTriangleFromPrimitive(&triangles[j], p, GL_TRUE);
4668 if(triangles[0].prop & T_VAR_COLOR){
4669 gl2ps->xreflist[gro->shobjno] = offs;
4670 offs += gl2psPrintPDFShader(gro->shobjno, triangles, size, 0);
4672 if(triangles[0].prop & T_ALPHA_LESS_1){
4673 gl2ps->xreflist[gro->gsobjno] = offs;
4674 offs += gl2psPrintPDFShaderSimpleExtGS(gro->gsobjno, triangles[0].vertex[0].rgba[3]);
4676 if(triangles[0].prop & T_VAR_ALPHA){
4677 gl2ps->xreflist[gro->gsobjno] = offs;
4678 offs += gl2psPrintPDFShaderExtGS(gro->gsobjno, gro->trgroupobjno);
4679 gl2ps->xreflist[gro->trgroupobjno] = offs;
4680 offs += gl2psPrintPDFShaderMask(gro->trgroupobjno, gro->maskshno);
4681 gl2ps->xreflist[gro->maskshobjno] = offs;
4682 offs += gl2psPrintPDFShader(gro->maskshobjno, triangles, size, 8);
4684 gl2psFree(triangles);
4687 gl2ps->xreflist[gro->imobjno] = offs;
4688 offs += gl2psPrintPDFPixmap(gro->imobjno, gro->imobjno+1, p->data.image, 0);
4689 if(p->data.image->format == GL_RGBA){
4690 gl2ps->xreflist[gro->imobjno+1] = offs;
4691 offs += gl2psPrintPDFPixmap(gro->imobjno+1, -1, p->data.image, 8);
4695 gl2ps->xreflist[gro->fontobjno] = offs;
4696 offs += gl2psPrintPDFText(gro->fontobjno,p->data.text,gro->fontno);
4698 case GL2PS_SPECIAL :
4701 if(p->data.text->alignment == GL2PS_PDF)
4702 offs += fprintf(gl2ps->stream,
"%s\n", p->data.text->str);
4715 static void gl2psPrintPDFFooter(
void)
4719 gl2psPDFgroupListInit();
4720 gl2psPDFgroupListWriteMainStream();
4722 offs = gl2ps->xreflist[5] + gl2ps->streamlength;
4723 offs += gl2psClosePDFDataStream();
4724 gl2ps->xreflist[5] = offs;
4726 offs += gl2psPrintPDFDataStreamLength(gl2ps->streamlength);
4727 gl2ps->xreflist[6] = offs;
4728 gl2ps->streamlength = 0;
4730 offs += gl2psPrintPDFOpenPage();
4731 offs += gl2psPDFgroupListWriteVariableResources();
4732 gl2ps->xreflist = (
int*)gl2psRealloc(gl2ps->xreflist,
4733 sizeof(
int) * (gl2ps->objects_stack + 1));
4734 gl2ps->xreflist[7] = offs;
4736 offs += gl2psPrintPDFGSObject();
4737 gl2ps->xreflist[8] = offs;
4739 gl2ps->xreflist[gl2ps->objects_stack] =
4740 gl2psPDFgroupListWriteObjects(gl2ps->xreflist[8]);
4744 fprintf(gl2ps->stream,
4747 "%010d 65535 f \n", gl2ps->objects_stack, 0);
4749 for(i = 1; i < gl2ps->objects_stack; ++i)
4750 fprintf(gl2ps->stream,
"%010d 00000 n \n", gl2ps->xreflist[i]);
4752 fprintf(gl2ps->stream,
4761 gl2ps->objects_stack, gl2ps->xreflist[gl2ps->objects_stack]);
4764 gl2psFree(gl2ps->xreflist);
4765 gl2psListAction(gl2ps->pdfprimlist, gl2psFreePrimitive);
4766 gl2psListDelete(gl2ps->pdfprimlist);
4767 gl2psPDFgroupListDelete();
4769 #if defined(GL2PS_HAVE_ZLIB)
4770 if(gl2ps->options & GL2PS_COMPRESS){
4771 gl2psFreeCompress();
4772 gl2psFree(gl2ps->compress);
4773 gl2ps->compress = NULL;
4780 static void gl2psPrintPDFBeginViewport(GLint viewport[4])
4785 int x = viewport[0], y = viewport[1], w = viewport[2], h = viewport[3];
4787 glRenderMode(GL_FEEDBACK);
4790 gl2psPrintPDFHeader();
4791 gl2ps->header = GL_FALSE;
4794 offs += gl2psPrintf(
"q\n");
4796 if(gl2ps->options & GL2PS_DRAW_BACKGROUND){
4797 if(gl2ps->colormode == GL_RGBA || gl2ps->colorsize == 0){
4798 glGetFloatv(GL_COLOR_CLEAR_VALUE, rgba);
4801 glGetIntegerv(GL_INDEX_CLEAR_VALUE, &index);
4802 rgba[0] = gl2ps->colormap[index][0];
4803 rgba[1] = gl2ps->colormap[index][1];
4804 rgba[2] = gl2ps->colormap[index][2];
4807 offs += gl2psPrintPDFFillColor(rgba);
4808 offs += gl2psPrintf(
"%d %d %d %d re\n"
4814 offs += gl2psPrintf(
"%d %d %d %d re\n"
4820 gl2ps->streamlength += offs;
4823 static GLint gl2psPrintPDFEndViewport(
void)
4827 res = gl2psPrintPrimitives();
4828 gl2ps->streamlength += gl2psPrintf(
"Q\n");
4832 static void gl2psPrintPDFFinalPrimitive(
void)
4838 static GL2PSbackend gl2psPDF = {
4839 gl2psPrintPDFHeader,
4840 gl2psPrintPDFFooter,
4841 gl2psPrintPDFBeginViewport,
4842 gl2psPrintPDFEndViewport,
4843 gl2psPrintPDFPrimitive,
4844 gl2psPrintPDFFinalPrimitive,
4846 "Portable Document Format"
4855 static void gl2psSVGGetCoordsAndColors(
int n, GL2PSvertex *verts,
4856 GL2PSxyz *xyz, GL2PSrgba *rgba)
4860 for(i = 0; i <
n; i++){
4861 xyz[i][0] = verts[i].xyz[0];
4862 xyz[i][1] = gl2ps->viewport[3] - verts[i].xyz[1];
4864 for(j = 0; j < 4; j++)
4865 rgba[i][j] = verts[i].rgba[j];
4869 static void gl2psSVGGetColorString(GL2PSrgba rgba,
char str[32])
4871 int r = (int)(255. * rgba[0]);
4872 int g = (int)(255. * rgba[1]);
4873 int b = (int)(255. * rgba[2]);
4874 int rc = (r < 0) ? 0 : (r > 255) ? 255 : r;
4875 int gc = (g < 0) ? 0 : (g > 255) ? 255 : g;
4876 int bc = (b < 0) ? 0 : (b > 255) ? 255 : b;
4877 sprintf(str,
"#%2.2x%2.2x%2.2x", rc, gc, bc);
4880 static void gl2psPrintSVGHeader(
void)
4882 int x, y,
width, height;
4888 if (gl2ps->options & GL2PS_LANDSCAPE){
4889 x = (int)gl2ps->viewport[1];
4890 y = (
int)gl2ps->viewport[0];
4891 width = (int)gl2ps->viewport[3];
4892 height = (
int)gl2ps->viewport[2];
4895 x = (int)gl2ps->viewport[0];
4896 y = (
int)gl2ps->viewport[1];
4897 width = (int)gl2ps->viewport[2];
4898 height = (
int)gl2ps->viewport[3];
4902 gl2psPrintGzipHeader();
4904 gl2psPrintf(
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n");
4905 gl2psPrintf(
"<svg xmlns=\"http://www.w3.org/2000/svg\"\n");
4906 gl2psPrintf(
" xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n"
4907 " width=\"%dpx\" height=\"%dpx\" viewBox=\"%d %d %d %d\">\n",
4908 width, height, x, y, width, height);
4909 gl2psPrintf(
"<title>%s</title>\n", gl2ps->title);
4910 gl2psPrintf(
"<desc>\n");
4911 gl2psPrintf(
"Creator: GL2PS %d.%d.%d%s, %s\n"
4914 GL2PS_MAJOR_VERSION, GL2PS_MINOR_VERSION, GL2PS_PATCH_VERSION,
4915 GL2PS_EXTRA_VERSION, GL2PS_COPYRIGHT, gl2ps->producer);
4916 gl2psPrintf(
"</desc>\n");
4917 gl2psPrintf(
"<defs>\n");
4918 gl2psPrintf(
"</defs>\n");
4920 if(gl2ps->options & GL2PS_DRAW_BACKGROUND){
4921 gl2psSVGGetColorString(gl2ps->bgcolor, col);
4922 gl2psPrintf(
"<polygon fill=\"%s\" points=\"%d,%d %d,%d %d,%d %d,%d\"/>\n", col,
4923 (
int)gl2ps->viewport[0], (
int)gl2ps->viewport[1],
4924 (
int)gl2ps->viewport[2], (
int)gl2ps->viewport[1],
4925 (
int)gl2ps->viewport[2], (
int)gl2ps->viewport[3],
4926 (
int)gl2ps->viewport[0], (
int)gl2ps->viewport[3]);
4930 gl2psPrintf(
"<g shape-rendering=\"crispEdges\">\n");
4933 static void gl2psPrintSVGSmoothTriangle(GL2PSxyz xyz[3], GL2PSrgba rgba[3])
4944 if(gl2psSameColorThreshold(3, rgba, gl2ps->threshold)){
4945 gl2psSVGGetColorString(rgba[0], col);
4946 gl2psPrintf(
"<polygon fill=\"%s\" ", col);
4947 if(rgba[0][3] < 1.0F) gl2psPrintf(
"fill-opacity=\"%g\" ", rgba[0][3]);
4948 gl2psPrintf(
"points=\"%g,%g %g,%g %g,%g\"/>\n", xyz[0][0], xyz[0][1],
4949 xyz[1][0], xyz[1][1], xyz[2][0], xyz[2][1]);
4953 for(i = 0; i < 3; i++){
4954 xyz2[0][i] = xyz[0][i];
4955 xyz2[1][i] = 0.5F * (xyz[0][i] + xyz[1][i]);
4956 xyz2[2][i] = 0.5F * (xyz[0][i] + xyz[2][i]);
4958 for(i = 0; i < 4; i++){
4959 rgba2[0][i] = rgba[0][i];
4960 rgba2[1][i] = 0.5F * (rgba[0][i] + rgba[1][i]);
4961 rgba2[2][i] = 0.5F * (rgba[0][i] + rgba[2][i]);
4963 gl2psPrintSVGSmoothTriangle(xyz2, rgba2);
4964 for(i = 0; i < 3; i++){
4965 xyz2[0][i] = 0.5F * (xyz[0][i] + xyz[1][i]);
4966 xyz2[1][i] = xyz[1][i];
4967 xyz2[2][i] = 0.5F * (xyz[1][i] + xyz[2][i]);
4969 for(i = 0; i < 4; i++){
4970 rgba2[0][i] = 0.5F * (rgba[0][i] + rgba[1][i]);
4971 rgba2[1][i] = rgba[1][i];
4972 rgba2[2][i] = 0.5F * (rgba[1][i] + rgba[2][i]);
4974 gl2psPrintSVGSmoothTriangle(xyz2, rgba2);
4975 for(i = 0; i < 3; i++){
4976 xyz2[0][i] = 0.5F * (xyz[0][i] + xyz[2][i]);
4977 xyz2[1][i] = xyz[2][i];
4978 xyz2[2][i] = 0.5F * (xyz[1][i] + xyz[2][i]);
4980 for(i = 0; i < 4; i++){
4981 rgba2[0][i] = 0.5F * (rgba[0][i] + rgba[2][i]);
4982 rgba2[1][i] = rgba[2][i];
4983 rgba2[2][i] = 0.5F * (rgba[1][i] + rgba[2][i]);
4985 gl2psPrintSVGSmoothTriangle(xyz2, rgba2);
4986 for(i = 0; i < 3; i++){
4987 xyz2[0][i] = 0.5F * (xyz[0][i] + xyz[1][i]);
4988 xyz2[1][i] = 0.5F * (xyz[1][i] + xyz[2][i]);
4989 xyz2[2][i] = 0.5F * (xyz[0][i] + xyz[2][i]);
4991 for(i = 0; i < 4; i++){
4992 rgba2[0][i] = 0.5F * (rgba[0][i] + rgba[1][i]);
4993 rgba2[1][i] = 0.5F * (rgba[1][i] + rgba[2][i]);
4994 rgba2[2][i] = 0.5F * (rgba[0][i] + rgba[2][i]);
4996 gl2psPrintSVGSmoothTriangle(xyz2, rgba2);
5000 static void gl2psPrintSVGDash(GLushort pattern, GLint factor)
5002 int i,
n, array[10];
5004 if(!pattern || !factor)
return;
5006 gl2psParseStipplePattern(pattern, factor, &n, array);
5007 gl2psPrintf(
"stroke-dasharray=\"");
5008 for(i = 0; i <
n; i++){
5009 if(i) gl2psPrintf(
",");
5010 gl2psPrintf(
"%d", array[i]);
5015 static void gl2psEndSVGLine(
void)
5018 if(gl2ps->lastvertex.rgba[0] >= 0.){
5019 gl2psPrintf(
"%g,%g\"/>\n", gl2ps->lastvertex.xyz[0],
5020 gl2ps->viewport[3] - gl2ps->lastvertex.xyz[1]);
5021 for(i = 0; i < 3; i++)
5022 gl2ps->lastvertex.xyz[i] = -1.;
5023 for(i = 0; i < 4; i++)
5024 gl2ps->lastvertex.rgba[i] = -1.;
5028 #if defined(GL2PS_HAVE_LIBPNG)
5029 static void gl2psPrintSVGPixmap(GLfloat x, GLfloat y, GL2PSimage *pixmap)
5031 static void gl2psPrintSVGPixmap(GLfloat, GLfloat, GL2PSimage*)
5034 #if defined(GL2PS_HAVE_LIBPNG)
5045 png = gl2psListCreate(pixmap->width * pixmap->height * 3, 1000,
5046 sizeof(
unsigned char));
5047 gl2psConvertPixmapToPNG(pixmap, png);
5048 gl2psListEncodeBase64(png);
5049 gl2psPrintf(
"<image x=\"%g\" y=\"%g\" width=\"%d\" height=\"%d\"\n",
5050 x, y - pixmap->height, pixmap->width, pixmap->height);
5051 gl2psPrintf(
"xlink:href=\"data:image/png;base64,");
5052 for(i = 0; i < gl2psListNbr(png); i++){
5053 gl2psListRead(png, i, &c);
5054 gl2psPrintf(
"%c", c);
5056 gl2psPrintf(
"\"/>\n");
5057 gl2psListDelete(png);
5059 gl2psMsg(GL2PS_WARNING,
"GL2PS must be compiled with PNG support in "
5060 "order to embed images in SVG streams");
5064 static void gl2psPrintSVGPrimitive(
void *data)
5066 GL2PSprimitive *prim;
5072 prim = *(GL2PSprimitive**)data;
5074 if((gl2ps->options & GL2PS_OCCLUSION_CULL) && prim->culled)
return;
5079 if(prim->type != GL2PS_LINE) gl2psEndSVGLine();
5081 gl2psSVGGetCoordsAndColors(prim->numverts, prim->verts, xyz, rgba);
5085 gl2psSVGGetColorString(rgba[0], col);
5086 gl2psPrintf(
"<circle fill=\"%s\" ", col);
5087 if(rgba[0][3] < 1.0F) gl2psPrintf(
"fill-opacity=\"%g\" ", rgba[0][3]);
5088 gl2psPrintf(
"cx=\"%g\" cy=\"%g\" r=\"%g\"/>\n",
5089 xyz[0][0], xyz[0][1], 0.5 * prim->width);
5092 if(!gl2psSamePosition(gl2ps->lastvertex.xyz, prim->verts[0].xyz) ||
5093 !gl2psSameColor(gl2ps->lastrgba, prim->verts[0].rgba) ||
5094 gl2ps->lastlinewidth != prim->width ||
5095 gl2ps->lastpattern != prim->pattern ||
5096 gl2ps->lastfactor != prim->factor){
5107 gl2ps->lastvertex = prim->verts[1];
5108 gl2psSetLastColor(prim->verts[0].rgba);
5109 gl2ps->lastlinewidth = prim->width;
5110 gl2ps->lastpattern = prim->pattern;
5111 gl2ps->lastfactor = prim->factor;
5113 gl2psSVGGetColorString(rgba[0], col);
5114 gl2psPrintf(
"<polyline fill=\"none\" stroke=\"%s\" stroke-width=\"%g\" ",
5116 if(rgba[0][3] < 1.0F) gl2psPrintf(
"stroke-opacity=\"%g\" ", rgba[0][3]);
5117 gl2psPrintSVGDash(prim->pattern, prim->factor);
5118 gl2psPrintf(
"points=\"%g,%g ", xyz[0][0], xyz[0][1]);
5121 gl2psPrintf(
"%g,%g ", xyz[0][0], xyz[0][1]);
5124 case GL2PS_TRIANGLE :
5125 gl2psPrintSVGSmoothTriangle(xyz, rgba);
5127 case GL2PS_QUADRANGLE :
5128 gl2psMsg(GL2PS_WARNING,
"There should not be any quad left to print");
5131 gl2psPrintSVGPixmap(xyz[0][0], xyz[0][1], prim->data.image);
5134 gl2psSVGGetColorString(prim->verts[0].rgba, col);
5135 gl2psPrintf(
"<text fill=\"%s\" x=\"%g\" y=\"%g\" font-size=\"%d\" ",
5136 col, xyz[0][0], xyz[0][1], prim->data.text->fontsize);
5137 if(prim->data.text->angle)
5138 gl2psPrintf(
"transform=\"rotate(%g, %g, %g)\" ",
5139 -prim->data.text->angle, xyz[0][0], xyz[0][1]);
5140 if(!strcmp(prim->data.text->fontname,
"Times-Roman"))
5141 gl2psPrintf(
"font-family=\"Times\">");
5142 else if(!strcmp(prim->data.text->fontname,
"Times-Bold"))
5143 gl2psPrintf(
"font-family=\"Times\" font-weight=\"bold\">");
5144 else if(!strcmp(prim->data.text->fontname,
"Times-Italic"))
5145 gl2psPrintf(
"font-family=\"Times\" font-style=\"italic\">");
5146 else if(!strcmp(prim->data.text->fontname,
"Times-BoldItalic"))
5147 gl2psPrintf(
"font-family=\"Times\" font-style=\"italic\" font-weight=\"bold\">");
5148 else if(!strcmp(prim->data.text->fontname,
"Helvetica-Bold"))
5149 gl2psPrintf(
"font-family=\"Helvetica\" font-weight=\"bold\">");
5150 else if(!strcmp(prim->data.text->fontname,
"Helvetica-Oblique"))
5151 gl2psPrintf(
"font-family=\"Helvetica\" font-style=\"oblique\">");
5152 else if(!strcmp(prim->data.text->fontname,
"Helvetica-BoldOblique"))
5153 gl2psPrintf(
"font-family=\"Helvetica\" font-style=\"oblique\" font-weight=\"bold\">");
5154 else if(!strcmp(prim->data.text->fontname,
"Courier-Bold"))
5155 gl2psPrintf(
"font-family=\"Courier\" font-weight=\"bold\">");
5156 else if(!strcmp(prim->data.text->fontname,
"Courier-Oblique"))
5157 gl2psPrintf(
"font-family=\"Courier\" font-style=\"oblique\">");
5158 else if(!strcmp(prim->data.text->fontname,
"Courier-BoldOblique"))
5159 gl2psPrintf(
"font-family=\"Courier\" font-style=\"oblique\" font-weight=\"bold\">");
5161 gl2psPrintf(
"font-family=\"%s\">", prim->data.text->fontname);
5162 gl2psPrintf(
"%s</text>\n", prim->data.text->str);
5164 case GL2PS_SPECIAL :
5167 if(prim->data.text->alignment == GL2PS_SVG)
5168 gl2psPrintf(
"%s\n", prim->data.text->str);
5175 static void gl2psPrintSVGFooter(
void)
5177 gl2psPrintf(
"</g>\n");
5178 gl2psPrintf(
"</svg>\n");
5180 gl2psPrintGzipFooter();
5183 static void gl2psPrintSVGBeginViewport(GLint viewport[4])
5188 int x = viewport[0], y = viewport[1], w = viewport[2], h = viewport[3];
5190 glRenderMode(GL_FEEDBACK);
5193 gl2psPrintSVGHeader();
5194 gl2ps->header = GL_FALSE;
5197 if(gl2ps->options & GL2PS_DRAW_BACKGROUND){
5198 if(gl2ps->colormode == GL_RGBA || gl2ps->colorsize == 0){
5199 glGetFloatv(GL_COLOR_CLEAR_VALUE, rgba);
5202 glGetIntegerv(GL_INDEX_CLEAR_VALUE, &index);
5203 rgba[0] = gl2ps->colormap[index][0];
5204 rgba[1] = gl2ps->colormap[index][1];
5205 rgba[2] = gl2ps->colormap[index][2];
5208 gl2psSVGGetColorString(rgba, col);
5209 gl2psPrintf(
"<polygon fill=\"%s\" points=\"%d,%d %d,%d %d,%d %d,%d\"/>\n", col,
5210 x, gl2ps->viewport[3] - y,
5211 x + w, gl2ps->viewport[3] - y,
5212 x + w, gl2ps->viewport[3] - (y + h),
5213 x, gl2ps->viewport[3] - (y + h));
5216 gl2psPrintf(
"<clipPath id=\"cp%d%d%d%d\">\n", x, y, w, h);
5217 gl2psPrintf(
" <polygon points=\"%d,%d %d,%d %d,%d %d,%d\"/>\n",
5218 x, gl2ps->viewport[3] - y,
5219 x + w, gl2ps->viewport[3] - y,
5220 x + w, gl2ps->viewport[3] - (y + h),
5221 x, gl2ps->viewport[3] - (y + h));
5222 gl2psPrintf(
"</clipPath>\n");
5223 gl2psPrintf(
"<g clip-path=\"url(#cp%d%d%d%d)\">\n", x, y, w, h);
5226 static GLint gl2psPrintSVGEndViewport(
void)
5230 res = gl2psPrintPrimitives();
5231 gl2psPrintf(
"</g>\n");
5235 static void gl2psPrintSVGFinalPrimitive(
void)
5243 static GL2PSbackend gl2psSVG = {
5244 gl2psPrintSVGHeader,
5245 gl2psPrintSVGFooter,
5246 gl2psPrintSVGBeginViewport,
5247 gl2psPrintSVGEndViewport,
5248 gl2psPrintSVGPrimitive,
5249 gl2psPrintSVGFinalPrimitive,
5251 "Scalable Vector Graphics"
5260 static void gl2psPrintPGFColor(GL2PSrgba rgba)
5262 if(!gl2psSameColor(gl2ps->lastrgba, rgba)){
5263 gl2psSetLastColor(rgba);
5264 fprintf(gl2ps->stream,
"\\color[rgb]{%f,%f,%f}\n", rgba[0], rgba[1], rgba[2]);
5268 static void gl2psPrintPGFHeader(
void)
5274 fprintf(gl2ps->stream,
5276 "%% Creator: GL2PS %d.%d.%d%s, %s\n"
5278 "%% CreationDate:\n",
5279 gl2ps->title, GL2PS_MAJOR_VERSION, GL2PS_MINOR_VERSION,
5280 GL2PS_PATCH_VERSION, GL2PS_EXTRA_VERSION, GL2PS_COPYRIGHT,
5283 fprintf(gl2ps->stream,
"\\begin{pgfpicture}\n");
5284 if(gl2ps->options & GL2PS_DRAW_BACKGROUND){
5285 gl2psPrintPGFColor(gl2ps->bgcolor);
5286 fprintf(gl2ps->stream,
5287 "\\pgfpathrectanglecorners{"
5288 "\\pgfpoint{%dpt}{%dpt}}{\\pgfpoint{%dpt}{%dpt}}\n"
5289 "\\pgfusepath{fill}\n",
5290 (
int)gl2ps->viewport[0], (
int)gl2ps->viewport[1],
5291 (
int)gl2ps->viewport[2], (
int)gl2ps->viewport[3]);
5295 static void gl2psPrintPGFDash(GLushort pattern, GLint factor)
5297 int i,
n, array[10];
5299 if(pattern == gl2ps->lastpattern && factor == gl2ps->lastfactor)
5302 gl2ps->lastpattern = pattern;
5303 gl2ps->lastfactor =
factor;
5305 if(!pattern || !factor){
5307 fprintf(gl2ps->stream,
"\\pgfsetdash{}{0pt}\n");
5310 gl2psParseStipplePattern(pattern, factor, &n, array);
5311 fprintf(gl2ps->stream,
"\\pgfsetdash{");
5312 for(i = 0; i <
n; i++) fprintf(gl2ps->stream,
"{%dpt}", array[i]);
5313 fprintf(gl2ps->stream,
"}{0pt}\n");
5317 static const char *gl2psPGFTextAlignment(
int align)
5320 case GL2PS_TEXT_C :
return "center";
5321 case GL2PS_TEXT_CL :
return "west";
5322 case GL2PS_TEXT_CR :
return "east";
5323 case GL2PS_TEXT_B :
return "south";
5324 case GL2PS_TEXT_BR :
return "south east";
5325 case GL2PS_TEXT_T :
return "north";
5326 case GL2PS_TEXT_TL :
return "north west";
5327 case GL2PS_TEXT_TR :
return "north east";
5328 case GL2PS_TEXT_BL :
5329 default :
return "south west";
5333 static void gl2psPrintPGFPrimitive(
void *data)
5335 GL2PSprimitive *prim;
5337 prim = *(GL2PSprimitive**)data;
5342 gl2psPrintPGFColor(prim->verts[0].rgba);
5343 fprintf(gl2ps->stream,
5344 "\\pgfpathrectangle{\\pgfpoint{%fpt}{%fpt}}"
5345 "{\\pgfpoint{%fpt}{%fpt}}\n\\pgfusepath{fill}\n",
5346 prim->verts[0].xyz[0]-0.5*prim->width,
5347 prim->verts[0].xyz[1]-0.5*prim->width,
5348 prim->width,prim->width);
5351 gl2psPrintPGFColor(prim->verts[0].rgba);
5352 if(gl2ps->lastlinewidth != prim->width){
5353 gl2ps->lastlinewidth = prim->width;
5354 fprintf(gl2ps->stream,
"\\pgfsetlinewidth{%fpt}\n", gl2ps->lastlinewidth);
5356 gl2psPrintPGFDash(prim->pattern, prim->factor);
5357 fprintf(gl2ps->stream,
5358 "\\pgfpathmoveto{\\pgfpoint{%fpt}{%fpt}}\n"
5359 "\\pgflineto{\\pgfpoint{%fpt}{%fpt}}\n"
5360 "\\pgfusepath{stroke}\n",
5361 prim->verts[1].xyz[0], prim->verts[1].xyz[1],
5362 prim->verts[0].xyz[0], prim->verts[0].xyz[1]);
5364 case GL2PS_TRIANGLE :
5365 if(gl2ps->lastlinewidth != 0){
5366 gl2ps->lastlinewidth = 0;
5367 fprintf(gl2ps->stream,
"\\pgfsetlinewidth{0.01pt}\n");
5369 gl2psPrintPGFColor(prim->verts[0].rgba);
5370 fprintf(gl2ps->stream,
5371 "\\pgfpathmoveto{\\pgfpoint{%fpt}{%fpt}}\n"
5372 "\\pgflineto{\\pgfpoint{%fpt}{%fpt}}\n"
5373 "\\pgflineto{\\pgfpoint{%fpt}{%fpt}}\n"
5375 "\\pgfusepath{fill,stroke}\n",
5376 prim->verts[2].xyz[0], prim->verts[2].xyz[1],
5377 prim->verts[1].xyz[0], prim->verts[1].xyz[1],
5378 prim->verts[0].xyz[0], prim->verts[0].xyz[1]);
5381 fprintf(gl2ps->stream,
"{\n\\pgftransformshift{\\pgfpoint{%fpt}{%fpt}}\n",
5382 prim->verts[0].xyz[0], prim->verts[0].xyz[1]);
5384 if(prim->data.text->angle)
5385 fprintf(gl2ps->stream,
"\\pgftransformrotate{%f}{", prim->data.text->angle);
5387 fprintf(gl2ps->stream,
"\\pgfnode{rectangle}{%s}{\\fontsize{%d}{0}\\selectfont",
5388 gl2psPGFTextAlignment(prim->data.text->alignment),
5389 prim->data.text->fontsize);
5391 fprintf(gl2ps->stream,
"\\textcolor[rgb]{%g,%g,%g}{{%s}}",
5392 prim->verts[0].rgba[0], prim->verts[0].rgba[1],
5393 prim->verts[0].rgba[2], prim->data.text->str);
5395 fprintf(gl2ps->stream,
"}{}{\\pgfusepath{discard}}}\n");
5397 case GL2PS_SPECIAL :
5400 if (prim->data.text->alignment == GL2PS_PGF)
5401 fprintf(gl2ps->stream,
"%s\n", prim->data.text->str);
5408 static void gl2psPrintPGFFooter(
void)
5410 fprintf(gl2ps->stream,
"\\end{pgfpicture}\n");
5413 static void gl2psPrintPGFBeginViewport(GLint viewport[4])
5417 int x = viewport[0], y = viewport[1], w = viewport[2], h = viewport[3];
5419 glRenderMode(GL_FEEDBACK);
5422 gl2psPrintPGFHeader();
5423 gl2ps->header = GL_FALSE;
5426 fprintf(gl2ps->stream,
"\\begin{pgfscope}\n");
5427 if(gl2ps->options & GL2PS_DRAW_BACKGROUND){
5428 if(gl2ps->colormode == GL_RGBA || gl2ps->colorsize == 0){
5429 glGetFloatv(GL_COLOR_CLEAR_VALUE, rgba);
5432 glGetIntegerv(GL_INDEX_CLEAR_VALUE, &index);
5433 rgba[0] = gl2ps->colormap[index][0];
5434 rgba[1] = gl2ps->colormap[index][1];
5435 rgba[2] = gl2ps->colormap[index][2];
5438 gl2psPrintPGFColor(rgba);
5439 fprintf(gl2ps->stream,
5440 "\\pgfpathrectangle{\\pgfpoint{%dpt}{%dpt}}"
5441 "{\\pgfpoint{%dpt}{%dpt}}\n"
5442 "\\pgfusepath{fill}\n",
5446 fprintf(gl2ps->stream,
5447 "\\pgfpathrectangle{\\pgfpoint{%dpt}{%dpt}}"
5448 "{\\pgfpoint{%dpt}{%dpt}}\n"
5449 "\\pgfusepath{clip}\n",
5453 static GLint gl2psPrintPGFEndViewport(
void)
5456 res = gl2psPrintPrimitives();
5457 fprintf(gl2ps->stream,
"\\end{pgfscope}\n");
5461 static void gl2psPrintPGFFinalPrimitive(
void)
5467 static GL2PSbackend gl2psPGF = {
5468 gl2psPrintPGFHeader,
5469 gl2psPrintPGFFooter,
5470 gl2psPrintPGFBeginViewport,
5471 gl2psPrintPGFEndViewport,
5472 gl2psPrintPGFPrimitive,
5473 gl2psPrintPGFFinalPrimitive,
5475 "PGF Latex Graphics"
5487 static GL2PSbackend *gl2psbackends[] = {
5496 static void gl2psComputeTightBoundingBox(
void *data)
5498 GL2PSprimitive *prim;
5501 prim = *(GL2PSprimitive**)data;
5503 for(i = 0; i < prim->numverts; i++){
5504 if(prim->verts[i].xyz[0] < gl2ps->viewport[0])
5505 gl2ps->viewport[0] = (GLint)prim->verts[i].xyz[0];
5506 if(prim->verts[i].xyz[0] > gl2ps->viewport[2])
5507 gl2ps->viewport[2] = (GLint)(prim->verts[i].xyz[0] + 0.5F);
5508 if(prim->verts[i].xyz[1] < gl2ps->viewport[1])
5509 gl2ps->viewport[1] = (GLint)prim->verts[i].xyz[1];
5510 if(prim->verts[i].xyz[1] > gl2ps->viewport[3])
5511 gl2ps->viewport[3] = (GLint)(prim->verts[i].xyz[1] + 0.5F);
5515 static GLint gl2psPrintPrimitives(
void)
5518 GL2PSxyz eye = {0.0F, 0.0F, 100.0F * GL2PS_ZSCALE};
5521 used = glRenderMode(GL_RENDER);
5524 gl2psMsg(GL2PS_INFO,
"OpenGL feedback buffer overflow");
5525 return GL2PS_OVERFLOW;
5529 gl2psParseFeedbackBuffer(used);
5531 gl2psRescaleAndOffset();
5534 if(gl2psListNbr(gl2ps->primitives) &&
5535 (gl2ps->options & GL2PS_TIGHT_BOUNDING_BOX)){
5536 gl2ps->viewport[0] = gl2ps->viewport[1] = 100000;
5537 gl2ps->viewport[2] = gl2ps->viewport[3] = -100000;
5538 gl2psListAction(gl2ps->primitives, gl2psComputeTightBoundingBox);
5540 (gl2psbackends[gl2ps->format]->printHeader)();
5541 gl2ps->header = GL_FALSE;
5544 if(!gl2psListNbr(gl2ps->primitives)){
5546 return GL2PS_NO_FEEDBACK;
5549 switch(gl2ps->sort){
5550 case GL2PS_NO_SORT :
5551 gl2psListAction(gl2ps->primitives, gl2psbackends[gl2ps->format]->printPrimitive);
5552 gl2psListAction(gl2ps->primitives, gl2psFreePrimitive);
5554 gl2psListReset(gl2ps->primitives);
5556 case GL2PS_SIMPLE_SORT :
5557 gl2psListSort(gl2ps->primitives, gl2psCompareDepth);
5558 if(gl2ps->options & GL2PS_OCCLUSION_CULL){
5559 gl2psListActionInverse(gl2ps->primitives, gl2psAddInImageTree);
5560 gl2psFreeBspImageTree(&gl2ps->imagetree);
5562 gl2psListAction(gl2ps->primitives, gl2psbackends[gl2ps->format]->printPrimitive);
5563 gl2psListAction(gl2ps->primitives, gl2psFreePrimitive);
5565 gl2psListReset(gl2ps->primitives);
5567 case GL2PS_BSP_SORT :
5568 root = (GL2PSbsptree*)gl2psMalloc(
sizeof(GL2PSbsptree));
5569 gl2psBuildBspTree(root, gl2ps->primitives);
5570 if(GL_TRUE == gl2ps->boundary) gl2psBuildPolygonBoundary(root);
5571 if(gl2ps->options & GL2PS_OCCLUSION_CULL){
5572 gl2psTraverseBspTree(root, eye, -GL2PS_EPSILON, gl2psLess,
5573 gl2psAddInImageTree, 1);
5574 gl2psFreeBspImageTree(&gl2ps->imagetree);
5576 gl2psTraverseBspTree(root, eye, GL2PS_EPSILON, gl2psGreater,
5577 gl2psbackends[gl2ps->format]->printPrimitive, 0);
5578 gl2psFreeBspTree(&root);
5581 gl2ps->primitives = gl2psListCreate(500, 500,
sizeof(GL2PSprimitive*));
5584 gl2psbackends[gl2ps->format]->printFinalPrimitive();
5586 return GL2PS_SUCCESS;
5595 GL2PSDLL_API GLint gl2psBeginPage(
const char *title,
const char *producer,
5596 GLint viewport[4], GLint format, GLint sort,
5597 GLint options, GLint colormode,
5598 GLint colorsize, GL2PSrgba *colormap,
5599 GLint nr, GLint ng, GLint nb, GLint buffersize,
5600 FILE *stream,
const char *filename)
5606 gl2psMsg(GL2PS_ERROR,
"gl2psBeginPage called in wrong program state");
5610 gl2ps = (GL2PScontext*)gl2psMalloc(
sizeof(GL2PScontext));
5612 if(format >= 0 && format < (GLint)(
sizeof(gl2psbackends) /
sizeof(gl2psbackends[0]))){
5613 gl2ps->format = format;
5616 gl2psMsg(GL2PS_ERROR,
"Unknown output format: %d", format);
5623 case GL2PS_NO_SORT :
5624 case GL2PS_SIMPLE_SORT :
5625 case GL2PS_BSP_SORT :
5629 gl2psMsg(GL2PS_ERROR,
"Unknown sorting algorithm: %d", sort);
5636 gl2ps->stream = stream;
5639 gl2psMsg(GL2PS_ERROR,
"Bad file pointer");
5645 gl2ps->header = GL_TRUE;
5646 gl2ps->maxbestroot = 10;
5647 gl2ps->options = options;
5648 gl2ps->compress = NULL;
5649 gl2ps->imagemap_head = NULL;
5650 gl2ps->imagemap_tail = NULL;
5652 if(gl2ps->options & GL2PS_USE_CURRENT_VIEWPORT){
5653 glGetIntegerv(GL_VIEWPORT, gl2ps->viewport);
5656 for(i = 0; i < 4; i++){
5657 gl2ps->viewport[i] = viewport[i];
5661 if(!gl2ps->viewport[2] || !gl2ps->viewport[3]){
5662 gl2psMsg(GL2PS_ERROR,
"Incorrect viewport (x=%d, y=%d, width=%d, height=%d)",
5663 gl2ps->viewport[0], gl2ps->viewport[1],
5664 gl2ps->viewport[2], gl2ps->viewport[3]);
5670 gl2ps->threshold[0] = nr ? 1.0F / (GLfloat)nr : 0.064F;
5671 gl2ps->threshold[1] = ng ? 1.0F / (GLfloat)ng : 0.034F;
5672 gl2ps->threshold[2] = nb ? 1.0F / (GLfloat)nb : 0.100F;
5673 gl2ps->colormode = colormode;
5674 gl2ps->buffersize = buffersize > 0 ? buffersize : 2048 * 2048;
5675 for(i = 0; i < 3; i++){
5676 gl2ps->lastvertex.xyz[i] = -1.0F;
5678 for(i = 0; i < 4; i++){
5679 gl2ps->lastvertex.rgba[i] = -1.0F;
5680 gl2ps->lastrgba[i] = -1.0F;
5682 gl2ps->lastlinewidth = -1.0F;
5683 gl2ps->lastpattern = 0;
5684 gl2ps->lastfactor = 0;
5685 gl2ps->imagetree = NULL;
5686 gl2ps->primitivetoadd = NULL;
5687 gl2ps->zerosurfacearea = GL_FALSE;
5688 gl2ps->pdfprimlist = NULL;
5689 gl2ps->pdfgrouplist = NULL;
5690 gl2ps->xreflist = NULL;
5694 gl2ps->blending = (gl2ps->format == GL2PS_SVG) ? GL_TRUE : glIsEnabled(GL_BLEND);
5695 glGetIntegerv(GL_BLEND_SRC, &gl2ps->blendfunc[0]);
5696 glGetIntegerv(GL_BLEND_DST, &gl2ps->blendfunc[1]);
5698 if(gl2ps->colormode == GL_RGBA){
5699 gl2ps->colorsize = 0;
5700 gl2ps->colormap = NULL;
5701 glGetFloatv(GL_COLOR_CLEAR_VALUE, gl2ps->bgcolor);
5703 else if(gl2ps->colormode == GL_COLOR_INDEX){
5704 if(!colorsize || !colormap){
5705 gl2psMsg(GL2PS_ERROR,
"Missing colormap for GL_COLOR_INDEX rendering");
5710 gl2ps->colorsize = colorsize;
5711 gl2ps->colormap = (GL2PSrgba*)gl2psMalloc(gl2ps->colorsize *
sizeof(GL2PSrgba));
5712 memcpy(gl2ps->colormap, colormap, gl2ps->colorsize *
sizeof(GL2PSrgba));
5713 glGetIntegerv(GL_INDEX_CLEAR_VALUE, &index);
5714 gl2ps->bgcolor[0] = gl2ps->colormap[index][0];
5715 gl2ps->bgcolor[1] = gl2ps->colormap[index][1];
5716 gl2ps->bgcolor[2] = gl2ps->colormap[index][2];
5717 gl2ps->bgcolor[3] = 1.0F;
5720 gl2psMsg(GL2PS_ERROR,
"Unknown color mode in gl2psBeginPage");
5727 gl2ps->title = (
char*)gl2psMalloc(
sizeof(
char));
5728 gl2ps->title[0] =
'\0';
5731 gl2ps->title = (
char*)gl2psMalloc((strlen(title)+1)*
sizeof(
char));
5732 strcpy(gl2ps->title, title);
5736 gl2ps->producer = (
char*)gl2psMalloc(
sizeof(
char));
5737 gl2ps->producer[0] =
'\0';
5740 gl2ps->producer = (
char*)gl2psMalloc((strlen(producer)+1)*
sizeof(
char));
5741 strcpy(gl2ps->producer, producer);
5745 gl2ps->filename = (
char*)gl2psMalloc(
sizeof(
char));
5746 gl2ps->filename[0] =
'\0';
5749 gl2ps->filename = (
char*)gl2psMalloc((strlen(filename)+1)*
sizeof(
char));
5750 strcpy(gl2ps->filename, filename);
5753 gl2ps->primitives = gl2psListCreate(500, 500,
sizeof(GL2PSprimitive*));
5754 gl2ps->auxprimitives = gl2psListCreate(100, 100,
sizeof(GL2PSprimitive*));
5755 gl2ps->feedback = (GLfloat*)gl2psMalloc(gl2ps->buffersize *
sizeof(GLfloat));
5756 glFeedbackBuffer(gl2ps->buffersize, GL_3D_COLOR, gl2ps->feedback);
5757 glRenderMode(GL_FEEDBACK);
5759 return GL2PS_SUCCESS;
5762 GL2PSDLL_API GLint gl2psEndPage(
void)
5766 if(!gl2ps)
return GL2PS_UNINITIALIZED;
5768 res = gl2psPrintPrimitives();
5770 if(res != GL2PS_OVERFLOW)
5771 (gl2psbackends[gl2ps->format]->printFooter)();
5773 fflush(gl2ps->stream);
5775 gl2psListDelete(gl2ps->primitives);
5776 gl2psListDelete(gl2ps->auxprimitives);
5777 gl2psFreeImagemap(gl2ps->imagemap_head);
5778 gl2psFree(gl2ps->colormap);
5779 gl2psFree(gl2ps->title);
5780 gl2psFree(gl2ps->producer);
5781 gl2psFree(gl2ps->filename);
5782 gl2psFree(gl2ps->feedback);
5789 GL2PSDLL_API GLint gl2psBeginViewport(GLint viewport[4])
5791 if(!gl2ps)
return GL2PS_UNINITIALIZED;
5793 (gl2psbackends[gl2ps->format]->beginViewport)(viewport);
5795 return GL2PS_SUCCESS;
5798 GL2PSDLL_API GLint gl2psEndViewport(
void)
5802 if(!gl2ps)
return GL2PS_UNINITIALIZED;
5804 res = (gl2psbackends[gl2ps->format]->endViewport)();
5807 gl2ps->lastlinewidth = -1.0F;
5812 GL2PSDLL_API GLint gl2psTextOpt(
const char *str,
const char *fontname,
5813 GLshort fontsize, GLint alignment, GLfloat angle)
5815 return gl2psAddText(GL2PS_TEXT, str, fontname, fontsize, alignment, angle);
5818 GL2PSDLL_API GLint gl2psText(
const char *str,
const char *fontname, GLshort fontsize)
5820 return gl2psAddText(GL2PS_TEXT, str, fontname, fontsize, GL2PS_TEXT_BL, 0.0F);
5823 GL2PSDLL_API GLint gl2psSpecial(GLint format,
const char *str)
5825 return gl2psAddText(GL2PS_SPECIAL, str,
"", 0, format, 0.0F);
5828 GL2PSDLL_API GLint gl2psDrawPixels(GLsizei width, GLsizei height,
5829 GLint xorig, GLint yorig,
5830 GLenum format, GLenum type,
5834 GLfloat pos[4], *piv;
5835 GL2PSprimitive *prim;
5838 if(!gl2ps || !pixels)
return GL2PS_UNINITIALIZED;
5840 if((width <= 0) || (height <= 0))
return GL2PS_ERROR;
5842 if(gl2ps->options & GL2PS_NO_PIXMAP)
return GL2PS_SUCCESS;
5844 if((format != GL_RGB && format != GL_RGBA) || type != GL_FLOAT){
5845 gl2psMsg(GL2PS_ERROR,
"gl2psDrawPixels only implemented for "
5846 "GL_RGB/GL_RGBA, GL_FLOAT pixels");
5850 glGetBooleanv(GL_CURRENT_RASTER_POSITION_VALID, &valid);
5851 if(GL_FALSE == valid)
return GL2PS_SUCCESS;
5853 glGetFloatv(GL_CURRENT_RASTER_POSITION, pos);
5855 prim = (GL2PSprimitive*)gl2psMalloc(
sizeof(GL2PSprimitive));
5856 prim->type = GL2PS_PIXMAP;
5859 prim->verts = (GL2PSvertex*)gl2psMalloc(
sizeof(GL2PSvertex));
5860 prim->verts[0].xyz[0] = pos[0] + xorig;
5861 prim->verts[0].xyz[1] = pos[1] + yorig;
5862 prim->verts[0].xyz[2] = pos[2];
5868 glGetFloatv(GL_CURRENT_RASTER_COLOR, prim->verts[0].rgba);
5869 prim->data.image = (GL2PSimage*)gl2psMalloc(
sizeof(GL2PSimage));
5870 prim->data.image->width =
width;
5871 prim->data.image->height = height;
5872 prim->data.image->format = format;
5873 prim->data.image->type = type;
5877 if(gl2ps->options & GL2PS_NO_BLENDING || !gl2ps->blending){
5879 prim->data.image->format = GL_RGB;
5880 size = height * width * 3;
5881 prim->data.image->pixels = (GLfloat*)gl2psMalloc(size *
sizeof(GLfloat));
5882 piv = (GLfloat*)pixels;
5883 for(i = 0; i < size; ++i, ++piv){
5884 prim->data.image->pixels[i] = *piv;
5890 size = height * width * 4;
5891 prim->data.image->pixels = (GLfloat*)gl2psMalloc(size *
sizeof(GLfloat));
5892 memcpy(prim->data.image->pixels, pixels, size *
sizeof(GLfloat));
5897 size = height * width * 3;
5898 prim->data.image->pixels = (GLfloat*)gl2psMalloc(size *
sizeof(GLfloat));
5899 memcpy(prim->data.image->pixels, pixels, size *
sizeof(GLfloat));
5903 gl2psListAdd(gl2ps->auxprimitives, &prim);
5904 glPassThrough(GL2PS_DRAW_PIXELS_TOKEN);
5906 return GL2PS_SUCCESS;
5909 GL2PSDLL_API GLint gl2psDrawImageMap(GLsizei width, GLsizei height,
5911 const unsigned char *imagemap){
5913 int sizeoffloat =
sizeof(GLfloat);
5915 if(!gl2ps || !imagemap)
return GL2PS_UNINITIALIZED;
5917 if((width <= 0) || (height <= 0))
return GL2PS_ERROR;
5919 size = height + height * ((width - 1) / 8);
5920 glPassThrough(GL2PS_IMAGEMAP_TOKEN);
5922 glVertex3f(position[0], position[1],position[2]);
5924 glPassThrough((GLfloat)width);
5925 glPassThrough((GLfloat)height);
5926 for(i = 0; i < size; i += sizeoffloat){
5927 float *value = (
float*)imagemap;
5928 glPassThrough(*value);
5929 imagemap += sizeoffloat;
5931 return GL2PS_SUCCESS;
5934 GL2PSDLL_API GLint gl2psEnable(GLint mode)
5938 if(!gl2ps)
return GL2PS_UNINITIALIZED;
5941 case GL2PS_POLYGON_OFFSET_FILL :
5942 glPassThrough(GL2PS_BEGIN_OFFSET_TOKEN);
5943 glGetFloatv(GL_POLYGON_OFFSET_FACTOR, &gl2ps->offset[0]);
5944 glGetFloatv(GL_POLYGON_OFFSET_UNITS, &gl2ps->offset[1]);
5946 case GL2PS_POLYGON_BOUNDARY :
5947 glPassThrough(GL2PS_BEGIN_BOUNDARY_TOKEN);
5949 case GL2PS_LINE_STIPPLE :
5950 glPassThrough(GL2PS_BEGIN_STIPPLE_TOKEN);
5951 glGetIntegerv(GL_LINE_STIPPLE_PATTERN, &tmp);
5952 glPassThrough((GLfloat)tmp);
5953 glGetIntegerv(GL_LINE_STIPPLE_REPEAT, &tmp);
5954 glPassThrough((GLfloat)tmp);
5957 glPassThrough(GL2PS_BEGIN_BLEND_TOKEN);
5960 gl2psMsg(GL2PS_WARNING,
"Unknown mode in gl2psEnable: %d", mode);
5961 return GL2PS_WARNING;
5964 return GL2PS_SUCCESS;
5967 GL2PSDLL_API GLint gl2psDisable(GLint mode)
5969 if(!gl2ps)
return GL2PS_UNINITIALIZED;
5972 case GL2PS_POLYGON_OFFSET_FILL :
5973 glPassThrough(GL2PS_END_OFFSET_TOKEN);
5975 case GL2PS_POLYGON_BOUNDARY :
5976 glPassThrough(GL2PS_END_BOUNDARY_TOKEN);
5978 case GL2PS_LINE_STIPPLE :
5979 glPassThrough(GL2PS_END_STIPPLE_TOKEN);
5982 glPassThrough(GL2PS_END_BLEND_TOKEN);
5985 gl2psMsg(GL2PS_WARNING,
"Unknown mode in gl2psDisable: %d", mode);
5986 return GL2PS_WARNING;
5989 return GL2PS_SUCCESS;
5992 GL2PSDLL_API GLint gl2psPointSize(GLfloat value)
5994 if(!gl2ps)
return GL2PS_UNINITIALIZED;
5996 glPassThrough(GL2PS_POINT_SIZE_TOKEN);
5997 glPassThrough(value);
5999 return GL2PS_SUCCESS;
6002 GL2PSDLL_API GLint gl2psLineWidth(GLfloat value)
6004 if(!gl2ps)
return GL2PS_UNINITIALIZED;
6006 glPassThrough(GL2PS_LINE_WIDTH_TOKEN);
6007 glPassThrough(value);
6009 return GL2PS_SUCCESS;
6012 GL2PSDLL_API GLint gl2psBlendFunc(GLenum sfactor, GLenum dfactor)
6014 if(!gl2ps)
return GL2PS_UNINITIALIZED;
6016 if(GL_FALSE == gl2psSupportedBlendMode(sfactor, dfactor))
6017 return GL2PS_WARNING;
6019 glPassThrough(GL2PS_SRC_BLEND_TOKEN);
6020 glPassThrough((GLfloat)sfactor);
6021 glPassThrough(GL2PS_DST_BLEND_TOKEN);
6022 glPassThrough((GLfloat)dfactor);
6024 return GL2PS_SUCCESS;
6027 GL2PSDLL_API GLint gl2psSetOptions(GLint options)
6029 if(!gl2ps)
return GL2PS_UNINITIALIZED;
6031 gl2ps->options = options;
6033 return GL2PS_SUCCESS;
6036 GL2PSDLL_API GLint gl2psGetOptions(GLint *options)
6040 return GL2PS_UNINITIALIZED;
6043 *options = gl2ps->options;
6045 return GL2PS_SUCCESS;
6048 GL2PSDLL_API
const char *gl2psGetFileExtension(GLint format)
6050 if(format >= 0 && format < (GLint)(
sizeof(gl2psbackends) /
sizeof(gl2psbackends[0])))
6051 return gl2psbackends[format]->file_extension;
6053 return "Unknown format";
6056 GL2PSDLL_API
const char *gl2psGetFormatDescription(GLint format)
6058 if(format >= 0 && format < (GLint)(
sizeof(gl2psbackends) /
sizeof(gl2psbackends[0])))
6059 return gl2psbackends[format]->description;
6061 return "Unknown format";
unsigned long ZEXPORT crc32(unsigned long crc, const unsigned char FAR *buf, uInt len)
static const G4double factor
int ZEXPORT compress(Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen)
static const G4double alpha
static const G4double pos