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