ATLAS Offline Software
Loading...
Searching...
No Matches
gl2ps.cxx
Go to the documentation of this file.
1/*
2 * GL2PS, an OpenGL to PostScript Printing Library
3 * Copyright (C) 1999-2025 C. Geuzaine
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of either:
7 *
8 * a) the GNU Library General Public License as published by the Free
9 * Software Foundation, either version 2 of the License, or (at your
10 * option) any later version; or
11 *
12 * b) the GL2PS License as published by Christophe Geuzaine, either
13 * version 2 of the License, or (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See either
18 * the GNU Library General Public License or the GL2PS License for
19 * more details.
20 *
21 * You should have received a copy of the GNU Library General Public
22 * License along with this library in the file named "COPYING.LGPL";
23 * if not, write to the Free Software Foundation, Inc., 675 Mass Ave,
24 * Cambridge, MA 02139, USA.
25 *
26 * You should have received a copy of the GL2PS License with this
27 * library in the file named "COPYING.GL2PS"; if not, I will be glad
28 * to provide one.
29 *
30 * For the latest info about gl2ps and a full list of contributors,
31 * see http://www.geuz.org/gl2ps/.
32 *
33 * Please report all bugs and problems to <gl2ps@geuz.org>.
34 */
35
36// #define GL2PS_HAVE_LIBPNG
37// #define GL2PS_HAVE_ZLIB
38
39
40#include "VP1HEPVis/gl2ps.h"
41
42#include <math.h>
43#include <string.h>
44#include <sys/types.h>
45#include <stdarg.h>
46#include <time.h>
47#include <float.h>
48
49#if defined(GL2PS_HAVE_ZLIB)
50#include <zlib.h>
51#endif
52
53#if defined(GL2PS_HAVE_LIBPNG)
54#include <png.h>
55#endif
56
57/*********************************************************************
58 *
59 * Private definitions, data structures and prototypes
60 *
61 *********************************************************************/
62
63/* Magic numbers (assuming that the order of magnitude of window
64 coordinates is 10^3) */
65
66#define GL2PS_EPSILON 5.0e-3F
67#define GL2PS_ZSCALE 1000.0F
68#define GL2PS_ZOFFSET 5.0e-2F
69#define GL2PS_ZOFFSET_LARGE 20.0F
70#define GL2PS_ZERO(arg) (fabs(arg) < 1.e-20)
71
72/* Primitive types */
73
74#define GL2PS_NO_TYPE -1
75#define GL2PS_TEXT 1
76#define GL2PS_POINT 2
77#define GL2PS_LINE 3
78#define GL2PS_QUADRANGLE 4
79#define GL2PS_TRIANGLE 5
80#define GL2PS_PIXMAP 6
81#define GL2PS_IMAGEMAP 7
82#define GL2PS_IMAGEMAP_WRITTEN 8
83#define GL2PS_IMAGEMAP_VISIBLE 9
84#define GL2PS_SPECIAL 10
85
86/* BSP tree primitive comparison */
87
88#define GL2PS_COINCIDENT 1
89#define GL2PS_IN_FRONT_OF 2
90#define GL2PS_IN_BACK_OF 3
91#define GL2PS_SPANNING 4
92
93/* 2D BSP tree primitive comparison */
94
95#define GL2PS_POINT_COINCIDENT 0
96#define GL2PS_POINT_INFRONT 1
97#define GL2PS_POINT_BACK 2
98
99/* Internal feedback buffer pass-through tokens */
100
101#define GL2PS_BEGIN_OFFSET_TOKEN 1
102#define GL2PS_END_OFFSET_TOKEN 2
103#define GL2PS_BEGIN_BOUNDARY_TOKEN 3
104#define GL2PS_END_BOUNDARY_TOKEN 4
105#define GL2PS_BEGIN_STIPPLE_TOKEN 5
106#define GL2PS_END_STIPPLE_TOKEN 6
107#define GL2PS_POINT_SIZE_TOKEN 7
108#define GL2PS_LINE_WIDTH_TOKEN 8
109#define GL2PS_BEGIN_BLEND_TOKEN 9
110#define GL2PS_END_BLEND_TOKEN 10
111#define GL2PS_SRC_BLEND_TOKEN 11
112#define GL2PS_DST_BLEND_TOKEN 12
113#define GL2PS_IMAGEMAP_TOKEN 13
114#define GL2PS_DRAW_PIXELS_TOKEN 14
115#define GL2PS_TEXT_TOKEN 15
116
125
126typedef GLfloat GL2PSxyz[3];
127typedef GLfloat GL2PSplane[4];
128
130
135
136typedef struct {
137 GLint nmax, size, incr, n;
138 char *array;
139} GL2PSlist;
140
142
148
153
154typedef struct {
156 int prop;
158
159typedef struct {
160 GLshort fontsize;
161 char *str, *fontname;
162 /* Note: for a 'special' string, 'alignment' holds the format
163 (PostScript, PDF, etc.) of the special string */
165 GLfloat angle;
167
168typedef struct {
169 GLsizei width, height;
170 /* Note: for an imagemap, 'type' indicates if it has already been
171 written to the file or not, and 'format' indicates if it is
172 visible or not */
173 GLenum format, type;
174 GLfloat *pixels;
175} GL2PSimage;
176
178
183
184typedef struct {
185 GLshort type, numverts;
186 GLushort pattern;
188 GLint factor;
189 GLfloat width;
191 union {
196
197typedef struct {
198#if defined(GL2PS_HAVE_ZLIB)
199 Bytef *dest, *src, *start;
200 uLongf destLen, srcLen;
201#else
202 int dummy;
203#endif
205
211
212typedef struct {
213 /* General */
216 GLboolean boundary, blending;
220 GLushort lastpattern;
223 FILE *stream;
225 GLboolean header;
226
227 /* BSP-specific */
229
230 /* Occlusion culling-specific */
234
235 /* PDF-specific */
239 int objects_stack; /* available objects */
240 int extgs_stack; /* graphics state object number */
241 int font_stack; /* font object number */
242 int im_stack; /* image object number */
243 int trgroupobjects_stack; /* xobject numbers */
244 int shader_stack; /* shader object numbers */
245 int mshader_stack; /* mask shader object numbers */
246
247 /* for image map list */
251
252typedef struct {
253 void (*printHeader)(void);
254 void (*printFooter)(void);
255 void (*beginViewport)(GLint viewport[4]);
256 GLint (*endViewport)(void);
257 void (*printPrimitive)(void *data);
258 void (*printFinalPrimitive)(void);
259 const char *file_extension;
260 const char *description;
262
263/* The gl2ps context. gl2ps is not thread safe (we should create a
264 local GL2PScontext during gl2psBeginPage) */
265
266static GL2PScontext *gl2ps = NULL;
267
268/* Need to forward-declare this one */
269
270static GLint gl2psPrintPrimitives(void);
271
272/*********************************************************************
273 *
274 * Utility routines
275 *
276 *********************************************************************/
277
278static void gl2psMsg(GLint level, const char *fmt, ...)
279{
280 va_list args;
281
282 if(!(gl2ps->options & GL2PS_SILENT)){
283 switch(level){
284 case GL2PS_INFO : fprintf(stderr, "GL2PS info: "); break;
285 case GL2PS_WARNING : fprintf(stderr, "GL2PS warning: "); break;
286 case GL2PS_ERROR : fprintf(stderr, "GL2PS error: "); break;
287 }
288 va_start(args, fmt);
289 vfprintf(stderr, fmt, args);
290 va_end(args);
291 fprintf(stderr, "\n");
292 }
293 /* if(level == GL2PS_ERROR) exit(1); */
294}
295
296static void *gl2psMalloc(size_t size)
297{
298 void *ptr;
299
300 if(!size) return NULL;
301 ptr = malloc(size);
302 if(!ptr){
303 gl2psMsg(GL2PS_ERROR, "Couldn't allocate requested memory");
304 return NULL;
305 }
306 return ptr;
307}
308
309static void *gl2psRealloc(void *ptr, size_t size)
310{
311 if(!size) return NULL;
312 ptr = realloc(ptr, size);
313 if(!ptr){
314 gl2psMsg(GL2PS_ERROR, "Couldn't reallocate requested memory");
315 return NULL;
316 }
317 return ptr;
318}
319
320static void gl2psFree(void *ptr)
321{
322 if(!ptr) return;
323 free(ptr);
324}
325
326static size_t gl2psWriteBigEndian(unsigned long data, size_t bytes)
327{
328 size_t i;
329 size_t size = sizeof(unsigned long);
330 for(i = 1; i <= bytes; ++i){
331 fputc(0xff & (data >> (size-i) * 8), gl2ps->stream);
332 }
333 return bytes;
334}
335
336/* zlib compression helper routines */
337
338#if defined(GL2PS_HAVE_ZLIB)
339
340static void gl2psSetupCompress(void)
341{
342 gl2ps->compress = (GL2PScompress*)gl2psMalloc(sizeof(GL2PScompress));
343 gl2ps->compress->src = NULL;
344 gl2ps->compress->start = NULL;
345 gl2ps->compress->dest = NULL;
346 gl2ps->compress->srcLen = 0;
347 gl2ps->compress->destLen = 0;
348}
349
350static void gl2psFreeCompress(void)
351{
352 if(!gl2ps->compress)
353 return;
354 gl2psFree(gl2ps->compress->start);
355 gl2psFree(gl2ps->compress->dest);
356 gl2ps->compress->src = NULL;
357 gl2ps->compress->start = NULL;
358 gl2ps->compress->dest = NULL;
359 gl2ps->compress->srcLen = 0;
360 gl2ps->compress->destLen = 0;
361}
362
363static int gl2psAllocCompress(unsigned int srcsize)
364{
365 gl2psFreeCompress();
366
367 if(!gl2ps->compress || !srcsize)
368 return GL2PS_ERROR;
369
370 gl2ps->compress->srcLen = srcsize;
371 gl2ps->compress->destLen = (int)ceil(1.001 * gl2ps->compress->srcLen + 12);
372 gl2ps->compress->src = (Bytef*)gl2psMalloc(gl2ps->compress->srcLen);
373 gl2ps->compress->start = gl2ps->compress->src;
374 gl2ps->compress->dest = (Bytef*)gl2psMalloc(gl2ps->compress->destLen);
375
376 return GL2PS_SUCCESS;
377}
378
379static void *gl2psReallocCompress(unsigned int srcsize)
380{
381 if(!gl2ps->compress || !srcsize)
382 return NULL;
383
384 if(srcsize < gl2ps->compress->srcLen)
385 return gl2ps->compress->start;
386
387 gl2ps->compress->srcLen = srcsize;
388 gl2ps->compress->destLen = (int)ceil(1.001 * gl2ps->compress->srcLen + 12);
389 gl2ps->compress->src = (Bytef*)gl2psRealloc(gl2ps->compress->src,
390 gl2ps->compress->srcLen);
391 gl2ps->compress->start = gl2ps->compress->src;
392 gl2ps->compress->dest = (Bytef*)gl2psRealloc(gl2ps->compress->dest,
393 gl2ps->compress->destLen);
394
395 return gl2ps->compress->start;
396}
397
398static size_t gl2psWriteBigEndianCompress(unsigned long data, size_t bytes)
399{
400 size_t i;
401 size_t size = sizeof(unsigned long);
402 for(i = 1; i <= bytes; ++i){
403 *gl2ps->compress->src = (Bytef)(0xff & (data >> (size-i) * 8));
404 ++gl2ps->compress->src;
405 }
406 return bytes;
407}
408
409static int gl2psDeflate(void)
410{
411 /* For compatibility with older zlib versions, we use compress(...)
412 instead of compress2(..., Z_BEST_COMPRESSION) */
413 return compress(gl2ps->compress->dest, &gl2ps->compress->destLen,
414 gl2ps->compress->start, gl2ps->compress->srcLen);
415}
416
417#endif
418
419static int gl2psPrintf(const char* fmt, ...)
420{
421 int ret;
422 va_list args;
423
424#if defined(GL2PS_HAVE_ZLIB)
425 unsigned int oldsize = 0;
426 static char buf[1000];
427 if(gl2ps->options & GL2PS_COMPRESS){
428 va_start(args, fmt);
429 ret = vsprintf(buf, fmt, args);
430 va_end(args);
431 oldsize = gl2ps->compress->srcLen;
432 gl2ps->compress->start = (Bytef*)gl2psReallocCompress(oldsize + ret);
433 memcpy(gl2ps->compress->start+oldsize, buf, ret);
434 ret = 0;
435 }
436 else{
437#endif
438 va_start(args, fmt);
439 ret = vfprintf(gl2ps->stream, fmt, args);
440 va_end(args);
441#if defined(GL2PS_HAVE_ZLIB)
442 }
443#endif
444 return ret;
445}
446
448{
449#if defined(GL2PS_HAVE_ZLIB)
450 char tmp[10] = {'\x1f', '\x8b', /* magic numbers: 0x1f, 0x8b */
451 8, /* compression method: Z_DEFLATED */
452 0, /* flags */
453 0, 0, 0, 0, /* time */
454 2, /* extra flags: max compression */
455 '\x03'}; /* OS code: 0x03 (Unix) */
456
457 if(gl2ps->options & GL2PS_COMPRESS){
458 gl2psSetupCompress();
459 /* add the gzip file header */
460 fwrite(tmp, 10, 1, gl2ps->stream);
461 }
462#endif
463}
464
466{
467#if defined(GL2PS_HAVE_ZLIB)
468 int n;
469 uLong crc, len;
470 char tmp[8];
471
472 if(gl2ps->options & GL2PS_COMPRESS){
473 if(Z_OK != gl2psDeflate()){
474 gl2psMsg(GL2PS_ERROR, "Zlib deflate error");
475 }
476 else{
477 /* determine the length of the header in the zlib stream */
478 n = 2; /* CMF+FLG */
479 if(gl2ps->compress->dest[1] & (1<<5)){
480 n += 4; /* DICTID */
481 }
482 /* write the data, without the zlib header and footer */
483 fwrite(gl2ps->compress->dest+n, gl2ps->compress->destLen-(n+4),
484 1, gl2ps->stream);
485 /* add the gzip file footer */
486 crc = crc32(0L, gl2ps->compress->start, gl2ps->compress->srcLen);
487 for(n = 0; n < 4; ++n){
488 tmp[n] = (char)(crc & 0xff);
489 crc >>= 8;
490 }
491 len = gl2ps->compress->srcLen;
492 for(n = 4; n < 8; ++n){
493 tmp[n] = (char)(len & 0xff);
494 len >>= 8;
495 }
496 fwrite(tmp, 8, 1, gl2ps->stream);
497 }
498 gl2psFreeCompress();
499 gl2psFree(gl2ps->compress);
500 gl2ps->compress = NULL;
501 }
502#endif
503}
504
505/* The list handling routines */
506
507static void gl2psListRealloc(GL2PSlist *list, GLint n)
508{
509 if(!list){
510 gl2psMsg(GL2PS_ERROR, "Cannot reallocate NULL list");
511 return;
512 }
513 if(n <= 0) return;
514 if(!list->array){
515 list->nmax = n;
516 list->array = (char*)gl2psMalloc(list->nmax * list->size);
517 }
518 else{
519 if(n > list->nmax){
520 list->nmax = ((n - 1) / list->incr + 1) * list->incr;
521 list->array = (char*)gl2psRealloc(list->array,
522 list->nmax * list->size);
523 }
524 }
525}
526
527static GL2PSlist *gl2psListCreate(GLint n, GLint incr, GLint size)
528{
529 GL2PSlist *list;
530
531 if(n < 0) n = 0;
532 if(incr <= 0) incr = 1;
533 list = (GL2PSlist*)gl2psMalloc(sizeof(GL2PSlist));
534 list->nmax = 0;
535 list->incr = incr;
536 list->size = size;
537 list->n = 0;
538 list->array = NULL;
539 gl2psListRealloc(list, n);
540 return list;
541}
542
543static void gl2psListReset(GL2PSlist *list)
544{
545 if(!list) return;
546 list->n = 0;
547}
548
549static void gl2psListDelete(GL2PSlist *list)
550{
551 if(!list) return;
552 gl2psFree(list->array);
553 gl2psFree(list);
554}
555
556static void gl2psListAdd(GL2PSlist *list, void *data)
557{
558 if(!list){
559 gl2psMsg(GL2PS_ERROR, "Cannot add into unallocated list");
560 return;
561 }
562 list->n++;
563 gl2psListRealloc(list, list->n);
564 memcpy(&list->array[(list->n - 1) * list->size], data, list->size);
565}
566
567static int gl2psListNbr(GL2PSlist *list)
568{
569 if(!list)
570 return 0;
571 return list->n;
572}
573
574static void *gl2psListPointer(GL2PSlist *list, GLint index)
575{
576 if(!list){
577 gl2psMsg(GL2PS_ERROR, "Cannot point into unallocated list");
578 return NULL;
579 }
580 if((index < 0) || (index >= list->n)){
581 gl2psMsg(GL2PS_ERROR, "Wrong list index in gl2psListPointer");
582 return NULL;
583 }
584 return &list->array[index * list->size];
585}
586
587static void gl2psListSort(GL2PSlist *list,
588 int (*fcmp)(const void *a, const void *b))
589{
590 if(!list)
591 return;
592 qsort(list->array, list->n, list->size, fcmp);
593}
594
595static void gl2psListAction(GL2PSlist *list, void (*action)(void *data))
596{
597 GLint i;
598
599 for(i = 0; i < gl2psListNbr(list); i++){
600 (*action)(gl2psListPointer(list, i));
601 }
602}
603
604static void gl2psListActionInverse(GL2PSlist *list, void (*action)(void *data))
605{
606 GLint i;
607
608 for(i = gl2psListNbr(list); i > 0; i--){
609 (*action)(gl2psListPointer(list, i-1));
610 }
611}
612
613#if defined(GL2PS_HAVE_LIBPNG)
614
615static void gl2psListRead(GL2PSlist *list, int index, void *data)
616{
617 if((index < 0) || (index >= list->n))
618 gl2psMsg(GL2PS_ERROR, "Wrong list index in gl2psListRead");
619 memcpy(data, &list->array[index * list->size], list->size);
620}
621
622static void gl2psEncodeBase64Block(unsigned char in[3], unsigned char out[4], int len)
623{
624 static const char cb64[] =
625 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
626
627 out[0] = cb64[ in[0] >> 2 ];
628 out[1] = cb64[ ((in[0] & 0x03) << 4) | ((in[1] & 0xf0) >> 4) ];
629 out[2] = (len > 1) ? cb64[ ((in[1] & 0x0f) << 2) | ((in[2] & 0xc0) >> 6) ] : '=';
630 out[3] = (len > 2) ? cb64[ in[2] & 0x3f ] : '=';
631}
632
633static void gl2psListEncodeBase64(GL2PSlist *list)
634{
635 unsigned char *buffer, in[3], out[4];
636 int i, n, index, len;
637
638 n = list->n * list->size;
639 buffer = (unsigned char*)gl2psMalloc(n * sizeof(unsigned char));
640 memcpy(buffer, list->array, n * sizeof(unsigned char));
641 gl2psListReset(list);
642
643 index = 0;
644 while(index < n) {
645 len = 0;
646 for(i = 0; i < 3; i++) {
647 if(index < n){
648 in[i] = buffer[index];
649 len++;
650 }
651 else{
652 in[i] = 0;
653 }
654 index++;
655 }
656 if(len) {
657 gl2psEncodeBase64Block(in, out, len);
658 for(i = 0; i < 4; i++)
659 gl2psListAdd(list, &out[i]);
660 }
661 }
662 gl2psFree(buffer);
663}
664
665#endif
666
667/* Helpers for rgba colors */
668
669static GLboolean gl2psSameColor(GL2PSrgba rgba1, GL2PSrgba rgba2)
670{
671 if(!GL2PS_ZERO(rgba1[0] - rgba2[0]) ||
672 !GL2PS_ZERO(rgba1[1] - rgba2[1]) ||
673 !GL2PS_ZERO(rgba1[2] - rgba2[2]))
674 return GL_FALSE;
675 return GL_TRUE;
676}
677
678static GLboolean gl2psVertsSameColor(const GL2PSprimitive *prim)
679{
680 int i;
681
682 for(i = 1; i < prim->numverts; i++){
683 if(!gl2psSameColor(prim->verts[0].rgba, prim->verts[i].rgba)){
684 return GL_FALSE;
685 }
686 }
687 return GL_TRUE;
688}
689
690static GLboolean gl2psSameColorThreshold(int n, GL2PSrgba rgba[],
692{
693 int i;
694
695 if(n < 2) return GL_TRUE;
696
697 for(i = 1; i < n; i++){
698 if(fabs(rgba[0][0] - rgba[i][0]) > threshold[0] ||
699 fabs(rgba[0][1] - rgba[i][1]) > threshold[1] ||
700 fabs(rgba[0][2] - rgba[i][2]) > threshold[2])
701 return GL_FALSE;
702 }
703
704 return GL_TRUE;
705}
706
708{
709 int i;
710 for(i = 0; i < 3; ++i){
711 gl2ps->lastrgba[i] = rgba[i];
712 }
713}
714
715static GLfloat gl2psGetRGB(GL2PSimage *im, GLuint x, GLuint y,
716 GLfloat *red, GLfloat *green, GLfloat *blue)
717{
718
719 GLsizei width = im->width;
720 GLsizei height = im->height;
721 GLfloat *pixels = im->pixels;
722 GLfloat *pimag;
723
724 /* OpenGL image is from down to up, PS image is up to down */
725 switch(im->format){
726 case GL_RGBA:
727 pimag = pixels + 4 * (width * (height - 1 - y) + x);
728 break;
729 case GL_RGB:
730 default:
731 pimag = pixels + 3 * (width * (height - 1 - y) + x);
732 break;
733 }
734 *red = *pimag; pimag++;
735 *green = *pimag; pimag++;
736 *blue = *pimag; pimag++;
737
738 return (im->format == GL_RGBA) ? *pimag : 1.0F;
739}
740
741/* Helper routines for pixmaps */
742
744{
745 int size;
746 GL2PSimage *image = (GL2PSimage*)gl2psMalloc(sizeof(GL2PSimage));
747
748 image->width = im->width;
749 image->height = im->height;
750 image->format = im->format;
751 image->type = im->type;
752
753 switch(image->format){
754 case GL_RGBA:
755 size = image->height * image->width * 4 * sizeof(GLfloat);
756 break;
757 case GL_RGB:
758 default:
759 size = image->height * image->width * 3 * sizeof(GLfloat);
760 break;
761 }
762
763 image->pixels = (GLfloat*)gl2psMalloc(size);
764 memcpy(image->pixels, im->pixels, size);
765
766 return image;
767}
768
770{
771 if(!im)
772 return;
773 gl2psFree(im->pixels);
774 gl2psFree(im);
775}
776
777#if defined(GL2PS_HAVE_LIBPNG)
778
779#if !defined(png_jmpbuf)
780# define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf)
781#endif
782
783static void gl2psUserWritePNG(png_structp png_ptr, png_bytep data, png_size_t length)
784{
785 unsigned int i;
786 GL2PSlist *png = (GL2PSlist*)png_get_io_ptr(png_ptr);
787 for(i = 0; i < length; i++)
788 gl2psListAdd(png, &data[i]);
789}
790
791static void gl2psUserFlushPNG(png_structp /*png_ptr*/)
792{
793}
794
795static void gl2psConvertPixmapToPNG(GL2PSimage *pixmap, GL2PSlist *png)
796{
797 png_structp png_ptr;
798 png_infop info_ptr;
799 unsigned char *row_data;
800 GLfloat dr, dg, db;
801 int row, col;
802
803 if(!(png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL)))
804 return;
805
806 if(!(info_ptr = png_create_info_struct(png_ptr))){
807 png_destroy_write_struct(&png_ptr, NULL);
808 return;
809 }
810
811 if(setjmp(png_jmpbuf(png_ptr))) {
812 png_destroy_write_struct(&png_ptr, &info_ptr);
813 return;
814 }
815
816 png_set_write_fn(png_ptr, (void *)png, gl2psUserWritePNG, gl2psUserFlushPNG);
817 png_set_compression_level(png_ptr, Z_DEFAULT_COMPRESSION);
818 png_set_IHDR(png_ptr, info_ptr, pixmap->width, pixmap->height, 8,
819 PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE,
820 PNG_FILTER_TYPE_BASE);
821 png_write_info(png_ptr, info_ptr);
822
823 row_data = (unsigned char*)gl2psMalloc(3 * pixmap->width * sizeof(unsigned char));
824 for(row = 0; row < pixmap->height; row++){
825 for(col = 0; col < pixmap->width; col++){
826 gl2psGetRGB(pixmap, col, row, &dr, &dg, &db);
827 row_data[3*col] = (unsigned char)(255. * dr);
828 row_data[3*col+1] = (unsigned char)(255. * dg);
829 row_data[3*col+2] = (unsigned char)(255. * db);
830 }
831 png_write_row(png_ptr, (png_bytep)row_data);
832 }
833 gl2psFree(row_data);
834
835 png_write_end(png_ptr, info_ptr);
836 png_destroy_write_struct(&png_ptr, &info_ptr);
837}
838
839#endif
840
841/* Helper routines for text strings */
842
843static GLint gl2psAddText(GLint type, const char *str, const char *fontname,
844 GLshort fontsize, GLint alignment, GLfloat angle)
845{
846 GLfloat pos[4];
847 GL2PSprimitive *prim;
848 GLboolean valid;
849
850 if(!gl2ps || !str || !fontname) return GL2PS_UNINITIALIZED;
851
852 if(gl2ps->options & GL2PS_NO_TEXT) return GL2PS_SUCCESS;
853
854 glGetBooleanv(GL_CURRENT_RASTER_POSITION_VALID, &valid);
855 if(GL_FALSE == valid) return GL2PS_SUCCESS; /* the primitive is culled */
856
857 glGetFloatv(GL_CURRENT_RASTER_POSITION, pos);
858
859 prim = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive));
860 prim->type = type;
861 prim->boundary = 0;
862 prim->numverts = 1;
863 prim->verts = (GL2PSvertex*)gl2psMalloc(sizeof(GL2PSvertex));
864 prim->verts[0].xyz[0] = pos[0];
865 prim->verts[0].xyz[1] = pos[1];
866 prim->verts[0].xyz[2] = pos[2];
867 prim->culled = 0;
868 prim->offset = 0;
869 prim->pattern = 0;
870 prim->factor = 0;
871 prim->width = 1;
872 glGetFloatv(GL_CURRENT_RASTER_COLOR, prim->verts[0].rgba);
873 prim->data.text = (GL2PSstring*)gl2psMalloc(sizeof(GL2PSstring));
874 prim->data.text->str = (char*)gl2psMalloc((strlen(str)+1)*sizeof(char));
875 strcpy(prim->data.text->str, str);
876 prim->data.text->fontname = (char*)gl2psMalloc((strlen(fontname)+1)*sizeof(char));
877 strcpy(prim->data.text->fontname, fontname);
878 prim->data.text->fontsize = fontsize;
879 prim->data.text->alignment = alignment;
880 prim->data.text->angle = angle;
881
882 gl2psListAdd(gl2ps->auxprimitives, &prim);
883 glPassThrough(GL2PS_TEXT_TOKEN);
884
885 return GL2PS_SUCCESS;
886}
887
889{
891 text->str = (char*)gl2psMalloc((strlen(t->str)+1)*sizeof(char));
892 strcpy(text->str, t->str);
893 text->fontname = (char*)gl2psMalloc((strlen(t->fontname)+1)*sizeof(char));
894 strcpy(text->fontname, t->fontname);
895 text->fontsize = t->fontsize;
896 text->alignment = t->alignment;
897 text->angle = t->angle;
898
899 return text;
900}
901
902static void gl2psFreeText(GL2PSstring *text)
903{
904 if(!text)
905 return;
906 gl2psFree(text->str);
907 gl2psFree(text->fontname);
908 gl2psFree(text);
909}
910
911/* Helpers for blending modes */
912
913static GLboolean gl2psSupportedBlendMode(GLenum sfactor, GLenum dfactor)
914{
915 /* returns TRUE if gl2ps supports the argument combination: only two
916 blending modes have been implemented so far */
917
918 if( (sfactor == GL_SRC_ALPHA && dfactor == GL_ONE_MINUS_SRC_ALPHA) ||
919 (sfactor == GL_ONE && dfactor == GL_ZERO) )
920 return GL_TRUE;
921 return GL_FALSE;
922}
923
925{
926 /* Transforms vertex depending on the actual blending function -
927 currently the vertex v is considered as source vertex and his
928 alpha value is changed to 1.0 if source blending GL_ONE is
929 active. This might be extended in the future */
930
931 if(!v || !gl2ps)
932 return;
933
934 if(gl2ps->options & GL2PS_NO_BLENDING || !gl2ps->blending){
935 v->rgba[3] = 1.0F;
936 return;
937 }
938
939 switch(gl2ps->blendfunc[0]){
940 case GL_ONE:
941 v->rgba[3] = 1.0F;
942 break;
943 default:
944 break;
945 }
946}
947
949{
950 /* int i; */
951
952 t->prop = T_VAR_COLOR;
953
954 /* Uncommenting the following lines activates an even more fine
955 grained distinction between triangle types - please don't delete,
956 a remarkable amount of PDF handling code inside this file depends
957 on it if activated */
958 /*
959 t->prop = T_CONST_COLOR;
960 for(i = 0; i < 3; ++i){
961 if(!GL2PS_ZERO(t->vertex[0].rgba[i] - t->vertex[1].rgba[i]) ||
962 !GL2PS_ZERO(t->vertex[1].rgba[i] - t->vertex[2].rgba[i])){
963 t->prop = T_VAR_COLOR;
964 break;
965 }
966 }
967 */
968
969 if(!GL2PS_ZERO(t->vertex[0].rgba[3] - t->vertex[1].rgba[3]) ||
970 !GL2PS_ZERO(t->vertex[1].rgba[3] - t->vertex[2].rgba[3])){
971 t->prop |= T_VAR_ALPHA;
972 }
973 else{
974 if(t->vertex[0].rgba[3] < 1)
975 t->prop |= T_ALPHA_LESS_1;
976 else
977 t->prop |= T_ALPHA_1;
978 }
979}
980
982 GLboolean assignprops)
983{
984 t->vertex[0] = p->verts[0];
985 t->vertex[1] = p->verts[1];
986 t->vertex[2] = p->verts[2];
987 if(GL_TRUE == assignprops)
989}
990
992{
993 int i;
994 GL2PSvertex vertex = { {-1.0F, -1.0F, -1.0F}, {-1.0F, -1.0F, -1.0F, -1.0F} };
995 for(i = 0; i < 3; i++)
996 t->vertex[i] = vertex;
997 t->prop = T_UNDEFINED;
998}
999
1000/* Miscellaneous helper routines */
1001
1003{
1004 GL2PSprimitive *prim;
1005
1006 if(!p){
1007 gl2psMsg(GL2PS_ERROR, "Trying to copy an empty primitive");
1008 return NULL;
1009 }
1010
1011 prim = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive));
1012
1013 prim->type = p->type;
1014 prim->numverts = p->numverts;
1015 prim->boundary = p->boundary;
1016 prim->offset = p->offset;
1017 prim->pattern = p->pattern;
1018 prim->factor = p->factor;
1019 prim->culled = p->culled;
1020 prim->width = p->width;
1021 prim->verts = (GL2PSvertex*)gl2psMalloc(p->numverts*sizeof(GL2PSvertex));
1022 memcpy(prim->verts, p->verts, p->numverts * sizeof(GL2PSvertex));
1023
1024 switch(prim->type){
1025 case GL2PS_PIXMAP :
1026 prim->data.image = gl2psCopyPixmap(p->data.image);
1027 break;
1028 case GL2PS_TEXT :
1029 case GL2PS_SPECIAL :
1030 prim->data.text = gl2psCopyText(p->data.text);
1031 break;
1032 default:
1033 break;
1034 }
1035
1036 return prim;
1037}
1038
1039static GLboolean gl2psSamePosition(GL2PSxyz p1, GL2PSxyz p2)
1040{
1041 if(!GL2PS_ZERO(p1[0] - p2[0]) ||
1042 !GL2PS_ZERO(p1[1] - p2[1]) ||
1043 !GL2PS_ZERO(p1[2] - p2[2]))
1044 return GL_FALSE;
1045 return GL_TRUE;
1046}
1047
1048/*********************************************************************
1049 *
1050 * 3D sorting routines
1051 *
1052 *********************************************************************/
1053
1054static GLfloat gl2psComparePointPlane(GL2PSxyz point, GL2PSplane plane)
1055{
1056 return (plane[0] * point[0] +
1057 plane[1] * point[1] +
1058 plane[2] * point[2] +
1059 plane[3]);
1060}
1061
1062static GLfloat gl2psPsca(GLfloat *a, GLfloat *b)
1063{
1064 return (a[0]*b[0] + a[1]*b[1] + a[2]*b[2]);
1065}
1066
1067static void gl2psPvec(GLfloat *a, GLfloat *b, GLfloat *c)
1068{
1069 c[0] = a[1]*b[2] - a[2]*b[1];
1070 c[1] = a[2]*b[0] - a[0]*b[2];
1071 c[2] = a[0]*b[1] - a[1]*b[0];
1072}
1073
1074static GLfloat gl2psNorm(GLfloat *a)
1075{
1076 return (GLfloat)sqrt(a[0]*a[0] + a[1]*a[1] + a[2]*a[2]);
1077}
1078
1079static void gl2psGetNormal(GLfloat *a, GLfloat *b, GLfloat *c)
1080{
1081 GLfloat norm;
1082
1083 gl2psPvec(a, b, c);
1084 if(!GL2PS_ZERO(norm = gl2psNorm(c))){
1085 c[0] = c[0] / norm;
1086 c[1] = c[1] / norm;
1087 c[2] = c[2] / norm;
1088 }
1089 else{
1090 /* The plane is still wrong despite our tests in gl2psGetPlane.
1091 Let's return a dummy value for now (this is a hack: we should
1092 do more intelligent tests in GetPlane) */
1093 c[0] = c[1] = 0.0F;
1094 c[2] = 1.0F;
1095 }
1096}
1097
1098static void gl2psGetPlane(GL2PSprimitive *prim, GL2PSplane plane)
1099{
1100 GL2PSxyz v = {0.0F, 0.0F, 0.0F}, w = {0.0F, 0.0F, 0.0F};
1101
1102 switch(prim->type){
1103 case GL2PS_TRIANGLE :
1104 case GL2PS_QUADRANGLE :
1105 v[0] = prim->verts[1].xyz[0] - prim->verts[0].xyz[0];
1106 v[1] = prim->verts[1].xyz[1] - prim->verts[0].xyz[1];
1107 v[2] = prim->verts[1].xyz[2] - prim->verts[0].xyz[2];
1108 w[0] = prim->verts[2].xyz[0] - prim->verts[0].xyz[0];
1109 w[1] = prim->verts[2].xyz[1] - prim->verts[0].xyz[1];
1110 w[2] = prim->verts[2].xyz[2] - prim->verts[0].xyz[2];
1111 if((GL2PS_ZERO(v[0]) && GL2PS_ZERO(v[1]) && GL2PS_ZERO(v[2])) ||
1112 (GL2PS_ZERO(w[0]) && GL2PS_ZERO(w[1]) && GL2PS_ZERO(w[2]))){
1113 plane[0] = plane[1] = 0.0F;
1114 plane[2] = 1.0F;
1115 plane[3] = -prim->verts[0].xyz[2];
1116 }
1117 else{
1118 gl2psGetNormal(v, w, plane);
1119 plane[3] =
1120 - plane[0] * prim->verts[0].xyz[0]
1121 - plane[1] * prim->verts[0].xyz[1]
1122 - plane[2] * prim->verts[0].xyz[2];
1123 }
1124 break;
1125 case GL2PS_LINE :
1126 v[0] = prim->verts[1].xyz[0] - prim->verts[0].xyz[0];
1127 v[1] = prim->verts[1].xyz[1] - prim->verts[0].xyz[1];
1128 v[2] = prim->verts[1].xyz[2] - prim->verts[0].xyz[2];
1129 if(GL2PS_ZERO(v[0]) && GL2PS_ZERO(v[1]) && GL2PS_ZERO(v[2])){
1130 plane[0] = plane[1] = 0.0F;
1131 plane[2] = 1.0F;
1132 plane[3] = -prim->verts[0].xyz[2];
1133 }
1134 else{
1135 if(GL2PS_ZERO(v[0])) w[0] = 1.0F;
1136 else if(GL2PS_ZERO(v[1])) w[1] = 1.0F;
1137 else w[2] = 1.0F;
1138 gl2psGetNormal(v, w, plane);
1139 plane[3] =
1140 - plane[0] * prim->verts[0].xyz[0]
1141 - plane[1] * prim->verts[0].xyz[1]
1142 - plane[2] * prim->verts[0].xyz[2];
1143 }
1144 break;
1145 case GL2PS_POINT :
1146 case GL2PS_PIXMAP :
1147 case GL2PS_TEXT :
1148 case GL2PS_SPECIAL :
1149 case GL2PS_IMAGEMAP:
1150 plane[0] = plane[1] = 0.0F;
1151 plane[2] = 1.0F;
1152 plane[3] = -prim->verts[0].xyz[2];
1153 break;
1154 default :
1155 gl2psMsg(GL2PS_ERROR, "Unknown primitive type in BSP tree");
1156 plane[0] = plane[1] = plane[3] = 0.0F;
1157 plane[2] = 1.0F;
1158 break;
1159 }
1160}
1161
1163 GL2PSvertex *c)
1164{
1165 GL2PSxyz v;
1166 GLfloat sect, psca;
1167
1168 v[0] = b->xyz[0] - a->xyz[0];
1169 v[1] = b->xyz[1] - a->xyz[1];
1170 v[2] = b->xyz[2] - a->xyz[2];
1171
1172 if(!GL2PS_ZERO(psca = gl2psPsca(plane, v)))
1173 sect = -gl2psComparePointPlane(a->xyz, plane) / psca;
1174 else
1175 sect = 0.0F;
1176
1177 c->xyz[0] = a->xyz[0] + v[0] * sect;
1178 c->xyz[1] = a->xyz[1] + v[1] * sect;
1179 c->xyz[2] = a->xyz[2] + v[2] * sect;
1180
1181 c->rgba[0] = (1 - sect) * a->rgba[0] + sect * b->rgba[0];
1182 c->rgba[1] = (1 - sect) * a->rgba[1] + sect * b->rgba[1];
1183 c->rgba[2] = (1 - sect) * a->rgba[2] + sect * b->rgba[2];
1184 c->rgba[3] = (1 - sect) * a->rgba[3] + sect * b->rgba[3];
1185}
1186
1188 GL2PSprimitive *child, GLshort numverts,
1189 GLshort *index0, GLshort *index1)
1190{
1191 GLshort i;
1192
1193 if(parent->type == GL2PS_IMAGEMAP){
1194 child->type = GL2PS_IMAGEMAP;
1195 child->data.image = parent->data.image;
1196 }
1197 else{
1198 if(numverts > 4){
1199 gl2psMsg(GL2PS_WARNING, "%d vertices in polygon", numverts);
1200 numverts = 4;
1201 }
1202 switch(numverts){
1203 case 1 : child->type = GL2PS_POINT; break;
1204 case 2 : child->type = GL2PS_LINE; break;
1205 case 3 : child->type = GL2PS_TRIANGLE; break;
1206 case 4 : child->type = GL2PS_QUADRANGLE; break;
1207 default: child->type = GL2PS_NO_TYPE; break;
1208 }
1209 }
1210
1211 child->boundary = 0; /* FIXME: not done! */
1212 child->culled = parent->culled;
1213 child->offset = parent->offset;
1214 child->pattern = parent->pattern;
1215 child->factor = parent->factor;
1216 child->width = parent->width;
1217 child->numverts = numverts;
1218 child->verts = (GL2PSvertex*)gl2psMalloc(numverts * sizeof(GL2PSvertex));
1219
1220 for(i = 0; i < numverts; i++){
1221 if(index1[i] < 0){
1222 child->verts[i] = parent->verts[index0[i]];
1223 }
1224 else{
1225 gl2psCutEdge(&parent->verts[index0[i]], &parent->verts[index1[i]],
1226 plane, &child->verts[i]);
1227 }
1228 }
1229}
1230
1231static void gl2psAddIndex(GLshort *index0, GLshort *index1, GLshort *nb,
1232 GLshort i, GLshort j)
1233{
1234 GLint k;
1235
1236 for(k = 0; k < *nb; k++){
1237 if((index0[k] == i && index1[k] == j) ||
1238 (index1[k] == i && index0[k] == j)) return;
1239 }
1240 index0[*nb] = i;
1241 index1[*nb] = j;
1242 (*nb)++;
1243}
1244
1245static GLshort gl2psGetIndex(GLshort i, GLshort num)
1246{
1247 return (i < num - 1) ? i + 1 : 0;
1248}
1249
1251{
1252 GLint type = GL2PS_COINCIDENT;
1253 GLshort i, j;
1254 GLfloat d[5];
1255
1256 for(i = 0; i < prim->numverts; i++){
1257 d[i] = gl2psComparePointPlane(prim->verts[i].xyz, plane);
1258 }
1259
1260 if(prim->numverts < 2){
1261 return 0;
1262 }
1263 else{
1264 for(i = 0; i < prim->numverts; i++){
1265 j = gl2psGetIndex(i, prim->numverts);
1266 if(d[j] > GL2PS_EPSILON){
1268 else if(type != GL2PS_IN_BACK_OF) return 1;
1269 if(d[i] < -GL2PS_EPSILON) return 1;
1270 }
1271 else if(d[j] < -GL2PS_EPSILON){
1273 else if(type != GL2PS_IN_FRONT_OF) return 1;
1274 if(d[i] > GL2PS_EPSILON) return 1;
1275 }
1276 }
1277 }
1278 return 0;
1279}
1280
1282 GL2PSprimitive **front, GL2PSprimitive **back)
1283{
1284 GLshort i(0), j(0), in = 0, out = 0, in0[5], in1[5], out0[5], out1[5];
1285 for (unsigned k=0;k<5;++k)
1286 in0[k]=in1[k]=out0[k]=out1[k]=0;
1287 GLint type;
1288 GLfloat d[5];
1289
1291
1292 for(i = 0; i < prim->numverts; i++){
1293 d[i] = gl2psComparePointPlane(prim->verts[i].xyz, plane);
1294 }
1295
1296 switch(prim->type){
1297 case GL2PS_POINT :
1298 if(d[0] > GL2PS_EPSILON) type = GL2PS_IN_BACK_OF;
1299 else if(d[0] < -GL2PS_EPSILON) type = GL2PS_IN_FRONT_OF;
1300 else type = GL2PS_COINCIDENT;
1301 break;
1302 default :
1303 for(i = 0; i < prim->numverts; i++){
1304 j = gl2psGetIndex(i, prim->numverts);
1305 if(d[j] > GL2PS_EPSILON){
1308 if(d[i] < -GL2PS_EPSILON){
1309 gl2psAddIndex(in0, in1, &in, i, j);
1310 gl2psAddIndex(out0, out1, &out, i, j);
1312 }
1313 gl2psAddIndex(out0, out1, &out, j, -1);
1314 }
1315 else if(d[j] < -GL2PS_EPSILON){
1318 if(d[i] > GL2PS_EPSILON){
1319 gl2psAddIndex(in0, in1, &in, i, j);
1320 gl2psAddIndex(out0, out1, &out, i, j);
1322 }
1323 gl2psAddIndex(in0, in1, &in, j, -1);
1324 }
1325 else{
1326 gl2psAddIndex(in0, in1, &in, j, -1);
1327 gl2psAddIndex(out0, out1, &out, j, -1);
1328 }
1329 }
1330 break;
1331 }
1332
1333 if(type == GL2PS_SPANNING){
1334 *back = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive));
1335 *front = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive));
1336 gl2psCreateSplitPrimitive(prim, plane, *back, out, out0, out1);
1337 gl2psCreateSplitPrimitive(prim, plane, *front, in, in0, in1);
1338 }
1339
1340 return type;
1341}
1342
1344 GL2PSprimitive **t1, GL2PSprimitive **t2)
1345{
1346 *t1 = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive));
1347 *t2 = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive));
1348 (*t1)->type = (*t2)->type = GL2PS_TRIANGLE;
1349 (*t1)->numverts = (*t2)->numverts = 3;
1350 (*t1)->culled = (*t2)->culled = quad->culled;
1351 (*t1)->offset = (*t2)->offset = quad->offset;
1352 (*t1)->pattern = (*t2)->pattern = quad->pattern;
1353 (*t1)->factor = (*t2)->factor = quad->factor;
1354 (*t1)->width = (*t2)->width = quad->width;
1355 (*t1)->verts = (GL2PSvertex*)gl2psMalloc(3 * sizeof(GL2PSvertex));
1356 (*t2)->verts = (GL2PSvertex*)gl2psMalloc(3 * sizeof(GL2PSvertex));
1357 (*t1)->verts[0] = quad->verts[0];
1358 (*t1)->verts[1] = quad->verts[1];
1359 (*t1)->verts[2] = quad->verts[2];
1360 (*t1)->boundary = ((quad->boundary & 1) ? 1 : 0) | ((quad->boundary & 2) ? 2 : 0);
1361 (*t2)->verts[0] = quad->verts[0];
1362 (*t2)->verts[1] = quad->verts[2];
1363 (*t2)->verts[2] = quad->verts[3];
1364 (*t2)->boundary = ((quad->boundary & 4) ? 2 : 0) | ((quad->boundary & 4) ? 2 : 0);
1365}
1366
1367static int gl2psCompareDepth(const void *a, const void *b)
1368{
1369 GL2PSprimitive *q, *w;
1370 GLfloat dq = 0.0F, dw = 0.0F, diff;
1371 int i;
1372
1373 q = *(GL2PSprimitive**)a;
1374 w = *(GL2PSprimitive**)b;
1375
1376 for(i = 0; i < q->numverts; i++){
1377 dq += q->verts[i].xyz[2];
1378 }
1379 dq /= (GLfloat)q->numverts;
1380
1381 for(i = 0; i < w->numverts; i++){
1382 dw += w->verts[i].xyz[2];
1383 }
1384 dw /= (GLfloat)w->numverts;
1385
1386 diff = dq - dw;
1387 if(diff > 0.){
1388 return -1;
1389 }
1390 else if(diff < 0.){
1391 return 1;
1392 }
1393 else{
1394 return 0;
1395 }
1396}
1397
1398static int gl2psTrianglesFirst(const void *a, const void *b)
1399{
1400 GL2PSprimitive *q, *w;
1401
1402 q = *(GL2PSprimitive**)a;
1403 w = *(GL2PSprimitive**)b;
1404 return (q->type < w->type ? 1 : -1);
1405}
1406
1407static GLint gl2psFindRoot(GL2PSlist *primitives, GL2PSprimitive **root)
1408{
1409 GLint i, j, count, best = 1000000, index = 0;
1410 GL2PSprimitive *prim1, *prim2;
1411 GL2PSplane plane;
1412 GLint maxp;
1413
1414 if(!gl2psListNbr(primitives)){
1415 gl2psMsg(GL2PS_ERROR, "Cannot fint root in empty primitive list");
1416 return 0;
1417 }
1418
1419 *root = *(GL2PSprimitive**)gl2psListPointer(primitives, 0);
1420
1421 if(gl2ps->options & GL2PS_BEST_ROOT){
1422 maxp = gl2psListNbr(primitives);
1423 if(maxp > gl2ps->maxbestroot){
1424 maxp = gl2ps->maxbestroot;
1425 }
1426 for(i = 0; i < maxp; i++){
1427 prim1 = *(GL2PSprimitive**)gl2psListPointer(primitives, i);
1428 gl2psGetPlane(prim1, plane);
1429 count = 0;
1430 for(j = 0; j < gl2psListNbr(primitives); j++){
1431 if(j != i){
1432 prim2 = *(GL2PSprimitive**)gl2psListPointer(primitives, j);
1433 count += gl2psTestSplitPrimitive(prim2, plane);
1434 }
1435 if(count > best) break;
1436 }
1437 if(count < best){
1438 best = count;
1439 index = i;
1440 *root = prim1;
1441 if(!count) return index;
1442 }
1443 }
1444 /* if(index) gl2psMsg(GL2PS_INFO, "GL2PS_BEST_ROOT was worth it: %d", index); */
1445 return index;
1446 }
1447 else{
1448 return 0;
1449 }
1450}
1451
1453{
1454 GL2PSimagemap *next;
1455 while(list != NULL){
1456 next = list->next;
1457 gl2psFree(list->image->pixels);
1458 gl2psFree(list->image);
1459 gl2psFree(list);
1460 list = next;
1461 }
1462}
1463
1464static void gl2psFreePrimitive(void *data)
1465{
1466 GL2PSprimitive *q;
1467
1468 q = *(GL2PSprimitive**)data;
1469 gl2psFree(q->verts);
1470 if(q->type == GL2PS_TEXT || q->type == GL2PS_SPECIAL){
1471 gl2psFreeText(q->data.text);
1472 }
1473 else if(q->type == GL2PS_PIXMAP){
1474 gl2psFreePixmap(q->data.image);
1475 }
1476 gl2psFree(q);
1477}
1478
1480{
1481 GL2PSprimitive *t1, *t2;
1482
1483 if(prim->type != GL2PS_QUADRANGLE){
1484 gl2psListAdd(list, &prim);
1485 }
1486 else{
1487 gl2psDivideQuad(prim, &t1, &t2);
1488 gl2psListAdd(list, &t1);
1489 gl2psListAdd(list, &t2);
1490 gl2psFreePrimitive(&prim);
1491 }
1492
1493}
1494
1496{
1497 if(*tree){
1498 if((*tree)->back) gl2psFreeBspTree(&(*tree)->back);
1499 if((*tree)->primitives){
1500 gl2psListAction((*tree)->primitives, gl2psFreePrimitive);
1501 gl2psListDelete((*tree)->primitives);
1502 }
1503 if((*tree)->front) gl2psFreeBspTree(&(*tree)->front);
1504 gl2psFree(*tree);
1505 *tree = NULL;
1506 }
1507}
1508
1509static GLboolean gl2psGreater(GLfloat f1, GLfloat f2)
1510{
1511 if(f1 > f2) return GL_TRUE;
1512 else return GL_FALSE;
1513}
1514
1515static GLboolean gl2psLess(GLfloat f1, GLfloat f2)
1516{
1517 if(f1 < f2) return GL_TRUE;
1518 else return GL_FALSE;
1519}
1520
1522{
1523 GL2PSprimitive *prim = nullptr, *frontprim = nullptr, *backprim = nullptr;
1524 GL2PSlist *frontlist, *backlist;
1525 GLint i, index;
1526
1527 tree->front = nullptr;
1528 tree->back = nullptr;
1529 tree->primitives = gl2psListCreate(1, 2, sizeof(GL2PSprimitive*));
1530 index = gl2psFindRoot(primitives, &prim);
1531 gl2psGetPlane(prim, tree->plane);
1532 gl2psAddPrimitiveInList(prim, tree->primitives);
1533
1534 frontlist = gl2psListCreate(1, 2, sizeof(GL2PSprimitive*));
1535 backlist = gl2psListCreate(1, 2, sizeof(GL2PSprimitive*));
1536
1537 for(i = 0; i < gl2psListNbr(primitives); i++){
1538 if(i != index){
1539 prim = *(GL2PSprimitive**)gl2psListPointer(primitives,i);
1540 switch(gl2psSplitPrimitive(prim, tree->plane, &frontprim, &backprim)){
1541 case GL2PS_COINCIDENT:
1542 gl2psAddPrimitiveInList(prim, tree->primitives);
1543 break;
1544 case GL2PS_IN_BACK_OF:
1545 gl2psAddPrimitiveInList(prim, backlist);
1546 break;
1547 case GL2PS_IN_FRONT_OF:
1548 gl2psAddPrimitiveInList(prim, frontlist);
1549 break;
1550 case GL2PS_SPANNING:
1551 gl2psAddPrimitiveInList(backprim, backlist);
1552 gl2psAddPrimitiveInList(frontprim, frontlist);
1553 gl2psFreePrimitive(&prim);
1554 break;
1555 }
1556 }
1557 }
1558
1559 if(gl2psListNbr(tree->primitives)){
1561 }
1562
1563 if(gl2psListNbr(frontlist)){
1565 tree->front = (GL2PSbsptree*)gl2psMalloc(sizeof(GL2PSbsptree));
1566 gl2psBuildBspTree(tree->front, frontlist);
1567 }
1568 else{
1569 gl2psListDelete(frontlist);
1570 }
1571
1572 if(gl2psListNbr(backlist)){
1574 tree->back = (GL2PSbsptree*)gl2psMalloc(sizeof(GL2PSbsptree));
1575 gl2psBuildBspTree(tree->back, backlist);
1576 }
1577 else{
1578 gl2psListDelete(backlist);
1579 }
1580
1581 gl2psListDelete(primitives);
1582}
1583
1584static void gl2psTraverseBspTree(GL2PSbsptree *tree, GL2PSxyz eye, GLfloat epsilon,
1585 GLboolean (*compare)(GLfloat f1, GLfloat f2),
1586 void (*action)(void *data), int inverse)
1587{
1588 GLfloat result;
1589
1590 if(!tree) return;
1591
1592 result = gl2psComparePointPlane(eye, tree->plane);
1593
1594 if(GL_TRUE == compare(result, epsilon)){
1595 gl2psTraverseBspTree(tree->back, eye, epsilon, compare, action, inverse);
1596 if(inverse){
1597 gl2psListActionInverse(tree->primitives, action);
1598 }
1599 else{
1600 gl2psListAction(tree->primitives, action);
1601 }
1602 gl2psTraverseBspTree(tree->front, eye, epsilon, compare, action, inverse);
1603 }
1604 else if(GL_TRUE == compare(-epsilon, result)){
1605 gl2psTraverseBspTree(tree->front, eye, epsilon, compare, action, inverse);
1606 if(inverse){
1607 gl2psListActionInverse(tree->primitives, action);
1608 }
1609 else{
1610 gl2psListAction(tree->primitives, action);
1611 }
1612 gl2psTraverseBspTree(tree->back, eye, epsilon, compare, action, inverse);
1613 }
1614 else{
1615 gl2psTraverseBspTree(tree->front, eye, epsilon, compare, action, inverse);
1616 gl2psTraverseBspTree(tree->back, eye, epsilon, compare, action, inverse);
1617 }
1618}
1619
1621{
1622 GL2PSprimitive *prim;
1623 GLfloat minZ, maxZ, rangeZ, scaleZ;
1624 GLfloat factor, units, area, dZ, dZdX, dZdY, maxdZ;
1625 int i, j;
1626
1627 if(!gl2psListNbr(gl2ps->primitives))
1628 return;
1629
1630 /* get z-buffer range */
1631 prim = *(GL2PSprimitive**)gl2psListPointer(gl2ps->primitives, 0);
1632 minZ = maxZ = prim->verts[0].xyz[2];
1633 for(i = 1; i < prim->numverts; i++){
1634 if(prim->verts[i].xyz[2] < minZ) minZ = prim->verts[i].xyz[2];
1635 if(prim->verts[i].xyz[2] > maxZ) maxZ = prim->verts[i].xyz[2];
1636 }
1637 for(i = 1; i < gl2psListNbr(gl2ps->primitives); i++){
1638 prim = *(GL2PSprimitive**)gl2psListPointer(gl2ps->primitives, i);
1639 for(j = 0; j < prim->numverts; j++){
1640 if(prim->verts[j].xyz[2] < minZ) minZ = prim->verts[j].xyz[2];
1641 if(prim->verts[j].xyz[2] > maxZ) maxZ = prim->verts[j].xyz[2];
1642 }
1643 }
1644 rangeZ = (maxZ - minZ);
1645
1646 /* rescale z-buffer coordinate in [0,GL2PS_ZSCALE], to make it of
1647 the same order of magnitude as the x and y coordinates */
1648 scaleZ = GL2PS_ZERO(rangeZ) ? GL2PS_ZSCALE : (GL2PS_ZSCALE / rangeZ);
1649 /* avoid precision loss (we use floats!) */
1650 if(scaleZ > 100000.F) scaleZ = 100000.F;
1651
1652 /* apply offsets */
1653 for(i = 0; i < gl2psListNbr(gl2ps->primitives); i++){
1654 prim = *(GL2PSprimitive**)gl2psListPointer(gl2ps->primitives, i);
1655 for(j = 0; j < prim->numverts; j++){
1656 prim->verts[j].xyz[2] = (prim->verts[j].xyz[2] - minZ) * scaleZ;
1657 }
1658 if((gl2ps->options & GL2PS_SIMPLE_LINE_OFFSET) &&
1659 (prim->type == GL2PS_LINE)){
1660 if(gl2ps->sort == GL2PS_SIMPLE_SORT){
1661 prim->verts[0].xyz[2] -= GL2PS_ZOFFSET_LARGE;
1662 prim->verts[1].xyz[2] -= GL2PS_ZOFFSET_LARGE;
1663 }
1664 else{
1665 prim->verts[0].xyz[2] -= GL2PS_ZOFFSET;
1666 prim->verts[1].xyz[2] -= GL2PS_ZOFFSET;
1667 }
1668 }
1669 else if(prim->offset && (prim->type == GL2PS_TRIANGLE)){
1670 factor = gl2ps->offset[0];
1671 units = gl2ps->offset[1];
1672 area =
1673 (prim->verts[1].xyz[0] - prim->verts[0].xyz[0]) *
1674 (prim->verts[2].xyz[1] - prim->verts[1].xyz[1]) -
1675 (prim->verts[2].xyz[0] - prim->verts[1].xyz[0]) *
1676 (prim->verts[1].xyz[1] - prim->verts[0].xyz[1]);
1677 if(!GL2PS_ZERO(area)){
1678 dZdX =
1679 ((prim->verts[2].xyz[1] - prim->verts[1].xyz[1]) *
1680 (prim->verts[1].xyz[2] - prim->verts[0].xyz[2]) -
1681 (prim->verts[1].xyz[1] - prim->verts[0].xyz[1]) *
1682 (prim->verts[2].xyz[2] - prim->verts[1].xyz[2])) / area;
1683 dZdY =
1684 ((prim->verts[1].xyz[0] - prim->verts[0].xyz[0]) *
1685 (prim->verts[2].xyz[2] - prim->verts[1].xyz[2]) -
1686 (prim->verts[2].xyz[0] - prim->verts[1].xyz[0]) *
1687 (prim->verts[1].xyz[2] - prim->verts[0].xyz[2])) / area;
1688 maxdZ = (GLfloat)sqrt(dZdX * dZdX + dZdY * dZdY);
1689 }
1690 else{
1691 maxdZ = 0.0F;
1692 }
1693 dZ = factor * maxdZ + units;
1694 prim->verts[0].xyz[2] += dZ;
1695 prim->verts[1].xyz[2] += dZ;
1696 prim->verts[2].xyz[2] += dZ;
1697 }
1698 }
1699}
1700
1701/*********************************************************************
1702 *
1703 * 2D sorting routines (for occlusion culling)
1704 *
1705 *********************************************************************/
1706
1708{
1709 GLfloat n;
1710
1711 plane[0] = b[1] - a[1];
1712 plane[1] = a[0] - b[0];
1713 n = (GLfloat)sqrt(plane[0]*plane[0] + plane[1]*plane[1]);
1714 plane[2] = 0.0F;
1715 if(!GL2PS_ZERO(n)){
1716 plane[0] /= n;
1717 plane[1] /= n;
1718 plane[3] = -plane[0]*a[0]-plane[1]*a[1];
1719 return 1;
1720 }
1721 else{
1722 plane[0] = -1.0F;
1723 plane[1] = 0.0F;
1724 plane[3] = a[0];
1725 return 0;
1726 }
1727}
1728
1730{
1731 if(*tree){
1732 if((*tree)->back) gl2psFreeBspImageTree(&(*tree)->back);
1733 if((*tree)->front) gl2psFreeBspImageTree(&(*tree)->front);
1734 gl2psFree(*tree);
1735 *tree = NULL;
1736 }
1737}
1738
1739static GLint gl2psCheckPoint(GL2PSxyz point, GL2PSplane plane)
1740{
1741 GLfloat pt_dis;
1742
1743 pt_dis = gl2psComparePointPlane(point, plane);
1744 if(pt_dis > GL2PS_EPSILON) return GL2PS_POINT_INFRONT;
1745 else if(pt_dis < -GL2PS_EPSILON) return GL2PS_POINT_BACK;
1746 else return GL2PS_POINT_COINCIDENT;
1747}
1748
1751{
1752 GLint ret = 0;
1753 GLint i;
1754 GLint offset = 0;
1755 GL2PSbsptree2d *head = NULL, *cur = NULL;
1756
1757 if((*tree == NULL) && (prim->numverts > 2)){
1758 /* don't cull if transparent
1759 for(i = 0; i < prim->numverts - 1; i++)
1760 if(prim->verts[i].rgba[3] < 1.0F) return;
1761 */
1763 for(i = 0; i < prim->numverts-1; i++){
1764 if(!gl2psGetPlaneFromPoints(prim->verts[i].xyz,
1765 prim->verts[i+1].xyz,
1766 head->plane)){
1767 if(prim->numverts-i > 3){
1768 offset++;
1769 }
1770 else{
1771 gl2psFree(head);
1772 return;
1773 }
1774 }
1775 else{
1776 break;
1777 }
1778 }
1779 head->back = NULL;
1780 head->front = NULL;
1781 for(i = 2+offset; i < prim->numverts; i++){
1782 ret = gl2psCheckPoint(prim->verts[i].xyz, head->plane);
1783 if(ret != GL2PS_POINT_COINCIDENT) break;
1784 }
1785 switch(ret){
1786 case GL2PS_POINT_INFRONT :
1787 cur = head;
1788 for(i = 1+offset; i < prim->numverts-1; i++){
1789 if(cur->front == NULL){
1790 cur->front = (GL2PSbsptree2d*)gl2psMalloc(sizeof(GL2PSbsptree2d));
1791 }
1792 if(gl2psGetPlaneFromPoints(prim->verts[i].xyz,
1793 prim->verts[i+1].xyz,
1794 cur->front->plane)){
1795 cur = cur->front;
1796 cur->front = NULL;
1797 cur->back = NULL;
1798 }
1799 }
1800 if(cur->front == NULL){
1801 cur->front = (GL2PSbsptree2d*)gl2psMalloc(sizeof(GL2PSbsptree2d));
1802 }
1803 if(gl2psGetPlaneFromPoints(prim->verts[i].xyz,
1804 prim->verts[offset].xyz,
1805 cur->front->plane)){
1806 cur->front->front = NULL;
1807 cur->front->back = NULL;
1808 }
1809 else{
1810 gl2psFree(cur->front);
1811 cur->front = NULL;
1812 }
1813 break;
1814 case GL2PS_POINT_BACK :
1815 for(i = 0; i < 4; i++){
1816 head->plane[i] = -head->plane[i];
1817 }
1818 cur = head;
1819 for(i = 1+offset; i < prim->numverts-1; i++){
1820 if(cur->front == NULL){
1821 cur->front = (GL2PSbsptree2d*)gl2psMalloc(sizeof(GL2PSbsptree2d));
1822 }
1823 if(gl2psGetPlaneFromPoints(prim->verts[i+1].xyz,
1824 prim->verts[i].xyz,
1825 cur->front->plane)){
1826 cur = cur->front;
1827 cur->front = NULL;
1828 cur->back = NULL;
1829 }
1830 }
1831 if(cur->front == NULL){
1832 cur->front = (GL2PSbsptree2d*)gl2psMalloc(sizeof(GL2PSbsptree2d));
1833 }
1834 if(gl2psGetPlaneFromPoints(prim->verts[offset].xyz,
1835 prim->verts[i].xyz,
1836 cur->front->plane)){
1837 cur->front->front = NULL;
1838 cur->front->back = NULL;
1839 }
1840 else{
1841 gl2psFree(cur->front);
1842 cur->front = NULL;
1843 }
1844 break;
1845 default:
1846 gl2psFree(head);
1847 return;
1848 }
1849 (*tree) = head;
1850 }
1851}
1852
1854{
1855 GLint i;
1856 GLint pos;
1857
1858 pos = gl2psCheckPoint(prim->verts[0].xyz, plane);
1859 for(i = 1; i < prim->numverts; i++){
1860 pos |= gl2psCheckPoint(prim->verts[i].xyz, plane);
1862 }
1863 if(pos & GL2PS_POINT_INFRONT) return GL2PS_IN_FRONT_OF;
1864 else if(pos & GL2PS_POINT_BACK) return GL2PS_IN_BACK_OF;
1865 else return GL2PS_COINCIDENT;
1866}
1867
1869 GLshort numverts,
1870 GL2PSvertex *vertx)
1871{
1872 GLint i;
1874
1875 if(parent->type == GL2PS_IMAGEMAP){
1876 child->type = GL2PS_IMAGEMAP;
1877 child->data.image = parent->data.image;
1878 }
1879 else {
1880 switch(numverts){
1881 case 1 : child->type = GL2PS_POINT; break;
1882 case 2 : child->type = GL2PS_LINE; break;
1883 case 3 : child->type = GL2PS_TRIANGLE; break;
1884 case 4 : child->type = GL2PS_QUADRANGLE; break;
1885 default: child->type = GL2PS_NO_TYPE; break; /* FIXME */
1886 }
1887 }
1888 child->boundary = 0; /* FIXME: not done! */
1889 child->culled = parent->culled;
1890 child->offset = parent->offset;
1891 child->pattern = parent->pattern;
1892 child->factor = parent->factor;
1893 child->width = parent->width;
1894 child->numverts = numverts;
1895 child->verts = (GL2PSvertex*)gl2psMalloc(numverts * sizeof(GL2PSvertex));
1896 for(i = 0; i < numverts; i++){
1897 child->verts[i] = vertx[i];
1898 }
1899 return child;
1900}
1901
1903 GL2PSplane plane,
1904 GL2PSprimitive **front,
1905 GL2PSprimitive **back)
1906{
1907 /* cur will hold the position of the current vertex
1908 prev will hold the position of the previous vertex
1909 prev0 will hold the position of the vertex number 0
1910 v1 and v2 represent the current and previous vertices, respectively
1911 flag is set if the current vertex should be checked against the plane */
1912 GLint cur = -1, prev = -1, i, v1 = 0, v2 = 0, flag = 1, prev0 = -1;
1913
1914 /* list of vertices that will go in front and back primitive */
1915 GL2PSvertex *front_list = NULL, *back_list = NULL;
1916
1917 /* number of vertices in front and back list */
1918 GLshort front_count = 0, back_count = 0;
1919
1920 for(i = 0; i <= prim->numverts; i++){
1921 v1 = i;
1922 if(v1 == prim->numverts){
1923 if(prim->numverts < 3) break;
1924 v1 = 0;
1925 v2 = prim->numverts - 1;
1926 cur = prev0;
1927 }
1928 else if(flag){
1929 cur = gl2psCheckPoint(prim->verts[v1].xyz, plane);
1930 if(i == 0){
1931 prev0 = cur;
1932 }
1933 }
1934 if(((prev == -1) || (prev == cur) || (prev == 0) || (cur == 0)) &&
1935 (i < prim->numverts)){
1936 if(cur == GL2PS_POINT_INFRONT){
1937 front_count++;
1938 front_list = (GL2PSvertex*)gl2psRealloc(front_list,
1939 sizeof(GL2PSvertex)*front_count);
1940 front_list[front_count-1] = prim->verts[v1];
1941 }
1942 else if(cur == GL2PS_POINT_BACK){
1943 back_count++;
1944 back_list = (GL2PSvertex*)gl2psRealloc(back_list,
1945 sizeof(GL2PSvertex)*back_count);
1946 back_list[back_count-1] = prim->verts[v1];
1947 }
1948 else{
1949 front_count++;
1950 front_list = (GL2PSvertex*)gl2psRealloc(front_list,
1951 sizeof(GL2PSvertex)*front_count);
1952 front_list[front_count-1] = prim->verts[v1];
1953 back_count++;
1954 back_list = (GL2PSvertex*)gl2psRealloc(back_list,
1955 sizeof(GL2PSvertex)*back_count);
1956 back_list[back_count-1] = prim->verts[v1];
1957 }
1958 flag = 1;
1959 }
1960 else if((prev != cur) && (cur != 0) && (prev != 0)){
1961 if(v1 != 0){
1962 v2 = v1-1;
1963 i--;
1964 }
1965 front_count++;
1966 front_list = (GL2PSvertex*)gl2psRealloc(front_list,
1967 sizeof(GL2PSvertex)*front_count);
1968 gl2psCutEdge(&prim->verts[v2], &prim->verts[v1],
1969 plane, &front_list[front_count-1]);
1970 back_count++;
1971 back_list = (GL2PSvertex*)gl2psRealloc(back_list,
1972 sizeof(GL2PSvertex)*back_count);
1973 back_list[back_count-1] = front_list[front_count-1];
1974 flag = 0;
1975 }
1976 prev = cur;
1977 }
1978 *front = gl2psCreateSplitPrimitive2D(prim, front_count, front_list);
1979 *back = gl2psCreateSplitPrimitive2D(prim, back_count, back_list);
1980 gl2psFree(front_list);
1981 gl2psFree(back_list);
1982}
1983
1985{
1986 GLint ret = 0;
1987 GL2PSprimitive *frontprim = NULL, *backprim = NULL;
1988
1989 /* FIXME: until we consider the actual extent of text strings and
1990 pixmaps, never cull them. Otherwise the whole string/pixmap gets
1991 culled as soon as the reference point is hidden */
1992 if(prim->type == GL2PS_PIXMAP ||
1993 prim->type == GL2PS_TEXT ||
1994 prim->type == GL2PS_SPECIAL){
1995 return 1;
1996 }
1997
1998 if(*tree == NULL){
1999 if((prim->type != GL2PS_IMAGEMAP) && (GL_FALSE == gl2ps->zerosurfacearea)){
2000 gl2psAddPlanesInBspTreeImage(gl2ps->primitivetoadd, tree);
2001 }
2002 return 1;
2003 }
2004 else{
2005 switch(gl2psCheckPrimitive(prim, (*tree)->plane)){
2006 case GL2PS_IN_BACK_OF: return gl2psAddInBspImageTree(prim, &(*tree)->back);
2007 case GL2PS_IN_FRONT_OF:
2008 if((*tree)->front != NULL) return gl2psAddInBspImageTree(prim, &(*tree)->front);
2009 else return 0;
2010 case GL2PS_SPANNING:
2011 gl2psSplitPrimitive2D(prim, (*tree)->plane, &frontprim, &backprim);
2012 ret = gl2psAddInBspImageTree(backprim, &(*tree)->back);
2013 if((*tree)->front != NULL){
2014 if(gl2psAddInBspImageTree(frontprim, &(*tree)->front)){
2015 ret = 1;
2016 }
2017 }
2018 gl2psFree(frontprim->verts);
2019 gl2psFree(frontprim);
2020 gl2psFree(backprim->verts);
2021 gl2psFree(backprim);
2022 return ret;
2023 case GL2PS_COINCIDENT:
2024 if((*tree)->back != NULL){
2025 gl2ps->zerosurfacearea = GL_TRUE;
2026 ret = gl2psAddInBspImageTree(prim, &(*tree)->back);
2027 gl2ps->zerosurfacearea = GL_FALSE;
2028 if(ret) return ret;
2029 }
2030 if((*tree)->front != NULL){
2031 gl2ps->zerosurfacearea = GL_TRUE;
2032 ret = gl2psAddInBspImageTree(prim, &(*tree)->front);
2033 gl2ps->zerosurfacearea = GL_FALSE;
2034 if(ret) return ret;
2035 }
2036 if(prim->type == GL2PS_LINE) return 1;
2037 else return 0;
2038 }
2039 }
2040 return 0;
2041}
2042
2043static void gl2psAddInImageTree(void *data)
2044{
2045 GL2PSprimitive *prim = *(GL2PSprimitive **)data;
2046 gl2ps->primitivetoadd = prim;
2047 if(prim->type == GL2PS_IMAGEMAP && prim->data.image->format == GL2PS_IMAGEMAP_VISIBLE){
2048 prim->culled = 1;
2049 }
2050 else if(!gl2psAddInBspImageTree(prim, &gl2ps->imagetree)){
2051 prim->culled = 1;
2052 }
2053 else if(prim->type == GL2PS_IMAGEMAP){
2055 }
2056}
2057
2058/* Boundary construction */
2059
2061{
2062 GL2PSprimitive *b;
2063 GLshort i;
2064 GL2PSxyz c;
2065
2066 c[0] = c[1] = c[2] = 0.0F;
2067 for(i = 0; i < prim->numverts; i++){
2068 c[0] += prim->verts[i].xyz[0];
2069 c[1] += prim->verts[i].xyz[1];
2070 }
2071 c[0] /= prim->numverts;
2072 c[1] /= prim->numverts;
2073
2074 for(i = 0; i < prim->numverts; i++){
2075 if(prim->boundary & (GLint)pow(2., i)){
2077 b->type = GL2PS_LINE;
2078 b->offset = prim->offset;
2079 b->pattern = prim->pattern;
2080 b->factor = prim->factor;
2081 b->culled = prim->culled;
2082 b->width = prim->width;
2083 b->boundary = 0;
2084 b->numverts = 2;
2085 b->verts = (GL2PSvertex*)gl2psMalloc(2 * sizeof(GL2PSvertex));
2086
2087#if 0 /* FIXME: need to work on boundary offset... */
2088 v[0] = c[0] - prim->verts[i].xyz[0];
2089 v[1] = c[1] - prim->verts[i].xyz[1];
2090 v[2] = 0.0F;
2091 norm = gl2psNorm(v);
2092 v[0] /= norm;
2093 v[1] /= norm;
2094 b->verts[0].xyz[0] = prim->verts[i].xyz[0] +0.1*v[0];
2095 b->verts[0].xyz[1] = prim->verts[i].xyz[1] +0.1*v[1];
2096 b->verts[0].xyz[2] = prim->verts[i].xyz[2];
2097 v[0] = c[0] - prim->verts[gl2psGetIndex(i, prim->numverts)].xyz[0];
2098 v[1] = c[1] - prim->verts[gl2psGetIndex(i, prim->numverts)].xyz[1];
2099 norm = gl2psNorm(v);
2100 v[0] /= norm;
2101 v[1] /= norm;
2102 b->verts[1].xyz[0] = prim->verts[gl2psGetIndex(i, prim->numverts)].xyz[0] +0.1*v[0];
2103 b->verts[1].xyz[1] = prim->verts[gl2psGetIndex(i, prim->numverts)].xyz[1] +0.1*v[1];
2104 b->verts[1].xyz[2] = prim->verts[gl2psGetIndex(i, prim->numverts)].xyz[2];
2105#else
2106 b->verts[0].xyz[0] = prim->verts[i].xyz[0];
2107 b->verts[0].xyz[1] = prim->verts[i].xyz[1];
2108 b->verts[0].xyz[2] = prim->verts[i].xyz[2];
2109 b->verts[1].xyz[0] = prim->verts[gl2psGetIndex(i, prim->numverts)].xyz[0];
2110 b->verts[1].xyz[1] = prim->verts[gl2psGetIndex(i, prim->numverts)].xyz[1];
2111 b->verts[1].xyz[2] = prim->verts[gl2psGetIndex(i, prim->numverts)].xyz[2];
2112#endif
2113
2114 b->verts[0].rgba[0] = 0.0F;
2115 b->verts[0].rgba[1] = 0.0F;
2116 b->verts[0].rgba[2] = 0.0F;
2117 b->verts[0].rgba[3] = 0.0F;
2118 b->verts[1].rgba[0] = 0.0F;
2119 b->verts[1].rgba[1] = 0.0F;
2120 b->verts[1].rgba[2] = 0.0F;
2121 b->verts[1].rgba[3] = 0.0F;
2122 gl2psListAdd(list, &b);
2123 }
2124 }
2125
2126}
2127
2129{
2130 GLint i;
2131 GL2PSprimitive *prim;
2132
2133 if(!tree) return;
2135 for(i = 0; i < gl2psListNbr(tree->primitives); i++){
2136 prim = *(GL2PSprimitive**)gl2psListPointer(tree->primitives, i);
2137 if(prim->boundary) gl2psAddBoundaryInList(prim, tree->primitives);
2138 }
2140}
2141
2142/*********************************************************************
2143 *
2144 * Feedback buffer parser
2145 *
2146 *********************************************************************/
2147
2148static void gl2psAddPolyPrimitive(GLshort type, GLshort numverts,
2149 GL2PSvertex *verts, GLint offset,
2150 GLushort pattern, GLint factor,
2151 GLfloat width, char boundary)
2152{
2153 GL2PSprimitive *prim;
2154
2155 prim = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive));
2156 prim->type = type;
2157 prim->numverts = numverts;
2158 prim->verts = (GL2PSvertex*)gl2psMalloc(numverts * sizeof(GL2PSvertex));
2159 memcpy(prim->verts, verts, numverts * sizeof(GL2PSvertex));
2160 prim->boundary = boundary;
2161 prim->offset = offset;
2162 prim->pattern = pattern;
2163 prim->factor = factor;
2164 prim->width = width;
2165 prim->culled = 0;
2166
2167 /* FIXME: here we should have an option to split stretched
2168 tris/quads to enhance SIMPLE_SORT */
2169
2170 gl2psListAdd(gl2ps->primitives, &prim);
2171}
2172
2173static GLint gl2psGetVertex(GL2PSvertex *v, GLfloat *p)
2174{
2175 GLint i;
2176
2177 v->xyz[0] = p[0];
2178 v->xyz[1] = p[1];
2179 v->xyz[2] = p[2];
2180
2181 if(gl2ps->colormode == GL_COLOR_INDEX && gl2ps->colorsize > 0){
2182 i = (GLint)(p[3] + 0.5);
2183 v->rgba[0] = gl2ps->colormap[i][0];
2184 v->rgba[1] = gl2ps->colormap[i][1];
2185 v->rgba[2] = gl2ps->colormap[i][2];
2186 v->rgba[3] = gl2ps->colormap[i][3];
2187 return 4;
2188 }
2189 else{
2190 v->rgba[0] = p[3];
2191 v->rgba[1] = p[4];
2192 v->rgba[2] = p[5];
2193 v->rgba[3] = p[6];
2194 return 7;
2195 }
2196}
2197
2199{
2200 char flag;
2201 GLushort pattern = 0;
2202 GLboolean boundary;
2203 GLint i, sizeoffloat, count, v, vtot, offset = 0, factor = 0, auxindex = 0;
2204 GLfloat lwidth = 1.0F, psize = 1.0F;
2205 GLfloat *current;
2206 GL2PSvertex vertices[3];
2207 GL2PSprimitive *prim;
2209
2210 current = gl2ps->feedback;
2211 boundary = gl2ps->boundary = GL_FALSE;
2212
2213 while(used > 0){
2214
2215 if(GL_TRUE == boundary) gl2ps->boundary = GL_TRUE;
2216
2217 switch((GLint)*current){
2218 case GL_POINT_TOKEN :
2219 current ++;
2220 used --;
2221 i = gl2psGetVertex(&vertices[0], current);
2222 current += i;
2223 used -= i;
2224 gl2psAddPolyPrimitive(GL2PS_POINT, 1, vertices, 0,
2225 pattern, factor, psize, 0);
2226 break;
2227 case GL_LINE_TOKEN :
2228 case GL_LINE_RESET_TOKEN :
2229 current ++;
2230 used --;
2231 i = gl2psGetVertex(&vertices[0], current);
2232 current += i;
2233 used -= i;
2234 i = gl2psGetVertex(&vertices[1], current);
2235 current += i;
2236 used -= i;
2237 gl2psAddPolyPrimitive(GL2PS_LINE, 2, vertices, 0,
2238 pattern, factor, lwidth, 0);
2239 break;
2240 case GL_POLYGON_TOKEN :
2241 count = (GLint)current[1];
2242 current += 2;
2243 used -= 2;
2244 v = vtot = 0;
2245 while(count > 0 && used > 0){
2246 i = gl2psGetVertex(&vertices[v], current);
2247 gl2psAdaptVertexForBlending(&vertices[v]);
2248 current += i;
2249 used -= i;
2250 count --;
2251 vtot++;
2252 if(v == 2){
2253 if(GL_TRUE == boundary){
2254 if(!count && vtot == 2) flag = 1|2|4;
2255 else if(!count) flag = 2|4;
2256 else if(vtot == 2) flag = 1|2;
2257 else flag = 2;
2258 }
2259 else
2260 flag = 0;
2261 gl2psAddPolyPrimitive(GL2PS_TRIANGLE, 3, vertices, offset,
2262 pattern, factor, 1, flag);
2263 vertices[1] = vertices[2];
2264 }
2265 else
2266 v ++;
2267 }
2268 break;
2269 case GL_BITMAP_TOKEN :
2270 case GL_DRAW_PIXEL_TOKEN :
2271 case GL_COPY_PIXEL_TOKEN :
2272 current ++;
2273 used --;
2274 i = gl2psGetVertex(&vertices[0], current);
2275 current += i;
2276 used -= i;
2277 break;
2278 case GL_PASS_THROUGH_TOKEN :
2279 switch((GLint)current[1]){
2280 case GL2PS_BEGIN_OFFSET_TOKEN : offset = 1; break;
2281 case GL2PS_END_OFFSET_TOKEN : offset = 0; break;
2282 case GL2PS_BEGIN_BOUNDARY_TOKEN : boundary = GL_TRUE; break;
2283 case GL2PS_END_BOUNDARY_TOKEN : boundary = GL_FALSE; break;
2284 case GL2PS_END_STIPPLE_TOKEN : pattern = factor = 0; break;
2285 case GL2PS_BEGIN_BLEND_TOKEN : gl2ps->blending = GL_TRUE; break;
2286 case GL2PS_END_BLEND_TOKEN : gl2ps->blending = GL_FALSE; break;
2288 current += 2;
2289 used -= 2;
2290 pattern = (GLushort)current[1];
2291 current += 2;
2292 used -= 2;
2293 factor = (GLint)current[1];
2294 break;
2296 current += 2;
2297 used -= 2;
2298 gl2ps->blendfunc[0] = (GLint)current[1];
2299 break;
2301 current += 2;
2302 used -= 2;
2303 gl2ps->blendfunc[1] = (GLint)current[1];
2304 break;
2306 current += 2;
2307 used -= 2;
2308 psize = current[1];
2309 break;
2311 current += 2;
2312 used -= 2;
2313 lwidth = current[1];
2314 break;
2316 prim = (GL2PSprimitive *)gl2psMalloc(sizeof(GL2PSprimitive));
2317 prim->type = GL2PS_IMAGEMAP;
2318 prim->boundary = 0;
2319 prim->numverts = 4;
2320 prim->verts = (GL2PSvertex *)gl2psMalloc(4 * sizeof(GL2PSvertex));
2321 prim->culled = 0;
2322 prim->offset = 0;
2323 prim->pattern = 0;
2324 prim->factor = 0;
2325 prim->width = 1;
2326
2327 node = static_cast<GL2PSimagemap*>(gl2psMalloc(sizeof(GL2PSimagemap)));
2328 node->image = static_cast<GL2PSimage*>(gl2psMalloc(sizeof(GL2PSimage)));
2329 node->image->type = 0;
2330 node->image->format = 0;
2331 node->next = NULL;
2332
2333 if(gl2ps->imagemap_head == NULL)
2334 gl2ps->imagemap_head = node;
2335 else
2336 gl2ps->imagemap_tail->next = node;
2337 gl2ps->imagemap_tail = node;
2338 prim->data.image = node->image;
2339
2340 current += 2; used -= 2;
2341 i = gl2psGetVertex(&prim->verts[0], &current[1]);
2342 current += i; used -= i;
2343
2344 node->image->width = (GLint)current[2];
2345 current += 2; used -= 2;
2346 node->image->height = (GLint)current[2];
2347 prim->verts[0].xyz[0] = prim->verts[0].xyz[0] - (int)(node->image->width / 2) + 0.5F;
2348 prim->verts[0].xyz[1] = prim->verts[0].xyz[1] - (int)(node->image->height / 2) + 0.5F;
2349 for(i = 1; i < 4; i++){
2350 for(v = 0; v < 3; v++){
2351 prim->verts[i].xyz[v] = prim->verts[0].xyz[v];
2352 prim->verts[i].rgba[v] = prim->verts[0].rgba[v];
2353 }
2354 prim->verts[i].rgba[v] = prim->verts[0].rgba[v];
2355 }
2356 prim->verts[1].xyz[0] = prim->verts[1].xyz[0] + node->image->width;
2357 prim->verts[2].xyz[0] = prim->verts[1].xyz[0];
2358 prim->verts[2].xyz[1] = prim->verts[2].xyz[1] + node->image->height;
2359 prim->verts[3].xyz[1] = prim->verts[2].xyz[1];
2360
2361 sizeoffloat = sizeof(GLfloat);
2362 v = 2 * sizeoffloat;
2363 vtot = node->image->height + node->image->height *
2364 ((node->image->width - 1) / 8);
2365 node->image->pixels = (GLfloat*)gl2psMalloc(v + vtot);
2366 node->image->pixels[0] = prim->verts[0].xyz[0];
2367 node->image->pixels[1] = prim->verts[0].xyz[1];
2368
2369 for(i = 0; i < vtot; i += sizeoffloat){
2370 current += 2; used -= 2;
2371 if((vtot - i) >= 4)
2372 memcpy(&(node->image->pixels[i + v]), &(current[2]), sizeoffloat);
2373 else
2374 memcpy(&(node->image->pixels[i + v]), &(current[2]), vtot - i);
2375 }
2376 current++; used--;
2377 gl2psListAdd(gl2ps->primitives, &prim);
2378 break;
2380 case GL2PS_TEXT_TOKEN :
2381 if(auxindex < gl2psListNbr(gl2ps->auxprimitives))
2382 gl2psListAdd(gl2ps->primitives,
2383 gl2psListPointer(gl2ps->auxprimitives, auxindex++));
2384 else
2385 gl2psMsg(GL2PS_ERROR, "Wrong number of auxiliary tokens in buffer");
2386 break;
2387 }
2388 current += 2;
2389 used -= 2;
2390 break;
2391 default :
2392 gl2psMsg(GL2PS_WARNING, "Unknown token in buffer");
2393 current ++;
2394 used --;
2395 break;
2396 }
2397 }
2398
2399 gl2psListReset(gl2ps->auxprimitives);
2400}
2401
2402/*********************************************************************
2403 *
2404 * PostScript routines
2405 *
2406 *********************************************************************/
2407
2408static void gl2psWriteByte(unsigned char byte)
2409{
2410 unsigned char h = byte / 16;
2411 unsigned char l = byte % 16;
2412 gl2psPrintf("%x%x", h, l);
2413}
2414
2415static void gl2psPrintPostScriptPixmap(GLfloat x, GLfloat y, GL2PSimage *im)
2416{
2417 GLuint nbhex, nbyte, nrgb, nbits;
2418 GLuint row, col, ibyte, icase;
2419 GLfloat dr, dg, db, fgrey;
2420 unsigned char red = 0, green = 0, blue = 0, b, grey;
2421 GLuint width = (GLuint)im->width;
2422 GLuint height = (GLuint)im->height;
2423
2424 /* FIXME: should we define an option for these? Or just keep the
2425 8-bit per component case? */
2426
2427 //TK: coverity does not like how we hardcode some options here but
2428 //keep the code below. But since this is some complex code lifted
2429 //from somewhere else, we want to keep it that way at the moment:
2430
2431 const int greyscale = 0; /* set to 1 to output greyscale image */
2432 const int nbit = 8; /* number of bits per color compoment (2, 4 or 8) */
2433
2434 if((width <= 0) || (height <= 0)) return;
2435
2436 gl2psPrintf("gsave\n");
2437 gl2psPrintf("%.2f %.2f translate\n", x, y);
2438 gl2psPrintf("%d %d scale\n", width, height);
2439
2440 if(greyscale){ /* greyscale */
2441 //coverity[DEADCODE]
2442 gl2psPrintf("/picstr %d string def\n", width);
2443 gl2psPrintf("%d %d %d\n", width, height, 8);
2444 gl2psPrintf("[ %d 0 0 -%d 0 %d ]\n", width, height, height);
2445 gl2psPrintf("{ currentfile picstr readhexstring pop }\n");
2446 gl2psPrintf("image\n");
2447 for(row = 0; row < height; row++){
2448 for(col = 0; col < width; col++){
2449 gl2psGetRGB(im, col, row, &dr, &dg, &db);
2450 fgrey = (0.30F * dr + 0.59F * dg + 0.11F * db);
2451 grey = (unsigned char)(255. * fgrey);
2452 gl2psWriteByte(grey);
2453 }
2454 gl2psPrintf("\n");
2455 }
2456 nbhex = width * height * 2;
2457 gl2psPrintf("%%%% nbhex digit :%d\n", nbhex);
2458 }
2459 else if(nbit == 2){ /* color, 2 bits for r and g and b; rgbs following each other */
2460 //coverity[DEADCODE]
2461 nrgb = width * 3;
2462 nbits = nrgb * nbit;
2463 nbyte = nbits / 8;
2464 if((nbyte * 8) != nbits) nbyte++;
2465 gl2psPrintf("/rgbstr %d string def\n", nbyte);
2466 gl2psPrintf("%d %d %d\n", width, height, nbit);
2467 gl2psPrintf("[ %d 0 0 -%d 0 %d ]\n", width, height, height);
2468 gl2psPrintf("{ currentfile rgbstr readhexstring pop }\n");
2469 gl2psPrintf("false 3\n");
2470 gl2psPrintf("colorimage\n");
2471 for(row = 0; row < height; row++){
2472 icase = 1;
2473 col = 0;
2474 b = 0;
2475 for(ibyte = 0; ibyte < nbyte; ibyte++){
2476 if(icase == 1) {
2477 if(col < width) {
2478 gl2psGetRGB(im, col, row, &dr, &dg, &db);
2479 }
2480 else {
2481 dr = dg = db = 0;
2482 }
2483 col++;
2484 red = (unsigned char)(3. * dr);
2485 green = (unsigned char)(3. * dg);
2486 blue = (unsigned char)(3. * db);
2487 b = red;
2488 b = (b<<2) + green;
2489 b = (b<<2) + blue;
2490 if(col < width) {
2491 gl2psGetRGB(im, col, row, &dr, &dg, &db);
2492 }
2493 else {
2494 dr = dg = db = 0;
2495 }
2496 col++;
2497 red = (unsigned char)(3. * dr);
2498 green = (unsigned char)(3. * dg);
2499 blue = (unsigned char)(3. * db);
2500 b = (b<<2) + red;
2501 gl2psWriteByte(b);
2502 b = 0;
2503 icase++;
2504 }
2505 else if(icase == 2) {
2506 b = green;
2507 b = (b<<2) + blue;
2508 if(col < width) {
2509 gl2psGetRGB(im, col, row, &dr, &dg, &db);
2510 }
2511 else {
2512 dr = dg = db = 0;
2513 }
2514 col++;
2515 red = (unsigned char)(3. * dr);
2516 green = (unsigned char)(3. * dg);
2517 blue = (unsigned char)(3. * db);
2518 b = (b<<2) + red;
2519 b = (b<<2) + green;
2520 gl2psWriteByte(b);
2521 b = 0;
2522 icase++;
2523 }
2524 else if(icase == 3) {
2525 b = blue;
2526 if(col < width) {
2527 gl2psGetRGB(im, col, row, &dr, &dg, &db);
2528 }
2529 else {
2530 dr = dg = db = 0;
2531 }
2532 col++;
2533 red = (unsigned char)(3. * dr);
2534 green = (unsigned char)(3. * dg);
2535 blue = (unsigned char)(3. * db);
2536 b = (b<<2) + red;
2537 b = (b<<2) + green;
2538 b = (b<<2) + blue;
2539 gl2psWriteByte(b);
2540 b = 0;
2541 icase = 1;
2542 }
2543 }
2544 gl2psPrintf("\n");
2545 }
2546 }
2547 else if(nbit == 4){ /* color, 4 bits for r and g and b; rgbs following each other */
2548 nrgb = width * 3;
2549 nbits = nrgb * nbit;
2550 nbyte = nbits / 8;
2551 if((nbyte * 8) != nbits) nbyte++;
2552 gl2psPrintf("/rgbstr %d string def\n", nbyte);
2553 gl2psPrintf("%d %d %d\n", width, height, nbit);
2554 gl2psPrintf("[ %d 0 0 -%d 0 %d ]\n", width, height, height);
2555 gl2psPrintf("{ currentfile rgbstr readhexstring pop }\n");
2556 gl2psPrintf("false 3\n");
2557 gl2psPrintf("colorimage\n");
2558 for(row = 0; row < height; row++){
2559 col = 0;
2560 icase = 1;
2561 for(ibyte = 0; ibyte < nbyte; ibyte++){
2562 if(icase == 1) {
2563 if(col < width) {
2564 gl2psGetRGB(im, col, row, &dr, &dg, &db);
2565 }
2566 else {
2567 dr = dg = db = 0;
2568 }
2569 col++;
2570 red = (unsigned char)(15. * dr);
2571 green = (unsigned char)(15. * dg);
2572 gl2psPrintf("%x%x", red, green);
2573 icase++;
2574 }
2575 else if(icase == 2) {
2576 blue = (unsigned char)(15. * db);
2577 if(col < width) {
2578 gl2psGetRGB(im, col, row, &dr, &dg, &db);
2579 }
2580 else {
2581 dr = dg = db = 0;
2582 }
2583 col++;
2584 red = (unsigned char)(15. * dr);
2585 gl2psPrintf("%x%x", blue, red);
2586 icase++;
2587 }
2588 else if(icase == 3) {
2589 green = (unsigned char)(15. * dg);
2590 blue = (unsigned char)(15. * db);
2591 gl2psPrintf("%x%x", green, blue);
2592 icase = 1;
2593 }
2594 }
2595 gl2psPrintf("\n");
2596 }
2597 }
2598 else{ /* 8 bit for r and g and b */
2599 nbyte = width * 3;
2600 gl2psPrintf("/rgbstr %d string def\n", nbyte);
2601 gl2psPrintf("%d %d %d\n", width, height, 8);
2602 gl2psPrintf("[ %d 0 0 -%d 0 %d ]\n", width, height, height);
2603 gl2psPrintf("{ currentfile rgbstr readhexstring pop }\n");
2604 gl2psPrintf("false 3\n");
2605 gl2psPrintf("colorimage\n");
2606 for(row = 0; row < height; row++){
2607 for(col = 0; col < width; col++){
2608 gl2psGetRGB(im, col, row, &dr, &dg, &db);
2609 red = (unsigned char)(255. * dr);
2611 green = (unsigned char)(255. * dg);
2613 blue = (unsigned char)(255. * db);
2614 gl2psWriteByte(blue);
2615 }
2616 gl2psPrintf("\n");
2617 }
2618 }
2619
2620 gl2psPrintf("grestore\n");
2621}
2622
2623static void gl2psPrintPostScriptImagemap(GLfloat x, GLfloat y,
2624 GLsizei width, GLsizei height,
2625 const unsigned char *imagemap){
2626 int i, size;
2627
2628 if((width <= 0) || (height <= 0)) return;
2629
2630 size = height + height * (width - 1) / 8;
2631
2632 gl2psPrintf("gsave\n");
2633 gl2psPrintf("%.2f %.2f translate\n", x, y);
2634 gl2psPrintf("%d %d scale\n%d %d\ntrue\n", width, height,width, height);
2635 gl2psPrintf("[ %d 0 0 -%d 0 %d ] {<", width, height);
2636 for(i = 0; i < size; i++){
2637 gl2psWriteByte(*imagemap);
2638 imagemap++;
2639 }
2640 gl2psPrintf(">} imagemask\ngrestore\n");
2641}
2642
2644{
2645 time_t now;
2646
2647 /* Since compression is not part of the PostScript standard,
2648 compressed PostScript files are just gzipped PostScript files
2649 ("ps.gz" or "eps.gz") */
2651
2652 time(&now);
2653
2654 if(gl2ps->format == GL2PS_PS){
2655 gl2psPrintf("%%!PS-Adobe-3.0\n");
2656 }
2657 else{
2658 gl2psPrintf("%%!PS-Adobe-3.0 EPSF-3.0\n");
2659 }
2660
2661 gl2psPrintf("%%%%Title: %s\n"
2662 "%%%%Creator: GL2PS %d.%d.%d%s, %s\n"
2663 "%%%%For: %s\n"
2664 "%%%%CreationDate: %s"
2665 "%%%%LanguageLevel: 3\n"
2666 "%%%%DocumentData: Clean7Bit\n"
2667 "%%%%Pages: 1\n",
2670 gl2ps->producer, ctime(&now));
2671
2672 if(gl2ps->format == GL2PS_PS){
2673 gl2psPrintf("%%%%Orientation: %s\n"
2674 "%%%%DocumentMedia: Default %d %d 0 () ()\n",
2675 (gl2ps->options & GL2PS_LANDSCAPE) ? "Landscape" : "Portrait",
2676 (gl2ps->options & GL2PS_LANDSCAPE) ? (int)gl2ps->viewport[3] :
2677 (int)gl2ps->viewport[2],
2678 (gl2ps->options & GL2PS_LANDSCAPE) ? (int)gl2ps->viewport[2] :
2679 (int)gl2ps->viewport[3]);
2680 }
2681
2682 gl2psPrintf("%%%%BoundingBox: %d %d %d %d\n"
2683 "%%%%EndComments\n",
2684 (gl2ps->options & GL2PS_LANDSCAPE) ? (int)gl2ps->viewport[1] :
2685 (int)gl2ps->viewport[0],
2686 (gl2ps->options & GL2PS_LANDSCAPE) ? (int)gl2ps->viewport[0] :
2687 (int)gl2ps->viewport[1],
2688 (gl2ps->options & GL2PS_LANDSCAPE) ? (int)gl2ps->viewport[3] :
2689 (int)gl2ps->viewport[2],
2690 (gl2ps->options & GL2PS_LANDSCAPE) ? (int)gl2ps->viewport[2] :
2691 (int)gl2ps->viewport[3]);
2692
2693 /* RGB color: r g b C (replace C by G in output to change from rgb to gray)
2694 Grayscale: r g b G
2695 Font choose: size fontname FC
2696 Text string: (string) x y size fontname S??
2697 Rotated text string: (string) angle x y size fontname S??R
2698 Point primitive: x y size P
2699 Line width: width W
2700 Line start: x y LS
2701 Line joining last point: x y L
2702 Line end: x y LE
2703 Flat-shaded triangle: x3 y3 x2 y2 x1 y1 T
2704 Smooth-shaded triangle: x3 y3 r3 g3 b3 x2 y2 r2 g2 b2 x1 y1 r1 g1 b1 ST */
2705
2706 gl2psPrintf("%%%%BeginProlog\n"
2707 "/gl2psdict 64 dict def gl2psdict begin\n"
2708 "0 setlinecap 0 setlinejoin\n"
2709 "/tryPS3shading %s def %% set to false to force subdivision\n"
2710 "/rThreshold %g def %% red component subdivision threshold\n"
2711 "/gThreshold %g def %% green component subdivision threshold\n"
2712 "/bThreshold %g def %% blue component subdivision threshold\n",
2713 (gl2ps->options & GL2PS_NO_PS3_SHADING) ? "false" : "true",
2714 gl2ps->threshold[0], gl2ps->threshold[1], gl2ps->threshold[2]);
2715
2716 gl2psPrintf("/BD { bind def } bind def\n"
2717 "/C { setrgbcolor } BD\n"
2718 "/G { 0.082 mul exch 0.6094 mul add exch 0.3086 mul add neg 1.0 add setgray } BD\n"
2719 "/W { setlinewidth } BD\n");
2720
2721 gl2psPrintf("/FC { findfont exch /SH exch def SH scalefont setfont } BD\n"
2722 "/SW { dup stringwidth pop } BD\n"
2723 "/S { FC moveto show } BD\n"
2724 "/SBC{ FC moveto SW -2 div 0 rmoveto show } BD\n"
2725 "/SBR{ FC moveto SW neg 0 rmoveto show } BD\n"
2726 "/SCL{ FC moveto 0 SH -2 div rmoveto show } BD\n"
2727 "/SCC{ FC moveto SW -2 div SH -2 div rmoveto show } BD\n"
2728 "/SCR{ FC moveto SW neg SH -2 div rmoveto show } BD\n"
2729 "/STL{ FC moveto 0 SH neg rmoveto show } BD\n"
2730 "/STC{ FC moveto SW -2 div SH neg rmoveto show } BD\n"
2731 "/STR{ FC moveto SW neg SH neg rmoveto show } BD\n");
2732
2733 /* rotated text routines: same nameanem with R appended */
2734
2735 gl2psPrintf("/FCT { FC translate 0 0 } BD\n"
2736 "/SR { gsave FCT moveto rotate show grestore } BD\n"
2737 "/SBCR{ gsave FCT moveto rotate SW -2 div 0 rmoveto show grestore } BD\n"
2738 "/SBRR{ gsave FCT moveto rotate SW neg 0 rmoveto show grestore } BD\n"
2739 "/SCLR{ gsave FCT moveto rotate 0 SH -2 div rmoveto show grestore} BD\n");
2740 gl2psPrintf("/SCCR{ gsave FCT moveto rotate SW -2 div SH -2 div rmoveto show grestore} BD\n"
2741 "/SCRR{ gsave FCT moveto rotate SW neg SH -2 div rmoveto show grestore} BD\n"
2742 "/STLR{ gsave FCT moveto rotate 0 SH neg rmoveto show grestore } BD\n"
2743 "/STCR{ gsave FCT moveto rotate SW -2 div SH neg rmoveto show grestore } BD\n"
2744 "/STRR{ gsave FCT moveto rotate SW neg SH neg rmoveto show grestore } BD\n");
2745
2746 gl2psPrintf("/P { newpath 0.0 360.0 arc closepath fill } BD\n"
2747 "/LS { newpath moveto } BD\n"
2748 "/L { lineto } BD\n"
2749 "/LE { lineto stroke } BD\n"
2750 "/T { newpath moveto lineto lineto closepath fill } BD\n");
2751
2752 /* Smooth-shaded triangle with PostScript level 3 shfill operator:
2753 x3 y3 r3 g3 b3 x2 y2 r2 g2 b2 x1 y1 r1 g1 b1 STshfill */
2754
2755 gl2psPrintf("/STshfill {\n"
2756 " /b1 exch def /g1 exch def /r1 exch def /y1 exch def /x1 exch def\n"
2757 " /b2 exch def /g2 exch def /r2 exch def /y2 exch def /x2 exch def\n"
2758 " /b3 exch def /g3 exch def /r3 exch def /y3 exch def /x3 exch def\n"
2759 " gsave << /ShadingType 4 /ColorSpace [/DeviceRGB]\n"
2760 " /DataSource [ 0 x1 y1 r1 g1 b1 0 x2 y2 r2 g2 b2 0 x3 y3 r3 g3 b3 ] >>\n"
2761 " shfill grestore } BD\n");
2762
2763 /* Flat-shaded triangle with middle color:
2764 x3 y3 r3 g3 b3 x2 y2 r2 g2 b2 x1 y1 r1 g1 b1 Tm */
2765
2766 gl2psPrintf(/* stack : x3 y3 r3 g3 b3 x2 y2 r2 g2 b2 x1 y1 r1 g1 b1 */
2767 "/Tm { 3 -1 roll 8 -1 roll 13 -1 roll add add 3 div\n" /* r = (r1+r2+r3)/3 */
2768 /* stack : x3 y3 g3 b3 x2 y2 g2 b2 x1 y1 g1 b1 r */
2769 " 3 -1 roll 7 -1 roll 11 -1 roll add add 3 div\n" /* g = (g1+g2+g3)/3 */
2770 /* stack : x3 y3 b3 x2 y2 b2 x1 y1 b1 r g b */
2771 " 3 -1 roll 6 -1 roll 9 -1 roll add add 3 div" /* b = (b1+b2+b3)/3 */
2772 /* stack : x3 y3 x2 y2 x1 y1 r g b */
2773 " C T } BD\n");
2774
2775 /* Split triangle in four sub-triangles (at sides middle points) and call the
2776 STnoshfill procedure on each, interpolating the colors in RGB space:
2777 x3 y3 r3 g3 b3 x2 y2 r2 g2 b2 x1 y1 r1 g1 b1 STsplit
2778 (in procedure comments key: (Vi) = xi yi ri gi bi) */
2779
2780 gl2psPrintf("/STsplit {\n"
2781 " 4 index 15 index add 0.5 mul\n" /* x13 = (x1+x3)/2 */
2782 " 4 index 15 index add 0.5 mul\n" /* y13 = (y1+y3)/2 */
2783 " 4 index 15 index add 0.5 mul\n" /* r13 = (r1+r3)/2 */
2784 " 4 index 15 index add 0.5 mul\n" /* g13 = (g1+g3)/2 */
2785 " 4 index 15 index add 0.5 mul\n" /* b13 = (b1+b3)/2 */
2786 " 5 copy 5 copy 25 15 roll\n");
2787
2788 /* at his point, stack = (V3) (V13) (V13) (V13) (V2) (V1) */
2789
2790 gl2psPrintf(" 9 index 30 index add 0.5 mul\n" /* x23 = (x2+x3)/2 */
2791 " 9 index 30 index add 0.5 mul\n" /* y23 = (y2+y3)/2 */
2792 " 9 index 30 index add 0.5 mul\n" /* r23 = (r2+r3)/2 */
2793 " 9 index 30 index add 0.5 mul\n" /* g23 = (g2+g3)/2 */
2794 " 9 index 30 index add 0.5 mul\n" /* b23 = (b2+b3)/2 */
2795 " 5 copy 5 copy 35 5 roll 25 5 roll 15 5 roll\n");
2796
2797 /* stack = (V3) (V13) (V23) (V13) (V23) (V13) (V23) (V2) (V1) */
2798
2799 gl2psPrintf(" 4 index 10 index add 0.5 mul\n" /* x12 = (x1+x2)/2 */
2800 " 4 index 10 index add 0.5 mul\n" /* y12 = (y1+y2)/2 */
2801 " 4 index 10 index add 0.5 mul\n" /* r12 = (r1+r2)/2 */
2802 " 4 index 10 index add 0.5 mul\n" /* g12 = (g1+g2)/2 */
2803 " 4 index 10 index add 0.5 mul\n" /* b12 = (b1+b2)/2 */
2804 " 5 copy 5 copy 40 5 roll 25 5 roll 15 5 roll 25 5 roll\n");
2805
2806 /* stack = (V3) (V13) (V23) (V13) (V12) (V23) (V13) (V1) (V12) (V23) (V12) (V2) */
2807
2808 gl2psPrintf(" STnoshfill STnoshfill STnoshfill STnoshfill } BD\n");
2809
2810 /* Gouraud shaded triangle using recursive subdivision until the difference
2811 between corner colors does not exceed the thresholds:
2812 x3 y3 r3 g3 b3 x2 y2 r2 g2 b2 x1 y1 r1 g1 b1 STnoshfill */
2813
2814 gl2psPrintf("/STnoshfill {\n"
2815 " 2 index 8 index sub abs rThreshold gt\n" /* |r1-r2|>rth */
2816 " { STsplit }\n"
2817 " { 1 index 7 index sub abs gThreshold gt\n" /* |g1-g2|>gth */
2818 " { STsplit }\n"
2819 " { dup 6 index sub abs bThreshold gt\n" /* |b1-b2|>bth */
2820 " { STsplit }\n"
2821 " { 2 index 13 index sub abs rThreshold gt\n" /* |r1-r3|>rht */
2822 " { STsplit }\n"
2823 " { 1 index 12 index sub abs gThreshold gt\n" /* |g1-g3|>gth */
2824 " { STsplit }\n"
2825 " { dup 11 index sub abs bThreshold gt\n" /* |b1-b3|>bth */
2826 " { STsplit }\n"
2827 " { 7 index 13 index sub abs rThreshold gt\n"); /* |r2-r3|>rht */
2828 gl2psPrintf(" { STsplit }\n"
2829 " { 6 index 12 index sub abs gThreshold gt\n" /* |g2-g3|>gth */
2830 " { STsplit }\n"
2831 " { 5 index 11 index sub abs bThreshold gt\n" /* |b2-b3|>bth */
2832 " { STsplit }\n"
2833 " { Tm }\n" /* all colors sufficiently similar */
2834 " ifelse }\n"
2835 " ifelse }\n"
2836 " ifelse }\n"
2837 " ifelse }\n"
2838 " ifelse }\n"
2839 " ifelse }\n"
2840 " ifelse }\n"
2841 " ifelse }\n"
2842 " ifelse } BD\n");
2843
2844 gl2psPrintf("tryPS3shading\n"
2845 "{ /shfill where\n"
2846 " { /ST { STshfill } BD }\n"
2847 " { /ST { STnoshfill } BD }\n"
2848 " ifelse }\n"
2849 "{ /ST { STnoshfill } BD }\n"
2850 "ifelse\n");
2851
2852 gl2psPrintf("end\n"
2853 "%%%%EndProlog\n"
2854 "%%%%BeginSetup\n"
2855 "/DeviceRGB setcolorspace\n"
2856 "gl2psdict begin\n"
2857 "%%%%EndSetup\n"
2858 "%%%%Page: 1 1\n"
2859 "%%%%BeginPageSetup\n");
2860
2861 if(gl2ps->options & GL2PS_LANDSCAPE){
2862 gl2psPrintf("%d 0 translate 90 rotate\n",
2863 (int)gl2ps->viewport[3]);
2864 }
2865
2866 gl2psPrintf("%%%%EndPageSetup\n"
2867 "mark\n"
2868 "gsave\n"
2869 "1.0 1.0 scale\n");
2870
2871 if(gl2ps->options & GL2PS_DRAW_BACKGROUND){
2872 gl2psPrintf("%g %g %g C\n"
2873 "newpath %d %d moveto %d %d lineto %d %d lineto %d %d lineto\n"
2874 "closepath fill\n",
2875 gl2ps->bgcolor[0], gl2ps->bgcolor[1], gl2ps->bgcolor[2],
2876 (int)gl2ps->viewport[0], (int)gl2ps->viewport[1], (int)gl2ps->viewport[2],
2877 (int)gl2ps->viewport[1], (int)gl2ps->viewport[2], (int)gl2ps->viewport[3],
2878 (int)gl2ps->viewport[0], (int)gl2ps->viewport[3]);
2879 }
2880}
2881
2883{
2884 if(!gl2psSameColor(gl2ps->lastrgba, rgba)){
2885 gl2psSetLastColor(rgba);
2886 gl2psPrintf("%g %g %g C\n", rgba[0], rgba[1], rgba[2]);
2887 }
2888}
2889
2891{
2892 gl2ps->lastrgba[0] = gl2ps->lastrgba[1] = gl2ps->lastrgba[2] = -1.;
2893}
2894
2895static void gl2psEndPostScriptLine(void)
2896{
2897 int i;
2898 if(gl2ps->lastvertex.rgba[0] >= 0.){
2899 gl2psPrintf("%g %g LE\n", gl2ps->lastvertex.xyz[0], gl2ps->lastvertex.xyz[1]);
2900 for(i = 0; i < 3; i++)
2901 gl2ps->lastvertex.xyz[i] = -1.;
2902 for(i = 0; i < 4; i++)
2903 gl2ps->lastvertex.rgba[i] = -1.;
2904 }
2905}
2906
2907static void gl2psParseStipplePattern(GLushort pattern, GLint factor,
2908 int *nb, int array[10])
2909{
2910 int i, n;
2911 int on[8] = {0, 0, 0, 0, 0, 0, 0, 0};
2912 int off[8] = {0, 0, 0, 0, 0, 0, 0, 0};
2913 char tmp[16];
2914
2915 /* extract the 16 bits from the OpenGL stipple pattern */
2916 for(n = 15; n >= 0; n--){
2917 tmp[n] = (char)(pattern & 0x01);
2918 pattern >>= 1;
2919 }
2920 /* compute the on/off pixel sequence */
2921 n = 0;
2922 for(i = 0; i < 8; i++){
2923 while(n < 16 && !tmp[n]){ off[i]++; n++; }
2924 while(n < 16 && tmp[n]){ on[i]++; n++; }
2925 if(n >= 15){ i++; break; }
2926 }
2927
2928 /* store the on/off array from right to left, starting with off
2929 pixels. The PostScript specification allows for at most 11
2930 elements in the on/off array, so we limit ourselves to 5 on/off
2931 couples (our longest possible array is thus [on4 off4 on3 off3
2932 on2 off2 on1 off1 on0 off0]) */
2933 *nb = 0;
2934 for(n = i - 1; n >= 0 && *nb <= 8; n--){
2935 array[(*nb)++] = factor * on[n];
2936 array[(*nb)++] = factor * off[n];
2937 }
2938}
2939
2940static int gl2psPrintPostScriptDash(GLushort pattern, GLint factor, const char *str)
2941{
2942 int len = 0, i, n, array[10];
2943
2944 if(pattern == gl2ps->lastpattern && factor == gl2ps->lastfactor)
2945 return 0;
2946
2947 gl2ps->lastpattern = pattern;
2948 gl2ps->lastfactor = factor;
2949
2950 if(!pattern || !factor){
2951 /* solid line */
2952 len += gl2psPrintf("[] 0 %s\n", str);
2953 }
2954 else{
2955 gl2psParseStipplePattern(pattern, factor, &n, array);
2956 len += gl2psPrintf("[");
2957 for(i = 0; i < n; i++){
2958 if(i) len += gl2psPrintf(" ");
2959 len += gl2psPrintf("%d", array[i]);
2960 }
2961 len += gl2psPrintf("] 0 %s\n", str);
2962 }
2963
2964 return len;
2965}
2966
2968{
2969 int newline;
2970 GL2PSprimitive *prim;
2971
2972 prim = *(GL2PSprimitive**)data;
2973
2974 if((gl2ps->options & GL2PS_OCCLUSION_CULL) && prim->culled) return;
2975
2976 /* Every effort is made to draw lines as connected segments (i.e.,
2977 using a single PostScript path): this is the only way to get nice
2978 line joins and to not restart the stippling for every line
2979 segment. So if the primitive to print is not a line we must first
2980 finish the current line (if any): */
2981 if(prim->type != GL2PS_LINE) gl2psEndPostScriptLine();
2982
2983 switch(prim->type){
2984 case GL2PS_POINT :
2986 gl2psPrintf("%g %g %g P\n",
2987 prim->verts[0].xyz[0], prim->verts[0].xyz[1], 0.5 * prim->width);
2988 break;
2989 case GL2PS_LINE :
2990 if(!gl2psSamePosition(gl2ps->lastvertex.xyz, prim->verts[0].xyz) ||
2991 !gl2psSameColor(gl2ps->lastrgba, prim->verts[0].rgba) ||
2992 gl2ps->lastlinewidth != prim->width ||
2993 gl2ps->lastpattern != prim->pattern ||
2994 gl2ps->lastfactor != prim->factor){
2995 /* End the current line if the new segment does not start where
2996 the last one ended, or if the color, the width or the
2997 stippling have changed (multi-stroking lines with changing
2998 colors is necessary until we use /shfill for lines;
2999 unfortunately this means that at the moment we can screw up
3000 line stippling for smooth-shaded lines) */
3002 newline = 1;
3003 }
3004 else{
3005 newline = 0;
3006 }
3007 if(gl2ps->lastlinewidth != prim->width){
3008 gl2ps->lastlinewidth = prim->width;
3009 gl2psPrintf("%g W\n", gl2ps->lastlinewidth);
3010 }
3011 gl2psPrintPostScriptDash(prim->pattern, prim->factor, "setdash");
3013 gl2psPrintf("%g %g %s\n", prim->verts[0].xyz[0], prim->verts[0].xyz[1],
3014 newline ? "LS" : "L");
3015 gl2ps->lastvertex = prim->verts[1];
3016 break;
3017 case GL2PS_TRIANGLE :
3018 if(!gl2psVertsSameColor(prim)){
3020 gl2psPrintf("%g %g %g %g %g %g %g %g %g %g %g %g %g %g %g ST\n",
3021 prim->verts[2].xyz[0], prim->verts[2].xyz[1],
3022 prim->verts[2].rgba[0], prim->verts[2].rgba[1],
3023 prim->verts[2].rgba[2], prim->verts[1].xyz[0],
3024 prim->verts[1].xyz[1], prim->verts[1].rgba[0],
3025 prim->verts[1].rgba[1], prim->verts[1].rgba[2],
3026 prim->verts[0].xyz[0], prim->verts[0].xyz[1],
3027 prim->verts[0].rgba[0], prim->verts[0].rgba[1],
3028 prim->verts[0].rgba[2]);
3029 }
3030 else{
3032 gl2psPrintf("%g %g %g %g %g %g T\n",
3033 prim->verts[2].xyz[0], prim->verts[2].xyz[1],
3034 prim->verts[1].xyz[0], prim->verts[1].xyz[1],
3035 prim->verts[0].xyz[0], prim->verts[0].xyz[1]);
3036 }
3037 break;
3038 case GL2PS_QUADRANGLE :
3039 gl2psMsg(GL2PS_WARNING, "There should not be any quad left to print");
3040 break;
3041 case GL2PS_PIXMAP :
3042 gl2psPrintPostScriptPixmap(prim->verts[0].xyz[0], prim->verts[0].xyz[1],
3043 prim->data.image);
3044 break;
3045 case GL2PS_IMAGEMAP :
3046 if(prim->data.image->type != GL2PS_IMAGEMAP_WRITTEN){
3049 prim->data.image->pixels[1],
3050 prim->data.image->width, prim->data.image->height,
3051 reinterpret_cast<const unsigned char*>(&(prim->data.image->pixels[2])));
3053 }
3054 break;
3055 case GL2PS_TEXT :
3057 gl2psPrintf("(%s) ", prim->data.text->str);
3058 if(prim->data.text->angle)
3059 gl2psPrintf("%g ", prim->data.text->angle);
3060 gl2psPrintf("%g %g %d /%s ",
3061 prim->verts[0].xyz[0], prim->verts[0].xyz[1],
3062 prim->data.text->fontsize, prim->data.text->fontname);
3063 switch(prim->data.text->alignment){
3064 case GL2PS_TEXT_C:
3065 gl2psPrintf(prim->data.text->angle ? "SCCR\n" : "SCC\n");
3066 break;
3067 case GL2PS_TEXT_CL:
3068 gl2psPrintf(prim->data.text->angle ? "SCLR\n" : "SCL\n");
3069 break;
3070 case GL2PS_TEXT_CR:
3071 gl2psPrintf(prim->data.text->angle ? "SCRR\n" : "SCR\n");
3072 break;
3073 case GL2PS_TEXT_B:
3074 gl2psPrintf(prim->data.text->angle ? "SBCR\n" : "SBC\n");
3075 break;
3076 case GL2PS_TEXT_BR:
3077 gl2psPrintf(prim->data.text->angle ? "SBRR\n" : "SBR\n");
3078 break;
3079 case GL2PS_TEXT_T:
3080 gl2psPrintf(prim->data.text->angle ? "STCR\n" : "STC\n");
3081 break;
3082 case GL2PS_TEXT_TL:
3083 gl2psPrintf(prim->data.text->angle ? "STLR\n" : "STL\n");
3084 break;
3085 case GL2PS_TEXT_TR:
3086 gl2psPrintf(prim->data.text->angle ? "STRR\n" : "STR\n");
3087 break;
3088 case GL2PS_TEXT_BL:
3089 default:
3090 gl2psPrintf(prim->data.text->angle ? "SR\n" : "S\n");
3091 break;
3092 }
3093 break;
3094 case GL2PS_SPECIAL :
3095 /* alignment contains the format for which the special output text
3096 is intended */
3097 if(prim->data.text->alignment == GL2PS_PS ||
3098 prim->data.text->alignment == GL2PS_EPS)
3099 gl2psPrintf("%s\n", prim->data.text->str);
3100 break;
3101 default :
3102 break;
3103 }
3104}
3105
3107{
3108 gl2psPrintf("grestore\n"
3109 "showpage\n"
3110 "cleartomark\n"
3111 "%%%%PageTrailer\n"
3112 "%%%%Trailer\n"
3113 "end\n"
3114 "%%%%EOF\n");
3115
3117}
3118
3119static void gl2psPrintPostScriptBeginViewport(GLint viewport[4])
3120{
3121 GLint index;
3122 GLfloat rgba[4];
3123 int x = viewport[0], y = viewport[1], w = viewport[2], h = viewport[3];
3124
3125 glRenderMode(GL_FEEDBACK);
3126
3127 if(gl2ps->header){
3129 gl2ps->header = GL_FALSE;
3130 }
3131
3132 gl2psPrintf("gsave\n"
3133 "1.0 1.0 scale\n");
3134
3135 if(gl2ps->options & GL2PS_DRAW_BACKGROUND){
3136 if(gl2ps->colormode == GL_RGBA || gl2ps->colorsize == 0){
3137 glGetFloatv(GL_COLOR_CLEAR_VALUE, rgba);
3138 }
3139 else{
3140 glGetIntegerv(GL_INDEX_CLEAR_VALUE, &index);
3141 rgba[0] = gl2ps->colormap[index][0];
3142 rgba[1] = gl2ps->colormap[index][1];
3143 rgba[2] = gl2ps->colormap[index][2];
3144 rgba[3] = 1.0F;
3145 }
3146 gl2psPrintf("%g %g %g C\n"
3147 "newpath %d %d moveto %d %d lineto %d %d lineto %d %d lineto\n"
3148 "closepath fill\n",
3149 rgba[0], rgba[1], rgba[2],
3150 x, y, x+w, y, x+w, y+h, x, y+h);
3151 }
3152
3153 gl2psPrintf("newpath %d %d moveto %d %d lineto %d %d lineto %d %d lineto\n"
3154 "closepath clip\n",
3155 x, y, x+w, y, x+w, y+h, x, y+h);
3156
3157}
3158
3160{
3161 GLint res;
3162
3164 gl2psPrintf("grestore\n");
3165 return res;
3166}
3167
3169{
3170 /* End any remaining line, if any */
3172}
3173
3174/* definition of the PostScript and Encapsulated PostScript backends */
3175
3186
3197
3198/*********************************************************************
3199 *
3200 * LaTeX routines
3201 *
3202 *********************************************************************/
3203
3204static void gl2psPrintTeXHeader(void)
3205{
3206 char name[256];
3207 time_t now;
3208 int i;
3209
3210 if(gl2ps->filename && strlen(gl2ps->filename) < 256){
3211 for(i = strlen(gl2ps->filename)-1; i >= 0; i--){
3212 if(gl2ps->filename[i] == '.'){
3213 strncpy(name, gl2ps->filename, i);
3214 name[i] = '\0';
3215 break;
3216 }
3217 }
3218 if(i <= 0) strcpy(name, gl2ps->filename);
3219 }
3220 else{
3221 strcpy(name, "untitled");
3222 }
3223
3224 time(&now);
3225
3226 fprintf(gl2ps->stream,
3227 "%% Title: %s\n"
3228 "%% Creator: GL2PS %d.%d.%d%s, %s\n"
3229 "%% For: %s\n"
3230 "%% CreationDate: %s",
3233 gl2ps->producer, ctime(&now));
3234
3235 fprintf(gl2ps->stream,
3236 "\\setlength{\\unitlength}{1pt}\n"
3237 "\\begin{picture}(0,0)\n"
3238 "\\includegraphics{%s}\n"
3239 "\\end{picture}%%\n"
3240 "%s\\begin{picture}(%d,%d)(0,0)\n",
3241 name, (gl2ps->options & GL2PS_LANDSCAPE) ? "\\rotatebox{90}{" : "",
3242 (int)gl2ps->viewport[2], (int)gl2ps->viewport[3]);
3243}
3244
3246{
3247 GL2PSprimitive *prim;
3248
3249 prim = *(GL2PSprimitive**)data;
3250
3251 switch(prim->type){
3252 case GL2PS_TEXT :
3253 fprintf(gl2ps->stream, "\\fontsize{%d}{0}\n\\selectfont",
3254 prim->data.text->fontsize);
3255 fprintf(gl2ps->stream, "\\put(%g,%g){\\makebox(0,0)",
3256 prim->verts[0].xyz[0], prim->verts[0].xyz[1]);
3257 switch(prim->data.text->alignment){
3258 case GL2PS_TEXT_C:
3259 fprintf(gl2ps->stream, "{");
3260 break;
3261 case GL2PS_TEXT_CL:
3262 fprintf(gl2ps->stream, "[l]{");
3263 break;
3264 case GL2PS_TEXT_CR:
3265 fprintf(gl2ps->stream, "[r]{");
3266 break;
3267 case GL2PS_TEXT_B:
3268 fprintf(gl2ps->stream, "[b]{");
3269 break;
3270 case GL2PS_TEXT_BR:
3271 fprintf(gl2ps->stream, "[br]{");
3272 break;
3273 case GL2PS_TEXT_T:
3274 fprintf(gl2ps->stream, "[t]{");
3275 break;
3276 case GL2PS_TEXT_TL:
3277 fprintf(gl2ps->stream, "[tl]{");
3278 break;
3279 case GL2PS_TEXT_TR:
3280 fprintf(gl2ps->stream, "[tr]{");
3281 break;
3282 case GL2PS_TEXT_BL:
3283 default:
3284 fprintf(gl2ps->stream, "[bl]{");
3285 break;
3286 }
3287 if(prim->data.text->angle)
3288 fprintf(gl2ps->stream, "\\rotatebox{%g}{", prim->data.text->angle);
3289 fprintf(gl2ps->stream, "\\textcolor[rgb]{%g,%g,%g}{{%s}}",
3290 prim->verts[0].rgba[0], prim->verts[0].rgba[1], prim->verts[0].rgba[2],
3291 prim->data.text->str);
3292 if(prim->data.text->angle)
3293 fprintf(gl2ps->stream, "}");
3294 fprintf(gl2ps->stream, "}}\n");
3295 break;
3296 case GL2PS_SPECIAL :
3297 /* alignment contains the format for which the special output text
3298 is intended */
3299 if (prim->data.text->alignment == GL2PS_TEX)
3300 fprintf(gl2ps->stream, "%s\n", prim->data.text->str);
3301 break;
3302 default :
3303 break;
3304 }
3305}
3306
3307static void gl2psPrintTeXFooter(void)
3308{
3309 fprintf(gl2ps->stream, "\\end{picture}%s\n",
3310 (gl2ps->options & GL2PS_LANDSCAPE) ? "}" : "");
3311}
3312
3313static void gl2psPrintTeXBeginViewport(GLint viewport[4])
3314{
3315 GLint a __attribute__((unused)) = viewport[0];
3316 glRenderMode(GL_FEEDBACK);
3317
3318 if(gl2ps->header){
3320 gl2ps->header = GL_FALSE;
3321 }
3322}
3323
3325{
3326 return gl2psPrintPrimitives();
3327}
3328
3330{
3331}
3332
3333/* definition of the LaTeX backend */
3334
3345
3346/*********************************************************************
3347 *
3348 * PDF routines
3349 *
3350 *********************************************************************/
3351
3353{
3354#if defined(GL2PS_HAVE_ZLIB)
3355 if(gl2ps->options & GL2PS_COMPRESS){
3356 return fprintf(gl2ps->stream, "/Filter [/FlateDecode]\n");
3357 }
3358#endif
3359 return 0;
3360}
3361
3363{
3364 int i, offs = 0;
3365
3366 gl2psSetLastColor(rgba);
3367 for(i = 0; i < 3; ++i){
3368 if(GL2PS_ZERO(rgba[i]))
3369 offs += gl2psPrintf("%.0f ", 0.);
3370 else if(rgba[i] < 1e-4 || rgba[i] > 1e6) /* avoid %e formatting */
3371 offs += gl2psPrintf("%f ", rgba[i]);
3372 else
3373 offs += gl2psPrintf("%g ", rgba[i]);
3374 }
3375 offs += gl2psPrintf("RG\n");
3376 return offs;
3377}
3378
3380{
3381 int i, offs = 0;
3382
3383 for(i = 0; i < 3; ++i){
3384 if(GL2PS_ZERO(rgba[i]))
3385 offs += gl2psPrintf("%.0f ", 0.);
3386 else if(rgba[i] < 1e-4 || rgba[i] > 1e6) /* avoid %e formatting */
3387 offs += gl2psPrintf("%f ", rgba[i]);
3388 else
3389 offs += gl2psPrintf("%g ", rgba[i]);
3390 }
3391 offs += gl2psPrintf("rg\n");
3392 return offs;
3393}
3394
3395static int gl2psPrintPDFLineWidth(GLfloat lw)
3396{
3397 if(GL2PS_ZERO(lw))
3398 return gl2psPrintf("%.0f w\n", 0.);
3399 else if(lw < 1e-4 || lw > 1e6) /* avoid %e formatting */
3400 return gl2psPrintf("%f w\n", lw);
3401 else
3402 return gl2psPrintf("%g w\n", lw);
3403}
3404
3405static void gl2psPutPDFText(GL2PSstring *text, int cnt, GLfloat x, GLfloat y)
3406{
3407 GLfloat rad, crad, srad;
3408
3409 if(text->angle == 0.0F){
3410 gl2ps->streamlength += gl2psPrintf
3411 ("BT\n"
3412 "/F%d %d Tf\n"
3413 "%f %f Td\n"
3414 "(%s) Tj\n"
3415 "ET\n",
3416 cnt, text->fontsize, x, y, text->str);
3417 }
3418 else{
3419 rad = M_PI * text->angle / 180.0F;
3420 srad = (GLfloat)sin(rad);
3421 crad = (GLfloat)cos(rad);
3422 gl2ps->streamlength += gl2psPrintf
3423 ("BT\n"
3424 "/F%d %d Tf\n"
3425 "%f %f %f %f %f %f Tm\n"
3426 "(%s) Tj\n"
3427 "ET\n",
3428 cnt, text->fontsize, crad, srad, -srad, crad, x, y, text->str);
3429 }
3430}
3431
3432static void gl2psPutPDFImage(GL2PSimage *image, int cnt, GLfloat x, GLfloat y)
3433{
3434 gl2ps->streamlength += gl2psPrintf
3435 ("q\n"
3436 "%d 0 0 %d %f %f cm\n"
3437 "/Im%d Do\n"
3438 "Q\n",
3439 (int)image->width, (int)image->height, x, y, cnt);
3440}
3441
3442static void gl2psPDFstacksInit(void)
3443{
3444 gl2ps->objects_stack = 7 /* FIXED_XREF_ENTRIES */ + 1;
3445 gl2ps->extgs_stack = 0;
3446 gl2ps->font_stack = 0;
3447 gl2ps->im_stack = 0;
3448 gl2ps->trgroupobjects_stack = 0;
3449 gl2ps->shader_stack = 0;
3450 gl2ps->mshader_stack = 0;
3451}
3452
3454{
3455 if(!gro)
3456 return;
3457
3458 gro->ptrlist = NULL;
3459 gro->fontno = gro->gsno = gro->imno = gro->maskshno = gro->shno
3460 = gro->trgroupno = gro->fontobjno = gro->imobjno = gro->shobjno
3461 = gro->maskshobjno = gro->gsobjno = gro->trgroupobjno = -1;
3462}
3463
3464/* Build up group objects and assign name and object numbers */
3465
3466static void gl2psPDFgroupListInit(void)
3467{
3468 int i;
3469 GL2PSprimitive *p = NULL;
3470 GL2PSpdfgroup gro;
3471 int lasttype = GL2PS_NO_TYPE;
3472 GL2PSrgba lastrgba = {-1.0F, -1.0F, -1.0F, -1.0F};
3473 GLushort lastpattern = 0;
3474 GLint lastfactor = 0;
3475 GLfloat lastwidth = 1;
3476 GL2PStriangle lastt, tmpt;
3477 int lastTriangleWasNotSimpleWithSameColor = 0;
3478
3479 if(!gl2ps->pdfprimlist)
3480 return;
3481
3482 gl2ps->pdfgrouplist = gl2psListCreate(500, 500, sizeof(GL2PSpdfgroup));
3483 gl2psInitTriangle(&lastt);
3484
3485 for(i = 0; i < gl2psListNbr(gl2ps->pdfprimlist); ++i){
3486 p = *(GL2PSprimitive**)gl2psListPointer(gl2ps->pdfprimlist, i);
3487 switch(p->type){
3488 case GL2PS_PIXMAP:
3490 gro.ptrlist = gl2psListCreate(1, 2, sizeof(GL2PSprimitive*));
3491 gro.imno = gl2ps->im_stack++;
3492 gl2psListAdd(gro.ptrlist, &p);
3493 gl2psListAdd(gl2ps->pdfgrouplist, &gro);
3494 break;
3495 case GL2PS_TEXT:
3497 gro.ptrlist = gl2psListCreate(1, 2, sizeof(GL2PSprimitive*));
3498 gro.fontno = gl2ps->font_stack++;
3499 gl2psListAdd(gro.ptrlist, &p);
3500 gl2psListAdd(gl2ps->pdfgrouplist, &gro);
3501 break;
3502 case GL2PS_LINE:
3503 if(lasttype != p->type || lastwidth != p->width ||
3504 lastpattern != p->pattern || lastfactor != p->factor ||
3505 !gl2psSameColor(p->verts[0].rgba, lastrgba)){
3507 gro.ptrlist = gl2psListCreate(1, 2, sizeof(GL2PSprimitive*));
3508 gl2psListAdd(gro.ptrlist, &p);
3509 gl2psListAdd(gl2ps->pdfgrouplist, &gro);
3510 }
3511 else{
3512 gl2psListAdd(gro.ptrlist, &p);
3513 }
3514 lastpattern = p->pattern;
3515 lastfactor = p->factor;
3516 lastwidth = p->width;
3517 lastrgba[0] = p->verts[0].rgba[0];
3518 lastrgba[1] = p->verts[0].rgba[1];
3519 lastrgba[2] = p->verts[0].rgba[2];
3520 break;
3521 case GL2PS_POINT:
3522 if(lasttype != p->type || lastwidth != p->width ||
3523 !gl2psSameColor(p->verts[0].rgba, lastrgba)){
3525 gro.ptrlist = gl2psListCreate(1,2,sizeof(GL2PSprimitive*));
3526 gl2psListAdd(gro.ptrlist, &p);
3527 gl2psListAdd(gl2ps->pdfgrouplist, &gro);
3528 }
3529 else{
3530 gl2psListAdd(gro.ptrlist, &p);
3531 }
3532 lastwidth = p->width;
3533 lastrgba[0] = p->verts[0].rgba[0];
3534 lastrgba[1] = p->verts[0].rgba[1];
3535 lastrgba[2] = p->verts[0].rgba[2];
3536 break;
3537 case GL2PS_TRIANGLE:
3538 gl2psFillTriangleFromPrimitive(&tmpt, p, GL_TRUE);
3539 lastTriangleWasNotSimpleWithSameColor =
3540 !(tmpt.prop & T_CONST_COLOR && tmpt.prop & T_ALPHA_1) ||
3541 !gl2psSameColor(tmpt.vertex[0].rgba, lastt.vertex[0].rgba);
3542 if(lasttype == p->type && tmpt.prop == lastt.prop &&
3543 lastTriangleWasNotSimpleWithSameColor){
3544 /* TODO Check here for last alpha */
3545 gl2psListAdd(gro.ptrlist, &p);
3546 }
3547 else{
3549 gro.ptrlist = gl2psListCreate(1, 2, sizeof(GL2PSprimitive*));
3550 gl2psListAdd(gro.ptrlist, &p);
3551 gl2psListAdd(gl2ps->pdfgrouplist, &gro);
3552 }
3553 lastt = tmpt;
3554 break;
3555 default:
3556 break;
3557 }
3558 lasttype = p->type;
3559 }
3560}
3561
3563{
3564 GL2PStriangle t;
3565 GL2PSprimitive *prim = NULL;
3566
3567 if(!gro)
3568 return;
3569
3570 if(!gl2psListNbr(gro->ptrlist))
3571 return;
3572
3573 prim = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, 0);
3574
3575 if(prim->type != GL2PS_TRIANGLE)
3576 return;
3577
3578 gl2psFillTriangleFromPrimitive(&t, prim, GL_TRUE);
3579
3580 if(t.prop & T_CONST_COLOR && t.prop & T_ALPHA_LESS_1){
3581 gro->gsno = gl2ps->extgs_stack++;
3582 gro->gsobjno = gl2ps->objects_stack ++;
3583 }
3584 else if(t.prop & T_CONST_COLOR && t.prop & T_VAR_ALPHA){
3585 gro->gsno = gl2ps->extgs_stack++;
3586 gro->gsobjno = gl2ps->objects_stack++;
3587 gro->trgroupno = gl2ps->trgroupobjects_stack++;
3588 gro->trgroupobjno = gl2ps->objects_stack++;
3589 gro->maskshno = gl2ps->mshader_stack++;
3590 gro->maskshobjno = gl2ps->objects_stack++;
3591 }
3592 else if(t.prop & T_VAR_COLOR && t.prop & T_ALPHA_1){
3593 gro->shno = gl2ps->shader_stack++;
3594 gro->shobjno = gl2ps->objects_stack++;
3595 }
3596 else if(t.prop & T_VAR_COLOR && t.prop & T_ALPHA_LESS_1){
3597 gro->gsno = gl2ps->extgs_stack++;
3598 gro->gsobjno = gl2ps->objects_stack++;
3599 gro->shno = gl2ps->shader_stack++;
3600 gro->shobjno = gl2ps->objects_stack++;
3601 }
3602 else if(t.prop & T_VAR_COLOR && t.prop & T_VAR_ALPHA){
3603 gro->gsno = gl2ps->extgs_stack++;
3604 gro->gsobjno = gl2ps->objects_stack++;
3605 gro->shno = gl2ps->shader_stack++;
3606 gro->shobjno = 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++;
3611 }
3612}
3613
3614/* Main stream data */
3615
3617{
3618 int i, j, lastel;
3619 GL2PSprimitive *prim = NULL, *prev = NULL;
3620 GL2PSpdfgroup *gro;
3621 GL2PStriangle t;
3622
3623 if(!gl2ps->pdfgrouplist)
3624 return;
3625
3626 for(i = 0; i < gl2psListNbr(gl2ps->pdfgrouplist); ++i){
3627 gro = (GL2PSpdfgroup*)gl2psListPointer(gl2ps->pdfgrouplist, i);
3628
3629 lastel = gl2psListNbr(gro->ptrlist) - 1;
3630 if(lastel < 0)
3631 continue;
3632
3633 prim = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, 0);
3634
3635 switch(prim->type){
3636 case GL2PS_POINT:
3637 gl2ps->streamlength += gl2psPrintf("1 J\n");
3638 gl2ps->streamlength += gl2psPrintPDFLineWidth(prim->width);
3639 gl2ps->streamlength += gl2psPrintPDFStrokeColor(prim->verts[0].rgba);
3640 for(j = 0; j <= lastel; ++j){
3641 prim = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, j);
3642 gl2ps->streamlength +=
3643 gl2psPrintf("%f %f m %f %f l\n",
3644 prim->verts[0].xyz[0], prim->verts[0].xyz[1],
3645 prim->verts[0].xyz[0], prim->verts[0].xyz[1]);
3646 }
3647 gl2ps->streamlength += gl2psPrintf("S\n");
3648 gl2ps->streamlength += gl2psPrintf("0 J\n");
3649 break;
3650 case GL2PS_LINE:
3651 /* We try to use as few paths as possible to draw lines, in
3652 order to get nice stippling even when the individual segments
3653 are smaller than the stipple */
3654 gl2ps->streamlength += gl2psPrintPDFLineWidth(prim->width);
3655 gl2ps->streamlength += gl2psPrintPDFStrokeColor(prim->verts[0].rgba);
3656 gl2ps->streamlength += gl2psPrintPostScriptDash(prim->pattern, prim->factor, "d");
3657 /* start new path */
3658 gl2ps->streamlength +=
3659 gl2psPrintf("%f %f m\n",
3660 prim->verts[0].xyz[0], prim->verts[0].xyz[1]);
3661
3662 for(j = 1; j <= lastel; ++j){
3663 prev = prim;
3664 prim = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, j);
3665 if(!gl2psSamePosition(prim->verts[0].xyz, prev->verts[1].xyz)){
3666 /* the starting point of the new segment does not match the
3667 end point of the previous line, so we end the current
3668 path and start a new one */
3669 gl2ps->streamlength +=
3670 gl2psPrintf("%f %f l\n",
3671 prev->verts[1].xyz[0], prev->verts[1].xyz[1]);
3672 gl2ps->streamlength +=
3673 gl2psPrintf("%f %f m\n",
3674 prim->verts[0].xyz[0], prim->verts[0].xyz[1]);
3675 }
3676 else{
3677 /* the two segements are connected, so we just append to the
3678 current path */
3679 gl2ps->streamlength +=
3680 gl2psPrintf("%f %f l\n",
3681 prim->verts[0].xyz[0], prim->verts[0].xyz[1]);
3682 }
3683 }
3684 /* end last path */
3685 gl2ps->streamlength +=
3686 gl2psPrintf("%f %f l\n",
3687 prim->verts[1].xyz[0], prim->verts[1].xyz[1]);
3688 gl2ps->streamlength += gl2psPrintf("S\n");
3689 break;
3690 case GL2PS_TRIANGLE:
3691 gl2psFillTriangleFromPrimitive(&t, prim, GL_TRUE);
3693
3694 /* No alpha and const color: Simple PDF draw orders */
3695 if(t.prop & T_CONST_COLOR && t.prop & T_ALPHA_1){
3696 gl2ps->streamlength += gl2psPrintPDFFillColor(t.vertex[0].rgba);
3697 for(j = 0; j <= lastel; ++j){
3698 prim = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, j);
3699 gl2psFillTriangleFromPrimitive(&t, prim, GL_FALSE);
3700 gl2ps->streamlength
3701 += gl2psPrintf("%f %f m\n"
3702 "%f %f l\n"
3703 "%f %f l\n"
3704 "h f\n",
3705 t.vertex[0].xyz[0], t.vertex[0].xyz[1],
3706 t.vertex[1].xyz[0], t.vertex[1].xyz[1],
3707 t.vertex[2].xyz[0], t.vertex[2].xyz[1]);
3708 }
3709 }
3710 /* Const alpha < 1 and const color: Simple PDF draw orders
3711 and an extra extended Graphics State for the alpha const */
3712 else if(t.prop & T_CONST_COLOR && t.prop & T_ALPHA_LESS_1){
3713 gl2ps->streamlength += gl2psPrintf("q\n"
3714 "/GS%d gs\n",
3715 gro->gsno);
3716 gl2ps->streamlength += gl2psPrintPDFFillColor(prim->verts[0].rgba);
3717 for(j = 0; j <= lastel; ++j){
3718 prim = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, j);
3719 gl2psFillTriangleFromPrimitive(&t, prim, GL_FALSE);
3720 gl2ps->streamlength
3721 += gl2psPrintf("%f %f m\n"
3722 "%f %f l\n"
3723 "%f %f l\n"
3724 "h f\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]);
3728 }
3729 gl2ps->streamlength += gl2psPrintf("Q\n");
3730 }
3731 /* Variable alpha and const color: Simple PDF draw orders
3732 and an extra extended Graphics State + Xobject + Shader
3733 object for the alpha mask */
3734 else if(t.prop & T_CONST_COLOR && t.prop & T_VAR_ALPHA){
3735 gl2ps->streamlength += gl2psPrintf("q\n"
3736 "/GS%d gs\n"
3737 "/TrG%d Do\n",
3738 gro->gsno, gro->trgroupno);
3739 gl2ps->streamlength += gl2psPrintPDFFillColor(prim->verts[0].rgba);
3740 for(j = 0; j <= lastel; ++j){
3741 prim = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, j);
3742 gl2psFillTriangleFromPrimitive(&t, prim, GL_FALSE);
3743 gl2ps->streamlength
3744 += gl2psPrintf("%f %f m\n"
3745 "%f %f l\n"
3746 "%f %f l\n"
3747 "h f\n",
3748 t.vertex[0].xyz[0], t.vertex[0].xyz[1],
3749 t.vertex[1].xyz[0], t.vertex[1].xyz[1],
3750 t.vertex[2].xyz[0], t.vertex[2].xyz[1]);
3751 }
3752 gl2ps->streamlength += gl2psPrintf("Q\n");
3753 }
3754 /* Variable color and no alpha: Shader Object for the colored
3755 triangle(s) */
3756 else if(t.prop & T_VAR_COLOR && t.prop & T_ALPHA_1){
3757 gl2ps->streamlength += gl2psPrintf("/Sh%d sh\n", gro->shno);
3758 }
3759 /* Variable color and const alpha < 1: Shader Object for the
3760 colored triangle(s) and an extra extended Graphics State
3761 for the alpha const */
3762 else if(t.prop & T_VAR_COLOR && t.prop & T_ALPHA_LESS_1){
3763 gl2ps->streamlength += gl2psPrintf("q\n"
3764 "/GS%d gs\n"
3765 "/Sh%d sh\n"
3766 "Q\n",
3767 gro->gsno, gro->shno);
3768 }
3769 /* Variable alpha and color: Shader Object for the colored
3770 triangle(s) and an extra extended Graphics State
3771 + Xobject + Shader object for the alpha mask */
3772 else if(t.prop & T_VAR_COLOR && t.prop & T_VAR_ALPHA){
3773 gl2ps->streamlength += gl2psPrintf("q\n"
3774 "/GS%d gs\n"
3775 "/TrG%d Do\n"
3776 "/Sh%d sh\n"
3777 "Q\n",
3778 gro->gsno, gro->trgroupno, gro->shno);
3779 }
3780 break;
3781 case GL2PS_PIXMAP:
3782 for(j = 0; j <= lastel; ++j){
3783 prim = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, j);
3784 gl2psPutPDFImage(prim->data.image, gro->imno, prim->verts[0].xyz[0],
3785 prim->verts[0].xyz[1]);
3786 }
3787 break;
3788 case GL2PS_TEXT:
3789 for(j = 0; j <= lastel; ++j){
3790 prim = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, j);
3791 gl2ps->streamlength += gl2psPrintPDFFillColor(prim->verts[0].rgba);
3792 gl2psPutPDFText(prim->data.text, gro->fontno, prim->verts[0].xyz[0],
3793 prim->verts[0].xyz[1]);
3794 }
3795 break;
3796 default:
3797 break;
3798 }
3799 }
3800}
3801
3802/* Graphics State names */
3803
3805{
3806 GL2PSpdfgroup *gro;
3807 int offs = 0;
3808 int i;
3809
3810 offs += fprintf(gl2ps->stream,
3811 "/ExtGState\n"
3812 "<<\n"
3813 "/GSa 7 0 R\n");
3814 for(i = 0; i < gl2psListNbr(gl2ps->pdfgrouplist); ++i){
3815 gro = (GL2PSpdfgroup*)gl2psListPointer(gl2ps->pdfgrouplist, i);
3816 if(gro->gsno >= 0)
3817 offs += fprintf(gl2ps->stream, "/GS%d %d 0 R\n", gro->gsno, gro->gsobjno);
3818 }
3819 offs += fprintf(gl2ps->stream, ">>\n");
3820 return offs;
3821}
3822
3823/* Main Shader names */
3824
3826{
3827 GL2PSpdfgroup *gro;
3828 int offs = 0;
3829 int i;
3830
3831 offs += fprintf(gl2ps->stream,
3832 "/Shading\n"
3833 "<<\n");
3834 for(i = 0; i < gl2psListNbr(gl2ps->pdfgrouplist); ++i){
3835 gro = (GL2PSpdfgroup*)gl2psListPointer(gl2ps->pdfgrouplist, i);
3836 if(gro->shno >= 0)
3837 offs += fprintf(gl2ps->stream, "/Sh%d %d 0 R\n", gro->shno, gro->shobjno);
3838 if(gro->maskshno >= 0)
3839 offs += fprintf(gl2ps->stream, "/TrSh%d %d 0 R\n", gro->maskshno, gro->maskshobjno);
3840 }
3841 offs += fprintf(gl2ps->stream,">>\n");
3842 return offs;
3843}
3844
3845/* Images & Mask Shader XObject names */
3846
3848{
3849 int i;
3850 GL2PSprimitive *p = NULL;
3851 GL2PSpdfgroup *gro;
3852 int offs = 0;
3853
3854 offs += fprintf(gl2ps->stream,
3855 "/XObject\n"
3856 "<<\n");
3857
3858 for(i = 0; i < gl2psListNbr(gl2ps->pdfgrouplist); ++i){
3859 gro = (GL2PSpdfgroup*)gl2psListPointer(gl2ps->pdfgrouplist, i);
3860 if(!gl2psListNbr(gro->ptrlist))
3861 continue;
3862 p = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, 0);
3863 switch(p->type){
3864 case GL2PS_PIXMAP:
3865 gro->imobjno = gl2ps->objects_stack++;
3866 if(GL_RGBA == p->data.image->format) /* reserve one object for image mask */
3867 gl2ps->objects_stack++;
3868 offs += fprintf(gl2ps->stream, "/Im%d %d 0 R\n", gro->imno, gro->imobjno);
3869 break;
3870 case GL2PS_TRIANGLE:
3871 if(gro->trgroupno >=0)
3872 offs += fprintf(gl2ps->stream, "/TrG%d %d 0 R\n", gro->trgroupno, gro->trgroupobjno);
3873 break;
3874 default:
3875 break;
3876 }
3877 }
3878 offs += fprintf(gl2ps->stream,">>\n");
3879 return offs;
3880}
3881
3882/* Font names */
3883
3885{
3886 int i;
3887 GL2PSpdfgroup *gro;
3888 int offs = 0;
3889
3890 offs += fprintf(gl2ps->stream, "/Font\n<<\n");
3891
3892 for(i = 0; i < gl2psListNbr(gl2ps->pdfgrouplist); ++i){
3893 gro = (GL2PSpdfgroup*)gl2psListPointer(gl2ps->pdfgrouplist, i);
3894 if(gro->fontno < 0)
3895 continue;
3896 gro->fontobjno = gl2ps->objects_stack++;
3897 offs += fprintf(gl2ps->stream, "/F%d %d 0 R\n", gro->fontno, gro->fontobjno);
3898 }
3899 offs += fprintf(gl2ps->stream, ">>\n");
3900
3901 return offs;
3902}
3903
3905{
3906 int i;
3907 GL2PSpdfgroup *gro = NULL;
3908
3909 if(!gl2ps->pdfgrouplist)
3910 return;
3911
3912 for(i = 0; i < gl2psListNbr(gl2ps->pdfgrouplist); ++i){
3913 gro = (GL2PSpdfgroup*)gl2psListPointer(gl2ps->pdfgrouplist,i);
3915 }
3916
3917 gl2psListDelete(gl2ps->pdfgrouplist);
3918 gl2ps->pdfgrouplist = NULL;
3919}
3920
3921/* Print 1st PDF object - file info */
3922
3923static int gl2psPrintPDFInfo(void)
3924{
3925 int offs;
3926 time_t now;
3927 struct tm newtime;
3928
3929 time(&now);
3930
3931 offs = fprintf(gl2ps->stream,
3932 "1 0 obj\n"
3933 "<<\n"
3934 "/Title (%s)\n"
3935 "/Creator (GL2PS %d.%d.%d%s, %s)\n"
3936 "/Producer (%s)\n",
3939 gl2ps->producer);
3940
3941 if(!gmtime_r(&now, &newtime)){
3942 offs += fprintf(gl2ps->stream,
3943 ">>\n"
3944 "endobj\n");
3945 return offs;
3946 }
3947
3948 offs += fprintf(gl2ps->stream,
3949 "/CreationDate (D:%d%02d%02d%02d%02d%02d)\n"
3950 ">>\n"
3951 "endobj\n",
3952 newtime.tm_year+1900,
3953 newtime.tm_mon+1,
3954 newtime.tm_mday,
3955 newtime.tm_hour,
3956 newtime.tm_min,
3957 newtime.tm_sec);
3958 return offs;
3959}
3960
3961/* Create catalog and page structure - 2nd and 3th PDF object */
3962
3963static int gl2psPrintPDFCatalog(void)
3964{
3965 return fprintf(gl2ps->stream,
3966 "2 0 obj\n"
3967 "<<\n"
3968 "/Type /Catalog\n"
3969 "/Pages 3 0 R\n"
3970 ">>\n"
3971 "endobj\n");
3972}
3973
3974static int gl2psPrintPDFPages(void)
3975{
3976 return fprintf(gl2ps->stream,
3977 "3 0 obj\n"
3978 "<<\n"
3979 "/Type /Pages\n"
3980 "/Kids [6 0 R]\n"
3981 "/Count 1\n"
3982 ">>\n"
3983 "endobj\n");
3984}
3985
3986/* Open stream for data - graphical objects, fonts etc. PDF object 4 */
3987
3989{
3990 int offs = 0;
3991
3992 offs += fprintf(gl2ps->stream,
3993 "4 0 obj\n"
3994 "<<\n"
3995 "/Length 5 0 R\n" );
3997 offs += fprintf(gl2ps->stream,
3998 ">>\n"
3999 "stream\n");
4000 return offs;
4001}
4002
4003/* Stream setup - Graphics state, fill background if allowed */
4004
4006{
4007 int offs;
4008
4009 offs = gl2psPrintf("/GSa gs\n");
4010
4011 if(gl2ps->options & GL2PS_DRAW_BACKGROUND){
4012 offs += gl2psPrintPDFFillColor(gl2ps->bgcolor);
4013 offs += gl2psPrintf("%d %d %d %d re\n",
4014 (int)gl2ps->viewport[0], (int)gl2ps->viewport[1],
4015 (int)gl2ps->viewport[2], (int)gl2ps->viewport[3]);
4016 offs += gl2psPrintf("f\n");
4017 }
4018 return offs;
4019}
4020
4021/* Use the functions above to create the first part of the PDF*/
4022
4023static void gl2psPrintPDFHeader(void)
4024{
4025 int offs = 0;
4026 gl2ps->pdfprimlist = gl2psListCreate(500, 500, sizeof(GL2PSprimitive*));
4028
4029 gl2ps->xreflist = (int*)gl2psMalloc(sizeof(int) * gl2ps->objects_stack);
4030
4031#if defined(GL2PS_HAVE_ZLIB)
4032 if(gl2ps->options & GL2PS_COMPRESS){
4033 gl2psSetupCompress();
4034 }
4035#endif
4036 gl2ps->xreflist[0] = 0;
4037 offs += fprintf(gl2ps->stream, "%%PDF-1.4\n");
4038 gl2ps->xreflist[1] = offs;
4039
4040 offs += gl2psPrintPDFInfo();
4041 gl2ps->xreflist[2] = offs;
4042
4043 offs += gl2psPrintPDFCatalog();
4044 gl2ps->xreflist[3] = offs;
4045
4046 offs += gl2psPrintPDFPages();
4047 gl2ps->xreflist[4] = offs;
4048
4049 offs += gl2psOpenPDFDataStream();
4050 gl2ps->xreflist[5] = offs; /* finished in gl2psPrintPDFFooter */
4051 gl2ps->streamlength = gl2psOpenPDFDataStreamWritePreface();
4052}
4053
4054/* The central primitive drawing */
4055
4057{
4059
4060 if((gl2ps->options & GL2PS_OCCLUSION_CULL) && prim->culled)
4061 return;
4062
4063 prim = gl2psCopyPrimitive(prim); /* deep copy */
4064 gl2psListAdd(gl2ps->pdfprimlist, &prim);
4065}
4066
4067/* close stream and ... */
4068
4070{
4071 int offs = 0;
4072
4073#if defined(GL2PS_HAVE_ZLIB)
4074 if(gl2ps->options & GL2PS_COMPRESS){
4075 if(Z_OK != gl2psDeflate())
4076 gl2psMsg(GL2PS_ERROR, "Zlib deflate error");
4077 else
4078 fwrite(gl2ps->compress->dest, gl2ps->compress->destLen, 1, gl2ps->stream);
4079 gl2ps->streamlength += gl2ps->compress->destLen;
4080
4081 offs += gl2ps->streamlength;
4082 gl2psFreeCompress();
4083 }
4084#endif
4085
4086 offs += fprintf(gl2ps->stream,
4087 "endstream\n"
4088 "endobj\n");
4089 return offs;
4090}
4091
4092/* ... write the now known length object */
4093
4095{
4096 return fprintf(gl2ps->stream,
4097 "5 0 obj\n"
4098 "%d\n"
4099 "endobj\n", val);
4100}
4101
4102/* Put the info created before in PDF objects */
4103
4105{
4106 int offs;
4107
4108 /* Write fixed part */
4109
4110 offs = fprintf(gl2ps->stream,
4111 "6 0 obj\n"
4112 "<<\n"
4113 "/Type /Page\n"
4114 "/Parent 3 0 R\n"
4115 "/MediaBox [%d %d %d %d]\n",
4116 (int)gl2ps->viewport[0], (int)gl2ps->viewport[1],
4117 (int)gl2ps->viewport[2], (int)gl2ps->viewport[3]);
4118
4119 if(gl2ps->options & GL2PS_LANDSCAPE)
4120 offs += fprintf(gl2ps->stream, "/Rotate -90\n");
4121
4122 offs += fprintf(gl2ps->stream,
4123 "/Contents 4 0 R\n"
4124 "/Resources\n"
4125 "<<\n"
4126 "/ProcSet [/PDF /Text /ImageB /ImageC] %%/ImageI\n");
4127
4128 return offs;
4129
4130 /* End fixed part, proceeds in gl2psPDFgroupListWriteVariableResources() */
4131}
4132
4134{
4135 int offs = 0;
4136
4137 /* a) Graphics States for shader alpha masks*/
4139
4140 /* b) Shader and shader masks */
4142
4143 /* c) XObjects (Images & Shader Masks) */
4145
4146 /* d) Fonts */
4148
4149 /* End resources and page */
4150 offs += fprintf(gl2ps->stream,
4151 ">>\n"
4152 ">>\n"
4153 "endobj\n");
4154 return offs;
4155}
4156
4157/* Standard Graphics State */
4158
4160{
4161 return fprintf(gl2ps->stream,
4162 "7 0 obj\n"
4163 "<<\n"
4164 "/Type /ExtGState\n"
4165 "/SA false\n"
4166 "/SM 0.02\n"
4167 "/OP false\n"
4168 "/op false\n"
4169 "/OPM 0\n"
4170 "/BG2 /Default\n"
4171 "/UCR2 /Default\n"
4172 "/TR2 /Default\n"
4173 ">>\n"
4174 "endobj\n");
4175}
4176
4177/* Put vertex' edge flag (8bit) and coordinates (32bit) in shader stream */
4178
4180 size_t (*action)(unsigned long data,
4181 size_t size),
4182 GLfloat dx, GLfloat dy,
4183 GLfloat xmin, GLfloat ymin)
4184{
4185 int offs = 0;
4186 unsigned long imap;
4187 GLfloat diff;
4188 double dmax = static_cast<double>(~1UL);
4189 char edgeflag = 0;
4190
4191 /* FIXME: temp bux fix for 64 bit archs: */
4192 if(sizeof(unsigned long) == 8) dmax = dmax - 2048.;
4193
4194 offs += (*action)(edgeflag, 1);
4195
4196 /* The Shader stream in PDF requires to be in a 'big-endian'
4197 order */
4198
4199 if(GL2PS_ZERO(dx * dy)){
4200 offs += (*action)(0, 4);
4201 offs += (*action)(0, 4);
4202 }
4203 else{
4204 diff = (vertex->xyz[0] - xmin) / dx;
4205 if(diff > 1)
4206 diff = 1.0F;
4207 else if(diff < 0)
4208 diff = 0.0F;
4209 imap = (unsigned long)(diff * dmax);
4210 offs += (*action)(imap, 4);
4211
4212 diff = (vertex->xyz[1] - ymin) / dy;
4213 if(diff > 1)
4214 diff = 1.0F;
4215 else if(diff < 0)
4216 diff = 0.0F;
4217 imap = (unsigned long)(diff * dmax);
4218 offs += (*action)(imap, 4);
4219 }
4220
4221 return offs;
4222}
4223
4224/* Put vertex' rgb value (8bit for every component) in shader stream */
4225
4227 size_t (*action)(unsigned long data,
4228 size_t size))
4229{
4230 int offs = 0;
4231 unsigned long imap;
4232 double dmax = static_cast<double>(~1UL);
4233
4234 /* FIXME: temp bux fix for 64 bit archs: */
4235 if(sizeof(unsigned long) == 8) dmax = dmax - 2048.;
4236
4237 imap = (unsigned long)((vertex->rgba[0]) * dmax);
4238 offs += (*action)(imap, 1);
4239
4240 imap = (unsigned long)((vertex->rgba[1]) * dmax);
4241 offs += (*action)(imap, 1);
4242
4243 imap = (unsigned long)((vertex->rgba[2]) * dmax);
4244 offs += (*action)(imap, 1);
4245
4246 return offs;
4247}
4248
4249/* Put vertex' alpha (8/16bit) in shader stream */
4250
4252 size_t (*action)(unsigned long data,
4253 size_t size),
4254 int sigbyte)
4255{
4256 int offs = 0;
4257 unsigned long imap;
4258 double dmax = static_cast<double>(~1UL);
4259
4260 /* FIXME: temp bux fix for 64 bit archs: */
4261 if(sizeof(unsigned long) == 8) dmax = dmax - 2048.;
4262
4263 if(sigbyte != 8 && sigbyte != 16)
4264 sigbyte = 8;
4265
4266 sigbyte /= 8;
4267
4268 imap = (unsigned long)((vertex->rgba[3]) * dmax);
4269
4270 offs += (*action)(imap, sigbyte);
4271
4272 return offs;
4273}
4274
4275/* Put a triangles raw data in shader stream */
4276
4278 GLfloat dx, GLfloat dy,
4279 GLfloat xmin, GLfloat ymin,
4280 size_t (*action)(unsigned long data,
4281 size_t size),
4282 int gray)
4283{
4284 int i, offs = 0;
4285 GL2PSvertex v;
4286
4287 if(gray && gray != 8 && gray != 16)
4288 gray = 8;
4289
4290 for(i = 0; i < 3; ++i){
4291 offs += gl2psPrintPDFShaderStreamDataCoord(&triangle->vertex[i], action,
4292 dx, dy, xmin, ymin);
4293 if(gray){
4294 v = triangle->vertex[i];
4295 offs += gl2psPrintPDFShaderStreamDataAlpha(&v, action, gray);
4296 }
4297 else{
4298 offs += gl2psPrintPDFShaderStreamDataRGB(&triangle->vertex[i], action);
4299 }
4300 }
4301
4302 return offs;
4303}
4304
4305static void gl2psPDFRectHull(GLfloat *xmin, GLfloat *xmax,
4306 GLfloat *ymin, GLfloat *ymax,
4307 GL2PStriangle *triangles, int cnt)
4308{
4309 int i, j;
4310
4311 *xmin = triangles[0].vertex[0].xyz[0];
4312 *xmax = triangles[0].vertex[0].xyz[0];
4313 *ymin = triangles[0].vertex[0].xyz[1];
4314 *ymax = triangles[0].vertex[0].xyz[1];
4315
4316 for(i = 0; i < cnt; ++i){
4317 for(j = 0; j < 3; ++j){
4318 if(*xmin > triangles[i].vertex[j].xyz[0])
4319 *xmin = triangles[i].vertex[j].xyz[0];
4320 if(*xmax < triangles[i].vertex[j].xyz[0])
4321 *xmax = triangles[i].vertex[j].xyz[0];
4322 if(*ymin > triangles[i].vertex[j].xyz[1])
4323 *ymin = triangles[i].vertex[j].xyz[1];
4324 if(*ymax < triangles[i].vertex[j].xyz[1])
4325 *ymax = triangles[i].vertex[j].xyz[1];
4326 }
4327 }
4328}
4329
4330/* Writes shaded triangle
4331 gray == 0 means write RGB triangles
4332 gray == 8 8bit-grayscale (for alpha masks)
4333 gray == 16 16bit-grayscale (for alpha masks) */
4334
4335static int gl2psPrintPDFShader(int obj, GL2PStriangle *triangles,
4336 int size, int gray)
4337{
4338 int i, offs = 0, vertexbytes, done = 0;
4339 GLfloat xmin, xmax, ymin, ymax;
4340
4341 switch(gray){
4342 case 0:
4343 vertexbytes = 1+4+4+1+1+1;
4344 break;
4345 case 8:
4346 vertexbytes = 1+4+4+1;
4347 break;
4348 case 16:
4349 vertexbytes = 1+4+4+2;
4350 break;
4351 default:
4352 gray = 8;
4353 vertexbytes = 1+4+4+1;
4354 break;
4355 }
4356
4357 gl2psPDFRectHull(&xmin, &xmax, &ymin, &ymax, triangles, size);
4358
4359 offs += fprintf(gl2ps->stream,
4360 "%d 0 obj\n"
4361 "<< "
4362 "/ShadingType 4 "
4363 "/ColorSpace %s "
4364 "/BitsPerCoordinate 32 "
4365 "/BitsPerComponent %d "
4366 "/BitsPerFlag 8 "
4367 "/Decode [%f %f %f %f 0 1 %s] ",
4368 obj,
4369 (gray) ? "/DeviceGray" : "/DeviceRGB",
4370 (gray) ? gray : 8,
4371 xmin, xmax, ymin, ymax,
4372 (gray) ? "" : "0 1 0 1");
4373
4374#if defined(GL2PS_HAVE_ZLIB)
4375 if(gl2ps->options & GL2PS_COMPRESS){
4376 gl2psAllocCompress(vertexbytes * size * 3);
4377
4378 for(i = 0; i < size; ++i)
4379 gl2psPrintPDFShaderStreamData(&triangles[i],
4381 gl2psWriteBigEndianCompress, gray);
4382
4383 if(Z_OK == gl2psDeflate() && 23 + gl2ps->compress->destLen < gl2ps->compress->srcLen){
4385 offs += fprintf(gl2ps->stream,
4386 "/Length %d "
4387 ">>\n"
4388 "stream\n",
4389 (int)gl2ps->compress->destLen);
4390 offs += gl2ps->compress->destLen * fwrite(gl2ps->compress->dest,
4391 gl2ps->compress->destLen,
4392 1, gl2ps->stream);
4393 done = 1;
4394 }
4395 gl2psFreeCompress();
4396 }
4397#endif
4398
4399 if(!done){
4400 /* no compression, or too long after compression, or compress error
4401 -> write non-compressed entry */
4402 offs += fprintf(gl2ps->stream,
4403 "/Length %d "
4404 ">>\n"
4405 "stream\n",
4406 vertexbytes * 3 * size);
4407 for(i = 0; i < size; ++i)
4408 offs += gl2psPrintPDFShaderStreamData(&triangles[i],
4410 gl2psWriteBigEndian, gray);
4411 }
4412
4413 offs += fprintf(gl2ps->stream,
4414 "\nendstream\n"
4415 "endobj\n");
4416
4417 return offs;
4418}
4419
4420/* Writes a XObject for a shaded triangle mask */
4421
4422static int gl2psPrintPDFShaderMask(int obj, int childobj)
4423{
4424 int offs = 0, len;
4425
4426 offs += fprintf(gl2ps->stream,
4427 "%d 0 obj\n"
4428 "<<\n"
4429 "/Type /XObject\n"
4430 "/Subtype /Form\n"
4431 "/BBox [ %d %d %d %d ]\n"
4432 "/Group \n<<\n/S /Transparency /CS /DeviceRGB\n"
4433 ">>\n",
4434 obj,
4435 (int)gl2ps->viewport[0], (int)gl2ps->viewport[1],
4436 (int)gl2ps->viewport[2], (int)gl2ps->viewport[3]);
4437
4438 len = (childobj>0)
4439 ? strlen("/TrSh sh\n") + (int)log10((double)childobj)+1
4440 : strlen("/TrSh0 sh\n");
4441
4442 offs += fprintf(gl2ps->stream,
4443 "/Length %d\n"
4444 ">>\n"
4445 "stream\n",
4446 len);
4447 offs += fprintf(gl2ps->stream,
4448 "/TrSh%d sh\n",
4449 childobj);
4450 offs += fprintf(gl2ps->stream,
4451 "endstream\n"
4452 "endobj\n");
4453
4454 return offs;
4455}
4456
4457/* Writes a Extended graphics state for a shaded triangle mask if
4458 simplealpha ist true the childobj argument is ignored and a /ca
4459 statement will be written instead */
4460
4461static int gl2psPrintPDFShaderExtGS(int obj, int childobj)
4462{
4463 int offs = 0;
4464
4465 offs += fprintf(gl2ps->stream,
4466 "%d 0 obj\n"
4467 "<<\n",
4468 obj);
4469
4470 offs += fprintf(gl2ps->stream,
4471 "/SMask << /S /Alpha /G %d 0 R >> ",
4472 childobj);
4473
4474 offs += fprintf(gl2ps->stream,
4475 ">>\n"
4476 "endobj\n");
4477 return offs;
4478}
4479
4480/* a simple graphics state */
4481
4482static int gl2psPrintPDFShaderSimpleExtGS(int obj, GLfloat alpha)
4483{
4484 int offs = 0;
4485
4486 offs += fprintf(gl2ps->stream,
4487 "%d 0 obj\n"
4488 "<<\n"
4489 "/ca %g"
4490 ">>\n"
4491 "endobj\n",
4492 obj, alpha);
4493 return offs;
4494}
4495
4496/* Similar groups of functions for pixmaps and text */
4497
4499 size_t (*action)(unsigned long data,
4500 size_t size),
4501 int gray)
4502{
4503 int x, y, shift;
4504 GLfloat r, g, b, a;
4505
4506 if(im->format != GL_RGBA && gray)
4507 return 0;
4508
4509 if(gray && gray != 8 && gray != 16)
4510 gray = 8;
4511
4512 gray /= 8;
4513
4514 shift = (sizeof(unsigned long) - 1) * 8;
4515
4516 for(y = 0; y < im->height; ++y){
4517 for(x = 0; x < im->width; ++x){
4518 a = gl2psGetRGB(im, x, y, &r, &g, &b);
4519 if(im->format == GL_RGBA && gray){
4520 (*action)((unsigned long)(a * 255) << shift, gray);
4521 }
4522 else{
4523 (*action)((unsigned long)(r * 255) << shift, 1);
4524 (*action)((unsigned long)(g * 255) << shift, 1);
4525 (*action)((unsigned long)(b * 255) << shift, 1);
4526 }
4527 }
4528 }
4529
4530 switch(gray){
4531 case 0: return 3 * im->width * im->height;
4532 case 1: return im->width * im->height;
4533 case 2: return 2 * im->width * im->height;
4534 default: return 3 * im->width * im->height;
4535 }
4536}
4537
4538static int gl2psPrintPDFPixmap(int obj, int childobj, GL2PSimage *im, int gray)
4539{
4540 int offs = 0, done = 0, sigbytes = 3;
4541
4542 if(gray && gray !=8 && gray != 16)
4543 gray = 8;
4544
4545 if(gray)
4546 sigbytes = gray / 8;
4547
4548 offs += fprintf(gl2ps->stream,
4549 "%d 0 obj\n"
4550 "<<\n"
4551 "/Type /XObject\n"
4552 "/Subtype /Image\n"
4553 "/Width %d\n"
4554 "/Height %d\n"
4555 "/ColorSpace %s \n"
4556 "/BitsPerComponent 8\n",
4557 obj,
4558 (int)im->width, (int)im->height,
4559 (gray) ? "/DeviceGray" : "/DeviceRGB" );
4560 if(GL_RGBA == im->format && gray == 0){
4561 offs += fprintf(gl2ps->stream,
4562 "/SMask %d 0 R\n",
4563 childobj);
4564 }
4565
4566#if defined(GL2PS_HAVE_ZLIB)
4567 if(gl2ps->options & GL2PS_COMPRESS){
4568 gl2psAllocCompress((int)(im->width * im->height * sigbytes));
4569
4570 gl2psPrintPDFPixmapStreamData(im, gl2psWriteBigEndianCompress, gray);
4571
4572 if(Z_OK == gl2psDeflate() && 23 + gl2ps->compress->destLen < gl2ps->compress->srcLen){
4574 offs += fprintf(gl2ps->stream,
4575 "/Length %d "
4576 ">>\n"
4577 "stream\n",
4578 (int)gl2ps->compress->destLen);
4579 offs += gl2ps->compress->destLen * fwrite(gl2ps->compress->dest, gl2ps->compress->destLen,
4580 1, gl2ps->stream);
4581 done = 1;
4582 }
4583 gl2psFreeCompress();
4584 }
4585#endif
4586
4587 if(!done){
4588 /* no compression, or too long after compression, or compress error
4589 -> write non-compressed entry */
4590 offs += fprintf(gl2ps->stream,
4591 "/Length %d "
4592 ">>\n"
4593 "stream\n",
4594 (int)(im->width * im->height * sigbytes));
4596 }
4597
4598 offs += fprintf(gl2ps->stream,
4599 "\nendstream\n"
4600 "endobj\n");
4601
4602 return offs;
4603}
4604
4605static int gl2psPrintPDFText(int obj, GL2PSstring *s, int fontnumber)
4606{
4607 int offs = 0;
4608
4609 offs += fprintf(gl2ps->stream,
4610 "%d 0 obj\n"
4611 "<<\n"
4612 "/Type /Font\n"
4613 "/Subtype /Type1\n"
4614 "/Name /F%d\n"
4615 "/BaseFont /%s\n"
4616 "/Encoding /MacRomanEncoding\n"
4617 ">>\n"
4618 "endobj\n",
4619 obj, fontnumber, s->fontname);
4620 return offs;
4621}
4622
4623/* Write the physical objects */
4624
4625static int gl2psPDFgroupListWriteObjects(int entryoffs)
4626{
4627 int i,j;
4628 GL2PSprimitive *p = NULL;
4629 GL2PSpdfgroup *gro;
4630 int offs = entryoffs;
4631 GL2PStriangle *triangles;
4632 int size = 0;
4633
4634 if(!gl2ps->pdfgrouplist)
4635 return offs;
4636
4637 for(i = 0; i < gl2psListNbr(gl2ps->pdfgrouplist); ++i){
4638 gro = (GL2PSpdfgroup*)gl2psListPointer(gl2ps->pdfgrouplist, i);
4639 if(!gl2psListNbr(gro->ptrlist))
4640 continue;
4641 p = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, 0);
4642 switch(p->type){
4643 case GL2PS_POINT:
4644 break;
4645 case GL2PS_LINE:
4646 break;
4647 case GL2PS_TRIANGLE:
4648 size = gl2psListNbr(gro->ptrlist);
4649 triangles = (GL2PStriangle*)gl2psMalloc(sizeof(GL2PStriangle) * size);
4650 for(j = 0; j < size; ++j){
4651 p = *(GL2PSprimitive**)gl2psListPointer(gro->ptrlist, j);
4652 gl2psFillTriangleFromPrimitive(&triangles[j], p, GL_TRUE);
4653 }
4654 if(triangles[0].prop & T_VAR_COLOR){
4655 gl2ps->xreflist[gro->shobjno] = offs;
4656 offs += gl2psPrintPDFShader(gro->shobjno, triangles, size, 0);
4657 }
4658 if(triangles[0].prop & T_ALPHA_LESS_1){
4659 gl2ps->xreflist[gro->gsobjno] = offs;
4660 offs += gl2psPrintPDFShaderSimpleExtGS(gro->gsobjno, triangles[0].vertex[0].rgba[3]);
4661 }
4662 if(triangles[0].prop & T_VAR_ALPHA){
4663 gl2ps->xreflist[gro->gsobjno] = offs;
4664 offs += gl2psPrintPDFShaderExtGS(gro->gsobjno, gro->trgroupobjno);
4665 gl2ps->xreflist[gro->trgroupobjno] = offs;
4666 offs += gl2psPrintPDFShaderMask(gro->trgroupobjno, gro->maskshno);
4667 gl2ps->xreflist[gro->maskshobjno] = offs;
4668 offs += gl2psPrintPDFShader(gro->maskshobjno, triangles, size, 8);
4669 }
4670 gl2psFree(triangles);
4671 break;
4672 case GL2PS_PIXMAP:
4673 gl2ps->xreflist[gro->imobjno] = offs;
4674 offs += gl2psPrintPDFPixmap(gro->imobjno, gro->imobjno+1, p->data.image, 0);
4675 if(p->data.image->format == GL_RGBA){
4676 gl2ps->xreflist[gro->imobjno+1] = offs;
4677 offs += gl2psPrintPDFPixmap(gro->imobjno+1, -1, p->data.image, 8);
4678 }
4679 break;
4680 case GL2PS_TEXT:
4681 gl2ps->xreflist[gro->fontobjno] = offs;
4682 offs += gl2psPrintPDFText(gro->fontobjno,p->data.text,gro->fontno);
4683 break;
4684 case GL2PS_SPECIAL :
4685 /* alignment contains the format for which the special output text
4686 is intended */
4687 if(p->data.text->alignment == GL2PS_PDF)
4688 offs += fprintf(gl2ps->stream, "%s\n", p->data.text->str);
4689 break;
4690 default:
4691 break;
4692 }
4693 }
4694 return offs;
4695}
4696
4697/* All variable data has been written at this point and all required
4698 functioninality has been gathered, so we can write now file footer
4699 with cross reference table and trailer */
4700
4701static void gl2psPrintPDFFooter(void)
4702{
4703 int i, offs;
4704
4707
4708 offs = gl2ps->xreflist[5] + gl2ps->streamlength;
4709 offs += gl2psClosePDFDataStream();
4710 gl2ps->xreflist[5] = offs;
4711
4712 offs += gl2psPrintPDFDataStreamLength(gl2ps->streamlength);
4713 gl2ps->xreflist[6] = offs;
4714 gl2ps->streamlength = 0;
4715
4716 offs += gl2psPrintPDFOpenPage();
4718 gl2ps->xreflist = (int*)gl2psRealloc(gl2ps->xreflist,
4719 sizeof(int) * (gl2ps->objects_stack + 1));
4720 gl2ps->xreflist[7] = offs;
4721
4722 offs += gl2psPrintPDFGSObject();
4723 gl2ps->xreflist[8] = offs;
4724
4725 gl2ps->xreflist[gl2ps->objects_stack] =
4727
4728 /* Start cross reference table. The file has to been opened in
4729 binary mode to preserve the 20 digit string length! */
4730 fprintf(gl2ps->stream,
4731 "xref\n"
4732 "0 %d\n"
4733 "%010d 65535 f \n", gl2ps->objects_stack, 0);
4734
4735 for(i = 1; i < gl2ps->objects_stack; ++i)
4736 fprintf(gl2ps->stream, "%010d 00000 n \n", gl2ps->xreflist[i]);
4737
4738 fprintf(gl2ps->stream,
4739 "trailer\n"
4740 "<<\n"
4741 "/Size %d\n"
4742 "/Info 1 0 R\n"
4743 "/Root 2 0 R\n"
4744 ">>\n"
4745 "startxref\n%d\n"
4746 "%%%%EOF\n",
4747 gl2ps->objects_stack, gl2ps->xreflist[gl2ps->objects_stack]);
4748
4749 /* Free auxiliary lists and arrays */
4750 gl2psFree(gl2ps->xreflist);
4752 gl2psListDelete(gl2ps->pdfprimlist);
4754
4755#if defined(GL2PS_HAVE_ZLIB)
4756 if(gl2ps->options & GL2PS_COMPRESS){
4757 gl2psFreeCompress();
4758 gl2psFree(gl2ps->compress);
4759 gl2ps->compress = NULL;
4760 }
4761#endif
4762}
4763
4764/* PDF begin viewport */
4765
4766static void gl2psPrintPDFBeginViewport(GLint viewport[4])
4767{
4768 int offs = 0;
4769 GLint index;
4770 GLfloat rgba[4];
4771 int x = viewport[0], y = viewport[1], w = viewport[2], h = viewport[3];
4772
4773 glRenderMode(GL_FEEDBACK);
4774
4775 if(gl2ps->header){
4777 gl2ps->header = GL_FALSE;
4778 }
4779
4780 offs += gl2psPrintf("q\n");
4781
4782 if(gl2ps->options & GL2PS_DRAW_BACKGROUND){
4783 if(gl2ps->colormode == GL_RGBA || gl2ps->colorsize == 0){
4784 glGetFloatv(GL_COLOR_CLEAR_VALUE, rgba);
4785 }
4786 else{
4787 glGetIntegerv(GL_INDEX_CLEAR_VALUE, &index);
4788 rgba[0] = gl2ps->colormap[index][0];
4789 rgba[1] = gl2ps->colormap[index][1];
4790 rgba[2] = gl2ps->colormap[index][2];
4791 rgba[3] = 1.0F;
4792 }
4793 offs += gl2psPrintPDFFillColor(rgba);
4794 offs += gl2psPrintf("%d %d %d %d re\n"
4795 "W\n"
4796 "f\n",
4797 x, y, w, h);
4798 }
4799 else{
4800 offs += gl2psPrintf("%d %d %d %d re\n"
4801 "W\n"
4802 "n\n",
4803 x, y, w, h);
4804 }
4805
4806 gl2ps->streamlength += offs;
4807}
4808
4810{
4811 GLint res;
4812
4814 gl2ps->streamlength += gl2psPrintf("Q\n");
4815 return res;
4816}
4817
4819{
4820}
4821
4822/* definition of the PDF backend */
4823
4834
4835/*********************************************************************
4836 *
4837 * SVG routines
4838 *
4839 *********************************************************************/
4840
4841static void gl2psSVGGetCoordsAndColors(int n, GL2PSvertex *verts,
4842 GL2PSxyz *xyz, GL2PSrgba *rgba)
4843{
4844 int i, j;
4845
4846 for(i = 0; i < n; i++){
4847 xyz[i][0] = verts[i].xyz[0];
4848 xyz[i][1] = gl2ps->viewport[3] - verts[i].xyz[1];
4849 xyz[i][2] = 0.0F;
4850 for(j = 0; j < 4; j++)
4851 rgba[i][j] = verts[i].rgba[j];
4852 }
4853}
4854
4855static void gl2psSVGGetColorString(GL2PSrgba rgba, char str[32])
4856{
4857 int r = (int)(255. * rgba[0]);
4858 int g = (int)(255. * rgba[1]);
4859 int b = (int)(255. * rgba[2]);
4860 int rc = (r < 0) ? 0 : (r > 255) ? 255 : r;
4861 int gc = (g < 0) ? 0 : (g > 255) ? 255 : g;
4862 int bc = (b < 0) ? 0 : (b > 255) ? 255 : b;
4863 sprintf(str, "#%2.2x%2.2x%2.2x", rc, gc, bc);
4864}
4865
4866static void gl2psPrintSVGHeader(void)
4867{
4868 int x, y, width, height;
4869 char col[32];
4870 time_t now;
4871
4872 time(&now);
4873
4874 if (gl2ps->options & GL2PS_LANDSCAPE){
4875 x = (int)gl2ps->viewport[1];
4876 y = (int)gl2ps->viewport[0];
4877 width = (int)gl2ps->viewport[3];
4878 height = (int)gl2ps->viewport[2];
4879 }
4880 else{
4881 x = (int)gl2ps->viewport[0];
4882 y = (int)gl2ps->viewport[1];
4883 width = (int)gl2ps->viewport[2];
4884 height = (int)gl2ps->viewport[3];
4885 }
4886
4887 /* Compressed SVG files (.svgz) are simply gzipped SVG files */
4889
4890 gl2psPrintf("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n");
4891 gl2psPrintf("<svg xmlns=\"http://www.w3.org/2000/svg\"\n");
4892 gl2psPrintf(" xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n"
4893 " width=\"%dpx\" height=\"%dpx\" viewBox=\"%d %d %d %d\">\n",
4894 width, height, x, y, width, height);
4895 gl2psPrintf("<title>%s</title>\n", gl2ps->title);
4896 gl2psPrintf("<desc>\n");
4897 gl2psPrintf("Creator: GL2PS %d.%d.%d%s, %s\n"
4898 "For: %s\n"
4899 "CreationDate: %s",
4901 GL2PS_EXTRA_VERSION, GL2PS_COPYRIGHT, gl2ps->producer, ctime(&now));
4902 gl2psPrintf("</desc>\n");
4903 gl2psPrintf("<defs>\n");
4904 gl2psPrintf("</defs>\n");
4905
4906 if(gl2ps->options & GL2PS_DRAW_BACKGROUND){
4907 gl2psSVGGetColorString(gl2ps->bgcolor, col);
4908 gl2psPrintf("<polygon fill=\"%s\" points=\"%d,%d %d,%d %d,%d %d,%d\"/>\n", col,
4909 (int)gl2ps->viewport[0], (int)gl2ps->viewport[1],
4910 (int)gl2ps->viewport[2], (int)gl2ps->viewport[1],
4911 (int)gl2ps->viewport[2], (int)gl2ps->viewport[3],
4912 (int)gl2ps->viewport[0], (int)gl2ps->viewport[3]);
4913 }
4914
4915 /* group all the primitives and disable antialiasing */
4916 gl2psPrintf("<g shape-rendering=\"crispEdges\">\n");
4917}
4918
4920{
4921 int i;
4922 GL2PSxyz xyz2[3];
4923 GL2PSrgba rgba2[3];
4924 char col[32];
4925
4926 /* Apparently there is no easy way to do Gouraud shading in SVG
4927 without explicitly pre-defining gradients, so for now we just do
4928 recursive subdivision */
4929
4930 if(gl2psSameColorThreshold(3, rgba, gl2ps->threshold)){
4931 gl2psSVGGetColorString(rgba[0], col);
4932 gl2psPrintf("<polygon fill=\"%s\" ", col);
4933 if(rgba[0][3] < 1.0F) gl2psPrintf("fill-opacity=\"%g\" ", rgba[0][3]);
4934 gl2psPrintf("points=\"%g,%g %g,%g %g,%g\"/>\n", xyz[0][0], xyz[0][1],
4935 xyz[1][0], xyz[1][1], xyz[2][0], xyz[2][1]);
4936 }
4937 else{
4938 /* subdivide into 4 subtriangles */
4939 for(i = 0; i < 3; i++){
4940 xyz2[0][i] = xyz[0][i];
4941 xyz2[1][i] = 0.5F * (xyz[0][i] + xyz[1][i]);
4942 xyz2[2][i] = 0.5F * (xyz[0][i] + xyz[2][i]);
4943 }
4944 for(i = 0; i < 4; i++){
4945 rgba2[0][i] = rgba[0][i];
4946 rgba2[1][i] = 0.5F * (rgba[0][i] + rgba[1][i]);
4947 rgba2[2][i] = 0.5F * (rgba[0][i] + rgba[2][i]);
4948 }
4949 gl2psPrintSVGSmoothTriangle(xyz2, rgba2);
4950 for(i = 0; i < 3; i++){
4951 xyz2[0][i] = 0.5F * (xyz[0][i] + xyz[1][i]);
4952 xyz2[1][i] = xyz[1][i];
4953 xyz2[2][i] = 0.5F * (xyz[1][i] + xyz[2][i]);
4954 }
4955 for(i = 0; i < 4; i++){
4956 rgba2[0][i] = 0.5F * (rgba[0][i] + rgba[1][i]);
4957 rgba2[1][i] = rgba[1][i];
4958 rgba2[2][i] = 0.5F * (rgba[1][i] + rgba[2][i]);
4959 }
4960 gl2psPrintSVGSmoothTriangle(xyz2, rgba2);
4961 for(i = 0; i < 3; i++){
4962 xyz2[0][i] = 0.5F * (xyz[0][i] + xyz[2][i]);
4963 xyz2[1][i] = xyz[2][i];
4964 xyz2[2][i] = 0.5F * (xyz[1][i] + xyz[2][i]);
4965 }
4966 for(i = 0; i < 4; i++){
4967 rgba2[0][i] = 0.5F * (rgba[0][i] + rgba[2][i]);
4968 rgba2[1][i] = rgba[2][i];
4969 rgba2[2][i] = 0.5F * (rgba[1][i] + rgba[2][i]);
4970 }
4971 gl2psPrintSVGSmoothTriangle(xyz2, rgba2);
4972 for(i = 0; i < 3; i++){
4973 xyz2[0][i] = 0.5F * (xyz[0][i] + xyz[1][i]);
4974 xyz2[1][i] = 0.5F * (xyz[1][i] + xyz[2][i]);
4975 xyz2[2][i] = 0.5F * (xyz[0][i] + xyz[2][i]);
4976 }
4977 for(i = 0; i < 4; i++){
4978 rgba2[0][i] = 0.5F * (rgba[0][i] + rgba[1][i]);
4979 rgba2[1][i] = 0.5F * (rgba[1][i] + rgba[2][i]);
4980 rgba2[2][i] = 0.5F * (rgba[0][i] + rgba[2][i]);
4981 }
4982 gl2psPrintSVGSmoothTriangle(xyz2, rgba2);
4983 }
4984}
4985
4986static void gl2psPrintSVGDash(GLushort pattern, GLint factor)
4987{
4988 int i, n, array[10];
4989
4990 if(!pattern || !factor) return; /* solid line */
4991
4992 gl2psParseStipplePattern(pattern, factor, &n, array);
4993 gl2psPrintf("stroke-dasharray=\"");
4994 for(i = 0; i < n; i++){
4995 if(i) gl2psPrintf(",");
4996 gl2psPrintf("%d", array[i]);
4997 }
4998 gl2psPrintf("\" ");
4999}
5000
5001static void gl2psEndSVGLine(void)
5002{
5003 int i;
5004 if(gl2ps->lastvertex.rgba[0] >= 0.){
5005 gl2psPrintf("%g,%g\"/>\n", gl2ps->lastvertex.xyz[0],
5006 gl2ps->viewport[3] - gl2ps->lastvertex.xyz[1]);
5007 for(i = 0; i < 3; i++)
5008 gl2ps->lastvertex.xyz[i] = -1.;
5009 for(i = 0; i < 4; i++)
5010 gl2ps->lastvertex.rgba[i] = -1.;
5011 }
5012}
5013
5015#if defined(GL2PS_HAVE_LIBPNG)
5016GLfloat x, GLfloat y, GL2PSimage *pixmap
5017#else
5018GLfloat, GLfloat, GL2PSimage *
5019#endif
5020)
5021
5022{
5023#if defined(GL2PS_HAVE_LIBPNG)
5024 GL2PSlist *png;
5025 unsigned char c;
5026 int i;
5027
5028 /* The only image types supported by the SVG standard are JPEG, PNG
5029 and SVG. Here we choose PNG, and since we want to embed the image
5030 directly in the SVG stream (and not link to an external image
5031 file), we need to encode the pixmap into PNG in memory, then
5032 encode it into base64. */
5033
5034 png = gl2psListCreate(pixmap->width * pixmap->height * 3, 1000,
5035 sizeof(unsigned char));
5036 gl2psConvertPixmapToPNG(pixmap, png);
5037 gl2psListEncodeBase64(png);
5038 gl2psPrintf("<image x=\"%g\" y=\"%g\" width=\"%d\" height=\"%d\"\n",
5039 x, y - pixmap->height, pixmap->width, pixmap->height);
5040 gl2psPrintf("xlink:href=\"data:image/png;base64,");
5041 for(i = 0; i < gl2psListNbr(png); i++){
5042 gl2psListRead(png, i, &c);
5043 gl2psPrintf("%c", c);
5044 }
5045 gl2psPrintf("\"/>\n");
5046 gl2psListDelete(png);
5047#else
5048 gl2psMsg(GL2PS_WARNING, "GL2PS must be compiled with PNG support in "
5049 "order to embed images in SVG streams");
5050#endif
5051}
5052
5054{
5055 GL2PSprimitive *prim;
5056 GL2PSxyz xyz[4];
5057 GL2PSrgba rgba[4];
5058 char col[32];
5059 int newline;
5060
5061 prim = *(GL2PSprimitive**)data;
5062
5063 if((gl2ps->options & GL2PS_OCCLUSION_CULL) && prim->culled) return;
5064
5065 /* We try to draw connected lines as a single path to get nice line
5066 joins and correct stippling. So if the primitive to print is not
5067 a line we must first finish the current line (if any): */
5068 if(prim->type != GL2PS_LINE) gl2psEndSVGLine();
5069
5070 gl2psSVGGetCoordsAndColors(prim->numverts, prim->verts, xyz, rgba);
5071
5072 switch(prim->type){
5073 case GL2PS_POINT :
5074 gl2psSVGGetColorString(rgba[0], col);
5075 gl2psPrintf("<circle fill=\"%s\" ", col);
5076 if(rgba[0][3] < 1.0F) gl2psPrintf("fill-opacity=\"%g\" ", rgba[0][3]);
5077 gl2psPrintf("cx=\"%g\" cy=\"%g\" r=\"%g\"/>\n",
5078 xyz[0][0], xyz[0][1], 0.5 * prim->width);
5079 break;
5080 case GL2PS_LINE :
5081 if(!gl2psSamePosition(gl2ps->lastvertex.xyz, prim->verts[0].xyz) ||
5082 !gl2psSameColor(gl2ps->lastrgba, prim->verts[0].rgba) ||
5083 gl2ps->lastlinewidth != prim->width ||
5084 gl2ps->lastpattern != prim->pattern ||
5085 gl2ps->lastfactor != prim->factor){
5086 /* End the current line if the new segment does not start where
5087 the last one ended, or if the color, the width or the
5088 stippling have changed (we will need to use multi-point
5089 gradients for smooth-shaded lines) */
5091 newline = 1;
5092 }
5093 else{
5094 newline = 0;
5095 }
5096 gl2ps->lastvertex = prim->verts[1];
5097 gl2psSetLastColor(prim->verts[0].rgba);
5098 gl2ps->lastlinewidth = prim->width;
5099 gl2ps->lastpattern = prim->pattern;
5100 gl2ps->lastfactor = prim->factor;
5101 if(newline){
5102 gl2psSVGGetColorString(rgba[0], col);
5103 gl2psPrintf("<polyline fill=\"none\" stroke=\"%s\" stroke-width=\"%g\" ",
5104 col, prim->width);
5105 if(rgba[0][3] < 1.0F) gl2psPrintf("stroke-opacity=\"%g\" ", rgba[0][3]);
5106 gl2psPrintSVGDash(prim->pattern, prim->factor);
5107 gl2psPrintf("points=\"%g,%g ", xyz[0][0], xyz[0][1]);
5108 }
5109 else{
5110 gl2psPrintf("%g,%g ", xyz[0][0], xyz[0][1]);
5111 }
5112 break;
5113 case GL2PS_TRIANGLE :
5115 break;
5116 case GL2PS_QUADRANGLE :
5117 gl2psMsg(GL2PS_WARNING, "There should not be any quad left to print");
5118 break;
5119 case GL2PS_PIXMAP :
5120 gl2psPrintSVGPixmap(xyz[0][0], xyz[0][1], prim->data.image);
5121 break;
5122 case GL2PS_TEXT :
5123 gl2psSVGGetColorString(prim->verts[0].rgba, col);
5124 gl2psPrintf("<text fill=\"%s\" x=\"%g\" y=\"%g\" font-size=\"%d\" ",
5125 col, xyz[0][0], xyz[0][1], prim->data.text->fontsize);
5126 if(prim->data.text->angle)
5127 gl2psPrintf("transform=\"rotate(%g, %g, %g)\" ",
5128 -prim->data.text->angle, xyz[0][0], xyz[0][1]);
5129 if(!strcmp(prim->data.text->fontname, "Times-Roman"))
5130 gl2psPrintf("font-family=\"Times\">");
5131 else if(!strcmp(prim->data.text->fontname, "Times-Bold"))
5132 gl2psPrintf("font-family=\"Times\" font-weight=\"bold\">");
5133 else if(!strcmp(prim->data.text->fontname, "Times-Italic"))
5134 gl2psPrintf("font-family=\"Times\" font-style=\"italic\">");
5135 else if(!strcmp(prim->data.text->fontname, "Times-BoldItalic"))
5136 gl2psPrintf("font-family=\"Times\" font-style=\"italic\" font-weight=\"bold\">");
5137 else if(!strcmp(prim->data.text->fontname, "Helvetica-Bold"))
5138 gl2psPrintf("font-family=\"Helvetica\" font-weight=\"bold\">");
5139 else if(!strcmp(prim->data.text->fontname, "Helvetica-Oblique"))
5140 gl2psPrintf("font-family=\"Helvetica\" font-style=\"oblique\">");
5141 else if(!strcmp(prim->data.text->fontname, "Helvetica-BoldOblique"))
5142 gl2psPrintf("font-family=\"Helvetica\" font-style=\"oblique\" font-weight=\"bold\">");
5143 else if(!strcmp(prim->data.text->fontname, "Courier-Bold"))
5144 gl2psPrintf("font-family=\"Courier\" font-weight=\"bold\">");
5145 else if(!strcmp(prim->data.text->fontname, "Courier-Oblique"))
5146 gl2psPrintf("font-family=\"Courier\" font-style=\"oblique\">");
5147 else if(!strcmp(prim->data.text->fontname, "Courier-BoldOblique"))
5148 gl2psPrintf("font-family=\"Courier\" font-style=\"oblique\" font-weight=\"bold\">");
5149 else
5150 gl2psPrintf("font-family=\"%s\">", prim->data.text->fontname);
5151 gl2psPrintf("%s</text>\n", prim->data.text->str);
5152 break;
5153 case GL2PS_SPECIAL :
5154 /* alignment contains the format for which the special output text
5155 is intended */
5156 if(prim->data.text->alignment == GL2PS_SVG)
5157 gl2psPrintf("%s\n", prim->data.text->str);
5158 break;
5159 default :
5160 break;
5161 }
5162}
5163
5164static void gl2psPrintSVGFooter(void)
5165{
5166 gl2psPrintf("</g>\n");
5167 gl2psPrintf("</svg>\n");
5168
5170}
5171
5172static void gl2psPrintSVGBeginViewport(GLint viewport[4])
5173{
5174 GLint index;
5175 char col[32];
5176 GLfloat rgba[4];
5177 int x = viewport[0], y = viewport[1], w = viewport[2], h = viewport[3];
5178
5179 glRenderMode(GL_FEEDBACK);
5180
5181 if(gl2ps->header){
5183 gl2ps->header = GL_FALSE;
5184 }
5185
5186 if(gl2ps->options & GL2PS_DRAW_BACKGROUND){
5187 if(gl2ps->colormode == GL_RGBA || gl2ps->colorsize == 0){
5188 glGetFloatv(GL_COLOR_CLEAR_VALUE, rgba);
5189 }
5190 else{
5191 glGetIntegerv(GL_INDEX_CLEAR_VALUE, &index);
5192 rgba[0] = gl2ps->colormap[index][0];
5193 rgba[1] = gl2ps->colormap[index][1];
5194 rgba[2] = gl2ps->colormap[index][2];
5195 rgba[3] = 1.0F;
5196 }
5197 gl2psSVGGetColorString(rgba, col);
5198 gl2psPrintf("<polygon fill=\"%s\" points=\"%d,%d %d,%d %d,%d %d,%d\"/>\n", col,
5199 x, gl2ps->viewport[3] - y,
5200 x + w, gl2ps->viewport[3] - y,
5201 x + w, gl2ps->viewport[3] - (y + h),
5202 x, gl2ps->viewport[3] - (y + h));
5203 }
5204
5205 gl2psPrintf("<clipPath id=\"cp%d%d%d%d\">\n", x, y, w, h);
5206 gl2psPrintf(" <polygon points=\"%d,%d %d,%d %d,%d %d,%d\"/>\n",
5207 x, gl2ps->viewport[3] - y,
5208 x + w, gl2ps->viewport[3] - y,
5209 x + w, gl2ps->viewport[3] - (y + h),
5210 x, gl2ps->viewport[3] - (y + h));
5211 gl2psPrintf("</clipPath>\n");
5212 gl2psPrintf("<g clip-path=\"url(#cp%d%d%d%d)\">\n", x, y, w, h);
5213}
5214
5216{
5217 GLint res;
5218
5220 gl2psPrintf("</g>\n");
5221 return res;
5222}
5223
5225{
5226 /* End any remaining line, if any */
5228}
5229
5230/* definition of the SVG backend */
5231
5242
5243/*********************************************************************
5244 *
5245 * PGF routines
5246 *
5247 *********************************************************************/
5248
5250{
5251 if(!gl2psSameColor(gl2ps->lastrgba, rgba)){
5252 gl2psSetLastColor(rgba);
5253 fprintf(gl2ps->stream, "\\color[rgb]{%f,%f,%f}\n", rgba[0], rgba[1], rgba[2]);
5254 }
5255}
5256
5257static void gl2psPrintPGFHeader(void)
5258{
5259 time_t now;
5260
5261 time(&now);
5262
5263 fprintf(gl2ps->stream,
5264 "%% Title: %s\n"
5265 "%% Creator: GL2PS %d.%d.%d%s, %s\n"
5266 "%% For: %s\n"
5267 "%% CreationDate: %s",
5270 gl2ps->producer, ctime(&now));
5271
5272 fprintf(gl2ps->stream, "\\begin{pgfpicture}\n");
5273 if(gl2ps->options & GL2PS_DRAW_BACKGROUND){
5274 gl2psPrintPGFColor(gl2ps->bgcolor);
5275 fprintf(gl2ps->stream,
5276 "\\pgfpathrectanglecorners{"
5277 "\\pgfpoint{%dpt}{%dpt}}{\\pgfpoint{%dpt}{%dpt}}\n"
5278 "\\pgfusepath{fill}\n",
5279 (int)gl2ps->viewport[0], (int)gl2ps->viewport[1],
5280 (int)gl2ps->viewport[2], (int)gl2ps->viewport[3]);
5281 }
5282}
5283
5284static void gl2psPrintPGFDash(GLushort pattern, GLint factor)
5285{
5286 int i, n, array[10];
5287
5288 if(pattern == gl2ps->lastpattern && factor == gl2ps->lastfactor)
5289 return;
5290
5291 gl2ps->lastpattern = pattern;
5292 gl2ps->lastfactor = factor;
5293
5294 if(!pattern || !factor){
5295 /* solid line */
5296 fprintf(gl2ps->stream, "\\pgfsetdash{}{0pt}\n");
5297 }
5298 else{
5299 gl2psParseStipplePattern(pattern, factor, &n, array);
5300 fprintf(gl2ps->stream, "\\pgfsetdash{");
5301 for(i = 0; i < n; i++) fprintf(gl2ps->stream, "{%dpt}", array[i]);
5302 fprintf(gl2ps->stream, "}{0pt}\n");
5303 }
5304}
5305
5306static const char *gl2psPGFTextAlignment(int align)
5307{
5308 switch(align){
5309 case GL2PS_TEXT_C : return "center";
5310 case GL2PS_TEXT_CL : return "west";
5311 case GL2PS_TEXT_CR : return "east";
5312 case GL2PS_TEXT_B : return "south";
5313 case GL2PS_TEXT_BR : return "south east";
5314 case GL2PS_TEXT_T : return "north";
5315 case GL2PS_TEXT_TL : return "north west";
5316 case GL2PS_TEXT_TR : return "north east";
5317 case GL2PS_TEXT_BL :
5318 default : return "south west";
5319 }
5320}
5321
5323{
5324 GL2PSprimitive *prim;
5325
5326 prim = *(GL2PSprimitive**)data;
5327
5328 switch(prim->type){
5329 case GL2PS_POINT :
5330 /* Points in openGL are rectangular */
5331 gl2psPrintPGFColor(prim->verts[0].rgba);
5332 fprintf(gl2ps->stream,
5333 "\\pgfpathrectangle{\\pgfpoint{%fpt}{%fpt}}"
5334 "{\\pgfpoint{%fpt}{%fpt}}\n\\pgfusepath{fill}\n",
5335 prim->verts[0].xyz[0]-0.5*prim->width,
5336 prim->verts[0].xyz[1]-0.5*prim->width,
5337 prim->width,prim->width);
5338 break;
5339 case GL2PS_LINE :
5340 gl2psPrintPGFColor(prim->verts[0].rgba);
5341 if(gl2ps->lastlinewidth != prim->width){
5342 gl2ps->lastlinewidth = prim->width;
5343 fprintf(gl2ps->stream, "\\pgfsetlinewidth{%fpt}\n", gl2ps->lastlinewidth);
5344 }
5345 gl2psPrintPGFDash(prim->pattern, prim->factor);
5346 fprintf(gl2ps->stream,
5347 "\\pgfpathmoveto{\\pgfpoint{%fpt}{%fpt}}\n"
5348 "\\pgflineto{\\pgfpoint{%fpt}{%fpt}}\n"
5349 "\\pgfusepath{stroke}\n",
5350 prim->verts[1].xyz[0], prim->verts[1].xyz[1],
5351 prim->verts[0].xyz[0], prim->verts[0].xyz[1]);
5352 break;
5353 case GL2PS_TRIANGLE :
5354 if(gl2ps->lastlinewidth != 0){
5355 gl2ps->lastlinewidth = 0;
5356 fprintf(gl2ps->stream, "\\pgfsetlinewidth{0.01pt}\n");
5357 }
5358 gl2psPrintPGFColor(prim->verts[0].rgba);
5359 fprintf(gl2ps->stream,
5360 "\\pgfpathmoveto{\\pgfpoint{%fpt}{%fpt}}\n"
5361 "\\pgflineto{\\pgfpoint{%fpt}{%fpt}}\n"
5362 "\\pgflineto{\\pgfpoint{%fpt}{%fpt}}\n"
5363 "\\pgfpathclose\n"
5364 "\\pgfusepath{fill,stroke}\n",
5365 prim->verts[2].xyz[0], prim->verts[2].xyz[1],
5366 prim->verts[1].xyz[0], prim->verts[1].xyz[1],
5367 prim->verts[0].xyz[0], prim->verts[0].xyz[1]);
5368 break;
5369 case GL2PS_TEXT :
5370 fprintf(gl2ps->stream, "{\n\\pgftransformshift{\\pgfpoint{%fpt}{%fpt}}\n",
5371 prim->verts[0].xyz[0], prim->verts[0].xyz[1]);
5372
5373 if(prim->data.text->angle)
5374 fprintf(gl2ps->stream, "\\pgftransformrotate{%f}{", prim->data.text->angle);
5375
5376 fprintf(gl2ps->stream, "\\pgfnode{rectangle}{%s}{\\fontsize{%d}{0}\\selectfont",
5378 prim->data.text->fontsize);
5379
5380 fprintf(gl2ps->stream, "\\textcolor[rgb]{%g,%g,%g}{{%s}}",
5381 prim->verts[0].rgba[0], prim->verts[0].rgba[1],
5382 prim->verts[0].rgba[2], prim->data.text->str);
5383
5384 fprintf(gl2ps->stream, "}{}{\\pgfusepath{discard}}}\n");
5385 break;
5386 case GL2PS_SPECIAL :
5387 /* alignment contains the format for which the special output text
5388 is intended */
5389 if (prim->data.text->alignment == GL2PS_PGF)
5390 fprintf(gl2ps->stream, "%s\n", prim->data.text->str);
5391 break;
5392 default :
5393 break;
5394 }
5395}
5396
5397static void gl2psPrintPGFFooter(void)
5398{
5399 fprintf(gl2ps->stream, "\\end{pgfpicture}\n");
5400}
5401
5402static void gl2psPrintPGFBeginViewport(GLint viewport[4])
5403{
5404 GLint index;
5405 GLfloat rgba[4];
5406 int x = viewport[0], y = viewport[1], w = viewport[2], h = viewport[3];
5407
5408 glRenderMode(GL_FEEDBACK);
5409
5410 if(gl2ps->header){
5412 gl2ps->header = GL_FALSE;
5413 }
5414
5415 fprintf(gl2ps->stream, "\\begin{pgfscope}\n");
5416 if(gl2ps->options & GL2PS_DRAW_BACKGROUND){
5417 if(gl2ps->colormode == GL_RGBA || gl2ps->colorsize == 0){
5418 glGetFloatv(GL_COLOR_CLEAR_VALUE, rgba);
5419 }
5420 else{
5421 glGetIntegerv(GL_INDEX_CLEAR_VALUE, &index);
5422 rgba[0] = gl2ps->colormap[index][0];
5423 rgba[1] = gl2ps->colormap[index][1];
5424 rgba[2] = gl2ps->colormap[index][2];
5425 rgba[3] = 1.0F;
5426 }
5427 gl2psPrintPGFColor(rgba);
5428 fprintf(gl2ps->stream,
5429 "\\pgfpathrectangle{\\pgfpoint{%dpt}{%dpt}}"
5430 "{\\pgfpoint{%dpt}{%dpt}}\n"
5431 "\\pgfusepath{fill}\n",
5432 x, y, w, h);
5433 }
5434
5435 fprintf(gl2ps->stream,
5436 "\\pgfpathrectangle{\\pgfpoint{%dpt}{%dpt}}"
5437 "{\\pgfpoint{%dpt}{%dpt}}\n"
5438 "\\pgfusepath{clip}\n",
5439 x, y, w, h);
5440}
5441
5443{
5444 GLint res;
5446 fprintf(gl2ps->stream, "\\end{pgfscope}\n");
5447 return res;
5448}
5449
5451{
5452}
5453
5454/* definition of the PGF backend */
5455
5466
5467/*********************************************************************
5468 *
5469 * General primitive printing routine
5470 *
5471 *********************************************************************/
5472
5473/* Warning: the ordering of the backends must match the format
5474 #defines in gl2ps.h */
5475
5477 &gl2psPS, /* 0 */
5478 &gl2psEPS, /* 1 */
5479 &gl2psTEX, /* 2 */
5480 &gl2psPDF, /* 3 */
5481 &gl2psSVG, /* 4 */
5482 &gl2psPGF /* 5 */
5483};
5484
5486{
5487 GL2PSprimitive *prim;
5488 int i;
5489
5490 prim = *(GL2PSprimitive**)data;
5491
5492 for(i = 0; i < prim->numverts; i++){
5493 if(prim->verts[i].xyz[0] < gl2ps->viewport[0])
5494 gl2ps->viewport[0] = (GLint)prim->verts[i].xyz[0];
5495 if(prim->verts[i].xyz[0] > gl2ps->viewport[2])
5496 gl2ps->viewport[2] = (GLint)(prim->verts[i].xyz[0] + 0.5F);
5497 if(prim->verts[i].xyz[1] < gl2ps->viewport[1])
5498 gl2ps->viewport[1] = (GLint)prim->verts[i].xyz[1];
5499 if(prim->verts[i].xyz[1] > gl2ps->viewport[3])
5500 gl2ps->viewport[3] = (GLint)(prim->verts[i].xyz[1] + 0.5F);
5501 }
5502}
5503
5504static GLint gl2psPrintPrimitives(void)
5505{
5506 GL2PSbsptree *root;
5507 GL2PSxyz eye = {0.0F, 0.0F, 100.0F * GL2PS_ZSCALE};
5508 GLint used;
5509
5510 used = glRenderMode(GL_RENDER);
5511
5512 if(used < 0){
5513 gl2psMsg(GL2PS_INFO, "OpenGL feedback buffer overflow");
5514 return GL2PS_OVERFLOW;
5515 }
5516
5517 if(used > 0)
5519
5521
5522 if(gl2ps->header){
5523 if(gl2psListNbr(gl2ps->primitives) &&
5524 (gl2ps->options & GL2PS_TIGHT_BOUNDING_BOX)){
5525 gl2ps->viewport[0] = gl2ps->viewport[1] = 100000;
5526 gl2ps->viewport[2] = gl2ps->viewport[3] = -100000;
5528 }
5529 (gl2psbackends[gl2ps->format]->printHeader)();
5530 gl2ps->header = GL_FALSE;
5531 }
5532
5533 if(!gl2psListNbr(gl2ps->primitives)){
5534 /* empty feedback buffer and/or nothing else to print */
5535 return GL2PS_NO_FEEDBACK;
5536 }
5537
5538 switch(gl2ps->sort){
5539 case GL2PS_NO_SORT :
5540 gl2psListAction(gl2ps->primitives, gl2psbackends[gl2ps->format]->printPrimitive);
5542 /* reset the primitive list, waiting for the next viewport */
5543 gl2psListReset(gl2ps->primitives);
5544 break;
5545 case GL2PS_SIMPLE_SORT :
5547 if(gl2ps->options & GL2PS_OCCLUSION_CULL){
5549 gl2psFreeBspImageTree(&gl2ps->imagetree);
5550 }
5551 gl2psListAction(gl2ps->primitives, gl2psbackends[gl2ps->format]->printPrimitive);
5553 /* reset the primitive list, waiting for the next viewport */
5554 gl2psListReset(gl2ps->primitives);
5555 break;
5556 case GL2PS_BSP_SORT :
5557 root = (GL2PSbsptree*)gl2psMalloc(sizeof(GL2PSbsptree));
5558 gl2psBuildBspTree(root, gl2ps->primitives);
5559 if(GL_TRUE == gl2ps->boundary) gl2psBuildPolygonBoundary(root);
5560 if(gl2ps->options & GL2PS_OCCLUSION_CULL){
5563 gl2psFreeBspImageTree(&gl2ps->imagetree);
5564 }
5566 gl2psbackends[gl2ps->format]->printPrimitive, 0);
5567 gl2psFreeBspTree(&root);
5568 /* reallocate the primitive list (it's been deleted by
5569 gl2psBuildBspTree) in case there is another viewport */
5570 gl2ps->primitives = gl2psListCreate(500, 500, sizeof(GL2PSprimitive*));
5571 break;
5572 }
5573 gl2psbackends[gl2ps->format]->printFinalPrimitive();
5574
5575 return GL2PS_SUCCESS;
5576}
5577
5578/*********************************************************************
5579 *
5580 * Public routines
5581 *
5582 *********************************************************************/
5583
5584GL2PSDLL_API GLint gl2psBeginPage(const char *title, const char *producer,
5585 GLint viewport[4], GLint format, GLint sort,
5586 GLint options, GLint colormode,
5587 GLint colorsize, GL2PSrgba *colormap,
5588 GLint nr, GLint ng, GLint nb, GLint buffersize,
5589 FILE *stream, const char *filename)
5590{
5591 GLint index;
5592 int i;
5593
5594 if(gl2ps){
5595 gl2psMsg(GL2PS_ERROR, "gl2psBeginPage called in wrong program state");
5596 return GL2PS_ERROR;
5597 }
5598
5600
5601 if(format >= 0 && format < (GLint)(sizeof(gl2psbackends) / sizeof(gl2psbackends[0]))){
5602 gl2ps->format = format;
5603 }
5604 else {
5605 gl2psMsg(GL2PS_ERROR, "Unknown output format: %d", format);
5607 gl2ps = NULL;
5608 return GL2PS_ERROR;
5609 }
5610
5611 switch(sort){
5612 case GL2PS_NO_SORT :
5613 case GL2PS_SIMPLE_SORT :
5614 case GL2PS_BSP_SORT :
5615 gl2ps->sort = sort;
5616 break;
5617 default :
5618 gl2psMsg(GL2PS_ERROR, "Unknown sorting algorithm: %d", sort);
5620 gl2ps = NULL;
5621 return GL2PS_ERROR;
5622 }
5623
5624 if(stream){
5625 gl2ps->stream = stream;
5626 }
5627 else{
5628 gl2psMsg(GL2PS_ERROR, "Bad file pointer");
5630 gl2ps = NULL;
5631 return GL2PS_ERROR;
5632 }
5633
5634 gl2ps->header = GL_TRUE;
5635 gl2ps->maxbestroot = 10;
5636 gl2ps->options = options;
5637 gl2ps->compress = NULL;
5638 gl2ps->imagemap_head = NULL;
5639 gl2ps->imagemap_tail = NULL;
5640
5641 if(gl2ps->options & GL2PS_USE_CURRENT_VIEWPORT){
5642 glGetIntegerv(GL_VIEWPORT, gl2ps->viewport);
5643 }
5644 else{
5645 for(i = 0; i < 4; i++){
5646 gl2ps->viewport[i] = viewport[i];
5647 }
5648 }
5649
5650 if(!gl2ps->viewport[2] || !gl2ps->viewport[3]){
5651 gl2psMsg(GL2PS_ERROR, "Incorrect viewport (x=%d, y=%d, width=%d, height=%d)",
5652 gl2ps->viewport[0], gl2ps->viewport[1],
5653 gl2ps->viewport[2], gl2ps->viewport[3]);
5655 gl2ps = NULL;
5656 return GL2PS_ERROR;
5657 }
5658
5659 gl2ps->threshold[0] = nr ? 1.0F / (GLfloat)nr : 0.064F;
5660 gl2ps->threshold[1] = ng ? 1.0F / (GLfloat)ng : 0.034F;
5661 gl2ps->threshold[2] = nb ? 1.0F / (GLfloat)nb : 0.100F;
5662 gl2ps->colormode = colormode;
5663 gl2ps->buffersize = buffersize > 0 ? buffersize : 2048 * 2048;
5664 for(i = 0; i < 3; i++){
5665 gl2ps->lastvertex.xyz[i] = -1.0F;
5666 }
5667 for(i = 0; i < 4; i++){
5668 gl2ps->lastvertex.rgba[i] = -1.0F;
5669 gl2ps->lastrgba[i] = -1.0F;
5670 }
5671 gl2ps->lastlinewidth = -1.0F;
5672 gl2ps->lastpattern = 0;
5673 gl2ps->lastfactor = 0;
5674 gl2ps->imagetree = NULL;
5675 gl2ps->primitivetoadd = NULL;
5676 gl2ps->zerosurfacearea = GL_FALSE;
5677 gl2ps->pdfprimlist = NULL;
5678 gl2ps->pdfgrouplist = NULL;
5679 gl2ps->xreflist = NULL;
5680
5681 /* get default blending mode from current OpenGL state (enabled by
5682 default for SVG) */
5683 gl2ps->blending = (gl2ps->format == GL2PS_SVG) ? GL_TRUE : glIsEnabled(GL_BLEND);
5684 glGetIntegerv(GL_BLEND_SRC, &gl2ps->blendfunc[0]);
5685 glGetIntegerv(GL_BLEND_DST, &gl2ps->blendfunc[1]);
5686
5687 if(gl2ps->colormode == GL_RGBA){
5688 gl2ps->colorsize = 0;
5689 gl2ps->colormap = NULL;
5690 glGetFloatv(GL_COLOR_CLEAR_VALUE, gl2ps->bgcolor);
5691 }
5692 else if(gl2ps->colormode == GL_COLOR_INDEX){
5693 if(!colorsize || !colormap){
5694 gl2psMsg(GL2PS_ERROR, "Missing colormap for GL_COLOR_INDEX rendering");
5696 gl2ps = NULL;
5697 return GL2PS_ERROR;
5698 }
5699 gl2ps->colorsize = colorsize;
5700 gl2ps->colormap = (GL2PSrgba*)gl2psMalloc(gl2ps->colorsize * sizeof(GL2PSrgba));
5701 memcpy(gl2ps->colormap, colormap, gl2ps->colorsize * sizeof(GL2PSrgba));
5702 glGetIntegerv(GL_INDEX_CLEAR_VALUE, &index);
5703 gl2ps->bgcolor[0] = gl2ps->colormap[index][0];
5704 gl2ps->bgcolor[1] = gl2ps->colormap[index][1];
5705 gl2ps->bgcolor[2] = gl2ps->colormap[index][2];
5706 gl2ps->bgcolor[3] = 1.0F;
5707 }
5708 else{
5709 gl2psMsg(GL2PS_ERROR, "Unknown color mode in gl2psBeginPage");
5711 gl2ps = NULL;
5712 return GL2PS_ERROR;
5713 }
5714
5715 if(!title){
5716 gl2ps->title = (char*)gl2psMalloc(sizeof(char));
5717 gl2ps->title[0] = '\0';
5718 }
5719 else{
5720 gl2ps->title = (char*)gl2psMalloc((strlen(title)+1)*sizeof(char));
5721 strcpy(gl2ps->title, title);
5722 }
5723
5724 if(!producer){
5725 gl2ps->producer = (char*)gl2psMalloc(sizeof(char));
5726 gl2ps->producer[0] = '\0';
5727 }
5728 else{
5729 gl2ps->producer = (char*)gl2psMalloc((strlen(producer)+1)*sizeof(char));
5730 strcpy(gl2ps->producer, producer);
5731 }
5732
5733 if(!filename){
5734 gl2ps->filename = (char*)gl2psMalloc(sizeof(char));
5735 gl2ps->filename[0] = '\0';
5736 }
5737 else{
5738 gl2ps->filename = (char*)gl2psMalloc((strlen(filename)+1)*sizeof(char));
5739 strcpy(gl2ps->filename, filename);
5740 }
5741
5742 gl2ps->primitives = gl2psListCreate(500, 500, sizeof(GL2PSprimitive*));
5743 gl2ps->auxprimitives = gl2psListCreate(100, 100, sizeof(GL2PSprimitive*));
5744 gl2ps->feedback = (GLfloat*)gl2psMalloc(gl2ps->buffersize * sizeof(GLfloat));
5745 glFeedbackBuffer(gl2ps->buffersize, GL_3D_COLOR, gl2ps->feedback);
5746 glRenderMode(GL_FEEDBACK);
5747
5748 return GL2PS_SUCCESS;
5749}
5750
5752{
5753 GLint res;
5754
5755 if(!gl2ps) return GL2PS_UNINITIALIZED;
5756
5758
5759 if(res != GL2PS_OVERFLOW)
5760 (gl2psbackends[gl2ps->format]->printFooter)();
5761
5762 fflush(gl2ps->stream);
5763
5764 gl2psListDelete(gl2ps->primitives);
5765 gl2psListDelete(gl2ps->auxprimitives);
5766 gl2psFreeImagemap(gl2ps->imagemap_head);
5767 gl2psFree(gl2ps->colormap);
5768 gl2psFree(gl2ps->title);
5769 gl2psFree(gl2ps->producer);
5770 gl2psFree(gl2ps->filename);
5771 gl2psFree(gl2ps->feedback);
5773 gl2ps = NULL;
5774
5775 return res;
5776}
5777
5778GL2PSDLL_API GLint gl2psBeginViewport(GLint viewport[4])
5779{
5780 if(!gl2ps) return GL2PS_UNINITIALIZED;
5781
5782 (gl2psbackends[gl2ps->format]->beginViewport)(viewport);
5783
5784 return GL2PS_SUCCESS;
5785}
5786
5788{
5789 GLint res;
5790
5791 if(!gl2ps) return GL2PS_UNINITIALIZED;
5792
5793 res = (gl2psbackends[gl2ps->format]->endViewport)();
5794
5795 /* reset last used colors, line widths */
5796 gl2ps->lastlinewidth = -1.0F;
5797
5798 return res;
5799}
5800
5801GL2PSDLL_API GLint gl2psTextOpt(const char *str, const char *fontname,
5802 GLshort fontsize, GLint alignment, GLfloat angle)
5803{
5804 return gl2psAddText(GL2PS_TEXT, str, fontname, fontsize, alignment, angle);
5805}
5806
5807GL2PSDLL_API GLint gl2psText(const char *str, const char *fontname, GLshort fontsize)
5808{
5809 return gl2psAddText(GL2PS_TEXT, str, fontname, fontsize, GL2PS_TEXT_BL, 0.0F);
5810}
5811
5812GL2PSDLL_API GLint gl2psSpecial(GLint format, const char *str)
5813{
5814 return gl2psAddText(GL2PS_SPECIAL, str, "", 0, format, 0.0F);
5815}
5816
5817GL2PSDLL_API GLint gl2psDrawPixels(GLsizei width, GLsizei height,
5818 GLint xorig, GLint yorig,
5819 GLenum format, GLenum type,
5820 const void *pixels)
5821{
5822 int size, i;
5823 GLfloat pos[4], *piv;
5824 GL2PSprimitive *prim;
5825 GLboolean valid;
5826
5827 if(!gl2ps || !pixels) return GL2PS_UNINITIALIZED;
5828
5829 if((width <= 0) || (height <= 0)) return GL2PS_ERROR;
5830
5831 if(gl2ps->options & GL2PS_NO_PIXMAP) return GL2PS_SUCCESS;
5832
5833 if((format != GL_RGB && format != GL_RGBA) || type != GL_FLOAT){
5834 gl2psMsg(GL2PS_ERROR, "gl2psDrawPixels only implemented for "
5835 "GL_RGB/GL_RGBA, GL_FLOAT pixels");
5836 return GL2PS_ERROR;
5837 }
5838
5839 glGetBooleanv(GL_CURRENT_RASTER_POSITION_VALID, &valid);
5840 if(GL_FALSE == valid) return GL2PS_SUCCESS; /* the primitive is culled */
5841
5842 glGetFloatv(GL_CURRENT_RASTER_POSITION, pos);
5843
5844 prim = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive));
5845 prim->type = GL2PS_PIXMAP;
5846 prim->boundary = 0;
5847 prim->numverts = 1;
5848 prim->verts = (GL2PSvertex*)gl2psMalloc(sizeof(GL2PSvertex));
5849 prim->verts[0].xyz[0] = pos[0] + xorig;
5850 prim->verts[0].xyz[1] = pos[1] + yorig;
5851 prim->verts[0].xyz[2] = pos[2];
5852 prim->culled = 0;
5853 prim->offset = 0;
5854 prim->pattern = 0;
5855 prim->factor = 0;
5856 prim->width = 1;
5857 glGetFloatv(GL_CURRENT_RASTER_COLOR, prim->verts[0].rgba);
5858 prim->data.image = (GL2PSimage*)gl2psMalloc(sizeof(GL2PSimage));
5859 prim->data.image->width = width;
5860 prim->data.image->height = height;
5861 prim->data.image->format = format;
5862 prim->data.image->type = type;
5863
5864 switch(format){
5865 case GL_RGBA:
5866 if(gl2ps->options & GL2PS_NO_BLENDING || !gl2ps->blending){
5867 /* special case: blending turned off */
5868 prim->data.image->format = GL_RGB;
5869 size = height * width * 3;
5870 prim->data.image->pixels = (GLfloat*)gl2psMalloc(size * sizeof(GLfloat));
5871 piv = (GLfloat*)pixels;
5872 for(i = 0; i < size; ++i, ++piv){
5873 prim->data.image->pixels[i] = *piv;
5874 if(!((i+1)%3))
5875 ++piv;
5876 }
5877 }
5878 else{
5879 size = height * width * 4;
5880 prim->data.image->pixels = (GLfloat*)gl2psMalloc(size * sizeof(GLfloat));
5881 memcpy(prim->data.image->pixels, pixels, size * sizeof(GLfloat));
5882 }
5883 break;
5884 case GL_RGB:
5885 default:
5886 size = height * width * 3;
5887 prim->data.image->pixels = (GLfloat*)gl2psMalloc(size * sizeof(GLfloat));
5888 memcpy(prim->data.image->pixels, pixels, size * sizeof(GLfloat));
5889 break;
5890 }
5891
5892 gl2psListAdd(gl2ps->auxprimitives, &prim);
5893 glPassThrough(GL2PS_DRAW_PIXELS_TOKEN);
5894
5895 return GL2PS_SUCCESS;
5896}
5897
5898GL2PSDLL_API GLint gl2psDrawImageMap(GLsizei width, GLsizei height,
5899 const GLfloat position[3],
5900 const unsigned char *imagemap){
5901 int size, i;
5902 int sizeoffloat = sizeof(GLfloat);
5903
5904 if(!gl2ps || !imagemap) return GL2PS_UNINITIALIZED;
5905
5906 if((width <= 0) || (height <= 0)) return GL2PS_ERROR;
5907
5908 size = height + height * ((width - 1) / 8);
5909 glPassThrough(GL2PS_IMAGEMAP_TOKEN);
5910 glBegin(GL_POINTS);
5911 glVertex3f(position[0], position[1],position[2]);
5912 glEnd();
5913 glPassThrough((GLfloat)width);
5914 glPassThrough((GLfloat)height);
5915 for(i = 0; i < size; i += sizeoffloat){
5916 // cppcheck-suppress invalidPointerCast
5917 const float *value = reinterpret_cast<const float*>(imagemap);
5918 glPassThrough(*value);
5919 imagemap += sizeoffloat;
5920 }
5921 return GL2PS_SUCCESS;
5922}
5923
5924GL2PSDLL_API GLint gl2psEnable(GLint mode)
5925{
5926 GLint tmp;
5927
5928 if(!gl2ps) return GL2PS_UNINITIALIZED;
5929
5930 switch(mode){
5932 glPassThrough(GL2PS_BEGIN_OFFSET_TOKEN);
5933 glGetFloatv(GL_POLYGON_OFFSET_FACTOR, &gl2ps->offset[0]);
5934 glGetFloatv(GL_POLYGON_OFFSET_UNITS, &gl2ps->offset[1]);
5935 break;
5937 glPassThrough(GL2PS_BEGIN_BOUNDARY_TOKEN);
5938 break;
5939 case GL2PS_LINE_STIPPLE :
5940 glPassThrough(GL2PS_BEGIN_STIPPLE_TOKEN);
5941 glGetIntegerv(GL_LINE_STIPPLE_PATTERN, &tmp);
5942 glPassThrough((GLfloat)tmp);
5943 glGetIntegerv(GL_LINE_STIPPLE_REPEAT, &tmp);
5944 glPassThrough((GLfloat)tmp);
5945 break;
5946 case GL2PS_BLEND :
5947 glPassThrough(GL2PS_BEGIN_BLEND_TOKEN);
5948 break;
5949 default :
5950 gl2psMsg(GL2PS_WARNING, "Unknown mode in gl2psEnable: %d", mode);
5951 return GL2PS_WARNING;
5952 }
5953
5954 return GL2PS_SUCCESS;
5955}
5956
5958{
5959 if(!gl2ps) return GL2PS_UNINITIALIZED;
5960
5961 switch(mode){
5963 glPassThrough(GL2PS_END_OFFSET_TOKEN);
5964 break;
5966 glPassThrough(GL2PS_END_BOUNDARY_TOKEN);
5967 break;
5968 case GL2PS_LINE_STIPPLE :
5969 glPassThrough(GL2PS_END_STIPPLE_TOKEN);
5970 break;
5971 case GL2PS_BLEND :
5972 glPassThrough(GL2PS_END_BLEND_TOKEN);
5973 break;
5974 default :
5975 gl2psMsg(GL2PS_WARNING, "Unknown mode in gl2psDisable: %d", mode);
5976 return GL2PS_WARNING;
5977 }
5978
5979 return GL2PS_SUCCESS;
5980}
5981
5982GL2PSDLL_API GLint gl2psPointSize(GLfloat value)
5983{
5984 if(!gl2ps) return GL2PS_UNINITIALIZED;
5985
5986 glPassThrough(GL2PS_POINT_SIZE_TOKEN);
5987 glPassThrough(value);
5988
5989 return GL2PS_SUCCESS;
5990}
5991
5992GL2PSDLL_API GLint gl2psLineWidth(GLfloat value)
5993{
5994 if(!gl2ps) return GL2PS_UNINITIALIZED;
5995
5996 glPassThrough(GL2PS_LINE_WIDTH_TOKEN);
5997 glPassThrough(value);
5998
5999 return GL2PS_SUCCESS;
6000}
6001
6002GL2PSDLL_API GLint gl2psBlendFunc(GLenum sfactor, GLenum dfactor)
6003{
6004 if(!gl2ps) return GL2PS_UNINITIALIZED;
6005
6006 if(GL_FALSE == gl2psSupportedBlendMode(sfactor, dfactor))
6007 return GL2PS_WARNING;
6008
6009 glPassThrough(GL2PS_SRC_BLEND_TOKEN);
6010 glPassThrough((GLfloat)sfactor);
6011 glPassThrough(GL2PS_DST_BLEND_TOKEN);
6012 glPassThrough((GLfloat)dfactor);
6013
6014 return GL2PS_SUCCESS;
6015}
6016
6017GL2PSDLL_API GLint gl2psSetOptions(GLint options)
6018{
6019 if(!gl2ps) return GL2PS_UNINITIALIZED;
6020
6021 gl2ps->options = options;
6022
6023 return GL2PS_SUCCESS;
6024}
6025
6026GL2PSDLL_API GLint gl2psGetOptions(GLint *options)
6027{
6028 if(!gl2ps) {
6029 *options = 0;
6030 return GL2PS_UNINITIALIZED;
6031 }
6032
6033 *options = gl2ps->options;
6034
6035 return GL2PS_SUCCESS;
6036}
6037
6038GL2PSDLL_API const char *gl2psGetFileExtension(GLint format)
6039{
6040 if(format >= 0 && format < (GLint)(sizeof(gl2psbackends) / sizeof(gl2psbackends[0])))
6041 return gl2psbackends[format]->file_extension;
6042 else
6043 return "Unknown format";
6044}
6045
6047{
6048 if(format >= 0 && format < (GLint)(sizeof(gl2psbackends) / sizeof(gl2psbackends[0])))
6049 return gl2psbackends[format]->description;
6050 else
6051 return "Unknown format";
6052}
#define M_PI
double area(double R)
double length(const pvec &v)
char data[hepevt_bytes_allocation_ATLAS]
Definition HepEvt.cxx:11
std::pair< std::vector< unsigned int >, bool > res
static Double_t a
static Double_t rc
void sort(typename DataModel_detail::iterator< DVL > beg, typename DataModel_detail::iterator< DVL > end)
Specialization of sort for DataVector/List.
void diff(const Jet &rJet1, const Jet &rJet2, std::map< std::string, double > varDiff)
Difference between jets - Non-Class function required by trigger.
Definition Jet.cxx:631
double angle(const GeoTrf::Vector2D &a, const GeoTrf::Vector2D &b)
const double width
__attribute__((always_inline)) inline uint16_t TileCalibDrawerBase
const char *const fmt
#define y
#define xyz
#define x
void unused(Args &&...)
constexpr int pow(int base, int exp) noexcept
Header file for AthHistogramAlgorithm.
Definition node.h:24
void type(TYPE t)
Definition node.h:51
holding In fact this class is here in order to allow STL container for all features This class is sho...
std::string head(std::string s, const std::string &pattern)
head of a string
#define GL2PS_POINT
Definition gl2ps.cxx:76
static void gl2psPDFgroupObjectInit(GL2PSpdfgroup *gro)
Definition gl2ps.cxx:3453
#define GL2PS_END_STIPPLE_TOKEN
Definition gl2ps.cxx:106
#define GL2PS_BEGIN_OFFSET_TOKEN
Definition gl2ps.cxx:101
static void gl2psPrintTeXFooter(void)
Definition gl2ps.cxx:3307
static void gl2psListSort(GL2PSlist *list, int(*fcmp)(const void *a, const void *b))
Definition gl2ps.cxx:587
static void gl2psPrintPGFHeader(void)
Definition gl2ps.cxx:5257
static void gl2psGetPlane(GL2PSprimitive *prim, GL2PSplane plane)
Definition gl2ps.cxx:1098
static GLfloat gl2psNorm(GLfloat *a)
Definition gl2ps.cxx:1074
static GL2PSbackend * gl2psbackends[]
Definition gl2ps.cxx:5476
#define GL2PS_DST_BLEND_TOKEN
Definition gl2ps.cxx:112
static GLboolean gl2psSameColorThreshold(int n, GL2PSrgba rgba[], GL2PSrgba threshold)
Definition gl2ps.cxx:690
static void gl2psAssignTriangleProperties(GL2PStriangle *t)
Definition gl2ps.cxx:948
struct _GL2PSimagemap GL2PSimagemap
Definition gl2ps.cxx:177
static GL2PSbackend gl2psPS
Definition gl2ps.cxx:3176
static void gl2psPrintTeXPrimitive(void *data)
Definition gl2ps.cxx:3245
static GL2PSbackend gl2psTEX
Definition gl2ps.cxx:3335
GL2PSDLL_API GLint gl2psEndViewport(void)
Definition gl2ps.cxx:5787
static GL2PScontext * gl2ps
Definition gl2ps.cxx:266
static void gl2psPrintPostScriptFooter(void)
Definition gl2ps.cxx:3106
static void gl2psDivideQuad(GL2PSprimitive *quad, GL2PSprimitive **t1, GL2PSprimitive **t2)
Definition gl2ps.cxx:1343
GL2PSDLL_API const char * gl2psGetFormatDescription(GLint format)
Definition gl2ps.cxx:6046
static int gl2psPrintPDFOpenPage(void)
Definition gl2ps.cxx:4104
#define GL2PS_COINCIDENT
Definition gl2ps.cxx:88
static GLboolean gl2psSameColor(GL2PSrgba rgba1, GL2PSrgba rgba2)
Definition gl2ps.cxx:669
static const char * gl2psPGFTextAlignment(int align)
Definition gl2ps.cxx:5306
GL2PSDLL_API GLint gl2psDrawPixels(GLsizei width, GLsizei height, GLint xorig, GLint yorig, GLenum format, GLenum type, const void *pixels)
Definition gl2ps.cxx:5817
static void gl2psPrintTeXBeginViewport(GLint viewport[4])
Definition gl2ps.cxx:3313
static int gl2psPrintPDFShader(int obj, GL2PStriangle *triangles, int size, int gray)
Definition gl2ps.cxx:4335
static int gl2psListNbr(GL2PSlist *list)
Definition gl2ps.cxx:567
#define GL2PS_SPANNING
Definition gl2ps.cxx:91
static GLboolean gl2psSamePosition(GL2PSxyz p1, GL2PSxyz p2)
Definition gl2ps.cxx:1039
static void gl2psSplitPrimitive2D(GL2PSprimitive *prim, GL2PSplane plane, GL2PSprimitive **front, GL2PSprimitive **back)
Definition gl2ps.cxx:1902
static int gl2psPrintPDFPages(void)
Definition gl2ps.cxx:3974
static GLint gl2psPrintPrimitives(void)
Definition gl2ps.cxx:5504
static GLfloat gl2psPsca(GLfloat *a, GLfloat *b)
Definition gl2ps.cxx:1062
#define GL2PS_BEGIN_STIPPLE_TOKEN
Definition gl2ps.cxx:105
GL2PSDLL_API const char * gl2psGetFileExtension(GLint format)
Definition gl2ps.cxx:6038
static void gl2psPrintPostScriptFinalPrimitive(void)
Definition gl2ps.cxx:3168
static void gl2psPrintPGFPrimitive(void *data)
Definition gl2ps.cxx:5322
static void gl2psEndPostScriptLine(void)
Definition gl2ps.cxx:2895
static int gl2psPDFgroupListWriteXObjectResources(void)
Definition gl2ps.cxx:3847
static void gl2psFreePrimitive(void *data)
Definition gl2ps.cxx:1464
static GLint gl2psSplitPrimitive(GL2PSprimitive *prim, GL2PSplane plane, GL2PSprimitive **front, GL2PSprimitive **back)
Definition gl2ps.cxx:1281
static void * gl2psListPointer(GL2PSlist *list, GLint index)
Definition gl2ps.cxx:574
static GLshort gl2psGetIndex(GLshort i, GLshort num)
Definition gl2ps.cxx:1245
#define GL2PS_IMAGEMAP_VISIBLE
Definition gl2ps.cxx:83
#define GL2PS_IN_BACK_OF
Definition gl2ps.cxx:90
static void gl2psInitTriangle(GL2PStriangle *t)
Definition gl2ps.cxx:991
static void gl2psPrintTeXHeader(void)
Definition gl2ps.cxx:3204
static void gl2psPDFgroupListWriteMainStream(void)
Definition gl2ps.cxx:3616
#define GL2PS_ZERO(arg)
Definition gl2ps.cxx:70
static void gl2psAddPrimitiveInList(GL2PSprimitive *prim, GL2PSlist *list)
Definition gl2ps.cxx:1479
static int gl2psPDFgroupListWriteFontResources(void)
Definition gl2ps.cxx:3884
static void gl2psAdaptVertexForBlending(GL2PSvertex *v)
Definition gl2ps.cxx:924
static int gl2psPrintPDFCompressorType(void)
Definition gl2ps.cxx:3352
static GLint gl2psPrintPostScriptEndViewport(void)
Definition gl2ps.cxx:3159
static void gl2psAddIndex(GLshort *index0, GLshort *index1, GLshort *nb, GLshort i, GLshort j)
Definition gl2ps.cxx:1231
static void gl2psPrintSVGFooter(void)
Definition gl2ps.cxx:5164
GL2PSDLL_API GLint gl2psPointSize(GLfloat value)
Definition gl2ps.cxx:5982
static void gl2psFreeBspImageTree(GL2PSbsptree2d **tree)
Definition gl2ps.cxx:1729
static GLboolean gl2psVertsSameColor(const GL2PSprimitive *prim)
Definition gl2ps.cxx:678
GL2PSDLL_API GLint gl2psSpecial(GLint format, const char *str)
Definition gl2ps.cxx:5812
static int gl2psOpenPDFDataStreamWritePreface(void)
Definition gl2ps.cxx:4005
static int gl2psPrintPDFShaderStreamDataRGB(GL2PSvertex *vertex, size_t(*action)(unsigned long data, size_t size))
Definition gl2ps.cxx:4226
static void gl2psPrintGzipHeader()
Definition gl2ps.cxx:447
static int gl2psPDFgroupListWriteShaderResources(void)
Definition gl2ps.cxx:3825
GL2PSDLL_API GLint gl2psBeginPage(const char *title, const char *producer, GLint viewport[4], GLint format, GLint sort, GLint options, GLint colormode, GLint colorsize, GL2PSrgba *colormap, GLint nr, GLint ng, GLint nb, GLint buffersize, FILE *stream, const char *filename)
Definition gl2ps.cxx:5584
static GLboolean gl2psGreater(GLfloat f1, GLfloat f2)
Definition gl2ps.cxx:1509
static void gl2psPrintPDFPrimitive(void *data)
Definition gl2ps.cxx:4056
#define GL2PS_IMAGEMAP_WRITTEN
Definition gl2ps.cxx:82
static int gl2psCompareDepth(const void *a, const void *b)
Definition gl2ps.cxx:1367
#define GL2PS_TEXT
Definition gl2ps.cxx:75
static void gl2psSetLastColor(GL2PSrgba rgba)
Definition gl2ps.cxx:707
static int gl2psPrintPDFShaderSimpleExtGS(int obj, GLfloat alpha)
Definition gl2ps.cxx:4482
#define GL2PS_PIXMAP
Definition gl2ps.cxx:80
#define GL2PS_POINT_SIZE_TOKEN
Definition gl2ps.cxx:107
static void gl2psPrintPostScriptPixmap(GLfloat x, GLfloat y, GL2PSimage *im)
Definition gl2ps.cxx:2415
struct _GL2PSbsptree2d GL2PSbsptree2d
Definition gl2ps.cxx:129
#define GL2PS_ZSCALE
Definition gl2ps.cxx:67
static void gl2psPrintPGFDash(GLushort pattern, GLint factor)
Definition gl2ps.cxx:5284
static void gl2psTraverseBspTree(GL2PSbsptree *tree, GL2PSxyz eye, GLfloat epsilon, GLboolean(*compare)(GLfloat f1, GLfloat f2), void(*action)(void *data), int inverse)
Definition gl2ps.cxx:1584
static void gl2psPrintPGFBeginViewport(GLint viewport[4])
Definition gl2ps.cxx:5402
GL2PSDLL_API GLint gl2psBlendFunc(GLenum sfactor, GLenum dfactor)
Definition gl2ps.cxx:6002
static void * gl2psRealloc(void *ptr, size_t size)
Definition gl2ps.cxx:309
#define GL2PS_END_BLEND_TOKEN
Definition gl2ps.cxx:110
#define GL2PS_EPSILON
Definition gl2ps.cxx:66
static void gl2psPrintPostScriptPrimitive(void *data)
Definition gl2ps.cxx:2967
#define GL2PS_ZOFFSET
Definition gl2ps.cxx:68
static int gl2psPrintPDFShaderStreamDataCoord(GL2PSvertex *vertex, size_t(*action)(unsigned long data, size_t size), GLfloat dx, GLfloat dy, GLfloat xmin, GLfloat ymin)
Definition gl2ps.cxx:4179
static void gl2psFreePixmap(GL2PSimage *im)
Definition gl2ps.cxx:769
static void gl2psListDelete(GL2PSlist *list)
Definition gl2ps.cxx:549
GL2PSDLL_API GLint gl2psDrawImageMap(GLsizei width, GLsizei height, const GLfloat position[3], const unsigned char *imagemap)
Definition gl2ps.cxx:5898
static int gl2psPrintPostScriptDash(GLushort pattern, GLint factor, const char *str)
Definition gl2ps.cxx:2940
static void gl2psComputeTightBoundingBox(void *data)
Definition gl2ps.cxx:5485
static void gl2psBuildBspTree(GL2PSbsptree *tree, GL2PSlist *primitives)
Definition gl2ps.cxx:1521
static int gl2psPDFgroupListWriteGStateResources(void)
Definition gl2ps.cxx:3804
#define GL2PS_SPECIAL
Definition gl2ps.cxx:84
GL2PSDLL_API GLint gl2psSetOptions(GLint options)
Definition gl2ps.cxx:6017
struct _GL2PSbsptree GL2PSbsptree
Definition gl2ps.cxx:141
#define GL2PS_POINT_BACK
Definition gl2ps.cxx:97
static void gl2psCutEdge(GL2PSvertex *a, GL2PSvertex *b, GL2PSplane plane, GL2PSvertex *c)
Definition gl2ps.cxx:1162
static GLboolean gl2psLess(GLfloat f1, GLfloat f2)
Definition gl2ps.cxx:1515
static GLint gl2psGetVertex(GL2PSvertex *v, GLfloat *p)
Definition gl2ps.cxx:2173
static int gl2psPrintPDFText(int obj, GL2PSstring *s, int fontnumber)
Definition gl2ps.cxx:4605
static GLint gl2psCheckPoint(GL2PSxyz point, GL2PSplane plane)
Definition gl2ps.cxx:1739
#define GL2PS_SRC_BLEND_TOKEN
Definition gl2ps.cxx:111
static void gl2psPrintGzipFooter()
Definition gl2ps.cxx:465
#define GL2PS_LINE
Definition gl2ps.cxx:77
static void gl2psPvec(GLfloat *a, GLfloat *b, GLfloat *c)
Definition gl2ps.cxx:1067
static void * gl2psMalloc(size_t size)
Definition gl2ps.cxx:296
static void gl2psPDFRectHull(GLfloat *xmin, GLfloat *xmax, GLfloat *ymin, GLfloat *ymax, GL2PStriangle *triangles, int cnt)
Definition gl2ps.cxx:4305
static void gl2psPrintSVGPrimitive(void *data)
Definition gl2ps.cxx:5053
static void gl2psSVGGetCoordsAndColors(int n, GL2PSvertex *verts, GL2PSxyz *xyz, GL2PSrgba *rgba)
Definition gl2ps.cxx:4841
static GL2PSimage * gl2psCopyPixmap(GL2PSimage *im)
Definition gl2ps.cxx:743
static GLint gl2psPrintSVGEndViewport(void)
Definition gl2ps.cxx:5215
#define GL2PS_TEXT_TOKEN
Definition gl2ps.cxx:115
GL2PSDLL_API GLint gl2psDisable(GLint mode)
Definition gl2ps.cxx:5957
static void gl2psRescaleAndOffset()
Definition gl2ps.cxx:1620
static void gl2psSVGGetColorString(GL2PSrgba rgba, char str[32])
Definition gl2ps.cxx:4855
static int gl2psPrintPDFInfo(void)
Definition gl2ps.cxx:3923
GL2PSDLL_API GLint gl2psBeginViewport(GLint viewport[4])
Definition gl2ps.cxx:5778
static int gl2psTrianglesFirst(const void *a, const void *b)
Definition gl2ps.cxx:1398
static void gl2psBuildPolygonBoundary(GL2PSbsptree *tree)
Definition gl2ps.cxx:2128
static GLint gl2psCheckPrimitive(GL2PSprimitive *prim, GL2PSplane plane)
Definition gl2ps.cxx:1853
static void gl2psPrintSVGHeader(void)
Definition gl2ps.cxx:4866
static void gl2psFreeBspTree(GL2PSbsptree **tree)
Definition gl2ps.cxx:1495
static void gl2psSortOutTrianglePDFgroup(GL2PSpdfgroup *gro)
Definition gl2ps.cxx:3562
static void gl2psPrintTeXFinalPrimitive(void)
Definition gl2ps.cxx:3329
static void gl2psPrintPGFFinalPrimitive(void)
Definition gl2ps.cxx:5450
static int gl2psPrintPDFDataStreamLength(int val)
Definition gl2ps.cxx:4094
static void gl2psPrintPDFFooter(void)
Definition gl2ps.cxx:4701
#define GL2PS_POINT_INFRONT
Definition gl2ps.cxx:96
static void gl2psFree(void *ptr)
Definition gl2ps.cxx:320
static void gl2psAddPolyPrimitive(GLshort type, GLshort numverts, GL2PSvertex *verts, GLint offset, GLushort pattern, GLint factor, GLfloat width, char boundary)
Definition gl2ps.cxx:2148
static GLint gl2psFindRoot(GL2PSlist *primitives, GL2PSprimitive **root)
Definition gl2ps.cxx:1407
static GLint gl2psAddInBspImageTree(GL2PSprimitive *prim, GL2PSbsptree2d **tree)
Definition gl2ps.cxx:1984
static void gl2psListAction(GL2PSlist *list, void(*action)(void *data))
Definition gl2ps.cxx:595
#define GL2PS_IMAGEMAP_TOKEN
Definition gl2ps.cxx:113
#define GL2PS_BEGIN_BLEND_TOKEN
Definition gl2ps.cxx:109
GL2PSDLL_API GLint gl2psTextOpt(const char *str, const char *fontname, GLshort fontsize, GLint alignment, GLfloat angle)
Definition gl2ps.cxx:5801
static GLint gl2psPrintTeXEndViewport(void)
Definition gl2ps.cxx:3324
static int gl2psPDFgroupListWriteObjects(int entryoffs)
Definition gl2ps.cxx:4625
#define GL2PS_END_OFFSET_TOKEN
Definition gl2ps.cxx:102
#define GL2PS_QUADRANGLE
Definition gl2ps.cxx:78
#define GL2PS_ZOFFSET_LARGE
Definition gl2ps.cxx:69
static GL2PSstring * gl2psCopyText(GL2PSstring *t)
Definition gl2ps.cxx:888
static int gl2psPrintPDFPixmapStreamData(GL2PSimage *im, size_t(*action)(unsigned long data, size_t size), int gray)
Definition gl2ps.cxx:4498
static void gl2psEndSVGLine(void)
Definition gl2ps.cxx:5001
GL2PSDLL_API GLint gl2psEndPage(void)
Definition gl2ps.cxx:5751
static void gl2psAddBoundaryInList(GL2PSprimitive *prim, GL2PSlist *list)
Definition gl2ps.cxx:2060
static void gl2psPrintPostScriptImagemap(GLfloat x, GLfloat y, GLsizei width, GLsizei height, const unsigned char *imagemap)
Definition gl2ps.cxx:2623
static void gl2psAddPlanesInBspTreeImage(GL2PSprimitive *prim, GL2PSbsptree2d **tree)
Definition gl2ps.cxx:1749
static void gl2psMsg(GLint level, const char *fmt,...)
Definition gl2ps.cxx:278
#define GL2PS_NO_TYPE
Definition gl2ps.cxx:74
GL2PS_TRIANGLE_PROPERTY
Definition gl2ps.cxx:117
@ T_CONST_COLOR
Definition gl2ps.cxx:119
@ T_VAR_ALPHA
Definition gl2ps.cxx:123
@ T_UNDEFINED
Definition gl2ps.cxx:118
@ T_ALPHA_1
Definition gl2ps.cxx:121
@ T_VAR_COLOR
Definition gl2ps.cxx:120
@ T_ALPHA_LESS_1
Definition gl2ps.cxx:122
static void gl2psPDFgroupListInit(void)
Definition gl2ps.cxx:3466
static GLint gl2psPrintPDFEndViewport(void)
Definition gl2ps.cxx:4809
GL2PSDLL_API GLint gl2psText(const char *str, const char *fontname, GLshort fontsize)
Definition gl2ps.cxx:5807
#define GL2PS_TRIANGLE
Definition gl2ps.cxx:79
static void gl2psPrintSVGSmoothTriangle(GL2PSxyz xyz[3], GL2PSrgba rgba[3])
Definition gl2ps.cxx:4919
static GLint gl2psAddText(GLint type, const char *str, const char *fontname, GLshort fontsize, GLint alignment, GLfloat angle)
Definition gl2ps.cxx:843
static void gl2psPrintPDFHeader(void)
Definition gl2ps.cxx:4023
GL2PSDLL_API GLint gl2psEnable(GLint mode)
Definition gl2ps.cxx:5924
static void gl2psListAdd(GL2PSlist *list, void *data)
Definition gl2ps.cxx:556
static int gl2psPrintPDFStrokeColor(GL2PSrgba rgba)
Definition gl2ps.cxx:3362
static void gl2psPrintPostScriptHeader(void)
Definition gl2ps.cxx:2643
GLfloat GL2PSxyz[3]
Definition gl2ps.cxx:126
static void gl2psPrintSVGFinalPrimitive(void)
Definition gl2ps.cxx:5224
static void gl2psAddInImageTree(void *data)
Definition gl2ps.cxx:2043
static int gl2psPrintf(const char *fmt,...)
Definition gl2ps.cxx:419
static int gl2psClosePDFDataStream(void)
Definition gl2ps.cxx:4069
static void gl2psPDFgroupListDelete(void)
Definition gl2ps.cxx:3904
static int gl2psPrintPDFLineWidth(GLfloat lw)
Definition gl2ps.cxx:3395
static int gl2psPrintPDFShaderStreamDataAlpha(GL2PSvertex *vertex, size_t(*action)(unsigned long data, size_t size), int sigbyte)
Definition gl2ps.cxx:4251
static int gl2psPrintPDFCatalog(void)
Definition gl2ps.cxx:3963
static GL2PSprimitive * gl2psCreateSplitPrimitive2D(GL2PSprimitive *parent, GLshort numverts, GL2PSvertex *vertx)
Definition gl2ps.cxx:1868
static void gl2psPutPDFText(GL2PSstring *text, int cnt, GLfloat x, GLfloat y)
Definition gl2ps.cxx:3405
static GLint gl2psPrintPGFEndViewport(void)
Definition gl2ps.cxx:5442
static void gl2psFreeText(GL2PSstring *text)
Definition gl2ps.cxx:902
static int gl2psPrintPDFPixmap(int obj, int childobj, GL2PSimage *im, int gray)
Definition gl2ps.cxx:4538
static GL2PSbackend gl2psPGF
Definition gl2ps.cxx:5456
static void gl2psPrintPostScriptBeginViewport(GLint viewport[4])
Definition gl2ps.cxx:3119
static void gl2psListRealloc(GL2PSlist *list, GLint n)
Definition gl2ps.cxx:507
GLfloat GL2PSplane[4]
Definition gl2ps.cxx:127
#define GL2PS_IN_FRONT_OF
Definition gl2ps.cxx:89
static void gl2psPrintPostScriptColor(GL2PSrgba rgba)
Definition gl2ps.cxx:2882
static void gl2psListActionInverse(GL2PSlist *list, void(*action)(void *data))
Definition gl2ps.cxx:604
static void gl2psPrintPDFFinalPrimitive(void)
Definition gl2ps.cxx:4818
GL2PSDLL_API GLint gl2psLineWidth(GLfloat value)
Definition gl2ps.cxx:5992
static void gl2psCreateSplitPrimitive(GL2PSprimitive *parent, GL2PSplane plane, GL2PSprimitive *child, GLshort numverts, GLshort *index0, GLshort *index1)
Definition gl2ps.cxx:1187
static GLboolean gl2psSupportedBlendMode(GLenum sfactor, GLenum dfactor)
Definition gl2ps.cxx:913
static GLfloat gl2psGetRGB(GL2PSimage *im, GLuint x, GLuint y, GLfloat *red, GLfloat *green, GLfloat *blue)
Definition gl2ps.cxx:715
static void gl2psPrintPDFBeginViewport(GLint viewport[4])
Definition gl2ps.cxx:4766
static GL2PSprimitive * gl2psCopyPrimitive(GL2PSprimitive *p)
Definition gl2ps.cxx:1002
static size_t gl2psWriteBigEndian(unsigned long data, size_t bytes)
Definition gl2ps.cxx:326
static void gl2psPDFstacksInit(void)
Definition gl2ps.cxx:3442
static void gl2psFreeImagemap(GL2PSimagemap *list)
Definition gl2ps.cxx:1452
static GLint gl2psTestSplitPrimitive(GL2PSprimitive *prim, GL2PSplane plane)
Definition gl2ps.cxx:1250
static int gl2psPrintPDFShaderExtGS(int obj, int childobj)
Definition gl2ps.cxx:4461
static void gl2psGetNormal(GLfloat *a, GLfloat *b, GLfloat *c)
Definition gl2ps.cxx:1079
static void gl2psPrintSVGBeginViewport(GLint viewport[4])
Definition gl2ps.cxx:5172
static int gl2psOpenPDFDataStream(void)
Definition gl2ps.cxx:3988
static void gl2psPrintSVGDash(GLushort pattern, GLint factor)
Definition gl2ps.cxx:4986
#define GL2PS_BEGIN_BOUNDARY_TOKEN
Definition gl2ps.cxx:103
static void gl2psParseFeedbackBuffer(GLint used)
Definition gl2ps.cxx:2198
static void gl2psPrintPGFColor(GL2PSrgba rgba)
Definition gl2ps.cxx:5249
static int gl2psPrintPDFShaderMask(int obj, int childobj)
Definition gl2ps.cxx:4422
static int gl2psPrintPDFFillColor(GL2PSrgba rgba)
Definition gl2ps.cxx:3379
static void gl2psParseStipplePattern(GLushort pattern, GLint factor, int *nb, int array[10])
Definition gl2ps.cxx:2907
static GL2PSbackend gl2psPDF
Definition gl2ps.cxx:4824
static GL2PSbackend gl2psSVG
Definition gl2ps.cxx:5232
static void gl2psListReset(GL2PSlist *list)
Definition gl2ps.cxx:543
#define GL2PS_END_BOUNDARY_TOKEN
Definition gl2ps.cxx:104
#define GL2PS_DRAW_PIXELS_TOKEN
Definition gl2ps.cxx:114
#define GL2PS_IMAGEMAP
Definition gl2ps.cxx:81
static GL2PSlist * gl2psListCreate(GLint n, GLint incr, GLint size)
Definition gl2ps.cxx:527
static int gl2psPrintPDFGSObject(void)
Definition gl2ps.cxx:4159
static void gl2psPutPDFImage(GL2PSimage *image, int cnt, GLfloat x, GLfloat y)
Definition gl2ps.cxx:3432
static void gl2psWriteByte(unsigned char byte)
Definition gl2ps.cxx:2408
static void gl2psResetPostScriptColor(void)
Definition gl2ps.cxx:2890
static GLfloat gl2psComparePointPlane(GL2PSxyz point, GL2PSplane plane)
Definition gl2ps.cxx:1054
GL2PSDLL_API GLint gl2psGetOptions(GLint *options)
Definition gl2ps.cxx:6026
static void gl2psPrintSVGPixmap(GLfloat, GLfloat, GL2PSimage *)
Definition gl2ps.cxx:5014
static GL2PSbackend gl2psEPS
Definition gl2ps.cxx:3187
static int gl2psPDFgroupListWriteVariableResources(void)
Definition gl2ps.cxx:4133
static void gl2psFillTriangleFromPrimitive(GL2PStriangle *t, GL2PSprimitive *p, GLboolean assignprops)
Definition gl2ps.cxx:981
#define GL2PS_POINT_COINCIDENT
Definition gl2ps.cxx:95
#define GL2PS_LINE_WIDTH_TOKEN
Definition gl2ps.cxx:108
static void gl2psPrintPGFFooter(void)
Definition gl2ps.cxx:5397
static int gl2psPrintPDFShaderStreamData(GL2PStriangle *triangle, GLfloat dx, GLfloat dy, GLfloat xmin, GLfloat ymin, size_t(*action)(unsigned long data, size_t size), int gray)
Definition gl2ps.cxx:4277
static GLint gl2psGetPlaneFromPoints(GL2PSxyz a, GL2PSxyz b, GL2PSplane plane)
Definition gl2ps.cxx:1707
#define GL2PS_SVG
Definition gl2ps.h:98
#define GL2PS_UNINITIALIZED
Definition gl2ps.h:115
#define GL2PS_TIGHT_BOUNDING_BOX
Definition gl2ps.h:132
#define GL2PS_SIMPLE_SORT
Definition gl2ps.h:104
#define GL2PS_NO_BLENDING
Definition gl2ps.h:131
#define GL2PS_ERROR
Definition gl2ps.h:112
#define GL2PS_BSP_SORT
Definition gl2ps.h:105
#define GL2PS_SIMPLE_LINE_OFFSET
Definition gl2ps.h:121
#define GL2PS_TEXT_T
Definition gl2ps.h:153
#define GL2PS_OCCLUSION_CULL
Definition gl2ps.h:124
#define GL2PS_PATCH_VERSION
Definition gl2ps.h:83
#define GL2PS_SILENT
Definition gl2ps.h:122
#define GL2PS_LINE_STIPPLE
Definition gl2ps.h:138
#define GL2PS_POLYGON_BOUNDARY
Definition gl2ps.h:137
#define GL2PS_OVERFLOW
Definition gl2ps.h:114
#define GL2PSDLL_API
Definition gl2ps.h:60
GLfloat GL2PSrgba[4]
Definition gl2ps.h:157
#define GL2PS_COPYRIGHT
Definition gl2ps.h:90
#define GL2PS_MAJOR_VERSION
Definition gl2ps.h:81
#define GL2PS_POLYGON_OFFSET_FILL
Definition gl2ps.h:136
#define GL2PS_TEXT_TL
Definition gl2ps.h:154
#define GL2PS_BEST_ROOT
Definition gl2ps.h:123
#define GL2PS_DRAW_BACKGROUND
Definition gl2ps.h:120
#define GL2PS_SUCCESS
Definition gl2ps.h:109
#define GL2PS_TEXT_CL
Definition gl2ps.h:148
#define GL2PS_TEXT_BL
Definition gl2ps.h:151
#define GL2PS_INFO
Definition gl2ps.h:110
#define GL2PS_LANDSCAPE
Definition gl2ps.h:126
#define GL2PS_NO_PS3_SHADING
Definition gl2ps.h:127
#define GL2PS_EXTRA_VERSION
Definition gl2ps.h:84
#define GL2PS_COMPRESS
Definition gl2ps.h:130
#define GL2PS_MINOR_VERSION
Definition gl2ps.h:82
#define GL2PS_NO_SORT
Definition gl2ps.h:103
#define GL2PS_NO_FEEDBACK
Definition gl2ps.h:113
#define GL2PS_TEXT_BR
Definition gl2ps.h:152
#define GL2PS_EPS
Definition gl2ps.h:95
#define GL2PS_NO_PIXMAP
Definition gl2ps.h:128
#define GL2PS_WARNING
Definition gl2ps.h:111
#define GL2PS_PGF
Definition gl2ps.h:99
#define GL2PS_USE_CURRENT_VIEWPORT
Definition gl2ps.h:129
#define GL2PS_TEXT_CR
Definition gl2ps.h:149
#define GL2PS_TEXT_TR
Definition gl2ps.h:155
#define GL2PS_TEX
Definition gl2ps.h:96
#define GL2PS_PDF
Definition gl2ps.h:97
#define GL2PS_PS
Definition gl2ps.h:94
#define GL2PS_NO_TEXT
Definition gl2ps.h:125
#define GL2PS_BLEND
Definition gl2ps.h:139
#define GL2PS_TEXT_B
Definition gl2ps.h:150
#define GL2PS_TEXT_C
Definition gl2ps.h:147
int r
Definition globals.cxx:22
int count(std::string s, const std::string &regx)
count how many occurances of a regx are in a string
Definition hcg.cxx:146
double xmax
Definition listroot.cxx:61
double ymin
Definition listroot.cxx:63
double xmin
Definition listroot.cxx:60
double ymax
Definition listroot.cxx:64
void compress(const AmgSymMatrix(N) &covMatrix, std::vector< float > &vec)
row
Appending html table to final .html summary file.
Definition index.py:1
void(* printFinalPrimitive)(void)
Definition gl2ps.cxx:258
const char * file_extension
Definition gl2ps.cxx:259
GLint(* endViewport)(void)
Definition gl2ps.cxx:256
const char * description
Definition gl2ps.cxx:260
void(* printPrimitive)(void *data)
Definition gl2ps.cxx:257
void(* beginViewport)(GLint viewport[4])
Definition gl2ps.cxx:255
void(* printFooter)(void)
Definition gl2ps.cxx:254
void(* printHeader)(void)
Definition gl2ps.cxx:253
int trgroupobjects_stack
Definition gl2ps.cxx:243
GLint maxbestroot
Definition gl2ps.cxx:228
GLboolean zerosurfacearea
Definition gl2ps.cxx:231
GLint sort
Definition gl2ps.cxx:214
GL2PSimagemap * imagemap_head
Definition gl2ps.cxx:248
GL2PSlist * pdfgrouplist
Definition gl2ps.cxx:237
char * producer
Definition gl2ps.cxx:215
GL2PSimagemap * imagemap_tail
Definition gl2ps.cxx:249
GLboolean boundary
Definition gl2ps.cxx:216
int objects_stack
Definition gl2ps.cxx:239
GLint format
Definition gl2ps.cxx:214
GLint viewport[4]
Definition gl2ps.cxx:218
GLushort lastpattern
Definition gl2ps.cxx:220
int mshader_stack
Definition gl2ps.cxx:245
int shader_stack
Definition gl2ps.cxx:244
GL2PSrgba threshold
Definition gl2ps.cxx:219
GLint blendfunc[2]
Definition gl2ps.cxx:218
GLboolean blending
Definition gl2ps.cxx:216
int font_stack
Definition gl2ps.cxx:241
GLint colormode
Definition gl2ps.cxx:214
GL2PSvertex lastvertex
Definition gl2ps.cxx:221
char * title
Definition gl2ps.cxx:215
GL2PSprimitive * primitivetoadd
Definition gl2ps.cxx:233
GLint options
Definition gl2ps.cxx:214
GL2PSlist * primitives
Definition gl2ps.cxx:222
GLint lastfactor
Definition gl2ps.cxx:218
GLfloat * feedback
Definition gl2ps.cxx:217
int extgs_stack
Definition gl2ps.cxx:240
GL2PSrgba bgcolor
Definition gl2ps.cxx:219
GL2PSrgba lastrgba
Definition gl2ps.cxx:219
GL2PScompress * compress
Definition gl2ps.cxx:224
char * filename
Definition gl2ps.cxx:215
int streamlength
Definition gl2ps.cxx:236
GL2PSrgba * colormap
Definition gl2ps.cxx:219
GLint colorsize
Definition gl2ps.cxx:214
GL2PSbsptree2d * imagetree
Definition gl2ps.cxx:232
GL2PSlist * pdfprimlist
Definition gl2ps.cxx:237
FILE * stream
Definition gl2ps.cxx:223
GL2PSlist * auxprimitives
Definition gl2ps.cxx:222
GLboolean header
Definition gl2ps.cxx:225
GLint buffersize
Definition gl2ps.cxx:214
int * xreflist
Definition gl2ps.cxx:238
GLfloat lastlinewidth
Definition gl2ps.cxx:217
GLfloat offset[2]
Definition gl2ps.cxx:217
GLfloat * pixels
Definition gl2ps.cxx:174
GLenum type
Definition gl2ps.cxx:173
GLsizei width
Definition gl2ps.cxx:169
GLenum format
Definition gl2ps.cxx:173
GLsizei height
Definition gl2ps.cxx:169
GLint n
Definition gl2ps.cxx:137
GLint nmax
Definition gl2ps.cxx:137
char * array
Definition gl2ps.cxx:138
GLint size
Definition gl2ps.cxx:137
GLint incr
Definition gl2ps.cxx:137
int trgroupobjno
Definition gl2ps.cxx:209
int maskshobjno
Definition gl2ps.cxx:209
GL2PSlist * ptrlist
Definition gl2ps.cxx:207
GLshort numverts
Definition gl2ps.cxx:185
union GL2PSprimitive::@040324153072217261054023207035000330116237114065 data
GLushort pattern
Definition gl2ps.cxx:186
GLshort type
Definition gl2ps.cxx:185
GL2PSvertex * verts
Definition gl2ps.cxx:190
GL2PSimage * image
Definition gl2ps.cxx:193
GLfloat width
Definition gl2ps.cxx:189
GL2PSstring * text
Definition gl2ps.cxx:192
char * fontname
Definition gl2ps.cxx:161
GLint alignment
Definition gl2ps.cxx:164
char * str
Definition gl2ps.cxx:161
GLfloat angle
Definition gl2ps.cxx:165
GLshort fontsize
Definition gl2ps.cxx:160
GL2PSvertex vertex[3]
Definition gl2ps.cxx:155
GL2PSxyz xyz
Definition gl2ps.cxx:150
GL2PSrgba rgba
Definition gl2ps.cxx:151
GL2PSplane plane
Definition gl2ps.cxx:132
GL2PSbsptree2d * front
Definition gl2ps.cxx:133
GL2PSbsptree2d * back
Definition gl2ps.cxx:133
GL2PSbsptree * front
Definition gl2ps.cxx:146
GL2PSbsptree * back
Definition gl2ps.cxx:146
GL2PSlist * primitives
Definition gl2ps.cxx:145
GL2PSplane plane
Definition gl2ps.cxx:144
GL2PSimagemap * next
Definition gl2ps.cxx:181
GL2PSimage * image
Definition gl2ps.cxx:180
TChain * tree