Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/externals/g4tools/include/tools/gl2ps

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

Diff markup

Differences between /externals/g4tools/include/tools/gl2ps (Version 11.3.0) and /externals/g4tools/include/tools/gl2ps (Version 11.2.2)


  1 #ifndef tools_gl2ps                                 1 #ifndef tools_gl2ps
  2 #define tools_gl2ps                                 2 #define tools_gl2ps
  3                                                     3 
  4 // This version of gl2ps-1.4.2 contains four m      4 // This version of gl2ps-1.4.2 contains four main changes:
  5 // - it is pure header.                             5 // - it is pure header.
  6 // - the code had been "namespace protected" b      6 // - the code had been "namespace protected" by changing :
  7 //     gl2ps_<xxx> to tools_gl2ps_<xxx>             7 //     gl2ps_<xxx> to tools_gl2ps_<xxx>
  8 //   and :                                          8 //   and :
  9 //     GL2PS_<xxx> to TOOLS_GL2PS_<xxx>             9 //     GL2PS_<xxx> to TOOLS_GL2PS_<xxx>
 10 // - the code had been made thread safe by avo     10 // - the code had been made thread safe by avoiding the internal writeable
 11 //   static singleton gl2ps context object. Wi     11 //   static singleton gl2ps context object. With this version, you have to
 12 //   create yourself a context, and pass it as     12 //   create yourself a context, and pass it as first argument to all public
 13 //   tools_gl2ps functions that you want to us     13 //   tools_gl2ps functions that you want to use with some code as:
 14 //     ....                                        14 //     ....
 15 //     #include <tools/gl2ps>                      15 //     #include <tools/gl2ps>
 16 //     ....                                        16 //     ....
 17 //     tools_GL2PScontext* gl2ps_context = too     17 //     tools_GL2PScontext* gl2ps_context = tools_gl2psCreateContext();
 18 //     ....                                        18 //     ....
 19 //     tools_gl2psBeginPage(gl2ps_context,...)     19 //     tools_gl2psBeginPage(gl2ps_context,...);
 20 //     ...                                         20 //     ...
 21 //     tools_gl2psEndPage(gl2ps_context);          21 //     tools_gl2psEndPage(gl2ps_context);
 22 //     ....                                        22 //     ....
 23 //     tools_gl2psDeleteContext(gl2ps_context)     23 //     tools_gl2psDeleteContext(gl2ps_context);
 24 //     ....                                        24 //     ....
 25 // - it does not call directly OpenGL function     25 // - it does not call directly OpenGL functions 
 26 //     glIsEnabled,glBegin,glEnd,glGetFloatv,g     26 //     glIsEnabled,glBegin,glEnd,glGetFloatv,glVertex3f,glGetBooleanv,
 27 //     glGetIntegerv,glRenderMode,glFeedbackBu     27 //     glGetIntegerv,glRenderMode,glFeedbackBuffer,glPassThrough
 28 //   but pointer to functions with the same si     28 //   but pointer to functions with the same signature. This permits to
 29 //   use tools_gl2ps in a non OpenGL context,      29 //   use tools_gl2ps in a non OpenGL context, for example on primitives declared
 30 //   by using tools_gl2psAddPolyPrimitive. If      30 //   by using tools_gl2psAddPolyPrimitive. If you want to use tools_gl2ps on primitives
 31 //   got by using the OpenGL FEEDBACK mode (th     31 //   got by using the OpenGL FEEDBACK mode (the "original way"), you have first
 32 //   to declare the OpenGL upper functions on      32 //   to declare the OpenGL upper functions on a tools_GL2PScontext with:
 33 //     ....                                        33 //     ....
 34 //     #include <tools/gl2ps>                      34 //     #include <tools/gl2ps>
 35 //     ....                                        35 //     ....
 36 //     #include <GL/gl.h>                          36 //     #include <GL/gl.h>
 37 //     ....                                        37 //     ....
 38 //     tools_GL2PScontext* gl2ps_context = too     38 //     tools_GL2PScontext* gl2ps_context = tools_gl2psCreateContext();
 39 //     ...                                         39 //     ...
 40 //     tools_gl2ps_gl_funcs_t _funcs = {           40 //     tools_gl2ps_gl_funcs_t _funcs = {
 41 //       glIsEnabled,                              41 //       glIsEnabled,
 42 //       glBegin,                                  42 //       glBegin,
 43 //       glEnd,                                    43 //       glEnd,
 44 //       glGetFloatv,                              44 //       glGetFloatv,
 45 //       glVertex3f,                               45 //       glVertex3f,
 46 //       glGetBooleanv,                            46 //       glGetBooleanv,
 47 //       glGetIntegerv,                            47 //       glGetIntegerv,
 48 //       glRenderMode,                             48 //       glRenderMode,
 49 //       glFeedbackBuffer,                         49 //       glFeedbackBuffer,
 50 //       glPassThrough                             50 //       glPassThrough
 51 //     };                                          51 //     };
 52 //     tools_gl2ps_set_gl_funcs(gl2ps_context,     52 //     tools_gl2ps_set_gl_funcs(gl2ps_context,&_funcs);
 53 //     ...                                         53 //     ...
 54 //                                                 54 //      
 55 //    Guy Barrand. 15/March/2022                   55 //    Guy Barrand. 15/March/2022
 56 //                                                 56 //
 57                                                    57 
 58 /*                                                 58 /*
 59  * GL2PS, an OpenGL to PostScript Printing Lib     59  * GL2PS, an OpenGL to PostScript Printing Library
 60  * Copyright (C) 1999-2020 C. Geuzaine             60  * Copyright (C) 1999-2020 C. Geuzaine
 61  *                                                 61  *
 62  * This program is free software; you can redi     62  * This program is free software; you can redistribute it and/or
 63  * modify it under the terms of either:            63  * modify it under the terms of either:
 64  *                                                 64  *
 65  * a) the GNU Library General Public License a     65  * a) the GNU Library General Public License as published by the Free
 66  * Software Foundation, either version 2 of th     66  * Software Foundation, either version 2 of the License, or (at your
 67  * option) any later version; or                   67  * option) any later version; or
 68  *                                                 68  *
 69  * b) the GL2PS License as published by Christ     69  * b) the GL2PS License as published by Christophe Geuzaine, either
 70  * version 2 of the License, or (at your optio     70  * version 2 of the License, or (at your option) any later version.
 71  *                                                 71  *
 72  * This program is distributed in the hope tha     72  * This program is distributed in the hope that it will be useful, but
 73  * WITHOUT ANY WARRANTY; without even the impl     73  * WITHOUT ANY WARRANTY; without even the implied warranty of
 74  * MERCHANTABILITY or FITNESS FOR A PARTICULAR     74  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See either
 75  * the GNU Library General Public License or t     75  * the GNU Library General Public License or the GL2PS License for
 76  * more details.                                   76  * more details.
 77  *                                                 77  *
 78  * You should have received a copy of the GNU      78  * You should have received a copy of the GNU Library General Public
 79  * License along with this library in the file     79  * License along with this library in the file named "COPYING.LGPL";
 80  * if not, write to the Free Software Foundati     80  * if not, write to the Free Software Foundation, Inc., 51 Franklin
 81  * Street, Fifth Floor, Boston, MA 02110-1301,     81  * Street, Fifth Floor, Boston, MA 02110-1301, USA.
 82  *                                                 82  *
 83  * You should have received a copy of the GL2P     83  * You should have received a copy of the GL2PS License with this
 84  * library in the file named "COPYING.GL2PS";      84  * library in the file named "COPYING.GL2PS"; if not, I will be glad
 85  * to provide one.                                 85  * to provide one.
 86  *                                                 86  *
 87  * For the latest info about gl2ps and a full      87  * For the latest info about gl2ps and a full list of contributors,
 88  * see http://www.geuz.org/gl2ps/.                 88  * see http://www.geuz.org/gl2ps/.
 89  *                                                 89  *
 90  * Please report all bugs and problems to <gl2     90  * Please report all bugs and problems to <gl2ps@geuz.org>.
 91  */                                                91  */
 92                                                    92 
 93 #include "gl2ps_def.h"                             93 #include "gl2ps_def.h"
 94                                                    94 
 95 #include <stdlib.h>                                95 #include <stdlib.h>
 96 #include <stdio.h>                                 96 #include <stdio.h>
 97                                                    97 
 98 #include <math.h>                                  98 #include <math.h>
 99 #include <string.h>                                99 #include <string.h>
100 #include <sys/types.h>                            100 #include <sys/types.h>
101 #include <stdarg.h>                               101 #include <stdarg.h>
102 #include <time.h>                                 102 #include <time.h>
103 #include <float.h>                                103 #include <float.h>
104                                                   104 
105 #if defined(TOOLS_GL2PS_HAVE_ZLIB)                105 #if defined(TOOLS_GL2PS_HAVE_ZLIB)
106 #include <zlib.h>                                 106 #include <zlib.h>
107 #endif                                            107 #endif
108                                                   108 
109 #if defined(TOOLS_GL2PS_HAVE_LIBPNG)              109 #if defined(TOOLS_GL2PS_HAVE_LIBPNG)
110 #include <png.h>                                  110 #include <png.h>
111 #endif                                            111 #endif
112                                                   112 
113 /*********************************************    113 /*********************************************************************
114  *                                                114  *
115  * Private definitions, data structures and pr    115  * Private definitions, data structures and prototypes
116  *                                                116  *
117  *********************************************    117  *********************************************************************/
118                                                   118 
119 /* Magic numbers (assuming that the order of m    119 /* Magic numbers (assuming that the order of magnitude of window
120    coordinates is 10^3) */                        120    coordinates is 10^3) */
121                                                   121 
122 #define TOOLS_GL2PS_EPSILON       5.0e-3F         122 #define TOOLS_GL2PS_EPSILON       5.0e-3F
123 #define TOOLS_GL2PS_ZSCALE        1000.0F         123 #define TOOLS_GL2PS_ZSCALE        1000.0F
124 #define TOOLS_GL2PS_ZOFFSET       5.0e-2F         124 #define TOOLS_GL2PS_ZOFFSET       5.0e-2F
125 #define TOOLS_GL2PS_ZOFFSET_LARGE 20.0F           125 #define TOOLS_GL2PS_ZOFFSET_LARGE 20.0F
126 #define TOOLS_GL2PS_ZERO(arg)     (fabs(arg) <    126 #define TOOLS_GL2PS_ZERO(arg)     (fabs(arg) < 1.e-20)
127                                                   127 
128 /* BSP tree primitive comparison */               128 /* BSP tree primitive comparison */
129                                                   129 
130 #define TOOLS_GL2PS_COINCIDENT  1                 130 #define TOOLS_GL2PS_COINCIDENT  1
131 #define TOOLS_GL2PS_IN_FRONT_OF 2                 131 #define TOOLS_GL2PS_IN_FRONT_OF 2
132 #define TOOLS_GL2PS_IN_BACK_OF  3                 132 #define TOOLS_GL2PS_IN_BACK_OF  3
133 #define TOOLS_GL2PS_SPANNING    4                 133 #define TOOLS_GL2PS_SPANNING    4
134                                                   134 
135 /* 2D BSP tree primitive comparison */            135 /* 2D BSP tree primitive comparison */
136                                                   136 
137 #define TOOLS_GL2PS_POINT_COINCIDENT 0            137 #define TOOLS_GL2PS_POINT_COINCIDENT 0
138 #define TOOLS_GL2PS_POINT_INFRONT    1            138 #define TOOLS_GL2PS_POINT_INFRONT    1
139 #define TOOLS_GL2PS_POINT_BACK       2            139 #define TOOLS_GL2PS_POINT_BACK       2
140                                                   140 
141 /* Internal feedback buffer pass-through token    141 /* Internal feedback buffer pass-through tokens */
142                                                   142 
143 #define TOOLS_GL2PS_BEGIN_OFFSET_TOKEN   1        143 #define TOOLS_GL2PS_BEGIN_OFFSET_TOKEN   1
144 #define TOOLS_GL2PS_END_OFFSET_TOKEN     2        144 #define TOOLS_GL2PS_END_OFFSET_TOKEN     2
145 #define TOOLS_GL2PS_BEGIN_BOUNDARY_TOKEN 3        145 #define TOOLS_GL2PS_BEGIN_BOUNDARY_TOKEN 3
146 #define TOOLS_GL2PS_END_BOUNDARY_TOKEN   4        146 #define TOOLS_GL2PS_END_BOUNDARY_TOKEN   4
147 #define TOOLS_GL2PS_BEGIN_STIPPLE_TOKEN  5        147 #define TOOLS_GL2PS_BEGIN_STIPPLE_TOKEN  5
148 #define TOOLS_GL2PS_END_STIPPLE_TOKEN    6        148 #define TOOLS_GL2PS_END_STIPPLE_TOKEN    6
149 #define TOOLS_GL2PS_POINT_SIZE_TOKEN     7        149 #define TOOLS_GL2PS_POINT_SIZE_TOKEN     7
150 #define TOOLS_GL2PS_LINE_CAP_TOKEN       8        150 #define TOOLS_GL2PS_LINE_CAP_TOKEN       8
151 #define TOOLS_GL2PS_LINE_JOIN_TOKEN      9        151 #define TOOLS_GL2PS_LINE_JOIN_TOKEN      9
152 #define TOOLS_GL2PS_LINE_WIDTH_TOKEN     10       152 #define TOOLS_GL2PS_LINE_WIDTH_TOKEN     10
153 #define TOOLS_GL2PS_BEGIN_BLEND_TOKEN    11       153 #define TOOLS_GL2PS_BEGIN_BLEND_TOKEN    11
154 #define TOOLS_GL2PS_END_BLEND_TOKEN      12       154 #define TOOLS_GL2PS_END_BLEND_TOKEN      12
155 #define TOOLS_GL2PS_SRC_BLEND_TOKEN      13       155 #define TOOLS_GL2PS_SRC_BLEND_TOKEN      13
156 #define TOOLS_GL2PS_DST_BLEND_TOKEN      14       156 #define TOOLS_GL2PS_DST_BLEND_TOKEN      14
157 #define TOOLS_GL2PS_IMAGEMAP_TOKEN       15       157 #define TOOLS_GL2PS_IMAGEMAP_TOKEN       15
158 #define TOOLS_GL2PS_DRAW_PIXELS_TOKEN    16       158 #define TOOLS_GL2PS_DRAW_PIXELS_TOKEN    16
159 #define TOOLS_GL2PS_TEXT_TOKEN           17       159 #define TOOLS_GL2PS_TEXT_TOKEN           17
160                                                   160 
161 typedef enum {                                    161 typedef enum {
162   T_UNDEFINED    = -1,                            162   T_UNDEFINED    = -1,
163   T_CONST_COLOR  = 1,                             163   T_CONST_COLOR  = 1,
164   T_VAR_COLOR    = 1<<1,                          164   T_VAR_COLOR    = 1<<1,
165   T_ALPHA_1      = 1<<2,                          165   T_ALPHA_1      = 1<<2,
166   T_ALPHA_LESS_1 = 1<<3,                          166   T_ALPHA_LESS_1 = 1<<3,
167   T_VAR_ALPHA    = 1<<4                           167   T_VAR_ALPHA    = 1<<4
168 } TOOLS_GL2PS_TRIANGLE_PROPERTY;                  168 } TOOLS_GL2PS_TRIANGLE_PROPERTY;
169                                                   169 
170 typedef tools_GLfloat tools_GL2PSplane[4];        170 typedef tools_GLfloat tools_GL2PSplane[4];
171                                                   171 
172 typedef struct tools_GL2PSbsptree2d_ tools_GL2    172 typedef struct tools_GL2PSbsptree2d_ tools_GL2PSbsptree2d;
173                                                   173 
174 struct tools_GL2PSbsptree2d_ {                    174 struct tools_GL2PSbsptree2d_ {
175   tools_GL2PSplane plane;                         175   tools_GL2PSplane plane;
176   tools_GL2PSbsptree2d *front, *back;             176   tools_GL2PSbsptree2d *front, *back;
177 };                                                177 };
178                                                   178 
179 typedef struct {                                  179 typedef struct {
180   tools_GLint nmax, size, incr, n;                180   tools_GLint nmax, size, incr, n;
181   char *array;                                    181   char *array;
182 } tools_GL2PSlist;                                182 } tools_GL2PSlist;
183                                                   183 
184 typedef struct tools_GL2PSbsptree_ tools_GL2PS    184 typedef struct tools_GL2PSbsptree_ tools_GL2PSbsptree;
185                                                   185 
186 struct tools_GL2PSbsptree_ {                      186 struct tools_GL2PSbsptree_ {
187   tools_GL2PSplane plane;                         187   tools_GL2PSplane plane;
188   tools_GL2PSlist *primitives;                    188   tools_GL2PSlist *primitives;
189   tools_GL2PSbsptree *front, *back;               189   tools_GL2PSbsptree *front, *back;
190 };                                                190 };
191                                                   191 
192 typedef struct {                                  192 typedef struct {
193   tools_GL2PSvertex vertex[3];                    193   tools_GL2PSvertex vertex[3];
194   int prop;                                       194   int prop;
195 } tools_GL2PStriangle;                            195 } tools_GL2PStriangle;
196                                                   196 
197 typedef struct {                                  197 typedef struct {
198   tools_GLshort fontsize;                         198   tools_GLshort fontsize;
199   char *str, *fontname;                           199   char *str, *fontname;
200   /* Note: for a 'special' string, 'alignment'    200   /* Note: for a 'special' string, 'alignment' holds the format
201      (PostScript, PDF, etc.) of the special st    201      (PostScript, PDF, etc.) of the special string */
202   tools_GLint alignment;                          202   tools_GLint alignment;
203   tools_GLfloat angle;                            203   tools_GLfloat angle;
204 } tools_GL2PSstring;                              204 } tools_GL2PSstring;
205                                                   205 
206 typedef struct {                                  206 typedef struct {
207   tools_GLsizei width, height;                    207   tools_GLsizei width, height;
208   /* Note: for an imagemap, 'type' indicates i    208   /* Note: for an imagemap, 'type' indicates if it has already been
209      written to the file or not, and 'format'     209      written to the file or not, and 'format' indicates if it is
210      visible or not */                            210      visible or not */
211   tools_GLenum format, type;                      211   tools_GLenum format, type;
212   tools_GLfloat zoom_x, zoom_y;                   212   tools_GLfloat zoom_x, zoom_y;
213   tools_GLfloat *pixels;                          213   tools_GLfloat *pixels;
214 } tools_GL2PSimage;                               214 } tools_GL2PSimage;
215                                                   215 
216 typedef struct tools_GL2PSimagemap_ tools_GL2P    216 typedef struct tools_GL2PSimagemap_ tools_GL2PSimagemap;
217                                                   217 
218 struct tools_GL2PSimagemap_ {                     218 struct tools_GL2PSimagemap_ {
219   tools_GL2PSimage *image;                        219   tools_GL2PSimage *image;
220   tools_GL2PSimagemap *next;                      220   tools_GL2PSimagemap *next;
221 };                                                221 };
222                                                   222 
223 typedef struct {                                  223 typedef struct {
224   tools_GLshort type, numverts;                   224   tools_GLshort type, numverts;
225   tools_GLushort pattern;                         225   tools_GLushort pattern;
226   char boundary, offset, culled;                  226   char boundary, offset, culled;
227   tools_GLint factor, linecap, linejoin, sorti    227   tools_GLint factor, linecap, linejoin, sortid;
228   tools_GLfloat width, ofactor, ounits;           228   tools_GLfloat width, ofactor, ounits;
229   tools_GL2PSvertex *verts;                       229   tools_GL2PSvertex *verts;
230   union {                                         230   union {
231     tools_GL2PSstring *text;                      231     tools_GL2PSstring *text;
232     tools_GL2PSimage *image;                      232     tools_GL2PSimage *image;
233   } data;                                         233   } data;
234 } tools_GL2PSprimitive;                           234 } tools_GL2PSprimitive;
235                                                   235 
236 typedef struct {                                  236 typedef struct {
237 #if defined(TOOLS_GL2PS_HAVE_ZLIB)                237 #if defined(TOOLS_GL2PS_HAVE_ZLIB)
238   Bytef *dest, *src, *start;                      238   Bytef *dest, *src, *start;
239   uLongf destLen, srcLen;                         239   uLongf destLen, srcLen;
240 #else                                             240 #else
241   int dummy;                                      241   int dummy;
242 #endif                                            242 #endif
243 } tools_GL2PScompress;                            243 } tools_GL2PScompress;
244                                                   244 
245 typedef struct{                                   245 typedef struct{
246   tools_GL2PSlist* ptrlist;                       246   tools_GL2PSlist* ptrlist;
247   int gsno, fontno, imno, shno, maskshno, trgr    247   int gsno, fontno, imno, shno, maskshno, trgroupno;
248   int gsobjno, fontobjno, imobjno, shobjno, ma    248   int gsobjno, fontobjno, imobjno, shobjno, maskshobjno, trgroupobjno;
249 } tools_GL2PSpdfgroup;                            249 } tools_GL2PSpdfgroup;
250                                                   250 
251 typedef struct tools_GL2PScontextRec {            251 typedef struct tools_GL2PScontextRec {
252   /* General */                                   252   /* General */
253   tools_GLint format, sort, options, colorsize    253   tools_GLint format, sort, options, colorsize, colormode, buffersize;
254   tools_GLint lastlinecap, lastlinejoin;          254   tools_GLint lastlinecap, lastlinejoin;
255   char *title, *producer, *filename;              255   char *title, *producer, *filename;
256   tools_GLboolean boundary, blending;             256   tools_GLboolean boundary, blending;
257   tools_GLfloat *feedback, lastlinewidth;         257   tools_GLfloat *feedback, lastlinewidth;
258   tools_GLint viewport[4], blendfunc[2], lastf    258   tools_GLint viewport[4], blendfunc[2], lastfactor;
259   tools_GL2PSrgba *colormap, lastrgba, thresho    259   tools_GL2PSrgba *colormap, lastrgba, threshold, bgcolor;
260   tools_GLushort lastpattern;                     260   tools_GLushort lastpattern;
261   tools_GL2PSvertex lastvertex;                   261   tools_GL2PSvertex lastvertex;
262   tools_GL2PSlist *primitives, *auxprimitives;    262   tools_GL2PSlist *primitives, *auxprimitives;
263   FILE *stream;                                   263   FILE *stream;
264   tools_GL2PScompress *compress;                  264   tools_GL2PScompress *compress;
265   tools_GLboolean header;                         265   tools_GLboolean header;
266   tools_GL2PSvertex rasterpos;                    266   tools_GL2PSvertex rasterpos;
267   tools_GLboolean forcerasterpos;                 267   tools_GLboolean forcerasterpos;
268                                                   268 
269   /* BSP-specific */                              269   /* BSP-specific */
270   tools_GLint maxbestroot;                        270   tools_GLint maxbestroot;
271                                                   271 
272   /* Occlusion culling-specific */                272   /* Occlusion culling-specific */
273   tools_GLboolean zerosurfacearea;                273   tools_GLboolean zerosurfacearea;
274   tools_GL2PSbsptree2d *imagetree;                274   tools_GL2PSbsptree2d *imagetree;
275   tools_GL2PSprimitive *primitivetoadd;           275   tools_GL2PSprimitive *primitivetoadd;
276                                                   276 
277   /* PDF-specific */                              277   /* PDF-specific */
278   int streamlength;                               278   int streamlength;
279   tools_GL2PSlist *pdfprimlist, *pdfgrouplist;    279   tools_GL2PSlist *pdfprimlist, *pdfgrouplist;
280   int *xreflist;                                  280   int *xreflist;
281   int objects_stack; /* available objects */      281   int objects_stack; /* available objects */
282   int extgs_stack; /* graphics state object nu    282   int extgs_stack; /* graphics state object number */
283   int font_stack; /* font object number */        283   int font_stack; /* font object number */
284   int im_stack; /* image object number */         284   int im_stack; /* image object number */
285   int trgroupobjects_stack; /* xobject numbers    285   int trgroupobjects_stack; /* xobject numbers */
286   int shader_stack; /* shader object numbers *    286   int shader_stack; /* shader object numbers */
287   int mshader_stack; /* mask shader object num    287   int mshader_stack; /* mask shader object numbers */
288                                                   288 
289   /* for image map list */                        289   /* for image map list */
290   tools_GL2PSimagemap *imagemap_head;             290   tools_GL2PSimagemap *imagemap_head;
291   tools_GL2PSimagemap *imagemap_tail;             291   tools_GL2PSimagemap *imagemap_tail;
292                                                   292 
293   /* for TEX scaling */                           293   /* for TEX scaling */
294   tools_GLfloat tex_scaling;                      294   tools_GLfloat tex_scaling;
295                                                   295 
296   /*G.Barrand : OpenGL functions:*/               296   /*G.Barrand : OpenGL functions:*/
297   tools_gl2ps_gl_funcs_t m_gl_funcs;              297   tools_gl2ps_gl_funcs_t m_gl_funcs;
298 } tools_GL2PScontext;                             298 } tools_GL2PScontext;
299                                                   299 
300 typedef struct {                                  300 typedef struct {
301   void  (*printHeader)(tools_GL2PScontext*);      301   void  (*printHeader)(tools_GL2PScontext*);
302   void  (*printFooter)(tools_GL2PScontext*);      302   void  (*printFooter)(tools_GL2PScontext*);
303   void  (*beginViewport)(tools_GL2PScontext*,t    303   void  (*beginViewport)(tools_GL2PScontext*,tools_GLint viewport[4]);
304   tools_GLint (*endViewport)(tools_GL2PScontex    304   tools_GLint (*endViewport)(tools_GL2PScontext*);
305   void  (*printPrimitive)(tools_GL2PScontext*,    305   void  (*printPrimitive)(tools_GL2PScontext*,void *data);
306   void  (*printFinalPrimitive)(tools_GL2PScont    306   void  (*printFinalPrimitive)(tools_GL2PScontext*);
307   const char *file_extension;                     307   const char *file_extension;
308   const char *description;                        308   const char *description;
309 } tools_GL2PSbackend;                             309 } tools_GL2PSbackend;
310                                                   310 
311 /* The gl2ps context. gl2ps is not thread safe    311 /* The gl2ps context. gl2ps is not thread safe (we should create a
312    local GL2PScontext during tools_gl2psBeginP    312    local GL2PScontext during tools_gl2psBeginPage) */
313                                                   313 
314 //static GL2PScontext *gl2ps = NULL;              314 //static GL2PScontext *gl2ps = NULL;
315                                                   315 
316 /* Need to forward-declare this one */            316 /* Need to forward-declare this one */
317                                                   317 
318 inline tools_GLint tools_gl2psPrintPrimitives(    318 inline tools_GLint tools_gl2psPrintPrimitives(tools_GL2PScontext*);
319                                                   319 
320 /*********************************************    320 /*********************************************************************
321  *                                                321  *
322  * Utility routines                               322  * Utility routines
323  *                                                323  *
324  *********************************************    324  *********************************************************************/
325                                                   325 
326 inline void tools_gl2psMsg(tools_GLint level,     326 inline void tools_gl2psMsg(tools_GLint level, const char *fmt, ...)
327 {                                                 327 {
328   va_list args;                                   328   va_list args;
329                                                   329 
330 /*if(!(gl2ps->options & TOOLS_GL2PS_SILENT))*/    330 /*if(!(gl2ps->options & TOOLS_GL2PS_SILENT))*/{
331     switch(level){                                331     switch(level){
332     case TOOLS_GL2PS_INFO : fprintf(stderr, "G    332     case TOOLS_GL2PS_INFO : fprintf(stderr, "GL2PS info: "); break;
333     case TOOLS_GL2PS_WARNING : fprintf(stderr,    333     case TOOLS_GL2PS_WARNING : fprintf(stderr, "GL2PS warning: "); break;
334     case TOOLS_GL2PS_ERROR : fprintf(stderr, "    334     case TOOLS_GL2PS_ERROR : fprintf(stderr, "GL2PS error: "); break;
335     }                                             335     }
336     va_start(args, fmt);                          336     va_start(args, fmt);
337     vfprintf(stderr, fmt, args);                  337     vfprintf(stderr, fmt, args);
338     va_end(args);                                 338     va_end(args);
339     fprintf(stderr, "\n");                        339     fprintf(stderr, "\n");
340   }                                               340   }
341   /* if(level == TOOLS_GL2PS_ERROR) exit(1); *    341   /* if(level == TOOLS_GL2PS_ERROR) exit(1); */
342 }                                                 342 }
343                                                   343 
344 inline void *tools_gl2psMalloc(size_t size)       344 inline void *tools_gl2psMalloc(size_t size)
345 {                                                 345 {
346   void *ptr;                                      346   void *ptr;
347                                                   347 
348   if(!size) return NULL;                          348   if(!size) return NULL;
349   ptr = malloc(size);                             349   ptr = malloc(size);
350   if(!ptr){                                       350   if(!ptr){
351     tools_gl2psMsg(TOOLS_GL2PS_ERROR, "Couldn'    351     tools_gl2psMsg(TOOLS_GL2PS_ERROR, "Couldn't allocate requested memory");
352     return NULL;                                  352     return NULL;
353   }                                               353   }
354   return ptr;                                     354   return ptr;
355 }                                                 355 }
356                                                   356 
357 inline void *tools_gl2psRealloc(void *ptr, siz    357 inline void *tools_gl2psRealloc(void *ptr, size_t size)
358 {                                                 358 {
359   void *orig = ptr;                               359   void *orig = ptr;
360   if(!size) return NULL;                          360   if(!size) return NULL;
361   ptr = realloc(orig, size);                      361   ptr = realloc(orig, size);
362   if(!ptr){                                       362   if(!ptr){
363     tools_gl2psMsg(TOOLS_GL2PS_ERROR, "Couldn'    363     tools_gl2psMsg(TOOLS_GL2PS_ERROR, "Couldn't reallocate requested memory");
364     free(orig);                                   364     free(orig);
365     return NULL;                                  365     return NULL;
366   }                                               366   }
367   return ptr;                                     367   return ptr;
368 }                                                 368 }
369                                                   369 
370 inline void tools_gl2psFree(void *ptr)            370 inline void tools_gl2psFree(void *ptr)
371 {                                                 371 {
372   if(!ptr) return;                                372   if(!ptr) return;
373   free(ptr);                                      373   free(ptr);
374 }                                                 374 }
375                                                   375 
376 /*G.Barrand: begin*/                              376 /*G.Barrand: begin*/
377 inline tools_GLboolean tools_dummy_glIsEnabled    377 inline tools_GLboolean tools_dummy_glIsEnabled      (tools_GLenum) {return TOOLS_GL_FALSE;}
378 inline void      tools_dummy_glBegin              378 inline void      tools_dummy_glBegin          (tools_GLenum) {
379   /*printf("debug : tools_dummy_glBegin.\n");*    379   /*printf("debug : tools_dummy_glBegin.\n");*/
380 }                                                 380 }
381 inline void      tools_dummy_glEnd                381 inline void      tools_dummy_glEnd            () {}
382 inline void      tools_dummy_glGetFloatv          382 inline void      tools_dummy_glGetFloatv      (tools_GLenum,tools_GLfloat*) {}
383 inline void      tools_dummy_glVertex3f           383 inline void      tools_dummy_glVertex3f       (tools_GLfloat,tools_GLfloat,tools_GLfloat) {}
384 inline void      tools_dummy_glGetBooleanv        384 inline void      tools_dummy_glGetBooleanv    (tools_GLenum,tools_GLboolean*) {}
385 inline void      tools_dummy_glGetIntegerv        385 inline void      tools_dummy_glGetIntegerv    (tools_GLenum,tools_GLint*) {}
386 inline tools_GLint     tools_dummy_glRenderMod    386 inline tools_GLint     tools_dummy_glRenderMode     (tools_GLenum) {
387   /*printf("debug : tools_dummy_glRenderMode.\    387   /*printf("debug : tools_dummy_glRenderMode.\n");*/
388   return 0;                                       388   return 0;
389 }                                                 389 }
390 inline void      tools_dummy_glFeedbackBuffer     390 inline void      tools_dummy_glFeedbackBuffer (tools_GLsizei,tools_GLenum,tools_GLfloat*) {}
391 inline void      tools_dummy_glPassThrough        391 inline void      tools_dummy_glPassThrough    (tools_GLfloat ) {}
392                                                   392 
393 inline tools_GL2PScontext* tools_gl2psCreateCo    393 inline tools_GL2PScontext* tools_gl2psCreateContext(void) {
394   tools_GL2PScontext* gl2ps = (tools_GL2PScont    394   tools_GL2PScontext* gl2ps = (tools_GL2PScontext*)tools_gl2psMalloc(sizeof(tools_GL2PScontext));
395   if(!gl2ps) return 0;                            395   if(!gl2ps) return 0;
396                                                   396 
397   gl2ps->format = 0;                              397   gl2ps->format = 0;
398   gl2ps->sort = 0;                                398   gl2ps->sort = 0;
399   gl2ps->options = 0;                             399   gl2ps->options = 0;
400   gl2ps->colorsize = 0;                           400   gl2ps->colorsize = 0;
401   gl2ps->colormode = 0;                           401   gl2ps->colormode = 0;
402   gl2ps->buffersize = 0;                          402   gl2ps->buffersize = 0;
403   gl2ps->lastlinecap = 0;                         403   gl2ps->lastlinecap = 0;
404   gl2ps->lastlinejoin = 0;                        404   gl2ps->lastlinejoin = 0;
405   gl2ps->title = NULL;                            405   gl2ps->title = NULL;
406   gl2ps->producer = NULL;                         406   gl2ps->producer = NULL;
407   gl2ps->filename = NULL;                         407   gl2ps->filename = NULL;
408   gl2ps->boundary = TOOLS_GL_FALSE;               408   gl2ps->boundary = TOOLS_GL_FALSE;
409   gl2ps->blending = TOOLS_GL_FALSE;               409   gl2ps->blending = TOOLS_GL_FALSE;
410   gl2ps->feedback = NULL;                         410   gl2ps->feedback = NULL;
411   gl2ps->lastlinewidth = 0;                       411   gl2ps->lastlinewidth = 0;
412   gl2ps->viewport[0] = 0;                         412   gl2ps->viewport[0] = 0;
413   gl2ps->viewport[1] = 0;                         413   gl2ps->viewport[1] = 0;
414   gl2ps->viewport[2] = 0;                         414   gl2ps->viewport[2] = 0;
415   gl2ps->viewport[3] = 0;                         415   gl2ps->viewport[3] = 0;
416                                                   416 
417   gl2ps->blendfunc[0] = 0;                        417   gl2ps->blendfunc[0] = 0;
418   gl2ps->blendfunc[1] = 0;                        418   gl2ps->blendfunc[1] = 0;
419                                                   419 
420   gl2ps->lastfactor = 0;                          420   gl2ps->lastfactor = 0;
421   gl2ps->colormap = NULL;                         421   gl2ps->colormap = NULL;
422   gl2ps->lastrgba[0] = 0;                         422   gl2ps->lastrgba[0] = 0;
423   gl2ps->lastrgba[1] = 0;                         423   gl2ps->lastrgba[1] = 0;
424   gl2ps->lastrgba[2] = 0;                         424   gl2ps->lastrgba[2] = 0;
425   gl2ps->lastrgba[3] = 0;                         425   gl2ps->lastrgba[3] = 0;
426   gl2ps->threshold[0] = 0;                        426   gl2ps->threshold[0] = 0;
427   gl2ps->threshold[1] = 0;                        427   gl2ps->threshold[1] = 0;
428   gl2ps->threshold[2] = 0;                        428   gl2ps->threshold[2] = 0;
429   gl2ps->threshold[3] = 0;                        429   gl2ps->threshold[3] = 0;
430   gl2ps->bgcolor[0] = 0;                          430   gl2ps->bgcolor[0] = 0;
431   gl2ps->bgcolor[1] = 0;                          431   gl2ps->bgcolor[1] = 0;
432   gl2ps->bgcolor[2] = 0;                          432   gl2ps->bgcolor[2] = 0;
433   gl2ps->bgcolor[3] = 0;                          433   gl2ps->bgcolor[3] = 0;
434                                                   434   
435   gl2ps->lastpattern = 0;                         435   gl2ps->lastpattern = 0;
436   gl2ps->lastvertex.xyz[0] = 0;                   436   gl2ps->lastvertex.xyz[0] = 0;
437   gl2ps->lastvertex.xyz[1] = 0;                   437   gl2ps->lastvertex.xyz[1] = 0;
438   gl2ps->lastvertex.xyz[2] = 0;                   438   gl2ps->lastvertex.xyz[2] = 0;
439   gl2ps->lastvertex.rgba[0] = 0;                  439   gl2ps->lastvertex.rgba[0] = 0;
440   gl2ps->lastvertex.rgba[1] = 0;                  440   gl2ps->lastvertex.rgba[1] = 0;
441   gl2ps->lastvertex.rgba[2] = 0;                  441   gl2ps->lastvertex.rgba[2] = 0;
442   gl2ps->lastvertex.rgba[3] = 0;                  442   gl2ps->lastvertex.rgba[3] = 0;
443                                                   443   
444   gl2ps->primitives = NULL;                       444   gl2ps->primitives = NULL;
445   gl2ps->auxprimitives = NULL;                    445   gl2ps->auxprimitives = NULL;
446   gl2ps->stream = NULL;                           446   gl2ps->stream = NULL;
447   gl2ps->compress = NULL;                         447   gl2ps->compress = NULL;
448   gl2ps->header = TOOLS_GL_FALSE;                 448   gl2ps->header = TOOLS_GL_FALSE;
449   gl2ps->rasterpos.xyz[0] = 0;                    449   gl2ps->rasterpos.xyz[0] = 0;
450   gl2ps->rasterpos.xyz[1] = 0;                    450   gl2ps->rasterpos.xyz[1] = 0;
451   gl2ps->rasterpos.xyz[2] = 0;                    451   gl2ps->rasterpos.xyz[2] = 0;
452   gl2ps->rasterpos.rgba[0] = 0;                   452   gl2ps->rasterpos.rgba[0] = 0;
453   gl2ps->rasterpos.rgba[1] = 0;                   453   gl2ps->rasterpos.rgba[1] = 0;
454   gl2ps->rasterpos.rgba[2] = 0;                   454   gl2ps->rasterpos.rgba[2] = 0;
455   gl2ps->rasterpos.rgba[3] = 0;                   455   gl2ps->rasterpos.rgba[3] = 0;
456                                                   456   
457   gl2ps->forcerasterpos = TOOLS_GL_FALSE;         457   gl2ps->forcerasterpos = TOOLS_GL_FALSE;
458   gl2ps->maxbestroot = 0;                         458   gl2ps->maxbestroot = 0;
459   gl2ps->zerosurfacearea = TOOLS_GL_FALSE;        459   gl2ps->zerosurfacearea = TOOLS_GL_FALSE;
460   gl2ps->imagetree = NULL;                        460   gl2ps->imagetree = NULL;
461   gl2ps->primitivetoadd = NULL;                   461   gl2ps->primitivetoadd = NULL;
462                                                   462 
463   gl2ps->streamlength = 0;                        463   gl2ps->streamlength = 0;
464   gl2ps->pdfprimlist = NULL;                      464   gl2ps->pdfprimlist = NULL;
465   gl2ps->pdfgrouplist = NULL;                     465   gl2ps->pdfgrouplist = NULL;
466   gl2ps->xreflist = NULL;                         466   gl2ps->xreflist = NULL;
467                                                   467   
468   gl2ps->objects_stack = 0;                       468   gl2ps->objects_stack = 0;
469   gl2ps->extgs_stack = 0;                         469   gl2ps->extgs_stack = 0;
470   gl2ps->font_stack = 0;                          470   gl2ps->font_stack = 0;
471   gl2ps->im_stack = 0;                            471   gl2ps->im_stack = 0;
472   gl2ps->trgroupobjects_stack = 0;                472   gl2ps->trgroupobjects_stack = 0;
473   gl2ps->shader_stack = 0;                        473   gl2ps->shader_stack = 0;
474   gl2ps->mshader_stack = 0;                       474   gl2ps->mshader_stack = 0;
475   gl2ps->imagemap_head = NULL;                    475   gl2ps->imagemap_head = NULL;
476   gl2ps->imagemap_tail = NULL;                    476   gl2ps->imagemap_tail = NULL;
477                                                   477 
478   gl2ps->m_gl_funcs.m_glIsEnabled = tools_dumm    478   gl2ps->m_gl_funcs.m_glIsEnabled = tools_dummy_glIsEnabled;
479   gl2ps->m_gl_funcs.m_glBegin = tools_dummy_gl    479   gl2ps->m_gl_funcs.m_glBegin = tools_dummy_glBegin;
480   gl2ps->m_gl_funcs.m_glEnd = tools_dummy_glEn    480   gl2ps->m_gl_funcs.m_glEnd = tools_dummy_glEnd;
481   gl2ps->m_gl_funcs.m_glGetFloatv = tools_dumm    481   gl2ps->m_gl_funcs.m_glGetFloatv = tools_dummy_glGetFloatv;
482   gl2ps->m_gl_funcs.m_glVertex3f = tools_dummy    482   gl2ps->m_gl_funcs.m_glVertex3f = tools_dummy_glVertex3f;
483   gl2ps->m_gl_funcs.m_glGetBooleanv = tools_du    483   gl2ps->m_gl_funcs.m_glGetBooleanv = tools_dummy_glGetBooleanv;
484   gl2ps->m_gl_funcs.m_glGetIntegerv = tools_du    484   gl2ps->m_gl_funcs.m_glGetIntegerv = tools_dummy_glGetIntegerv;
485   gl2ps->m_gl_funcs.m_glRenderMode = tools_dum    485   gl2ps->m_gl_funcs.m_glRenderMode = tools_dummy_glRenderMode;
486   gl2ps->m_gl_funcs.m_glFeedbackBuffer = tools    486   gl2ps->m_gl_funcs.m_glFeedbackBuffer = tools_dummy_glFeedbackBuffer;
487   gl2ps->m_gl_funcs.m_glPassThrough = tools_du    487   gl2ps->m_gl_funcs.m_glPassThrough = tools_dummy_glPassThrough;
488                                                   488 
489   return gl2ps;                                   489   return gl2ps;
490 }                                                 490 }
491 inline void tools_gl2psDeleteContext(tools_GL2    491 inline void tools_gl2psDeleteContext(tools_GL2PScontext* a_context) {
492   tools_gl2psFree(a_context);                     492   tools_gl2psFree(a_context);
493 }                                                 493 }  
494                                                   494 
495 inline void tools_gl2ps_set_gl_funcs(tools_GL2    495 inline void tools_gl2ps_set_gl_funcs(tools_GL2PScontext* gl2ps, tools_gl2ps_gl_funcs_t* a_funcs) {
496   gl2ps->m_gl_funcs.m_glIsEnabled = a_funcs->m    496   gl2ps->m_gl_funcs.m_glIsEnabled = a_funcs->m_glIsEnabled;
497   gl2ps->m_gl_funcs.m_glBegin = a_funcs->m_glB    497   gl2ps->m_gl_funcs.m_glBegin = a_funcs->m_glBegin;
498   gl2ps->m_gl_funcs.m_glEnd = a_funcs->m_glEnd    498   gl2ps->m_gl_funcs.m_glEnd = a_funcs->m_glEnd;
499   gl2ps->m_gl_funcs.m_glGetFloatv = a_funcs->m    499   gl2ps->m_gl_funcs.m_glGetFloatv = a_funcs->m_glGetFloatv;
500   gl2ps->m_gl_funcs.m_glVertex3f = a_funcs->m_    500   gl2ps->m_gl_funcs.m_glVertex3f = a_funcs->m_glVertex3f;
501   gl2ps->m_gl_funcs.m_glGetBooleanv = a_funcs-    501   gl2ps->m_gl_funcs.m_glGetBooleanv = a_funcs->m_glGetBooleanv;
502   gl2ps->m_gl_funcs.m_glGetIntegerv = a_funcs-    502   gl2ps->m_gl_funcs.m_glGetIntegerv = a_funcs->m_glGetIntegerv;
503   gl2ps->m_gl_funcs.m_glRenderMode = a_funcs->    503   gl2ps->m_gl_funcs.m_glRenderMode = a_funcs->m_glRenderMode;
504   gl2ps->m_gl_funcs.m_glFeedbackBuffer = a_fun    504   gl2ps->m_gl_funcs.m_glFeedbackBuffer = a_funcs->m_glFeedbackBuffer;
505   gl2ps->m_gl_funcs.m_glPassThrough = a_funcs-    505   gl2ps->m_gl_funcs.m_glPassThrough = a_funcs->m_glPassThrough;
506 }                                                 506 }
507                                                   507 
508 inline void tools_gl2ps_reset_gl_funcs(tools_G    508 inline void tools_gl2ps_reset_gl_funcs(tools_GL2PScontext* gl2ps) {
509   gl2ps->m_gl_funcs.m_glIsEnabled = tools_dumm    509   gl2ps->m_gl_funcs.m_glIsEnabled = tools_dummy_glIsEnabled;
510   gl2ps->m_gl_funcs.m_glBegin = tools_dummy_gl    510   gl2ps->m_gl_funcs.m_glBegin = tools_dummy_glBegin;
511   gl2ps->m_gl_funcs.m_glEnd = tools_dummy_glEn    511   gl2ps->m_gl_funcs.m_glEnd = tools_dummy_glEnd;
512   gl2ps->m_gl_funcs.m_glGetFloatv = tools_dumm    512   gl2ps->m_gl_funcs.m_glGetFloatv = tools_dummy_glGetFloatv;
513   gl2ps->m_gl_funcs.m_glVertex3f = tools_dummy    513   gl2ps->m_gl_funcs.m_glVertex3f = tools_dummy_glVertex3f;
514   gl2ps->m_gl_funcs.m_glGetBooleanv = tools_du    514   gl2ps->m_gl_funcs.m_glGetBooleanv = tools_dummy_glGetBooleanv;
515   gl2ps->m_gl_funcs.m_glGetIntegerv = tools_du    515   gl2ps->m_gl_funcs.m_glGetIntegerv = tools_dummy_glGetIntegerv;
516   gl2ps->m_gl_funcs.m_glRenderMode = tools_dum    516   gl2ps->m_gl_funcs.m_glRenderMode = tools_dummy_glRenderMode;
517   gl2ps->m_gl_funcs.m_glFeedbackBuffer = tools    517   gl2ps->m_gl_funcs.m_glFeedbackBuffer = tools_dummy_glFeedbackBuffer;
518   gl2ps->m_gl_funcs.m_glPassThrough = tools_du    518   gl2ps->m_gl_funcs.m_glPassThrough = tools_dummy_glPassThrough;
519 }                                                 519 }
520                                                   520 
521 #define tools_glIsEnabled      gl2ps->m_gl_fun    521 #define tools_glIsEnabled      gl2ps->m_gl_funcs.m_glIsEnabled
522 #define tools_glBegin          gl2ps->m_gl_fun    522 #define tools_glBegin          gl2ps->m_gl_funcs.m_glBegin
523 #define tools_glEnd            gl2ps->m_gl_fun    523 #define tools_glEnd            gl2ps->m_gl_funcs.m_glEnd
524 #define tools_glGetFloatv      gl2ps->m_gl_fun    524 #define tools_glGetFloatv      gl2ps->m_gl_funcs.m_glGetFloatv
525 #define tools_glVertex3f       gl2ps->m_gl_fun    525 #define tools_glVertex3f       gl2ps->m_gl_funcs.m_glVertex3f
526 #define tools_glGetBooleanv    gl2ps->m_gl_fun    526 #define tools_glGetBooleanv    gl2ps->m_gl_funcs.m_glGetBooleanv
527 #define tools_glGetIntegerv    gl2ps->m_gl_fun    527 #define tools_glGetIntegerv    gl2ps->m_gl_funcs.m_glGetIntegerv
528 #define tools_glRenderMode     gl2ps->m_gl_fun    528 #define tools_glRenderMode     gl2ps->m_gl_funcs.m_glRenderMode
529 #define tools_glFeedbackBuffer gl2ps->m_gl_fun    529 #define tools_glFeedbackBuffer gl2ps->m_gl_funcs.m_glFeedbackBuffer
530 #define tools_glPassThrough    gl2ps->m_gl_fun    530 #define tools_glPassThrough    gl2ps->m_gl_funcs.m_glPassThrough
531                                                   531 
532 /*G.Barrand: end*/                                532 /*G.Barrand: end*/
533                                                   533 
534 inline int tools_gl2psWriteBigEndian(tools_GL2    534 inline int tools_gl2psWriteBigEndian(tools_GL2PScontext* gl2ps, unsigned long data, int bytes)
535 {                                                 535 {
536   int i;                                          536   int i;
537   int size = sizeof(unsigned long);               537   int size = sizeof(unsigned long);
538   for(i = 1; i <= bytes; ++i){                    538   for(i = 1; i <= bytes; ++i){
539     fputc(0xff & (data >> (size - i) * 8), gl2    539     fputc(0xff & (data >> (size - i) * 8), gl2ps->stream);
540   }                                               540   }
541   return bytes;                                   541   return bytes;
542 }                                                 542 }
543                                                   543 
544 /* zlib compression helper routines */            544 /* zlib compression helper routines */
545                                                   545 
546 #if defined(TOOLS_GL2PS_HAVE_ZLIB)                546 #if defined(TOOLS_GL2PS_HAVE_ZLIB)
547                                                   547 
548 inline void tools_gl2psSetupCompress(tools_GL2    548 inline void tools_gl2psSetupCompress(tools_GL2PScontext* gl2ps)
549 {                                                 549 {
550   gl2ps->compress = (tools_GL2PScompress*)tool    550   gl2ps->compress = (tools_GL2PScompress*)tools_gl2psMalloc(sizeof(tools_GL2PScompress));
551   gl2ps->compress->src = NULL;                    551   gl2ps->compress->src = NULL;
552   gl2ps->compress->start = NULL;                  552   gl2ps->compress->start = NULL;
553   gl2ps->compress->dest = NULL;                   553   gl2ps->compress->dest = NULL;
554   gl2ps->compress->srcLen = 0;                    554   gl2ps->compress->srcLen = 0;
555   gl2ps->compress->destLen = 0;                   555   gl2ps->compress->destLen = 0;
556 }                                                 556 }
557                                                   557 
558 inline void tools_gl2psFreeCompress(tools_GL2P    558 inline void tools_gl2psFreeCompress(tools_GL2PScontext* gl2ps)
559 {                                                 559 {
560   if(!gl2ps->compress)                            560   if(!gl2ps->compress)
561     return;                                       561     return;
562   tools_gl2psFree(gl2ps->compress->start);        562   tools_gl2psFree(gl2ps->compress->start);
563   tools_gl2psFree(gl2ps->compress->dest);         563   tools_gl2psFree(gl2ps->compress->dest);
564   gl2ps->compress->src = NULL;                    564   gl2ps->compress->src = NULL;
565   gl2ps->compress->start = NULL;                  565   gl2ps->compress->start = NULL;
566   gl2ps->compress->dest = NULL;                   566   gl2ps->compress->dest = NULL;
567   gl2ps->compress->srcLen = 0;                    567   gl2ps->compress->srcLen = 0;
568   gl2ps->compress->destLen = 0;                   568   gl2ps->compress->destLen = 0;
569 }                                                 569 }
570                                                   570 
571 inline int tools_gl2psAllocCompress(tools_GL2P    571 inline int tools_gl2psAllocCompress(tools_GL2PScontext* gl2ps, unsigned int srcsize)
572 {                                                 572 {
573   tools_gl2psFreeCompress(gl2ps);                 573   tools_gl2psFreeCompress(gl2ps);
574                                                   574 
575   if(!gl2ps->compress || !srcsize)                575   if(!gl2ps->compress || !srcsize)
576     return TOOLS_GL2PS_ERROR;                     576     return TOOLS_GL2PS_ERROR;
577                                                   577 
578   gl2ps->compress->srcLen = srcsize;              578   gl2ps->compress->srcLen = srcsize;
579   gl2ps->compress->destLen = (int)ceil(1.001 *    579   gl2ps->compress->destLen = (int)ceil(1.001 * gl2ps->compress->srcLen + 12);
580   gl2ps->compress->src = (Bytef*)tools_gl2psMa    580   gl2ps->compress->src = (Bytef*)tools_gl2psMalloc(gl2ps->compress->srcLen);
581   gl2ps->compress->start = gl2ps->compress->sr    581   gl2ps->compress->start = gl2ps->compress->src;
582   gl2ps->compress->dest = (Bytef*)tools_gl2psM    582   gl2ps->compress->dest = (Bytef*)tools_gl2psMalloc(gl2ps->compress->destLen);
583                                                   583 
584   return TOOLS_GL2PS_SUCCESS;                     584   return TOOLS_GL2PS_SUCCESS;
585 }                                                 585 }
586                                                   586 
587 inline void *tools_gl2psReallocCompress(tools_    587 inline void *tools_gl2psReallocCompress(tools_GL2PScontext* gl2ps, unsigned int srcsize)
588 {                                                 588 {
589   if(!gl2ps->compress || !srcsize)                589   if(!gl2ps->compress || !srcsize)
590     return NULL;                                  590     return NULL;
591                                                   591 
592   if(srcsize < gl2ps->compress->srcLen)           592   if(srcsize < gl2ps->compress->srcLen)
593     return gl2ps->compress->start;                593     return gl2ps->compress->start;
594                                                   594 
595   gl2ps->compress->srcLen = srcsize;              595   gl2ps->compress->srcLen = srcsize;
596   gl2ps->compress->destLen = (int)ceil(1.001 *    596   gl2ps->compress->destLen = (int)ceil(1.001 * gl2ps->compress->srcLen + 12);
597   gl2ps->compress->src = (Bytef*)tools_gl2psRe    597   gl2ps->compress->src = (Bytef*)tools_gl2psRealloc(gl2ps->compress->src,
598                                                   598                                               gl2ps->compress->srcLen);
599   gl2ps->compress->start = gl2ps->compress->sr    599   gl2ps->compress->start = gl2ps->compress->src;
600   gl2ps->compress->dest = (Bytef*)tools_gl2psR    600   gl2ps->compress->dest = (Bytef*)tools_gl2psRealloc(gl2ps->compress->dest,
601                                                   601                                                gl2ps->compress->destLen);
602                                                   602 
603   return gl2ps->compress->start;                  603   return gl2ps->compress->start;
604 }                                                 604 }
605                                                   605 
606 inline int tools_gl2psWriteBigEndianCompress(t    606 inline int tools_gl2psWriteBigEndianCompress(tools_GL2PScontext* gl2ps, unsigned long data, int bytes)
607 {                                                 607 {
608   int i;                                          608   int i;
609   int size = sizeof(unsigned long);               609   int size = sizeof(unsigned long);
610   for(i = 1; i <= bytes; ++i){                    610   for(i = 1; i <= bytes; ++i){
611     *gl2ps->compress->src = (Bytef)(0xff & (da    611     *gl2ps->compress->src = (Bytef)(0xff & (data >> (size-i) * 8));
612     ++gl2ps->compress->src;                       612     ++gl2ps->compress->src;
613   }                                               613   }
614   return bytes;                                   614   return bytes;
615 }                                                 615 }
616                                                   616 
617 inline int tools_gl2psDeflate(tools_GL2PSconte    617 inline int tools_gl2psDeflate(tools_GL2PScontext* gl2ps)
618 {                                                 618 {
619   /* For compatibility with older zlib version    619   /* For compatibility with older zlib versions, we use compress(...)
620      instead of compress2(..., Z_BEST_COMPRESS    620      instead of compress2(..., Z_BEST_COMPRESSION) */
621   return compress(gl2ps->compress->dest, &gl2p    621   return compress(gl2ps->compress->dest, &gl2ps->compress->destLen,
622                   gl2ps->compress->start, gl2p    622                   gl2ps->compress->start, gl2ps->compress->srcLen);
623 }                                                 623 }
624                                                   624 
625 #endif                                            625 #endif
626                                                   626 
627 inline int tools_gl2psPrintf(tools_GL2PScontex    627 inline int tools_gl2psPrintf(tools_GL2PScontext* gl2ps, const char* fmt, ...)
628 {                                                 628 {
629   int ret;                                        629   int ret;
630   va_list args;                                   630   va_list args;
631                                                   631 
632 #if defined(TOOLS_GL2PS_HAVE_ZLIB)                632 #if defined(TOOLS_GL2PS_HAVE_ZLIB)
633 //static char buf[1024]; //G.Barrand: avoid th    633 //static char buf[1024]; //G.Barrand: avoid this writeable static.
634 //char *bufptr = buf;                             634 //char *bufptr = buf;
635 //tools_GLboolean freebuf = TOOLS_GL_FALSE;       635 //tools_GLboolean freebuf = TOOLS_GL_FALSE;
636   char* bufptr = (char *)tools_gl2psMalloc(102    636   char* bufptr = (char *)tools_gl2psMalloc(1024);
637   tools_GLboolean freebuf = TOOLS_GL_TRUE;        637   tools_GLboolean freebuf = TOOLS_GL_TRUE;
638   unsigned int oldsize = 0;                       638   unsigned int oldsize = 0;
639 #if !defined(TOOLS_GL2PS_HAVE_NO_VSNPRINTF)       639 #if !defined(TOOLS_GL2PS_HAVE_NO_VSNPRINTF)
640   /* Try writing the string to a 1024 byte buf    640   /* Try writing the string to a 1024 byte buffer. If it is too small to fit,
641      keep trying larger sizes until it does. *    641      keep trying larger sizes until it does. */
642 //int bufsize = sizeof(buf);                      642 //int bufsize = sizeof(buf);
643   int bufsize = 1024;                             643   int bufsize = 1024;
644 #endif                                            644 #endif
645   if(gl2ps->options & TOOLS_GL2PS_COMPRESS){      645   if(gl2ps->options & TOOLS_GL2PS_COMPRESS){
646     va_start(args, fmt);                          646     va_start(args, fmt);
647 #if defined(TOOLS_GL2PS_HAVE_NO_VSNPRINTF)        647 #if defined(TOOLS_GL2PS_HAVE_NO_VSNPRINTF)
648     ret = vsprintf(buf, fmt, args);               648     ret = vsprintf(buf, fmt, args);
649 #else                                             649 #else
650     ret = vsnprintf(bufptr, bufsize, fmt, args    650     ret = vsnprintf(bufptr, bufsize, fmt, args);
651 #endif                                            651 #endif
652     va_end(args);                                 652     va_end(args);
653 #if !defined(TOOLS_GL2PS_HAVE_NO_VSNPRINTF)       653 #if !defined(TOOLS_GL2PS_HAVE_NO_VSNPRINTF)
654     while(ret >= (bufsize - 1) || ret < 0){       654     while(ret >= (bufsize - 1) || ret < 0){
655       /* Too big. Allocate a new buffer. */       655       /* Too big. Allocate a new buffer. */
656       bufsize *= 2;                               656       bufsize *= 2;
657       if(freebuf == TOOLS_GL_TRUE) tools_gl2ps    657       if(freebuf == TOOLS_GL_TRUE) tools_gl2psFree(bufptr);
658       bufptr = (char *)tools_gl2psMalloc(bufsi    658       bufptr = (char *)tools_gl2psMalloc(bufsize);
659       freebuf = TOOLS_GL_TRUE;                    659       freebuf = TOOLS_GL_TRUE;
660       va_start(args, fmt);                        660       va_start(args, fmt);
661       ret = vsnprintf(bufptr, bufsize, fmt, ar    661       ret = vsnprintf(bufptr, bufsize, fmt, args);
662       va_end(args);                               662       va_end(args);
663     }                                             663     }
664 #endif                                            664 #endif
665     oldsize = gl2ps->compress->srcLen;            665     oldsize = gl2ps->compress->srcLen;
666     gl2ps->compress->start = (Bytef*)tools_gl2    666     gl2ps->compress->start = (Bytef*)tools_gl2psReallocCompress(gl2ps, oldsize + ret);
667     memcpy(gl2ps->compress->start + oldsize, b    667     memcpy(gl2ps->compress->start + oldsize, bufptr, ret);
668     if(freebuf == TOOLS_GL_TRUE) tools_gl2psFr    668     if(freebuf == TOOLS_GL_TRUE) tools_gl2psFree(bufptr);
669     ret = 0;                                      669     ret = 0;
670   }                                               670   }
671   else{                                           671   else{
672 #endif                                            672 #endif
673     va_start(args, fmt);                          673     va_start(args, fmt);
674     ret = vfprintf(gl2ps->stream, fmt, args);     674     ret = vfprintf(gl2ps->stream, fmt, args);
675     va_end(args);                                 675     va_end(args);
676 #if defined(TOOLS_GL2PS_HAVE_ZLIB)                676 #if defined(TOOLS_GL2PS_HAVE_ZLIB)
677   }                                               677   }
678 #endif                                            678 #endif
679   return ret;                                     679   return ret;
680 }                                                 680 }
681                                                   681 
682 inline void tools_gl2psPrintGzipHeader(tools_G    682 inline void tools_gl2psPrintGzipHeader(tools_GL2PScontext* gl2ps)
683 {                                                 683 {
684 #if defined(TOOLS_GL2PS_HAVE_ZLIB)                684 #if defined(TOOLS_GL2PS_HAVE_ZLIB)
685   char tmp[10] = {'\x1f', '\x8b', /* magic num    685   char tmp[10] = {'\x1f', '\x8b', /* magic numbers: 0x1f, 0x8b */
686                   8, /* compression method: Z_    686                   8, /* compression method: Z_DEFLATED */
687                   0, /* flags */                  687                   0, /* flags */
688                   0, 0, 0, 0, /* time */          688                   0, 0, 0, 0, /* time */
689                   2, /* extra flags: max compr    689                   2, /* extra flags: max compression */
690                   '\x03'}; /* OS code: 0x03 (U    690                   '\x03'}; /* OS code: 0x03 (Unix) */
691                                                   691 
692   if(gl2ps->options & TOOLS_GL2PS_COMPRESS){      692   if(gl2ps->options & TOOLS_GL2PS_COMPRESS){
693     tools_gl2psSetupCompress(gl2ps);              693     tools_gl2psSetupCompress(gl2ps);
694     /* add the gzip file header */                694     /* add the gzip file header */
695     fwrite(tmp, 10, 1, gl2ps->stream);            695     fwrite(tmp, 10, 1, gl2ps->stream);
696   }                                               696   }
697 #endif                                            697 #endif
698   (void)gl2ps;                                    698   (void)gl2ps;
699 }                                                 699 }
700                                                   700 
701 inline void tools_gl2psPrintGzipFooter(tools_G    701 inline void tools_gl2psPrintGzipFooter(tools_GL2PScontext* gl2ps)
702 {                                                 702 {
703 #if defined(TOOLS_GL2PS_HAVE_ZLIB)                703 #if defined(TOOLS_GL2PS_HAVE_ZLIB)
704   int n;                                          704   int n;
705   uLong crc, len;                                 705   uLong crc, len;
706   char tmp[8];                                    706   char tmp[8];
707                                                   707 
708   if(gl2ps->options & TOOLS_GL2PS_COMPRESS){      708   if(gl2ps->options & TOOLS_GL2PS_COMPRESS){
709     if(Z_OK != tools_gl2psDeflate(gl2ps)){        709     if(Z_OK != tools_gl2psDeflate(gl2ps)){
710       tools_gl2psMsg(TOOLS_GL2PS_ERROR, "Zlib     710       tools_gl2psMsg(TOOLS_GL2PS_ERROR, "Zlib deflate error");
711     }                                             711     }
712     else{                                         712     else{
713       /* determine the length of the header in    713       /* determine the length of the header in the zlib stream */
714       n = 2; /* CMF+FLG */                        714       n = 2; /* CMF+FLG */
715       if(gl2ps->compress->dest[1] & (1<<5)){      715       if(gl2ps->compress->dest[1] & (1<<5)){
716         n += 4; /* DICTID */                      716         n += 4; /* DICTID */
717       }                                           717       }
718       /* write the data, without the zlib head    718       /* write the data, without the zlib header and footer */
719       fwrite(gl2ps->compress->dest+n, gl2ps->c    719       fwrite(gl2ps->compress->dest+n, gl2ps->compress->destLen-(n+4),
720              1, gl2ps->stream);                   720              1, gl2ps->stream);
721       /* add the gzip file footer */              721       /* add the gzip file footer */
722       crc = crc32(0L, gl2ps->compress->start,     722       crc = crc32(0L, gl2ps->compress->start, gl2ps->compress->srcLen);
723       for(n = 0; n < 4; ++n){                     723       for(n = 0; n < 4; ++n){
724         tmp[n] = (char)(crc & 0xff);              724         tmp[n] = (char)(crc & 0xff);
725         crc >>= 8;                                725         crc >>= 8;
726       }                                           726       }
727       len = gl2ps->compress->srcLen;              727       len = gl2ps->compress->srcLen;
728       for(n = 4; n < 8; ++n){                     728       for(n = 4; n < 8; ++n){
729         tmp[n] = (char)(len & 0xff);              729         tmp[n] = (char)(len & 0xff);
730         len >>= 8;                                730         len >>= 8;
731       }                                           731       }
732       fwrite(tmp, 8, 1, gl2ps->stream);           732       fwrite(tmp, 8, 1, gl2ps->stream);
733     }                                             733     }
734     tools_gl2psFreeCompress(gl2ps);               734     tools_gl2psFreeCompress(gl2ps);
735     tools_gl2psFree(gl2ps->compress);             735     tools_gl2psFree(gl2ps->compress);
736     gl2ps->compress = NULL;                       736     gl2ps->compress = NULL;
737   }                                               737   }
738 #endif                                            738 #endif
739   (void)gl2ps;                                    739   (void)gl2ps;
740 }                                                 740 }
741                                                   741 
742 /* The list handling routines */                  742 /* The list handling routines */
743                                                   743 
744 inline void tools_gl2psListRealloc(tools_GL2PS    744 inline void tools_gl2psListRealloc(tools_GL2PSlist *list, tools_GLint n)
745 {                                                 745 {
746   if(!list){                                      746   if(!list){
747     tools_gl2psMsg(TOOLS_GL2PS_ERROR, "Cannot     747     tools_gl2psMsg(TOOLS_GL2PS_ERROR, "Cannot reallocate NULL list");
748     return;                                       748     return;
749   }                                               749   }
750   if(n <= 0) return;                              750   if(n <= 0) return;
751   if(!list->array){                               751   if(!list->array){
752     list->nmax = n;                               752     list->nmax = n;
753     list->array = (char*)tools_gl2psMalloc(lis    753     list->array = (char*)tools_gl2psMalloc(list->nmax * list->size);
754   }                                               754   }
755   else{                                           755   else{
756     if(n > list->nmax){                           756     if(n > list->nmax){
757       list->nmax = ((n - 1) / list->incr + 1)     757       list->nmax = ((n - 1) / list->incr + 1) * list->incr;
758       list->array = (char*)tools_gl2psRealloc(    758       list->array = (char*)tools_gl2psRealloc(list->array,
759                                         list->    759                                         list->nmax * list->size);
760     }                                             760     }
761   }                                               761   }
762 }                                                 762 }
763                                                   763 
764 inline tools_GL2PSlist *tools_gl2psListCreate(    764 inline tools_GL2PSlist *tools_gl2psListCreate(tools_GLint n, tools_GLint incr, tools_GLint size)
765 {                                                 765 {
766   tools_GL2PSlist *list;                          766   tools_GL2PSlist *list;
767                                                   767 
768   if(n < 0) n = 0;                                768   if(n < 0) n = 0;
769   if(incr <= 0) incr = 1;                         769   if(incr <= 0) incr = 1;
770   list = (tools_GL2PSlist*)tools_gl2psMalloc(s    770   list = (tools_GL2PSlist*)tools_gl2psMalloc(sizeof(tools_GL2PSlist));
771   list->nmax = 0;                                 771   list->nmax = 0;
772   list->incr = incr;                              772   list->incr = incr;
773   list->size = size;                              773   list->size = size;
774   list->n = 0;                                    774   list->n = 0;
775   list->array = NULL;                             775   list->array = NULL;
776   tools_gl2psListRealloc(list, n);                776   tools_gl2psListRealloc(list, n);
777   return list;                                    777   return list;
778 }                                                 778 }
779                                                   779 
780 inline void tools_gl2psListReset(tools_GL2PSli    780 inline void tools_gl2psListReset(tools_GL2PSlist *list)
781 {                                                 781 {
782   if(!list) return;                               782   if(!list) return;
783   list->n = 0;                                    783   list->n = 0;
784 }                                                 784 }
785                                                   785 
786 inline void tools_gl2psListDelete(tools_GL2PSl    786 inline void tools_gl2psListDelete(tools_GL2PSlist *list)
787 {                                                 787 {
788   if(!list) return;                               788   if(!list) return;
789   tools_gl2psFree(list->array);                   789   tools_gl2psFree(list->array);
790   tools_gl2psFree(list);                          790   tools_gl2psFree(list);
791 }                                                 791 }
792                                                   792 
793 inline void tools_gl2psListAdd(tools_GL2PSlist    793 inline void tools_gl2psListAdd(tools_GL2PSlist *list, void *data)
794 {                                                 794 {
795   if(!list){                                      795   if(!list){
796     tools_gl2psMsg(TOOLS_GL2PS_ERROR, "Cannot     796     tools_gl2psMsg(TOOLS_GL2PS_ERROR, "Cannot add into unallocated list");
797     return;                                       797     return;
798   }                                               798   }
799   list->n++;                                      799   list->n++;
800   tools_gl2psListRealloc(list, list->n);          800   tools_gl2psListRealloc(list, list->n);
801   memcpy(&list->array[(list->n - 1) * list->si    801   memcpy(&list->array[(list->n - 1) * list->size], data, list->size);
802 }                                                 802 }
803                                                   803 
804 inline int tools_gl2psListNbr(tools_GL2PSlist     804 inline int tools_gl2psListNbr(tools_GL2PSlist *list)
805 {                                                 805 {
806   if(!list)                                       806   if(!list)
807     return 0;                                     807     return 0;
808   return list->n;                                 808   return list->n;
809 }                                                 809 }
810                                                   810 
811 inline void *tools_gl2psListPointer(tools_GL2P    811 inline void *tools_gl2psListPointer(tools_GL2PSlist *list, tools_GLint idx)
812 {                                                 812 {
813   if(!list){                                      813   if(!list){
814     tools_gl2psMsg(TOOLS_GL2PS_ERROR, "Cannot     814     tools_gl2psMsg(TOOLS_GL2PS_ERROR, "Cannot point into unallocated list");
815     return NULL;                                  815     return NULL;
816   }                                               816   }
817   if((idx < 0) || (idx >= list->n)){              817   if((idx < 0) || (idx >= list->n)){
818     tools_gl2psMsg(TOOLS_GL2PS_ERROR, "Wrong l    818     tools_gl2psMsg(TOOLS_GL2PS_ERROR, "Wrong list index in tools_gl2psListPointer");
819     return NULL;                                  819     return NULL;
820   }                                               820   }
821   return &list->array[idx * list->size];          821   return &list->array[idx * list->size];
822 }                                                 822 }
823                                                   823 
824 //G.Barrand: begin:                               824 //G.Barrand: begin:
825 inline bool tools_gl2psPortableSort(void* a_it    825 inline bool tools_gl2psPortableSort(void* a_items,size_t a_nitem,size_t a_item_size,int(*a_cmp)(const void*,const void*)) {
826   //  We observed that qsort on macOS/clang, L    826   //  We observed that qsort on macOS/clang, Linux/gcc, Windows/VisualC++
827   // does not produce the same output list for    827   // does not produce the same output list for objects considered as "the same".
828   // "Same objects" are put correctly contiguo    828   // "Same objects" are put correctly contiguously but not in the same order
829   // according the platform. In case of gl2ps,    829   // according the platform. In case of gl2ps, if using qsort we have, at end,
830   // primitives in the output file which are n    830   // primitives in the output file which are not in the same order according the platform.
831   // Then, we let the possibility to use a por    831   // Then, we let the possibility to use a portable sort algorithm that will
832   // give the same sorted list, and then the s    832   // give the same sorted list, and then the same output file, on all platforms.
833   if(a_nitem<=1) return true;                     833   if(a_nitem<=1) return true;
834   if(!a_item_size) return true;                   834   if(!a_item_size) return true;
835   void* tmp = ::malloc(a_item_size);              835   void* tmp = ::malloc(a_item_size);
836   if(!tmp) return false;                          836   if(!tmp) return false;
837   char* p = (char*)a_items;                       837   char* p = (char*)a_items;
838   size_t i,j;                                     838   size_t i,j;
839   char* a = p;char* b;                            839   char* a = p;char* b;
840   for(i=0;i<a_nitem;i++,a+=a_item_size) {         840   for(i=0;i<a_nitem;i++,a+=a_item_size) {
841     b = p+a_item_size*(i+1);                      841     b = p+a_item_size*(i+1);
842     for(j=i+1;j<a_nitem;j++,b+=a_item_size) {     842     for(j=i+1;j<a_nitem;j++,b+=a_item_size) {
843       if(a_cmp(b,a)>=0) continue;  //b>=a         843       if(a_cmp(b,a)>=0) continue;  //b>=a
844       ::memcpy(tmp,a,a_item_size);                844       ::memcpy(tmp,a,a_item_size);
845       ::memcpy(a,b,a_item_size);                  845       ::memcpy(a,b,a_item_size);
846       ::memcpy(b,tmp,a_item_size);                846       ::memcpy(b,tmp,a_item_size);
847     }                                             847     }
848   }                                               848   }
849   ::free(tmp);                                    849   ::free(tmp);
850   return true;                                    850   return true;
851 }                                                 851 }
852 //G.Barrand: end.                                 852 //G.Barrand: end.
853                                                   853 
854 inline void tools_gl2psListSort(tools_GL2PScon    854 inline void tools_gl2psListSort(tools_GL2PScontext* gl2ps,
855                                 tools_GL2PSlis    855                                 tools_GL2PSlist *list,
856                                 int (*fcmp)(co    856                                 int (*fcmp)(const void *a, const void *b))
857 {                                                 857 {
858   if(!list) return;                               858   if(!list) return;
859   if(gl2ps->options & TOOLS_GL2PS_PORTABLE_SOR    859   if(gl2ps->options & TOOLS_GL2PS_PORTABLE_SORT) {
860     tools_gl2psPortableSort(list->array, list-    860     tools_gl2psPortableSort(list->array, list->n, list->size, fcmp);
861   } else {                                        861   } else {
862     ::qsort(list->array, list->n, list->size,     862     ::qsort(list->array, list->n, list->size, fcmp);
863   }                                               863   }
864 }                                                 864 }
865                                                   865 
866 /* Must be a list of tools_GL2PSprimitives. */    866 /* Must be a list of tools_GL2PSprimitives. */
867 inline void tools_gl2psListAssignSortIds(tools    867 inline void tools_gl2psListAssignSortIds(tools_GL2PSlist *list)
868 {                                                 868 {
869   tools_GLint i;                                  869   tools_GLint i;
870   for(i = 0; i < tools_gl2psListNbr(list); i++    870   for(i = 0; i < tools_gl2psListNbr(list); i++){
871     (*(tools_GL2PSprimitive**)tools_gl2psListP    871     (*(tools_GL2PSprimitive**)tools_gl2psListPointer(list, i))->sortid = i;
872   }                                               872   }
873 }                                                 873 }
874                                                   874 
875 inline void tools_gl2psListAction(tools_GL2PSl    875 inline void tools_gl2psListAction(tools_GL2PSlist *list, void (*action)(void *data))
876 {                                                 876 {
877   tools_GLint i;                                  877   tools_GLint i;
878                                                   878 
879   for(i = 0; i < tools_gl2psListNbr(list); i++    879   for(i = 0; i < tools_gl2psListNbr(list); i++){
880     (*action)(tools_gl2psListPointer(list, i))    880     (*action)(tools_gl2psListPointer(list, i));
881   }                                               881   }
882 }                                                 882 }
883                                                   883 
884 inline void tools_gl2psListActionInverse(tools    884 inline void tools_gl2psListActionInverse(tools_GL2PSlist *list, void (*action)(void *data))
885 {                                                 885 {
886   tools_GLint i;                                  886   tools_GLint i;
887                                                   887 
888   for(i = tools_gl2psListNbr(list); i > 0; i--    888   for(i = tools_gl2psListNbr(list); i > 0; i--){
889     (*action)(tools_gl2psListPointer(list, i-1    889     (*action)(tools_gl2psListPointer(list, i-1));
890   }                                               890   }
891 }                                                 891 }
892                                                   892 
893 inline void tools_gl2psListActionContext(tools    893 inline void tools_gl2psListActionContext(tools_GL2PScontext* gl2ps, tools_GL2PSlist *list, void (*action)(tools_GL2PScontext*, void *data))
894 {                                                 894 {
895   tools_GLint i;                                  895   tools_GLint i;
896                                                   896 
897   for(i = 0; i < tools_gl2psListNbr(list); i++    897   for(i = 0; i < tools_gl2psListNbr(list); i++){
898     (*action)(gl2ps, tools_gl2psListPointer(li    898     (*action)(gl2ps, tools_gl2psListPointer(list, i));
899   }                                               899   }
900 }                                                 900 }
901                                                   901 
902 inline void tools_gl2psListActionInverseContex    902 inline void tools_gl2psListActionInverseContext(tools_GL2PScontext* gl2ps, tools_GL2PSlist *list, void (*action)(tools_GL2PScontext*, void *data))
903 {                                                 903 {
904   tools_GLint i;                                  904   tools_GLint i;
905                                                   905 
906   for(i = tools_gl2psListNbr(list); i > 0; i--    906   for(i = tools_gl2psListNbr(list); i > 0; i--){
907     (*action)(gl2ps, tools_gl2psListPointer(li    907     (*action)(gl2ps, tools_gl2psListPointer(list, i-1));
908   }                                               908   }
909 }                                                 909 }
910                                                   910 
911 #if defined(TOOLS_GL2PS_HAVE_LIBPNG)              911 #if defined(TOOLS_GL2PS_HAVE_LIBPNG)
912                                                   912 
913 inline void tools_gl2psListRead(tools_GL2PSlis    913 inline void tools_gl2psListRead(tools_GL2PSlist *list, int index, void *data)
914 {                                                 914 {
915   if((index < 0) || (index >= list->n))           915   if((index < 0) || (index >= list->n))
916     tools_gl2psMsg(TOOLS_GL2PS_ERROR, "Wrong l    916     tools_gl2psMsg(TOOLS_GL2PS_ERROR, "Wrong list index in tools_gl2psListRead");
917   memcpy(data, &list->array[index * list->size    917   memcpy(data, &list->array[index * list->size], list->size);
918 }                                                 918 }
919                                                   919 
920 inline void tools_gl2psEncodeBase64Block(unsig    920 inline void tools_gl2psEncodeBase64Block(unsigned char in[3], unsigned char out[4], int len)
921 {                                                 921 {
922   static const char cb64[] =                      922   static const char cb64[] =
923     "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmno    923     "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
924                                                   924 
925   out[0] = cb64[ in[0] >> 2 ];                    925   out[0] = cb64[ in[0] >> 2 ];
926   out[1] = cb64[ ((in[0] & 0x03) << 4) | ((in[    926   out[1] = cb64[ ((in[0] & 0x03) << 4) | ((in[1] & 0xf0) >> 4) ];
927   out[2] = (len > 1) ? cb64[ ((in[1] & 0x0f) <    927   out[2] = (len > 1) ? cb64[ ((in[1] & 0x0f) << 2) | ((in[2] & 0xc0) >> 6) ] : '=';
928   out[3] = (len > 2) ? cb64[ in[2] & 0x3f ] :     928   out[3] = (len > 2) ? cb64[ in[2] & 0x3f ] : '=';
929 }                                                 929 }
930                                                   930 
931 inline void tools_gl2psListEncodeBase64(tools_    931 inline void tools_gl2psListEncodeBase64(tools_GL2PSlist *list)
932 {                                                 932 {
933   unsigned char *buffer, in[3], out[4];           933   unsigned char *buffer, in[3], out[4];
934   int i, n, index, len;                           934   int i, n, index, len;
935                                                   935 
936   n = list->n * list->size;                       936   n = list->n * list->size;
937   buffer = (unsigned char*)tools_gl2psMalloc(n    937   buffer = (unsigned char*)tools_gl2psMalloc(n * sizeof(unsigned char));
938   memcpy(buffer, list->array, n * sizeof(unsig    938   memcpy(buffer, list->array, n * sizeof(unsigned char));
939   tools_gl2psListReset(list);                     939   tools_gl2psListReset(list);
940                                                   940 
941   index = 0;                                      941   index = 0;
942   while(index < n) {                              942   while(index < n) {
943     len = 0;                                      943     len = 0;
944     for(i = 0; i < 3; i++) {                      944     for(i = 0; i < 3; i++) {
945       if(index < n){                              945       if(index < n){
946         in[i] = buffer[index];                    946         in[i] = buffer[index];
947         len++;                                    947         len++;
948       }                                           948       }
949       else{                                       949       else{
950         in[i] = 0;                                950         in[i] = 0;
951       }                                           951       }
952       index++;                                    952       index++;
953     }                                             953     }
954     if(len) {                                     954     if(len) {
955       tools_gl2psEncodeBase64Block(in, out, le    955       tools_gl2psEncodeBase64Block(in, out, len);
956       for(i = 0; i < 4; i++)                      956       for(i = 0; i < 4; i++)
957         tools_gl2psListAdd(list, &out[i]);        957         tools_gl2psListAdd(list, &out[i]);
958     }                                             958     }
959   }                                               959   }
960   tools_gl2psFree(buffer);                        960   tools_gl2psFree(buffer);
961 }                                                 961 }
962                                                   962 
963 #endif                                            963 #endif
964                                                   964 
965 /* Helpers for rgba colors */                     965 /* Helpers for rgba colors */
966                                                   966 
967 inline tools_GLboolean tools_gl2psSameColor(to    967 inline tools_GLboolean tools_gl2psSameColor(tools_GL2PSrgba rgba1, tools_GL2PSrgba rgba2)
968 {                                                 968 {
969   if(!TOOLS_GL2PS_ZERO(rgba1[0] - rgba2[0]) ||    969   if(!TOOLS_GL2PS_ZERO(rgba1[0] - rgba2[0]) ||
970      !TOOLS_GL2PS_ZERO(rgba1[1] - rgba2[1]) ||    970      !TOOLS_GL2PS_ZERO(rgba1[1] - rgba2[1]) ||
971      !TOOLS_GL2PS_ZERO(rgba1[2] - rgba2[2]))      971      !TOOLS_GL2PS_ZERO(rgba1[2] - rgba2[2]))
972     return TOOLS_GL_FALSE;                        972     return TOOLS_GL_FALSE;
973   return TOOLS_GL_TRUE;                           973   return TOOLS_GL_TRUE;
974 }                                                 974 }
975                                                   975 
976 inline tools_GLboolean tools_gl2psVertsSameCol    976 inline tools_GLboolean tools_gl2psVertsSameColor(const tools_GL2PSprimitive *prim)
977 {                                                 977 {
978   int i;                                          978   int i;
979                                                   979 
980   for(i = 1; i < prim->numverts; i++){            980   for(i = 1; i < prim->numverts; i++){
981     if(!tools_gl2psSameColor(prim->verts[0].rg    981     if(!tools_gl2psSameColor(prim->verts[0].rgba, prim->verts[i].rgba)){
982       return TOOLS_GL_FALSE;                      982       return TOOLS_GL_FALSE;
983     }                                             983     }
984   }                                               984   }
985   return TOOLS_GL_TRUE;                           985   return TOOLS_GL_TRUE;
986 }                                                 986 }
987                                                   987 
988 inline tools_GLboolean tools_gl2psSameColorThr    988 inline tools_GLboolean tools_gl2psSameColorThreshold(int n, tools_GL2PSrgba rgba[],
989                                          tools    989                                          tools_GL2PSrgba threshold)
990 {                                                 990 {
991   int i;                                          991   int i;
992                                                   992 
993   if(n < 2) return TOOLS_GL_TRUE;                 993   if(n < 2) return TOOLS_GL_TRUE;
994                                                   994 
995   for(i = 1; i < n; i++){                         995   for(i = 1; i < n; i++){
996     if(fabs(rgba[0][0] - rgba[i][0]) > thresho    996     if(fabs(rgba[0][0] - rgba[i][0]) > threshold[0] ||
997        fabs(rgba[0][1] - rgba[i][1]) > thresho    997        fabs(rgba[0][1] - rgba[i][1]) > threshold[1] ||
998        fabs(rgba[0][2] - rgba[i][2]) > thresho    998        fabs(rgba[0][2] - rgba[i][2]) > threshold[2])
999       return TOOLS_GL_FALSE;                      999       return TOOLS_GL_FALSE;
1000   }                                              1000   }
1001                                                  1001 
1002   return TOOLS_GL_TRUE;                          1002   return TOOLS_GL_TRUE;
1003 }                                                1003 }
1004                                                  1004 
1005 inline void tools_gl2psSetLastColor(tools_GL2    1005 inline void tools_gl2psSetLastColor(tools_GL2PScontext* gl2ps, tools_GL2PSrgba rgba)
1006 {                                                1006 {
1007   int i;                                         1007   int i;
1008   for(i = 0; i < 3; ++i){                        1008   for(i = 0; i < 3; ++i){
1009     gl2ps->lastrgba[i] = rgba[i];                1009     gl2ps->lastrgba[i] = rgba[i];
1010   }                                              1010   }
1011 }                                                1011 }
1012                                                  1012 
1013 inline tools_GLfloat tools_gl2psGetRGB(tools_    1013 inline tools_GLfloat tools_gl2psGetRGB(tools_GL2PSimage *im, tools_GLuint x, tools_GLuint y,
1014                            tools_GLfloat *red    1014                            tools_GLfloat *red, tools_GLfloat *green, tools_GLfloat *blue)
1015 {                                                1015 {
1016                                                  1016 
1017   tools_GLsizei width = im->width;               1017   tools_GLsizei width = im->width;
1018   tools_GLsizei height = im->height;             1018   tools_GLsizei height = im->height;
1019   tools_GLfloat *pixels = im->pixels;            1019   tools_GLfloat *pixels = im->pixels;
1020   tools_GLfloat *pimag;                          1020   tools_GLfloat *pimag;
1021                                                  1021 
1022   /* OpenGL image is from down to up, PS imag    1022   /* OpenGL image is from down to up, PS image is up to down */
1023   switch(im->format){                            1023   switch(im->format){
1024   case TOOLS_GL_RGBA:                            1024   case TOOLS_GL_RGBA:
1025     pimag = pixels + 4 * (width * (height - 1    1025     pimag = pixels + 4 * (width * (height - 1 - y) + x);
1026     break;                                       1026     break;
1027   case TOOLS_GL_RGB:                             1027   case TOOLS_GL_RGB:
1028   default:                                       1028   default:
1029     pimag = pixels + 3 * (width * (height - 1    1029     pimag = pixels + 3 * (width * (height - 1 - y) + x);
1030     break;                                       1030     break;
1031   }                                              1031   }
1032   *red = *pimag; pimag++;                        1032   *red = *pimag; pimag++;
1033   *green = *pimag; pimag++;                      1033   *green = *pimag; pimag++;
1034   *blue = *pimag; pimag++;                       1034   *blue = *pimag; pimag++;
1035                                                  1035 
1036   return (im->format == TOOLS_GL_RGBA) ? *pim    1036   return (im->format == TOOLS_GL_RGBA) ? *pimag : 1.0F;
1037 }                                                1037 }
1038                                                  1038 
1039 /* Helper routines for pixmaps */                1039 /* Helper routines for pixmaps */
1040                                                  1040 
1041 inline tools_GL2PSimage *tools_gl2psCopyPixma    1041 inline tools_GL2PSimage *tools_gl2psCopyPixmap(tools_GL2PSimage *im)
1042 {                                                1042 {
1043   int size;                                      1043   int size;
1044   tools_GL2PSimage *image = (tools_GL2PSimage    1044   tools_GL2PSimage *image = (tools_GL2PSimage*)tools_gl2psMalloc(sizeof(tools_GL2PSimage));
1045                                                  1045 
1046   image->width = im->width;                      1046   image->width = im->width;
1047   image->height = im->height;                    1047   image->height = im->height;
1048   image->format = im->format;                    1048   image->format = im->format;
1049   image->type = im->type;                        1049   image->type = im->type;
1050   image->zoom_x = im->zoom_x;                    1050   image->zoom_x = im->zoom_x;
1051   image->zoom_y = im->zoom_y;                    1051   image->zoom_y = im->zoom_y;
1052                                                  1052 
1053   switch(image->format){                         1053   switch(image->format){
1054   case TOOLS_GL_RGBA:                            1054   case TOOLS_GL_RGBA:
1055     size = image->height * image->width * 4 *    1055     size = image->height * image->width * 4 * sizeof(tools_GLfloat);
1056     break;                                       1056     break;
1057   case TOOLS_GL_RGB:                             1057   case TOOLS_GL_RGB:
1058   default:                                       1058   default:
1059     size = image->height * image->width * 3 *    1059     size = image->height * image->width * 3 * sizeof(tools_GLfloat);
1060     break;                                       1060     break;
1061   }                                              1061   }
1062                                                  1062 
1063   image->pixels = (tools_GLfloat*)tools_gl2ps    1063   image->pixels = (tools_GLfloat*)tools_gl2psMalloc(size);
1064   memcpy(image->pixels, im->pixels, size);       1064   memcpy(image->pixels, im->pixels, size);
1065                                                  1065 
1066   return image;                                  1066   return image;
1067 }                                                1067 }
1068                                                  1068 
1069 inline void tools_gl2psFreePixmap(tools_GL2PS    1069 inline void tools_gl2psFreePixmap(tools_GL2PSimage *im)
1070 {                                                1070 {
1071   if(!im)                                        1071   if(!im)
1072     return;                                      1072     return;
1073   tools_gl2psFree(im->pixels);                   1073   tools_gl2psFree(im->pixels);
1074   tools_gl2psFree(im);                           1074   tools_gl2psFree(im);
1075 }                                                1075 }
1076                                                  1076 
1077 #if defined(TOOLS_GL2PS_HAVE_LIBPNG)             1077 #if defined(TOOLS_GL2PS_HAVE_LIBPNG)
1078                                                  1078 
1079 #if !defined(png_jmpbuf)                         1079 #if !defined(png_jmpbuf)
1080 #  define png_jmpbuf(png_ptr) ((png_ptr)->jmp    1080 #  define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf)
1081 #endif                                           1081 #endif
1082                                                  1082 
1083 inline void tools_gl2psUserWritePNG(png_struc    1083 inline void tools_gl2psUserWritePNG(png_structp png_ptr, png_bytep data, png_size_t length)
1084 {                                                1084 {
1085   unsigned int i;                                1085   unsigned int i;
1086   tools_GL2PSlist *png = (tools_GL2PSlist*)pn    1086   tools_GL2PSlist *png = (tools_GL2PSlist*)png_get_io_ptr(png_ptr);
1087   for(i = 0; i < length; i++)                    1087   for(i = 0; i < length; i++)
1088     tools_gl2psListAdd(png, &data[i]);           1088     tools_gl2psListAdd(png, &data[i]);
1089 }                                                1089 }
1090                                                  1090 
1091 inline void tools_gl2psUserFlushPNG(png_struc    1091 inline void tools_gl2psUserFlushPNG(png_structp png_ptr)
1092 {                                                1092 {
1093   (void) png_ptr;  /* not used */                1093   (void) png_ptr;  /* not used */
1094 }                                                1094 }
1095                                                  1095 
1096 inline void tools_gl2psConvertPixmapToPNG(too    1096 inline void tools_gl2psConvertPixmapToPNG(tools_GL2PSimage *pixmap, tools_GL2PSlist *png)
1097 {                                                1097 {
1098   png_structp png_ptr;                           1098   png_structp png_ptr;
1099   png_infop info_ptr;                            1099   png_infop info_ptr;
1100   unsigned char *row_data;                       1100   unsigned char *row_data;
1101   tools_GLfloat dr, dg, db;                      1101   tools_GLfloat dr, dg, db;
1102   int row, col;                                  1102   int row, col;
1103                                                  1103 
1104   if(!(png_ptr = png_create_write_struct(PNG_    1104   if(!(png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL)))
1105     return;                                      1105     return;
1106                                                  1106 
1107   if(!(info_ptr = png_create_info_struct(png_    1107   if(!(info_ptr = png_create_info_struct(png_ptr))){
1108     png_destroy_write_struct(&png_ptr, NULL);    1108     png_destroy_write_struct(&png_ptr, NULL);
1109     return;                                      1109     return;
1110   }                                              1110   }
1111                                                  1111 
1112   if(setjmp(png_jmpbuf(png_ptr))) {              1112   if(setjmp(png_jmpbuf(png_ptr))) {
1113     png_destroy_write_struct(&png_ptr, &info_    1113     png_destroy_write_struct(&png_ptr, &info_ptr);
1114     return;                                      1114     return;
1115   }                                              1115   }
1116                                                  1116 
1117   png_set_write_fn(png_ptr, (void *)png, tool    1117   png_set_write_fn(png_ptr, (void *)png, tools_gl2psUserWritePNG, tools_gl2psUserFlushPNG);
1118   png_set_compression_level(png_ptr, Z_DEFAUL    1118   png_set_compression_level(png_ptr, Z_DEFAULT_COMPRESSION);
1119   png_set_IHDR(png_ptr, info_ptr, pixmap->wid    1119   png_set_IHDR(png_ptr, info_ptr, pixmap->width, pixmap->height, 8,
1120                PNG_COLOR_TYPE_RGB, PNG_INTERL    1120                PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE,
1121                PNG_FILTER_TYPE_BASE);            1121                PNG_FILTER_TYPE_BASE);
1122   png_write_info(png_ptr, info_ptr);             1122   png_write_info(png_ptr, info_ptr);
1123                                                  1123 
1124   row_data = (unsigned char*)tools_gl2psMallo    1124   row_data = (unsigned char*)tools_gl2psMalloc(3 * pixmap->width * sizeof(unsigned char));
1125   for(row = 0; row < pixmap->height; row++){     1125   for(row = 0; row < pixmap->height; row++){
1126     for(col = 0; col < pixmap->width; col++){    1126     for(col = 0; col < pixmap->width; col++){
1127       tools_gl2psGetRGB(pixmap, col, row, &dr    1127       tools_gl2psGetRGB(pixmap, col, row, &dr, &dg, &db);
1128       row_data[3*col] = (unsigned char)(255.     1128       row_data[3*col] = (unsigned char)(255. * dr);
1129       row_data[3*col+1] = (unsigned char)(255    1129       row_data[3*col+1] = (unsigned char)(255. * dg);
1130       row_data[3*col+2] = (unsigned char)(255    1130       row_data[3*col+2] = (unsigned char)(255. * db);
1131     }                                            1131     }
1132     png_write_row(png_ptr, (png_bytep)row_dat    1132     png_write_row(png_ptr, (png_bytep)row_data);
1133   }                                              1133   }
1134   tools_gl2psFree(row_data);                     1134   tools_gl2psFree(row_data);
1135                                                  1135 
1136   png_write_end(png_ptr, info_ptr);              1136   png_write_end(png_ptr, info_ptr);
1137   png_destroy_write_struct(&png_ptr, &info_pt    1137   png_destroy_write_struct(&png_ptr, &info_ptr);
1138 }                                                1138 }
1139                                                  1139 
1140 #endif                                           1140 #endif
1141                                                  1141 
1142 /* Helper routines for text strings */           1142 /* Helper routines for text strings */
1143                                                  1143 
1144 inline tools_GLint tools_gl2psAddText(tools_G    1144 inline tools_GLint tools_gl2psAddText(tools_GL2PScontext* gl2ps, tools_GLint type, const char *str, const char *fontname,
1145                           tools_GLshort fonts    1145                           tools_GLshort fontsize, tools_GLint alignment, tools_GLfloat angle,
1146                           tools_GL2PSrgba col    1146                           tools_GL2PSrgba color, tools_GLboolean setblpos,
1147                           tools_GLfloat blx,     1147                           tools_GLfloat blx, tools_GLfloat bly)
1148 {                                                1148 {
1149   tools_GLfloat pos[4];                          1149   tools_GLfloat pos[4];
1150   tools_GL2PSprimitive *prim;                    1150   tools_GL2PSprimitive *prim;
1151   tools_GLboolean valid;                         1151   tools_GLboolean valid;
1152                                                  1152 
1153   if(/*!gl2ps ||*/ !str || !fontname) return     1153   if(/*!gl2ps ||*/ !str || !fontname) return TOOLS_GL2PS_UNINITIALIZED;
1154                                                  1154 
1155   if(gl2ps->options & TOOLS_GL2PS_NO_TEXT) re    1155   if(gl2ps->options & TOOLS_GL2PS_NO_TEXT) return TOOLS_GL2PS_SUCCESS;
1156                                                  1156 
1157   if (gl2ps->forcerasterpos) {                   1157   if (gl2ps->forcerasterpos) {
1158     pos[0] = gl2ps->rasterpos.xyz[0];            1158     pos[0] = gl2ps->rasterpos.xyz[0];
1159     pos[1] = gl2ps->rasterpos.xyz[1];            1159     pos[1] = gl2ps->rasterpos.xyz[1];
1160     pos[2] = gl2ps->rasterpos.xyz[2];            1160     pos[2] = gl2ps->rasterpos.xyz[2];
1161     pos[3] = 1.f;                                1161     pos[3] = 1.f;
1162   }                                              1162   }
1163   else {                                         1163   else {
1164     tools_glGetBooleanv(TOOLS_GL_CURRENT_RAST    1164     tools_glGetBooleanv(TOOLS_GL_CURRENT_RASTER_POSITION_VALID, &valid);
1165     if(TOOLS_GL_FALSE == valid) return TOOLS_    1165     if(TOOLS_GL_FALSE == valid) return TOOLS_GL2PS_SUCCESS; /* the primitive is culled */
1166     tools_glGetFloatv(TOOLS_GL_CURRENT_RASTER    1166     tools_glGetFloatv(TOOLS_GL_CURRENT_RASTER_POSITION, pos);
1167   }                                              1167   }
1168                                                  1168 
1169   prim = (tools_GL2PSprimitive*)tools_gl2psMa    1169   prim = (tools_GL2PSprimitive*)tools_gl2psMalloc(sizeof(tools_GL2PSprimitive));
1170   prim->type = (tools_GLshort)type;              1170   prim->type = (tools_GLshort)type;
1171   prim->boundary = 0;                            1171   prim->boundary = 0;
1172   prim->numverts = setblpos ? 2 : 1;             1172   prim->numverts = setblpos ? 2 : 1;
1173   prim->verts = (tools_GL2PSvertex*)tools_gl2    1173   prim->verts = (tools_GL2PSvertex*)tools_gl2psMalloc(sizeof(tools_GL2PSvertex) * prim->numverts);
1174   prim->verts[0].xyz[0] = pos[0];                1174   prim->verts[0].xyz[0] = pos[0];
1175   prim->verts[0].xyz[1] = pos[1];                1175   prim->verts[0].xyz[1] = pos[1];
1176   prim->verts[0].xyz[2] = pos[2];                1176   prim->verts[0].xyz[2] = pos[2];
1177   if (setblpos) {                                1177   if (setblpos) {
1178     prim->verts[1].xyz[0] = blx;                 1178     prim->verts[1].xyz[0] = blx;
1179     prim->verts[1].xyz[1] = bly;                 1179     prim->verts[1].xyz[1] = bly;
1180     prim->verts[1].xyz[2] = 0;                   1180     prim->verts[1].xyz[2] = 0;
1181   }                                              1181   }
1182   prim->culled = 0;                              1182   prim->culled = 0;
1183   prim->offset = 0;                              1183   prim->offset = 0;
1184   prim->ofactor = 0.0;                           1184   prim->ofactor = 0.0;
1185   prim->ounits = 0.0;                            1185   prim->ounits = 0.0;
1186   prim->pattern = 0;                             1186   prim->pattern = 0;
1187   prim->factor = 0;                              1187   prim->factor = 0;
1188   prim->width = 1;                               1188   prim->width = 1;
1189   prim->linecap = 0;                             1189   prim->linecap = 0;
1190   prim->linejoin = 0;                            1190   prim->linejoin = 0;
1191                                                  1191 
1192   if (color) {                                   1192   if (color) {
1193     memcpy(prim->verts[0].rgba, color, 4 * si    1193     memcpy(prim->verts[0].rgba, color, 4 * sizeof(float));
1194   }                                              1194   }
1195   else {                                         1195   else {
1196     if (gl2ps->forcerasterpos) {                 1196     if (gl2ps->forcerasterpos) {
1197       prim->verts[0].rgba[0] = gl2ps->rasterp    1197       prim->verts[0].rgba[0] = gl2ps->rasterpos.rgba[0];
1198       prim->verts[0].rgba[1] = gl2ps->rasterp    1198       prim->verts[0].rgba[1] = gl2ps->rasterpos.rgba[1];
1199       prim->verts[0].rgba[2] = gl2ps->rasterp    1199       prim->verts[0].rgba[2] = gl2ps->rasterpos.rgba[2];
1200       prim->verts[0].rgba[3] = gl2ps->rasterp    1200       prim->verts[0].rgba[3] = gl2ps->rasterpos.rgba[3];
1201     }                                            1201     }
1202     else {                                       1202     else {
1203       tools_glGetFloatv(TOOLS_GL_CURRENT_RAST    1203       tools_glGetFloatv(TOOLS_GL_CURRENT_RASTER_COLOR, prim->verts[0].rgba);
1204     }                                            1204     }
1205   }                                              1205   }
1206   prim->data.text = (tools_GL2PSstring*)tools    1206   prim->data.text = (tools_GL2PSstring*)tools_gl2psMalloc(sizeof(tools_GL2PSstring));
1207   prim->data.text->str = (char*)tools_gl2psMa    1207   prim->data.text->str = (char*)tools_gl2psMalloc((strlen(str)+1)*sizeof(char));
1208   strcpy(prim->data.text->str, str);             1208   strcpy(prim->data.text->str, str);
1209   prim->data.text->fontname = (char*)tools_gl    1209   prim->data.text->fontname = (char*)tools_gl2psMalloc((strlen(fontname)+1)*sizeof(char));
1210   strcpy(prim->data.text->fontname, fontname)    1210   strcpy(prim->data.text->fontname, fontname);
1211   prim->data.text->fontsize = fontsize;          1211   prim->data.text->fontsize = fontsize;
1212   prim->data.text->alignment = alignment;        1212   prim->data.text->alignment = alignment;
1213   prim->data.text->angle = angle;                1213   prim->data.text->angle = angle;
1214                                                  1214 
1215   gl2ps->forcerasterpos = TOOLS_GL_FALSE;        1215   gl2ps->forcerasterpos = TOOLS_GL_FALSE;
1216                                                  1216 
1217   /* If no OpenGL context, just add directly     1217   /* If no OpenGL context, just add directly to primitives */
1218   if (gl2ps->options & TOOLS_GL2PS_NO_OPENGL_    1218   if (gl2ps->options & TOOLS_GL2PS_NO_OPENGL_CONTEXT) {
1219     tools_gl2psListAdd(gl2ps->primitives, &pr    1219     tools_gl2psListAdd(gl2ps->primitives, &prim);
1220   }                                              1220   }
1221   else {                                         1221   else {
1222     tools_gl2psListAdd(gl2ps->auxprimitives,     1222     tools_gl2psListAdd(gl2ps->auxprimitives, &prim);
1223     tools_glPassThrough(TOOLS_GL2PS_TEXT_TOKE    1223     tools_glPassThrough(TOOLS_GL2PS_TEXT_TOKEN);
1224   }                                              1224   }
1225                                                  1225 
1226   return TOOLS_GL2PS_SUCCESS;                    1226   return TOOLS_GL2PS_SUCCESS;
1227 }                                                1227 }
1228                                                  1228 
1229 inline tools_GL2PSstring *tools_gl2psCopyText    1229 inline tools_GL2PSstring *tools_gl2psCopyText(tools_GL2PSstring *t)
1230 {                                                1230 {
1231   tools_GL2PSstring *text = (tools_GL2PSstrin    1231   tools_GL2PSstring *text = (tools_GL2PSstring*)tools_gl2psMalloc(sizeof(tools_GL2PSstring));
1232   text->str = (char*)tools_gl2psMalloc((strle    1232   text->str = (char*)tools_gl2psMalloc((strlen(t->str)+1)*sizeof(char));
1233   strcpy(text->str, t->str);                     1233   strcpy(text->str, t->str);
1234   text->fontname = (char*)tools_gl2psMalloc((    1234   text->fontname = (char*)tools_gl2psMalloc((strlen(t->fontname)+1)*sizeof(char));
1235   strcpy(text->fontname, t->fontname);           1235   strcpy(text->fontname, t->fontname);
1236   text->fontsize = t->fontsize;                  1236   text->fontsize = t->fontsize;
1237   text->alignment = t->alignment;                1237   text->alignment = t->alignment;
1238   text->angle = t->angle;                        1238   text->angle = t->angle;
1239                                                  1239 
1240   return text;                                   1240   return text;
1241 }                                                1241 }
1242                                                  1242 
1243 inline void tools_gl2psFreeText(tools_GL2PSst    1243 inline void tools_gl2psFreeText(tools_GL2PSstring *text)
1244 {                                                1244 {
1245   if(!text)                                      1245   if(!text)
1246     return;                                      1246     return;
1247   tools_gl2psFree(text->str);                    1247   tools_gl2psFree(text->str);
1248   tools_gl2psFree(text->fontname);               1248   tools_gl2psFree(text->fontname);
1249   tools_gl2psFree(text);                         1249   tools_gl2psFree(text);
1250 }                                                1250 }
1251                                                  1251 
1252 /* Helpers for blending modes */                 1252 /* Helpers for blending modes */
1253                                                  1253 
1254 inline tools_GLboolean tools_gl2psSupportedBl    1254 inline tools_GLboolean tools_gl2psSupportedBlendMode(tools_GLenum sfactor, tools_GLenum dfactor)
1255 {                                                1255 {
1256   /* returns TRUE if gl2ps supports the argum    1256   /* returns TRUE if gl2ps supports the argument combination: only two
1257      blending modes have been implemented so     1257      blending modes have been implemented so far */
1258                                                  1258 
1259   if( (sfactor == TOOLS_GL_SRC_ALPHA && dfact    1259   if( (sfactor == TOOLS_GL_SRC_ALPHA && dfactor == TOOLS_GL_ONE_MINUS_SRC_ALPHA) ||
1260       (sfactor == TOOLS_GL_ONE && dfactor ==     1260       (sfactor == TOOLS_GL_ONE && dfactor == TOOLS_GL_ZERO) )
1261     return TOOLS_GL_TRUE;                        1261     return TOOLS_GL_TRUE;
1262   return TOOLS_GL_FALSE;                         1262   return TOOLS_GL_FALSE;
1263 }                                                1263 }
1264                                                  1264 
1265 inline void tools_gl2psAdaptVertexForBlending    1265 inline void tools_gl2psAdaptVertexForBlending(tools_GL2PScontext* gl2ps, tools_GL2PSvertex *v)
1266 {                                                1266 {
1267   /* Transforms vertex depending on the actua    1267   /* Transforms vertex depending on the actual blending function -
1268      currently the vertex v is considered as     1268      currently the vertex v is considered as source vertex and his
1269      alpha value is changed to 1.0 if source     1269      alpha value is changed to 1.0 if source blending TOOLS_GL_ONE is
1270      active. This might be extended in the fu    1270      active. This might be extended in the future */
1271                                                  1271 
1272   if(!v /* || !gl2ps*/)                          1272   if(!v /* || !gl2ps*/)
1273     return;                                      1273     return;
1274                                                  1274 
1275   if(gl2ps->options & TOOLS_GL2PS_NO_BLENDING    1275   if(gl2ps->options & TOOLS_GL2PS_NO_BLENDING || !gl2ps->blending){
1276     v->rgba[3] = 1.0F;                           1276     v->rgba[3] = 1.0F;
1277     return;                                      1277     return;
1278   }                                              1278   }
1279                                                  1279 
1280   switch(gl2ps->blendfunc[0]){                   1280   switch(gl2ps->blendfunc[0]){
1281   case TOOLS_GL_ONE:                             1281   case TOOLS_GL_ONE:
1282     v->rgba[3] = 1.0F;                           1282     v->rgba[3] = 1.0F;
1283     break;                                       1283     break;
1284   default:                                       1284   default:
1285     break;                                       1285     break;
1286   }                                              1286   }
1287 }                                                1287 }
1288                                                  1288 
1289 inline void tools_gl2psAssignTriangleProperti    1289 inline void tools_gl2psAssignTriangleProperties(tools_GL2PStriangle *t)
1290 {                                                1290 {
1291   /* int i; */                                   1291   /* int i; */
1292                                                  1292 
1293   t->prop = T_VAR_COLOR;                         1293   t->prop = T_VAR_COLOR;
1294                                                  1294 
1295   /* Uncommenting the following lines activat    1295   /* Uncommenting the following lines activates an even more fine
1296      grained distinction between triangle typ    1296      grained distinction between triangle types - please don't delete,
1297      a remarkable amount of PDF handling code    1297      a remarkable amount of PDF handling code inside this file depends
1298      on it if activated */                       1298      on it if activated */
1299   /*                                             1299   /*
1300   t->prop = T_CONST_COLOR;                       1300   t->prop = T_CONST_COLOR;
1301   for(i = 0; i < 3; ++i){                        1301   for(i = 0; i < 3; ++i){
1302     if(!TOOLS_GL2PS_ZERO(t->vertex[0].rgba[i]    1302     if(!TOOLS_GL2PS_ZERO(t->vertex[0].rgba[i] - t->vertex[1].rgba[i]) ||
1303        !TOOLS_GL2PS_ZERO(t->vertex[1].rgba[i]    1303        !TOOLS_GL2PS_ZERO(t->vertex[1].rgba[i] - t->vertex[2].rgba[i])){
1304       t->prop = T_VAR_COLOR;                     1304       t->prop = T_VAR_COLOR;
1305       break;                                     1305       break;
1306     }                                            1306     }
1307   }                                              1307   }
1308   */                                             1308   */
1309                                                  1309 
1310   if(!TOOLS_GL2PS_ZERO(t->vertex[0].rgba[3] -    1310   if(!TOOLS_GL2PS_ZERO(t->vertex[0].rgba[3] - t->vertex[1].rgba[3]) ||
1311      !TOOLS_GL2PS_ZERO(t->vertex[1].rgba[3] -    1311      !TOOLS_GL2PS_ZERO(t->vertex[1].rgba[3] - t->vertex[2].rgba[3])){
1312     t->prop |= T_VAR_ALPHA;                      1312     t->prop |= T_VAR_ALPHA;
1313   }                                              1313   }
1314   else{                                          1314   else{
1315     if(t->vertex[0].rgba[3] < 1)                 1315     if(t->vertex[0].rgba[3] < 1)
1316       t->prop |= T_ALPHA_LESS_1;                 1316       t->prop |= T_ALPHA_LESS_1;
1317     else                                         1317     else
1318       t->prop |= T_ALPHA_1;                      1318       t->prop |= T_ALPHA_1;
1319   }                                              1319   }
1320 }                                                1320 }
1321                                                  1321 
1322 inline void tools_gl2psFillTriangleFromPrimit    1322 inline void tools_gl2psFillTriangleFromPrimitive(tools_GL2PStriangle *t, tools_GL2PSprimitive *p,
1323                                            to    1323                                            tools_GLboolean assignprops)
1324 {                                                1324 {
1325   t->vertex[0] = p->verts[0];                    1325   t->vertex[0] = p->verts[0];
1326   t->vertex[1] = p->verts[1];                    1326   t->vertex[1] = p->verts[1];
1327   t->vertex[2] = p->verts[2];                    1327   t->vertex[2] = p->verts[2];
1328   if(TOOLS_GL_TRUE == assignprops)               1328   if(TOOLS_GL_TRUE == assignprops)
1329     tools_gl2psAssignTriangleProperties(t);      1329     tools_gl2psAssignTriangleProperties(t);
1330 }                                                1330 }
1331                                                  1331 
1332 inline void tools_gl2psInitTriangle(tools_GL2    1332 inline void tools_gl2psInitTriangle(tools_GL2PStriangle *t)
1333 {                                                1333 {
1334   int i;                                         1334   int i;
1335   tools_GL2PSvertex vertex = { {-1.0F, -1.0F,    1335   tools_GL2PSvertex vertex = { {-1.0F, -1.0F, -1.0F}, {-1.0F, -1.0F, -1.0F, -1.0F} };
1336   for(i = 0; i < 3; i++)                         1336   for(i = 0; i < 3; i++)
1337     t->vertex[i] = vertex;                       1337     t->vertex[i] = vertex;
1338   t->prop = T_UNDEFINED;                         1338   t->prop = T_UNDEFINED;
1339 }                                                1339 }
1340                                                  1340 
1341 /* Miscellaneous helper routines */              1341 /* Miscellaneous helper routines */
1342                                                  1342 
1343 inline void tools_gl2psResetLineProperties(to    1343 inline void tools_gl2psResetLineProperties(tools_GL2PScontext* gl2ps)
1344 {                                                1344 {
1345   gl2ps->lastlinewidth = 0.;                     1345   gl2ps->lastlinewidth = 0.;
1346   gl2ps->lastlinecap = gl2ps->lastlinejoin =     1346   gl2ps->lastlinecap = gl2ps->lastlinejoin = 0;
1347 }                                                1347 }
1348                                                  1348 
1349 inline tools_GL2PSprimitive *tools_gl2psCopyP    1349 inline tools_GL2PSprimitive *tools_gl2psCopyPrimitive(tools_GL2PSprimitive *p)
1350 {                                                1350 {
1351   tools_GL2PSprimitive *prim;                    1351   tools_GL2PSprimitive *prim;
1352                                                  1352 
1353   if(!p){                                        1353   if(!p){
1354     tools_gl2psMsg(TOOLS_GL2PS_ERROR, "Trying    1354     tools_gl2psMsg(TOOLS_GL2PS_ERROR, "Trying to copy an empty primitive");
1355     return NULL;                                 1355     return NULL;
1356   }                                              1356   }
1357                                                  1357 
1358   prim = (tools_GL2PSprimitive*)tools_gl2psMa    1358   prim = (tools_GL2PSprimitive*)tools_gl2psMalloc(sizeof(tools_GL2PSprimitive));
1359                                                  1359 
1360   prim->type = p->type;                          1360   prim->type = p->type;
1361   prim->numverts = p->numverts;                  1361   prim->numverts = p->numverts;
1362   prim->boundary = p->boundary;                  1362   prim->boundary = p->boundary;
1363   prim->offset = p->offset;                      1363   prim->offset = p->offset;
1364   prim->ofactor = p->ofactor;                    1364   prim->ofactor = p->ofactor;
1365   prim->ounits = p->ounits;                      1365   prim->ounits = p->ounits;
1366   prim->pattern = p->pattern;                    1366   prim->pattern = p->pattern;
1367   prim->factor = p->factor;                      1367   prim->factor = p->factor;
1368   prim->culled = p->culled;                      1368   prim->culled = p->culled;
1369   prim->width = p->width;                        1369   prim->width = p->width;
1370   prim->linecap = p->linecap;                    1370   prim->linecap = p->linecap;
1371   prim->linejoin = p->linejoin;                  1371   prim->linejoin = p->linejoin;
1372   prim->verts = (tools_GL2PSvertex*)tools_gl2    1372   prim->verts = (tools_GL2PSvertex*)tools_gl2psMalloc(p->numverts*sizeof(tools_GL2PSvertex));
1373   memcpy(prim->verts, p->verts, p->numverts *    1373   memcpy(prim->verts, p->verts, p->numverts * sizeof(tools_GL2PSvertex));
1374                                                  1374 
1375   switch(prim->type){                            1375   switch(prim->type){
1376   case TOOLS_GL2PS_PIXMAP :                      1376   case TOOLS_GL2PS_PIXMAP :
1377     prim->data.image = tools_gl2psCopyPixmap(    1377     prim->data.image = tools_gl2psCopyPixmap(p->data.image);
1378     break;                                       1378     break;
1379   case TOOLS_GL2PS_TEXT :                        1379   case TOOLS_GL2PS_TEXT :
1380   case TOOLS_GL2PS_SPECIAL :                     1380   case TOOLS_GL2PS_SPECIAL :
1381     prim->data.text = tools_gl2psCopyText(p->    1381     prim->data.text = tools_gl2psCopyText(p->data.text);
1382     break;                                       1382     break;
1383   default:                                       1383   default:
1384     break;                                       1384     break;
1385   }                                              1385   }
1386                                                  1386 
1387   return prim;                                   1387   return prim;
1388 }                                                1388 }
1389                                                  1389 
1390 inline tools_GLboolean tools_gl2psSamePositio    1390 inline tools_GLboolean tools_gl2psSamePosition(tools_GL2PSxyz p1, tools_GL2PSxyz p2)
1391 {                                                1391 {
1392   if(!TOOLS_GL2PS_ZERO(p1[0] - p2[0]) ||         1392   if(!TOOLS_GL2PS_ZERO(p1[0] - p2[0]) ||
1393      !TOOLS_GL2PS_ZERO(p1[1] - p2[1]) ||         1393      !TOOLS_GL2PS_ZERO(p1[1] - p2[1]) ||
1394      !TOOLS_GL2PS_ZERO(p1[2] - p2[2]))           1394      !TOOLS_GL2PS_ZERO(p1[2] - p2[2]))
1395     return TOOLS_GL_FALSE;                       1395     return TOOLS_GL_FALSE;
1396   return TOOLS_GL_TRUE;                          1396   return TOOLS_GL_TRUE;
1397 }                                                1397 }
1398                                                  1398 
1399 /********************************************    1399 /*********************************************************************
1400  *                                               1400  *
1401  * 3D sorting routines                           1401  * 3D sorting routines
1402  *                                               1402  *
1403  ********************************************    1403  *********************************************************************/
1404                                                  1404 
1405 inline tools_GLfloat tools_gl2psComparePointP    1405 inline tools_GLfloat tools_gl2psComparePointPlane(tools_GL2PSxyz point, tools_GL2PSplane plane)
1406 {                                                1406 {
1407   return (plane[0] * point[0] +                  1407   return (plane[0] * point[0] +
1408           plane[1] * point[1] +                  1408           plane[1] * point[1] +
1409           plane[2] * point[2] +                  1409           plane[2] * point[2] +
1410           plane[3]);                             1410           plane[3]);
1411 }                                                1411 }
1412                                                  1412 
1413 inline tools_GLfloat tools_gl2psPsca(tools_GL    1413 inline tools_GLfloat tools_gl2psPsca(tools_GLfloat *a, tools_GLfloat *b)
1414 {                                                1414 {
1415   return (a[0]*b[0] + a[1]*b[1] + a[2]*b[2]);    1415   return (a[0]*b[0] + a[1]*b[1] + a[2]*b[2]);
1416 }                                                1416 }
1417                                                  1417 
1418 inline void tools_gl2psPvec(tools_GLfloat *a,    1418 inline void tools_gl2psPvec(tools_GLfloat *a, tools_GLfloat *b, tools_GLfloat *c)
1419 {                                                1419 {
1420   c[0] = a[1]*b[2] - a[2]*b[1];                  1420   c[0] = a[1]*b[2] - a[2]*b[1];
1421   c[1] = a[2]*b[0] - a[0]*b[2];                  1421   c[1] = a[2]*b[0] - a[0]*b[2];
1422   c[2] = a[0]*b[1] - a[1]*b[0];                  1422   c[2] = a[0]*b[1] - a[1]*b[0];
1423 }                                                1423 }
1424                                                  1424 
1425 inline tools_GLfloat tools_gl2psNorm(tools_GL    1425 inline tools_GLfloat tools_gl2psNorm(tools_GLfloat *a)
1426 {                                                1426 {
1427   return (tools_GLfloat)sqrt(a[0]*a[0] + a[1]    1427   return (tools_GLfloat)sqrt(a[0]*a[0] + a[1]*a[1] + a[2]*a[2]);
1428 }                                                1428 }
1429                                                  1429 
1430 inline void tools_gl2psGetNormal(tools_GLfloa    1430 inline void tools_gl2psGetNormal(tools_GLfloat *a, tools_GLfloat *b, tools_GLfloat *c)
1431 {                                                1431 {
1432   tools_GLfloat norm;                            1432   tools_GLfloat norm;
1433                                                  1433 
1434   tools_gl2psPvec(a, b, c);                      1434   tools_gl2psPvec(a, b, c);
1435   if(!TOOLS_GL2PS_ZERO(norm = tools_gl2psNorm    1435   if(!TOOLS_GL2PS_ZERO(norm = tools_gl2psNorm(c))){
1436     c[0] = c[0] / norm;                          1436     c[0] = c[0] / norm;
1437     c[1] = c[1] / norm;                          1437     c[1] = c[1] / norm;
1438     c[2] = c[2] / norm;                          1438     c[2] = c[2] / norm;
1439   }                                              1439   }
1440   else{                                          1440   else{
1441     /* The plane is still wrong despite our t    1441     /* The plane is still wrong despite our tests in tools_gl2psGetPlane.
1442        Let's return a dummy value for now (th    1442        Let's return a dummy value for now (this is a hack: we should
1443        do more intelligent tests in GetPlane)    1443        do more intelligent tests in GetPlane) */
1444     c[0] = c[1] = 0.0F;                          1444     c[0] = c[1] = 0.0F;
1445     c[2] = 1.0F;                                 1445     c[2] = 1.0F;
1446   }                                              1446   }
1447 }                                                1447 }
1448                                                  1448 
1449 inline void tools_gl2psGetPlane(tools_GL2PSpr    1449 inline void tools_gl2psGetPlane(tools_GL2PSprimitive *prim, tools_GL2PSplane plane)
1450 {                                                1450 {
1451   tools_GL2PSxyz v = {0.0F, 0.0F, 0.0F}, w =     1451   tools_GL2PSxyz v = {0.0F, 0.0F, 0.0F}, w = {0.0F, 0.0F, 0.0F};
1452                                                  1452 
1453   switch(prim->type){                            1453   switch(prim->type){
1454   case TOOLS_GL2PS_TRIANGLE :                    1454   case TOOLS_GL2PS_TRIANGLE :
1455   case TOOLS_GL2PS_QUADRANGLE :                  1455   case TOOLS_GL2PS_QUADRANGLE :
1456     v[0] = prim->verts[1].xyz[0] - prim->vert    1456     v[0] = prim->verts[1].xyz[0] - prim->verts[0].xyz[0];
1457     v[1] = prim->verts[1].xyz[1] - prim->vert    1457     v[1] = prim->verts[1].xyz[1] - prim->verts[0].xyz[1];
1458     v[2] = prim->verts[1].xyz[2] - prim->vert    1458     v[2] = prim->verts[1].xyz[2] - prim->verts[0].xyz[2];
1459     w[0] = prim->verts[2].xyz[0] - prim->vert    1459     w[0] = prim->verts[2].xyz[0] - prim->verts[0].xyz[0];
1460     w[1] = prim->verts[2].xyz[1] - prim->vert    1460     w[1] = prim->verts[2].xyz[1] - prim->verts[0].xyz[1];
1461     w[2] = prim->verts[2].xyz[2] - prim->vert    1461     w[2] = prim->verts[2].xyz[2] - prim->verts[0].xyz[2];
1462     if((TOOLS_GL2PS_ZERO(v[0]) && TOOLS_GL2PS    1462     if((TOOLS_GL2PS_ZERO(v[0]) && TOOLS_GL2PS_ZERO(v[1]) && TOOLS_GL2PS_ZERO(v[2])) ||
1463        (TOOLS_GL2PS_ZERO(w[0]) && TOOLS_GL2PS    1463        (TOOLS_GL2PS_ZERO(w[0]) && TOOLS_GL2PS_ZERO(w[1]) && TOOLS_GL2PS_ZERO(w[2]))){
1464       plane[0] = plane[1] = 0.0F;                1464       plane[0] = plane[1] = 0.0F;
1465       plane[2] = 1.0F;                           1465       plane[2] = 1.0F;
1466       plane[3] = -prim->verts[0].xyz[2];         1466       plane[3] = -prim->verts[0].xyz[2];
1467     }                                            1467     }
1468     else{                                        1468     else{
1469       tools_gl2psGetNormal(v, w, plane);         1469       tools_gl2psGetNormal(v, w, plane);
1470       plane[3] =                                 1470       plane[3] =
1471         - plane[0] * prim->verts[0].xyz[0]       1471         - plane[0] * prim->verts[0].xyz[0]
1472         - plane[1] * prim->verts[0].xyz[1]       1472         - plane[1] * prim->verts[0].xyz[1]
1473         - plane[2] * prim->verts[0].xyz[2];      1473         - plane[2] * prim->verts[0].xyz[2];
1474     }                                            1474     }
1475     break;                                       1475     break;
1476   case TOOLS_GL2PS_LINE :                        1476   case TOOLS_GL2PS_LINE :
1477     v[0] = prim->verts[1].xyz[0] - prim->vert    1477     v[0] = prim->verts[1].xyz[0] - prim->verts[0].xyz[0];
1478     v[1] = prim->verts[1].xyz[1] - prim->vert    1478     v[1] = prim->verts[1].xyz[1] - prim->verts[0].xyz[1];
1479     v[2] = prim->verts[1].xyz[2] - prim->vert    1479     v[2] = prim->verts[1].xyz[2] - prim->verts[0].xyz[2];
1480     if(TOOLS_GL2PS_ZERO(v[0]) && TOOLS_GL2PS_    1480     if(TOOLS_GL2PS_ZERO(v[0]) && TOOLS_GL2PS_ZERO(v[1]) && TOOLS_GL2PS_ZERO(v[2])){
1481       plane[0] = plane[1] = 0.0F;                1481       plane[0] = plane[1] = 0.0F;
1482       plane[2] = 1.0F;                           1482       plane[2] = 1.0F;
1483       plane[3] = -prim->verts[0].xyz[2];         1483       plane[3] = -prim->verts[0].xyz[2];
1484     }                                            1484     }
1485     else{                                        1485     else{
1486       if(TOOLS_GL2PS_ZERO(v[0]))      w[0] =     1486       if(TOOLS_GL2PS_ZERO(v[0]))      w[0] = 1.0F;
1487       else if(TOOLS_GL2PS_ZERO(v[1])) w[1] =     1487       else if(TOOLS_GL2PS_ZERO(v[1])) w[1] = 1.0F;
1488       else                      w[2] = 1.0F;     1488       else                      w[2] = 1.0F;
1489       tools_gl2psGetNormal(v, w, plane);         1489       tools_gl2psGetNormal(v, w, plane);
1490       plane[3] =                                 1490       plane[3] =
1491         - plane[0] * prim->verts[0].xyz[0]       1491         - plane[0] * prim->verts[0].xyz[0]
1492         - plane[1] * prim->verts[0].xyz[1]       1492         - plane[1] * prim->verts[0].xyz[1]
1493         - plane[2] * prim->verts[0].xyz[2];      1493         - plane[2] * prim->verts[0].xyz[2];
1494     }                                            1494     }
1495     break;                                       1495     break;
1496   case TOOLS_GL2PS_POINT :                       1496   case TOOLS_GL2PS_POINT :
1497   case TOOLS_GL2PS_PIXMAP :                      1497   case TOOLS_GL2PS_PIXMAP :
1498   case TOOLS_GL2PS_TEXT :                        1498   case TOOLS_GL2PS_TEXT :
1499   case TOOLS_GL2PS_SPECIAL :                     1499   case TOOLS_GL2PS_SPECIAL :
1500   case TOOLS_GL2PS_IMAGEMAP:                     1500   case TOOLS_GL2PS_IMAGEMAP:
1501     plane[0] = plane[1] = 0.0F;                  1501     plane[0] = plane[1] = 0.0F;
1502     plane[2] = 1.0F;                             1502     plane[2] = 1.0F;
1503     plane[3] = -prim->verts[0].xyz[2];           1503     plane[3] = -prim->verts[0].xyz[2];
1504     break;                                       1504     break;
1505   default :                                      1505   default :
1506     tools_gl2psMsg(TOOLS_GL2PS_ERROR, "Unknow    1506     tools_gl2psMsg(TOOLS_GL2PS_ERROR, "Unknown primitive type in BSP tree");
1507     plane[0] = plane[1] = plane[3] = 0.0F;       1507     plane[0] = plane[1] = plane[3] = 0.0F;
1508     plane[2] = 1.0F;                             1508     plane[2] = 1.0F;
1509     break;                                       1509     break;
1510   }                                              1510   }
1511 }                                                1511 }
1512                                                  1512 
1513 inline void tools_gl2psCutEdge(tools_GL2PSver    1513 inline void tools_gl2psCutEdge(tools_GL2PSvertex *a, tools_GL2PSvertex *b, tools_GL2PSplane plane,
1514                          tools_GL2PSvertex *c    1514                          tools_GL2PSvertex *c)
1515 {                                                1515 {
1516   tools_GL2PSxyz v;                              1516   tools_GL2PSxyz v;
1517   tools_GLfloat sect, psca;                      1517   tools_GLfloat sect, psca;
1518                                                  1518 
1519   v[0] = b->xyz[0] - a->xyz[0];                  1519   v[0] = b->xyz[0] - a->xyz[0];
1520   v[1] = b->xyz[1] - a->xyz[1];                  1520   v[1] = b->xyz[1] - a->xyz[1];
1521   v[2] = b->xyz[2] - a->xyz[2];                  1521   v[2] = b->xyz[2] - a->xyz[2];
1522                                                  1522 
1523   if(!TOOLS_GL2PS_ZERO(psca = tools_gl2psPsca    1523   if(!TOOLS_GL2PS_ZERO(psca = tools_gl2psPsca(plane, v)))
1524     sect = -tools_gl2psComparePointPlane(a->x    1524     sect = -tools_gl2psComparePointPlane(a->xyz, plane) / psca;
1525   else                                           1525   else
1526     sect = 0.0F;                                 1526     sect = 0.0F;
1527                                                  1527 
1528   c->xyz[0] = a->xyz[0] + v[0] * sect;           1528   c->xyz[0] = a->xyz[0] + v[0] * sect;
1529   c->xyz[1] = a->xyz[1] + v[1] * sect;           1529   c->xyz[1] = a->xyz[1] + v[1] * sect;
1530   c->xyz[2] = a->xyz[2] + v[2] * sect;           1530   c->xyz[2] = a->xyz[2] + v[2] * sect;
1531                                                  1531 
1532   c->rgba[0] = (1 - sect) * a->rgba[0] + sect    1532   c->rgba[0] = (1 - sect) * a->rgba[0] + sect * b->rgba[0];
1533   c->rgba[1] = (1 - sect) * a->rgba[1] + sect    1533   c->rgba[1] = (1 - sect) * a->rgba[1] + sect * b->rgba[1];
1534   c->rgba[2] = (1 - sect) * a->rgba[2] + sect    1534   c->rgba[2] = (1 - sect) * a->rgba[2] + sect * b->rgba[2];
1535   c->rgba[3] = (1 - sect) * a->rgba[3] + sect    1535   c->rgba[3] = (1 - sect) * a->rgba[3] + sect * b->rgba[3];
1536 }                                                1536 }
1537                                                  1537 
1538 inline void tools_gl2psCreateSplitPrimitive(t    1538 inline void tools_gl2psCreateSplitPrimitive(tools_GL2PSprimitive *parent, tools_GL2PSplane plane,
1539                                       tools_G    1539                                       tools_GL2PSprimitive *child, tools_GLshort numverts,
1540                                       tools_G    1540                                       tools_GLshort *index0, tools_GLshort *index1)
1541 {                                                1541 {
1542   tools_GLshort i;                               1542   tools_GLshort i;
1543                                                  1543 
1544   if(parent->type == TOOLS_GL2PS_IMAGEMAP){      1544   if(parent->type == TOOLS_GL2PS_IMAGEMAP){
1545     child->type = TOOLS_GL2PS_IMAGEMAP;          1545     child->type = TOOLS_GL2PS_IMAGEMAP;
1546     child->data.image = parent->data.image;      1546     child->data.image = parent->data.image;
1547   }                                              1547   }
1548   else{                                          1548   else{
1549     if(numverts > 4){                            1549     if(numverts > 4){
1550       tools_gl2psMsg(TOOLS_GL2PS_WARNING, "%d    1550       tools_gl2psMsg(TOOLS_GL2PS_WARNING, "%d vertices in polygon", numverts);
1551       numverts = 4;                              1551       numverts = 4;
1552     }                                            1552     }
1553     switch(numverts){                            1553     switch(numverts){
1554     case 1 : child->type = TOOLS_GL2PS_POINT;    1554     case 1 : child->type = TOOLS_GL2PS_POINT; break;
1555     case 2 : child->type = TOOLS_GL2PS_LINE;     1555     case 2 : child->type = TOOLS_GL2PS_LINE; break;
1556     case 3 : child->type = TOOLS_GL2PS_TRIANG    1556     case 3 : child->type = TOOLS_GL2PS_TRIANGLE; break;
1557     case 4 : child->type = TOOLS_GL2PS_QUADRA    1557     case 4 : child->type = TOOLS_GL2PS_QUADRANGLE; break;
1558     default: child->type = TOOLS_GL2PS_NO_TYP    1558     default: child->type = TOOLS_GL2PS_NO_TYPE; break;
1559     }                                            1559     }
1560   }                                              1560   }
1561                                                  1561 
1562   child->boundary = 0; /* FIXME: not done! */    1562   child->boundary = 0; /* FIXME: not done! */
1563   child->culled = parent->culled;                1563   child->culled = parent->culled;
1564   child->offset = parent->offset;                1564   child->offset = parent->offset;
1565   child->ofactor = parent->ofactor;              1565   child->ofactor = parent->ofactor;
1566   child->ounits = parent->ounits;                1566   child->ounits = parent->ounits;
1567   child->pattern = parent->pattern;              1567   child->pattern = parent->pattern;
1568   child->factor = parent->factor;                1568   child->factor = parent->factor;
1569   child->width = parent->width;                  1569   child->width = parent->width;
1570   child->linecap = parent->linecap;              1570   child->linecap = parent->linecap;
1571   child->linejoin = parent->linejoin;            1571   child->linejoin = parent->linejoin;
1572   child->numverts = numverts;                    1572   child->numverts = numverts;
1573   child->verts = (tools_GL2PSvertex*)tools_gl    1573   child->verts = (tools_GL2PSvertex*)tools_gl2psMalloc(numverts * sizeof(tools_GL2PSvertex));
1574                                                  1574 
1575   for(i = 0; i < numverts; i++){                 1575   for(i = 0; i < numverts; i++){
1576     if(index1[i] < 0){                           1576     if(index1[i] < 0){
1577       child->verts[i] = parent->verts[index0[    1577       child->verts[i] = parent->verts[index0[i]];
1578     }                                            1578     }
1579     else{                                        1579     else{
1580       tools_gl2psCutEdge(&parent->verts[index    1580       tools_gl2psCutEdge(&parent->verts[index0[i]], &parent->verts[index1[i]],
1581                    plane, &child->verts[i]);     1581                    plane, &child->verts[i]);
1582     }                                            1582     }
1583   }                                              1583   }
1584 }                                                1584 }
1585                                                  1585 
1586 inline void tools_gl2psAddIndex(tools_GLshort    1586 inline void tools_gl2psAddIndex(tools_GLshort *index0, tools_GLshort *index1, tools_GLshort *nb,
1587                           tools_GLshort i, to    1587                           tools_GLshort i, tools_GLshort j)
1588 {                                                1588 {
1589   tools_GLint k;                                 1589   tools_GLint k;
1590                                                  1590 
1591   for(k = 0; k < *nb; k++){                      1591   for(k = 0; k < *nb; k++){
1592     if((index0[k] == i && index1[k] == j) ||     1592     if((index0[k] == i && index1[k] == j) ||
1593        (index1[k] == i && index0[k] == j)) re    1593        (index1[k] == i && index0[k] == j)) return;
1594   }                                              1594   }
1595   index0[*nb] = i;                               1595   index0[*nb] = i;
1596   index1[*nb] = j;                               1596   index1[*nb] = j;
1597   (*nb)++;                                       1597   (*nb)++;
1598 }                                                1598 }
1599                                                  1599 
1600 inline tools_GLshort tools_gl2psGetIndex(tool    1600 inline tools_GLshort tools_gl2psGetIndex(tools_GLshort i, tools_GLshort num)
1601 {                                                1601 {
1602   return (i < num - 1) ? i + 1 : 0;              1602   return (i < num - 1) ? i + 1 : 0;
1603 }                                                1603 }
1604                                                  1604 
1605 inline tools_GLint tools_gl2psTestSplitPrimit    1605 inline tools_GLint tools_gl2psTestSplitPrimitive(tools_GL2PSprimitive *prim, tools_GL2PSplane plane)
1606 {                                                1606 {
1607   tools_GLint type = TOOLS_GL2PS_COINCIDENT;     1607   tools_GLint type = TOOLS_GL2PS_COINCIDENT;
1608   tools_GLshort i, j;                            1608   tools_GLshort i, j;
1609   tools_GLfloat d[5];                            1609   tools_GLfloat d[5];
1610                                                  1610 
1611   for(i = 0; i < prim->numverts; i++){           1611   for(i = 0; i < prim->numverts; i++){
1612     d[i] = tools_gl2psComparePointPlane(prim-    1612     d[i] = tools_gl2psComparePointPlane(prim->verts[i].xyz, plane);
1613   }                                              1613   }
1614                                                  1614 
1615   if(prim->numverts < 2){                        1615   if(prim->numverts < 2){
1616     return 0;                                    1616     return 0;
1617   }                                              1617   }
1618   else{                                          1618   else{
1619     for(i = 0; i < prim->numverts; i++){         1619     for(i = 0; i < prim->numverts; i++){
1620       j = tools_gl2psGetIndex(i, prim->numver    1620       j = tools_gl2psGetIndex(i, prim->numverts);
1621       if(d[j] > TOOLS_GL2PS_EPSILON){            1621       if(d[j] > TOOLS_GL2PS_EPSILON){
1622         if(type == TOOLS_GL2PS_COINCIDENT)       1622         if(type == TOOLS_GL2PS_COINCIDENT)      type = TOOLS_GL2PS_IN_BACK_OF;
1623         else if(type != TOOLS_GL2PS_IN_BACK_O    1623         else if(type != TOOLS_GL2PS_IN_BACK_OF) return 1;
1624         if(d[i] < -TOOLS_GL2PS_EPSILON)          1624         if(d[i] < -TOOLS_GL2PS_EPSILON)         return 1;
1625       }                                          1625       }
1626       else if(d[j] < -TOOLS_GL2PS_EPSILON){      1626       else if(d[j] < -TOOLS_GL2PS_EPSILON){
1627         if(type == TOOLS_GL2PS_COINCIDENT)       1627         if(type == TOOLS_GL2PS_COINCIDENT)       type = TOOLS_GL2PS_IN_FRONT_OF;
1628         else if(type != TOOLS_GL2PS_IN_FRONT_    1628         else if(type != TOOLS_GL2PS_IN_FRONT_OF) return 1;
1629         if(d[i] > TOOLS_GL2PS_EPSILON)           1629         if(d[i] > TOOLS_GL2PS_EPSILON)           return 1;
1630       }                                          1630       }
1631     }                                            1631     }
1632   }                                              1632   }
1633   return 0;                                      1633   return 0;
1634 }                                                1634 }
1635                                                  1635 
1636 inline tools_GLint tools_gl2psSplitPrimitive(    1636 inline tools_GLint tools_gl2psSplitPrimitive(tools_GL2PSprimitive *prim, tools_GL2PSplane plane,
1637                                  tools_GL2PSp    1637                                  tools_GL2PSprimitive **front, tools_GL2PSprimitive **back)
1638 {                                                1638 {
1639   tools_GLshort i, j, in = 0, out = 0, in0[5]    1639   tools_GLshort i, j, in = 0, out = 0, in0[5], in1[5], out0[5], out1[5];
1640   tools_GLint type;                              1640   tools_GLint type;
1641   tools_GLfloat d[5] = {0.0};                    1641   tools_GLfloat d[5] = {0.0};
1642                                                  1642 
1643   type = TOOLS_GL2PS_COINCIDENT;                 1643   type = TOOLS_GL2PS_COINCIDENT;
1644                                                  1644 
1645   for(i = 0; i < prim->numverts; i++){           1645   for(i = 0; i < prim->numverts; i++){
1646     d[i] = tools_gl2psComparePointPlane(prim-    1646     d[i] = tools_gl2psComparePointPlane(prim->verts[i].xyz, plane);
1647   }                                              1647   }
1648                                                  1648 
1649   switch(prim->type){                            1649   switch(prim->type){
1650   case TOOLS_GL2PS_POINT :                       1650   case TOOLS_GL2PS_POINT :
1651     if(d[0] > TOOLS_GL2PS_EPSILON)       type    1651     if(d[0] > TOOLS_GL2PS_EPSILON)       type = TOOLS_GL2PS_IN_BACK_OF;
1652     else if(d[0] < -TOOLS_GL2PS_EPSILON) type    1652     else if(d[0] < -TOOLS_GL2PS_EPSILON) type = TOOLS_GL2PS_IN_FRONT_OF;
1653     else                           type = TOO    1653     else                           type = TOOLS_GL2PS_COINCIDENT;
1654     break;                                       1654     break;
1655   default :                                      1655   default :
1656     for(i = 0; i < prim->numverts; i++){         1656     for(i = 0; i < prim->numverts; i++){
1657       j = tools_gl2psGetIndex(i, prim->numver    1657       j = tools_gl2psGetIndex(i, prim->numverts);
1658       if(d[j] > TOOLS_GL2PS_EPSILON){            1658       if(d[j] > TOOLS_GL2PS_EPSILON){
1659         if(type == TOOLS_GL2PS_COINCIDENT)       1659         if(type == TOOLS_GL2PS_COINCIDENT)      type = TOOLS_GL2PS_IN_BACK_OF;
1660         else if(type != TOOLS_GL2PS_IN_BACK_O    1660         else if(type != TOOLS_GL2PS_IN_BACK_OF) type = TOOLS_GL2PS_SPANNING;
1661         if(d[i] < -TOOLS_GL2PS_EPSILON){         1661         if(d[i] < -TOOLS_GL2PS_EPSILON){
1662           tools_gl2psAddIndex(in0, in1, &in,     1662           tools_gl2psAddIndex(in0, in1, &in, i, j);
1663           tools_gl2psAddIndex(out0, out1, &ou    1663           tools_gl2psAddIndex(out0, out1, &out, i, j);
1664           type = TOOLS_GL2PS_SPANNING;           1664           type = TOOLS_GL2PS_SPANNING;
1665         }                                        1665         }
1666         tools_gl2psAddIndex(out0, out1, &out,    1666         tools_gl2psAddIndex(out0, out1, &out, j, -1);
1667       }                                          1667       }
1668       else if(d[j] < -TOOLS_GL2PS_EPSILON){      1668       else if(d[j] < -TOOLS_GL2PS_EPSILON){
1669         if(type == TOOLS_GL2PS_COINCIDENT)       1669         if(type == TOOLS_GL2PS_COINCIDENT)       type = TOOLS_GL2PS_IN_FRONT_OF;
1670         else if(type != TOOLS_GL2PS_IN_FRONT_    1670         else if(type != TOOLS_GL2PS_IN_FRONT_OF) type = TOOLS_GL2PS_SPANNING;
1671         if(d[i] > TOOLS_GL2PS_EPSILON){          1671         if(d[i] > TOOLS_GL2PS_EPSILON){
1672           tools_gl2psAddIndex(in0, in1, &in,     1672           tools_gl2psAddIndex(in0, in1, &in, i, j);
1673           tools_gl2psAddIndex(out0, out1, &ou    1673           tools_gl2psAddIndex(out0, out1, &out, i, j);
1674           type = TOOLS_GL2PS_SPANNING;           1674           type = TOOLS_GL2PS_SPANNING;
1675         }                                        1675         }
1676         tools_gl2psAddIndex(in0, in1, &in, j,    1676         tools_gl2psAddIndex(in0, in1, &in, j, -1);
1677       }                                          1677       }
1678       else{                                      1678       else{
1679         tools_gl2psAddIndex(in0, in1, &in, j,    1679         tools_gl2psAddIndex(in0, in1, &in, j, -1);
1680         tools_gl2psAddIndex(out0, out1, &out,    1680         tools_gl2psAddIndex(out0, out1, &out, j, -1);
1681       }                                          1681       }
1682     }                                            1682     }
1683     break;                                       1683     break;
1684   }                                              1684   }
1685                                                  1685 
1686   if(type == TOOLS_GL2PS_SPANNING){              1686   if(type == TOOLS_GL2PS_SPANNING){
1687     *back = (tools_GL2PSprimitive*)tools_gl2p    1687     *back = (tools_GL2PSprimitive*)tools_gl2psMalloc(sizeof(tools_GL2PSprimitive));
1688     *front = (tools_GL2PSprimitive*)tools_gl2    1688     *front = (tools_GL2PSprimitive*)tools_gl2psMalloc(sizeof(tools_GL2PSprimitive));
1689     tools_gl2psCreateSplitPrimitive(prim, pla    1689     tools_gl2psCreateSplitPrimitive(prim, plane, *back, out, out0, out1);
1690     tools_gl2psCreateSplitPrimitive(prim, pla    1690     tools_gl2psCreateSplitPrimitive(prim, plane, *front, in, in0, in1);
1691   }                                              1691   }
1692                                                  1692 
1693   return type;                                   1693   return type;
1694 }                                                1694 }
1695                                                  1695 
1696 inline void tools_gl2psDivideQuad(tools_GL2PS    1696 inline void tools_gl2psDivideQuad(tools_GL2PSprimitive *quad,
1697                             tools_GL2PSprimit    1697                             tools_GL2PSprimitive **t1, tools_GL2PSprimitive **t2)
1698 {                                                1698 {
1699   *t1 = (tools_GL2PSprimitive*)tools_gl2psMal    1699   *t1 = (tools_GL2PSprimitive*)tools_gl2psMalloc(sizeof(tools_GL2PSprimitive));
1700   *t2 = (tools_GL2PSprimitive*)tools_gl2psMal    1700   *t2 = (tools_GL2PSprimitive*)tools_gl2psMalloc(sizeof(tools_GL2PSprimitive));
1701   (*t1)->type = (*t2)->type = TOOLS_GL2PS_TRI    1701   (*t1)->type = (*t2)->type = TOOLS_GL2PS_TRIANGLE;
1702   (*t1)->numverts = (*t2)->numverts = 3;         1702   (*t1)->numverts = (*t2)->numverts = 3;
1703   (*t1)->culled = (*t2)->culled = quad->culle    1703   (*t1)->culled = (*t2)->culled = quad->culled;
1704   (*t1)->offset = (*t2)->offset = quad->offse    1704   (*t1)->offset = (*t2)->offset = quad->offset;
1705   (*t1)->ofactor = (*t2)->ofactor = quad->ofa    1705   (*t1)->ofactor = (*t2)->ofactor = quad->ofactor;
1706   (*t1)->ounits = (*t2)->ounits = quad->ounit    1706   (*t1)->ounits = (*t2)->ounits = quad->ounits;
1707   (*t1)->pattern = (*t2)->pattern = quad->pat    1707   (*t1)->pattern = (*t2)->pattern = quad->pattern;
1708   (*t1)->factor = (*t2)->factor = quad->facto    1708   (*t1)->factor = (*t2)->factor = quad->factor;
1709   (*t1)->width = (*t2)->width = quad->width;     1709   (*t1)->width = (*t2)->width = quad->width;
1710   (*t1)->linecap = (*t2)->linecap = quad->lin    1710   (*t1)->linecap = (*t2)->linecap = quad->linecap;
1711   (*t1)->linejoin = (*t2)->linejoin = quad->l    1711   (*t1)->linejoin = (*t2)->linejoin = quad->linejoin;
1712   (*t1)->verts = (tools_GL2PSvertex*)tools_gl    1712   (*t1)->verts = (tools_GL2PSvertex*)tools_gl2psMalloc(3 * sizeof(tools_GL2PSvertex));
1713   (*t2)->verts = (tools_GL2PSvertex*)tools_gl    1713   (*t2)->verts = (tools_GL2PSvertex*)tools_gl2psMalloc(3 * sizeof(tools_GL2PSvertex));
1714   (*t1)->verts[0] = quad->verts[0];              1714   (*t1)->verts[0] = quad->verts[0];
1715   (*t1)->verts[1] = quad->verts[1];              1715   (*t1)->verts[1] = quad->verts[1];
1716   (*t1)->verts[2] = quad->verts[2];              1716   (*t1)->verts[2] = quad->verts[2];
1717   (*t1)->boundary = ((quad->boundary & 1) ? 1    1717   (*t1)->boundary = ((quad->boundary & 1) ? 1 : 0) | ((quad->boundary & 2) ? 2 : 0);
1718   (*t2)->verts[0] = quad->verts[0];              1718   (*t2)->verts[0] = quad->verts[0];
1719   (*t2)->verts[1] = quad->verts[2];              1719   (*t2)->verts[1] = quad->verts[2];
1720   (*t2)->verts[2] = quad->verts[3];              1720   (*t2)->verts[2] = quad->verts[3];
1721   (*t2)->boundary = ((quad->boundary & 4) ? 2    1721   (*t2)->boundary = ((quad->boundary & 4) ? 2 : 0) | ((quad->boundary & 8) ? 4 : 0);
1722 }                                                1722 }
1723                                                  1723 
1724 inline int tools_gl2psCompareDepth(const void    1724 inline int tools_gl2psCompareDepth(const void *a, const void *b)
1725 {                                                1725 {
1726   const tools_GL2PSprimitive *q, *w;             1726   const tools_GL2PSprimitive *q, *w;
1727   tools_GLfloat dq = 0.0F, dw = 0.0F, diff;      1727   tools_GLfloat dq = 0.0F, dw = 0.0F, diff;
1728   int i;                                         1728   int i;
1729                                                  1729 
1730   q = *(const tools_GL2PSprimitive* const*)a;    1730   q = *(const tools_GL2PSprimitive* const*)a;
1731   w = *(const tools_GL2PSprimitive* const*)b;    1731   w = *(const tools_GL2PSprimitive* const*)b;
1732                                                  1732 
1733   for(i = 0; i < q->numverts; i++){              1733   for(i = 0; i < q->numverts; i++){
1734     dq += q->verts[i].xyz[2];                    1734     dq += q->verts[i].xyz[2];
1735   }                                              1735   }
1736   dq /= (tools_GLfloat)q->numverts;              1736   dq /= (tools_GLfloat)q->numverts;
1737                                                  1737 
1738   for(i = 0; i < w->numverts; i++){              1738   for(i = 0; i < w->numverts; i++){
1739     dw += w->verts[i].xyz[2];                    1739     dw += w->verts[i].xyz[2];
1740   }                                              1740   }
1741   dw /= (tools_GLfloat)w->numverts;              1741   dw /= (tools_GLfloat)w->numverts;
1742                                                  1742 
1743   diff = dq - dw;                                1743   diff = dq - dw;
1744   if(diff > 0.){                                 1744   if(diff > 0.){
1745     return -1;                                   1745     return -1;
1746   }                                              1746   }
1747   else if(diff < 0.){                            1747   else if(diff < 0.){
1748     return 1;                                    1748     return 1;
1749   }                                              1749   }
1750   else{                                          1750   else{
1751     /* Ensure that initial ordering is preser    1751     /* Ensure that initial ordering is preserved when depths match. */
1752     if(q->sortid==w->sortid) return 0;  //G.B    1752     if(q->sortid==w->sortid) return 0;  //G.Barrand.
1753     return q->sortid < w->sortid ? -1 : 1;       1753     return q->sortid < w->sortid ? -1 : 1;
1754   }                                              1754   }
1755 }                                                1755 }
1756                                                  1756 
1757 inline int tools_gl2psTrianglesFirst(const vo    1757 inline int tools_gl2psTrianglesFirst(const void *a, const void *b)
1758 {                                                1758 {
1759   const tools_GL2PSprimitive *q, *w;             1759   const tools_GL2PSprimitive *q, *w;
1760                                                  1760 
1761   q = *(const tools_GL2PSprimitive* const*)a;    1761   q = *(const tools_GL2PSprimitive* const*)a;
1762   w = *(const tools_GL2PSprimitive* const*)b;    1762   w = *(const tools_GL2PSprimitive* const*)b;
1763   if(q->type==w->type) return 0;  //G.Barrand    1763   if(q->type==w->type) return 0;  //G.Barrand.
1764   return (q->type < w->type ? 1 : -1);           1764   return (q->type < w->type ? 1 : -1);
1765 }                                                1765 }
1766                                                  1766 
1767 inline tools_GLint tools_gl2psFindRoot(tools_    1767 inline tools_GLint tools_gl2psFindRoot(tools_GL2PScontext* gl2ps, tools_GL2PSlist *primitives, tools_GL2PSprimitive **root)
1768 {                                                1768 {
1769   tools_GLint i, j, count, best = 1000000, id    1769   tools_GLint i, j, count, best = 1000000, idx = 0;
1770   tools_GL2PSprimitive *prim1, *prim2;           1770   tools_GL2PSprimitive *prim1, *prim2;
1771   tools_GL2PSplane plane;                        1771   tools_GL2PSplane plane;
1772   tools_GLint maxp;                              1772   tools_GLint maxp;
1773                                                  1773 
1774   if(!tools_gl2psListNbr(primitives)){           1774   if(!tools_gl2psListNbr(primitives)){
1775     tools_gl2psMsg(TOOLS_GL2PS_ERROR, "Cannot    1775     tools_gl2psMsg(TOOLS_GL2PS_ERROR, "Cannot fint root in empty primitive list");
1776     *root = 0; /*G.Barrand: to quiet gcc.*/      1776     *root = 0; /*G.Barrand: to quiet gcc.*/
1777     return 0;                                    1777     return 0;
1778   }                                              1778   }
1779                                                  1779 
1780   *root = *(tools_GL2PSprimitive**)tools_gl2p    1780   *root = *(tools_GL2PSprimitive**)tools_gl2psListPointer(primitives, 0);
1781                                                  1781 
1782   if(gl2ps->options & TOOLS_GL2PS_BEST_ROOT){    1782   if(gl2ps->options & TOOLS_GL2PS_BEST_ROOT){
1783     maxp = tools_gl2psListNbr(primitives);       1783     maxp = tools_gl2psListNbr(primitives);
1784     if(maxp > gl2ps->maxbestroot){               1784     if(maxp > gl2ps->maxbestroot){
1785       maxp = gl2ps->maxbestroot;                 1785       maxp = gl2ps->maxbestroot;
1786     }                                            1786     }
1787     for(i = 0; i < maxp; i++){                   1787     for(i = 0; i < maxp; i++){
1788       prim1 = *(tools_GL2PSprimitive**)tools_    1788       prim1 = *(tools_GL2PSprimitive**)tools_gl2psListPointer(primitives, i);
1789       tools_gl2psGetPlane(prim1, plane);         1789       tools_gl2psGetPlane(prim1, plane);
1790       count = 0;                                 1790       count = 0;
1791       for(j = 0; j < tools_gl2psListNbr(primi    1791       for(j = 0; j < tools_gl2psListNbr(primitives); j++){
1792         if(j != i){                              1792         if(j != i){
1793           prim2 = *(tools_GL2PSprimitive**)to    1793           prim2 = *(tools_GL2PSprimitive**)tools_gl2psListPointer(primitives, j);
1794           count += tools_gl2psTestSplitPrimit    1794           count += tools_gl2psTestSplitPrimitive(prim2, plane);
1795         }                                        1795         }
1796         if(count > best) break;                  1796         if(count > best) break;
1797       }                                          1797       }
1798       if(count < best){                          1798       if(count < best){
1799         best = count;                            1799         best = count;
1800         idx = i;                                 1800         idx = i;
1801         *root = prim1;                           1801         *root = prim1;
1802         if(!count) return idx;                   1802         if(!count) return idx;
1803       }                                          1803       }
1804     }                                            1804     }
1805     /* if(index) tools_gl2psMsg(TOOLS_GL2PS_I    1805     /* if(index) tools_gl2psMsg(TOOLS_GL2PS_INFO, "TOOLS_GL2PS_BEST_ROOT was worth it: %d", index); */
1806     return idx;                                  1806     return idx;
1807   }                                              1807   }
1808   else{                                          1808   else{
1809     return 0;                                    1809     return 0;
1810   }                                              1810   }
1811 }                                                1811 }
1812                                                  1812 
1813 inline void tools_gl2psFreeImagemap(tools_GL2    1813 inline void tools_gl2psFreeImagemap(tools_GL2PSimagemap *list)
1814 {                                                1814 {
1815   tools_GL2PSimagemap *next;                     1815   tools_GL2PSimagemap *next;
1816   while(list != NULL){                           1816   while(list != NULL){
1817     next = list->next;                           1817     next = list->next;
1818     tools_gl2psFree(list->image->pixels);        1818     tools_gl2psFree(list->image->pixels);
1819     tools_gl2psFree(list->image);                1819     tools_gl2psFree(list->image);
1820     tools_gl2psFree(list);                       1820     tools_gl2psFree(list);
1821     list = next;                                 1821     list = next;
1822   }                                              1822   }
1823 }                                                1823 }
1824                                                  1824 
1825 inline void tools_gl2psFreePrimitive(void *da    1825 inline void tools_gl2psFreePrimitive(void *data)
1826 {                                                1826 {
1827   tools_GL2PSprimitive *q;                       1827   tools_GL2PSprimitive *q;
1828                                                  1828 
1829   q = *(tools_GL2PSprimitive**)data;             1829   q = *(tools_GL2PSprimitive**)data;
1830   tools_gl2psFree(q->verts);                     1830   tools_gl2psFree(q->verts);
1831   if(q->type == TOOLS_GL2PS_TEXT || q->type =    1831   if(q->type == TOOLS_GL2PS_TEXT || q->type == TOOLS_GL2PS_SPECIAL){
1832     tools_gl2psFreeText(q->data.text);           1832     tools_gl2psFreeText(q->data.text);
1833   }                                              1833   }
1834   else if(q->type == TOOLS_GL2PS_PIXMAP){        1834   else if(q->type == TOOLS_GL2PS_PIXMAP){
1835     tools_gl2psFreePixmap(q->data.image);        1835     tools_gl2psFreePixmap(q->data.image);
1836   }                                              1836   }
1837   tools_gl2psFree(q);                            1837   tools_gl2psFree(q);
1838 }                                                1838 }
1839                                                  1839 
1840 inline void tools_gl2psAddPrimitiveInList(too    1840 inline void tools_gl2psAddPrimitiveInList(tools_GL2PSprimitive *prim, tools_GL2PSlist *list)
1841 {                                                1841 {
1842   tools_GL2PSprimitive *t1, *t2;                 1842   tools_GL2PSprimitive *t1, *t2;
1843                                                  1843 
1844   if(prim->type != TOOLS_GL2PS_QUADRANGLE){      1844   if(prim->type != TOOLS_GL2PS_QUADRANGLE){
1845     tools_gl2psListAdd(list, &prim);             1845     tools_gl2psListAdd(list, &prim);
1846   }                                              1846   }
1847   else{                                          1847   else{
1848     tools_gl2psDivideQuad(prim, &t1, &t2);       1848     tools_gl2psDivideQuad(prim, &t1, &t2);
1849     tools_gl2psListAdd(list, &t1);               1849     tools_gl2psListAdd(list, &t1);
1850     tools_gl2psListAdd(list, &t2);               1850     tools_gl2psListAdd(list, &t2);
1851     tools_gl2psFreePrimitive(&prim);             1851     tools_gl2psFreePrimitive(&prim);
1852   }                                              1852   }
1853                                                  1853 
1854 }                                                1854 }
1855                                                  1855 
1856 inline void tools_gl2psFreeBspTree(tools_GL2P    1856 inline void tools_gl2psFreeBspTree(tools_GL2PSbsptree **tree)
1857 {                                                1857 {
1858   if(*tree){                                     1858   if(*tree){
1859     if((*tree)->back) tools_gl2psFreeBspTree(    1859     if((*tree)->back) tools_gl2psFreeBspTree(&(*tree)->back);
1860     if((*tree)->primitives){                     1860     if((*tree)->primitives){
1861       tools_gl2psListAction((*tree)->primitiv    1861       tools_gl2psListAction((*tree)->primitives, tools_gl2psFreePrimitive);
1862       tools_gl2psListDelete((*tree)->primitiv    1862       tools_gl2psListDelete((*tree)->primitives);
1863     }                                            1863     }
1864     if((*tree)->front) tools_gl2psFreeBspTree    1864     if((*tree)->front) tools_gl2psFreeBspTree(&(*tree)->front);
1865     tools_gl2psFree(*tree);                      1865     tools_gl2psFree(*tree);
1866     *tree = NULL;                                1866     *tree = NULL;
1867   }                                              1867   }
1868 }                                                1868 }
1869                                                  1869 
1870 inline tools_GLboolean tools_gl2psGreater(too    1870 inline tools_GLboolean tools_gl2psGreater(tools_GLfloat f1, tools_GLfloat f2)
1871 {                                                1871 {
1872   if(f1 > f2) return TOOLS_GL_TRUE;              1872   if(f1 > f2) return TOOLS_GL_TRUE;
1873   else return TOOLS_GL_FALSE;                    1873   else return TOOLS_GL_FALSE;
1874 }                                                1874 }
1875                                                  1875 
1876 inline tools_GLboolean tools_gl2psLess(tools_    1876 inline tools_GLboolean tools_gl2psLess(tools_GLfloat f1, tools_GLfloat f2)
1877 {                                                1877 {
1878   if(f1 < f2) return TOOLS_GL_TRUE;              1878   if(f1 < f2) return TOOLS_GL_TRUE;
1879   else return TOOLS_GL_FALSE;                    1879   else return TOOLS_GL_FALSE;
1880 }                                                1880 }
1881                                                  1881 
1882 inline void tools_gl2psBuildBspTree(tools_GL2    1882 inline void tools_gl2psBuildBspTree(tools_GL2PScontext* gl2ps, tools_GL2PSbsptree *tree, tools_GL2PSlist *primitives)
1883 {                                                1883 {
1884   tools_GL2PSprimitive *prim = NULL, *frontpr    1884   tools_GL2PSprimitive *prim = NULL, *frontprim = NULL, *backprim = NULL;
1885   tools_GL2PSlist *frontlist, *backlist;         1885   tools_GL2PSlist *frontlist, *backlist;
1886   tools_GLint i, idx;                            1886   tools_GLint i, idx;
1887                                                  1887 
1888   tree->front = NULL;                            1888   tree->front = NULL;
1889   tree->back = NULL;                             1889   tree->back = NULL;
1890   tree->primitives = tools_gl2psListCreate(1,    1890   tree->primitives = tools_gl2psListCreate(1, 2, sizeof(tools_GL2PSprimitive*));
1891   idx = tools_gl2psFindRoot(gl2ps, primitives    1891   idx = tools_gl2psFindRoot(gl2ps, primitives, &prim);
1892   tools_gl2psGetPlane(prim, tree->plane);        1892   tools_gl2psGetPlane(prim, tree->plane);
1893   tools_gl2psAddPrimitiveInList(prim, tree->p    1893   tools_gl2psAddPrimitiveInList(prim, tree->primitives);
1894                                                  1894 
1895   frontlist = tools_gl2psListCreate(1, 2, siz    1895   frontlist = tools_gl2psListCreate(1, 2, sizeof(tools_GL2PSprimitive*));
1896   backlist = tools_gl2psListCreate(1, 2, size    1896   backlist = tools_gl2psListCreate(1, 2, sizeof(tools_GL2PSprimitive*));
1897                                                  1897 
1898   for(i = 0; i < tools_gl2psListNbr(primitive    1898   for(i = 0; i < tools_gl2psListNbr(primitives); i++){
1899     if(i != idx){                                1899     if(i != idx){
1900       prim = *(tools_GL2PSprimitive**)tools_g    1900       prim = *(tools_GL2PSprimitive**)tools_gl2psListPointer(primitives,i);
1901       switch(tools_gl2psSplitPrimitive(prim,     1901       switch(tools_gl2psSplitPrimitive(prim, tree->plane, &frontprim, &backprim)){
1902       case TOOLS_GL2PS_COINCIDENT:               1902       case TOOLS_GL2PS_COINCIDENT:
1903         tools_gl2psAddPrimitiveInList(prim, t    1903         tools_gl2psAddPrimitiveInList(prim, tree->primitives);
1904         break;                                   1904         break;
1905       case TOOLS_GL2PS_IN_BACK_OF:               1905       case TOOLS_GL2PS_IN_BACK_OF:
1906         tools_gl2psAddPrimitiveInList(prim, b    1906         tools_gl2psAddPrimitiveInList(prim, backlist);
1907         break;                                   1907         break;
1908       case TOOLS_GL2PS_IN_FRONT_OF:              1908       case TOOLS_GL2PS_IN_FRONT_OF:
1909         tools_gl2psAddPrimitiveInList(prim, f    1909         tools_gl2psAddPrimitiveInList(prim, frontlist);
1910         break;                                   1910         break;
1911       case TOOLS_GL2PS_SPANNING:                 1911       case TOOLS_GL2PS_SPANNING:
1912         tools_gl2psAddPrimitiveInList(backpri    1912         tools_gl2psAddPrimitiveInList(backprim, backlist);
1913         tools_gl2psAddPrimitiveInList(frontpr    1913         tools_gl2psAddPrimitiveInList(frontprim, frontlist);
1914         tools_gl2psFreePrimitive(&prim);         1914         tools_gl2psFreePrimitive(&prim);
1915         break;                                   1915         break;
1916       }                                          1916       }
1917     }                                            1917     }
1918   }                                              1918   }
1919                                                  1919 
1920   if(tools_gl2psListNbr(tree->primitives)){      1920   if(tools_gl2psListNbr(tree->primitives)){
1921     tools_gl2psListSort(gl2ps, tree->primitiv    1921     tools_gl2psListSort(gl2ps, tree->primitives, tools_gl2psTrianglesFirst);
1922   }                                              1922   }
1923                                                  1923 
1924   if(tools_gl2psListNbr(frontlist)){             1924   if(tools_gl2psListNbr(frontlist)){
1925     tools_gl2psListSort(gl2ps, frontlist, too    1925     tools_gl2psListSort(gl2ps, frontlist, tools_gl2psTrianglesFirst);
1926     tree->front = (tools_GL2PSbsptree*)tools_    1926     tree->front = (tools_GL2PSbsptree*)tools_gl2psMalloc(sizeof(tools_GL2PSbsptree));
1927     tools_gl2psBuildBspTree(gl2ps, tree->fron    1927     tools_gl2psBuildBspTree(gl2ps, tree->front, frontlist);
1928   }                                              1928   }
1929   else{                                          1929   else{
1930     tools_gl2psListDelete(frontlist);            1930     tools_gl2psListDelete(frontlist);
1931   }                                              1931   }
1932                                                  1932 
1933   if(tools_gl2psListNbr(backlist)){              1933   if(tools_gl2psListNbr(backlist)){
1934     tools_gl2psListSort(gl2ps, backlist, tool    1934     tools_gl2psListSort(gl2ps, backlist, tools_gl2psTrianglesFirst);
1935     tree->back = (tools_GL2PSbsptree*)tools_g    1935     tree->back = (tools_GL2PSbsptree*)tools_gl2psMalloc(sizeof(tools_GL2PSbsptree));
1936     tools_gl2psBuildBspTree(gl2ps, tree->back    1936     tools_gl2psBuildBspTree(gl2ps, tree->back, backlist);
1937   }                                              1937   }
1938   else{                                          1938   else{
1939     tools_gl2psListDelete(backlist);             1939     tools_gl2psListDelete(backlist);
1940   }                                              1940   }
1941                                                  1941 
1942   tools_gl2psListDelete(primitives);             1942   tools_gl2psListDelete(primitives);
1943 }                                                1943 }
1944                                                  1944 
1945 inline void tools_gl2psTraverseBspTree(tools_    1945 inline void tools_gl2psTraverseBspTree(tools_GL2PScontext* gl2ps, tools_GL2PSbsptree *tree, tools_GL2PSxyz eye, tools_GLfloat epsilon,
1946                                  tools_GLbool    1946                                  tools_GLboolean (*compare)(tools_GLfloat f1, tools_GLfloat f2),
1947                                  void (*actio    1947                                  void (*action)(tools_GL2PScontext*, void *data), int inverse)
1948 {                                                1948 {
1949   tools_GLfloat result;                          1949   tools_GLfloat result;
1950                                                  1950 
1951   if(!tree) return;                              1951   if(!tree) return;
1952                                                  1952 
1953   result = tools_gl2psComparePointPlane(eye,     1953   result = tools_gl2psComparePointPlane(eye, tree->plane);
1954                                                  1954 
1955   if(TOOLS_GL_TRUE == compare(result, epsilon    1955   if(TOOLS_GL_TRUE == compare(result, epsilon)){
1956     tools_gl2psTraverseBspTree(gl2ps, tree->b    1956     tools_gl2psTraverseBspTree(gl2ps, tree->back, eye, epsilon, compare, action, inverse);
1957     if(inverse){                                 1957     if(inverse){
1958       tools_gl2psListActionInverseContext(gl2    1958       tools_gl2psListActionInverseContext(gl2ps, tree->primitives, action);
1959     }                                            1959     }
1960     else{                                        1960     else{
1961       tools_gl2psListActionContext(gl2ps, tre    1961       tools_gl2psListActionContext(gl2ps, tree->primitives, action);
1962     }                                            1962     }
1963     tools_gl2psTraverseBspTree(gl2ps, tree->f    1963     tools_gl2psTraverseBspTree(gl2ps, tree->front, eye, epsilon, compare, action, inverse);
1964   }                                              1964   }
1965   else if(TOOLS_GL_TRUE == compare(-epsilon,     1965   else if(TOOLS_GL_TRUE == compare(-epsilon, result)){
1966     tools_gl2psTraverseBspTree(gl2ps, tree->f    1966     tools_gl2psTraverseBspTree(gl2ps, tree->front, eye, epsilon, compare, action, inverse);
1967     if(inverse){                                 1967     if(inverse){
1968       tools_gl2psListActionInverseContext(gl2    1968       tools_gl2psListActionInverseContext(gl2ps, tree->primitives, action);
1969     }                                            1969     }
1970     else{                                        1970     else{
1971       tools_gl2psListActionContext(gl2ps, tre    1971       tools_gl2psListActionContext(gl2ps, tree->primitives, action);
1972     }                                            1972     }
1973     tools_gl2psTraverseBspTree(gl2ps, tree->b    1973     tools_gl2psTraverseBspTree(gl2ps, tree->back, eye, epsilon, compare, action, inverse);
1974   }                                              1974   }
1975   else{                                          1975   else{
1976     tools_gl2psTraverseBspTree(gl2ps, tree->f    1976     tools_gl2psTraverseBspTree(gl2ps, tree->front, eye, epsilon, compare, action, inverse);
1977     tools_gl2psTraverseBspTree(gl2ps, tree->b    1977     tools_gl2psTraverseBspTree(gl2ps, tree->back, eye, epsilon, compare, action, inverse);
1978   }                                              1978   }
1979 }                                                1979 }
1980                                                  1980 
1981 inline void tools_gl2psRescaleAndOffset(tools    1981 inline void tools_gl2psRescaleAndOffset(tools_GL2PScontext* gl2ps)
1982 {                                                1982 {
1983   tools_GL2PSprimitive *prim;                    1983   tools_GL2PSprimitive *prim;
1984   tools_GLfloat minZ, maxZ, rangeZ, scaleZ;      1984   tools_GLfloat minZ, maxZ, rangeZ, scaleZ;
1985   tools_GLfloat factor, units, area, dZ, dZdX    1985   tools_GLfloat factor, units, area, dZ, dZdX, dZdY, maxdZ;
1986   int i, j;                                      1986   int i, j;
1987                                                  1987 
1988   if(!tools_gl2psListNbr(gl2ps->primitives))     1988   if(!tools_gl2psListNbr(gl2ps->primitives))
1989     return;                                      1989     return;
1990                                                  1990 
1991   /* get z-buffer range */                       1991   /* get z-buffer range */
1992   prim = *(tools_GL2PSprimitive**)tools_gl2ps    1992   prim = *(tools_GL2PSprimitive**)tools_gl2psListPointer(gl2ps->primitives, 0);
1993   minZ = maxZ = prim->verts[0].xyz[2];           1993   minZ = maxZ = prim->verts[0].xyz[2];
1994   for(i = 1; i < prim->numverts; i++){           1994   for(i = 1; i < prim->numverts; i++){
1995     if(prim->verts[i].xyz[2] < minZ) minZ = p    1995     if(prim->verts[i].xyz[2] < minZ) minZ = prim->verts[i].xyz[2];
1996     if(prim->verts[i].xyz[2] > maxZ) maxZ = p    1996     if(prim->verts[i].xyz[2] > maxZ) maxZ = prim->verts[i].xyz[2];
1997   }                                              1997   }
1998   for(i = 1; i < tools_gl2psListNbr(gl2ps->pr    1998   for(i = 1; i < tools_gl2psListNbr(gl2ps->primitives); i++){
1999     prim = *(tools_GL2PSprimitive**)tools_gl2    1999     prim = *(tools_GL2PSprimitive**)tools_gl2psListPointer(gl2ps->primitives, i);
2000     for(j = 0; j < prim->numverts; j++){         2000     for(j = 0; j < prim->numverts; j++){
2001       if(prim->verts[j].xyz[2] < minZ) minZ =    2001       if(prim->verts[j].xyz[2] < minZ) minZ = prim->verts[j].xyz[2];
2002       if(prim->verts[j].xyz[2] > maxZ) maxZ =    2002       if(prim->verts[j].xyz[2] > maxZ) maxZ = prim->verts[j].xyz[2];
2003     }                                            2003     }
2004   }                                              2004   }
2005   rangeZ = (maxZ - minZ);                        2005   rangeZ = (maxZ - minZ);
2006                                                  2006 
2007   /* rescale z-buffer coordinate in [0,TOOLS_    2007   /* rescale z-buffer coordinate in [0,TOOLS_GL2PS_ZSCALE], to make it of
2008      the same order of magnitude as the x and    2008      the same order of magnitude as the x and y coordinates */
2009   scaleZ = TOOLS_GL2PS_ZERO(rangeZ) ? TOOLS_G    2009   scaleZ = TOOLS_GL2PS_ZERO(rangeZ) ? TOOLS_GL2PS_ZSCALE : (TOOLS_GL2PS_ZSCALE / rangeZ);
2010   /* avoid precision loss (we use floats!) */    2010   /* avoid precision loss (we use floats!) */
2011   if(scaleZ > 100000.F) scaleZ = 100000.F;       2011   if(scaleZ > 100000.F) scaleZ = 100000.F;
2012                                                  2012 
2013   /* apply offsets */                            2013   /* apply offsets */
2014   for(i = 0; i < tools_gl2psListNbr(gl2ps->pr    2014   for(i = 0; i < tools_gl2psListNbr(gl2ps->primitives); i++){
2015     prim = *(tools_GL2PSprimitive**)tools_gl2    2015     prim = *(tools_GL2PSprimitive**)tools_gl2psListPointer(gl2ps->primitives, i);
2016     for(j = 0; j < prim->numverts; j++){         2016     for(j = 0; j < prim->numverts; j++){
2017       prim->verts[j].xyz[2] = (prim->verts[j]    2017       prim->verts[j].xyz[2] = (prim->verts[j].xyz[2] - minZ) * scaleZ;
2018     }                                            2018     }
2019     if((gl2ps->options & TOOLS_GL2PS_SIMPLE_L    2019     if((gl2ps->options & TOOLS_GL2PS_SIMPLE_LINE_OFFSET) &&
2020        (prim->type == TOOLS_GL2PS_LINE)){        2020        (prim->type == TOOLS_GL2PS_LINE)){
2021       if(gl2ps->sort == TOOLS_GL2PS_SIMPLE_SO    2021       if(gl2ps->sort == TOOLS_GL2PS_SIMPLE_SORT){
2022         prim->verts[0].xyz[2] -= TOOLS_GL2PS_    2022         prim->verts[0].xyz[2] -= TOOLS_GL2PS_ZOFFSET_LARGE;
2023         prim->verts[1].xyz[2] -= TOOLS_GL2PS_    2023         prim->verts[1].xyz[2] -= TOOLS_GL2PS_ZOFFSET_LARGE;
2024       }                                          2024       }
2025       else{                                      2025       else{
2026         prim->verts[0].xyz[2] -= TOOLS_GL2PS_    2026         prim->verts[0].xyz[2] -= TOOLS_GL2PS_ZOFFSET;
2027         prim->verts[1].xyz[2] -= TOOLS_GL2PS_    2027         prim->verts[1].xyz[2] -= TOOLS_GL2PS_ZOFFSET;
2028       }                                          2028       }
2029     }                                            2029     }
2030     else if(prim->offset && (prim->type == TO    2030     else if(prim->offset && (prim->type == TOOLS_GL2PS_TRIANGLE)){
2031       factor = prim->ofactor;                    2031       factor = prim->ofactor;
2032       units = prim->ounits;                      2032       units = prim->ounits;
2033       area =                                     2033       area =
2034         (prim->verts[1].xyz[0] - prim->verts[    2034         (prim->verts[1].xyz[0] - prim->verts[0].xyz[0]) *
2035         (prim->verts[2].xyz[1] - prim->verts[    2035         (prim->verts[2].xyz[1] - prim->verts[1].xyz[1]) -
2036         (prim->verts[2].xyz[0] - prim->verts[    2036         (prim->verts[2].xyz[0] - prim->verts[1].xyz[0]) *
2037         (prim->verts[1].xyz[1] - prim->verts[    2037         (prim->verts[1].xyz[1] - prim->verts[0].xyz[1]);
2038       if(!TOOLS_GL2PS_ZERO(area)){               2038       if(!TOOLS_GL2PS_ZERO(area)){
2039         dZdX =                                   2039         dZdX =
2040           ((prim->verts[2].xyz[1] - prim->ver    2040           ((prim->verts[2].xyz[1] - prim->verts[1].xyz[1]) *
2041            (prim->verts[1].xyz[2] - prim->ver    2041            (prim->verts[1].xyz[2] - prim->verts[0].xyz[2]) -
2042            (prim->verts[1].xyz[1] - prim->ver    2042            (prim->verts[1].xyz[1] - prim->verts[0].xyz[1]) *
2043            (prim->verts[2].xyz[2] - prim->ver    2043            (prim->verts[2].xyz[2] - prim->verts[1].xyz[2])) / area;
2044         dZdY =                                   2044         dZdY =
2045           ((prim->verts[1].xyz[0] - prim->ver    2045           ((prim->verts[1].xyz[0] - prim->verts[0].xyz[0]) *
2046            (prim->verts[2].xyz[2] - prim->ver    2046            (prim->verts[2].xyz[2] - prim->verts[1].xyz[2]) -
2047            (prim->verts[2].xyz[0] - prim->ver    2047            (prim->verts[2].xyz[0] - prim->verts[1].xyz[0]) *
2048            (prim->verts[1].xyz[2] - prim->ver    2048            (prim->verts[1].xyz[2] - prim->verts[0].xyz[2])) / area;
2049         maxdZ = (tools_GLfloat)sqrt(dZdX * dZ    2049         maxdZ = (tools_GLfloat)sqrt(dZdX * dZdX + dZdY * dZdY);
2050       }                                          2050       }
2051       else{                                      2051       else{
2052         maxdZ = 0.0F;                            2052         maxdZ = 0.0F;
2053       }                                          2053       }
2054       dZ = factor * maxdZ + units;               2054       dZ = factor * maxdZ + units;
2055       prim->verts[0].xyz[2] += dZ;               2055       prim->verts[0].xyz[2] += dZ;
2056       prim->verts[1].xyz[2] += dZ;               2056       prim->verts[1].xyz[2] += dZ;
2057       prim->verts[2].xyz[2] += dZ;               2057       prim->verts[2].xyz[2] += dZ;
2058     }                                            2058     }
2059   }                                              2059   }
2060 }                                                2060 }
2061                                                  2061 
2062 /********************************************    2062 /*********************************************************************
2063  *                                               2063  *
2064  * 2D sorting routines (for occlusion culling    2064  * 2D sorting routines (for occlusion culling)
2065  *                                               2065  *
2066  ********************************************    2066  *********************************************************************/
2067                                                  2067 
2068 inline tools_GLint tools_gl2psGetPlaneFromPoi    2068 inline tools_GLint tools_gl2psGetPlaneFromPoints(tools_GL2PSxyz a, tools_GL2PSxyz b, tools_GL2PSplane plane)
2069 {                                                2069 {
2070   tools_GLfloat n;                               2070   tools_GLfloat n;
2071                                                  2071 
2072   plane[0] = b[1] - a[1];                        2072   plane[0] = b[1] - a[1];
2073   plane[1] = a[0] - b[0];                        2073   plane[1] = a[0] - b[0];
2074   n = (tools_GLfloat)sqrt(plane[0]*plane[0] +    2074   n = (tools_GLfloat)sqrt(plane[0]*plane[0] + plane[1]*plane[1]);
2075   plane[2] = 0.0F;                               2075   plane[2] = 0.0F;
2076   if(!TOOLS_GL2PS_ZERO(n)){                      2076   if(!TOOLS_GL2PS_ZERO(n)){
2077     plane[0] /= n;                               2077     plane[0] /= n;
2078     plane[1] /= n;                               2078     plane[1] /= n;
2079     plane[3] = -plane[0]*a[0]-plane[1]*a[1];     2079     plane[3] = -plane[0]*a[0]-plane[1]*a[1];
2080     return 1;                                    2080     return 1;
2081   }                                              2081   }
2082   else{                                          2082   else{
2083     plane[0] = -1.0F;                            2083     plane[0] = -1.0F;
2084     plane[1] = 0.0F;                             2084     plane[1] = 0.0F;
2085     plane[3] = a[0];                             2085     plane[3] = a[0];
2086     return 0;                                    2086     return 0;
2087   }                                              2087   }
2088 }                                                2088 }
2089                                                  2089 
2090 inline void tools_gl2psFreeBspImageTree(tools    2090 inline void tools_gl2psFreeBspImageTree(tools_GL2PSbsptree2d **tree)
2091 {                                                2091 {
2092   if(*tree){                                     2092   if(*tree){
2093     if((*tree)->back)  tools_gl2psFreeBspImag    2093     if((*tree)->back)  tools_gl2psFreeBspImageTree(&(*tree)->back);
2094     if((*tree)->front) tools_gl2psFreeBspImag    2094     if((*tree)->front) tools_gl2psFreeBspImageTree(&(*tree)->front);
2095     tools_gl2psFree(*tree);                      2095     tools_gl2psFree(*tree);
2096     *tree = NULL;                                2096     *tree = NULL;
2097   }                                              2097   }
2098 }                                                2098 }
2099                                                  2099 
2100 inline tools_GLint tools_gl2psCheckPoint(tool    2100 inline tools_GLint tools_gl2psCheckPoint(tools_GL2PSxyz point, tools_GL2PSplane plane)
2101 {                                                2101 {
2102   tools_GLfloat pt_dis;                          2102   tools_GLfloat pt_dis;
2103                                                  2103 
2104   pt_dis = tools_gl2psComparePointPlane(point    2104   pt_dis = tools_gl2psComparePointPlane(point, plane);
2105   if(pt_dis > TOOLS_GL2PS_EPSILON)        ret    2105   if(pt_dis > TOOLS_GL2PS_EPSILON)        return TOOLS_GL2PS_POINT_INFRONT;
2106   else if(pt_dis < -TOOLS_GL2PS_EPSILON)  ret    2106   else if(pt_dis < -TOOLS_GL2PS_EPSILON)  return TOOLS_GL2PS_POINT_BACK;
2107   else                              return TO    2107   else                              return TOOLS_GL2PS_POINT_COINCIDENT;
2108 }                                                2108 }
2109                                                  2109 
2110 inline void tools_gl2psAddPlanesInBspTreeImag    2110 inline void tools_gl2psAddPlanesInBspTreeImage(tools_GL2PSprimitive *prim,
2111                                          tool    2111                                          tools_GL2PSbsptree2d **tree)
2112 {                                                2112 {
2113   tools_GLint ret = 0;                           2113   tools_GLint ret = 0;
2114   tools_GLint i;                                 2114   tools_GLint i;
2115   tools_GLint offset = 0;                        2115   tools_GLint offset = 0;
2116   tools_GL2PSbsptree2d *head = NULL, *cur = N    2116   tools_GL2PSbsptree2d *head = NULL, *cur = NULL;
2117                                                  2117 
2118   if((*tree == NULL) && (prim->numverts > 2))    2118   if((*tree == NULL) && (prim->numverts > 2)){
2119     /* don't cull if transparent                 2119     /* don't cull if transparent
2120     for(i = 0; i < prim->numverts - 1; i++)      2120     for(i = 0; i < prim->numverts - 1; i++)
2121       if(prim->verts[i].rgba[3] < 1.0F) retur    2121       if(prim->verts[i].rgba[3] < 1.0F) return;
2122     */                                           2122     */
2123     head = (tools_GL2PSbsptree2d*)tools_gl2ps    2123     head = (tools_GL2PSbsptree2d*)tools_gl2psMalloc(sizeof(tools_GL2PSbsptree2d));
2124     for(i = 0; i < prim->numverts-1; i++){       2124     for(i = 0; i < prim->numverts-1; i++){
2125       if(!tools_gl2psGetPlaneFromPoints(prim-    2125       if(!tools_gl2psGetPlaneFromPoints(prim->verts[i].xyz,
2126                                   prim->verts    2126                                   prim->verts[i+1].xyz,
2127                                   head->plane    2127                                   head->plane)){
2128         if(prim->numverts-i > 3){                2128         if(prim->numverts-i > 3){
2129           offset++;                              2129           offset++;
2130         }                                        2130         }
2131         else{                                    2131         else{
2132           tools_gl2psFree(head);                 2132           tools_gl2psFree(head);
2133           return;                                2133           return;
2134         }                                        2134         }
2135       }                                          2135       }
2136       else{                                      2136       else{
2137         break;                                   2137         break;
2138       }                                          2138       }
2139     }                                            2139     }
2140     head->back = NULL;                           2140     head->back = NULL;
2141     head->front = NULL;                          2141     head->front = NULL;
2142     for(i = 2+offset; i < prim->numverts; i++    2142     for(i = 2+offset; i < prim->numverts; i++){
2143       ret = tools_gl2psCheckPoint(prim->verts    2143       ret = tools_gl2psCheckPoint(prim->verts[i].xyz, head->plane);
2144       if(ret != TOOLS_GL2PS_POINT_COINCIDENT)    2144       if(ret != TOOLS_GL2PS_POINT_COINCIDENT) break;
2145     }                                            2145     }
2146     switch(ret){                                 2146     switch(ret){
2147     case TOOLS_GL2PS_POINT_INFRONT :             2147     case TOOLS_GL2PS_POINT_INFRONT :
2148       cur = head;                                2148       cur = head;
2149       for(i = 1+offset; i < prim->numverts-1;    2149       for(i = 1+offset; i < prim->numverts-1; i++){
2150         if(cur->front == NULL){                  2150         if(cur->front == NULL){
2151           cur->front = (tools_GL2PSbsptree2d*    2151           cur->front = (tools_GL2PSbsptree2d*)tools_gl2psMalloc(sizeof(tools_GL2PSbsptree2d));
2152         }                                        2152         }
2153         if(tools_gl2psGetPlaneFromPoints(prim    2153         if(tools_gl2psGetPlaneFromPoints(prim->verts[i].xyz,
2154                                    prim->vert    2154                                    prim->verts[i+1].xyz,
2155                                    cur->front    2155                                    cur->front->plane)){
2156           cur = cur->front;                      2156           cur = cur->front;
2157           cur->front = NULL;                     2157           cur->front = NULL;
2158           cur->back = NULL;                      2158           cur->back = NULL;
2159         }                                        2159         }
2160       }                                          2160       }
2161       if(cur->front == NULL){                    2161       if(cur->front == NULL){
2162         cur->front = (tools_GL2PSbsptree2d*)t    2162         cur->front = (tools_GL2PSbsptree2d*)tools_gl2psMalloc(sizeof(tools_GL2PSbsptree2d));
2163       }                                          2163       }
2164       if(tools_gl2psGetPlaneFromPoints(prim->    2164       if(tools_gl2psGetPlaneFromPoints(prim->verts[i].xyz,
2165                                  prim->verts[    2165                                  prim->verts[offset].xyz,
2166                                  cur->front->    2166                                  cur->front->plane)){
2167         cur->front->front = NULL;                2167         cur->front->front = NULL;
2168         cur->front->back = NULL;                 2168         cur->front->back = NULL;
2169       }                                          2169       }
2170       else{                                      2170       else{
2171         tools_gl2psFree(cur->front);             2171         tools_gl2psFree(cur->front);
2172         cur->front = NULL;                       2172         cur->front = NULL;
2173       }                                          2173       }
2174       break;                                     2174       break;
2175     case TOOLS_GL2PS_POINT_BACK :                2175     case TOOLS_GL2PS_POINT_BACK :
2176       for(i = 0; i < 4; i++){                    2176       for(i = 0; i < 4; i++){
2177         head->plane[i] = -head->plane[i];        2177         head->plane[i] = -head->plane[i];
2178       }                                          2178       }
2179       cur = head;                                2179       cur = head;
2180       for(i = 1+offset; i < prim->numverts-1;    2180       for(i = 1+offset; i < prim->numverts-1; i++){
2181         if(cur->front == NULL){                  2181         if(cur->front == NULL){
2182           cur->front = (tools_GL2PSbsptree2d*    2182           cur->front = (tools_GL2PSbsptree2d*)tools_gl2psMalloc(sizeof(tools_GL2PSbsptree2d));
2183         }                                        2183         }
2184         if(tools_gl2psGetPlaneFromPoints(prim    2184         if(tools_gl2psGetPlaneFromPoints(prim->verts[i+1].xyz,
2185                                    prim->vert    2185                                    prim->verts[i].xyz,
2186                                    cur->front    2186                                    cur->front->plane)){
2187           cur = cur->front;                      2187           cur = cur->front;
2188           cur->front = NULL;                     2188           cur->front = NULL;
2189           cur->back = NULL;                      2189           cur->back = NULL;
2190         }                                        2190         }
2191       }                                          2191       }
2192       if(cur->front == NULL){                    2192       if(cur->front == NULL){
2193         cur->front = (tools_GL2PSbsptree2d*)t    2193         cur->front = (tools_GL2PSbsptree2d*)tools_gl2psMalloc(sizeof(tools_GL2PSbsptree2d));
2194       }                                          2194       }
2195       if(tools_gl2psGetPlaneFromPoints(prim->    2195       if(tools_gl2psGetPlaneFromPoints(prim->verts[offset].xyz,
2196                                  prim->verts[    2196                                  prim->verts[i].xyz,
2197                                  cur->front->    2197                                  cur->front->plane)){
2198         cur->front->front = NULL;                2198         cur->front->front = NULL;
2199         cur->front->back = NULL;                 2199         cur->front->back = NULL;
2200       }                                          2200       }
2201       else{                                      2201       else{
2202         tools_gl2psFree(cur->front);             2202         tools_gl2psFree(cur->front);
2203         cur->front = NULL;                       2203         cur->front = NULL;
2204       }                                          2204       }
2205       break;                                     2205       break;
2206     default:                                     2206     default:
2207       tools_gl2psFree(head);                     2207       tools_gl2psFree(head);
2208       return;                                    2208       return;
2209     }                                            2209     }
2210     (*tree) = head;                              2210     (*tree) = head;
2211   }                                              2211   }
2212 }                                                2212 }
2213                                                  2213 
2214 inline tools_GLint tools_gl2psCheckPrimitive(    2214 inline tools_GLint tools_gl2psCheckPrimitive(tools_GL2PSprimitive *prim, tools_GL2PSplane plane)
2215 {                                                2215 {
2216   tools_GLint i;                                 2216   tools_GLint i;
2217   tools_GLint pos;                               2217   tools_GLint pos;
2218                                                  2218 
2219   pos = tools_gl2psCheckPoint(prim->verts[0].    2219   pos = tools_gl2psCheckPoint(prim->verts[0].xyz, plane);
2220   for(i = 1; i < prim->numverts; i++){           2220   for(i = 1; i < prim->numverts; i++){
2221     pos |= tools_gl2psCheckPoint(prim->verts[    2221     pos |= tools_gl2psCheckPoint(prim->verts[i].xyz, plane);
2222     if(pos == (TOOLS_GL2PS_POINT_INFRONT | TO    2222     if(pos == (TOOLS_GL2PS_POINT_INFRONT | TOOLS_GL2PS_POINT_BACK)) return TOOLS_GL2PS_SPANNING;
2223   }                                              2223   }
2224   if(pos & TOOLS_GL2PS_POINT_INFRONT)   retur    2224   if(pos & TOOLS_GL2PS_POINT_INFRONT)   return TOOLS_GL2PS_IN_FRONT_OF;
2225   else if(pos & TOOLS_GL2PS_POINT_BACK) retur    2225   else if(pos & TOOLS_GL2PS_POINT_BACK) return TOOLS_GL2PS_IN_BACK_OF;
2226   else                            return TOOL    2226   else                            return TOOLS_GL2PS_COINCIDENT;
2227 }                                                2227 }
2228                                                  2228 
2229 inline tools_GL2PSprimitive *tools_gl2psCreat    2229 inline tools_GL2PSprimitive *tools_gl2psCreateSplitPrimitive2D(tools_GL2PSprimitive *parent,
2230                                                  2230                                                    tools_GLshort numverts,
2231                                                  2231                                                    tools_GL2PSvertex *vertx)
2232 {                                                2232 {
2233   tools_GLint i;                                 2233   tools_GLint i;
2234   tools_GL2PSprimitive *child = (tools_GL2PSp    2234   tools_GL2PSprimitive *child = (tools_GL2PSprimitive*)tools_gl2psMalloc(sizeof(tools_GL2PSprimitive));
2235                                                  2235 
2236   if(parent->type == TOOLS_GL2PS_IMAGEMAP){      2236   if(parent->type == TOOLS_GL2PS_IMAGEMAP){
2237     child->type = TOOLS_GL2PS_IMAGEMAP;          2237     child->type = TOOLS_GL2PS_IMAGEMAP;
2238     child->data.image = parent->data.image;      2238     child->data.image = parent->data.image;
2239   }                                              2239   }
2240   else {                                         2240   else {
2241     switch(numverts){                            2241     switch(numverts){
2242     case 1 : child->type = TOOLS_GL2PS_POINT;    2242     case 1 : child->type = TOOLS_GL2PS_POINT; break;
2243     case 2 : child->type = TOOLS_GL2PS_LINE;     2243     case 2 : child->type = TOOLS_GL2PS_LINE; break;
2244     case 3 : child->type = TOOLS_GL2PS_TRIANG    2244     case 3 : child->type = TOOLS_GL2PS_TRIANGLE; break;
2245     case 4 : child->type = TOOLS_GL2PS_QUADRA    2245     case 4 : child->type = TOOLS_GL2PS_QUADRANGLE; break;
2246     default: child->type = TOOLS_GL2PS_NO_TYP    2246     default: child->type = TOOLS_GL2PS_NO_TYPE; break; /* FIXME */
2247     }                                            2247     }
2248   }                                              2248   }
2249   child->boundary = 0; /* FIXME: not done! */    2249   child->boundary = 0; /* FIXME: not done! */
2250   child->culled = parent->culled;                2250   child->culled = parent->culled;
2251   child->offset = parent->offset;                2251   child->offset = parent->offset;
2252   child->ofactor = parent->ofactor;              2252   child->ofactor = parent->ofactor;
2253   child->ounits = parent->ounits;                2253   child->ounits = parent->ounits;
2254   child->pattern = parent->pattern;              2254   child->pattern = parent->pattern;
2255   child->factor = parent->factor;                2255   child->factor = parent->factor;
2256   child->width = parent->width;                  2256   child->width = parent->width;
2257   child->linecap = parent->linecap;              2257   child->linecap = parent->linecap;
2258   child->linejoin = parent->linejoin;            2258   child->linejoin = parent->linejoin;
2259   child->numverts = numverts;                    2259   child->numverts = numverts;
2260   child->verts = (tools_GL2PSvertex*)tools_gl    2260   child->verts = (tools_GL2PSvertex*)tools_gl2psMalloc(numverts * sizeof(tools_GL2PSvertex));
2261   for(i = 0; i < numverts; i++){                 2261   for(i = 0; i < numverts; i++){
2262     child->verts[i] = vertx[i];                  2262     child->verts[i] = vertx[i];
2263   }                                              2263   }
2264   return child;                                  2264   return child;
2265 }                                                2265 }
2266                                                  2266 
2267 inline void tools_gl2psSplitPrimitive2D(tools    2267 inline void tools_gl2psSplitPrimitive2D(tools_GL2PSprimitive *prim,
2268                                   tools_GL2PS    2268                                   tools_GL2PSplane plane,
2269                                   tools_GL2PS    2269                                   tools_GL2PSprimitive **front,
2270                                   tools_GL2PS    2270                                   tools_GL2PSprimitive **back)
2271 {                                                2271 {
2272   /* cur will hold the position of the curren    2272   /* cur will hold the position of the current vertex
2273      prev will hold the position of the previ    2273      prev will hold the position of the previous vertex
2274      prev0 will hold the position of the vert    2274      prev0 will hold the position of the vertex number 0
2275      v1 and v2 represent the current and prev    2275      v1 and v2 represent the current and previous vertices, respectively
2276      flag is set if the current vertex should    2276      flag is set if the current vertex should be checked against the plane */
2277   tools_GLint cur = -1, prev = -1, i, v1 = 0,    2277   tools_GLint cur = -1, prev = -1, i, v1 = 0, v2 = 0, flag = 1, prev0 = -1;
2278                                                  2278 
2279   /* list of vertices that will go in front a    2279   /* list of vertices that will go in front and back primitive */
2280   tools_GL2PSvertex *front_list = NULL, *back    2280   tools_GL2PSvertex *front_list = NULL, *back_list = NULL;
2281                                                  2281 
2282   /* number of vertices in front and back lis    2282   /* number of vertices in front and back list */
2283   tools_GLshort front_count = 0, back_count =    2283   tools_GLshort front_count = 0, back_count = 0;
2284                                                  2284 
2285   for(i = 0; i <= prim->numverts; i++){          2285   for(i = 0; i <= prim->numverts; i++){
2286     v1 = i;                                      2286     v1 = i;
2287     if(v1 == prim->numverts){                    2287     if(v1 == prim->numverts){
2288       if(prim->numverts < 3) break;              2288       if(prim->numverts < 3) break;
2289       v1 = 0;                                    2289       v1 = 0;
2290       v2 = prim->numverts - 1;                   2290       v2 = prim->numverts - 1;
2291       cur = prev0;                               2291       cur = prev0;
2292     }                                            2292     }
2293     else if(flag){                               2293     else if(flag){
2294       cur = tools_gl2psCheckPoint(prim->verts    2294       cur = tools_gl2psCheckPoint(prim->verts[v1].xyz, plane);
2295       if(i == 0){                                2295       if(i == 0){
2296         prev0 = cur;                             2296         prev0 = cur;
2297       }                                          2297       }
2298     }                                            2298     }
2299     if(((prev == -1) || (prev == cur) || (pre    2299     if(((prev == -1) || (prev == cur) || (prev == 0) || (cur == 0)) &&
2300        (i < prim->numverts)){                    2300        (i < prim->numverts)){
2301       if(cur == TOOLS_GL2PS_POINT_INFRONT){      2301       if(cur == TOOLS_GL2PS_POINT_INFRONT){
2302         front_count++;                           2302         front_count++;
2303         front_list = (tools_GL2PSvertex*)tool    2303         front_list = (tools_GL2PSvertex*)tools_gl2psRealloc(front_list,
2304                                                  2304                                                 sizeof(tools_GL2PSvertex)*front_count);
2305         front_list[front_count-1] = prim->ver    2305         front_list[front_count-1] = prim->verts[v1];
2306       }                                          2306       }
2307       else if(cur == TOOLS_GL2PS_POINT_BACK){    2307       else if(cur == TOOLS_GL2PS_POINT_BACK){
2308         back_count++;                            2308         back_count++;
2309         back_list = (tools_GL2PSvertex*)tools    2309         back_list = (tools_GL2PSvertex*)tools_gl2psRealloc(back_list,
2310                                                  2310                                                sizeof(tools_GL2PSvertex)*back_count);
2311         back_list[back_count-1] = prim->verts    2311         back_list[back_count-1] = prim->verts[v1];
2312       }                                          2312       }
2313       else{                                      2313       else{
2314         front_count++;                           2314         front_count++;
2315         front_list = (tools_GL2PSvertex*)tool    2315         front_list = (tools_GL2PSvertex*)tools_gl2psRealloc(front_list,
2316                                                  2316                                                 sizeof(tools_GL2PSvertex)*front_count);
2317         front_list[front_count-1] = prim->ver    2317         front_list[front_count-1] = prim->verts[v1];
2318         back_count++;                            2318         back_count++;
2319         back_list = (tools_GL2PSvertex*)tools    2319         back_list = (tools_GL2PSvertex*)tools_gl2psRealloc(back_list,
2320                                                  2320                                                sizeof(tools_GL2PSvertex)*back_count);
2321         back_list[back_count-1] = prim->verts    2321         back_list[back_count-1] = prim->verts[v1];
2322       }                                          2322       }
2323       flag = 1;                                  2323       flag = 1;
2324     }                                            2324     }
2325     else if((prev != cur) && (cur != 0) && (p    2325     else if((prev != cur) && (cur != 0) && (prev != 0)){
2326       if(v1 != 0){                               2326       if(v1 != 0){
2327         v2 = v1-1;                               2327         v2 = v1-1;
2328         i--;                                     2328         i--;
2329       }                                          2329       }
2330       front_count++;                             2330       front_count++;
2331       front_list = (tools_GL2PSvertex*)tools_    2331       front_list = (tools_GL2PSvertex*)tools_gl2psRealloc(front_list,
2332                                                  2332                                               sizeof(tools_GL2PSvertex)*front_count);
2333       tools_gl2psCutEdge(&prim->verts[v2], &p    2333       tools_gl2psCutEdge(&prim->verts[v2], &prim->verts[v1],
2334                    plane, &front_list[front_c    2334                    plane, &front_list[front_count-1]);
2335       back_count++;                              2335       back_count++;
2336       back_list = (tools_GL2PSvertex*)tools_g    2336       back_list = (tools_GL2PSvertex*)tools_gl2psRealloc(back_list,
2337                                                  2337                                              sizeof(tools_GL2PSvertex)*back_count);
2338       back_list[back_count-1] = front_list[fr    2338       back_list[back_count-1] = front_list[front_count-1];
2339       flag = 0;                                  2339       flag = 0;
2340     }                                            2340     }
2341     prev = cur;                                  2341     prev = cur;
2342   }                                              2342   }
2343   *front = tools_gl2psCreateSplitPrimitive2D(    2343   *front = tools_gl2psCreateSplitPrimitive2D(prim, front_count, front_list);
2344   *back = tools_gl2psCreateSplitPrimitive2D(p    2344   *back = tools_gl2psCreateSplitPrimitive2D(prim, back_count, back_list);
2345   tools_gl2psFree(front_list);                   2345   tools_gl2psFree(front_list);
2346   tools_gl2psFree(back_list);                    2346   tools_gl2psFree(back_list);
2347 }                                                2347 }
2348                                                  2348 
2349 inline tools_GLint tools_gl2psAddInBspImageTr    2349 inline tools_GLint tools_gl2psAddInBspImageTree(tools_GL2PScontext* gl2ps, tools_GL2PSprimitive *prim, tools_GL2PSbsptree2d **tree)
2350 {                                                2350 {
2351   tools_GLint ret = 0;                           2351   tools_GLint ret = 0;
2352   tools_GL2PSprimitive *frontprim = NULL, *ba    2352   tools_GL2PSprimitive *frontprim = NULL, *backprim = NULL;
2353                                                  2353 
2354   /* FIXME: until we consider the actual exte    2354   /* FIXME: until we consider the actual extent of text strings and
2355      pixmaps, never cull them. Otherwise the     2355      pixmaps, never cull them. Otherwise the whole string/pixmap gets
2356      culled as soon as the reference point is    2356      culled as soon as the reference point is hidden */
2357   if(prim->type == TOOLS_GL2PS_PIXMAP ||         2357   if(prim->type == TOOLS_GL2PS_PIXMAP ||
2358      prim->type == TOOLS_GL2PS_TEXT ||           2358      prim->type == TOOLS_GL2PS_TEXT ||
2359      prim->type == TOOLS_GL2PS_SPECIAL){         2359      prim->type == TOOLS_GL2PS_SPECIAL){
2360     return 1;                                    2360     return 1;
2361   }                                              2361   }
2362                                                  2362 
2363   if(*tree == NULL){                             2363   if(*tree == NULL){
2364     if((prim->type != TOOLS_GL2PS_IMAGEMAP) &    2364     if((prim->type != TOOLS_GL2PS_IMAGEMAP) && (TOOLS_GL_FALSE == gl2ps->zerosurfacearea)){
2365       tools_gl2psAddPlanesInBspTreeImage(gl2p    2365       tools_gl2psAddPlanesInBspTreeImage(gl2ps->primitivetoadd, tree);
2366     }                                            2366     }
2367     return 1;                                    2367     return 1;
2368   }                                              2368   }
2369   else{                                          2369   else{
2370     switch(tools_gl2psCheckPrimitive(prim, (*    2370     switch(tools_gl2psCheckPrimitive(prim, (*tree)->plane)){
2371     case TOOLS_GL2PS_IN_BACK_OF: return tools    2371     case TOOLS_GL2PS_IN_BACK_OF: return tools_gl2psAddInBspImageTree(gl2ps, prim, &(*tree)->back);
2372     case TOOLS_GL2PS_IN_FRONT_OF:                2372     case TOOLS_GL2PS_IN_FRONT_OF:
2373       if((*tree)->front != NULL) return tools    2373       if((*tree)->front != NULL) return tools_gl2psAddInBspImageTree(gl2ps, prim, &(*tree)->front);
2374       else                       return 0;       2374       else                       return 0;
2375     case TOOLS_GL2PS_SPANNING:                   2375     case TOOLS_GL2PS_SPANNING:
2376       tools_gl2psSplitPrimitive2D(prim, (*tre    2376       tools_gl2psSplitPrimitive2D(prim, (*tree)->plane, &frontprim, &backprim);
2377       ret = tools_gl2psAddInBspImageTree(gl2p    2377       ret = tools_gl2psAddInBspImageTree(gl2ps, backprim, &(*tree)->back);
2378       if((*tree)->front != NULL){                2378       if((*tree)->front != NULL){
2379         if(tools_gl2psAddInBspImageTree(gl2ps    2379         if(tools_gl2psAddInBspImageTree(gl2ps, frontprim, &(*tree)->front)){
2380           ret = 1;                               2380           ret = 1;
2381         }                                        2381         }
2382       }                                          2382       }
2383       tools_gl2psFree(frontprim->verts);         2383       tools_gl2psFree(frontprim->verts);
2384       tools_gl2psFree(frontprim);                2384       tools_gl2psFree(frontprim);
2385       tools_gl2psFree(backprim->verts);          2385       tools_gl2psFree(backprim->verts);
2386       tools_gl2psFree(backprim);                 2386       tools_gl2psFree(backprim);
2387       return ret;                                2387       return ret;
2388     case TOOLS_GL2PS_COINCIDENT:                 2388     case TOOLS_GL2PS_COINCIDENT:
2389       if((*tree)->back != NULL){                 2389       if((*tree)->back != NULL){
2390         gl2ps->zerosurfacearea = TOOLS_GL_TRU    2390         gl2ps->zerosurfacearea = TOOLS_GL_TRUE;
2391         ret = tools_gl2psAddInBspImageTree(gl    2391         ret = tools_gl2psAddInBspImageTree(gl2ps, prim, &(*tree)->back);
2392         gl2ps->zerosurfacearea = TOOLS_GL_FAL    2392         gl2ps->zerosurfacearea = TOOLS_GL_FALSE;
2393         if(ret) return ret;                      2393         if(ret) return ret;
2394       }                                          2394       }
2395       if((*tree)->front != NULL){                2395       if((*tree)->front != NULL){
2396         gl2ps->zerosurfacearea = TOOLS_GL_TRU    2396         gl2ps->zerosurfacearea = TOOLS_GL_TRUE;
2397         ret = tools_gl2psAddInBspImageTree(gl    2397         ret = tools_gl2psAddInBspImageTree(gl2ps, prim, &(*tree)->front);
2398         gl2ps->zerosurfacearea = TOOLS_GL_FAL    2398         gl2ps->zerosurfacearea = TOOLS_GL_FALSE;
2399         if(ret) return ret;                      2399         if(ret) return ret;
2400       }                                          2400       }
2401       if(prim->type == TOOLS_GL2PS_LINE) retu    2401       if(prim->type == TOOLS_GL2PS_LINE) return 1;
2402       else                         return 0;     2402       else                         return 0;
2403     }                                            2403     }
2404   }                                              2404   }
2405   return 0;                                      2405   return 0;
2406 }                                                2406 }
2407                                                  2407 
2408 inline void tools_gl2psAddInImageTree(tools_G    2408 inline void tools_gl2psAddInImageTree(tools_GL2PScontext* gl2ps, void *data)
2409 {                                                2409 {
2410   tools_GL2PSprimitive *prim = *(tools_GL2PSp    2410   tools_GL2PSprimitive *prim = *(tools_GL2PSprimitive **)data;
2411   gl2ps->primitivetoadd = prim;                  2411   gl2ps->primitivetoadd = prim;
2412   if(prim->type == TOOLS_GL2PS_IMAGEMAP && pr    2412   if(prim->type == TOOLS_GL2PS_IMAGEMAP && prim->data.image->format == TOOLS_GL2PS_IMAGEMAP_VISIBLE){
2413     prim->culled = 1;                            2413     prim->culled = 1;
2414   }                                              2414   }
2415   else if(!tools_gl2psAddInBspImageTree(gl2ps    2415   else if(!tools_gl2psAddInBspImageTree(gl2ps, prim, &gl2ps->imagetree)){
2416     prim->culled = 1;                            2416     prim->culled = 1;
2417   }                                              2417   }
2418   else if(prim->type == TOOLS_GL2PS_IMAGEMAP)    2418   else if(prim->type == TOOLS_GL2PS_IMAGEMAP){
2419     prim->data.image->format = TOOLS_GL2PS_IM    2419     prim->data.image->format = TOOLS_GL2PS_IMAGEMAP_VISIBLE;
2420   }                                              2420   }
2421 }                                                2421 }
2422                                                  2422 
2423 /* Boundary construction */                      2423 /* Boundary construction */
2424                                                  2424 
2425 inline void tools_gl2psAddBoundaryInList(tool    2425 inline void tools_gl2psAddBoundaryInList(tools_GL2PSprimitive *prim, tools_GL2PSlist *list)
2426 {                                                2426 {
2427   tools_GL2PSprimitive *b;                       2427   tools_GL2PSprimitive *b;
2428   tools_GLshort i;                               2428   tools_GLshort i;
2429   tools_GL2PSxyz c;                              2429   tools_GL2PSxyz c;
2430                                                  2430 
2431   c[0] = c[1] = c[2] = 0.0F;                     2431   c[0] = c[1] = c[2] = 0.0F;
2432   for(i = 0; i < prim->numverts; i++){           2432   for(i = 0; i < prim->numverts; i++){
2433     c[0] += prim->verts[i].xyz[0];               2433     c[0] += prim->verts[i].xyz[0];
2434     c[1] += prim->verts[i].xyz[1];               2434     c[1] += prim->verts[i].xyz[1];
2435   }                                              2435   }
2436   c[0] /= prim->numverts;                        2436   c[0] /= prim->numverts;
2437   c[1] /= prim->numverts;                        2437   c[1] /= prim->numverts;
2438                                                  2438 
2439   for(i = 0; i < prim->numverts; i++){           2439   for(i = 0; i < prim->numverts; i++){
2440     if(prim->boundary & (tools_GLint)pow(2.,     2440     if(prim->boundary & (tools_GLint)pow(2., i)){
2441       b = (tools_GL2PSprimitive*)tools_gl2psM    2441       b = (tools_GL2PSprimitive*)tools_gl2psMalloc(sizeof(tools_GL2PSprimitive));
2442       b->type = TOOLS_GL2PS_LINE;                2442       b->type = TOOLS_GL2PS_LINE;
2443       b->offset = prim->offset;                  2443       b->offset = prim->offset;
2444       b->ofactor = prim->ofactor;                2444       b->ofactor = prim->ofactor;
2445       b->ounits = prim->ounits;                  2445       b->ounits = prim->ounits;
2446       b->pattern = prim->pattern;                2446       b->pattern = prim->pattern;
2447       b->factor = prim->factor;                  2447       b->factor = prim->factor;
2448       b->culled = prim->culled;                  2448       b->culled = prim->culled;
2449       b->width = prim->width;                    2449       b->width = prim->width;
2450       b->linecap = prim->linecap;                2450       b->linecap = prim->linecap;
2451       b->linejoin = prim->linejoin;              2451       b->linejoin = prim->linejoin;
2452       b->boundary = 0;                           2452       b->boundary = 0;
2453       b->numverts = 2;                           2453       b->numverts = 2;
2454       b->verts = (tools_GL2PSvertex*)tools_gl    2454       b->verts = (tools_GL2PSvertex*)tools_gl2psMalloc(2 * sizeof(tools_GL2PSvertex));
2455                                                  2455 
2456 #if 0 /* FIXME: need to work on boundary offs    2456 #if 0 /* FIXME: need to work on boundary offset... */
2457       v[0] = c[0] - prim->verts[i].xyz[0];       2457       v[0] = c[0] - prim->verts[i].xyz[0];
2458       v[1] = c[1] - prim->verts[i].xyz[1];       2458       v[1] = c[1] - prim->verts[i].xyz[1];
2459       v[2] = 0.0F;                               2459       v[2] = 0.0F;
2460       norm = tools_gl2psNorm(v);                 2460       norm = tools_gl2psNorm(v);
2461       v[0] /= norm;                              2461       v[0] /= norm;
2462       v[1] /= norm;                              2462       v[1] /= norm;
2463       b->verts[0].xyz[0] = prim->verts[i].xyz    2463       b->verts[0].xyz[0] = prim->verts[i].xyz[0] +0.1*v[0];
2464       b->verts[0].xyz[1] = prim->verts[i].xyz    2464       b->verts[0].xyz[1] = prim->verts[i].xyz[1] +0.1*v[1];
2465       b->verts[0].xyz[2] = prim->verts[i].xyz    2465       b->verts[0].xyz[2] = prim->verts[i].xyz[2];
2466       v[0] = c[0] - prim->verts[tools_gl2psGe    2466       v[0] = c[0] - prim->verts[tools_gl2psGetIndex(i, prim->numverts)].xyz[0];
2467       v[1] = c[1] - prim->verts[tools_gl2psGe    2467       v[1] = c[1] - prim->verts[tools_gl2psGetIndex(i, prim->numverts)].xyz[1];
2468       norm = tools_gl2psNorm(v);                 2468       norm = tools_gl2psNorm(v);
2469       v[0] /= norm;                              2469       v[0] /= norm;
2470       v[1] /= norm;                              2470       v[1] /= norm;
2471       b->verts[1].xyz[0] = prim->verts[tools_    2471       b->verts[1].xyz[0] = prim->verts[tools_gl2psGetIndex(i, prim->numverts)].xyz[0] +0.1*v[0];
2472       b->verts[1].xyz[1] = prim->verts[tools_    2472       b->verts[1].xyz[1] = prim->verts[tools_gl2psGetIndex(i, prim->numverts)].xyz[1] +0.1*v[1];
2473       b->verts[1].xyz[2] = prim->verts[tools_    2473       b->verts[1].xyz[2] = prim->verts[tools_gl2psGetIndex(i, prim->numverts)].xyz[2];
2474 #else                                            2474 #else
2475       b->verts[0].xyz[0] = prim->verts[i].xyz    2475       b->verts[0].xyz[0] = prim->verts[i].xyz[0];
2476       b->verts[0].xyz[1] = prim->verts[i].xyz    2476       b->verts[0].xyz[1] = prim->verts[i].xyz[1];
2477       b->verts[0].xyz[2] = prim->verts[i].xyz    2477       b->verts[0].xyz[2] = prim->verts[i].xyz[2];
2478       b->verts[1].xyz[0] = prim->verts[tools_    2478       b->verts[1].xyz[0] = prim->verts[tools_gl2psGetIndex(i, prim->numverts)].xyz[0];
2479       b->verts[1].xyz[1] = prim->verts[tools_    2479       b->verts[1].xyz[1] = prim->verts[tools_gl2psGetIndex(i, prim->numverts)].xyz[1];
2480       b->verts[1].xyz[2] = prim->verts[tools_    2480       b->verts[1].xyz[2] = prim->verts[tools_gl2psGetIndex(i, prim->numverts)].xyz[2];
2481 #endif                                           2481 #endif
2482                                                  2482 
2483       b->verts[0].rgba[0] = 0.0F;                2483       b->verts[0].rgba[0] = 0.0F;
2484       b->verts[0].rgba[1] = 0.0F;                2484       b->verts[0].rgba[1] = 0.0F;
2485       b->verts[0].rgba[2] = 0.0F;                2485       b->verts[0].rgba[2] = 0.0F;
2486       b->verts[0].rgba[3] = 0.0F;                2486       b->verts[0].rgba[3] = 0.0F;
2487       b->verts[1].rgba[0] = 0.0F;                2487       b->verts[1].rgba[0] = 0.0F;
2488       b->verts[1].rgba[1] = 0.0F;                2488       b->verts[1].rgba[1] = 0.0F;
2489       b->verts[1].rgba[2] = 0.0F;                2489       b->verts[1].rgba[2] = 0.0F;
2490       b->verts[1].rgba[3] = 0.0F;                2490       b->verts[1].rgba[3] = 0.0F;
2491       tools_gl2psListAdd(list, &b);              2491       tools_gl2psListAdd(list, &b);
2492     }                                            2492     }
2493   }                                              2493   }
2494                                                  2494 
2495 }                                                2495 }
2496                                                  2496 
2497 inline void tools_gl2psBuildPolygonBoundary(t    2497 inline void tools_gl2psBuildPolygonBoundary(tools_GL2PSbsptree *tree)
2498 {                                                2498 {
2499   tools_GLint i;                                 2499   tools_GLint i;
2500   tools_GL2PSprimitive *prim;                    2500   tools_GL2PSprimitive *prim;
2501                                                  2501 
2502   if(!tree) return;                              2502   if(!tree) return;
2503   tools_gl2psBuildPolygonBoundary(tree->back)    2503   tools_gl2psBuildPolygonBoundary(tree->back);
2504   for(i = 0; i < tools_gl2psListNbr(tree->pri    2504   for(i = 0; i < tools_gl2psListNbr(tree->primitives); i++){
2505     prim = *(tools_GL2PSprimitive**)tools_gl2    2505     prim = *(tools_GL2PSprimitive**)tools_gl2psListPointer(tree->primitives, i);
2506     if(prim->boundary) tools_gl2psAddBoundary    2506     if(prim->boundary) tools_gl2psAddBoundaryInList(prim, tree->primitives);
2507   }                                              2507   }
2508   tools_gl2psBuildPolygonBoundary(tree->front    2508   tools_gl2psBuildPolygonBoundary(tree->front);
2509 }                                                2509 }
2510                                                  2510 
2511 /********************************************    2511 /*********************************************************************
2512  *                                               2512  *
2513  * Feedback buffer parser                        2513  * Feedback buffer parser
2514  *                                               2514  *
2515  ********************************************    2515  *********************************************************************/
2516                                                  2516 
2517 TOOLS_GL2PSDLL_API void tools_gl2psAddPolyPri    2517 TOOLS_GL2PSDLL_API void tools_gl2psAddPolyPrimitive(tools_GL2PScontext* gl2ps, tools_GLshort type, tools_GLshort numverts,
2518                                         tools    2518                                         tools_GL2PSvertex *verts, tools_GLint offset,
2519                                         tools    2519                                         tools_GLfloat ofactor, tools_GLfloat ounits,
2520                                         tools    2520                                         tools_GLushort pattern, tools_GLint factor,
2521                                         tools    2521                                         tools_GLfloat width, tools_GLint linecap,
2522                                         tools    2522                                         tools_GLint linejoin,char boundary)
2523 {                                                2523 {
2524   tools_GL2PSprimitive *prim;                    2524   tools_GL2PSprimitive *prim;
2525                                                  2525 
2526   prim = (tools_GL2PSprimitive*)tools_gl2psMa    2526   prim = (tools_GL2PSprimitive*)tools_gl2psMalloc(sizeof(tools_GL2PSprimitive));
2527   prim->type = type;                             2527   prim->type = type;
2528   prim->numverts = numverts;                     2528   prim->numverts = numverts;
2529   prim->verts = (tools_GL2PSvertex*)tools_gl2    2529   prim->verts = (tools_GL2PSvertex*)tools_gl2psMalloc(numverts * sizeof(tools_GL2PSvertex));
2530   memcpy(prim->verts, verts, numverts * sizeo    2530   memcpy(prim->verts, verts, numverts * sizeof(tools_GL2PSvertex));
2531   prim->boundary = boundary;                     2531   prim->boundary = boundary;
2532   prim->offset = (char)offset;                   2532   prim->offset = (char)offset;
2533   prim->ofactor = ofactor;                       2533   prim->ofactor = ofactor;
2534   prim->ounits = ounits;                         2534   prim->ounits = ounits;
2535   prim->pattern = pattern;                       2535   prim->pattern = pattern;
2536   prim->factor = factor;                         2536   prim->factor = factor;
2537   prim->width = width;                           2537   prim->width = width;
2538   prim->linecap = linecap;                       2538   prim->linecap = linecap;
2539   prim->linejoin = linejoin;                     2539   prim->linejoin = linejoin;
2540   prim->culled = 0;                              2540   prim->culled = 0;
2541                                                  2541 
2542   /* FIXME: here we should have an option to     2542   /* FIXME: here we should have an option to split stretched
2543      tris/quads to enhance SIMPLE_SORT */        2543      tris/quads to enhance SIMPLE_SORT */
2544                                                  2544 
2545   tools_gl2psListAdd(gl2ps->primitives, &prim    2545   tools_gl2psListAdd(gl2ps->primitives, &prim);
2546 }                                                2546 }
2547                                                  2547 
2548 inline tools_GLint tools_gl2psGetVertex(tools    2548 inline tools_GLint tools_gl2psGetVertex(tools_GL2PScontext* gl2ps, tools_GL2PSvertex *v, tools_GLfloat *p)
2549 {                                                2549 {
2550   tools_GLint i;                                 2550   tools_GLint i;
2551                                                  2551 
2552   v->xyz[0] = p[0];                              2552   v->xyz[0] = p[0];
2553   v->xyz[1] = p[1];                              2553   v->xyz[1] = p[1];
2554   v->xyz[2] = p[2];                              2554   v->xyz[2] = p[2];
2555                                                  2555 
2556   if(gl2ps->colormode == TOOLS_GL_COLOR_INDEX    2556   if(gl2ps->colormode == TOOLS_GL_COLOR_INDEX && gl2ps->colorsize > 0){
2557     i = (tools_GLint)(p[3] + 0.5);               2557     i = (tools_GLint)(p[3] + 0.5);
2558     v->rgba[0] = gl2ps->colormap[i][0];          2558     v->rgba[0] = gl2ps->colormap[i][0];
2559     v->rgba[1] = gl2ps->colormap[i][1];          2559     v->rgba[1] = gl2ps->colormap[i][1];
2560     v->rgba[2] = gl2ps->colormap[i][2];          2560     v->rgba[2] = gl2ps->colormap[i][2];
2561     v->rgba[3] = gl2ps->colormap[i][3];          2561     v->rgba[3] = gl2ps->colormap[i][3];
2562     return 4;                                    2562     return 4;
2563   }                                              2563   }
2564   else{                                          2564   else{
2565     v->rgba[0] = p[3];                           2565     v->rgba[0] = p[3];
2566     v->rgba[1] = p[4];                           2566     v->rgba[1] = p[4];
2567     v->rgba[2] = p[5];                           2567     v->rgba[2] = p[5];
2568     v->rgba[3] = p[6];                           2568     v->rgba[3] = p[6];
2569     return 7;                                    2569     return 7;
2570   }                                              2570   }
2571 }                                                2571 }
2572                                                  2572 
2573 inline void tools_gl2psParseFeedbackBuffer(to    2573 inline void tools_gl2psParseFeedbackBuffer(tools_GL2PScontext* gl2ps, tools_GLint used)
2574 {                                                2574 {
2575   char flag;                                     2575   char flag;
2576   tools_GLushort pattern = 0;                    2576   tools_GLushort pattern = 0;
2577   tools_GLboolean boundary;                      2577   tools_GLboolean boundary;
2578   tools_GLint i, sizeoffloat, count, v, vtot,    2578   tools_GLint i, sizeoffloat, count, v, vtot, offset = 0, factor = 0, auxindex = 0;
2579   tools_GLint lcap = 0, ljoin = 0;               2579   tools_GLint lcap = 0, ljoin = 0;
2580   tools_GLfloat lwidth = 1.0F, psize = 1.0F,     2580   tools_GLfloat lwidth = 1.0F, psize = 1.0F, ofactor = 0.0F, ounits = 0.0F;
2581   tools_GLfloat *current;                        2581   tools_GLfloat *current;
2582   tools_GL2PSvertex vertices[3];                 2582   tools_GL2PSvertex vertices[3];
2583   tools_GL2PSprimitive *prim;                    2583   tools_GL2PSprimitive *prim;
2584   tools_GL2PSimagemap *node;                     2584   tools_GL2PSimagemap *node;
2585                                                  2585 
2586   current = gl2ps->feedback;                     2586   current = gl2ps->feedback;
2587   boundary = gl2ps->boundary = TOOLS_GL_FALSE    2587   boundary = gl2ps->boundary = TOOLS_GL_FALSE;
2588                                                  2588 
2589   while(used > 0){                               2589   while(used > 0){
2590                                                  2590 
2591     if(TOOLS_GL_TRUE == boundary) gl2ps->boun    2591     if(TOOLS_GL_TRUE == boundary) gl2ps->boundary = TOOLS_GL_TRUE;
2592                                                  2592 
2593     switch((tools_GLint)*current){               2593     switch((tools_GLint)*current){
2594     case TOOLS_GL_POINT_TOKEN :                  2594     case TOOLS_GL_POINT_TOKEN :
2595       current ++;                                2595       current ++;
2596       used --;                                   2596       used --;
2597       i = tools_gl2psGetVertex(gl2ps, &vertic    2597       i = tools_gl2psGetVertex(gl2ps, &vertices[0], current);
2598       current += i;                              2598       current += i;
2599       used    -= i;                              2599       used    -= i;
2600       tools_gl2psAddPolyPrimitive(gl2ps, TOOL    2600       tools_gl2psAddPolyPrimitive(gl2ps, TOOLS_GL2PS_POINT, 1, vertices, 0, 0.0, 0.0,
2601                             pattern, factor,     2601                             pattern, factor, psize, lcap, ljoin, 0);
2602       break;                                     2602       break;
2603     case TOOLS_GL_LINE_TOKEN :                   2603     case TOOLS_GL_LINE_TOKEN :
2604     case TOOLS_GL_LINE_RESET_TOKEN :             2604     case TOOLS_GL_LINE_RESET_TOKEN :
2605       current ++;                                2605       current ++;
2606       used --;                                   2606       used --;
2607       i = tools_gl2psGetVertex(gl2ps, &vertic    2607       i = tools_gl2psGetVertex(gl2ps, &vertices[0], current);
2608       current += i;                              2608       current += i;
2609       used    -= i;                              2609       used    -= i;
2610       i = tools_gl2psGetVertex(gl2ps, &vertic    2610       i = tools_gl2psGetVertex(gl2ps, &vertices[1], current);
2611       current += i;                              2611       current += i;
2612       used    -= i;                              2612       used    -= i;
2613       tools_gl2psAddPolyPrimitive(gl2ps, TOOL    2613       tools_gl2psAddPolyPrimitive(gl2ps, TOOLS_GL2PS_LINE, 2, vertices, 0, 0.0, 0.0,
2614                             pattern, factor,     2614                             pattern, factor, lwidth, lcap, ljoin, 0);
2615       break;                                     2615       break;
2616     case TOOLS_GL_POLYGON_TOKEN :                2616     case TOOLS_GL_POLYGON_TOKEN :
2617       count = (tools_GLint)current[1];           2617       count = (tools_GLint)current[1];
2618       current += 2;                              2618       current += 2;
2619       used -= 2;                                 2619       used -= 2;
2620       v = vtot = 0;                              2620       v = vtot = 0;
2621       while(count > 0 && used > 0){              2621       while(count > 0 && used > 0){
2622         i = tools_gl2psGetVertex(gl2ps, &vert    2622         i = tools_gl2psGetVertex(gl2ps, &vertices[v], current);
2623         tools_gl2psAdaptVertexForBlending(gl2    2623         tools_gl2psAdaptVertexForBlending(gl2ps, &vertices[v]);
2624         current += i;                            2624         current += i;
2625         used    -= i;                            2625         used    -= i;
2626         count --;                                2626         count --;
2627         vtot++;                                  2627         vtot++;
2628         if(v == 2){                              2628         if(v == 2){
2629           if(TOOLS_GL_TRUE == boundary){         2629           if(TOOLS_GL_TRUE == boundary){
2630             if(!count && vtot == 2) flag = 1|    2630             if(!count && vtot == 2) flag = 1|2|4;
2631             else if(!count) flag = 2|4;          2631             else if(!count) flag = 2|4;
2632             else if(vtot == 2) flag = 1|2;       2632             else if(vtot == 2) flag = 1|2;
2633             else flag = 2;                       2633             else flag = 2;
2634           }                                      2634           }
2635           else                                   2635           else
2636             flag = 0;                            2636             flag = 0;
2637           tools_gl2psAddPolyPrimitive(gl2ps,     2637           tools_gl2psAddPolyPrimitive(gl2ps, TOOLS_GL2PS_TRIANGLE, 3, vertices, offset, ofactor,
2638                                 ounits, patte    2638                                 ounits, pattern, factor, 1, lcap, ljoin,
2639                                 flag);           2639                                 flag);
2640           vertices[1] = vertices[2];             2640           vertices[1] = vertices[2];
2641         }                                        2641         }
2642         else                                     2642         else
2643           v ++;                                  2643           v ++;
2644       }                                          2644       }
2645       break;                                     2645       break;
2646     case TOOLS_GL_BITMAP_TOKEN :                 2646     case TOOLS_GL_BITMAP_TOKEN :
2647     case TOOLS_GL_DRAW_PIXEL_TOKEN :             2647     case TOOLS_GL_DRAW_PIXEL_TOKEN :
2648     case TOOLS_GL_COPY_PIXEL_TOKEN :             2648     case TOOLS_GL_COPY_PIXEL_TOKEN :
2649       current ++;                                2649       current ++;
2650       used --;                                   2650       used --;
2651       i = tools_gl2psGetVertex(gl2ps, &vertic    2651       i = tools_gl2psGetVertex(gl2ps, &vertices[0], current);
2652       current += i;                              2652       current += i;
2653       used    -= i;                              2653       used    -= i;
2654       break;                                     2654       break;
2655     case TOOLS_GL_PASS_THROUGH_TOKEN :           2655     case TOOLS_GL_PASS_THROUGH_TOKEN :
2656       switch((tools_GLint)current[1]){           2656       switch((tools_GLint)current[1]){
2657       case TOOLS_GL2PS_BEGIN_OFFSET_TOKEN :      2657       case TOOLS_GL2PS_BEGIN_OFFSET_TOKEN :
2658         offset = 1;                              2658         offset = 1;
2659         current += 2;                            2659         current += 2;
2660         used -= 2;                               2660         used -= 2;
2661         ofactor = current[1];                    2661         ofactor = current[1];
2662         current += 2;                            2662         current += 2;
2663         used -= 2;                               2663         used -= 2;
2664         ounits = current[1];                     2664         ounits = current[1];
2665         break;                                   2665         break;
2666       case TOOLS_GL2PS_END_OFFSET_TOKEN :        2666       case TOOLS_GL2PS_END_OFFSET_TOKEN :
2667         offset = 0;                              2667         offset = 0;
2668         ofactor = 0.0;                           2668         ofactor = 0.0;
2669         ounits = 0.0;                            2669         ounits = 0.0;
2670         break;                                   2670         break;
2671       case TOOLS_GL2PS_BEGIN_BOUNDARY_TOKEN :    2671       case TOOLS_GL2PS_BEGIN_BOUNDARY_TOKEN : boundary = TOOLS_GL_TRUE; break;
2672       case TOOLS_GL2PS_END_BOUNDARY_TOKEN : b    2672       case TOOLS_GL2PS_END_BOUNDARY_TOKEN : boundary = TOOLS_GL_FALSE; break;
2673       case TOOLS_GL2PS_END_STIPPLE_TOKEN : pa    2673       case TOOLS_GL2PS_END_STIPPLE_TOKEN : pattern = 0; factor = 0; break;
2674       case TOOLS_GL2PS_BEGIN_BLEND_TOKEN : gl    2674       case TOOLS_GL2PS_BEGIN_BLEND_TOKEN : gl2ps->blending = TOOLS_GL_TRUE; break;
2675       case TOOLS_GL2PS_END_BLEND_TOKEN : gl2p    2675       case TOOLS_GL2PS_END_BLEND_TOKEN : gl2ps->blending = TOOLS_GL_FALSE; break;
2676       case TOOLS_GL2PS_BEGIN_STIPPLE_TOKEN :     2676       case TOOLS_GL2PS_BEGIN_STIPPLE_TOKEN :
2677         current += 2;                            2677         current += 2;
2678         used -= 2;                               2678         used -= 2;
2679         pattern = (tools_GLushort)current[1];    2679         pattern = (tools_GLushort)current[1];
2680         current += 2;                            2680         current += 2;
2681         used -= 2;                               2681         used -= 2;
2682         factor = (tools_GLint)current[1];        2682         factor = (tools_GLint)current[1];
2683         break;                                   2683         break;
2684       case TOOLS_GL2PS_SRC_BLEND_TOKEN :         2684       case TOOLS_GL2PS_SRC_BLEND_TOKEN :
2685         current += 2;                            2685         current += 2;
2686         used -= 2;                               2686         used -= 2;
2687         gl2ps->blendfunc[0] = (tools_GLint)cu    2687         gl2ps->blendfunc[0] = (tools_GLint)current[1];
2688         break;                                   2688         break;
2689       case TOOLS_GL2PS_DST_BLEND_TOKEN :         2689       case TOOLS_GL2PS_DST_BLEND_TOKEN :
2690         current += 2;                            2690         current += 2;
2691         used -= 2;                               2691         used -= 2;
2692         gl2ps->blendfunc[1] = (tools_GLint)cu    2692         gl2ps->blendfunc[1] = (tools_GLint)current[1];
2693         break;                                   2693         break;
2694       case TOOLS_GL2PS_POINT_SIZE_TOKEN :        2694       case TOOLS_GL2PS_POINT_SIZE_TOKEN :
2695         current += 2;                            2695         current += 2;
2696         used -= 2;                               2696         used -= 2;
2697         psize = current[1];                      2697         psize = current[1];
2698         break;                                   2698         break;
2699       case TOOLS_GL2PS_LINE_CAP_TOKEN :          2699       case TOOLS_GL2PS_LINE_CAP_TOKEN :
2700         current += 2;                            2700         current += 2;
2701         used -= 2;                               2701         used -= 2;
2702         lcap = (tools_GLint)current[1];          2702         lcap = (tools_GLint)current[1];
2703         break;                                   2703         break;
2704       case TOOLS_GL2PS_LINE_JOIN_TOKEN :         2704       case TOOLS_GL2PS_LINE_JOIN_TOKEN :
2705         current += 2;                            2705         current += 2;
2706         used -= 2;                               2706         used -= 2;
2707         ljoin = (tools_GLint)current[1];         2707         ljoin = (tools_GLint)current[1];
2708         break;                                   2708         break;
2709       case TOOLS_GL2PS_LINE_WIDTH_TOKEN :        2709       case TOOLS_GL2PS_LINE_WIDTH_TOKEN :
2710         current += 2;                            2710         current += 2;
2711         used -= 2;                               2711         used -= 2;
2712         lwidth = current[1];                     2712         lwidth = current[1];
2713         break;                                   2713         break;
2714       case TOOLS_GL2PS_IMAGEMAP_TOKEN :          2714       case TOOLS_GL2PS_IMAGEMAP_TOKEN :
2715         prim = (tools_GL2PSprimitive *)tools_    2715         prim = (tools_GL2PSprimitive *)tools_gl2psMalloc(sizeof(tools_GL2PSprimitive));
2716         prim->type = TOOLS_GL2PS_IMAGEMAP;       2716         prim->type = TOOLS_GL2PS_IMAGEMAP;
2717         prim->boundary = 0;                      2717         prim->boundary = 0;
2718         prim->numverts = 4;                      2718         prim->numverts = 4;
2719         prim->verts = (tools_GL2PSvertex *)to    2719         prim->verts = (tools_GL2PSvertex *)tools_gl2psMalloc(4 * sizeof(tools_GL2PSvertex));
2720         prim->culled = 0;                        2720         prim->culled = 0;
2721         prim->offset = 0;                        2721         prim->offset = 0;
2722         prim->ofactor = 0.0;                     2722         prim->ofactor = 0.0;
2723         prim->ounits = 0.0;                      2723         prim->ounits = 0.0;
2724         prim->pattern = 0;                       2724         prim->pattern = 0;
2725         prim->factor = 0;                        2725         prim->factor = 0;
2726         prim->width = 1;                         2726         prim->width = 1;
2727                                                  2727 
2728         node = (tools_GL2PSimagemap*)tools_gl    2728         node = (tools_GL2PSimagemap*)tools_gl2psMalloc(sizeof(tools_GL2PSimagemap));
2729         node->image = (tools_GL2PSimage*)tool    2729         node->image = (tools_GL2PSimage*)tools_gl2psMalloc(sizeof(tools_GL2PSimage));
2730         node->image->type = 0;                   2730         node->image->type = 0;
2731         node->image->format = 0;                 2731         node->image->format = 0;
2732         node->image->zoom_x = 1.0F;              2732         node->image->zoom_x = 1.0F;
2733         node->image->zoom_y = 1.0F;              2733         node->image->zoom_y = 1.0F;
2734         node->next = NULL;                       2734         node->next = NULL;
2735                                                  2735 
2736         if(gl2ps->imagemap_head == NULL)         2736         if(gl2ps->imagemap_head == NULL)
2737           gl2ps->imagemap_head = node;           2737           gl2ps->imagemap_head = node;
2738         else                                     2738         else
2739           gl2ps->imagemap_tail->next = node;     2739           gl2ps->imagemap_tail->next = node;
2740         gl2ps->imagemap_tail = node;             2740         gl2ps->imagemap_tail = node;
2741         prim->data.image = node->image;          2741         prim->data.image = node->image;
2742                                                  2742 
2743         current += 2; used -= 2;                 2743         current += 2; used -= 2;
2744         i = tools_gl2psGetVertex(gl2ps, &prim    2744         i = tools_gl2psGetVertex(gl2ps, &prim->verts[0], &current[1]);
2745         current += i; used -= i;                 2745         current += i; used -= i;
2746                                                  2746 
2747         node->image->width = (tools_GLint)cur    2747         node->image->width = (tools_GLint)current[2];
2748         current += 2; used -= 2;                 2748         current += 2; used -= 2;
2749         node->image->height = (tools_GLint)cu    2749         node->image->height = (tools_GLint)current[2];
2750         prim->verts[0].xyz[0] = prim->verts[0    2750         prim->verts[0].xyz[0] = prim->verts[0].xyz[0] - (int)(node->image->width / 2) + 0.5F;
2751         prim->verts[0].xyz[1] = prim->verts[0    2751         prim->verts[0].xyz[1] = prim->verts[0].xyz[1] - (int)(node->image->height / 2) + 0.5F;
2752         for(i = 1; i < 4; i++){                  2752         for(i = 1; i < 4; i++){
2753           for(v = 0; v < 3; v++){                2753           for(v = 0; v < 3; v++){
2754             prim->verts[i].xyz[v] = prim->ver    2754             prim->verts[i].xyz[v] = prim->verts[0].xyz[v];
2755             prim->verts[i].rgba[v] = prim->ve    2755             prim->verts[i].rgba[v] = prim->verts[0].rgba[v];
2756           }                                      2756           }
2757           prim->verts[i].rgba[v] = prim->vert    2757           prim->verts[i].rgba[v] = prim->verts[0].rgba[v];
2758         }                                        2758         }
2759         prim->verts[1].xyz[0] = prim->verts[1    2759         prim->verts[1].xyz[0] = prim->verts[1].xyz[0] + node->image->width;
2760         prim->verts[2].xyz[0] = prim->verts[1    2760         prim->verts[2].xyz[0] = prim->verts[1].xyz[0];
2761         prim->verts[2].xyz[1] = prim->verts[2    2761         prim->verts[2].xyz[1] = prim->verts[2].xyz[1] + node->image->height;
2762         prim->verts[3].xyz[1] = prim->verts[2    2762         prim->verts[3].xyz[1] = prim->verts[2].xyz[1];
2763                                                  2763 
2764         sizeoffloat = sizeof(tools_GLfloat);     2764         sizeoffloat = sizeof(tools_GLfloat);
2765         v = 2 * sizeoffloat;                     2765         v = 2 * sizeoffloat;
2766         vtot = node->image->height + node->im    2766         vtot = node->image->height + node->image->height *
2767           ((node->image->width - 1) / 8);        2767           ((node->image->width - 1) / 8);
2768         node->image->pixels = (tools_GLfloat*    2768         node->image->pixels = (tools_GLfloat*)tools_gl2psMalloc(v + vtot);
2769         node->image->pixels[0] = prim->verts[    2769         node->image->pixels[0] = prim->verts[0].xyz[0];
2770         node->image->pixels[1] = prim->verts[    2770         node->image->pixels[1] = prim->verts[0].xyz[1];
2771                                                  2771 
2772         for(i = 0; i < vtot; i += sizeoffloat    2772         for(i = 0; i < vtot; i += sizeoffloat){
2773           current += 2; used -= 2;               2773           current += 2; used -= 2;
2774           if((vtot - i) >= 4)                    2774           if((vtot - i) >= 4)
2775             memcpy(&(((char*)(node->image->pi    2775             memcpy(&(((char*)(node->image->pixels))[i + v]), &(current[2]), sizeoffloat);
2776           else                                   2776           else
2777             memcpy(&(((char*)(node->image->pi    2777             memcpy(&(((char*)(node->image->pixels))[i + v]), &(current[2]), vtot - i);
2778         }                                        2778         }
2779         current++; used--;                       2779         current++; used--;
2780         tools_gl2psListAdd(gl2ps->primitives,    2780         tools_gl2psListAdd(gl2ps->primitives, &prim);
2781         break;                                   2781         break;
2782       case TOOLS_GL2PS_DRAW_PIXELS_TOKEN :       2782       case TOOLS_GL2PS_DRAW_PIXELS_TOKEN :
2783       case TOOLS_GL2PS_TEXT_TOKEN :              2783       case TOOLS_GL2PS_TEXT_TOKEN :
2784         if(auxindex < tools_gl2psListNbr(gl2p    2784         if(auxindex < tools_gl2psListNbr(gl2ps->auxprimitives))
2785           tools_gl2psListAdd(gl2ps->primitive    2785           tools_gl2psListAdd(gl2ps->primitives,
2786                        tools_gl2psListPointer    2786                        tools_gl2psListPointer(gl2ps->auxprimitives, auxindex++));
2787         else                                     2787         else
2788           tools_gl2psMsg(TOOLS_GL2PS_ERROR, "    2788           tools_gl2psMsg(TOOLS_GL2PS_ERROR, "Wrong number of auxiliary tokens in buffer");
2789         break;                                   2789         break;
2790       }                                          2790       }
2791       current += 2;                              2791       current += 2;
2792       used -= 2;                                 2792       used -= 2;
2793       break;                                     2793       break;
2794     default :                                    2794     default :
2795       tools_gl2psMsg(TOOLS_GL2PS_WARNING, "Un    2795       tools_gl2psMsg(TOOLS_GL2PS_WARNING, "Unknown token in buffer");
2796       current ++;                                2796       current ++;
2797       used --;                                   2797       used --;
2798       break;                                     2798       break;
2799     }                                            2799     }
2800   }                                              2800   }
2801                                                  2801 
2802   tools_gl2psListReset(gl2ps->auxprimitives);    2802   tools_gl2psListReset(gl2ps->auxprimitives);
2803 }                                                2803 }
2804                                                  2804 
2805 /********************************************    2805 /*********************************************************************
2806  *                                               2806  *
2807  * PostScript routines                           2807  * PostScript routines
2808  *                                               2808  *
2809  ********************************************    2809  *********************************************************************/
2810                                                  2810 
2811 inline void tools_gl2psWriteByte(tools_GL2PSc    2811 inline void tools_gl2psWriteByte(tools_GL2PScontext* gl2ps, unsigned char byte)
2812 {                                                2812 {
2813   unsigned char h = byte / 16;                   2813   unsigned char h = byte / 16;
2814   unsigned char l = byte % 16;                   2814   unsigned char l = byte % 16;
2815   tools_gl2psPrintf(gl2ps,"%x%x", h, l);         2815   tools_gl2psPrintf(gl2ps,"%x%x", h, l);
2816 }                                                2816 }
2817                                                  2817 
2818 inline void tools_gl2psPrintPostScriptPixmap(    2818 inline void tools_gl2psPrintPostScriptPixmap(tools_GL2PScontext* gl2ps, tools_GLfloat x, tools_GLfloat y, tools_GL2PSimage *im,int greyscale,int nbit)
2819 {                                                2819 {
2820   tools_GLuint nbhex, nbyte, nrgb, nbits;        2820   tools_GLuint nbhex, nbyte, nrgb, nbits;
2821   tools_GLuint row, col, ibyte, icase;           2821   tools_GLuint row, col, ibyte, icase;
2822   tools_GLfloat dr = 0., dg = 0., db = 0., fg    2822   tools_GLfloat dr = 0., dg = 0., db = 0., fgrey;
2823   unsigned char red = 0, green = 0, blue = 0,    2823   unsigned char red = 0, green = 0, blue = 0, b, grey;
2824   tools_GLuint width = (tools_GLuint)im->widt    2824   tools_GLuint width = (tools_GLuint)im->width;
2825   tools_GLuint height = (tools_GLuint)im->hei    2825   tools_GLuint height = (tools_GLuint)im->height;
2826                                                  2826 
2827   /* FIXME: should we define an option for th    2827   /* FIXME: should we define an option for these? Or just keep the
2828      8-bit per component case? */                2828      8-bit per component case? */
2829 /*G.Barrand: have the two below lines in argu    2829 /*G.Barrand: have the two below lines in arguments to quiet Coverity about dead code.
2830   int greyscale = 0; // set to 1 to output gr    2830   int greyscale = 0; // set to 1 to output greyscale image.
2831   int nbit = 8; // number of bits per color c    2831   int nbit = 8; // number of bits per color compoment (2, 4 or 8).
2832 */                                               2832 */
2833                                                  2833 
2834   if((width <= 0) || (height <= 0)) return;      2834   if((width <= 0) || (height <= 0)) return;
2835                                                  2835 
2836   tools_gl2psPrintf(gl2ps,"gsave\n");            2836   tools_gl2psPrintf(gl2ps,"gsave\n");
2837   tools_gl2psPrintf(gl2ps,"%.2f %.2f translat    2837   tools_gl2psPrintf(gl2ps,"%.2f %.2f translate\n", x, y);
2838   tools_gl2psPrintf(gl2ps,"%.2f %.2f scale\n"    2838   tools_gl2psPrintf(gl2ps,"%.2f %.2f scale\n", width * im->zoom_x, height * im->zoom_y);
2839                                                  2839 
2840   if(greyscale){ /* greyscale */                 2840   if(greyscale){ /* greyscale */
2841     tools_gl2psPrintf(gl2ps,"/picstr %d strin    2841     tools_gl2psPrintf(gl2ps,"/picstr %d string def\n", width);
2842     tools_gl2psPrintf(gl2ps,"%d %d %d\n", wid    2842     tools_gl2psPrintf(gl2ps,"%d %d %d\n", width, height, 8);
2843     tools_gl2psPrintf(gl2ps,"[ %d 0 0 -%d 0 %    2843     tools_gl2psPrintf(gl2ps,"[ %d 0 0 -%d 0 %d ]\n", width, height, height);
2844     tools_gl2psPrintf(gl2ps,"{ currentfile pi    2844     tools_gl2psPrintf(gl2ps,"{ currentfile picstr readhexstring pop }\n");
2845     tools_gl2psPrintf(gl2ps,"image\n");          2845     tools_gl2psPrintf(gl2ps,"image\n");
2846     for(row = 0; row < height; row++){           2846     for(row = 0; row < height; row++){
2847       for(col = 0; col < width; col++){          2847       for(col = 0; col < width; col++){
2848         tools_gl2psGetRGB(im, col, row, &dr,     2848         tools_gl2psGetRGB(im, col, row, &dr, &dg, &db);
2849         fgrey = (0.30F * dr + 0.59F * dg + 0.    2849         fgrey = (0.30F * dr + 0.59F * dg + 0.11F * db);
2850         grey = (unsigned char)(255. * fgrey);    2850         grey = (unsigned char)(255. * fgrey);
2851         tools_gl2psWriteByte(gl2ps, grey);       2851         tools_gl2psWriteByte(gl2ps, grey);
2852       }                                          2852       }
2853       tools_gl2psPrintf(gl2ps,"\n");             2853       tools_gl2psPrintf(gl2ps,"\n");
2854     }                                            2854     }
2855     nbhex = width * height * 2;                  2855     nbhex = width * height * 2;
2856     tools_gl2psPrintf(gl2ps,"%%%% nbhex digit    2856     tools_gl2psPrintf(gl2ps,"%%%% nbhex digit          :%d\n", nbhex);
2857   }                                              2857   }
2858   else if(nbit == 2){ /* color, 2 bits for r     2858   else if(nbit == 2){ /* color, 2 bits for r and g and b; rgbs following each other */
2859     nrgb = width  * 3;                           2859     nrgb = width  * 3;
2860     nbits = nrgb * nbit;                         2860     nbits = nrgb * nbit;
2861     nbyte = nbits / 8;                           2861     nbyte = nbits / 8;
2862     if((nbyte * 8) != nbits) nbyte++;            2862     if((nbyte * 8) != nbits) nbyte++;
2863     tools_gl2psPrintf(gl2ps,"/rgbstr %d strin    2863     tools_gl2psPrintf(gl2ps,"/rgbstr %d string def\n", nbyte);
2864     tools_gl2psPrintf(gl2ps,"%d %d %d\n", wid    2864     tools_gl2psPrintf(gl2ps,"%d %d %d\n", width, height, nbit);
2865     tools_gl2psPrintf(gl2ps,"[ %d 0 0 -%d 0 %    2865     tools_gl2psPrintf(gl2ps,"[ %d 0 0 -%d 0 %d ]\n", width, height, height);
2866     tools_gl2psPrintf(gl2ps,"{ currentfile rg    2866     tools_gl2psPrintf(gl2ps,"{ currentfile rgbstr readhexstring pop }\n");
2867     tools_gl2psPrintf(gl2ps,"false 3\n");        2867     tools_gl2psPrintf(gl2ps,"false 3\n");
2868     tools_gl2psPrintf(gl2ps,"colorimage\n");     2868     tools_gl2psPrintf(gl2ps,"colorimage\n");
2869     for(row = 0; row < height; row++){           2869     for(row = 0; row < height; row++){
2870       icase = 1;                                 2870       icase = 1;
2871       col = 0;                                   2871       col = 0;
2872       b = 0;                                     2872       b = 0;
2873       for(ibyte = 0; ibyte < nbyte; ibyte++){    2873       for(ibyte = 0; ibyte < nbyte; ibyte++){
2874         if(icase == 1) {                         2874         if(icase == 1) {
2875           if(col < width) {                      2875           if(col < width) {
2876             tools_gl2psGetRGB(im, col, row, &    2876             tools_gl2psGetRGB(im, col, row, &dr, &dg, &db);
2877           }                                      2877           }
2878           else {                                 2878           else {
2879             dr = dg = db = 0;                    2879             dr = dg = db = 0;
2880           }                                      2880           }
2881           col++;                                 2881           col++;
2882           red = (unsigned char)(3. * dr);        2882           red = (unsigned char)(3. * dr);
2883           green = (unsigned char)(3. * dg);      2883           green = (unsigned char)(3. * dg);
2884           blue = (unsigned char)(3. * db);       2884           blue = (unsigned char)(3. * db);
2885           b = red;                               2885           b = red;
2886           b = (b<<2) + green;                    2886           b = (b<<2) + green;
2887           b = (b<<2) + blue;                     2887           b = (b<<2) + blue;
2888           if(col < width) {                      2888           if(col < width) {
2889             tools_gl2psGetRGB(im, col, row, &    2889             tools_gl2psGetRGB(im, col, row, &dr, &dg, &db);
2890           }                                      2890           }
2891           else {                                 2891           else {
2892             dr = dg = db = 0;                    2892             dr = dg = db = 0;
2893           }                                      2893           }
2894           col++;                                 2894           col++;
2895           red = (unsigned char)(3. * dr);        2895           red = (unsigned char)(3. * dr);
2896           green = (unsigned char)(3. * dg);      2896           green = (unsigned char)(3. * dg);
2897           blue = (unsigned char)(3. * db);       2897           blue = (unsigned char)(3. * db);
2898           b = (b<<2) + red;                      2898           b = (b<<2) + red;
2899           tools_gl2psWriteByte(gl2ps, b);        2899           tools_gl2psWriteByte(gl2ps, b);
2900           b = 0;                                 2900           b = 0;
2901           icase++;                               2901           icase++;
2902         }                                        2902         }
2903         else if(icase == 2) {                    2903         else if(icase == 2) {
2904           b = green;                             2904           b = green;
2905           b = (b<<2) + blue;                     2905           b = (b<<2) + blue;
2906           if(col < width) {                      2906           if(col < width) {
2907             tools_gl2psGetRGB(im, col, row, &    2907             tools_gl2psGetRGB(im, col, row, &dr, &dg, &db);
2908           }                                      2908           }
2909           else {                                 2909           else {
2910             dr = dg = db = 0;                    2910             dr = dg = db = 0;
2911           }                                      2911           }
2912           col++;                                 2912           col++;
2913           red = (unsigned char)(3. * dr);        2913           red = (unsigned char)(3. * dr);
2914           green = (unsigned char)(3. * dg);      2914           green = (unsigned char)(3. * dg);
2915           blue = (unsigned char)(3. * db);       2915           blue = (unsigned char)(3. * db);
2916           b = (b<<2) + red;                      2916           b = (b<<2) + red;
2917           b = (b<<2) + green;                    2917           b = (b<<2) + green;
2918           tools_gl2psWriteByte(gl2ps, b);        2918           tools_gl2psWriteByte(gl2ps, b);
2919           b = 0;                                 2919           b = 0;
2920           icase++;                               2920           icase++;
2921         }                                        2921         }
2922         else if(icase == 3) {                    2922         else if(icase == 3) {
2923           b = blue;                              2923           b = blue;
2924           if(col < width) {                      2924           if(col < width) {
2925             tools_gl2psGetRGB(im, col, row, &    2925             tools_gl2psGetRGB(im, col, row, &dr, &dg, &db);
2926           }                                      2926           }
2927           else {                                 2927           else {
2928             dr = dg = db = 0;                    2928             dr = dg = db = 0;
2929           }                                      2929           }
2930           col++;                                 2930           col++;
2931           red = (unsigned char)(3. * dr);        2931           red = (unsigned char)(3. * dr);
2932           green = (unsigned char)(3. * dg);      2932           green = (unsigned char)(3. * dg);
2933           blue = (unsigned char)(3. * db);       2933           blue = (unsigned char)(3. * db);
2934           b = (b<<2) + red;                      2934           b = (b<<2) + red;
2935           b = (b<<2) + green;                    2935           b = (b<<2) + green;
2936           b = (b<<2) + blue;                     2936           b = (b<<2) + blue;
2937           tools_gl2psWriteByte(gl2ps, b);        2937           tools_gl2psWriteByte(gl2ps, b);
2938           b = 0;                                 2938           b = 0;
2939           icase = 1;                             2939           icase = 1;
2940         }                                        2940         }
2941       }                                          2941       }
2942       tools_gl2psPrintf(gl2ps,"\n");             2942       tools_gl2psPrintf(gl2ps,"\n");
2943     }                                            2943     }
2944   }                                              2944   }
2945   else if(nbit == 4){ /* color, 4 bits for r     2945   else if(nbit == 4){ /* color, 4 bits for r and g and b; rgbs following each other */
2946     nrgb = width  * 3;                           2946     nrgb = width  * 3;
2947     nbits = nrgb * nbit;                         2947     nbits = nrgb * nbit;
2948     nbyte = nbits / 8;                           2948     nbyte = nbits / 8;
2949     if((nbyte * 8) != nbits) nbyte++;            2949     if((nbyte * 8) != nbits) nbyte++;
2950     tools_gl2psPrintf(gl2ps,"/rgbstr %d strin    2950     tools_gl2psPrintf(gl2ps,"/rgbstr %d string def\n", nbyte);
2951     tools_gl2psPrintf(gl2ps,"%d %d %d\n", wid    2951     tools_gl2psPrintf(gl2ps,"%d %d %d\n", width, height, nbit);
2952     tools_gl2psPrintf(gl2ps,"[ %d 0 0 -%d 0 %    2952     tools_gl2psPrintf(gl2ps,"[ %d 0 0 -%d 0 %d ]\n", width, height, height);
2953     tools_gl2psPrintf(gl2ps,"{ currentfile rg    2953     tools_gl2psPrintf(gl2ps,"{ currentfile rgbstr readhexstring pop }\n");
2954     tools_gl2psPrintf(gl2ps,"false 3\n");        2954     tools_gl2psPrintf(gl2ps,"false 3\n");
2955     tools_gl2psPrintf(gl2ps,"colorimage\n");     2955     tools_gl2psPrintf(gl2ps,"colorimage\n");
2956     for(row = 0; row < height; row++){           2956     for(row = 0; row < height; row++){
2957       col = 0;                                   2957       col = 0;
2958       icase = 1;                                 2958       icase = 1;
2959       for(ibyte = 0; ibyte < nbyte; ibyte++){    2959       for(ibyte = 0; ibyte < nbyte; ibyte++){
2960         if(icase == 1) {                         2960         if(icase == 1) {
2961           if(col < width) {                      2961           if(col < width) {
2962             tools_gl2psGetRGB(im, col, row, &    2962             tools_gl2psGetRGB(im, col, row, &dr, &dg, &db);
2963           }                                      2963           }
2964           else {                                 2964           else {
2965             dr = dg = db = 0;                    2965             dr = dg = db = 0;
2966           }                                      2966           }
2967           col++;                                 2967           col++;
2968           red = (unsigned char)(15. * dr);       2968           red = (unsigned char)(15. * dr);
2969           green = (unsigned char)(15. * dg);     2969           green = (unsigned char)(15. * dg);
2970           tools_gl2psPrintf(gl2ps,"%x%x", red    2970           tools_gl2psPrintf(gl2ps,"%x%x", red, green);
2971           icase++;                               2971           icase++;
2972         }                                        2972         }
2973         else if(icase == 2) {                    2973         else if(icase == 2) {
2974           blue = (unsigned char)(15. * db);      2974           blue = (unsigned char)(15. * db);
2975           if(col < width) {                      2975           if(col < width) {
2976             tools_gl2psGetRGB(im, col, row, &    2976             tools_gl2psGetRGB(im, col, row, &dr, &dg, &db);
2977           }                                      2977           }
2978           else {                                 2978           else {
2979             dr = dg = db = 0;                    2979             dr = dg = db = 0;
2980           }                                      2980           }
2981           col++;                                 2981           col++;
2982           red = (unsigned char)(15. * dr);       2982           red = (unsigned char)(15. * dr);
2983           tools_gl2psPrintf(gl2ps,"%x%x", blu    2983           tools_gl2psPrintf(gl2ps,"%x%x", blue, red);
2984           icase++;                               2984           icase++;
2985         }                                        2985         }
2986         else if(icase == 3) {                    2986         else if(icase == 3) {
2987           green = (unsigned char)(15. * dg);     2987           green = (unsigned char)(15. * dg);
2988           blue = (unsigned char)(15. * db);      2988           blue = (unsigned char)(15. * db);
2989           tools_gl2psPrintf(gl2ps,"%x%x", gre    2989           tools_gl2psPrintf(gl2ps,"%x%x", green, blue);
2990           icase = 1;                             2990           icase = 1;
2991         }                                        2991         }
2992       }                                          2992       }
2993       tools_gl2psPrintf(gl2ps,"\n");             2993       tools_gl2psPrintf(gl2ps,"\n");
2994     }                                            2994     }
2995   }                                              2995   }
2996   else{ /* 8 bit for r and g and b */            2996   else{ /* 8 bit for r and g and b */
2997     nbyte = width * 3;                           2997     nbyte = width * 3;
2998     tools_gl2psPrintf(gl2ps,"/rgbstr %d strin    2998     tools_gl2psPrintf(gl2ps,"/rgbstr %d string def\n", nbyte);
2999     tools_gl2psPrintf(gl2ps,"%d %d %d\n", wid    2999     tools_gl2psPrintf(gl2ps,"%d %d %d\n", width, height, 8);
3000     tools_gl2psPrintf(gl2ps,"[ %d 0 0 -%d 0 %    3000     tools_gl2psPrintf(gl2ps,"[ %d 0 0 -%d 0 %d ]\n", width, height, height);
3001     tools_gl2psPrintf(gl2ps,"{ currentfile rg    3001     tools_gl2psPrintf(gl2ps,"{ currentfile rgbstr readhexstring pop }\n");
3002     tools_gl2psPrintf(gl2ps,"false 3\n");        3002     tools_gl2psPrintf(gl2ps,"false 3\n");
3003     tools_gl2psPrintf(gl2ps,"colorimage\n");     3003     tools_gl2psPrintf(gl2ps,"colorimage\n");
3004     for(row = 0; row < height; row++){           3004     for(row = 0; row < height; row++){
3005       for(col = 0; col < width; col++){          3005       for(col = 0; col < width; col++){
3006         tools_gl2psGetRGB(im, col, row, &dr,     3006         tools_gl2psGetRGB(im, col, row, &dr, &dg, &db);
3007         red = (unsigned char)(255. * dr);        3007         red = (unsigned char)(255. * dr);
3008         tools_gl2psWriteByte(gl2ps, red);        3008         tools_gl2psWriteByte(gl2ps, red);
3009         green = (unsigned char)(255. * dg);      3009         green = (unsigned char)(255. * dg);
3010         tools_gl2psWriteByte(gl2ps, green);      3010         tools_gl2psWriteByte(gl2ps, green);
3011         blue = (unsigned char)(255. * db);       3011         blue = (unsigned char)(255. * db);
3012         tools_gl2psWriteByte(gl2ps, blue);       3012         tools_gl2psWriteByte(gl2ps, blue);
3013       }                                          3013       }
3014       tools_gl2psPrintf(gl2ps,"\n");             3014       tools_gl2psPrintf(gl2ps,"\n");
3015     }                                            3015     }
3016   }                                              3016   }
3017                                                  3017 
3018   tools_gl2psPrintf(gl2ps,"grestore\n");         3018   tools_gl2psPrintf(gl2ps,"grestore\n");
3019 }                                                3019 }
3020                                                  3020 
3021 inline void tools_gl2psPrintPostScriptImagema    3021 inline void tools_gl2psPrintPostScriptImagemap(tools_GL2PScontext* gl2ps, tools_GLfloat x, tools_GLfloat y,
3022                                          tool    3022                                          tools_GLsizei width, tools_GLsizei height,
3023                                          cons    3023                                          const unsigned char *imagemap){
3024   int i, size;                                   3024   int i, size;
3025                                                  3025 
3026   if((width <= 0) || (height <= 0)) return;      3026   if((width <= 0) || (height <= 0)) return;
3027                                                  3027 
3028   size = height + height * (width - 1) / 8;      3028   size = height + height * (width - 1) / 8;
3029                                                  3029 
3030   tools_gl2psPrintf(gl2ps,"gsave\n");            3030   tools_gl2psPrintf(gl2ps,"gsave\n");
3031   tools_gl2psPrintf(gl2ps,"%.2f %.2f translat    3031   tools_gl2psPrintf(gl2ps,"%.2f %.2f translate\n", x, y);
3032   tools_gl2psPrintf(gl2ps,"%d %d scale\n%d %d    3032   tools_gl2psPrintf(gl2ps,"%d %d scale\n%d %d\ntrue\n", width, height,width, height);
3033   tools_gl2psPrintf(gl2ps,"[ %d 0 0 -%d 0 %d     3033   tools_gl2psPrintf(gl2ps,"[ %d 0 0 -%d 0 %d ] {<", width, height, height); /*G.Barrand : add last height.*/
3034   for(i = 0; i < size; i++){                     3034   for(i = 0; i < size; i++){
3035     tools_gl2psWriteByte(gl2ps, *imagemap);      3035     tools_gl2psWriteByte(gl2ps, *imagemap);
3036     imagemap++;                                  3036     imagemap++;
3037   }                                              3037   }
3038   tools_gl2psPrintf(gl2ps,">} imagemask\ngres    3038   tools_gl2psPrintf(gl2ps,">} imagemask\ngrestore\n");
3039 }                                                3039 }
3040                                                  3040 
3041 inline void tools_gl2psPrintPostScriptHeader(    3041 inline void tools_gl2psPrintPostScriptHeader(tools_GL2PScontext* gl2ps)
3042 {                                                3042 {
3043   time_t now;                                    3043   time_t now;
3044                                                  3044 
3045   /* Since compression is not part of the Pos    3045   /* Since compression is not part of the PostScript standard,
3046      compressed PostScript files are just gzi    3046      compressed PostScript files are just gzipped PostScript files
3047      ("ps.gz" or "eps.gz") */                    3047      ("ps.gz" or "eps.gz") */
3048   tools_gl2psPrintGzipHeader(gl2ps);             3048   tools_gl2psPrintGzipHeader(gl2ps);
3049                                                  3049 
3050   time(&now);                                    3050   time(&now);
3051                                                  3051 
3052   if(gl2ps->format == TOOLS_GL2PS_PS){           3052   if(gl2ps->format == TOOLS_GL2PS_PS){
3053     tools_gl2psPrintf(gl2ps,"%%!PS-Adobe-3.0\    3053     tools_gl2psPrintf(gl2ps,"%%!PS-Adobe-3.0\n");
3054   }                                              3054   }
3055   else{                                          3055   else{
3056     tools_gl2psPrintf(gl2ps,"%%!PS-Adobe-3.0     3056     tools_gl2psPrintf(gl2ps,"%%!PS-Adobe-3.0 EPSF-3.0\n");
3057   }                                              3057   }
3058                                                  3058 
3059   tools_gl2psPrintf(gl2ps,"%%%%Title: %s\n"      3059   tools_gl2psPrintf(gl2ps,"%%%%Title: %s\n"
3060               "%%%%Creator: GL2PS %d.%d.%d%s,    3060               "%%%%Creator: GL2PS %d.%d.%d%s, %s\n"
3061               "%%%%For: %s\n"                    3061               "%%%%For: %s\n"
3062               "%%%%CreationDate: %s"             3062               "%%%%CreationDate: %s"
3063               "%%%%LanguageLevel: 3\n"           3063               "%%%%LanguageLevel: 3\n"
3064               "%%%%DocumentData: Clean7Bit\n"    3064               "%%%%DocumentData: Clean7Bit\n"
3065               "%%%%Pages: 1\n",                  3065               "%%%%Pages: 1\n",
3066               gl2ps->title, TOOLS_GL2PS_MAJOR    3066               gl2ps->title, TOOLS_GL2PS_MAJOR_VERSION, TOOLS_GL2PS_MINOR_VERSION,
3067               TOOLS_GL2PS_PATCH_VERSION, TOOL    3067               TOOLS_GL2PS_PATCH_VERSION, TOOLS_GL2PS_EXTRA_VERSION, TOOLS_GL2PS_COPYRIGHT,
3068               gl2ps->producer, ctime(&now));     3068               gl2ps->producer, ctime(&now));
3069                                                  3069 
3070   if(gl2ps->format == TOOLS_GL2PS_PS){           3070   if(gl2ps->format == TOOLS_GL2PS_PS){
3071     tools_gl2psPrintf(gl2ps,"%%%%Orientation:    3071     tools_gl2psPrintf(gl2ps,"%%%%Orientation: %s\n"
3072                 "%%%%DocumentMedia: Default %    3072                 "%%%%DocumentMedia: Default %d %d 0 () ()\n",
3073                 (gl2ps->options & TOOLS_GL2PS    3073                 (gl2ps->options & TOOLS_GL2PS_LANDSCAPE) ? "Landscape" : "Portrait",
3074                 (gl2ps->options & TOOLS_GL2PS    3074                 (gl2ps->options & TOOLS_GL2PS_LANDSCAPE) ? (int)gl2ps->viewport[3] :
3075                 (int)gl2ps->viewport[2],         3075                 (int)gl2ps->viewport[2],
3076                 (gl2ps->options & TOOLS_GL2PS    3076                 (gl2ps->options & TOOLS_GL2PS_LANDSCAPE) ? (int)gl2ps->viewport[2] :
3077                 (int)gl2ps->viewport[3]);        3077                 (int)gl2ps->viewport[3]);
3078   }                                              3078   }
3079                                                  3079 
3080   tools_gl2psPrintf(gl2ps,"%%%%BoundingBox: %    3080   tools_gl2psPrintf(gl2ps,"%%%%BoundingBox: %d %d %d %d\n"
3081               "%%%%EndComments\n",               3081               "%%%%EndComments\n",
3082               (gl2ps->options & TOOLS_GL2PS_L    3082               (gl2ps->options & TOOLS_GL2PS_LANDSCAPE) ? (int)gl2ps->viewport[1] :
3083               (int)gl2ps->viewport[0],           3083               (int)gl2ps->viewport[0],
3084               (gl2ps->options & TOOLS_GL2PS_L    3084               (gl2ps->options & TOOLS_GL2PS_LANDSCAPE) ? (int)gl2ps->viewport[0] :
3085               (int)gl2ps->viewport[1],           3085               (int)gl2ps->viewport[1],
3086               (gl2ps->options & TOOLS_GL2PS_L    3086               (gl2ps->options & TOOLS_GL2PS_LANDSCAPE) ? (int)gl2ps->viewport[3] :
3087               (int)gl2ps->viewport[2],           3087               (int)gl2ps->viewport[2],
3088               (gl2ps->options & TOOLS_GL2PS_L    3088               (gl2ps->options & TOOLS_GL2PS_LANDSCAPE) ? (int)gl2ps->viewport[2] :
3089               (int)gl2ps->viewport[3]);          3089               (int)gl2ps->viewport[3]);
3090                                                  3090 
3091   /* RGB color: r g b C (replace C by G in ou    3091   /* RGB color: r g b C (replace C by G in output to change from rgb to gray)
3092      Grayscale: r g b G                          3092      Grayscale: r g b G
3093      Font choose: size fontname FC               3093      Font choose: size fontname FC
3094      Text string: (string) x y size fontname     3094      Text string: (string) x y size fontname S??
3095      Rotated text string: (string) angle x y     3095      Rotated text string: (string) angle x y size fontname S??R
3096      Point primitive: x y size P                 3096      Point primitive: x y size P
3097      Line width: width W                         3097      Line width: width W
3098      Line start: x y LS                          3098      Line start: x y LS
3099      Line joining last point: x y L              3099      Line joining last point: x y L
3100      Line end: x y LE                            3100      Line end: x y LE
3101      Flat-shaded triangle: x3 y3 x2 y2 x1 y1     3101      Flat-shaded triangle: x3 y3 x2 y2 x1 y1 T
3102      Smooth-shaded triangle: x3 y3 r3 g3 b3 x    3102      Smooth-shaded triangle: x3 y3 r3 g3 b3 x2 y2 r2 g2 b2 x1 y1 r1 g1 b1 ST */
3103                                                  3103 
3104   tools_gl2psPrintf(gl2ps,"%%%%BeginProlog\n"    3104   tools_gl2psPrintf(gl2ps,"%%%%BeginProlog\n"
3105               "/gl2psdict 64 dict def gl2psdi    3105               "/gl2psdict 64 dict def gl2psdict begin\n"
3106               "/tryPS3shading %s def %% set t    3106               "/tryPS3shading %s def %% set to false to force subdivision\n"
3107               "/rThreshold %g def %% red comp    3107               "/rThreshold %g def %% red component subdivision threshold\n"
3108               "/gThreshold %g def %% green co    3108               "/gThreshold %g def %% green component subdivision threshold\n"
3109               "/bThreshold %g def %% blue com    3109               "/bThreshold %g def %% blue component subdivision threshold\n",
3110               (gl2ps->options & TOOLS_GL2PS_N    3110               (gl2ps->options & TOOLS_GL2PS_NO_PS3_SHADING) ? "false" : "true",
3111               gl2ps->threshold[0], gl2ps->thr    3111               gl2ps->threshold[0], gl2ps->threshold[1], gl2ps->threshold[2]);
3112                                                  3112 
3113   tools_gl2psPrintf(gl2ps,"/BD { bind def } b    3113   tools_gl2psPrintf(gl2ps,"/BD { bind def } bind def\n"
3114               "/C  { setrgbcolor } BD\n"         3114               "/C  { setrgbcolor } BD\n"
3115               "/G  { 0.082 mul exch 0.6094 mu    3115               "/G  { 0.082 mul exch 0.6094 mul add exch 0.3086 mul add neg 1.0 add setgray } BD\n"
3116               "/W  { setlinewidth } BD\n"        3116               "/W  { setlinewidth } BD\n"
3117               "/LC  { setlinecap } BD\n"         3117               "/LC  { setlinecap } BD\n"
3118               "/LJ  { setlinejoin } BD\n");      3118               "/LJ  { setlinejoin } BD\n");
3119                                                  3119 
3120   tools_gl2psPrintf(gl2ps,"/FC { findfont exc    3120   tools_gl2psPrintf(gl2ps,"/FC { findfont exch /SH exch def SH scalefont setfont } BD\n"
3121               "/SW { dup stringwidth pop } BD    3121               "/SW { dup stringwidth pop } BD\n"
3122               "/S  { FC moveto show } BD\n"      3122               "/S  { FC moveto show } BD\n"
3123               "/SBC{ FC moveto SW -2 div 0 rm    3123               "/SBC{ FC moveto SW -2 div 0 rmoveto show } BD\n"
3124               "/SBR{ FC moveto SW neg 0 rmove    3124               "/SBR{ FC moveto SW neg 0 rmoveto show } BD\n"
3125               "/SCL{ FC moveto 0 SH -2 div rm    3125               "/SCL{ FC moveto 0 SH -2 div rmoveto show } BD\n"
3126               "/SCC{ FC moveto SW -2 div SH -    3126               "/SCC{ FC moveto SW -2 div SH -2 div rmoveto show } BD\n"
3127               "/SCR{ FC moveto SW neg SH -2 d    3127               "/SCR{ FC moveto SW neg SH -2 div rmoveto show } BD\n"
3128               "/STL{ FC moveto 0 SH neg rmove    3128               "/STL{ FC moveto 0 SH neg rmoveto show } BD\n"
3129               "/STC{ FC moveto SW -2 div SH n    3129               "/STC{ FC moveto SW -2 div SH neg rmoveto show } BD\n"
3130               "/STR{ FC moveto SW neg SH neg     3130               "/STR{ FC moveto SW neg SH neg rmoveto show } BD\n");
3131                                                  3131 
3132   /* rotated text routines: same nameanem wit    3132   /* rotated text routines: same nameanem with R appended */
3133                                                  3133 
3134   tools_gl2psPrintf(gl2ps,"/FCT { FC translat    3134   tools_gl2psPrintf(gl2ps,"/FCT { FC translate 0 0 } BD\n"
3135               "/SR  { gsave FCT moveto rotate    3135               "/SR  { gsave FCT moveto rotate show grestore } BD\n"
3136               "/SBCR{ gsave FCT moveto rotate    3136               "/SBCR{ gsave FCT moveto rotate SW -2 div 0 rmoveto show grestore } BD\n"
3137               "/SBRR{ gsave FCT moveto rotate    3137               "/SBRR{ gsave FCT moveto rotate SW neg 0 rmoveto show grestore } BD\n"
3138               "/SCLR{ gsave FCT moveto rotate    3138               "/SCLR{ gsave FCT moveto rotate 0 SH -2 div rmoveto show grestore} BD\n");
3139   tools_gl2psPrintf(gl2ps,"/SCCR{ gsave FCT m    3139   tools_gl2psPrintf(gl2ps,"/SCCR{ gsave FCT moveto rotate SW -2 div SH -2 div rmoveto show grestore} BD\n"
3140               "/SCRR{ gsave FCT moveto rotate    3140               "/SCRR{ gsave FCT moveto rotate SW neg SH -2 div rmoveto show grestore} BD\n"
3141               "/STLR{ gsave FCT moveto rotate    3141               "/STLR{ gsave FCT moveto rotate 0 SH neg rmoveto show grestore } BD\n"
3142               "/STCR{ gsave FCT moveto rotate    3142               "/STCR{ gsave FCT moveto rotate SW -2 div SH neg rmoveto show grestore } BD\n"
3143               "/STRR{ gsave FCT moveto rotate    3143               "/STRR{ gsave FCT moveto rotate SW neg SH neg rmoveto show grestore } BD\n");
3144                                                  3144 
3145   tools_gl2psPrintf(gl2ps,"/P  { newpath 0.0     3145   tools_gl2psPrintf(gl2ps,"/P  { newpath 0.0 360.0 arc closepath fill } BD\n"
3146               "/LS { newpath moveto } BD\n"      3146               "/LS { newpath moveto } BD\n"
3147               "/L  { lineto } BD\n"              3147               "/L  { lineto } BD\n"
3148               "/LE { lineto stroke } BD\n"       3148               "/LE { lineto stroke } BD\n"
3149               "/T  { newpath moveto lineto li    3149               "/T  { newpath moveto lineto lineto closepath fill } BD\n");
3150                                                  3150 
3151   /* Smooth-shaded triangle with PostScript l    3151   /* Smooth-shaded triangle with PostScript level 3 shfill operator:
3152         x3 y3 r3 g3 b3 x2 y2 r2 g2 b2 x1 y1 r    3152         x3 y3 r3 g3 b3 x2 y2 r2 g2 b2 x1 y1 r1 g1 b1 STshfill */
3153                                                  3153 
3154   tools_gl2psPrintf(gl2ps,"/STshfill {\n"        3154   tools_gl2psPrintf(gl2ps,"/STshfill {\n"
3155               "      /b1 exch def /g1 exch de    3155               "      /b1 exch def /g1 exch def /r1 exch def /y1 exch def /x1 exch def\n"
3156               "      /b2 exch def /g2 exch de    3156               "      /b2 exch def /g2 exch def /r2 exch def /y2 exch def /x2 exch def\n"
3157               "      /b3 exch def /g3 exch de    3157               "      /b3 exch def /g3 exch def /r3 exch def /y3 exch def /x3 exch def\n"
3158               "      gsave << /ShadingType 4     3158               "      gsave << /ShadingType 4 /ColorSpace [/DeviceRGB]\n"
3159               "      /DataSource [ 0 x1 y1 r1    3159               "      /DataSource [ 0 x1 y1 r1 g1 b1 0 x2 y2 r2 g2 b2 0 x3 y3 r3 g3 b3 ] >>\n"
3160               "      shfill grestore } BD\n")    3160               "      shfill grestore } BD\n");
3161                                                  3161 
3162   /* Flat-shaded triangle with middle color:     3162   /* Flat-shaded triangle with middle color:
3163         x3 y3 r3 g3 b3 x2 y2 r2 g2 b2 x1 y1 r    3163         x3 y3 r3 g3 b3 x2 y2 r2 g2 b2 x1 y1 r1 g1 b1 Tm */
3164                                                  3164 
3165   tools_gl2psPrintf(gl2ps,/* stack : x3 y3 r3    3165   tools_gl2psPrintf(gl2ps,/* stack : x3 y3 r3 g3 b3 x2 y2 r2 g2 b2 x1 y1 r1 g1 b1 */
3166               "/Tm { 3 -1 roll 8 -1 roll 13 -    3166               "/Tm { 3 -1 roll 8 -1 roll 13 -1 roll add add 3 div\n" /* r = (r1+r2+r3)/3 */
3167               /* stack : x3 y3 g3 b3 x2 y2 g2    3167               /* stack : x3 y3 g3 b3 x2 y2 g2 b2 x1 y1 g1 b1 r */
3168               "      3 -1 roll 7 -1 roll 11 -    3168               "      3 -1 roll 7 -1 roll 11 -1 roll add add 3 div\n" /* g = (g1+g2+g3)/3 */
3169               /* stack : x3 y3 b3 x2 y2 b2 x1    3169               /* stack : x3 y3 b3 x2 y2 b2 x1 y1 b1 r g b */
3170               "      3 -1 roll 6 -1 roll 9 -1    3170               "      3 -1 roll 6 -1 roll 9 -1 roll add add 3 div" /* b = (b1+b2+b3)/3 */
3171               /* stack : x3 y3 x2 y2 x1 y1 r     3171               /* stack : x3 y3 x2 y2 x1 y1 r g b */
3172               " C T } BD\n");                    3172               " C T } BD\n");
3173                                                  3173 
3174   /* Split triangle in four sub-triangles (at    3174   /* Split triangle in four sub-triangles (at sides middle points) and call the
3175      STnoshfill procedure on each, interpolat    3175      STnoshfill procedure on each, interpolating the colors in RGB space:
3176         x3 y3 r3 g3 b3 x2 y2 r2 g2 b2 x1 y1 r    3176         x3 y3 r3 g3 b3 x2 y2 r2 g2 b2 x1 y1 r1 g1 b1 STsplit
3177      (in procedure comments key: (Vi) = xi yi    3177      (in procedure comments key: (Vi) = xi yi ri gi bi) */
3178                                                  3178 
3179   tools_gl2psPrintf(gl2ps,"/STsplit {\n"         3179   tools_gl2psPrintf(gl2ps,"/STsplit {\n"
3180               "      4 index 15 index add 0.5    3180               "      4 index 15 index add 0.5 mul\n" /* x13 = (x1+x3)/2 */
3181               "      4 index 15 index add 0.5    3181               "      4 index 15 index add 0.5 mul\n" /* y13 = (y1+y3)/2 */
3182               "      4 index 15 index add 0.5    3182               "      4 index 15 index add 0.5 mul\n" /* r13 = (r1+r3)/2 */
3183               "      4 index 15 index add 0.5    3183               "      4 index 15 index add 0.5 mul\n" /* g13 = (g1+g3)/2 */
3184               "      4 index 15 index add 0.5    3184               "      4 index 15 index add 0.5 mul\n" /* b13 = (b1+b3)/2 */
3185               "      5 copy 5 copy 25 15 roll    3185               "      5 copy 5 copy 25 15 roll\n");
3186                                                  3186 
3187   /* at his point, stack = (V3) (V13) (V13) (    3187   /* at his point, stack = (V3) (V13) (V13) (V13) (V2) (V1) */
3188                                                  3188 
3189   tools_gl2psPrintf(gl2ps,"      9 index 30 i    3189   tools_gl2psPrintf(gl2ps,"      9 index 30 index add 0.5 mul\n" /* x23 = (x2+x3)/2 */
3190               "      9 index 30 index add 0.5    3190               "      9 index 30 index add 0.5 mul\n" /* y23 = (y2+y3)/2 */
3191               "      9 index 30 index add 0.5    3191               "      9 index 30 index add 0.5 mul\n" /* r23 = (r2+r3)/2 */
3192               "      9 index 30 index add 0.5    3192               "      9 index 30 index add 0.5 mul\n" /* g23 = (g2+g3)/2 */
3193               "      9 index 30 index add 0.5    3193               "      9 index 30 index add 0.5 mul\n" /* b23 = (b2+b3)/2 */
3194               "      5 copy 5 copy 35 5 roll     3194               "      5 copy 5 copy 35 5 roll 25 5 roll 15 5 roll\n");
3195                                                  3195 
3196   /* stack = (V3) (V13) (V23) (V13) (V23) (V1    3196   /* stack = (V3) (V13) (V23) (V13) (V23) (V13) (V23) (V2) (V1) */
3197                                                  3197 
3198   tools_gl2psPrintf(gl2ps,"      4 index 10 i    3198   tools_gl2psPrintf(gl2ps,"      4 index 10 index add 0.5 mul\n" /* x12 = (x1+x2)/2 */
3199               "      4 index 10 index add 0.5    3199               "      4 index 10 index add 0.5 mul\n" /* y12 = (y1+y2)/2 */
3200               "      4 index 10 index add 0.5    3200               "      4 index 10 index add 0.5 mul\n" /* r12 = (r1+r2)/2 */
3201               "      4 index 10 index add 0.5    3201               "      4 index 10 index add 0.5 mul\n" /* g12 = (g1+g2)/2 */
3202               "      4 index 10 index add 0.5    3202               "      4 index 10 index add 0.5 mul\n" /* b12 = (b1+b2)/2 */
3203               "      5 copy 5 copy 40 5 roll     3203               "      5 copy 5 copy 40 5 roll 25 5 roll 15 5 roll 25 5 roll\n");
3204                                                  3204 
3205   /* stack = (V3) (V13) (V23) (V13) (V12) (V2    3205   /* stack = (V3) (V13) (V23) (V13) (V12) (V23) (V13) (V1) (V12) (V23) (V12) (V2) */
3206                                                  3206 
3207   tools_gl2psPrintf(gl2ps,"      STnoshfill S    3207   tools_gl2psPrintf(gl2ps,"      STnoshfill STnoshfill STnoshfill STnoshfill } BD\n");
3208                                                  3208 
3209   /* Gouraud shaded triangle using recursive     3209   /* Gouraud shaded triangle using recursive subdivision until the difference
3210      between corner colors does not exceed th    3210      between corner colors does not exceed the thresholds:
3211         x3 y3 r3 g3 b3 x2 y2 r2 g2 b2 x1 y1 r    3211         x3 y3 r3 g3 b3 x2 y2 r2 g2 b2 x1 y1 r1 g1 b1 STnoshfill  */
3212                                                  3212 
3213   tools_gl2psPrintf(gl2ps,"/STnoshfill {\n"      3213   tools_gl2psPrintf(gl2ps,"/STnoshfill {\n"
3214               "      2 index 8 index sub abs     3214               "      2 index 8 index sub abs rThreshold gt\n" /* |r1-r2|>rth */
3215               "      { STsplit }\n"              3215               "      { STsplit }\n"
3216               "      { 1 index 7 index sub ab    3216               "      { 1 index 7 index sub abs gThreshold gt\n" /* |g1-g2|>gth */
3217               "        { STsplit }\n"            3217               "        { STsplit }\n"
3218               "        { dup 6 index sub abs     3218               "        { dup 6 index sub abs bThreshold gt\n" /* |b1-b2|>bth */
3219               "          { STsplit }\n"          3219               "          { STsplit }\n"
3220               "          { 2 index 13 index s    3220               "          { 2 index 13 index sub abs rThreshold gt\n" /* |r1-r3|>rht */
3221               "            { STsplit }\n"        3221               "            { STsplit }\n"
3222               "            { 1 index 12 index    3222               "            { 1 index 12 index sub abs gThreshold gt\n" /* |g1-g3|>gth */
3223               "              { STsplit }\n"      3223               "              { STsplit }\n"
3224               "              { dup 11 index s    3224               "              { dup 11 index sub abs bThreshold gt\n" /* |b1-b3|>bth */
3225               "                { STsplit }\n"    3225               "                { STsplit }\n"
3226               "                { 7 index 13 i    3226               "                { 7 index 13 index sub abs rThreshold gt\n"); /* |r2-r3|>rht */
3227   tools_gl2psPrintf(gl2ps,"                      3227   tools_gl2psPrintf(gl2ps,"                  { STsplit }\n"
3228               "                  { 6 index 12    3228               "                  { 6 index 12 index sub abs gThreshold gt\n" /* |g2-g3|>gth */
3229               "                    { STsplit     3229               "                    { STsplit }\n"
3230               "                    { 5 index     3230               "                    { 5 index 11 index sub abs bThreshold gt\n" /* |b2-b3|>bth */
3231               "                      { STspli    3231               "                      { STsplit }\n"
3232               "                      { Tm }\n    3232               "                      { Tm }\n" /* all colors sufficiently similar */
3233               "                      ifelse }    3233               "                      ifelse }\n"
3234               "                    ifelse }\n    3234               "                    ifelse }\n"
3235               "                  ifelse }\n"     3235               "                  ifelse }\n"
3236               "                ifelse }\n"       3236               "                ifelse }\n"
3237               "              ifelse }\n"         3237               "              ifelse }\n"
3238               "            ifelse }\n"           3238               "            ifelse }\n"
3239               "          ifelse }\n"             3239               "          ifelse }\n"
3240               "        ifelse }\n"               3240               "        ifelse }\n"
3241               "      ifelse } BD\n");            3241               "      ifelse } BD\n");
3242                                                  3242 
3243   tools_gl2psPrintf(gl2ps,"tryPS3shading\n"      3243   tools_gl2psPrintf(gl2ps,"tryPS3shading\n"
3244               "{ /shfill where\n"                3244               "{ /shfill where\n"
3245               "  { /ST { STshfill } BD }\n"      3245               "  { /ST { STshfill } BD }\n"
3246               "  { /ST { STnoshfill } BD }\n"    3246               "  { /ST { STnoshfill } BD }\n"
3247               "  ifelse }\n"                     3247               "  ifelse }\n"
3248               "{ /ST { STnoshfill } BD }\n"      3248               "{ /ST { STnoshfill } BD }\n"
3249               "ifelse\n");                       3249               "ifelse\n");
3250                                                  3250 
3251   tools_gl2psPrintf(gl2ps,"end\n"                3251   tools_gl2psPrintf(gl2ps,"end\n"
3252               "%%%%EndProlog\n"                  3252               "%%%%EndProlog\n"
3253               "%%%%BeginSetup\n"                 3253               "%%%%BeginSetup\n"
3254               "/DeviceRGB setcolorspace\n"       3254               "/DeviceRGB setcolorspace\n"
3255               "gl2psdict begin\n"                3255               "gl2psdict begin\n"
3256               "%%%%EndSetup\n"                   3256               "%%%%EndSetup\n"
3257               "%%%%Page: 1 1\n"                  3257               "%%%%Page: 1 1\n"
3258               "%%%%BeginPageSetup\n");           3258               "%%%%BeginPageSetup\n");
3259                                                  3259 
3260   if(gl2ps->options & TOOLS_GL2PS_LANDSCAPE){    3260   if(gl2ps->options & TOOLS_GL2PS_LANDSCAPE){
3261     tools_gl2psPrintf(gl2ps,"%d 0 translate 9    3261     tools_gl2psPrintf(gl2ps,"%d 0 translate 90 rotate\n",
3262                 (int)gl2ps->viewport[3]);        3262                 (int)gl2ps->viewport[3]);
3263   }                                              3263   }
3264                                                  3264 
3265   tools_gl2psPrintf(gl2ps,"%%%%EndPageSetup\n    3265   tools_gl2psPrintf(gl2ps,"%%%%EndPageSetup\n"
3266               "mark\n"                           3266               "mark\n"
3267               "gsave\n"                          3267               "gsave\n"
3268               "1.0 1.0 scale\n");                3268               "1.0 1.0 scale\n");
3269                                                  3269 
3270   if(gl2ps->options & TOOLS_GL2PS_DRAW_BACKGR    3270   if(gl2ps->options & TOOLS_GL2PS_DRAW_BACKGROUND){
3271     tools_gl2psPrintf(gl2ps,"%g %g %g C\n"       3271     tools_gl2psPrintf(gl2ps,"%g %g %g C\n"
3272                 "newpath %d %d moveto %d %d l    3272                 "newpath %d %d moveto %d %d lineto %d %d lineto %d %d lineto\n"
3273                 "closepath fill\n",              3273                 "closepath fill\n",
3274                 gl2ps->bgcolor[0], gl2ps->bgc    3274                 gl2ps->bgcolor[0], gl2ps->bgcolor[1], gl2ps->bgcolor[2],
3275                 (int)gl2ps->viewport[0], (int    3275                 (int)gl2ps->viewport[0], (int)gl2ps->viewport[1], (int)gl2ps->viewport[2],
3276                 (int)gl2ps->viewport[1], (int    3276                 (int)gl2ps->viewport[1], (int)gl2ps->viewport[2], (int)gl2ps->viewport[3],
3277                 (int)gl2ps->viewport[0], (int    3277                 (int)gl2ps->viewport[0], (int)gl2ps->viewport[3]);
3278   }                                              3278   }
3279 }                                                3279 }
3280                                                  3280 
3281 inline void tools_gl2psPrintPostScriptColor(t    3281 inline void tools_gl2psPrintPostScriptColor(tools_GL2PScontext* gl2ps, tools_GL2PSrgba rgba)
3282 {                                                3282 {
3283   if(!tools_gl2psSameColor(gl2ps->lastrgba, r    3283   if(!tools_gl2psSameColor(gl2ps->lastrgba, rgba)){
3284     tools_gl2psSetLastColor(gl2ps, rgba);        3284     tools_gl2psSetLastColor(gl2ps, rgba);
3285     tools_gl2psPrintf(gl2ps,"%g %g %g C\n", r    3285     tools_gl2psPrintf(gl2ps,"%g %g %g C\n", rgba[0], rgba[1], rgba[2]);
3286   }                                              3286   }
3287 }                                                3287 }
3288                                                  3288 
3289 inline void tools_gl2psResetPostScriptColor(t    3289 inline void tools_gl2psResetPostScriptColor(tools_GL2PScontext* gl2ps)
3290 {                                                3290 {
3291   gl2ps->lastrgba[0] = gl2ps->lastrgba[1] = g    3291   gl2ps->lastrgba[0] = gl2ps->lastrgba[1] = gl2ps->lastrgba[2] = -1.;
3292 }                                                3292 }
3293                                                  3293 
3294 inline void tools_gl2psEndPostScriptLine(tool    3294 inline void tools_gl2psEndPostScriptLine(tools_GL2PScontext* gl2ps)
3295 {                                                3295 {
3296   int i;                                         3296   int i;
3297   if(gl2ps->lastvertex.rgba[0] >= 0.){           3297   if(gl2ps->lastvertex.rgba[0] >= 0.){
3298     tools_gl2psPrintf(gl2ps,"%g %g LE\n", gl2    3298     tools_gl2psPrintf(gl2ps,"%g %g LE\n", gl2ps->lastvertex.xyz[0], gl2ps->lastvertex.xyz[1]);
3299     for(i = 0; i < 3; i++)                       3299     for(i = 0; i < 3; i++)
3300       gl2ps->lastvertex.xyz[i] = -1.;            3300       gl2ps->lastvertex.xyz[i] = -1.;
3301     for(i = 0; i < 4; i++)                       3301     for(i = 0; i < 4; i++)
3302       gl2ps->lastvertex.rgba[i] = -1.;           3302       gl2ps->lastvertex.rgba[i] = -1.;
3303   }                                              3303   }
3304 }                                                3304 }
3305                                                  3305 
3306 inline void tools_gl2psParseStipplePattern(to    3306 inline void tools_gl2psParseStipplePattern(tools_GLushort pattern, tools_GLint factor,
3307                                      int *nb,    3307                                      int *nb, int array[10])
3308 {                                                3308 {
3309   int i, n;                                      3309   int i, n;
3310   int on[8] = {0, 0, 0, 0, 0, 0, 0, 0};          3310   int on[8] = {0, 0, 0, 0, 0, 0, 0, 0};
3311   int off[8] = {0, 0, 0, 0, 0, 0, 0, 0};         3311   int off[8] = {0, 0, 0, 0, 0, 0, 0, 0};
3312   char tmp[16];                                  3312   char tmp[16];
3313                                                  3313 
3314   /* extract the 16 bits from the OpenGL stip    3314   /* extract the 16 bits from the OpenGL stipple pattern */
3315   for(n = 15; n >= 0; n--){                      3315   for(n = 15; n >= 0; n--){
3316     tmp[n] = (char)(pattern & 0x01);             3316     tmp[n] = (char)(pattern & 0x01);
3317     pattern >>= 1;                               3317     pattern >>= 1;
3318   }                                              3318   }
3319   /* compute the on/off pixel sequence */        3319   /* compute the on/off pixel sequence */
3320   n = 0;                                         3320   n = 0;
3321   for(i = 0; i < 8; i++){                        3321   for(i = 0; i < 8; i++){
3322     while(n < 16 && !tmp[n]){ off[i]++; n++;     3322     while(n < 16 && !tmp[n]){ off[i]++; n++; }
3323     while(n < 16 && tmp[n]){ on[i]++; n++; }     3323     while(n < 16 && tmp[n]){ on[i]++; n++; }
3324     if(n >= 15){ i++; break; }                   3324     if(n >= 15){ i++; break; }
3325   }                                              3325   }
3326                                                  3326 
3327   /* store the on/off array from right to lef    3327   /* store the on/off array from right to left, starting with off
3328      pixels. The PostScript specification all    3328      pixels. The PostScript specification allows for at most 11
3329      elements in the on/off array, so we limi    3329      elements in the on/off array, so we limit ourselves to 5 on/off
3330      couples (our longest possible array is t    3330      couples (our longest possible array is thus [on4 off4 on3 off3
3331      on2 off2 on1 off1 on0 off0]) */             3331      on2 off2 on1 off1 on0 off0]) */
3332   *nb = 0;                                       3332   *nb = 0;
3333   for(n = i - 1; n >= 0; n--){                   3333   for(n = i - 1; n >= 0; n--){
3334     array[(*nb)++] = factor * on[n];             3334     array[(*nb)++] = factor * on[n];
3335     array[(*nb)++] = factor * off[n];            3335     array[(*nb)++] = factor * off[n];
3336     if(*nb == 10) break;                         3336     if(*nb == 10) break;
3337   }                                              3337   }
3338 }                                                3338 }
3339                                                  3339 
3340 inline int tools_gl2psPrintPostScriptDash(too    3340 inline int tools_gl2psPrintPostScriptDash(tools_GL2PScontext* gl2ps, tools_GLushort pattern, tools_GLint factor, const char *str)
3341 {                                                3341 {
3342   int len = 0, i, n, array[10];                  3342   int len = 0, i, n, array[10];
3343                                                  3343 
3344   if(pattern == gl2ps->lastpattern && factor     3344   if(pattern == gl2ps->lastpattern && factor == gl2ps->lastfactor)
3345     return 0;                                    3345     return 0;
3346                                                  3346 
3347   gl2ps->lastpattern = pattern;                  3347   gl2ps->lastpattern = pattern;
3348   gl2ps->lastfactor = factor;                    3348   gl2ps->lastfactor = factor;
3349                                                  3349 
3350   if(!pattern || !factor){                       3350   if(!pattern || !factor){
3351     /* solid line */                             3351     /* solid line */
3352     len += tools_gl2psPrintf(gl2ps,"[] 0 %s\n    3352     len += tools_gl2psPrintf(gl2ps,"[] 0 %s\n", str);
3353   }                                              3353   }
3354   else{                                          3354   else{
3355     tools_gl2psParseStipplePattern(pattern, f    3355     tools_gl2psParseStipplePattern(pattern, factor, &n, array);
3356     len += tools_gl2psPrintf(gl2ps,"[");         3356     len += tools_gl2psPrintf(gl2ps,"[");
3357     for(i = 0; i < n; i++){                      3357     for(i = 0; i < n; i++){
3358       if(i) len += tools_gl2psPrintf(gl2ps,"     3358       if(i) len += tools_gl2psPrintf(gl2ps," ");
3359       len += tools_gl2psPrintf(gl2ps,"%d", ar    3359       len += tools_gl2psPrintf(gl2ps,"%d", array[i]);
3360     }                                            3360     }
3361     len += tools_gl2psPrintf(gl2ps,"] 0 %s\n"    3361     len += tools_gl2psPrintf(gl2ps,"] 0 %s\n", str);
3362   }                                              3362   }
3363                                                  3363 
3364   return len;                                    3364   return len;
3365 }                                                3365 }
3366                                                  3366 
3367 inline void tools_gl2psPrintPostScriptPrimiti    3367 inline void tools_gl2psPrintPostScriptPrimitive(tools_GL2PScontext* gl2ps, void *data)
3368 {                                                3368 {
3369   int newline;                                   3369   int newline;
3370   tools_GL2PSprimitive *prim;                    3370   tools_GL2PSprimitive *prim;
3371                                                  3371 
3372   prim = *(tools_GL2PSprimitive**)data;          3372   prim = *(tools_GL2PSprimitive**)data;
3373                                                  3373 
3374   if((gl2ps->options & TOOLS_GL2PS_OCCLUSION_    3374   if((gl2ps->options & TOOLS_GL2PS_OCCLUSION_CULL) && prim->culled) return;
3375                                                  3375 
3376   /* Every effort is made to draw lines as co    3376   /* Every effort is made to draw lines as connected segments (i.e.,
3377      using a single PostScript path): this is    3377      using a single PostScript path): this is the only way to get nice
3378      line joins and to not restart the stippl    3378      line joins and to not restart the stippling for every line
3379      segment. So if the primitive to print is    3379      segment. So if the primitive to print is not a line we must first
3380      finish the current line (if any): */        3380      finish the current line (if any): */
3381   if(prim->type != TOOLS_GL2PS_LINE) tools_gl    3381   if(prim->type != TOOLS_GL2PS_LINE) tools_gl2psEndPostScriptLine(gl2ps);
3382                                                  3382 
3383   switch(prim->type){                            3383   switch(prim->type){
3384   case TOOLS_GL2PS_POINT :                       3384   case TOOLS_GL2PS_POINT :
3385     tools_gl2psPrintPostScriptColor(gl2ps, pr    3385     tools_gl2psPrintPostScriptColor(gl2ps, prim->verts[0].rgba);
3386     tools_gl2psPrintf(gl2ps,"%g %g %g P\n",      3386     tools_gl2psPrintf(gl2ps,"%g %g %g P\n",
3387                 prim->verts[0].xyz[0], prim->    3387                 prim->verts[0].xyz[0], prim->verts[0].xyz[1], 0.5 * prim->width);
3388     break;                                       3388     break;
3389   case TOOLS_GL2PS_LINE :                        3389   case TOOLS_GL2PS_LINE :
3390     if(!tools_gl2psSamePosition(gl2ps->lastve    3390     if(!tools_gl2psSamePosition(gl2ps->lastvertex.xyz, prim->verts[0].xyz) ||
3391        !tools_gl2psSameColor(gl2ps->lastrgba,    3391        !tools_gl2psSameColor(gl2ps->lastrgba, prim->verts[0].rgba) ||
3392        gl2ps->lastlinewidth != prim->width ||    3392        gl2ps->lastlinewidth != prim->width ||
3393        gl2ps->lastlinecap != prim->linecap ||    3393        gl2ps->lastlinecap != prim->linecap ||
3394        gl2ps->lastlinejoin != prim->linejoin     3394        gl2ps->lastlinejoin != prim->linejoin ||
3395        gl2ps->lastpattern != prim->pattern ||    3395        gl2ps->lastpattern != prim->pattern ||
3396        gl2ps->lastfactor != prim->factor){       3396        gl2ps->lastfactor != prim->factor){
3397       /* End the current line if the new segm    3397       /* End the current line if the new segment does not start where
3398          the last one ended, or if the color,    3398          the last one ended, or if the color, the width or the
3399          stippling have changed (multi-stroki    3399          stippling have changed (multi-stroking lines with changing
3400          colors is necessary until we use /sh    3400          colors is necessary until we use /shfill for lines;
3401          unfortunately this means that at the    3401          unfortunately this means that at the moment we can screw up
3402          line stippling for smooth-shaded lin    3402          line stippling for smooth-shaded lines) */
3403       tools_gl2psEndPostScriptLine(gl2ps);       3403       tools_gl2psEndPostScriptLine(gl2ps);
3404       newline = 1;                               3404       newline = 1;
3405     }                                            3405     }
3406     else{                                        3406     else{
3407       newline = 0;                               3407       newline = 0;
3408     }                                            3408     }
3409     if(gl2ps->lastlinewidth != prim->width){     3409     if(gl2ps->lastlinewidth != prim->width){
3410       gl2ps->lastlinewidth = prim->width;        3410       gl2ps->lastlinewidth = prim->width;
3411       tools_gl2psPrintf(gl2ps,"%g W\n", gl2ps    3411       tools_gl2psPrintf(gl2ps,"%g W\n", gl2ps->lastlinewidth);
3412     }                                            3412     }
3413     if(gl2ps->lastlinecap != prim->linecap){     3413     if(gl2ps->lastlinecap != prim->linecap){
3414       gl2ps->lastlinecap = prim->linecap;        3414       gl2ps->lastlinecap = prim->linecap;
3415       tools_gl2psPrintf(gl2ps,"%d LC\n", gl2p    3415       tools_gl2psPrintf(gl2ps,"%d LC\n", gl2ps->lastlinecap);
3416     }                                            3416     }
3417     if(gl2ps->lastlinejoin != prim->linejoin)    3417     if(gl2ps->lastlinejoin != prim->linejoin){
3418       gl2ps->lastlinejoin = prim->linejoin;      3418       gl2ps->lastlinejoin = prim->linejoin;
3419       tools_gl2psPrintf(gl2ps,"%d LJ\n", gl2p    3419       tools_gl2psPrintf(gl2ps,"%d LJ\n", gl2ps->lastlinejoin);
3420     }                                            3420     }
3421     tools_gl2psPrintPostScriptDash(gl2ps, pri    3421     tools_gl2psPrintPostScriptDash(gl2ps, prim->pattern, prim->factor, "setdash");
3422     tools_gl2psPrintPostScriptColor(gl2ps, pr    3422     tools_gl2psPrintPostScriptColor(gl2ps, prim->verts[0].rgba);
3423     tools_gl2psPrintf(gl2ps,"%g %g %s\n", pri    3423     tools_gl2psPrintf(gl2ps,"%g %g %s\n", prim->verts[0].xyz[0], prim->verts[0].xyz[1],
3424                 newline ? "LS" : "L");           3424                 newline ? "LS" : "L");
3425     gl2ps->lastvertex = prim->verts[1];          3425     gl2ps->lastvertex = prim->verts[1];
3426     break;                                       3426     break;
3427   case TOOLS_GL2PS_TRIANGLE :                    3427   case TOOLS_GL2PS_TRIANGLE :
3428     if(!tools_gl2psVertsSameColor(prim)){        3428     if(!tools_gl2psVertsSameColor(prim)){
3429       tools_gl2psResetPostScriptColor(gl2ps);    3429       tools_gl2psResetPostScriptColor(gl2ps);
3430       tools_gl2psPrintf(gl2ps,"%g %g %g %g %g    3430       tools_gl2psPrintf(gl2ps,"%g %g %g %g %g %g %g %g %g %g %g %g %g %g %g ST\n",
3431                   prim->verts[2].xyz[0], prim    3431                   prim->verts[2].xyz[0], prim->verts[2].xyz[1],
3432                   prim->verts[2].rgba[0], pri    3432                   prim->verts[2].rgba[0], prim->verts[2].rgba[1],
3433                   prim->verts[2].rgba[2], pri    3433                   prim->verts[2].rgba[2], prim->verts[1].xyz[0],
3434                   prim->verts[1].xyz[1], prim    3434                   prim->verts[1].xyz[1], prim->verts[1].rgba[0],
3435                   prim->verts[1].rgba[1], pri    3435                   prim->verts[1].rgba[1], prim->verts[1].rgba[2],
3436                   prim->verts[0].xyz[0], prim    3436                   prim->verts[0].xyz[0], prim->verts[0].xyz[1],
3437                   prim->verts[0].rgba[0], pri    3437                   prim->verts[0].rgba[0], prim->verts[0].rgba[1],
3438                   prim->verts[0].rgba[2]);       3438                   prim->verts[0].rgba[2]);
3439     }                                            3439     }
3440     else{                                        3440     else{
3441       tools_gl2psPrintPostScriptColor(gl2ps,     3441       tools_gl2psPrintPostScriptColor(gl2ps, prim->verts[0].rgba);
3442       tools_gl2psPrintf(gl2ps,"%g %g %g %g %g    3442       tools_gl2psPrintf(gl2ps,"%g %g %g %g %g %g T\n",
3443                   prim->verts[2].xyz[0], prim    3443                   prim->verts[2].xyz[0], prim->verts[2].xyz[1],
3444                   prim->verts[1].xyz[0], prim    3444                   prim->verts[1].xyz[0], prim->verts[1].xyz[1],
3445                   prim->verts[0].xyz[0], prim    3445                   prim->verts[0].xyz[0], prim->verts[0].xyz[1]);
3446     }                                            3446     }
3447     break;                                       3447     break;
3448   case TOOLS_GL2PS_QUADRANGLE :                  3448   case TOOLS_GL2PS_QUADRANGLE :
3449     tools_gl2psMsg(TOOLS_GL2PS_WARNING, "Ther    3449     tools_gl2psMsg(TOOLS_GL2PS_WARNING, "There should not be any quad left to print");
3450     break;                                       3450     break;
3451   case TOOLS_GL2PS_PIXMAP :                      3451   case TOOLS_GL2PS_PIXMAP :
3452     tools_gl2psPrintPostScriptPixmap(gl2ps, p    3452     tools_gl2psPrintPostScriptPixmap(gl2ps, prim->verts[0].xyz[0], prim->verts[0].xyz[1],
3453                                prim->data.ima    3453                                prim->data.image,0,8); /*G.Barrand: add two last arguments.*/
3454     break;                                       3454     break;
3455   case TOOLS_GL2PS_IMAGEMAP :                    3455   case TOOLS_GL2PS_IMAGEMAP :
3456     if(prim->data.image->type != TOOLS_GL2PS_    3456     if(prim->data.image->type != TOOLS_GL2PS_IMAGEMAP_WRITTEN){
3457       tools_gl2psPrintPostScriptColor(gl2ps,     3457       tools_gl2psPrintPostScriptColor(gl2ps, prim->verts[0].rgba);
3458       tools_gl2psPrintPostScriptImagemap(gl2p    3458       tools_gl2psPrintPostScriptImagemap(gl2ps, prim->data.image->pixels[0],
3459                                    prim->data    3459                                    prim->data.image->pixels[1],
3460                                    prim->data    3460                                    prim->data.image->width, prim->data.image->height,
3461                                    (const uns    3461                                    (const unsigned char*)(&(prim->data.image->pixels[2])));
3462       prim->data.image->type = TOOLS_GL2PS_IM    3462       prim->data.image->type = TOOLS_GL2PS_IMAGEMAP_WRITTEN;
3463     }                                            3463     }
3464     break;                                       3464     break;
3465   case TOOLS_GL2PS_TEXT :                        3465   case TOOLS_GL2PS_TEXT :
3466     tools_gl2psPrintPostScriptColor(gl2ps, pr    3466     tools_gl2psPrintPostScriptColor(gl2ps, prim->verts[0].rgba);
3467     tools_gl2psPrintf(gl2ps,"(%s) ", prim->da    3467     tools_gl2psPrintf(gl2ps,"(%s) ", prim->data.text->str);
3468     if(prim->data.text->angle)                   3468     if(prim->data.text->angle)
3469       tools_gl2psPrintf(gl2ps,"%g ", prim->da    3469       tools_gl2psPrintf(gl2ps,"%g ", prim->data.text->angle);
3470     tools_gl2psPrintf(gl2ps,"%g %g %d /%s ",     3470     tools_gl2psPrintf(gl2ps,"%g %g %d /%s ",
3471                 prim->verts[0].xyz[0], prim->    3471                 prim->verts[0].xyz[0], prim->verts[0].xyz[1],
3472                 prim->data.text->fontsize, pr    3472                 prim->data.text->fontsize, prim->data.text->fontname);
3473     switch(prim->data.text->alignment){          3473     switch(prim->data.text->alignment){
3474     case TOOLS_GL2PS_TEXT_C:                     3474     case TOOLS_GL2PS_TEXT_C:
3475       tools_gl2psPrintf(gl2ps, prim->data.tex    3475       tools_gl2psPrintf(gl2ps, prim->data.text->angle ? "SCCR\n" : "SCC\n");
3476       break;                                     3476       break;
3477     case TOOLS_GL2PS_TEXT_CL:                    3477     case TOOLS_GL2PS_TEXT_CL:
3478       tools_gl2psPrintf(gl2ps, prim->data.tex    3478       tools_gl2psPrintf(gl2ps, prim->data.text->angle ? "SCLR\n" : "SCL\n");
3479       break;                                     3479       break;
3480     case TOOLS_GL2PS_TEXT_CR:                    3480     case TOOLS_GL2PS_TEXT_CR:
3481       tools_gl2psPrintf(gl2ps, prim->data.tex    3481       tools_gl2psPrintf(gl2ps, prim->data.text->angle ? "SCRR\n" : "SCR\n");
3482       break;                                     3482       break;
3483     case TOOLS_GL2PS_TEXT_B:                     3483     case TOOLS_GL2PS_TEXT_B:
3484       tools_gl2psPrintf(gl2ps, prim->data.tex    3484       tools_gl2psPrintf(gl2ps, prim->data.text->angle ? "SBCR\n" : "SBC\n");
3485       break;                                     3485       break;
3486     case TOOLS_GL2PS_TEXT_BR:                    3486     case TOOLS_GL2PS_TEXT_BR:
3487       tools_gl2psPrintf(gl2ps, prim->data.tex    3487       tools_gl2psPrintf(gl2ps, prim->data.text->angle ? "SBRR\n" : "SBR\n");
3488       break;                                     3488       break;
3489     case TOOLS_GL2PS_TEXT_T:                     3489     case TOOLS_GL2PS_TEXT_T:
3490       tools_gl2psPrintf(gl2ps, prim->data.tex    3490       tools_gl2psPrintf(gl2ps, prim->data.text->angle ? "STCR\n" : "STC\n");
3491       break;                                     3491       break;
3492     case TOOLS_GL2PS_TEXT_TL:                    3492     case TOOLS_GL2PS_TEXT_TL:
3493       tools_gl2psPrintf(gl2ps, prim->data.tex    3493       tools_gl2psPrintf(gl2ps, prim->data.text->angle ? "STLR\n" : "STL\n");
3494       break;                                     3494       break;
3495     case TOOLS_GL2PS_TEXT_TR:                    3495     case TOOLS_GL2PS_TEXT_TR:
3496       tools_gl2psPrintf(gl2ps, prim->data.tex    3496       tools_gl2psPrintf(gl2ps, prim->data.text->angle ? "STRR\n" : "STR\n");
3497       break;                                     3497       break;
3498     case TOOLS_GL2PS_TEXT_BL:                    3498     case TOOLS_GL2PS_TEXT_BL:
3499     default:                                     3499     default:
3500       tools_gl2psPrintf(gl2ps, prim->data.tex    3500       tools_gl2psPrintf(gl2ps, prim->data.text->angle ? "SR\n" : "S\n");
3501       break;                                     3501       break;
3502     }                                            3502     }
3503     break;                                       3503     break;
3504   case TOOLS_GL2PS_SPECIAL :                     3504   case TOOLS_GL2PS_SPECIAL :
3505     /* alignment contains the format for whic    3505     /* alignment contains the format for which the special output text
3506        is intended */                            3506        is intended */
3507     if(prim->data.text->alignment == TOOLS_GL    3507     if(prim->data.text->alignment == TOOLS_GL2PS_PS ||
3508        prim->data.text->alignment == TOOLS_GL    3508        prim->data.text->alignment == TOOLS_GL2PS_EPS)
3509       tools_gl2psPrintf(gl2ps,"%s\n", prim->d    3509       tools_gl2psPrintf(gl2ps,"%s\n", prim->data.text->str);
3510     break;                                       3510     break;
3511   default :                                      3511   default :
3512     break;                                       3512     break;
3513   }                                              3513   }
3514 }                                                3514 }
3515                                                  3515 
3516 inline void tools_gl2psPrintPostScriptFooter(    3516 inline void tools_gl2psPrintPostScriptFooter(tools_GL2PScontext* gl2ps)
3517 {                                                3517 {
3518   tools_gl2psPrintf(gl2ps,"grestore\n"           3518   tools_gl2psPrintf(gl2ps,"grestore\n"
3519               "showpage\n"                       3519               "showpage\n"
3520               "cleartomark\n"                    3520               "cleartomark\n"
3521               "%%%%PageTrailer\n"                3521               "%%%%PageTrailer\n"
3522               "%%%%Trailer\n"                    3522               "%%%%Trailer\n"
3523               "end\n"                            3523               "end\n"
3524               "%%%%EOF\n");                      3524               "%%%%EOF\n");
3525                                                  3525 
3526   tools_gl2psPrintGzipFooter(gl2ps);             3526   tools_gl2psPrintGzipFooter(gl2ps);
3527 }                                                3527 }
3528                                                  3528 
3529 inline void tools_gl2psPrintPostScriptBeginVi    3529 inline void tools_gl2psPrintPostScriptBeginViewport(tools_GL2PScontext* gl2ps, tools_GLint viewport[4])
3530 {                                                3530 {
3531   tools_GLint idx;                               3531   tools_GLint idx;
3532   tools_GLfloat rgba[4];                         3532   tools_GLfloat rgba[4];
3533   int x = viewport[0], y = viewport[1], w = v    3533   int x = viewport[0], y = viewport[1], w = viewport[2], h = viewport[3];
3534                                                  3534 
3535   tools_glRenderMode(TOOLS_GL_FEEDBACK);         3535   tools_glRenderMode(TOOLS_GL_FEEDBACK);
3536                                                  3536 
3537   if(gl2ps->header){                             3537   if(gl2ps->header){
3538     tools_gl2psPrintPostScriptHeader(gl2ps);     3538     tools_gl2psPrintPostScriptHeader(gl2ps);
3539     gl2ps->header = TOOLS_GL_FALSE;              3539     gl2ps->header = TOOLS_GL_FALSE;
3540   }                                              3540   }
3541                                                  3541 
3542   tools_gl2psResetPostScriptColor(gl2ps);        3542   tools_gl2psResetPostScriptColor(gl2ps);
3543   tools_gl2psResetLineProperties(gl2ps);         3543   tools_gl2psResetLineProperties(gl2ps);
3544                                                  3544 
3545   tools_gl2psPrintf(gl2ps,"gsave\n"              3545   tools_gl2psPrintf(gl2ps,"gsave\n"
3546               "1.0 1.0 scale\n");                3546               "1.0 1.0 scale\n");
3547                                                  3547 
3548   if(gl2ps->options & TOOLS_GL2PS_DRAW_BACKGR    3548   if(gl2ps->options & TOOLS_GL2PS_DRAW_BACKGROUND){
3549     if(gl2ps->colormode == TOOLS_GL_RGBA || g    3549     if(gl2ps->colormode == TOOLS_GL_RGBA || gl2ps->colorsize == 0){
3550       tools_glGetFloatv(TOOLS_GL_COLOR_CLEAR_    3550       tools_glGetFloatv(TOOLS_GL_COLOR_CLEAR_VALUE, rgba);
3551     }                                            3551     }
3552     else{                                        3552     else{
3553       tools_glGetIntegerv(TOOLS_GL_INDEX_CLEA    3553       tools_glGetIntegerv(TOOLS_GL_INDEX_CLEAR_VALUE, &idx);
3554       rgba[0] = gl2ps->colormap[idx][0];         3554       rgba[0] = gl2ps->colormap[idx][0];
3555       rgba[1] = gl2ps->colormap[idx][1];         3555       rgba[1] = gl2ps->colormap[idx][1];
3556       rgba[2] = gl2ps->colormap[idx][2];         3556       rgba[2] = gl2ps->colormap[idx][2];
3557       rgba[3] = 1.0F;                            3557       rgba[3] = 1.0F;
3558     }                                            3558     }
3559     tools_gl2psPrintf(gl2ps,"%g %g %g C\n"       3559     tools_gl2psPrintf(gl2ps,"%g %g %g C\n"
3560                 "newpath %d %d moveto %d %d l    3560                 "newpath %d %d moveto %d %d lineto %d %d lineto %d %d lineto\n"
3561                 "closepath fill\n",              3561                 "closepath fill\n",
3562                 rgba[0], rgba[1], rgba[2],       3562                 rgba[0], rgba[1], rgba[2],
3563                 x, y, x+w, y, x+w, y+h, x, y+    3563                 x, y, x+w, y, x+w, y+h, x, y+h);
3564   }                                              3564   }
3565                                                  3565 
3566   tools_gl2psPrintf(gl2ps,"newpath %d %d move    3566   tools_gl2psPrintf(gl2ps,"newpath %d %d moveto %d %d lineto %d %d lineto %d %d lineto\n"
3567               "closepath clip\n",                3567               "closepath clip\n",
3568               x, y, x+w, y, x+w, y+h, x, y+h)    3568               x, y, x+w, y, x+w, y+h, x, y+h);
3569                                                  3569 
3570 }                                                3570 }
3571                                                  3571 
3572 inline tools_GLint tools_gl2psPrintPostScript    3572 inline tools_GLint tools_gl2psPrintPostScriptEndViewport(tools_GL2PScontext* gl2ps)
3573 {                                                3573 {
3574   tools_GLint res;                               3574   tools_GLint res;
3575                                                  3575 
3576   res = tools_gl2psPrintPrimitives(gl2ps);       3576   res = tools_gl2psPrintPrimitives(gl2ps);
3577   tools_gl2psPrintf(gl2ps,"grestore\n");         3577   tools_gl2psPrintf(gl2ps,"grestore\n");
3578   return res;                                    3578   return res;
3579 }                                                3579 }
3580                                                  3580 
3581 inline void tools_gl2psPrintPostScriptFinalPr    3581 inline void tools_gl2psPrintPostScriptFinalPrimitive(tools_GL2PScontext* gl2ps)
3582 {                                                3582 {
3583   /* End any remaining line, if any */           3583   /* End any remaining line, if any */
3584   tools_gl2psEndPostScriptLine(gl2ps);           3584   tools_gl2psEndPostScriptLine(gl2ps);
3585 }                                                3585 }
3586                                                  3586 
3587 /* definition of the PostScript and Encapsula    3587 /* definition of the PostScript and Encapsulated PostScript backends */
3588                                                  3588 
3589 static const tools_GL2PSbackend tools_gl2psPS    3589 static const tools_GL2PSbackend tools_gl2psPS = {
3590   tools_gl2psPrintPostScriptHeader,              3590   tools_gl2psPrintPostScriptHeader,
3591   tools_gl2psPrintPostScriptFooter,              3591   tools_gl2psPrintPostScriptFooter,
3592   tools_gl2psPrintPostScriptBeginViewport,       3592   tools_gl2psPrintPostScriptBeginViewport,
3593   tools_gl2psPrintPostScriptEndViewport,         3593   tools_gl2psPrintPostScriptEndViewport,
3594   tools_gl2psPrintPostScriptPrimitive,           3594   tools_gl2psPrintPostScriptPrimitive,
3595   tools_gl2psPrintPostScriptFinalPrimitive,      3595   tools_gl2psPrintPostScriptFinalPrimitive,
3596   "ps",                                          3596   "ps",
3597   "Postscript"                                   3597   "Postscript"
3598 };                                               3598 };
3599                                                  3599 
3600 static const tools_GL2PSbackend tools_gl2psEP    3600 static const tools_GL2PSbackend tools_gl2psEPS = {
3601   tools_gl2psPrintPostScriptHeader,              3601   tools_gl2psPrintPostScriptHeader,
3602   tools_gl2psPrintPostScriptFooter,              3602   tools_gl2psPrintPostScriptFooter,
3603   tools_gl2psPrintPostScriptBeginViewport,       3603   tools_gl2psPrintPostScriptBeginViewport,
3604   tools_gl2psPrintPostScriptEndViewport,         3604   tools_gl2psPrintPostScriptEndViewport,
3605   tools_gl2psPrintPostScriptPrimitive,           3605   tools_gl2psPrintPostScriptPrimitive,
3606   tools_gl2psPrintPostScriptFinalPrimitive,      3606   tools_gl2psPrintPostScriptFinalPrimitive,
3607   "eps",                                         3607   "eps",
3608   "Encapsulated Postscript"                      3608   "Encapsulated Postscript"
3609 };                                               3609 };
3610                                                  3610 
3611 /********************************************    3611 /*********************************************************************
3612  *                                               3612  *
3613  * LaTeX routines                                3613  * LaTeX routines
3614  *                                               3614  *
3615  ********************************************    3615  *********************************************************************/
3616                                                  3616 
3617 inline void tools_gl2psPrintTeXHeader(tools_G    3617 inline void tools_gl2psPrintTeXHeader(tools_GL2PScontext* gl2ps)
3618 {                                                3618 {
3619   char name[256];                                3619   char name[256];
3620   time_t now;                                    3620   time_t now;
3621   int i;                                         3621   int i;
3622   tools_GLfloat _s;                              3622   tools_GLfloat _s;
3623                                                  3623 
3624   if(gl2ps->filename && strlen(gl2ps->filenam    3624   if(gl2ps->filename && strlen(gl2ps->filename) < 256){
3625     for(i = (int)strlen(gl2ps->filename) - 1;    3625     for(i = (int)strlen(gl2ps->filename) - 1; i >= 0; i--){
3626       if(gl2ps->filename[i] == '.'){             3626       if(gl2ps->filename[i] == '.'){
3627         strncpy(name, gl2ps->filename, i);       3627         strncpy(name, gl2ps->filename, i);
3628         name[i] = '\0';                          3628         name[i] = '\0';
3629         break;                                   3629         break;
3630       }                                          3630       }
3631     }                                            3631     }
3632     if(i <= 0) strcpy(name, gl2ps->filename);    3632     if(i <= 0) strcpy(name, gl2ps->filename);
3633   }                                              3633   }
3634   else{                                          3634   else{
3635     strcpy(name, "untitled");                    3635     strcpy(name, "untitled");
3636   }                                              3636   }
3637                                                  3637 
3638   time(&now);                                    3638   time(&now);
3639                                                  3639 
3640   fprintf(gl2ps->stream,                         3640   fprintf(gl2ps->stream,
3641           "%% Title: %s\n"                       3641           "%% Title: %s\n"
3642           "%% Creator: GL2PS %d.%d.%d%s, %s\n    3642           "%% Creator: GL2PS %d.%d.%d%s, %s\n"
3643           "%% For: %s\n"                         3643           "%% For: %s\n"
3644           "%% CreationDate: %s",                 3644           "%% CreationDate: %s",
3645           gl2ps->title, TOOLS_GL2PS_MAJOR_VER    3645           gl2ps->title, TOOLS_GL2PS_MAJOR_VERSION, TOOLS_GL2PS_MINOR_VERSION,
3646           TOOLS_GL2PS_PATCH_VERSION, TOOLS_GL    3646           TOOLS_GL2PS_PATCH_VERSION, TOOLS_GL2PS_EXTRA_VERSION, TOOLS_GL2PS_COPYRIGHT,
3647           gl2ps->producer, ctime(&now));         3647           gl2ps->producer, ctime(&now));
3648                                                  3648 
3649   _s = gl2ps->tex_scaling;                       3649   _s = gl2ps->tex_scaling;
3650   if(_s <= 0.) _s = 1.;                          3650   if(_s <= 0.) _s = 1.;
3651   fprintf(gl2ps->stream,                         3651   fprintf(gl2ps->stream,
3652           "\\setlength{\\unitlength}{%gpt}\n"    3652           "\\setlength{\\unitlength}{%gpt}\n"
3653           "\\begin{picture}(0,0)\n"              3653           "\\begin{picture}(0,0)\n"
3654           "\\includegraphics[scale=%g]{%s}\n"    3654           "\\includegraphics[scale=%g]{%s}\n"
3655           "\\end{picture}%%\n"                   3655           "\\end{picture}%%\n"
3656           "%s\\begin{picture}(%d,%d)(0,0)\n",    3656           "%s\\begin{picture}(%d,%d)(0,0)\n",
3657           _s, _s, name,                          3657           _s, _s, name,
3658           (gl2ps->options & TOOLS_GL2PS_LANDS    3658           (gl2ps->options & TOOLS_GL2PS_LANDSCAPE) ? "\\rotatebox{90}{" : "",
3659           (int)(gl2ps->viewport[2]), (int)(gl    3659           (int)(gl2ps->viewport[2]), (int)(gl2ps->viewport[3]));
3660 }                                                3660 }
3661                                                  3661 
3662 inline void tools_gl2psPrintTeXPrimitive(tool    3662 inline void tools_gl2psPrintTeXPrimitive(tools_GL2PScontext* gl2ps, void *data)
3663 {                                                3663 {
3664   tools_GL2PSprimitive *prim;                    3664   tools_GL2PSprimitive *prim;
3665                                                  3665 
3666   prim = *(tools_GL2PSprimitive**)data;          3666   prim = *(tools_GL2PSprimitive**)data;
3667                                                  3667 
3668   switch(prim->type){                            3668   switch(prim->type){
3669   case TOOLS_GL2PS_TEXT :                        3669   case TOOLS_GL2PS_TEXT :
3670     if(!(gl2ps->options & TOOLS_GL2PS_NO_TEX_    3670     if(!(gl2ps->options & TOOLS_GL2PS_NO_TEX_FONTSIZE))
3671       fprintf(gl2ps->stream, "\\fontsize{%d}{    3671       fprintf(gl2ps->stream, "\\fontsize{%d}{0}\\selectfont",
3672               prim->data.text->fontsize);        3672               prim->data.text->fontsize);
3673     fprintf(gl2ps->stream, "\\put(%g,%g)",       3673     fprintf(gl2ps->stream, "\\put(%g,%g)",
3674             prim->verts[0].xyz[0],               3674             prim->verts[0].xyz[0],
3675             prim->verts[0].xyz[1]);              3675             prim->verts[0].xyz[1]);
3676     if(prim->data.text->angle)                   3676     if(prim->data.text->angle)
3677       fprintf(gl2ps->stream, "{\\rotatebox{%g    3677       fprintf(gl2ps->stream, "{\\rotatebox{%g}", prim->data.text->angle);
3678     fprintf(gl2ps->stream, "{\\makebox(0,0)")    3678     fprintf(gl2ps->stream, "{\\makebox(0,0)");
3679     switch(prim->data.text->alignment){          3679     switch(prim->data.text->alignment){
3680     case TOOLS_GL2PS_TEXT_C:                     3680     case TOOLS_GL2PS_TEXT_C:
3681       fprintf(gl2ps->stream, "{");               3681       fprintf(gl2ps->stream, "{");
3682       break;                                     3682       break;
3683     case TOOLS_GL2PS_TEXT_CL:                    3683     case TOOLS_GL2PS_TEXT_CL:
3684       fprintf(gl2ps->stream, "[l]{");            3684       fprintf(gl2ps->stream, "[l]{");
3685       break;                                     3685       break;
3686     case TOOLS_GL2PS_TEXT_CR:                    3686     case TOOLS_GL2PS_TEXT_CR:
3687       fprintf(gl2ps->stream, "[r]{");            3687       fprintf(gl2ps->stream, "[r]{");
3688       break;                                     3688       break;
3689     case TOOLS_GL2PS_TEXT_B:                     3689     case TOOLS_GL2PS_TEXT_B:
3690       fprintf(gl2ps->stream, "[b]{");            3690       fprintf(gl2ps->stream, "[b]{");
3691       break;                                     3691       break;
3692     case TOOLS_GL2PS_TEXT_BR:                    3692     case TOOLS_GL2PS_TEXT_BR:
3693       fprintf(gl2ps->stream, "[br]{");           3693       fprintf(gl2ps->stream, "[br]{");
3694       break;                                     3694       break;
3695     case TOOLS_GL2PS_TEXT_T:                     3695     case TOOLS_GL2PS_TEXT_T:
3696       fprintf(gl2ps->stream, "[t]{");            3696       fprintf(gl2ps->stream, "[t]{");
3697       break;                                     3697       break;
3698     case TOOLS_GL2PS_TEXT_TL:                    3698     case TOOLS_GL2PS_TEXT_TL:
3699       fprintf(gl2ps->stream, "[tl]{");           3699       fprintf(gl2ps->stream, "[tl]{");
3700       break;                                     3700       break;
3701     case TOOLS_GL2PS_TEXT_TR:                    3701     case TOOLS_GL2PS_TEXT_TR:
3702       fprintf(gl2ps->stream, "[tr]{");           3702       fprintf(gl2ps->stream, "[tr]{");
3703       break;                                     3703       break;
3704     case TOOLS_GL2PS_TEXT_BL:                    3704     case TOOLS_GL2PS_TEXT_BL:
3705     default:                                     3705     default:
3706       fprintf(gl2ps->stream, "[bl]{");           3706       fprintf(gl2ps->stream, "[bl]{");
3707       break;                                     3707       break;
3708     }                                            3708     }
3709     fprintf(gl2ps->stream, "\\textcolor[rgb]{    3709     fprintf(gl2ps->stream, "\\textcolor[rgb]{%g,%g,%g}{{%s}}",
3710             prim->verts[0].rgba[0], prim->ver    3710             prim->verts[0].rgba[0], prim->verts[0].rgba[1], prim->verts[0].rgba[2],
3711             prim->data.text->str);               3711             prim->data.text->str);
3712     if(prim->data.text->angle)                   3712     if(prim->data.text->angle)
3713       fprintf(gl2ps->stream, "}");               3713       fprintf(gl2ps->stream, "}");
3714     fprintf(gl2ps->stream, "}}\n");              3714     fprintf(gl2ps->stream, "}}\n");
3715     break;                                       3715     break;
3716   case TOOLS_GL2PS_SPECIAL :                     3716   case TOOLS_GL2PS_SPECIAL :
3717     /* alignment contains the format for whic    3717     /* alignment contains the format for which the special output text
3718        is intended */                            3718        is intended */
3719     if (prim->data.text->alignment == TOOLS_G    3719     if (prim->data.text->alignment == TOOLS_GL2PS_TEX)
3720       fprintf(gl2ps->stream, "%s\n", prim->da    3720       fprintf(gl2ps->stream, "%s\n", prim->data.text->str);
3721     break;                                       3721     break;
3722   default :                                      3722   default :
3723     break;                                       3723     break;
3724   }                                              3724   }
3725 }                                                3725 }
3726                                                  3726 
3727 inline void tools_gl2psPrintTeXFooter(tools_G    3727 inline void tools_gl2psPrintTeXFooter(tools_GL2PScontext* gl2ps)
3728 {                                                3728 {
3729   fprintf(gl2ps->stream, "\\end{picture}%s\n"    3729   fprintf(gl2ps->stream, "\\end{picture}%s\n",
3730           (gl2ps->options & TOOLS_GL2PS_LANDS    3730           (gl2ps->options & TOOLS_GL2PS_LANDSCAPE) ? "}" : "");
3731 }                                                3731 }
3732                                                  3732 
3733 inline void tools_gl2psPrintTeXBeginViewport(    3733 inline void tools_gl2psPrintTeXBeginViewport(tools_GL2PScontext* gl2ps, tools_GLint viewport[4])
3734 {                                                3734 {
3735   (void) viewport;  /* not used */               3735   (void) viewport;  /* not used */
3736   tools_glRenderMode(TOOLS_GL_FEEDBACK);         3736   tools_glRenderMode(TOOLS_GL_FEEDBACK);
3737                                                  3737 
3738   tools_gl2psResetLineProperties(gl2ps);         3738   tools_gl2psResetLineProperties(gl2ps);
3739                                                  3739 
3740   if(gl2ps->header){                             3740   if(gl2ps->header){
3741     tools_gl2psPrintTeXHeader(gl2ps);            3741     tools_gl2psPrintTeXHeader(gl2ps);
3742     gl2ps->header = TOOLS_GL_FALSE;              3742     gl2ps->header = TOOLS_GL_FALSE;
3743   }                                              3743   }
3744 }                                                3744 }
3745                                                  3745 
3746 inline tools_GLint tools_gl2psPrintTeXEndView    3746 inline tools_GLint tools_gl2psPrintTeXEndViewport(tools_GL2PScontext* gl2ps)
3747 {                                                3747 {
3748   return tools_gl2psPrintPrimitives(gl2ps);      3748   return tools_gl2psPrintPrimitives(gl2ps);
3749 }                                                3749 }
3750                                                  3750 
3751 inline void tools_gl2psPrintTeXFinalPrimitive    3751 inline void tools_gl2psPrintTeXFinalPrimitive(tools_GL2PScontext*)
3752 {                                                3752 {
3753 }                                                3753 }
3754                                                  3754 
3755 /* definition of the LaTeX backend */            3755 /* definition of the LaTeX backend */
3756                                                  3756 
3757 static const tools_GL2PSbackend tools_gl2psTE    3757 static const tools_GL2PSbackend tools_gl2psTEX = {
3758   tools_gl2psPrintTeXHeader,                     3758   tools_gl2psPrintTeXHeader,
3759   tools_gl2psPrintTeXFooter,                     3759   tools_gl2psPrintTeXFooter,
3760   tools_gl2psPrintTeXBeginViewport,              3760   tools_gl2psPrintTeXBeginViewport,
3761   tools_gl2psPrintTeXEndViewport,                3761   tools_gl2psPrintTeXEndViewport,
3762   tools_gl2psPrintTeXPrimitive,                  3762   tools_gl2psPrintTeXPrimitive,
3763   tools_gl2psPrintTeXFinalPrimitive,             3763   tools_gl2psPrintTeXFinalPrimitive,
3764   "tex",                                         3764   "tex",
3765   "LaTeX text"                                   3765   "LaTeX text"
3766 };                                               3766 };
3767                                                  3767 
3768 /********************************************    3768 /*********************************************************************
3769  *                                               3769  *
3770  * PDF routines                                  3770  * PDF routines
3771  *                                               3771  *
3772  ********************************************    3772  *********************************************************************/
3773                                                  3773 
3774 inline int tools_gl2psPrintPDFCompressorType(    3774 inline int tools_gl2psPrintPDFCompressorType(tools_GL2PScontext* gl2ps)
3775 {                                                3775 {
3776 #if defined(TOOLS_GL2PS_HAVE_ZLIB)               3776 #if defined(TOOLS_GL2PS_HAVE_ZLIB)
3777   if(gl2ps->options & TOOLS_GL2PS_COMPRESS){     3777   if(gl2ps->options & TOOLS_GL2PS_COMPRESS){
3778     return fprintf(gl2ps->stream, "/Filter [/    3778     return fprintf(gl2ps->stream, "/Filter [/FlateDecode]\n");
3779   }                                              3779   }
3780 #endif                                           3780 #endif
3781   (void)gl2ps;                                   3781   (void)gl2ps;
3782   return 0;                                      3782   return 0;
3783 }                                                3783 }
3784                                                  3784 
3785 inline int tools_gl2psPrintPDFStrokeColor(too    3785 inline int tools_gl2psPrintPDFStrokeColor(tools_GL2PScontext* gl2ps, tools_GL2PSrgba rgba)
3786 {                                                3786 {
3787   int i, offs = 0;                               3787   int i, offs = 0;
3788                                                  3788 
3789   tools_gl2psSetLastColor(gl2ps, rgba);          3789   tools_gl2psSetLastColor(gl2ps, rgba);
3790   for(i = 0; i < 3; ++i){                        3790   for(i = 0; i < 3; ++i){
3791     if(TOOLS_GL2PS_ZERO(rgba[i]))                3791     if(TOOLS_GL2PS_ZERO(rgba[i]))
3792       offs += tools_gl2psPrintf(gl2ps,"%.0f "    3792       offs += tools_gl2psPrintf(gl2ps,"%.0f ", 0.);
3793     else if(rgba[i] < 1e-4 || rgba[i] > 1e6)     3793     else if(rgba[i] < 1e-4 || rgba[i] > 1e6) /* avoid %e formatting */
3794       offs += tools_gl2psPrintf(gl2ps,"%f ",     3794       offs += tools_gl2psPrintf(gl2ps,"%f ", rgba[i]);
3795     else                                         3795     else
3796       offs += tools_gl2psPrintf(gl2ps,"%g ",     3796       offs += tools_gl2psPrintf(gl2ps,"%g ", rgba[i]);
3797   }                                              3797   }
3798   offs += tools_gl2psPrintf(gl2ps,"RG\n");       3798   offs += tools_gl2psPrintf(gl2ps,"RG\n");
3799   return offs;                                   3799   return offs;
3800 }                                                3800 }
3801                                                  3801 
3802 inline int tools_gl2psPrintPDFFillColor(tools    3802 inline int tools_gl2psPrintPDFFillColor(tools_GL2PScontext* gl2ps, tools_GL2PSrgba rgba)
3803 {                                                3803 {
3804   int i, offs = 0;                               3804   int i, offs = 0;
3805                                                  3805 
3806   for(i = 0; i < 3; ++i){                        3806   for(i = 0; i < 3; ++i){
3807     if(TOOLS_GL2PS_ZERO(rgba[i]))                3807     if(TOOLS_GL2PS_ZERO(rgba[i]))
3808       offs += tools_gl2psPrintf(gl2ps,"%.0f "    3808       offs += tools_gl2psPrintf(gl2ps,"%.0f ", 0.);
3809     else if(rgba[i] < 1e-4 || rgba[i] > 1e6)     3809     else if(rgba[i] < 1e-4 || rgba[i] > 1e6) /* avoid %e formatting */
3810       offs += tools_gl2psPrintf(gl2ps,"%f ",     3810       offs += tools_gl2psPrintf(gl2ps,"%f ", rgba[i]);
3811     else                                         3811     else
3812       offs += tools_gl2psPrintf(gl2ps,"%g ",     3812       offs += tools_gl2psPrintf(gl2ps,"%g ", rgba[i]);
3813   }                                              3813   }
3814   offs += tools_gl2psPrintf(gl2ps,"rg\n");       3814   offs += tools_gl2psPrintf(gl2ps,"rg\n");
3815   return offs;                                   3815   return offs;
3816 }                                                3816 }
3817                                                  3817 
3818 inline int tools_gl2psPrintPDFLineWidth(tools    3818 inline int tools_gl2psPrintPDFLineWidth(tools_GL2PScontext* gl2ps, tools_GLfloat lw)
3819 {                                                3819 {
3820   if(TOOLS_GL2PS_ZERO(lw))                       3820   if(TOOLS_GL2PS_ZERO(lw))
3821     return tools_gl2psPrintf(gl2ps,"%.0f w\n"    3821     return tools_gl2psPrintf(gl2ps,"%.0f w\n", 0.);
3822   else if(lw < 1e-4 || lw > 1e6) /* avoid %e     3822   else if(lw < 1e-4 || lw > 1e6) /* avoid %e formatting */
3823     return tools_gl2psPrintf(gl2ps,"%f w\n",     3823     return tools_gl2psPrintf(gl2ps,"%f w\n", lw);
3824   else                                           3824   else
3825     return tools_gl2psPrintf(gl2ps,"%g w\n",     3825     return tools_gl2psPrintf(gl2ps,"%g w\n", lw);
3826 }                                                3826 }
3827                                                  3827 
3828 inline int tools_gl2psPrintPDFLineCap(tools_G    3828 inline int tools_gl2psPrintPDFLineCap(tools_GL2PScontext* gl2ps, tools_GLint lc)
3829 {                                                3829 {
3830   if(gl2ps->lastlinecap == lc)                   3830   if(gl2ps->lastlinecap == lc)
3831     return 0;                                    3831     return 0;
3832   else                                           3832   else
3833     return tools_gl2psPrintf(gl2ps,"%d J\n",     3833     return tools_gl2psPrintf(gl2ps,"%d J\n", lc);
3834 }                                                3834 }
3835                                                  3835 
3836 inline int tools_gl2psPrintPDFLineJoin(tools_    3836 inline int tools_gl2psPrintPDFLineJoin(tools_GL2PScontext* gl2ps, tools_GLint lj)
3837 {                                                3837 {
3838   if(gl2ps->lastlinejoin == lj)                  3838   if(gl2ps->lastlinejoin == lj)
3839     return 0;                                    3839     return 0;
3840   else                                           3840   else
3841     return tools_gl2psPrintf(gl2ps,"%d j\n",     3841     return tools_gl2psPrintf(gl2ps,"%d j\n", lj);
3842 }                                                3842 }
3843                                                  3843 
3844 inline void tools_gl2psPutPDFText(tools_GL2PS    3844 inline void tools_gl2psPutPDFText(tools_GL2PScontext* gl2ps, tools_GL2PSstring *text, int cnt, tools_GLfloat x, tools_GLfloat y)
3845 {                                                3845 {
3846   tools_GLfloat _rad, crad, srad;                3846   tools_GLfloat _rad, crad, srad;
3847                                                  3847 
3848   if(text->angle == 0.0F){                       3848   if(text->angle == 0.0F){
3849     gl2ps->streamlength += tools_gl2psPrintf     3849     gl2ps->streamlength += tools_gl2psPrintf
3850       (gl2ps, "BT\n"                             3850       (gl2ps, "BT\n"
3851        "/F%d %d Tf\n"                            3851        "/F%d %d Tf\n"
3852        "%f %f Td\n"                              3852        "%f %f Td\n"
3853        "(%s) Tj\n"                               3853        "(%s) Tj\n"
3854        "ET\n",                                   3854        "ET\n",
3855        cnt, text->fontsize, x, y, text->str);    3855        cnt, text->fontsize, x, y, text->str);
3856   }                                              3856   }
3857   else{                                          3857   else{
3858     _rad = (tools_GLfloat)(3.141593F * text->    3858     _rad = (tools_GLfloat)(3.141593F * text->angle / 180.0F);
3859     srad = (tools_GLfloat)sin(_rad);             3859     srad = (tools_GLfloat)sin(_rad);
3860     crad = (tools_GLfloat)cos(_rad);             3860     crad = (tools_GLfloat)cos(_rad);
3861     gl2ps->streamlength += tools_gl2psPrintf     3861     gl2ps->streamlength += tools_gl2psPrintf
3862       (gl2ps, "BT\n"                             3862       (gl2ps, "BT\n"
3863        "/F%d %d Tf\n"                            3863        "/F%d %d Tf\n"
3864        "%f %f %f %f %f %f Tm\n"                  3864        "%f %f %f %f %f %f Tm\n"
3865        "(%s) Tj\n"                               3865        "(%s) Tj\n"
3866        "ET\n",                                   3866        "ET\n",
3867        cnt, text->fontsize, crad, srad, -srad    3867        cnt, text->fontsize, crad, srad, -srad, crad, x, y, text->str);
3868   }                                              3868   }
3869 }                                                3869 }
3870                                                  3870 
3871 /*                                               3871 /*
3872   This is used for producing aligned text in     3872   This is used for producing aligned text in PDF. (x, y) is the anchor for the
3873   aligned text, (xbl, ybl) is the bottom left    3873   aligned text, (xbl, ybl) is the bottom left corner. Rotation happens
3874   around (x, y).*/                               3874   around (x, y).*/
3875 inline void tools_gl2psPutPDFTextBL(tools_GL2    3875 inline void tools_gl2psPutPDFTextBL(tools_GL2PScontext* gl2ps, tools_GL2PSstring *text, int cnt, tools_GLfloat x, tools_GLfloat y,
3876                               tools_GLfloat x    3876                               tools_GLfloat xbl, tools_GLfloat ybl)
3877 {                                                3877 {
3878   if(text->angle == 0.0F){                       3878   if(text->angle == 0.0F){
3879     gl2ps->streamlength += tools_gl2psPrintf     3879     gl2ps->streamlength += tools_gl2psPrintf
3880       (gl2ps, "BT\n"                             3880       (gl2ps, "BT\n"
3881        "/F%d %d Tf\n"                            3881        "/F%d %d Tf\n"
3882        "%f %f Td\n"                              3882        "%f %f Td\n"
3883        "(%s) Tj\n"                               3883        "(%s) Tj\n"
3884        "ET\n",                                   3884        "ET\n",
3885        cnt, text->fontsize, xbl, ybl, text->s    3885        cnt, text->fontsize, xbl, ybl, text->str);
3886   }                                              3886   }
3887   else{                                          3887   else{
3888     tools_GLfloat a, ca, sa;                     3888     tools_GLfloat a, ca, sa;
3889     tools_GLfloat pi = 3.141593F;                3889     tools_GLfloat pi = 3.141593F;
3890     tools_GLfloat i = atan2(y - ybl, x - xbl)    3890     tools_GLfloat i = atan2(y - ybl, x - xbl);
3891     tools_GLfloat r = sqrt((y - ybl) * (y - y    3891     tools_GLfloat r = sqrt((y - ybl) * (y - ybl) + (x - xbl) * (x - xbl));
3892                                                  3892 
3893     a = (tools_GLfloat)(pi * text->angle / 18    3893     a = (tools_GLfloat)(pi * text->angle / 180.0F);
3894     sa = (tools_GLfloat)sin(a);                  3894     sa = (tools_GLfloat)sin(a);
3895     ca = (tools_GLfloat)cos(a);                  3895     ca = (tools_GLfloat)cos(a);
3896     gl2ps->streamlength += tools_gl2psPrintf     3896     gl2ps->streamlength += tools_gl2psPrintf
3897       (gl2ps, "BT\n"                             3897       (gl2ps, "BT\n"
3898        "/F%d %d Tf\n"                            3898        "/F%d %d Tf\n"
3899        "%f %f %f %f %f %f Tm\n"                  3899        "%f %f %f %f %f %f Tm\n"
3900        "(%s) Tj\n"                               3900        "(%s) Tj\n"
3901        "ET\n",                                   3901        "ET\n",
3902        cnt, text->fontsize,                      3902        cnt, text->fontsize,
3903        ca, sa, -sa, ca,                          3903        ca, sa, -sa, ca,
3904        xbl + r * (cos(i) - cos(i + a)), ybl +    3904        xbl + r * (cos(i) - cos(i + a)), ybl + r * (sin(i) - sin(i+a)), text->str);
3905   }                                              3905   }
3906 }                                                3906 }
3907                                                  3907 
3908 inline void tools_gl2psPutPDFSpecial(tools_GL    3908 inline void tools_gl2psPutPDFSpecial(tools_GL2PScontext* gl2ps, int prim, int sec, tools_GL2PSstring *text)
3909 {                                                3909 {
3910   gl2ps->streamlength += tools_gl2psPrintf(gl    3910   gl2ps->streamlength += tools_gl2psPrintf(gl2ps,"/GS%d%d gs\n", prim, sec);
3911   gl2ps->streamlength += tools_gl2psPrintf(gl    3911   gl2ps->streamlength += tools_gl2psPrintf(gl2ps,"%s\n", text->str);
3912 }                                                3912 }
3913                                                  3913 
3914 inline void tools_gl2psPutPDFImage(tools_GL2P    3914 inline void tools_gl2psPutPDFImage(tools_GL2PScontext* gl2ps, tools_GL2PSimage *image, int cnt, tools_GLfloat x, tools_GLfloat y)
3915 {                                                3915 {
3916   gl2ps->streamlength += tools_gl2psPrintf       3916   gl2ps->streamlength += tools_gl2psPrintf
3917     (gl2ps, "q\n"                                3917     (gl2ps, "q\n"
3918      "%d 0 0 %d %f %f cm\n"                      3918      "%d 0 0 %d %f %f cm\n"
3919      "/Im%d Do\n"                                3919      "/Im%d Do\n"
3920      "Q\n",                                      3920      "Q\n",
3921      (int)(image->zoom_x * image->width), (in    3921      (int)(image->zoom_x * image->width), (int)(image->zoom_y * image->height),
3922      x, y, cnt);                                 3922      x, y, cnt);
3923 }                                                3923 }
3924                                                  3924 
3925 inline void tools_gl2psPDFstacksInit(tools_GL    3925 inline void tools_gl2psPDFstacksInit(tools_GL2PScontext* gl2ps)
3926 {                                                3926 {
3927   gl2ps->objects_stack = 7 /* FIXED_XREF_ENTR    3927   gl2ps->objects_stack = 7 /* FIXED_XREF_ENTRIES */ + 1;
3928   gl2ps->extgs_stack = 0;                        3928   gl2ps->extgs_stack = 0;
3929   gl2ps->font_stack = 0;                         3929   gl2ps->font_stack = 0;
3930   gl2ps->im_stack = 0;                           3930   gl2ps->im_stack = 0;
3931   gl2ps->trgroupobjects_stack = 0;               3931   gl2ps->trgroupobjects_stack = 0;
3932   gl2ps->shader_stack = 0;                       3932   gl2ps->shader_stack = 0;
3933   gl2ps->mshader_stack = 0;                      3933   gl2ps->mshader_stack = 0;
3934 }                                                3934 }
3935                                                  3935 
3936 inline void tools_gl2psPDFgroupObjectInit(too    3936 inline void tools_gl2psPDFgroupObjectInit(tools_GL2PSpdfgroup *gro)
3937 {                                                3937 {
3938   if(!gro)                                       3938   if(!gro)
3939     return;                                      3939     return;
3940                                                  3940 
3941   gro->ptrlist = NULL;                           3941   gro->ptrlist = NULL;
3942   gro->fontno = gro->gsno = gro->imno = gro->    3942   gro->fontno = gro->gsno = gro->imno = gro->maskshno = gro->shno
3943     = gro->trgroupno = gro->fontobjno = gro->    3943     = gro->trgroupno = gro->fontobjno = gro->imobjno = gro->shobjno
3944     = gro->maskshobjno = gro->gsobjno = gro->    3944     = gro->maskshobjno = gro->gsobjno = gro->trgroupobjno = -1;
3945 }                                                3945 }
3946                                                  3946 
3947 /* Build up group objects and assign name and    3947 /* Build up group objects and assign name and object numbers */
3948                                                  3948 
3949 inline void tools_gl2psPDFgroupListInit(tools    3949 inline void tools_gl2psPDFgroupListInit(tools_GL2PScontext* gl2ps)
3950 {                                                3950 {
3951   int i;                                         3951   int i;
3952   tools_GL2PSprimitive *p = NULL;                3952   tools_GL2PSprimitive *p = NULL;
3953   tools_GL2PSpdfgroup gro;                       3953   tools_GL2PSpdfgroup gro;
3954   int lasttype = TOOLS_GL2PS_NO_TYPE;            3954   int lasttype = TOOLS_GL2PS_NO_TYPE;
3955   tools_GL2PSrgba lastrgba = {-1.0F, -1.0F, -    3955   tools_GL2PSrgba lastrgba = {-1.0F, -1.0F, -1.0F, -1.0F};
3956   tools_GLushort lastpattern = 0;                3956   tools_GLushort lastpattern = 0;
3957   tools_GLint lastfactor = 0;                    3957   tools_GLint lastfactor = 0;
3958   tools_GLfloat lastwidth = 1;                   3958   tools_GLfloat lastwidth = 1;
3959   tools_GLint lastlinecap = 0;                   3959   tools_GLint lastlinecap = 0;
3960   tools_GLint lastlinejoin = 0;                  3960   tools_GLint lastlinejoin = 0;
3961   tools_GL2PStriangle lastt, tmpt;               3961   tools_GL2PStriangle lastt, tmpt;
3962   int lastTriangleWasNotSimpleWithSameColor =    3962   int lastTriangleWasNotSimpleWithSameColor = 0;
3963                                                  3963 
3964   if(!gl2ps->pdfprimlist)                        3964   if(!gl2ps->pdfprimlist)
3965     return;                                      3965     return;
3966                                                  3966 
3967   /*G.Barrand: add the below line to quiet Co    3967   /*G.Barrand: add the below line to quiet Coverity about gro.ptrlist not inited
3968                in the below TOOLS_GL2PS_LINE,    3968                in the below TOOLS_GL2PS_LINE, TOOLS_GL2PS_POINT cases.*/
3969   tools_gl2psPDFgroupObjectInit(&gro);           3969   tools_gl2psPDFgroupObjectInit(&gro);
3970                                                  3970   
3971   gl2ps->pdfgrouplist = tools_gl2psListCreate    3971   gl2ps->pdfgrouplist = tools_gl2psListCreate(500, 500, sizeof(tools_GL2PSpdfgroup));
3972   tools_gl2psInitTriangle(&lastt);               3972   tools_gl2psInitTriangle(&lastt);
3973                                                  3973 
3974   for(i = 0; i < tools_gl2psListNbr(gl2ps->pd    3974   for(i = 0; i < tools_gl2psListNbr(gl2ps->pdfprimlist); ++i){
3975     p = *(tools_GL2PSprimitive**)tools_gl2psL    3975     p = *(tools_GL2PSprimitive**)tools_gl2psListPointer(gl2ps->pdfprimlist, i);
3976     switch(p->type){                             3976     switch(p->type){
3977     case TOOLS_GL2PS_PIXMAP:                     3977     case TOOLS_GL2PS_PIXMAP:
3978       tools_gl2psPDFgroupObjectInit(&gro);       3978       tools_gl2psPDFgroupObjectInit(&gro);
3979       gro.ptrlist = tools_gl2psListCreate(1,     3979       gro.ptrlist = tools_gl2psListCreate(1, 2, sizeof(tools_GL2PSprimitive*));
3980       gro.imno = gl2ps->im_stack++;              3980       gro.imno = gl2ps->im_stack++;
3981       tools_gl2psListAdd(gro.ptrlist, &p);       3981       tools_gl2psListAdd(gro.ptrlist, &p);
3982       tools_gl2psListAdd(gl2ps->pdfgrouplist,    3982       tools_gl2psListAdd(gl2ps->pdfgrouplist, &gro);
3983       break;                                     3983       break;
3984     case TOOLS_GL2PS_TEXT:                       3984     case TOOLS_GL2PS_TEXT:
3985       tools_gl2psPDFgroupObjectInit(&gro);       3985       tools_gl2psPDFgroupObjectInit(&gro);
3986       gro.ptrlist = tools_gl2psListCreate(1,     3986       gro.ptrlist = tools_gl2psListCreate(1, 2, sizeof(tools_GL2PSprimitive*));
3987       gro.fontno = gl2ps->font_stack++;          3987       gro.fontno = gl2ps->font_stack++;
3988       tools_gl2psListAdd(gro.ptrlist, &p);       3988       tools_gl2psListAdd(gro.ptrlist, &p);
3989       tools_gl2psListAdd(gl2ps->pdfgrouplist,    3989       tools_gl2psListAdd(gl2ps->pdfgrouplist, &gro);
3990       break;                                     3990       break;
3991     case TOOLS_GL2PS_LINE:                       3991     case TOOLS_GL2PS_LINE:
3992       if(lasttype != p->type || lastwidth !=     3992       if(lasttype != p->type || lastwidth != p->width ||
3993          lastlinecap != p->linecap || lastlin    3993          lastlinecap != p->linecap || lastlinejoin != p->linejoin ||
3994          lastpattern != p->pattern || lastfac    3994          lastpattern != p->pattern || lastfactor != p->factor ||
3995          !tools_gl2psSameColor(p->verts[0].rg    3995          !tools_gl2psSameColor(p->verts[0].rgba, lastrgba)){
3996         tools_gl2psPDFgroupObjectInit(&gro);     3996         tools_gl2psPDFgroupObjectInit(&gro);
3997         gro.ptrlist = tools_gl2psListCreate(1    3997         gro.ptrlist = tools_gl2psListCreate(1, 2, sizeof(tools_GL2PSprimitive*));
3998         tools_gl2psListAdd(gro.ptrlist, &p);     3998         tools_gl2psListAdd(gro.ptrlist, &p);
3999         tools_gl2psListAdd(gl2ps->pdfgrouplis    3999         tools_gl2psListAdd(gl2ps->pdfgrouplist, &gro);
4000       }                                          4000       }
4001       else{                                      4001       else{
4002         tools_gl2psListAdd(gro.ptrlist, &p);     4002         tools_gl2psListAdd(gro.ptrlist, &p);
4003       }                                          4003       }
4004       lastpattern = p->pattern;                  4004       lastpattern = p->pattern;
4005       lastfactor = p->factor;                    4005       lastfactor = p->factor;
4006       lastwidth = p->width;                      4006       lastwidth = p->width;
4007       lastlinecap = p->linecap;                  4007       lastlinecap = p->linecap;
4008       lastlinejoin = p->linejoin;                4008       lastlinejoin = p->linejoin;
4009       lastrgba[0] = p->verts[0].rgba[0];         4009       lastrgba[0] = p->verts[0].rgba[0];
4010       lastrgba[1] = p->verts[0].rgba[1];         4010       lastrgba[1] = p->verts[0].rgba[1];
4011       lastrgba[2] = p->verts[0].rgba[2];         4011       lastrgba[2] = p->verts[0].rgba[2];
4012       break;                                     4012       break;
4013     case TOOLS_GL2PS_POINT:                      4013     case TOOLS_GL2PS_POINT:
4014       if(lasttype != p->type || lastwidth !=     4014       if(lasttype != p->type || lastwidth != p->width ||
4015          !tools_gl2psSameColor(p->verts[0].rg    4015          !tools_gl2psSameColor(p->verts[0].rgba, lastrgba)){
4016         tools_gl2psPDFgroupObjectInit(&gro);     4016         tools_gl2psPDFgroupObjectInit(&gro);
4017         gro.ptrlist = tools_gl2psListCreate(1    4017         gro.ptrlist = tools_gl2psListCreate(1,2,sizeof(tools_GL2PSprimitive*));
4018         tools_gl2psListAdd(gro.ptrlist, &p);     4018         tools_gl2psListAdd(gro.ptrlist, &p);
4019         tools_gl2psListAdd(gl2ps->pdfgrouplis    4019         tools_gl2psListAdd(gl2ps->pdfgrouplist, &gro);
4020       }                                          4020       }
4021       else{                                      4021       else{
4022         tools_gl2psListAdd(gro.ptrlist, &p);     4022         tools_gl2psListAdd(gro.ptrlist, &p);
4023       }                                          4023       }
4024       lastwidth = p->width;                      4024       lastwidth = p->width;
4025       lastrgba[0] = p->verts[0].rgba[0];         4025       lastrgba[0] = p->verts[0].rgba[0];
4026       lastrgba[1] = p->verts[0].rgba[1];         4026       lastrgba[1] = p->verts[0].rgba[1];
4027       lastrgba[2] = p->verts[0].rgba[2];         4027       lastrgba[2] = p->verts[0].rgba[2];
4028       break;                                     4028       break;
4029     case TOOLS_GL2PS_TRIANGLE:                   4029     case TOOLS_GL2PS_TRIANGLE:
4030       tools_gl2psFillTriangleFromPrimitive(&t    4030       tools_gl2psFillTriangleFromPrimitive(&tmpt, p, TOOLS_GL_TRUE);
4031       lastTriangleWasNotSimpleWithSameColor =    4031       lastTriangleWasNotSimpleWithSameColor =
4032         !(tmpt.prop & T_CONST_COLOR && tmpt.p    4032         !(tmpt.prop & T_CONST_COLOR && tmpt.prop & T_ALPHA_1) ||
4033         !tools_gl2psSameColor(tmpt.vertex[0].    4033         !tools_gl2psSameColor(tmpt.vertex[0].rgba, lastt.vertex[0].rgba);
4034       if(lasttype == p->type && tmpt.prop ==     4034       if(lasttype == p->type && tmpt.prop == lastt.prop &&
4035          lastTriangleWasNotSimpleWithSameColo    4035          lastTriangleWasNotSimpleWithSameColor){
4036         /* TODO Check here for last alpha */     4036         /* TODO Check here for last alpha */
4037         tools_gl2psListAdd(gro.ptrlist, &p);     4037         tools_gl2psListAdd(gro.ptrlist, &p);
4038       }                                          4038       }
4039       else{                                      4039       else{
4040         tools_gl2psPDFgroupObjectInit(&gro);     4040         tools_gl2psPDFgroupObjectInit(&gro);
4041         gro.ptrlist = tools_gl2psListCreate(1    4041         gro.ptrlist = tools_gl2psListCreate(1, 2, sizeof(tools_GL2PSprimitive*));
4042         tools_gl2psListAdd(gro.ptrlist, &p);     4042         tools_gl2psListAdd(gro.ptrlist, &p);
4043         tools_gl2psListAdd(gl2ps->pdfgrouplis    4043         tools_gl2psListAdd(gl2ps->pdfgrouplist, &gro);
4044       }                                          4044       }
4045       lastt = tmpt;                              4045       lastt = tmpt;
4046       break;                                     4046       break;
4047     case TOOLS_GL2PS_SPECIAL:                    4047     case TOOLS_GL2PS_SPECIAL:
4048       tools_gl2psPDFgroupObjectInit(&gro);       4048       tools_gl2psPDFgroupObjectInit(&gro);
4049       gro.ptrlist = tools_gl2psListCreate(1,     4049       gro.ptrlist = tools_gl2psListCreate(1, 2, sizeof(tools_GL2PSprimitive*));
4050       tools_gl2psListAdd(gro.ptrlist, &p);       4050       tools_gl2psListAdd(gro.ptrlist, &p);
4051       tools_gl2psListAdd(gl2ps->pdfgrouplist,    4051       tools_gl2psListAdd(gl2ps->pdfgrouplist, &gro);
4052       break;                                     4052       break;
4053     default:                                     4053     default:
4054       break;                                     4054       break;
4055     }                                            4055     }
4056     lasttype = p->type;                          4056     lasttype = p->type;
4057   }                                              4057   }
4058 }                                                4058 }
4059                                                  4059 
4060 inline void tools_gl2psSortOutTrianglePDFgrou    4060 inline void tools_gl2psSortOutTrianglePDFgroup(tools_GL2PScontext* gl2ps, tools_GL2PSpdfgroup *gro)
4061 {                                                4061 {
4062   tools_GL2PStriangle t;                         4062   tools_GL2PStriangle t;
4063   tools_GL2PSprimitive *prim = NULL;             4063   tools_GL2PSprimitive *prim = NULL;
4064                                                  4064 
4065   if(!gro)                                       4065   if(!gro)
4066     return;                                      4066     return;
4067                                                  4067 
4068   if(!tools_gl2psListNbr(gro->ptrlist))          4068   if(!tools_gl2psListNbr(gro->ptrlist))
4069     return;                                      4069     return;
4070                                                  4070 
4071   prim = *(tools_GL2PSprimitive**)tools_gl2ps    4071   prim = *(tools_GL2PSprimitive**)tools_gl2psListPointer(gro->ptrlist, 0);
4072                                                  4072 
4073   if(prim->type != TOOLS_GL2PS_TRIANGLE)         4073   if(prim->type != TOOLS_GL2PS_TRIANGLE)
4074     return;                                      4074     return;
4075                                                  4075 
4076   tools_gl2psFillTriangleFromPrimitive(&t, pr    4076   tools_gl2psFillTriangleFromPrimitive(&t, prim, TOOLS_GL_TRUE);
4077                                                  4077 
4078   if(t.prop & T_CONST_COLOR && t.prop & T_ALP    4078   if(t.prop & T_CONST_COLOR && t.prop & T_ALPHA_LESS_1){
4079     gro->gsno = gl2ps->extgs_stack++;            4079     gro->gsno = gl2ps->extgs_stack++;
4080     gro->gsobjno = gl2ps->objects_stack ++;      4080     gro->gsobjno = gl2ps->objects_stack ++;
4081   }                                              4081   }
4082   else if(t.prop & T_CONST_COLOR && t.prop &     4082   else if(t.prop & T_CONST_COLOR && t.prop & T_VAR_ALPHA){
4083     gro->gsno = gl2ps->extgs_stack++;            4083     gro->gsno = gl2ps->extgs_stack++;
4084     gro->gsobjno = gl2ps->objects_stack++;       4084     gro->gsobjno = gl2ps->objects_stack++;
4085     gro->trgroupno = gl2ps->trgroupobjects_st    4085     gro->trgroupno = gl2ps->trgroupobjects_stack++;
4086     gro->trgroupobjno = gl2ps->objects_stack+    4086     gro->trgroupobjno = gl2ps->objects_stack++;
4087     gro->maskshno = gl2ps->mshader_stack++;      4087     gro->maskshno = gl2ps->mshader_stack++;
4088     gro->maskshobjno = gl2ps->objects_stack++    4088     gro->maskshobjno = gl2ps->objects_stack++;
4089   }                                              4089   }
4090   else if(t.prop & T_VAR_COLOR && t.prop & T_    4090   else if(t.prop & T_VAR_COLOR && t.prop & T_ALPHA_1){
4091     gro->shno = gl2ps->shader_stack++;           4091     gro->shno = gl2ps->shader_stack++;
4092     gro->shobjno = gl2ps->objects_stack++;       4092     gro->shobjno = gl2ps->objects_stack++;
4093   }                                              4093   }
4094   else if(t.prop & T_VAR_COLOR && t.prop & T_    4094   else if(t.prop & T_VAR_COLOR && t.prop & T_ALPHA_LESS_1){
4095     gro->gsno = gl2ps->extgs_stack++;            4095     gro->gsno = gl2ps->extgs_stack++;
4096     gro->gsobjno = gl2ps->objects_stack++;       4096     gro->gsobjno = gl2ps->objects_stack++;
4097     gro->shno = gl2ps->shader_stack++;           4097     gro->shno = gl2ps->shader_stack++;
4098     gro->shobjno = gl2ps->objects_stack++;       4098     gro->shobjno = gl2ps->objects_stack++;
4099   }                                              4099   }
4100   else if(t.prop & T_VAR_COLOR && t.prop & T_    4100   else if(t.prop & T_VAR_COLOR && t.prop & T_VAR_ALPHA){
4101     gro->gsno = gl2ps->extgs_stack++;            4101     gro->gsno = gl2ps->extgs_stack++;
4102     gro->gsobjno = gl2ps->objects_stack++;       4102     gro->gsobjno = gl2ps->objects_stack++;
4103     gro->shno = gl2ps->shader_stack++;           4103     gro->shno = gl2ps->shader_stack++;
4104     gro->shobjno = gl2ps->objects_stack++;       4104     gro->shobjno = gl2ps->objects_stack++;
4105     gro->trgroupno = gl2ps->trgroupobjects_st    4105     gro->trgroupno = gl2ps->trgroupobjects_stack++;
4106     gro->trgroupobjno = gl2ps->objects_stack+    4106     gro->trgroupobjno = gl2ps->objects_stack++;
4107     gro->maskshno = gl2ps->mshader_stack++;      4107     gro->maskshno = gl2ps->mshader_stack++;
4108     gro->maskshobjno = gl2ps->objects_stack++    4108     gro->maskshobjno = gl2ps->objects_stack++;
4109   }                                              4109   }
4110 }                                                4110 }
4111                                                  4111 
4112 /* Main stream data */                           4112 /* Main stream data */
4113                                                  4113 
4114 inline void tools_gl2psPDFgroupListWriteMainS    4114 inline void tools_gl2psPDFgroupListWriteMainStream(tools_GL2PScontext* gl2ps)
4115 {                                                4115 {
4116   int i, j, lastel, count;                       4116   int i, j, lastel, count;
4117   tools_GL2PSprimitive *prim = NULL, *prev =     4117   tools_GL2PSprimitive *prim = NULL, *prev = NULL;
4118   tools_GL2PSpdfgroup *gro;                      4118   tools_GL2PSpdfgroup *gro;
4119   tools_GL2PStriangle t;                         4119   tools_GL2PStriangle t;
4120                                                  4120 
4121   if(!gl2ps->pdfgrouplist)                       4121   if(!gl2ps->pdfgrouplist)
4122     return;                                      4122     return;
4123                                                  4123 
4124   count = tools_gl2psListNbr(gl2ps->pdfgroupl    4124   count = tools_gl2psListNbr(gl2ps->pdfgrouplist);
4125                                                  4125 
4126   for(i = 0; i < count; ++i){                    4126   for(i = 0; i < count; ++i){
4127     gro = (tools_GL2PSpdfgroup*)tools_gl2psLi    4127     gro = (tools_GL2PSpdfgroup*)tools_gl2psListPointer(gl2ps->pdfgrouplist, i);
4128                                                  4128 
4129     lastel = tools_gl2psListNbr(gro->ptrlist)    4129     lastel = tools_gl2psListNbr(gro->ptrlist) - 1;
4130     if(lastel < 0)                               4130     if(lastel < 0)
4131       continue;                                  4131       continue;
4132                                                  4132 
4133     prim = *(tools_GL2PSprimitive**)tools_gl2    4133     prim = *(tools_GL2PSprimitive**)tools_gl2psListPointer(gro->ptrlist, 0);
4134                                                  4134 
4135     switch(prim->type){                          4135     switch(prim->type){
4136     case TOOLS_GL2PS_POINT:                      4136     case TOOLS_GL2PS_POINT:
4137       gl2ps->streamlength += tools_gl2psPrint    4137       gl2ps->streamlength += tools_gl2psPrintf(gl2ps,"1 J\n");
4138       gl2ps->streamlength += tools_gl2psPrint    4138       gl2ps->streamlength += tools_gl2psPrintPDFLineWidth(gl2ps, prim->width);
4139       gl2ps->streamlength += tools_gl2psPrint    4139       gl2ps->streamlength += tools_gl2psPrintPDFStrokeColor(gl2ps, prim->verts[0].rgba);
4140       for(j = 0; j <= lastel; ++j){              4140       for(j = 0; j <= lastel; ++j){
4141         prim = *(tools_GL2PSprimitive**)tools    4141         prim = *(tools_GL2PSprimitive**)tools_gl2psListPointer(gro->ptrlist, j);
4142         gl2ps->streamlength +=                   4142         gl2ps->streamlength +=
4143           tools_gl2psPrintf(gl2ps,"%f %f m %f    4143           tools_gl2psPrintf(gl2ps,"%f %f m %f %f l\n",
4144                       prim->verts[0].xyz[0],     4144                       prim->verts[0].xyz[0], prim->verts[0].xyz[1],
4145                       prim->verts[0].xyz[0],     4145                       prim->verts[0].xyz[0], prim->verts[0].xyz[1]);
4146       }                                          4146       }
4147       gl2ps->streamlength += tools_gl2psPrint    4147       gl2ps->streamlength += tools_gl2psPrintf(gl2ps,"S\n");
4148       gl2ps->streamlength += tools_gl2psPrint    4148       gl2ps->streamlength += tools_gl2psPrintf(gl2ps,"0 J\n");
4149       break;                                     4149       break;
4150     case TOOLS_GL2PS_LINE:                       4150     case TOOLS_GL2PS_LINE:
4151       /* We try to use as few paths as possib    4151       /* We try to use as few paths as possible to draw lines, in
4152          order to get nice stippling even whe    4152          order to get nice stippling even when the individual segments
4153          are smaller than the stipple */         4153          are smaller than the stipple */
4154       gl2ps->streamlength += tools_gl2psPrint    4154       gl2ps->streamlength += tools_gl2psPrintPDFLineWidth(gl2ps, prim->width);
4155       gl2ps->streamlength += tools_gl2psPrint    4155       gl2ps->streamlength += tools_gl2psPrintPDFLineCap(gl2ps, prim->linecap);
4156       gl2ps->streamlength += tools_gl2psPrint    4156       gl2ps->streamlength += tools_gl2psPrintPDFLineJoin(gl2ps, prim->linejoin);
4157       gl2ps->streamlength += tools_gl2psPrint    4157       gl2ps->streamlength += tools_gl2psPrintPDFStrokeColor(gl2ps, prim->verts[0].rgba);
4158       gl2ps->streamlength += tools_gl2psPrint    4158       gl2ps->streamlength += tools_gl2psPrintPostScriptDash(gl2ps, prim->pattern, prim->factor, "d");
4159       /* start new path */                       4159       /* start new path */
4160       gl2ps->streamlength +=                     4160       gl2ps->streamlength +=
4161         tools_gl2psPrintf(gl2ps,"%f %f m\n",     4161         tools_gl2psPrintf(gl2ps,"%f %f m\n",
4162                     prim->verts[0].xyz[0], pr    4162                     prim->verts[0].xyz[0], prim->verts[0].xyz[1]);
4163                                                  4163 
4164       for(j = 1; j <= lastel; ++j){              4164       for(j = 1; j <= lastel; ++j){
4165         prev = prim;                             4165         prev = prim;
4166         prim = *(tools_GL2PSprimitive**)tools    4166         prim = *(tools_GL2PSprimitive**)tools_gl2psListPointer(gro->ptrlist, j);
4167         if(!tools_gl2psSamePosition(prim->ver    4167         if(!tools_gl2psSamePosition(prim->verts[0].xyz, prev->verts[1].xyz)){
4168           /* the starting point of the new se    4168           /* the starting point of the new segment does not match the
4169              end point of the previous line,     4169              end point of the previous line, so we end the current
4170              path and start a new one */         4170              path and start a new one */
4171           gl2ps->streamlength +=                 4171           gl2ps->streamlength +=
4172             tools_gl2psPrintf(gl2ps,"%f %f l\    4172             tools_gl2psPrintf(gl2ps,"%f %f l\n",
4173                         prev->verts[1].xyz[0]    4173                         prev->verts[1].xyz[0], prev->verts[1].xyz[1]);
4174           gl2ps->streamlength +=                 4174           gl2ps->streamlength +=
4175             tools_gl2psPrintf(gl2ps,"%f %f m\    4175             tools_gl2psPrintf(gl2ps,"%f %f m\n",
4176                         prim->verts[0].xyz[0]    4176                         prim->verts[0].xyz[0], prim->verts[0].xyz[1]);
4177         }                                        4177         }
4178         else{                                    4178         else{
4179           /* the two segements are connected,    4179           /* the two segements are connected, so we just append to the
4180              current path */                     4180              current path */
4181           gl2ps->streamlength +=                 4181           gl2ps->streamlength +=
4182             tools_gl2psPrintf(gl2ps,"%f %f l\    4182             tools_gl2psPrintf(gl2ps,"%f %f l\n",
4183                         prim->verts[0].xyz[0]    4183                         prim->verts[0].xyz[0], prim->verts[0].xyz[1]);
4184         }                                        4184         }
4185       }                                          4185       }
4186       /* end last path */                        4186       /* end last path */
4187       gl2ps->streamlength +=                     4187       gl2ps->streamlength +=
4188         tools_gl2psPrintf(gl2ps,"%f %f l\n",     4188         tools_gl2psPrintf(gl2ps,"%f %f l\n",
4189                     prim->verts[1].xyz[0], pr    4189                     prim->verts[1].xyz[0], prim->verts[1].xyz[1]);
4190       gl2ps->streamlength += tools_gl2psPrint    4190       gl2ps->streamlength += tools_gl2psPrintf(gl2ps,"S\n");
4191       break;                                     4191       break;
4192     case TOOLS_GL2PS_TRIANGLE:                   4192     case TOOLS_GL2PS_TRIANGLE:
4193       tools_gl2psFillTriangleFromPrimitive(&t    4193       tools_gl2psFillTriangleFromPrimitive(&t, prim, TOOLS_GL_TRUE);
4194       tools_gl2psSortOutTrianglePDFgroup(gl2p    4194       tools_gl2psSortOutTrianglePDFgroup(gl2ps, gro);
4195                                                  4195 
4196       /* No alpha and const color: Simple PDF    4196       /* No alpha and const color: Simple PDF draw orders  */
4197       if(t.prop & T_CONST_COLOR && t.prop & T    4197       if(t.prop & T_CONST_COLOR && t.prop & T_ALPHA_1){
4198         gl2ps->streamlength += tools_gl2psPri    4198         gl2ps->streamlength += tools_gl2psPrintPDFFillColor(gl2ps, t.vertex[0].rgba);
4199         for(j = 0; j <= lastel; ++j){            4199         for(j = 0; j <= lastel; ++j){
4200           prim = *(tools_GL2PSprimitive**)too    4200           prim = *(tools_GL2PSprimitive**)tools_gl2psListPointer(gro->ptrlist, j);
4201           tools_gl2psFillTriangleFromPrimitiv    4201           tools_gl2psFillTriangleFromPrimitive(&t, prim, TOOLS_GL_FALSE);
4202           gl2ps->streamlength                    4202           gl2ps->streamlength
4203             += tools_gl2psPrintf(gl2ps,"%f %f    4203             += tools_gl2psPrintf(gl2ps,"%f %f m\n"
4204                            "%f %f l\n"           4204                            "%f %f l\n"
4205                            "%f %f l\n"           4205                            "%f %f l\n"
4206                            "h f\n",              4206                            "h f\n",
4207                            t.vertex[0].xyz[0]    4207                            t.vertex[0].xyz[0], t.vertex[0].xyz[1],
4208                            t.vertex[1].xyz[0]    4208                            t.vertex[1].xyz[0], t.vertex[1].xyz[1],
4209                            t.vertex[2].xyz[0]    4209                            t.vertex[2].xyz[0], t.vertex[2].xyz[1]);
4210         }                                        4210         }
4211       }                                          4211       }
4212       /* Const alpha < 1 and const color: Sim    4212       /* Const alpha < 1 and const color: Simple PDF draw orders
4213          and an extra extended Graphics State    4213          and an extra extended Graphics State for the alpha const */
4214       else if(t.prop & T_CONST_COLOR && t.pro    4214       else if(t.prop & T_CONST_COLOR && t.prop & T_ALPHA_LESS_1){
4215         gl2ps->streamlength += tools_gl2psPri    4215         gl2ps->streamlength += tools_gl2psPrintf(gl2ps,"q\n"
4216                                            "/    4216                                            "/GS%d gs\n",
4217                                            gr    4217                                            gro->gsno);
4218         gl2ps->streamlength += tools_gl2psPri    4218         gl2ps->streamlength += tools_gl2psPrintPDFFillColor(gl2ps, prim->verts[0].rgba);
4219         for(j = 0; j <= lastel; ++j){            4219         for(j = 0; j <= lastel; ++j){
4220           prim = *(tools_GL2PSprimitive**)too    4220           prim = *(tools_GL2PSprimitive**)tools_gl2psListPointer(gro->ptrlist, j);
4221           tools_gl2psFillTriangleFromPrimitiv    4221           tools_gl2psFillTriangleFromPrimitive(&t, prim, TOOLS_GL_FALSE);
4222           gl2ps->streamlength                    4222           gl2ps->streamlength
4223             += tools_gl2psPrintf(gl2ps,"%f %f    4223             += tools_gl2psPrintf(gl2ps,"%f %f m\n"
4224                            "%f %f l\n"           4224                            "%f %f l\n"
4225                            "%f %f l\n"           4225                            "%f %f l\n"
4226                            "h f\n",              4226                            "h f\n",
4227                            t.vertex[0].xyz[0]    4227                            t.vertex[0].xyz[0], t.vertex[0].xyz[1],
4228                            t.vertex[1].xyz[0]    4228                            t.vertex[1].xyz[0], t.vertex[1].xyz[1],
4229                            t.vertex[2].xyz[0]    4229                            t.vertex[2].xyz[0], t.vertex[2].xyz[1]);
4230         }                                        4230         }
4231         gl2ps->streamlength += tools_gl2psPri    4231         gl2ps->streamlength += tools_gl2psPrintf(gl2ps,"Q\n");
4232       }                                          4232       }
4233       /* Variable alpha and const color: Simp    4233       /* Variable alpha and const color: Simple PDF draw orders
4234          and an extra extended Graphics State    4234          and an extra extended Graphics State + Xobject + Shader
4235          object for the alpha mask */            4235          object for the alpha mask */
4236       else if(t.prop & T_CONST_COLOR && t.pro    4236       else if(t.prop & T_CONST_COLOR && t.prop & T_VAR_ALPHA){
4237         gl2ps->streamlength += tools_gl2psPri    4237         gl2ps->streamlength += tools_gl2psPrintf(gl2ps,"q\n"
4238                                            "/    4238                                            "/GS%d gs\n"
4239                                            "/    4239                                            "/TrG%d Do\n",
4240                                            gr    4240                                            gro->gsno, gro->trgroupno);
4241         gl2ps->streamlength += tools_gl2psPri    4241         gl2ps->streamlength += tools_gl2psPrintPDFFillColor(gl2ps, prim->verts[0].rgba);
4242         for(j = 0; j <= lastel; ++j){            4242         for(j = 0; j <= lastel; ++j){
4243           prim = *(tools_GL2PSprimitive**)too    4243           prim = *(tools_GL2PSprimitive**)tools_gl2psListPointer(gro->ptrlist, j);
4244           tools_gl2psFillTriangleFromPrimitiv    4244           tools_gl2psFillTriangleFromPrimitive(&t, prim, TOOLS_GL_FALSE);
4245           gl2ps->streamlength                    4245           gl2ps->streamlength
4246             += tools_gl2psPrintf(gl2ps,"%f %f    4246             += tools_gl2psPrintf(gl2ps,"%f %f m\n"
4247                            "%f %f l\n"           4247                            "%f %f l\n"
4248                            "%f %f l\n"           4248                            "%f %f l\n"
4249                            "h f\n",              4249                            "h f\n",
4250                            t.vertex[0].xyz[0]    4250                            t.vertex[0].xyz[0], t.vertex[0].xyz[1],
4251                            t.vertex[1].xyz[0]    4251                            t.vertex[1].xyz[0], t.vertex[1].xyz[1],
4252                            t.vertex[2].xyz[0]    4252                            t.vertex[2].xyz[0], t.vertex[2].xyz[1]);
4253         }                                        4253         }
4254         gl2ps->streamlength += tools_gl2psPri    4254         gl2ps->streamlength += tools_gl2psPrintf(gl2ps,"Q\n");
4255       }                                          4255       }
4256       /* Variable color and no alpha: Shader     4256       /* Variable color and no alpha: Shader Object for the colored
4257          triangle(s) */                          4257          triangle(s) */
4258       else if(t.prop & T_VAR_COLOR && t.prop     4258       else if(t.prop & T_VAR_COLOR && t.prop & T_ALPHA_1){
4259         gl2ps->streamlength += tools_gl2psPri    4259         gl2ps->streamlength += tools_gl2psPrintf(gl2ps,"/Sh%d sh\n", gro->shno);
4260       }                                          4260       }
4261       /* Variable color and const alpha < 1:     4261       /* Variable color and const alpha < 1: Shader Object for the
4262          colored triangle(s) and an extra ext    4262          colored triangle(s) and an extra extended Graphics State
4263          for the alpha const */                  4263          for the alpha const */
4264       else if(t.prop & T_VAR_COLOR && t.prop     4264       else if(t.prop & T_VAR_COLOR && t.prop & T_ALPHA_LESS_1){
4265         gl2ps->streamlength += tools_gl2psPri    4265         gl2ps->streamlength += tools_gl2psPrintf(gl2ps,"q\n"
4266                                            "/    4266                                            "/GS%d gs\n"
4267                                            "/    4267                                            "/Sh%d sh\n"
4268                                            "Q    4268                                            "Q\n",
4269                                            gr    4269                                            gro->gsno, gro->shno);
4270       }                                          4270       }
4271       /* Variable alpha and color: Shader Obj    4271       /* Variable alpha and color: Shader Object for the colored
4272          triangle(s) and an extra extended Gr    4272          triangle(s) and an extra extended Graphics State
4273          + Xobject + Shader object for the al    4273          + Xobject + Shader object for the alpha mask */
4274       else if(t.prop & T_VAR_COLOR && t.prop     4274       else if(t.prop & T_VAR_COLOR && t.prop & T_VAR_ALPHA){
4275         gl2ps->streamlength += tools_gl2psPri    4275         gl2ps->streamlength += tools_gl2psPrintf(gl2ps,"q\n"
4276                                            "/    4276                                            "/GS%d gs\n"
4277                                            "/    4277                                            "/TrG%d Do\n"
4278                                            "/    4278                                            "/Sh%d sh\n"
4279                                            "Q    4279                                            "Q\n",
4280                                            gr    4280                                            gro->gsno, gro->trgroupno, gro->shno);
4281       }                                          4281       }
4282       break;                                     4282       break;
4283     case TOOLS_GL2PS_PIXMAP:                     4283     case TOOLS_GL2PS_PIXMAP:
4284       for(j = 0; j <= lastel; ++j){              4284       for(j = 0; j <= lastel; ++j){
4285         prim = *(tools_GL2PSprimitive**)tools    4285         prim = *(tools_GL2PSprimitive**)tools_gl2psListPointer(gro->ptrlist, j);
4286         tools_gl2psPutPDFImage(gl2ps, prim->d    4286         tools_gl2psPutPDFImage(gl2ps, prim->data.image, gro->imno, prim->verts[0].xyz[0],
4287                          prim->verts[0].xyz[1    4287                          prim->verts[0].xyz[1]);
4288       }                                          4288       }
4289       break;                                     4289       break;
4290     case TOOLS_GL2PS_TEXT:                       4290     case TOOLS_GL2PS_TEXT:
4291       for(j = 0; j <= lastel; ++j){              4291       for(j = 0; j <= lastel; ++j){
4292         prim = *(tools_GL2PSprimitive**)tools    4292         prim = *(tools_GL2PSprimitive**)tools_gl2psListPointer(gro->ptrlist, j);
4293         gl2ps->streamlength += tools_gl2psPri    4293         gl2ps->streamlength += tools_gl2psPrintPDFFillColor(gl2ps, prim->verts[0].rgba);
4294         if (prim->numverts == 2) {               4294         if (prim->numverts == 2) {
4295           tools_gl2psPutPDFTextBL(gl2ps, prim    4295           tools_gl2psPutPDFTextBL(gl2ps, prim->data.text, gro->fontno, prim->verts[0].xyz[0],
4296                             prim->verts[0].xy    4296                             prim->verts[0].xyz[1],
4297                             prim->verts[1].xy    4297                             prim->verts[1].xyz[0],
4298                             prim->verts[1].xy    4298                             prim->verts[1].xyz[1]);
4299         }                                        4299         }
4300         else {                                   4300         else {
4301           tools_gl2psPutPDFText(gl2ps, prim->    4301           tools_gl2psPutPDFText(gl2ps, prim->data.text, gro->fontno, prim->verts[0].xyz[0],
4302                           prim->verts[0].xyz[    4302                           prim->verts[0].xyz[1]);
4303         }                                        4303         }
4304       }                                          4304       }
4305       break;                                     4305       break;
4306     case TOOLS_GL2PS_SPECIAL:                    4306     case TOOLS_GL2PS_SPECIAL:
4307       lastel = tools_gl2psListNbr(gro->ptrlis    4307       lastel = tools_gl2psListNbr(gro->ptrlist) - 1;
4308       if(lastel < 0)                             4308       if(lastel < 0)
4309         continue;                                4309         continue;
4310                                                  4310 
4311       for(j = 0; j <= lastel; ++j){              4311       for(j = 0; j <= lastel; ++j){
4312         prim = *(tools_GL2PSprimitive**)tools    4312         prim = *(tools_GL2PSprimitive**)tools_gl2psListPointer(gro->ptrlist, j);
4313         tools_gl2psPutPDFSpecial(gl2ps, i, j,    4313         tools_gl2psPutPDFSpecial(gl2ps, i, j, prim->data.text);
4314       }                                          4314       }
4315     default:                                     4315     default:
4316       break;                                     4316       break;
4317     }                                            4317     }
4318   }                                              4318   }
4319 }                                                4319 }
4320                                                  4320 
4321 /* Graphics State names */                       4321 /* Graphics State names */
4322                                                  4322 
4323 inline int tools_gl2psPDFgroupListWriteGState    4323 inline int tools_gl2psPDFgroupListWriteGStateResources(tools_GL2PScontext* gl2ps)
4324 {                                                4324 {
4325   tools_GL2PSpdfgroup *gro;                      4325   tools_GL2PSpdfgroup *gro;
4326   int offs = 0;                                  4326   int offs = 0;
4327   int i;                                         4327   int i;
4328                                                  4328 
4329   offs += fprintf(gl2ps->stream,                 4329   offs += fprintf(gl2ps->stream,
4330                   "/ExtGState\n"                 4330                   "/ExtGState\n"
4331                   "<<\n"                         4331                   "<<\n"
4332                   "/GSa 7 0 R\n");               4332                   "/GSa 7 0 R\n");
4333   for(i = 0; i < tools_gl2psListNbr(gl2ps->pd    4333   for(i = 0; i < tools_gl2psListNbr(gl2ps->pdfgrouplist); ++i){
4334     gro = (tools_GL2PSpdfgroup*)tools_gl2psLi    4334     gro = (tools_GL2PSpdfgroup*)tools_gl2psListPointer(gl2ps->pdfgrouplist, i);
4335     if(gro->gsno >= 0)                           4335     if(gro->gsno >= 0)
4336       offs += fprintf(gl2ps->stream, "/GS%d %    4336       offs += fprintf(gl2ps->stream, "/GS%d %d 0 R\n", gro->gsno, gro->gsobjno);
4337   }                                              4337   }
4338   offs += fprintf(gl2ps->stream, ">>\n");        4338   offs += fprintf(gl2ps->stream, ">>\n");
4339   return offs;                                   4339   return offs;
4340 }                                                4340 }
4341                                                  4341 
4342 /* Main Shader names */                          4342 /* Main Shader names */
4343                                                  4343 
4344 inline int tools_gl2psPDFgroupListWriteShader    4344 inline int tools_gl2psPDFgroupListWriteShaderResources(tools_GL2PScontext* gl2ps)
4345 {                                                4345 {
4346   tools_GL2PSpdfgroup *gro;                      4346   tools_GL2PSpdfgroup *gro;
4347   int offs = 0;                                  4347   int offs = 0;
4348   int i;                                         4348   int i;
4349                                                  4349 
4350   offs += fprintf(gl2ps->stream,                 4350   offs += fprintf(gl2ps->stream,
4351                   "/Shading\n"                   4351                   "/Shading\n"
4352                   "<<\n");                       4352                   "<<\n");
4353   for(i = 0; i < tools_gl2psListNbr(gl2ps->pd    4353   for(i = 0; i < tools_gl2psListNbr(gl2ps->pdfgrouplist); ++i){
4354     gro = (tools_GL2PSpdfgroup*)tools_gl2psLi    4354     gro = (tools_GL2PSpdfgroup*)tools_gl2psListPointer(gl2ps->pdfgrouplist, i);
4355     if(gro->shno >= 0)                           4355     if(gro->shno >= 0)
4356       offs += fprintf(gl2ps->stream, "/Sh%d %    4356       offs += fprintf(gl2ps->stream, "/Sh%d %d 0 R\n", gro->shno, gro->shobjno);
4357     if(gro->maskshno >= 0)                       4357     if(gro->maskshno >= 0)
4358       offs += fprintf(gl2ps->stream, "/TrSh%d    4358       offs += fprintf(gl2ps->stream, "/TrSh%d %d 0 R\n", gro->maskshno, gro->maskshobjno);
4359   }                                              4359   }
4360   offs += fprintf(gl2ps->stream,">>\n");         4360   offs += fprintf(gl2ps->stream,">>\n");
4361   return offs;                                   4361   return offs;
4362 }                                                4362 }
4363                                                  4363 
4364 /* Images & Mask Shader XObject names */         4364 /* Images & Mask Shader XObject names */
4365 inline int tools_gl2psPDFgroupListWriteXObjec    4365 inline int tools_gl2psPDFgroupListWriteXObjectResources(tools_GL2PScontext* gl2ps)
4366 {                                                4366 {
4367   int i;                                         4367   int i;
4368   tools_GL2PSprimitive *p = NULL;                4368   tools_GL2PSprimitive *p = NULL;
4369   tools_GL2PSpdfgroup *gro;                      4369   tools_GL2PSpdfgroup *gro;
4370   int offs = 0;                                  4370   int offs = 0;
4371                                                  4371 
4372   offs += fprintf(gl2ps->stream,                 4372   offs += fprintf(gl2ps->stream,
4373                   "/XObject\n"                   4373                   "/XObject\n"
4374                   "<<\n");                       4374                   "<<\n");
4375                                                  4375 
4376   for(i = 0; i < tools_gl2psListNbr(gl2ps->pd    4376   for(i = 0; i < tools_gl2psListNbr(gl2ps->pdfgrouplist); ++i){
4377     gro = (tools_GL2PSpdfgroup*)tools_gl2psLi    4377     gro = (tools_GL2PSpdfgroup*)tools_gl2psListPointer(gl2ps->pdfgrouplist, i);
4378     if(!tools_gl2psListNbr(gro->ptrlist))        4378     if(!tools_gl2psListNbr(gro->ptrlist))
4379       continue;                                  4379       continue;
4380     p = *(tools_GL2PSprimitive**)tools_gl2psL    4380     p = *(tools_GL2PSprimitive**)tools_gl2psListPointer(gro->ptrlist, 0);
4381     switch(p->type){                             4381     switch(p->type){
4382     case TOOLS_GL2PS_PIXMAP:                     4382     case TOOLS_GL2PS_PIXMAP:
4383       gro->imobjno = gl2ps->objects_stack++;     4383       gro->imobjno = gl2ps->objects_stack++;
4384       if(TOOLS_GL_RGBA == p->data.image->form    4384       if(TOOLS_GL_RGBA == p->data.image->format)  /* reserve one object for image mask */
4385         gl2ps->objects_stack++;                  4385         gl2ps->objects_stack++;
4386       offs += fprintf(gl2ps->stream, "/Im%d %    4386       offs += fprintf(gl2ps->stream, "/Im%d %d 0 R\n", gro->imno, gro->imobjno);
4387       break; /*G.Barrand : add this break.*/     4387       break; /*G.Barrand : add this break.*/
4388     case TOOLS_GL2PS_TRIANGLE:                   4388     case TOOLS_GL2PS_TRIANGLE:
4389       if(gro->trgroupno >=0)                     4389       if(gro->trgroupno >=0)
4390         offs += fprintf(gl2ps->stream, "/TrG%    4390         offs += fprintf(gl2ps->stream, "/TrG%d %d 0 R\n", gro->trgroupno, gro->trgroupobjno);
4391       break;                                     4391       break;
4392     default:                                     4392     default:
4393       break;                                     4393       break;
4394     }                                            4394     }
4395   }                                              4395   }
4396   offs += fprintf(gl2ps->stream,">>\n");         4396   offs += fprintf(gl2ps->stream,">>\n");
4397   return offs;                                   4397   return offs;
4398 }                                                4398 }
4399                                                  4399 
4400 /* Font names */                                 4400 /* Font names */
4401                                                  4401 
4402 inline int tools_gl2psPDFgroupListWriteFontRe    4402 inline int tools_gl2psPDFgroupListWriteFontResources(tools_GL2PScontext* gl2ps)
4403 {                                                4403 {
4404   int i;                                         4404   int i;
4405   tools_GL2PSpdfgroup *gro;                      4405   tools_GL2PSpdfgroup *gro;
4406   int offs = 0;                                  4406   int offs = 0;
4407                                                  4407 
4408   offs += fprintf(gl2ps->stream, "/Font\n<<\n    4408   offs += fprintf(gl2ps->stream, "/Font\n<<\n");
4409                                                  4409 
4410   for(i = 0; i < tools_gl2psListNbr(gl2ps->pd    4410   for(i = 0; i < tools_gl2psListNbr(gl2ps->pdfgrouplist); ++i){
4411     gro = (tools_GL2PSpdfgroup*)tools_gl2psLi    4411     gro = (tools_GL2PSpdfgroup*)tools_gl2psListPointer(gl2ps->pdfgrouplist, i);
4412     if(gro->fontno < 0)                          4412     if(gro->fontno < 0)
4413       continue;                                  4413       continue;
4414     gro->fontobjno = gl2ps->objects_stack++;     4414     gro->fontobjno = gl2ps->objects_stack++;
4415     offs += fprintf(gl2ps->stream, "/F%d %d 0    4415     offs += fprintf(gl2ps->stream, "/F%d %d 0 R\n", gro->fontno, gro->fontobjno);
4416   }                                              4416   }
4417   offs += fprintf(gl2ps->stream, ">>\n");        4417   offs += fprintf(gl2ps->stream, ">>\n");
4418                                                  4418 
4419   return offs;                                   4419   return offs;
4420 }                                                4420 }
4421                                                  4421 
4422 inline void tools_gl2psPDFgroupListDelete(too    4422 inline void tools_gl2psPDFgroupListDelete(tools_GL2PScontext* gl2ps)
4423 {                                                4423 {
4424   int i;                                         4424   int i;
4425   tools_GL2PSpdfgroup *gro = NULL;               4425   tools_GL2PSpdfgroup *gro = NULL;
4426                                                  4426 
4427   if(!gl2ps->pdfgrouplist)                       4427   if(!gl2ps->pdfgrouplist)
4428     return;                                      4428     return;
4429                                                  4429 
4430   for(i = 0; i < tools_gl2psListNbr(gl2ps->pd    4430   for(i = 0; i < tools_gl2psListNbr(gl2ps->pdfgrouplist); ++i){
4431     gro = (tools_GL2PSpdfgroup*)tools_gl2psLi    4431     gro = (tools_GL2PSpdfgroup*)tools_gl2psListPointer(gl2ps->pdfgrouplist,i);
4432     tools_gl2psListDelete(gro->ptrlist);         4432     tools_gl2psListDelete(gro->ptrlist);
4433   }                                              4433   }
4434                                                  4434 
4435   tools_gl2psListDelete(gl2ps->pdfgrouplist);    4435   tools_gl2psListDelete(gl2ps->pdfgrouplist);
4436   gl2ps->pdfgrouplist = NULL;                    4436   gl2ps->pdfgrouplist = NULL;
4437 }                                                4437 }
4438                                                  4438 
4439 /* Print 1st PDF object - file info */           4439 /* Print 1st PDF object - file info */
4440                                                  4440 
4441 inline int tools_gl2psPrintPDFInfo(tools_GL2P    4441 inline int tools_gl2psPrintPDFInfo(tools_GL2PScontext* gl2ps)
4442 {                                                4442 {
4443   int offs;                                      4443   int offs;
4444   time_t now;                                    4444   time_t now;
4445   struct tm *newtime;                            4445   struct tm *newtime;
4446                                                  4446 
4447   time(&now);                                    4447   time(&now);
4448   newtime = gmtime(&now);                        4448   newtime = gmtime(&now);
4449                                                  4449 
4450   offs = fprintf(gl2ps->stream,                  4450   offs = fprintf(gl2ps->stream,
4451                  "1 0 obj\n"                     4451                  "1 0 obj\n"
4452                  "<<\n"                          4452                  "<<\n"
4453                  "/Title (%s)\n"                 4453                  "/Title (%s)\n"
4454                  "/Creator (GL2PS %d.%d.%d%s,    4454                  "/Creator (GL2PS %d.%d.%d%s, %s)\n"
4455                  "/Producer (%s)\n",             4455                  "/Producer (%s)\n",
4456                  gl2ps->title, TOOLS_GL2PS_MA    4456                  gl2ps->title, TOOLS_GL2PS_MAJOR_VERSION, TOOLS_GL2PS_MINOR_VERSION,
4457                  TOOLS_GL2PS_PATCH_VERSION, T    4457                  TOOLS_GL2PS_PATCH_VERSION, TOOLS_GL2PS_EXTRA_VERSION, TOOLS_GL2PS_COPYRIGHT,
4458                  gl2ps->producer);               4458                  gl2ps->producer);
4459                                                  4459 
4460   if(!newtime){                                  4460   if(!newtime){
4461     offs += fprintf(gl2ps->stream,               4461     offs += fprintf(gl2ps->stream,
4462                     ">>\n"                       4462                     ">>\n"
4463                     "endobj\n");                 4463                     "endobj\n");
4464     return offs;                                 4464     return offs;
4465   }                                              4465   }
4466                                                  4466 
4467   offs += fprintf(gl2ps->stream,                 4467   offs += fprintf(gl2ps->stream,
4468                   "/CreationDate (D:%d%02d%02    4468                   "/CreationDate (D:%d%02d%02d%02d%02d%02d)\n"
4469                   ">>\n"                         4469                   ">>\n"
4470                   "endobj\n",                    4470                   "endobj\n",
4471                   newtime->tm_year+1900,         4471                   newtime->tm_year+1900,
4472                   newtime->tm_mon+1,             4472                   newtime->tm_mon+1,
4473                   newtime->tm_mday,              4473                   newtime->tm_mday,
4474                   newtime->tm_hour,              4474                   newtime->tm_hour,
4475                   newtime->tm_min,               4475                   newtime->tm_min,
4476                   newtime->tm_sec);              4476                   newtime->tm_sec);
4477   return offs;                                   4477   return offs;
4478 }                                                4478 }
4479                                                  4479 
4480 /* Create catalog and page structure - 2nd an    4480 /* Create catalog and page structure - 2nd and 3th PDF object */
4481                                                  4481 
4482 inline int tools_gl2psPrintPDFCatalog(tools_G    4482 inline int tools_gl2psPrintPDFCatalog(tools_GL2PScontext* gl2ps)
4483 {                                                4483 {
4484   return fprintf(gl2ps->stream,                  4484   return fprintf(gl2ps->stream,
4485                  "2 0 obj\n"                     4485                  "2 0 obj\n"
4486                  "<<\n"                          4486                  "<<\n"
4487                  "/Type /Catalog\n"              4487                  "/Type /Catalog\n"
4488                  "/Pages 3 0 R\n"                4488                  "/Pages 3 0 R\n"
4489                  ">>\n"                          4489                  ">>\n"
4490                  "endobj\n");                    4490                  "endobj\n");
4491 }                                                4491 }
4492                                                  4492 
4493 inline int tools_gl2psPrintPDFPages(tools_GL2    4493 inline int tools_gl2psPrintPDFPages(tools_GL2PScontext* gl2ps)
4494 {                                                4494 {
4495   return fprintf(gl2ps->stream,                  4495   return fprintf(gl2ps->stream,
4496                  "3 0 obj\n"                     4496                  "3 0 obj\n"
4497                  "<<\n"                          4497                  "<<\n"
4498                  "/Type /Pages\n"                4498                  "/Type /Pages\n"
4499                  "/Kids [6 0 R]\n"               4499                  "/Kids [6 0 R]\n"
4500                  "/Count 1\n"                    4500                  "/Count 1\n"
4501                  ">>\n"                          4501                  ">>\n"
4502                  "endobj\n");                    4502                  "endobj\n");
4503 }                                                4503 }
4504                                                  4504 
4505 /* Open stream for data - graphical objects,     4505 /* Open stream for data - graphical objects, fonts etc. PDF object 4 */
4506                                                  4506 
4507 inline int tools_gl2psOpenPDFDataStream(tools    4507 inline int tools_gl2psOpenPDFDataStream(tools_GL2PScontext* gl2ps)
4508 {                                                4508 {
4509   int offs = 0;                                  4509   int offs = 0;
4510                                                  4510 
4511   offs += fprintf(gl2ps->stream,                 4511   offs += fprintf(gl2ps->stream,
4512                   "4 0 obj\n"                    4512                   "4 0 obj\n"
4513                   "<<\n"                         4513                   "<<\n"
4514                   "/Length 5 0 R\n" );           4514                   "/Length 5 0 R\n" );
4515   offs += tools_gl2psPrintPDFCompressorType(g    4515   offs += tools_gl2psPrintPDFCompressorType(gl2ps);
4516   offs += fprintf(gl2ps->stream,                 4516   offs += fprintf(gl2ps->stream,
4517                   ">>\n"                         4517                   ">>\n"
4518                   "stream\n");                   4518                   "stream\n");
4519   return offs;                                   4519   return offs;
4520 }                                                4520 }
4521                                                  4521 
4522 /* Stream setup - Graphics state, fill backgr    4522 /* Stream setup - Graphics state, fill background if allowed */
4523                                                  4523 
4524 inline int tools_gl2psOpenPDFDataStreamWriteP    4524 inline int tools_gl2psOpenPDFDataStreamWritePreface(tools_GL2PScontext* gl2ps)
4525 {                                                4525 {
4526   int offs;                                      4526   int offs;
4527                                                  4527 
4528   offs = tools_gl2psPrintf(gl2ps,"/GSa gs\n")    4528   offs = tools_gl2psPrintf(gl2ps,"/GSa gs\n");
4529                                                  4529 
4530   if(gl2ps->options & TOOLS_GL2PS_DRAW_BACKGR    4530   if(gl2ps->options & TOOLS_GL2PS_DRAW_BACKGROUND){
4531     offs += tools_gl2psPrintPDFFillColor(gl2p    4531     offs += tools_gl2psPrintPDFFillColor(gl2ps, gl2ps->bgcolor);
4532     offs += tools_gl2psPrintf(gl2ps,"%d %d %d    4532     offs += tools_gl2psPrintf(gl2ps,"%d %d %d %d re\n",
4533                         (int)gl2ps->viewport[    4533                         (int)gl2ps->viewport[0], (int)gl2ps->viewport[1],
4534                         (int)gl2ps->viewport[    4534                         (int)gl2ps->viewport[2], (int)gl2ps->viewport[3]);
4535     offs += tools_gl2psPrintf(gl2ps,"f\n");      4535     offs += tools_gl2psPrintf(gl2ps,"f\n");
4536   }                                              4536   }
4537   return offs;                                   4537   return offs;
4538 }                                                4538 }
4539                                                  4539 
4540 /* Use the functions above to create the firs    4540 /* Use the functions above to create the first part of the PDF*/
4541                                                  4541 
4542 inline void tools_gl2psPrintPDFHeader(tools_G    4542 inline void tools_gl2psPrintPDFHeader(tools_GL2PScontext* gl2ps)
4543 {                                                4543 {
4544   int offs = 0;                                  4544   int offs = 0;
4545   gl2ps->pdfprimlist = tools_gl2psListCreate(    4545   gl2ps->pdfprimlist = tools_gl2psListCreate(500, 500, sizeof(tools_GL2PSprimitive*));
4546   tools_gl2psPDFstacksInit(gl2ps);               4546   tools_gl2psPDFstacksInit(gl2ps);
4547                                                  4547 
4548   gl2ps->xreflist = (int*)tools_gl2psMalloc(s    4548   gl2ps->xreflist = (int*)tools_gl2psMalloc(sizeof(int) * gl2ps->objects_stack);
4549                                                  4549 
4550 #if defined(TOOLS_GL2PS_HAVE_ZLIB)               4550 #if defined(TOOLS_GL2PS_HAVE_ZLIB)
4551   if(gl2ps->options & TOOLS_GL2PS_COMPRESS){     4551   if(gl2ps->options & TOOLS_GL2PS_COMPRESS){
4552     tools_gl2psSetupCompress(gl2ps);             4552     tools_gl2psSetupCompress(gl2ps);
4553   }                                              4553   }
4554 #endif                                           4554 #endif
4555   gl2ps->xreflist[0] = 0;                        4555   gl2ps->xreflist[0] = 0;
4556   offs += fprintf(gl2ps->stream, "%%PDF-1.4\n    4556   offs += fprintf(gl2ps->stream, "%%PDF-1.4\n");
4557   gl2ps->xreflist[1] = offs;                     4557   gl2ps->xreflist[1] = offs;
4558                                                  4558 
4559   offs += tools_gl2psPrintPDFInfo(gl2ps);        4559   offs += tools_gl2psPrintPDFInfo(gl2ps);
4560   gl2ps->xreflist[2] = offs;                     4560   gl2ps->xreflist[2] = offs;
4561                                                  4561 
4562   offs += tools_gl2psPrintPDFCatalog(gl2ps);     4562   offs += tools_gl2psPrintPDFCatalog(gl2ps);
4563   gl2ps->xreflist[3] = offs;                     4563   gl2ps->xreflist[3] = offs;
4564                                                  4564 
4565   offs += tools_gl2psPrintPDFPages(gl2ps);       4565   offs += tools_gl2psPrintPDFPages(gl2ps);
4566   gl2ps->xreflist[4] = offs;                     4566   gl2ps->xreflist[4] = offs;
4567                                                  4567 
4568   offs += tools_gl2psOpenPDFDataStream(gl2ps)    4568   offs += tools_gl2psOpenPDFDataStream(gl2ps);
4569   gl2ps->xreflist[5] = offs; /* finished in t    4569   gl2ps->xreflist[5] = offs; /* finished in tools_gl2psPrintPDFFooter */
4570   gl2ps->streamlength = tools_gl2psOpenPDFDat    4570   gl2ps->streamlength = tools_gl2psOpenPDFDataStreamWritePreface(gl2ps);
4571 }                                                4571 }
4572                                                  4572 
4573 /* The central primitive drawing */              4573 /* The central primitive drawing */
4574                                                  4574 
4575 inline void tools_gl2psPrintPDFPrimitive(tool    4575 inline void tools_gl2psPrintPDFPrimitive(tools_GL2PScontext* gl2ps, void *data)
4576 {                                                4576 {
4577   tools_GL2PSprimitive *prim = *(tools_GL2PSp    4577   tools_GL2PSprimitive *prim = *(tools_GL2PSprimitive**)data;
4578                                                  4578 
4579   if((gl2ps->options & TOOLS_GL2PS_OCCLUSION_    4579   if((gl2ps->options & TOOLS_GL2PS_OCCLUSION_CULL) && prim->culled)
4580     return;                                      4580     return;
4581                                                  4581 
4582   prim = tools_gl2psCopyPrimitive(prim); /* d    4582   prim = tools_gl2psCopyPrimitive(prim); /* deep copy */
4583   tools_gl2psListAdd(gl2ps->pdfprimlist, &pri    4583   tools_gl2psListAdd(gl2ps->pdfprimlist, &prim);
4584 }                                                4584 }
4585                                                  4585 
4586 /* close stream and ... */                       4586 /* close stream and ... */
4587                                                  4587 
4588 inline int tools_gl2psClosePDFDataStream(tool    4588 inline int tools_gl2psClosePDFDataStream(tools_GL2PScontext* gl2ps)
4589 {                                                4589 {
4590   int offs = 0;                                  4590   int offs = 0;
4591                                                  4591 
4592 #if defined(TOOLS_GL2PS_HAVE_ZLIB)               4592 #if defined(TOOLS_GL2PS_HAVE_ZLIB)
4593   if(gl2ps->options & TOOLS_GL2PS_COMPRESS){     4593   if(gl2ps->options & TOOLS_GL2PS_COMPRESS){
4594     if(Z_OK != tools_gl2psDeflate(gl2ps))        4594     if(Z_OK != tools_gl2psDeflate(gl2ps))
4595       tools_gl2psMsg(TOOLS_GL2PS_ERROR, "Zlib    4595       tools_gl2psMsg(TOOLS_GL2PS_ERROR, "Zlib deflate error");
4596     else                                         4596     else
4597       fwrite(gl2ps->compress->dest, gl2ps->co    4597       fwrite(gl2ps->compress->dest, gl2ps->compress->destLen, 1, gl2ps->stream);
4598     gl2ps->streamlength += gl2ps->compress->d    4598     gl2ps->streamlength += gl2ps->compress->destLen;
4599                                                  4599 
4600     offs += gl2ps->streamlength;                 4600     offs += gl2ps->streamlength;
4601     tools_gl2psFreeCompress(gl2ps);              4601     tools_gl2psFreeCompress(gl2ps);
4602   }                                              4602   }
4603 #endif                                           4603 #endif
4604                                                  4604 
4605   offs += fprintf(gl2ps->stream,                 4605   offs += fprintf(gl2ps->stream,
4606                   "endstream\n"                  4606                   "endstream\n"
4607                   "endobj\n");                   4607                   "endobj\n");
4608   return offs;                                   4608   return offs;
4609 }                                                4609 }
4610                                                  4610 
4611 /* ... write the now known length object */      4611 /* ... write the now known length object */
4612                                                  4612 
4613 inline int tools_gl2psPrintPDFDataStreamLengt    4613 inline int tools_gl2psPrintPDFDataStreamLength(tools_GL2PScontext* gl2ps, int val)
4614 {                                                4614 {
4615   return fprintf(gl2ps->stream,                  4615   return fprintf(gl2ps->stream,
4616                  "5 0 obj\n"                     4616                  "5 0 obj\n"
4617                  "%d\n"                          4617                  "%d\n"
4618                  "endobj\n", val);               4618                  "endobj\n", val);
4619 }                                                4619 }
4620                                                  4620 
4621 /* Put the info created before in PDF objects    4621 /* Put the info created before in PDF objects */
4622                                                  4622 
4623 inline int tools_gl2psPrintPDFOpenPage(tools_    4623 inline int tools_gl2psPrintPDFOpenPage(tools_GL2PScontext* gl2ps)
4624 {                                                4624 {
4625   int offs;                                      4625   int offs;
4626                                                  4626 
4627   /* Write fixed part */                         4627   /* Write fixed part */
4628                                                  4628 
4629   offs = fprintf(gl2ps->stream,                  4629   offs = fprintf(gl2ps->stream,
4630                  "6 0 obj\n"                     4630                  "6 0 obj\n"
4631                  "<<\n"                          4631                  "<<\n"
4632                  "/Type /Page\n"                 4632                  "/Type /Page\n"
4633                  "/Parent 3 0 R\n"               4633                  "/Parent 3 0 R\n"
4634                  "/MediaBox [%d %d %d %d]\n",    4634                  "/MediaBox [%d %d %d %d]\n",
4635                  (int)gl2ps->viewport[0], (in    4635                  (int)gl2ps->viewport[0], (int)gl2ps->viewport[1],
4636                  (int)gl2ps->viewport[2], (in    4636                  (int)gl2ps->viewport[2], (int)gl2ps->viewport[3]);
4637                                                  4637 
4638   if(gl2ps->options & TOOLS_GL2PS_LANDSCAPE)     4638   if(gl2ps->options & TOOLS_GL2PS_LANDSCAPE)
4639     offs += fprintf(gl2ps->stream, "/Rotate -    4639     offs += fprintf(gl2ps->stream, "/Rotate -90\n");
4640                                                  4640 
4641   offs += fprintf(gl2ps->stream,                 4641   offs += fprintf(gl2ps->stream,
4642                   "/Contents 4 0 R\n"            4642                   "/Contents 4 0 R\n"
4643                   "/Resources\n"                 4643                   "/Resources\n"
4644                   "<<\n"                         4644                   "<<\n"
4645                   "/ProcSet [/PDF /Text /Imag    4645                   "/ProcSet [/PDF /Text /ImageB /ImageC]  %%/ImageI\n");
4646                                                  4646 
4647   return offs;                                   4647   return offs;
4648                                                  4648 
4649   /* End fixed part, proceeds in tools_gl2psP    4649   /* End fixed part, proceeds in tools_gl2psPDFgroupListWriteVariableResources() */
4650 }                                                4650 }
4651                                                  4651 
4652 inline int tools_gl2psPDFgroupListWriteVariab    4652 inline int tools_gl2psPDFgroupListWriteVariableResources(tools_GL2PScontext* gl2ps)
4653 {                                                4653 {
4654   int offs = 0;                                  4654   int offs = 0;
4655                                                  4655 
4656   /* a) Graphics States for shader alpha mask    4656   /* a) Graphics States for shader alpha masks*/
4657   offs += tools_gl2psPDFgroupListWriteGStateR    4657   offs += tools_gl2psPDFgroupListWriteGStateResources(gl2ps);
4658                                                  4658 
4659   /* b) Shader and shader masks */               4659   /* b) Shader and shader masks */
4660   offs += tools_gl2psPDFgroupListWriteShaderR    4660   offs += tools_gl2psPDFgroupListWriteShaderResources(gl2ps);
4661                                                  4661 
4662   /* c) XObjects (Images & Shader Masks) */      4662   /* c) XObjects (Images & Shader Masks) */
4663   offs += tools_gl2psPDFgroupListWriteXObject    4663   offs += tools_gl2psPDFgroupListWriteXObjectResources(gl2ps);
4664                                                  4664 
4665   /* d) Fonts */                                 4665   /* d) Fonts */
4666   offs += tools_gl2psPDFgroupListWriteFontRes    4666   offs += tools_gl2psPDFgroupListWriteFontResources(gl2ps);
4667                                                  4667 
4668   /* End resources and page */                   4668   /* End resources and page */
4669   offs += fprintf(gl2ps->stream,                 4669   offs += fprintf(gl2ps->stream,
4670                   ">>\n"                         4670                   ">>\n"
4671                   ">>\n"                         4671                   ">>\n"
4672                   "endobj\n");                   4672                   "endobj\n");
4673   return offs;                                   4673   return offs;
4674 }                                                4674 }
4675                                                  4675 
4676 /* Standard Graphics State */                    4676 /* Standard Graphics State */
4677                                                  4677 
4678 inline int tools_gl2psPrintPDFGSObject(tools_    4678 inline int tools_gl2psPrintPDFGSObject(tools_GL2PScontext* gl2ps)
4679 {                                                4679 {
4680   return fprintf(gl2ps->stream,                  4680   return fprintf(gl2ps->stream,
4681                  "7 0 obj\n"                     4681                  "7 0 obj\n"
4682                  "<<\n"                          4682                  "<<\n"
4683                  "/Type /ExtGState\n"            4683                  "/Type /ExtGState\n"
4684                  "/SA false\n"                   4684                  "/SA false\n"
4685                  "/SM 0.02\n"                    4685                  "/SM 0.02\n"
4686                  "/OP false\n"                   4686                  "/OP false\n"
4687                  "/op false\n"                   4687                  "/op false\n"
4688                  "/OPM 0\n"                      4688                  "/OPM 0\n"
4689                  "/BG2 /Default\n"               4689                  "/BG2 /Default\n"
4690                  "/UCR2 /Default\n"              4690                  "/UCR2 /Default\n"
4691                  "/TR2 /Default\n"               4691                  "/TR2 /Default\n"
4692                  ">>\n"                          4692                  ">>\n"
4693                  "endobj\n");                    4693                  "endobj\n");
4694 }                                                4694 }
4695                                                  4695 
4696 /* Put vertex' edge flag (8bit) and coordinat    4696 /* Put vertex' edge flag (8bit) and coordinates (32bit) in shader stream */
4697                                                  4697 
4698 inline int tools_gl2psPrintPDFShaderStreamDat    4698 inline int tools_gl2psPrintPDFShaderStreamDataCoord(tools_GL2PScontext* gl2ps, tools_GL2PSvertex *vertex,
4699                                                  4699                                               int (*action)(tools_GL2PScontext*, unsigned long data, int size),
4700                                                  4700                                               tools_GLfloat dx, tools_GLfloat dy,
4701                                                  4701                                               tools_GLfloat xmin, tools_GLfloat ymin)
4702 {                                                4702 {
4703   int offs = 0;                                  4703   int offs = 0;
4704   unsigned long imap;                            4704   unsigned long imap;
4705   tools_GLfloat diff;                            4705   tools_GLfloat diff;
4706 //double dmax = ~1UL;                            4706 //double dmax = ~1UL;
4707   double dmax = (double)~1UL; //G.Barrand : c    4707   double dmax = (double)~1UL; //G.Barrand : clang10 : cast.
4708   char edgeflag = 0;                             4708   char edgeflag = 0;
4709                                                  4709 
4710   /* FIXME: temp bux fix for 64 bit archs: */    4710   /* FIXME: temp bux fix for 64 bit archs: */
4711   if(sizeof(unsigned long) == 8) dmax = dmax     4711   if(sizeof(unsigned long) == 8) dmax = dmax - 2048.;
4712                                                  4712 
4713   offs += (*action)(gl2ps, edgeflag, 1);         4713   offs += (*action)(gl2ps, edgeflag, 1);
4714                                                  4714 
4715   /* The Shader stream in PDF requires to be     4715   /* The Shader stream in PDF requires to be in a 'big-endian'
4716      order */                                    4716      order */
4717                                                  4717 
4718   if(TOOLS_GL2PS_ZERO(dx * dy)){                 4718   if(TOOLS_GL2PS_ZERO(dx * dy)){
4719     offs += (*action)(gl2ps, 0, 4);              4719     offs += (*action)(gl2ps, 0, 4);
4720     offs += (*action)(gl2ps, 0, 4);              4720     offs += (*action)(gl2ps, 0, 4);
4721   }                                              4721   }
4722   else{                                          4722   else{
4723     diff = (vertex->xyz[0] - xmin) / dx;         4723     diff = (vertex->xyz[0] - xmin) / dx;
4724     if(diff > 1)                                 4724     if(diff > 1)
4725       diff = 1.0F;                               4725       diff = 1.0F;
4726     else if(diff < 0)                            4726     else if(diff < 0)
4727       diff = 0.0F;                               4727       diff = 0.0F;
4728     imap = (unsigned long)(diff * dmax);         4728     imap = (unsigned long)(diff * dmax);
4729     offs += (*action)(gl2ps, imap, 4);           4729     offs += (*action)(gl2ps, imap, 4);
4730                                                  4730 
4731     diff = (vertex->xyz[1] - ymin) / dy;         4731     diff = (vertex->xyz[1] - ymin) / dy;
4732     if(diff > 1)                                 4732     if(diff > 1)
4733       diff = 1.0F;                               4733       diff = 1.0F;
4734     else if(diff < 0)                            4734     else if(diff < 0)
4735       diff = 0.0F;                               4735       diff = 0.0F;
4736     imap = (unsigned long)(diff * dmax);         4736     imap = (unsigned long)(diff * dmax);
4737     offs += (*action)(gl2ps, imap, 4);           4737     offs += (*action)(gl2ps, imap, 4);
4738   }                                              4738   }
4739                                                  4739 
4740   return offs;                                   4740   return offs;
4741 }                                                4741 }
4742                                                  4742 
4743 /* Put vertex' rgb value (8bit for every comp    4743 /* Put vertex' rgb value (8bit for every component) in shader stream */
4744                                                  4744 
4745 inline int tools_gl2psPrintPDFShaderStreamDat    4745 inline int tools_gl2psPrintPDFShaderStreamDataRGB(tools_GL2PScontext* gl2ps, tools_GL2PSvertex *vertex,
4746                                             i    4746                                             int (*action)(tools_GL2PScontext*, unsigned long data, int size))
4747 {                                                4747 {
4748   int offs = 0;                                  4748   int offs = 0;
4749   unsigned long imap;                            4749   unsigned long imap;
4750 //double dmax = ~1UL;                            4750 //double dmax = ~1UL;
4751   double dmax = (double)~1UL; //G.Barrand : c    4751   double dmax = (double)~1UL; //G.Barrand : clang10 : cast.
4752                                                  4752 
4753   /* FIXME: temp bux fix for 64 bit archs: */    4753   /* FIXME: temp bux fix for 64 bit archs: */
4754   if(sizeof(unsigned long) == 8) dmax = dmax     4754   if(sizeof(unsigned long) == 8) dmax = dmax - 2048.;
4755                                                  4755 
4756   imap = (unsigned long)((vertex->rgba[0]) *     4756   imap = (unsigned long)((vertex->rgba[0]) * dmax);
4757   offs += (*action)(gl2ps, imap, 1);             4757   offs += (*action)(gl2ps, imap, 1);
4758                                                  4758 
4759   imap = (unsigned long)((vertex->rgba[1]) *     4759   imap = (unsigned long)((vertex->rgba[1]) * dmax);
4760   offs += (*action)(gl2ps, imap, 1);             4760   offs += (*action)(gl2ps, imap, 1);
4761                                                  4761 
4762   imap = (unsigned long)((vertex->rgba[2]) *     4762   imap = (unsigned long)((vertex->rgba[2]) * dmax);
4763   offs += (*action)(gl2ps, imap, 1);             4763   offs += (*action)(gl2ps, imap, 1);
4764                                                  4764 
4765   return offs;                                   4765   return offs;
4766 }                                                4766 }
4767                                                  4767 
4768 /* Put vertex' alpha (8/16bit) in shader stre    4768 /* Put vertex' alpha (8/16bit) in shader stream */
4769                                                  4769 
4770 inline int tools_gl2psPrintPDFShaderStreamDat    4770 inline int tools_gl2psPrintPDFShaderStreamDataAlpha(tools_GL2PScontext* gl2ps, tools_GL2PSvertex *vertex,
4771                                                  4771                                               int (*action)(tools_GL2PScontext*, unsigned long data, int size),
4772                                                  4772                                               int sigbyte)
4773 {                                                4773 {
4774   int offs = 0;                                  4774   int offs = 0;
4775   unsigned long imap;                            4775   unsigned long imap;
4776 //double dmax = ~1UL;                            4776 //double dmax = ~1UL;
4777   double dmax = (double)~1UL; //G.Barrand : c    4777   double dmax = (double)~1UL; //G.Barrand : clang10 : cast.
4778                                                  4778 
4779   /* FIXME: temp bux fix for 64 bit archs: */    4779   /* FIXME: temp bux fix for 64 bit archs: */
4780   if(sizeof(unsigned long) == 8) dmax = dmax     4780   if(sizeof(unsigned long) == 8) dmax = dmax - 2048.;
4781                                                  4781 
4782   if(sigbyte != 8 && sigbyte != 16)              4782   if(sigbyte != 8 && sigbyte != 16)
4783     sigbyte = 8;                                 4783     sigbyte = 8;
4784                                                  4784 
4785   sigbyte /= 8;                                  4785   sigbyte /= 8;
4786                                                  4786 
4787   imap = (unsigned long)((vertex->rgba[3]) *     4787   imap = (unsigned long)((vertex->rgba[3]) * dmax);
4788                                                  4788 
4789   offs += (*action)(gl2ps, imap, sigbyte);       4789   offs += (*action)(gl2ps, imap, sigbyte);
4790                                                  4790 
4791   return offs;                                   4791   return offs;
4792 }                                                4792 }
4793                                                  4793 
4794 /* Put a triangles raw data in shader stream     4794 /* Put a triangles raw data in shader stream */
4795                                                  4795 
4796 inline int tools_gl2psPrintPDFShaderStreamDat    4796 inline int tools_gl2psPrintPDFShaderStreamData(tools_GL2PScontext* gl2ps, tools_GL2PStriangle *triangle,
4797                                          tool    4797                                          tools_GLfloat dx, tools_GLfloat dy,
4798                                          tool    4798                                          tools_GLfloat xmin, tools_GLfloat ymin,
4799                                          int     4799                                          int (*action)(tools_GL2PScontext*, unsigned long data, int size),
4800                                          int     4800                                          int a_gray)
4801 {                                                4801 {
4802   int i, offs = 0;                               4802   int i, offs = 0;
4803   tools_GL2PSvertex v;                           4803   tools_GL2PSvertex v;
4804                                                  4804 
4805   if(a_gray && a_gray != 8 && a_gray != 16)      4805   if(a_gray && a_gray != 8 && a_gray != 16)
4806     a_gray = 8;                                  4806     a_gray = 8;
4807                                                  4807 
4808   for(i = 0; i < 3; ++i){                        4808   for(i = 0; i < 3; ++i){
4809     offs += tools_gl2psPrintPDFShaderStreamDa    4809     offs += tools_gl2psPrintPDFShaderStreamDataCoord(gl2ps, &triangle->vertex[i], action,
4810                                                  4810                                                dx, dy, xmin, ymin);
4811     if(a_gray){                                  4811     if(a_gray){
4812       v = triangle->vertex[i];                   4812       v = triangle->vertex[i];
4813       offs += tools_gl2psPrintPDFShaderStream    4813       offs += tools_gl2psPrintPDFShaderStreamDataAlpha(gl2ps, &v, action, a_gray);
4814     }                                            4814     }
4815     else{                                        4815     else{
4816       offs += tools_gl2psPrintPDFShaderStream    4816       offs += tools_gl2psPrintPDFShaderStreamDataRGB(gl2ps, &triangle->vertex[i], action);
4817     }                                            4817     }
4818   }                                              4818   }
4819                                                  4819 
4820   return offs;                                   4820   return offs;
4821 }                                                4821 }
4822                                                  4822 
4823 inline void tools_gl2psPDFRectHull(tools_GLfl    4823 inline void tools_gl2psPDFRectHull(tools_GLfloat *xmin, tools_GLfloat *xmax,
4824                              tools_GLfloat *y    4824                              tools_GLfloat *ymin, tools_GLfloat *ymax,
4825                              tools_GL2PStrian    4825                              tools_GL2PStriangle *triangles, int cnt)
4826 {                                                4826 {
4827   int i, j;                                      4827   int i, j;
4828                                                  4828 
4829   *xmin = triangles[0].vertex[0].xyz[0];         4829   *xmin = triangles[0].vertex[0].xyz[0];
4830   *xmax = triangles[0].vertex[0].xyz[0];         4830   *xmax = triangles[0].vertex[0].xyz[0];
4831   *ymin = triangles[0].vertex[0].xyz[1];         4831   *ymin = triangles[0].vertex[0].xyz[1];
4832   *ymax = triangles[0].vertex[0].xyz[1];         4832   *ymax = triangles[0].vertex[0].xyz[1];
4833                                                  4833 
4834   for(i = 0; i < cnt; ++i){                      4834   for(i = 0; i < cnt; ++i){
4835     for(j = 0; j < 3; ++j){                      4835     for(j = 0; j < 3; ++j){
4836       if(*xmin > triangles[i].vertex[j].xyz[0    4836       if(*xmin > triangles[i].vertex[j].xyz[0])
4837         *xmin = triangles[i].vertex[j].xyz[0]    4837         *xmin = triangles[i].vertex[j].xyz[0];
4838       if(*xmax < triangles[i].vertex[j].xyz[0    4838       if(*xmax < triangles[i].vertex[j].xyz[0])
4839         *xmax = triangles[i].vertex[j].xyz[0]    4839         *xmax = triangles[i].vertex[j].xyz[0];
4840       if(*ymin > triangles[i].vertex[j].xyz[1    4840       if(*ymin > triangles[i].vertex[j].xyz[1])
4841         *ymin = triangles[i].vertex[j].xyz[1]    4841         *ymin = triangles[i].vertex[j].xyz[1];
4842       if(*ymax < triangles[i].vertex[j].xyz[1    4842       if(*ymax < triangles[i].vertex[j].xyz[1])
4843         *ymax = triangles[i].vertex[j].xyz[1]    4843         *ymax = triangles[i].vertex[j].xyz[1];
4844     }                                            4844     }
4845   }                                              4845   }
4846 }                                                4846 }
4847                                                  4847 
4848 /* Writes shaded triangle                        4848 /* Writes shaded triangle
4849    gray == 0 means write RGB triangles           4849    gray == 0 means write RGB triangles
4850    gray == 8             8bit-grayscale (for     4850    gray == 8             8bit-grayscale (for alpha masks)
4851    gray == 16            16bit-grayscale (for    4851    gray == 16            16bit-grayscale (for alpha masks) */
4852                                                  4852 
4853 inline int tools_gl2psPrintPDFShader(tools_GL    4853 inline int tools_gl2psPrintPDFShader(tools_GL2PScontext* gl2ps, int obj, tools_GL2PStriangle *triangles,
4854                                int size, int     4854                                int size, int a_gray)
4855 {                                                4855 {
4856   int i, offs = 0, vertexbytes, done = 0;        4856   int i, offs = 0, vertexbytes, done = 0;
4857   tools_GLfloat xmin, xmax, ymin, ymax;          4857   tools_GLfloat xmin, xmax, ymin, ymax;
4858                                                  4858 
4859   switch(a_gray){                                4859   switch(a_gray){
4860   case 0:                                        4860   case 0:
4861     vertexbytes = 1+4+4+1+1+1;                   4861     vertexbytes = 1+4+4+1+1+1;
4862     break;                                       4862     break;
4863   case 8:                                        4863   case 8:
4864     vertexbytes = 1+4+4+1;                       4864     vertexbytes = 1+4+4+1;
4865     break;                                       4865     break;
4866   case 16:                                       4866   case 16:
4867     vertexbytes = 1+4+4+2;                       4867     vertexbytes = 1+4+4+2;
4868     break;                                       4868     break;
4869   default:                                       4869   default:
4870     a_gray = 8;                                  4870     a_gray = 8;
4871     vertexbytes = 1+4+4+1;                       4871     vertexbytes = 1+4+4+1;
4872     break;                                       4872     break;
4873   }                                              4873   }
4874                                                  4874 
4875   tools_gl2psPDFRectHull(&xmin, &xmax, &ymin,    4875   tools_gl2psPDFRectHull(&xmin, &xmax, &ymin, &ymax, triangles, size);
4876                                                  4876 
4877   offs += fprintf(gl2ps->stream,                 4877   offs += fprintf(gl2ps->stream,
4878                   "%d 0 obj\n"                   4878                   "%d 0 obj\n"
4879                   "<< "                          4879                   "<< "
4880                   "/ShadingType 4 "              4880                   "/ShadingType 4 "
4881                   "/ColorSpace %s "              4881                   "/ColorSpace %s "
4882                   "/BitsPerCoordinate 32 "       4882                   "/BitsPerCoordinate 32 "
4883                   "/BitsPerComponent %d "        4883                   "/BitsPerComponent %d "
4884                   "/BitsPerFlag 8 "              4884                   "/BitsPerFlag 8 "
4885                   "/Decode [%f %f %f %f 0 1 %    4885                   "/Decode [%f %f %f %f 0 1 %s] ",
4886                   obj,                           4886                   obj,
4887                   (a_gray) ? "/DeviceGray" :     4887                   (a_gray) ? "/DeviceGray" : "/DeviceRGB",
4888                   (a_gray) ? a_gray : 8,         4888                   (a_gray) ? a_gray : 8,
4889                   xmin, xmax, ymin, ymax,        4889                   xmin, xmax, ymin, ymax,
4890                   (a_gray) ? "" : "0 1 0 1");    4890                   (a_gray) ? "" : "0 1 0 1");
4891                                                  4891 
4892 #if defined(TOOLS_GL2PS_HAVE_ZLIB)               4892 #if defined(TOOLS_GL2PS_HAVE_ZLIB)
4893   if(gl2ps->options & TOOLS_GL2PS_COMPRESS){     4893   if(gl2ps->options & TOOLS_GL2PS_COMPRESS){
4894     tools_gl2psAllocCompress(gl2ps,vertexbyte    4894     tools_gl2psAllocCompress(gl2ps,vertexbytes * size * 3);
4895                                                  4895 
4896     for(i = 0; i < size; ++i)                    4896     for(i = 0; i < size; ++i)
4897       tools_gl2psPrintPDFShaderStreamData(gl2    4897       tools_gl2psPrintPDFShaderStreamData(gl2ps,&triangles[i],
4898                                     xmax-xmin    4898                                     xmax-xmin, ymax-ymin, xmin, ymin,
4899                                     tools_gl2    4899                                     tools_gl2psWriteBigEndianCompress, a_gray);
4900                                                  4900 
4901     if(Z_OK == tools_gl2psDeflate(gl2ps) && 2    4901     if(Z_OK == tools_gl2psDeflate(gl2ps) && 23 + gl2ps->compress->destLen < gl2ps->compress->srcLen){
4902       offs += tools_gl2psPrintPDFCompressorTy    4902       offs += tools_gl2psPrintPDFCompressorType(gl2ps);
4903       offs += fprintf(gl2ps->stream,             4903       offs += fprintf(gl2ps->stream,
4904                       "/Length %d "              4904                       "/Length %d "
4905                       ">>\n"                     4905                       ">>\n"
4906                       "stream\n",                4906                       "stream\n",
4907                       (int)gl2ps->compress->d    4907                       (int)gl2ps->compress->destLen);
4908       offs += gl2ps->compress->destLen * fwri    4908       offs += gl2ps->compress->destLen * fwrite(gl2ps->compress->dest,
4909                                                  4909                                                 gl2ps->compress->destLen,
4910                                                  4910                                                 1, gl2ps->stream);
4911       done = 1;                                  4911       done = 1;
4912     }                                            4912     }
4913     tools_gl2psFreeCompress(gl2ps);              4913     tools_gl2psFreeCompress(gl2ps);
4914   }                                              4914   }
4915 #endif                                           4915 #endif
4916                                                  4916 
4917   if(!done){                                     4917   if(!done){
4918     /* no compression, or too long after comp    4918     /* no compression, or too long after compression, or compress error
4919        -> write non-compressed entry */          4919        -> write non-compressed entry */
4920     offs += fprintf(gl2ps->stream,               4920     offs += fprintf(gl2ps->stream,
4921                     "/Length %d "                4921                     "/Length %d "
4922                     ">>\n"                       4922                     ">>\n"
4923                     "stream\n",                  4923                     "stream\n",
4924                     vertexbytes * 3 * size);     4924                     vertexbytes * 3 * size);
4925     for(i = 0; i < size; ++i)                    4925     for(i = 0; i < size; ++i)
4926       offs += tools_gl2psPrintPDFShaderStream    4926       offs += tools_gl2psPrintPDFShaderStreamData(gl2ps, &triangles[i],
4927                                             x    4927                                             xmax-xmin, ymax-ymin, xmin, ymin,
4928                                             t    4928                                             tools_gl2psWriteBigEndian, a_gray);
4929   }                                              4929   }
4930                                                  4930 
4931   offs += fprintf(gl2ps->stream,                 4931   offs += fprintf(gl2ps->stream,
4932                   "\nendstream\n"                4932                   "\nendstream\n"
4933                   "endobj\n");                   4933                   "endobj\n");
4934                                                  4934 
4935   return offs;                                   4935   return offs;
4936 }                                                4936 }
4937                                                  4937 
4938 /* Writes a XObject for a shaded triangle mas    4938 /* Writes a XObject for a shaded triangle mask */
4939                                                  4939 
4940 inline int tools_gl2psPrintPDFShaderMask(tool    4940 inline int tools_gl2psPrintPDFShaderMask(tools_GL2PScontext* gl2ps, int obj, int childobj)
4941 {                                                4941 {
4942   int offs = 0, len;                             4942   int offs = 0, len;
4943                                                  4943 
4944   offs += fprintf(gl2ps->stream,                 4944   offs += fprintf(gl2ps->stream,
4945                   "%d 0 obj\n"                   4945                   "%d 0 obj\n"
4946                   "<<\n"                         4946                   "<<\n"
4947                   "/Type /XObject\n"             4947                   "/Type /XObject\n"
4948                   "/Subtype /Form\n"             4948                   "/Subtype /Form\n"
4949                   "/BBox [ %d %d %d %d ]\n"      4949                   "/BBox [ %d %d %d %d ]\n"
4950                   "/Group \n<<\n/S /Transpare    4950                   "/Group \n<<\n/S /Transparency /CS /DeviceRGB\n"
4951                   ">>\n",                        4951                   ">>\n",
4952                   obj,                           4952                   obj,
4953                   (int)gl2ps->viewport[0], (i    4953                   (int)gl2ps->viewport[0], (int)gl2ps->viewport[1],
4954                   (int)gl2ps->viewport[2], (i    4954                   (int)gl2ps->viewport[2], (int)gl2ps->viewport[3]);
4955                                                  4955 
4956   len = (childobj>0)                             4956   len = (childobj>0)
4957     ? (int)strlen("/TrSh sh\n") + (int)log10(    4957     ? (int)strlen("/TrSh sh\n") + (int)log10((double)childobj)+1
4958     : (int)strlen("/TrSh0 sh\n");                4958     : (int)strlen("/TrSh0 sh\n");
4959                                                  4959 
4960   offs += fprintf(gl2ps->stream,                 4960   offs += fprintf(gl2ps->stream,
4961                   "/Length %d\n"                 4961                   "/Length %d\n"
4962                   ">>\n"                         4962                   ">>\n"
4963                   "stream\n",                    4963                   "stream\n",
4964                   len);                          4964                   len);
4965   offs += fprintf(gl2ps->stream,                 4965   offs += fprintf(gl2ps->stream,
4966                   "/TrSh%d sh\n",                4966                   "/TrSh%d sh\n",
4967                   childobj);                     4967                   childobj);
4968   offs += fprintf(gl2ps->stream,                 4968   offs += fprintf(gl2ps->stream,
4969                   "endstream\n"                  4969                   "endstream\n"
4970                   "endobj\n");                   4970                   "endobj\n");
4971                                                  4971 
4972   return offs;                                   4972   return offs;
4973 }                                                4973 }
4974                                                  4974 
4975 /* Writes a Extended graphics state for a sha    4975 /* Writes a Extended graphics state for a shaded triangle mask if
4976    simplealpha ist true the childobj argument    4976    simplealpha ist true the childobj argument is ignored and a /ca
4977    statement will be written instead */          4977    statement will be written instead */
4978                                                  4978 
4979 inline int tools_gl2psPrintPDFShaderExtGS(too    4979 inline int tools_gl2psPrintPDFShaderExtGS(tools_GL2PScontext* gl2ps, int obj, int childobj)
4980 {                                                4980 {
4981   int offs = 0;                                  4981   int offs = 0;
4982                                                  4982 
4983   offs += fprintf(gl2ps->stream,                 4983   offs += fprintf(gl2ps->stream,
4984                   "%d 0 obj\n"                   4984                   "%d 0 obj\n"
4985                   "<<\n",                        4985                   "<<\n",
4986                   obj);                          4986                   obj);
4987                                                  4987 
4988   offs += fprintf(gl2ps->stream,                 4988   offs += fprintf(gl2ps->stream,
4989                   "/SMask << /S /Alpha /G %d     4989                   "/SMask << /S /Alpha /G %d 0 R >> ",
4990                   childobj);                     4990                   childobj);
4991                                                  4991 
4992   offs += fprintf(gl2ps->stream,                 4992   offs += fprintf(gl2ps->stream,
4993                   ">>\n"                         4993                   ">>\n"
4994                   "endobj\n");                   4994                   "endobj\n");
4995   return offs;                                   4995   return offs;
4996 }                                                4996 }
4997                                                  4997 
4998 /* a simple graphics state */                    4998 /* a simple graphics state */
4999                                                  4999 
5000 inline int tools_gl2psPrintPDFShaderSimpleExt    5000 inline int tools_gl2psPrintPDFShaderSimpleExtGS(tools_GL2PScontext* gl2ps, int obj, tools_GLfloat alpha)
5001 {                                                5001 {
5002   int offs = 0;                                  5002   int offs = 0;
5003                                                  5003 
5004   offs += fprintf(gl2ps->stream,                 5004   offs += fprintf(gl2ps->stream,
5005                   "%d 0 obj\n"                   5005                   "%d 0 obj\n"
5006                   "<<\n"                         5006                   "<<\n"
5007                   "/ca %g"                       5007                   "/ca %g"
5008                   ">>\n"                         5008                   ">>\n"
5009                   "endobj\n",                    5009                   "endobj\n",
5010                   obj, alpha);                   5010                   obj, alpha);
5011   return offs;                                   5011   return offs;
5012 }                                                5012 }
5013                                                  5013 
5014 /* Similar groups of functions for pixmaps an    5014 /* Similar groups of functions for pixmaps and text */
5015                                                  5015 
5016 inline int tools_gl2psPrintPDFPixmapStreamDat    5016 inline int tools_gl2psPrintPDFPixmapStreamData(tools_GL2PScontext* gl2ps, tools_GL2PSimage *im,
5017                                          int     5017                                          int (*action)(tools_GL2PScontext*, unsigned long data, int size),
5018                                          int     5018                                          int a_gray)
5019 {                                                5019 {
5020   int x, y, shift;                               5020   int x, y, shift;
5021   tools_GLfloat _r, _g, _b, _a;                  5021   tools_GLfloat _r, _g, _b, _a;
5022                                                  5022 
5023   if(im->format != TOOLS_GL_RGBA && a_gray)      5023   if(im->format != TOOLS_GL_RGBA && a_gray)
5024     return 0;                                    5024     return 0;
5025                                                  5025 
5026   if(a_gray && a_gray != 8 && a_gray != 16)      5026   if(a_gray && a_gray != 8 && a_gray != 16)
5027     a_gray = 8;                                  5027     a_gray = 8;
5028                                                  5028 
5029   a_gray /= 8;                                   5029   a_gray /= 8;
5030                                                  5030 
5031   shift = (sizeof(unsigned long) - 1) * 8;       5031   shift = (sizeof(unsigned long) - 1) * 8;
5032                                                  5032 
5033   for(y = 0; y < im->height; ++y){               5033   for(y = 0; y < im->height; ++y){
5034     for(x = 0; x < im->width; ++x){              5034     for(x = 0; x < im->width; ++x){
5035       _a = tools_gl2psGetRGB(im, x, y, &_r, &    5035       _a = tools_gl2psGetRGB(im, x, y, &_r, &_g, &_b);
5036       if(im->format == TOOLS_GL_RGBA && a_gra    5036       if(im->format == TOOLS_GL_RGBA && a_gray){
5037         (*action)(gl2ps, (unsigned long)(_a *    5037         (*action)(gl2ps, (unsigned long)(_a * 255) << shift, a_gray);
5038       }                                          5038       }
5039       else{                                      5039       else{
5040         (*action)(gl2ps, (unsigned long)(_r *    5040         (*action)(gl2ps, (unsigned long)(_r * 255) << shift, 1);
5041         (*action)(gl2ps, (unsigned long)(_g *    5041         (*action)(gl2ps, (unsigned long)(_g * 255) << shift, 1);
5042         (*action)(gl2ps, (unsigned long)(_b *    5042         (*action)(gl2ps, (unsigned long)(_b * 255) << shift, 1);
5043       }                                          5043       }
5044     }                                            5044     }
5045   }                                              5045   }
5046                                                  5046 
5047   switch(a_gray){                                5047   switch(a_gray){
5048   case 0: return 3 * im->width * im->height;     5048   case 0: return 3 * im->width * im->height;
5049   case 1: return im->width * im->height;         5049   case 1: return im->width * im->height;
5050   case 2: return 2 * im->width * im->height;     5050   case 2: return 2 * im->width * im->height;
5051   default: return 3 * im->width * im->height;    5051   default: return 3 * im->width * im->height;
5052   }                                              5052   }
5053 }                                                5053 }
5054                                                  5054 
5055 inline int tools_gl2psPrintPDFPixmap(tools_GL    5055 inline int tools_gl2psPrintPDFPixmap(tools_GL2PScontext* gl2ps, int obj, int childobj, tools_GL2PSimage *im, int a_gray)
5056 {                                                5056 {
5057   int offs = 0, done = 0, sigbytes = 3;          5057   int offs = 0, done = 0, sigbytes = 3;
5058                                                  5058 
5059   if(a_gray && a_gray !=8 && a_gray != 16)       5059   if(a_gray && a_gray !=8 && a_gray != 16)
5060     a_gray = 8;                                  5060     a_gray = 8;
5061                                                  5061 
5062   if(a_gray)                                     5062   if(a_gray)
5063     sigbytes = a_gray / 8;                       5063     sigbytes = a_gray / 8;
5064                                                  5064 
5065   offs += fprintf(gl2ps->stream,                 5065   offs += fprintf(gl2ps->stream,
5066                   "%d 0 obj\n"                   5066                   "%d 0 obj\n"
5067                   "<<\n"                         5067                   "<<\n"
5068                   "/Type /XObject\n"             5068                   "/Type /XObject\n"
5069                   "/Subtype /Image\n"            5069                   "/Subtype /Image\n"
5070                   "/Width %d\n"                  5070                   "/Width %d\n"
5071                   "/Height %d\n"                 5071                   "/Height %d\n"
5072                   "/ColorSpace %s \n"            5072                   "/ColorSpace %s \n"
5073                   "/BitsPerComponent 8\n",       5073                   "/BitsPerComponent 8\n",
5074                   obj,                           5074                   obj,
5075                   (int)im->width, (int)im->he    5075                   (int)im->width, (int)im->height,
5076                   (a_gray) ? "/DeviceGray" :     5076                   (a_gray) ? "/DeviceGray" : "/DeviceRGB" );
5077   if(TOOLS_GL_RGBA == im->format && a_gray ==    5077   if(TOOLS_GL_RGBA == im->format && a_gray == 0){
5078     offs += fprintf(gl2ps->stream,               5078     offs += fprintf(gl2ps->stream,
5079                     "/SMask %d 0 R\n",           5079                     "/SMask %d 0 R\n",
5080                     childobj);                   5080                     childobj);
5081   }                                              5081   }
5082                                                  5082 
5083 #if defined(TOOLS_GL2PS_HAVE_ZLIB)               5083 #if defined(TOOLS_GL2PS_HAVE_ZLIB)
5084   if(gl2ps->options & TOOLS_GL2PS_COMPRESS){     5084   if(gl2ps->options & TOOLS_GL2PS_COMPRESS){
5085     tools_gl2psAllocCompress(gl2ps,(int)(im->    5085     tools_gl2psAllocCompress(gl2ps,(int)(im->width * im->height * sigbytes));
5086                                                  5086 
5087     tools_gl2psPrintPDFPixmapStreamData(gl2ps    5087     tools_gl2psPrintPDFPixmapStreamData(gl2ps, im, tools_gl2psWriteBigEndianCompress, a_gray);
5088                                                  5088 
5089     if(Z_OK == tools_gl2psDeflate(gl2ps) && 2    5089     if(Z_OK == tools_gl2psDeflate(gl2ps) && 23 + gl2ps->compress->destLen < gl2ps->compress->srcLen){
5090       offs += tools_gl2psPrintPDFCompressorTy    5090       offs += tools_gl2psPrintPDFCompressorType(gl2ps);
5091       offs += fprintf(gl2ps->stream,             5091       offs += fprintf(gl2ps->stream,
5092                       "/Length %d "              5092                       "/Length %d "
5093                       ">>\n"                     5093                       ">>\n"
5094                       "stream\n",                5094                       "stream\n",
5095                       (int)gl2ps->compress->d    5095                       (int)gl2ps->compress->destLen);
5096       offs += gl2ps->compress->destLen * fwri    5096       offs += gl2ps->compress->destLen * fwrite(gl2ps->compress->dest, gl2ps->compress->destLen,
5097                                                  5097                                                 1, gl2ps->stream);
5098       done = 1;                                  5098       done = 1;
5099     }                                            5099     }
5100     tools_gl2psFreeCompress(gl2ps);              5100     tools_gl2psFreeCompress(gl2ps);
5101   }                                              5101   }
5102 #endif                                           5102 #endif
5103                                                  5103 
5104   if(!done){                                     5104   if(!done){
5105     /* no compression, or too long after comp    5105     /* no compression, or too long after compression, or compress error
5106        -> write non-compressed entry */          5106        -> write non-compressed entry */
5107     offs += fprintf(gl2ps->stream,               5107     offs += fprintf(gl2ps->stream,
5108                     "/Length %d "                5108                     "/Length %d "
5109                     ">>\n"                       5109                     ">>\n"
5110                     "stream\n",                  5110                     "stream\n",
5111                     (int)(im->width * im->hei    5111                     (int)(im->width * im->height * sigbytes));
5112     offs += tools_gl2psPrintPDFPixmapStreamDa    5112     offs += tools_gl2psPrintPDFPixmapStreamData(gl2ps, im, tools_gl2psWriteBigEndian, a_gray);
5113   }                                              5113   }
5114                                                  5114 
5115   offs += fprintf(gl2ps->stream,                 5115   offs += fprintf(gl2ps->stream,
5116                   "\nendstream\n"                5116                   "\nendstream\n"
5117                   "endobj\n");                   5117                   "endobj\n");
5118                                                  5118 
5119   return offs;                                   5119   return offs;
5120 }                                                5120 }
5121                                                  5121 
5122 inline int tools_gl2psPrintPDFText(tools_GL2P    5122 inline int tools_gl2psPrintPDFText(tools_GL2PScontext* gl2ps, int obj, tools_GL2PSstring *a_s, int fontnumber)
5123 {                                                5123 {
5124   int offs = 0;                                  5124   int offs = 0;
5125                                                  5125 
5126   offs += fprintf(gl2ps->stream,                 5126   offs += fprintf(gl2ps->stream,
5127                   "%d 0 obj\n"                   5127                   "%d 0 obj\n"
5128                   "<<\n"                         5128                   "<<\n"
5129                   "/Type /Font\n"                5129                   "/Type /Font\n"
5130                   "/Subtype /Type1\n"            5130                   "/Subtype /Type1\n"
5131                   "/Name /F%d\n"                 5131                   "/Name /F%d\n"
5132                   "/BaseFont /%s\n"              5132                   "/BaseFont /%s\n"
5133                   "/Encoding /MacRomanEncodin    5133                   "/Encoding /MacRomanEncoding\n"
5134                   ">>\n"                         5134                   ">>\n"
5135                   "endobj\n",                    5135                   "endobj\n",
5136                   obj, fontnumber, a_s->fontn    5136                   obj, fontnumber, a_s->fontname);
5137   return offs;                                   5137   return offs;
5138 }                                                5138 }
5139                                                  5139 
5140 /* Write the physical objects */                 5140 /* Write the physical objects */
5141                                                  5141 
5142 inline int tools_gl2psPDFgroupListWriteObject    5142 inline int tools_gl2psPDFgroupListWriteObjects(tools_GL2PScontext* gl2ps, int entryoffs)
5143 {                                                5143 {
5144   int i,j;                                       5144   int i,j;
5145   tools_GL2PSprimitive *p = NULL;                5145   tools_GL2PSprimitive *p = NULL;
5146   tools_GL2PSpdfgroup *gro;                      5146   tools_GL2PSpdfgroup *gro;
5147   int offs = entryoffs;                          5147   int offs = entryoffs;
5148   tools_GL2PStriangle *triangles;                5148   tools_GL2PStriangle *triangles;
5149   int size = 0;                                  5149   int size = 0;
5150                                                  5150 
5151   if(!gl2ps->pdfgrouplist)                       5151   if(!gl2ps->pdfgrouplist)
5152     return offs;                                 5152     return offs;
5153                                                  5153 
5154   for(i = 0; i < tools_gl2psListNbr(gl2ps->pd    5154   for(i = 0; i < tools_gl2psListNbr(gl2ps->pdfgrouplist); ++i){
5155     gro = (tools_GL2PSpdfgroup*)tools_gl2psLi    5155     gro = (tools_GL2PSpdfgroup*)tools_gl2psListPointer(gl2ps->pdfgrouplist, i);
5156     if(!tools_gl2psListNbr(gro->ptrlist))        5156     if(!tools_gl2psListNbr(gro->ptrlist))
5157       continue;                                  5157       continue;
5158     p = *(tools_GL2PSprimitive**)tools_gl2psL    5158     p = *(tools_GL2PSprimitive**)tools_gl2psListPointer(gro->ptrlist, 0);
5159     switch(p->type){                             5159     switch(p->type){
5160     case TOOLS_GL2PS_POINT:                      5160     case TOOLS_GL2PS_POINT:
5161       break;                                     5161       break;
5162     case TOOLS_GL2PS_LINE:                       5162     case TOOLS_GL2PS_LINE:
5163       break;                                     5163       break;
5164     case TOOLS_GL2PS_TRIANGLE:                   5164     case TOOLS_GL2PS_TRIANGLE:
5165       size = tools_gl2psListNbr(gro->ptrlist)    5165       size = tools_gl2psListNbr(gro->ptrlist);
5166       triangles = (tools_GL2PStriangle*)tools    5166       triangles = (tools_GL2PStriangle*)tools_gl2psMalloc(sizeof(tools_GL2PStriangle) * size);
5167       for(j = 0; j < size; ++j){                 5167       for(j = 0; j < size; ++j){
5168         p = *(tools_GL2PSprimitive**)tools_gl    5168         p = *(tools_GL2PSprimitive**)tools_gl2psListPointer(gro->ptrlist, j);
5169         tools_gl2psFillTriangleFromPrimitive(    5169         tools_gl2psFillTriangleFromPrimitive(&triangles[j], p, TOOLS_GL_TRUE);
5170       }                                          5170       }
5171       if(triangles[0].prop & T_VAR_COLOR){       5171       if(triangles[0].prop & T_VAR_COLOR){
5172         gl2ps->xreflist[gro->shobjno] = offs;    5172         gl2ps->xreflist[gro->shobjno] = offs;
5173         offs += tools_gl2psPrintPDFShader(gl2    5173         offs += tools_gl2psPrintPDFShader(gl2ps, gro->shobjno, triangles, size, 0);
5174       }                                          5174       }
5175       if(triangles[0].prop & T_ALPHA_LESS_1){    5175       if(triangles[0].prop & T_ALPHA_LESS_1){
5176         gl2ps->xreflist[gro->gsobjno] = offs;    5176         gl2ps->xreflist[gro->gsobjno] = offs;
5177         offs += tools_gl2psPrintPDFShaderSimp    5177         offs += tools_gl2psPrintPDFShaderSimpleExtGS(gl2ps, gro->gsobjno, triangles[0].vertex[0].rgba[3]);
5178       }                                          5178       }
5179       if(triangles[0].prop & T_VAR_ALPHA){       5179       if(triangles[0].prop & T_VAR_ALPHA){
5180         gl2ps->xreflist[gro->gsobjno] = offs;    5180         gl2ps->xreflist[gro->gsobjno] = offs;
5181         offs += tools_gl2psPrintPDFShaderExtG    5181         offs += tools_gl2psPrintPDFShaderExtGS(gl2ps, gro->gsobjno, gro->trgroupobjno);
5182         gl2ps->xreflist[gro->trgroupobjno] =     5182         gl2ps->xreflist[gro->trgroupobjno] = offs;
5183         offs += tools_gl2psPrintPDFShaderMask    5183         offs += tools_gl2psPrintPDFShaderMask(gl2ps, gro->trgroupobjno, gro->maskshno);
5184         gl2ps->xreflist[gro->maskshobjno] = o    5184         gl2ps->xreflist[gro->maskshobjno] = offs;
5185         offs += tools_gl2psPrintPDFShader(gl2    5185         offs += tools_gl2psPrintPDFShader(gl2ps, gro->maskshobjno, triangles, size, 8);
5186       }                                          5186       }
5187       tools_gl2psFree(triangles);                5187       tools_gl2psFree(triangles);
5188       break;                                     5188       break;
5189     case TOOLS_GL2PS_PIXMAP:                     5189     case TOOLS_GL2PS_PIXMAP:
5190       gl2ps->xreflist[gro->imobjno] = offs;      5190       gl2ps->xreflist[gro->imobjno] = offs;
5191       offs += tools_gl2psPrintPDFPixmap(gl2ps    5191       offs += tools_gl2psPrintPDFPixmap(gl2ps, gro->imobjno, gro->imobjno+1, p->data.image, 0);
5192       if(p->data.image->format == TOOLS_GL_RG    5192       if(p->data.image->format == TOOLS_GL_RGBA){
5193         gl2ps->xreflist[gro->imobjno+1] = off    5193         gl2ps->xreflist[gro->imobjno+1] = offs;
5194         offs += tools_gl2psPrintPDFPixmap(gl2    5194         offs += tools_gl2psPrintPDFPixmap(gl2ps, gro->imobjno+1, -1, p->data.image, 8);
5195       }                                          5195       }
5196       break;                                     5196       break;
5197     case TOOLS_GL2PS_TEXT:                       5197     case TOOLS_GL2PS_TEXT:
5198       gl2ps->xreflist[gro->fontobjno] = offs;    5198       gl2ps->xreflist[gro->fontobjno] = offs;
5199       offs += tools_gl2psPrintPDFText(gl2ps,     5199       offs += tools_gl2psPrintPDFText(gl2ps, gro->fontobjno,p->data.text,gro->fontno);
5200       break;                                     5200       break;
5201     case TOOLS_GL2PS_SPECIAL :                   5201     case TOOLS_GL2PS_SPECIAL :
5202       /* alignment contains the format for wh    5202       /* alignment contains the format for which the special output text
5203          is intended */                          5203          is intended */
5204       if(p->data.text->alignment == TOOLS_GL2    5204       if(p->data.text->alignment == TOOLS_GL2PS_PDF)
5205         offs += fprintf(gl2ps->stream, "%s\n"    5205         offs += fprintf(gl2ps->stream, "%s\n", p->data.text->str);
5206       break;                                     5206       break;
5207     default:                                     5207     default:
5208       break;                                     5208       break;
5209     }                                            5209     }
5210   }                                              5210   }
5211   return offs;                                   5211   return offs;
5212 }                                                5212 }
5213                                                  5213 
5214 /* All variable data has been written at this    5214 /* All variable data has been written at this point and all required
5215    functioninality has been gathered, so we c    5215    functioninality has been gathered, so we can write now file footer
5216    with cross reference table and trailer */     5216    with cross reference table and trailer */
5217                                                  5217 
5218 inline void tools_gl2psPrintPDFFooter(tools_G    5218 inline void tools_gl2psPrintPDFFooter(tools_GL2PScontext* gl2ps)
5219 {                                                5219 {
5220   int i, offs;                                   5220   int i, offs;
5221                                                  5221 
5222   tools_gl2psPDFgroupListInit(gl2ps);            5222   tools_gl2psPDFgroupListInit(gl2ps);
5223   tools_gl2psPDFgroupListWriteMainStream(gl2p    5223   tools_gl2psPDFgroupListWriteMainStream(gl2ps);
5224                                                  5224 
5225   offs = gl2ps->xreflist[5] + gl2ps->streamle    5225   offs = gl2ps->xreflist[5] + gl2ps->streamlength;
5226   offs += tools_gl2psClosePDFDataStream(gl2ps    5226   offs += tools_gl2psClosePDFDataStream(gl2ps);
5227   gl2ps->xreflist[5] = offs;                     5227   gl2ps->xreflist[5] = offs;
5228                                                  5228 
5229   offs += tools_gl2psPrintPDFDataStreamLength    5229   offs += tools_gl2psPrintPDFDataStreamLength(gl2ps, gl2ps->streamlength);
5230   gl2ps->xreflist[6] = offs;                     5230   gl2ps->xreflist[6] = offs;
5231   gl2ps->streamlength = 0;                       5231   gl2ps->streamlength = 0;
5232                                                  5232 
5233   offs += tools_gl2psPrintPDFOpenPage(gl2ps);    5233   offs += tools_gl2psPrintPDFOpenPage(gl2ps);
5234   offs += tools_gl2psPDFgroupListWriteVariabl    5234   offs += tools_gl2psPDFgroupListWriteVariableResources(gl2ps);
5235   gl2ps->xreflist = (int*)tools_gl2psRealloc(    5235   gl2ps->xreflist = (int*)tools_gl2psRealloc(gl2ps->xreflist,
5236                                        sizeof    5236                                        sizeof(int) * (gl2ps->objects_stack + 1));
5237   gl2ps->xreflist[7] = offs;                     5237   gl2ps->xreflist[7] = offs;
5238                                                  5238 
5239   offs += tools_gl2psPrintPDFGSObject(gl2ps);    5239   offs += tools_gl2psPrintPDFGSObject(gl2ps);
5240   gl2ps->xreflist[8] = offs;                     5240   gl2ps->xreflist[8] = offs;
5241                                                  5241 
5242   gl2ps->xreflist[gl2ps->objects_stack] =        5242   gl2ps->xreflist[gl2ps->objects_stack] =
5243     tools_gl2psPDFgroupListWriteObjects(gl2ps    5243     tools_gl2psPDFgroupListWriteObjects(gl2ps, gl2ps->xreflist[8]);
5244                                                  5244 
5245   /* Start cross reference table. The file ha    5245   /* Start cross reference table. The file has to been opened in
5246      binary mode to preserve the 20 digit str    5246      binary mode to preserve the 20 digit string length! */
5247   fprintf(gl2ps->stream,                         5247   fprintf(gl2ps->stream,
5248           "xref\n"                               5248           "xref\n"
5249           "0 %d\n"                               5249           "0 %d\n"
5250           "%010d 65535 f \n", gl2ps->objects_    5250           "%010d 65535 f \n", gl2ps->objects_stack, 0);
5251                                                  5251 
5252   for(i = 1; i < gl2ps->objects_stack; ++i)      5252   for(i = 1; i < gl2ps->objects_stack; ++i)
5253     fprintf(gl2ps->stream, "%010d 00000 n \n"    5253     fprintf(gl2ps->stream, "%010d 00000 n \n", gl2ps->xreflist[i]);
5254                                                  5254 
5255   fprintf(gl2ps->stream,                         5255   fprintf(gl2ps->stream,
5256           "trailer\n"                            5256           "trailer\n"
5257           "<<\n"                                 5257           "<<\n"
5258           "/Size %d\n"                           5258           "/Size %d\n"
5259           "/Info 1 0 R\n"                        5259           "/Info 1 0 R\n"
5260           "/Root 2 0 R\n"                        5260           "/Root 2 0 R\n"
5261           ">>\n"                                 5261           ">>\n"
5262           "startxref\n%d\n"                      5262           "startxref\n%d\n"
5263           "%%%%EOF\n",                           5263           "%%%%EOF\n",
5264           gl2ps->objects_stack, gl2ps->xrefli    5264           gl2ps->objects_stack, gl2ps->xreflist[gl2ps->objects_stack]);
5265                                                  5265 
5266   /* Free auxiliary lists and arrays */          5266   /* Free auxiliary lists and arrays */
5267   tools_gl2psFree(gl2ps->xreflist);              5267   tools_gl2psFree(gl2ps->xreflist);
5268   tools_gl2psListAction(gl2ps->pdfprimlist, t    5268   tools_gl2psListAction(gl2ps->pdfprimlist, tools_gl2psFreePrimitive);
5269   tools_gl2psListDelete(gl2ps->pdfprimlist);     5269   tools_gl2psListDelete(gl2ps->pdfprimlist);
5270   tools_gl2psPDFgroupListDelete(gl2ps);          5270   tools_gl2psPDFgroupListDelete(gl2ps);
5271                                                  5271 
5272 #if defined(TOOLS_GL2PS_HAVE_ZLIB)               5272 #if defined(TOOLS_GL2PS_HAVE_ZLIB)
5273   if(gl2ps->options & TOOLS_GL2PS_COMPRESS){     5273   if(gl2ps->options & TOOLS_GL2PS_COMPRESS){
5274     tools_gl2psFreeCompress(gl2ps);              5274     tools_gl2psFreeCompress(gl2ps);
5275     tools_gl2psFree(gl2ps->compress);            5275     tools_gl2psFree(gl2ps->compress);
5276     gl2ps->compress = NULL;                      5276     gl2ps->compress = NULL;
5277   }                                              5277   }
5278 #endif                                           5278 #endif
5279 }                                                5279 }
5280                                                  5280 
5281 /* PDF begin viewport */                         5281 /* PDF begin viewport */
5282                                                  5282 
5283 inline void tools_gl2psPrintPDFBeginViewport(    5283 inline void tools_gl2psPrintPDFBeginViewport(tools_GL2PScontext* gl2ps, tools_GLint viewport[4])
5284 {                                                5284 {
5285   int offs = 0;                                  5285   int offs = 0;
5286   tools_GLint idx;                               5286   tools_GLint idx;
5287   tools_GLfloat rgba[4];                         5287   tools_GLfloat rgba[4];
5288   int x = viewport[0], y = viewport[1], w = v    5288   int x = viewport[0], y = viewport[1], w = viewport[2], h = viewport[3];
5289                                                  5289 
5290   tools_glRenderMode(TOOLS_GL_FEEDBACK);         5290   tools_glRenderMode(TOOLS_GL_FEEDBACK);
5291                                                  5291 
5292   tools_gl2psResetLineProperties(gl2ps);         5292   tools_gl2psResetLineProperties(gl2ps);
5293                                                  5293 
5294   if(gl2ps->header){                             5294   if(gl2ps->header){
5295     tools_gl2psPrintPDFHeader(gl2ps);            5295     tools_gl2psPrintPDFHeader(gl2ps);
5296     gl2ps->header = TOOLS_GL_FALSE;              5296     gl2ps->header = TOOLS_GL_FALSE;
5297   }                                              5297   }
5298                                                  5298 
5299   offs += tools_gl2psPrintf(gl2ps,"q\n");        5299   offs += tools_gl2psPrintf(gl2ps,"q\n");
5300                                                  5300 
5301   if(gl2ps->options & TOOLS_GL2PS_DRAW_BACKGR    5301   if(gl2ps->options & TOOLS_GL2PS_DRAW_BACKGROUND){
5302     if(gl2ps->colormode == TOOLS_GL_RGBA || g    5302     if(gl2ps->colormode == TOOLS_GL_RGBA || gl2ps->colorsize == 0){
5303       tools_glGetFloatv(TOOLS_GL_COLOR_CLEAR_    5303       tools_glGetFloatv(TOOLS_GL_COLOR_CLEAR_VALUE, rgba);
5304     }                                            5304     }
5305     else{                                        5305     else{
5306       tools_glGetIntegerv(TOOLS_GL_INDEX_CLEA    5306       tools_glGetIntegerv(TOOLS_GL_INDEX_CLEAR_VALUE, &idx);
5307       rgba[0] = gl2ps->colormap[idx][0];         5307       rgba[0] = gl2ps->colormap[idx][0];
5308       rgba[1] = gl2ps->colormap[idx][1];         5308       rgba[1] = gl2ps->colormap[idx][1];
5309       rgba[2] = gl2ps->colormap[idx][2];         5309       rgba[2] = gl2ps->colormap[idx][2];
5310       rgba[3] = 1.0F;                            5310       rgba[3] = 1.0F;
5311     }                                            5311     }
5312     offs += tools_gl2psPrintPDFFillColor(gl2p    5312     offs += tools_gl2psPrintPDFFillColor(gl2ps, rgba);
5313     offs += tools_gl2psPrintf(gl2ps,"%d %d %d    5313     offs += tools_gl2psPrintf(gl2ps,"%d %d %d %d re\n"
5314                         "W\n"                    5314                         "W\n"
5315                         "f\n",                   5315                         "f\n",
5316                         x, y, w, h);             5316                         x, y, w, h);
5317   }                                              5317   }
5318   else{                                          5318   else{
5319     offs += tools_gl2psPrintf(gl2ps,"%d %d %d    5319     offs += tools_gl2psPrintf(gl2ps,"%d %d %d %d re\n"
5320                         "W\n"                    5320                         "W\n"
5321                         "n\n",                   5321                         "n\n",
5322                         x, y, w, h);             5322                         x, y, w, h);
5323   }                                              5323   }
5324                                                  5324 
5325   gl2ps->streamlength += offs;                   5325   gl2ps->streamlength += offs;
5326 }                                                5326 }
5327                                                  5327 
5328 inline tools_GLint tools_gl2psPrintPDFEndView    5328 inline tools_GLint tools_gl2psPrintPDFEndViewport(tools_GL2PScontext* gl2ps)
5329 {                                                5329 {
5330   tools_GLint res;                               5330   tools_GLint res;
5331                                                  5331 
5332   res = tools_gl2psPrintPrimitives(gl2ps);       5332   res = tools_gl2psPrintPrimitives(gl2ps);
5333   gl2ps->streamlength += tools_gl2psPrintf(gl    5333   gl2ps->streamlength += tools_gl2psPrintf(gl2ps,"Q\n");
5334   return res;                                    5334   return res;
5335 }                                                5335 }
5336                                                  5336 
5337 inline void tools_gl2psPrintPDFFinalPrimitive    5337 inline void tools_gl2psPrintPDFFinalPrimitive(tools_GL2PScontext*)
5338 {                                                5338 {
5339 }                                                5339 }
5340                                                  5340 
5341 /* definition of the PDF backend */              5341 /* definition of the PDF backend */
5342                                                  5342 
5343 static const tools_GL2PSbackend tools_gl2psPD    5343 static const tools_GL2PSbackend tools_gl2psPDF = {
5344   tools_gl2psPrintPDFHeader,                     5344   tools_gl2psPrintPDFHeader,
5345   tools_gl2psPrintPDFFooter,                     5345   tools_gl2psPrintPDFFooter,
5346   tools_gl2psPrintPDFBeginViewport,              5346   tools_gl2psPrintPDFBeginViewport,
5347   tools_gl2psPrintPDFEndViewport,                5347   tools_gl2psPrintPDFEndViewport,
5348   tools_gl2psPrintPDFPrimitive,                  5348   tools_gl2psPrintPDFPrimitive,
5349   tools_gl2psPrintPDFFinalPrimitive,             5349   tools_gl2psPrintPDFFinalPrimitive,
5350   "pdf",                                         5350   "pdf",
5351   "Portable Document Format"                     5351   "Portable Document Format"
5352 };                                               5352 };
5353                                                  5353 
5354 /********************************************    5354 /*********************************************************************
5355  *                                               5355  *
5356  * SVG routines                                  5356  * SVG routines
5357  *                                               5357  *
5358  ********************************************    5358  *********************************************************************/
5359                                                  5359 
5360 inline void tools_gl2psSVGGetCoordsAndColors(    5360 inline void tools_gl2psSVGGetCoordsAndColors(tools_GL2PScontext* gl2ps, int n, tools_GL2PSvertex *verts,
5361                                        tools_    5361                                        tools_GL2PSxyz *xyz, tools_GL2PSrgba *rgba)
5362 {                                                5362 {
5363   int i, j;                                      5363   int i, j;
5364                                                  5364 
5365   for(i = 0; i < n; i++){                        5365   for(i = 0; i < n; i++){
5366     xyz[i][0] = verts[i].xyz[0];                 5366     xyz[i][0] = verts[i].xyz[0];
5367     xyz[i][1] = gl2ps->viewport[3] - verts[i]    5367     xyz[i][1] = gl2ps->viewport[3] - verts[i].xyz[1];
5368     xyz[i][2] = 0.0F;                            5368     xyz[i][2] = 0.0F;
5369     for(j = 0; j < 4; j++)                       5369     for(j = 0; j < 4; j++)
5370       rgba[i][j] = verts[i].rgba[j];             5370       rgba[i][j] = verts[i].rgba[j];
5371   }                                              5371   }
5372 }                                                5372 }
5373                                                  5373 
5374 #include <sstream>  //G.Barrand                  5374 #include <sstream>  //G.Barrand
5375 #include <iomanip>  //G.Barrand                  5375 #include <iomanip>  //G.Barrand
5376                                                  5376 
5377 inline void tools_gl2psSVGGetColorString(tool    5377 inline void tools_gl2psSVGGetColorString(tools_GL2PSrgba rgba, char str[32])
5378 {                                                5378 {
5379   int _r = (int)(255. * rgba[0]);                5379   int _r = (int)(255. * rgba[0]);
5380   int _g = (int)(255. * rgba[1]);                5380   int _g = (int)(255. * rgba[1]);
5381   int _b = (int)(255. * rgba[2]);                5381   int _b = (int)(255. * rgba[2]);
5382   int rc = (_r < 0) ? 0 : (_r > 255) ? 255 :     5382   int rc = (_r < 0) ? 0 : (_r > 255) ? 255 : _r;
5383   int gc = (_g < 0) ? 0 : (_g > 255) ? 255 :     5383   int gc = (_g < 0) ? 0 : (_g > 255) ? 255 : _g;
5384   int bc = (_b < 0) ? 0 : (_b > 255) ? 255 :     5384   int bc = (_b < 0) ? 0 : (_b > 255) ? 255 : _b;
5385 //sprintf(str, "#%2.2x%2.2x%2.2x", rc, gc, bc    5385 //sprintf(str, "#%2.2x%2.2x%2.2x", rc, gc, bc); //G.Barrand
5386 //G.Barrand:begin:                               5386 //G.Barrand:begin:
5387   std::ostringstream oss;                        5387   std::ostringstream oss;
5388   oss << "#";                                    5388   oss << "#";
5389   oss << std::setw(2) << std::setfill('0') <<    5389   oss << std::setw(2) << std::setfill('0') << std::hex << rc;
5390   oss << std::setw(2) << std::setfill('0') <<    5390   oss << std::setw(2) << std::setfill('0') << std::hex << gc;
5391   oss << std::setw(2) << std::setfill('0') <<    5391   oss << std::setw(2) << std::setfill('0') << std::hex << bc;
5392   strcpy(str,oss.str().c_str());                 5392   strcpy(str,oss.str().c_str());
5393 //G.Barrand:end.                                 5393 //G.Barrand:end.
5394 }                                                5394 }
5395                                                  5395 
5396 inline void tools_gl2psPrintSVGHeader(tools_G    5396 inline void tools_gl2psPrintSVGHeader(tools_GL2PScontext* gl2ps)
5397 {                                                5397 {
5398   int x, y, width, height;                       5398   int x, y, width, height;
5399   char col[32];                                  5399   char col[32];
5400   time_t now;                                    5400   time_t now;
5401                                                  5401 
5402   time(&now);                                    5402   time(&now);
5403                                                  5403 
5404   if (gl2ps->options & TOOLS_GL2PS_LANDSCAPE)    5404   if (gl2ps->options & TOOLS_GL2PS_LANDSCAPE){
5405     x = (int)gl2ps->viewport[1];                 5405     x = (int)gl2ps->viewport[1];
5406     y = (int)gl2ps->viewport[0];                 5406     y = (int)gl2ps->viewport[0];
5407     width = (int)gl2ps->viewport[3];             5407     width = (int)gl2ps->viewport[3];
5408     height = (int)gl2ps->viewport[2];            5408     height = (int)gl2ps->viewport[2];
5409   }                                              5409   }
5410   else{                                          5410   else{
5411     x = (int)gl2ps->viewport[0];                 5411     x = (int)gl2ps->viewport[0];
5412     y = (int)gl2ps->viewport[1];                 5412     y = (int)gl2ps->viewport[1];
5413     width = (int)gl2ps->viewport[2];             5413     width = (int)gl2ps->viewport[2];
5414     height = (int)gl2ps->viewport[3];            5414     height = (int)gl2ps->viewport[3];
5415   }                                              5415   }
5416                                                  5416 
5417   /* Compressed SVG files (.svgz) are simply     5417   /* Compressed SVG files (.svgz) are simply gzipped SVG files */
5418   tools_gl2psPrintGzipHeader(gl2ps);             5418   tools_gl2psPrintGzipHeader(gl2ps);
5419                                                  5419 
5420   tools_gl2psPrintf(gl2ps,"<?xml version=\"1.    5420   tools_gl2psPrintf(gl2ps,"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n");
5421   tools_gl2psPrintf(gl2ps,"<svg xmlns=\"http:    5421   tools_gl2psPrintf(gl2ps,"<svg xmlns=\"http://www.w3.org/2000/svg\"\n");
5422   tools_gl2psPrintf(gl2ps,"     xmlns:xlink=\    5422   tools_gl2psPrintf(gl2ps,"     xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n"
5423               "     width=\"%dpt\" height=\"%    5423               "     width=\"%dpt\" height=\"%dpt\" viewBox=\"%d %d %d %d\">\n",
5424               width, height, x, y, width, hei    5424               width, height, x, y, width, height);
5425   tools_gl2psPrintf(gl2ps,"<title>%s</title>\    5425   tools_gl2psPrintf(gl2ps,"<title>%s</title>\n", gl2ps->title);
5426   tools_gl2psPrintf(gl2ps,"<desc>\n");           5426   tools_gl2psPrintf(gl2ps,"<desc>\n");
5427   tools_gl2psPrintf(gl2ps,"Creator: GL2PS %d.    5427   tools_gl2psPrintf(gl2ps,"Creator: GL2PS %d.%d.%d%s, %s\n"
5428               "For: %s\n"                        5428               "For: %s\n"
5429               "CreationDate: %s",                5429               "CreationDate: %s",
5430               TOOLS_GL2PS_MAJOR_VERSION, TOOL    5430               TOOLS_GL2PS_MAJOR_VERSION, TOOLS_GL2PS_MINOR_VERSION, TOOLS_GL2PS_PATCH_VERSION,
5431               TOOLS_GL2PS_EXTRA_VERSION, TOOL    5431               TOOLS_GL2PS_EXTRA_VERSION, TOOLS_GL2PS_COPYRIGHT, gl2ps->producer, ctime(&now));
5432   tools_gl2psPrintf(gl2ps,"</desc>\n");          5432   tools_gl2psPrintf(gl2ps,"</desc>\n");
5433   tools_gl2psPrintf(gl2ps,"<defs>\n");           5433   tools_gl2psPrintf(gl2ps,"<defs>\n");
5434   tools_gl2psPrintf(gl2ps,"</defs>\n");          5434   tools_gl2psPrintf(gl2ps,"</defs>\n");
5435                                                  5435 
5436   if(gl2ps->options & TOOLS_GL2PS_DRAW_BACKGR    5436   if(gl2ps->options & TOOLS_GL2PS_DRAW_BACKGROUND){
5437     tools_gl2psSVGGetColorString(gl2ps->bgcol    5437     tools_gl2psSVGGetColorString(gl2ps->bgcolor, col);
5438     tools_gl2psPrintf(gl2ps,"<polygon fill=\"    5438     tools_gl2psPrintf(gl2ps,"<polygon fill=\"%s\" points=\"%d,%d %d,%d %d,%d %d,%d\"/>\n", col,
5439                 (int)gl2ps->viewport[0], (int    5439                 (int)gl2ps->viewport[0], (int)gl2ps->viewport[1],
5440                 (int)gl2ps->viewport[2], (int    5440                 (int)gl2ps->viewport[2], (int)gl2ps->viewport[1],
5441                 (int)gl2ps->viewport[2], (int    5441                 (int)gl2ps->viewport[2], (int)gl2ps->viewport[3],
5442                 (int)gl2ps->viewport[0], (int    5442                 (int)gl2ps->viewport[0], (int)gl2ps->viewport[3]);
5443   }                                              5443   }
5444                                                  5444 
5445   /* group all the primitives and disable ant    5445   /* group all the primitives and disable antialiasing */
5446   tools_gl2psPrintf(gl2ps,"<g>\n");              5446   tools_gl2psPrintf(gl2ps,"<g>\n");
5447 }                                                5447 }
5448                                                  5448 
5449 inline void tools_gl2psPrintSVGSmoothTriangle    5449 inline void tools_gl2psPrintSVGSmoothTriangle(tools_GL2PScontext* gl2ps, tools_GL2PSxyz xyz[3], tools_GL2PSrgba rgba[3])
5450 {                                                5450 {
5451   int i;                                         5451   int i;
5452   tools_GL2PSxyz xyz2[3];                        5452   tools_GL2PSxyz xyz2[3];
5453   tools_GL2PSrgba rgba2[3];                      5453   tools_GL2PSrgba rgba2[3];
5454   char col[32];                                  5454   char col[32];
5455                                                  5455 
5456   /* Apparently there is no easy way to do Go    5456   /* Apparently there is no easy way to do Gouraud shading in SVG
5457      without explicitly pre-defining gradient    5457      without explicitly pre-defining gradients, so for now we just do
5458      recursive subdivision */                    5458      recursive subdivision */
5459                                                  5459 
5460   if(tools_gl2psSameColorThreshold(3, rgba, g    5460   if(tools_gl2psSameColorThreshold(3, rgba, gl2ps->threshold)){
5461     tools_gl2psSVGGetColorString(rgba[0], col    5461     tools_gl2psSVGGetColorString(rgba[0], col);
5462     tools_gl2psPrintf(gl2ps,"<polygon fill=\"    5462     tools_gl2psPrintf(gl2ps,"<polygon fill=\"%s\" ", col);
5463     if(rgba[0][3] < 1.0F) tools_gl2psPrintf(g    5463     if(rgba[0][3] < 1.0F) tools_gl2psPrintf(gl2ps,"fill-opacity=\"%g\" ", rgba[0][3]);
5464     tools_gl2psPrintf(gl2ps,"shape-rendering=    5464     tools_gl2psPrintf(gl2ps,"shape-rendering=\"crispEdges\" ");
5465     tools_gl2psPrintf(gl2ps,"points=\"%g,%g %    5465     tools_gl2psPrintf(gl2ps,"points=\"%g,%g %g,%g %g,%g\"/>\n", xyz[0][0], xyz[0][1],
5466                 xyz[1][0], xyz[1][1], xyz[2][    5466                 xyz[1][0], xyz[1][1], xyz[2][0], xyz[2][1]);
5467   }                                              5467   }
5468   else{                                          5468   else{
5469     /* subdivide into 4 subtriangles */          5469     /* subdivide into 4 subtriangles */
5470     for(i = 0; i < 3; i++){                      5470     for(i = 0; i < 3; i++){
5471       xyz2[0][i] = xyz[0][i];                    5471       xyz2[0][i] = xyz[0][i];
5472       xyz2[1][i] = 0.5F * (xyz[0][i] + xyz[1]    5472       xyz2[1][i] = 0.5F * (xyz[0][i] + xyz[1][i]);
5473       xyz2[2][i] = 0.5F * (xyz[0][i] + xyz[2]    5473       xyz2[2][i] = 0.5F * (xyz[0][i] + xyz[2][i]);
5474     }                                            5474     }
5475     for(i = 0; i < 4; i++){                      5475     for(i = 0; i < 4; i++){
5476       rgba2[0][i] = rgba[0][i];                  5476       rgba2[0][i] = rgba[0][i];
5477       rgba2[1][i] = 0.5F * (rgba[0][i] + rgba    5477       rgba2[1][i] = 0.5F * (rgba[0][i] + rgba[1][i]);
5478       rgba2[2][i] = 0.5F * (rgba[0][i] + rgba    5478       rgba2[2][i] = 0.5F * (rgba[0][i] + rgba[2][i]);
5479     }                                            5479     }
5480     tools_gl2psPrintSVGSmoothTriangle(gl2ps,     5480     tools_gl2psPrintSVGSmoothTriangle(gl2ps, xyz2, rgba2);
5481     for(i = 0; i < 3; i++){                      5481     for(i = 0; i < 3; i++){
5482       xyz2[0][i] = 0.5F * (xyz[0][i] + xyz[1]    5482       xyz2[0][i] = 0.5F * (xyz[0][i] + xyz[1][i]);
5483       xyz2[1][i] = xyz[1][i];                    5483       xyz2[1][i] = xyz[1][i];
5484       xyz2[2][i] = 0.5F * (xyz[1][i] + xyz[2]    5484       xyz2[2][i] = 0.5F * (xyz[1][i] + xyz[2][i]);
5485     }                                            5485     }
5486     for(i = 0; i < 4; i++){                      5486     for(i = 0; i < 4; i++){
5487       rgba2[0][i] = 0.5F * (rgba[0][i] + rgba    5487       rgba2[0][i] = 0.5F * (rgba[0][i] + rgba[1][i]);
5488       rgba2[1][i] = rgba[1][i];                  5488       rgba2[1][i] = rgba[1][i];
5489       rgba2[2][i] = 0.5F * (rgba[1][i] + rgba    5489       rgba2[2][i] = 0.5F * (rgba[1][i] + rgba[2][i]);
5490     }                                            5490     }
5491     tools_gl2psPrintSVGSmoothTriangle(gl2ps,     5491     tools_gl2psPrintSVGSmoothTriangle(gl2ps, xyz2, rgba2);
5492     for(i = 0; i < 3; i++){                      5492     for(i = 0; i < 3; i++){
5493       xyz2[0][i] = 0.5F * (xyz[0][i] + xyz[2]    5493       xyz2[0][i] = 0.5F * (xyz[0][i] + xyz[2][i]);
5494       xyz2[1][i] = xyz[2][i];                    5494       xyz2[1][i] = xyz[2][i];
5495       xyz2[2][i] = 0.5F * (xyz[1][i] + xyz[2]    5495       xyz2[2][i] = 0.5F * (xyz[1][i] + xyz[2][i]);
5496     }                                            5496     }
5497     for(i = 0; i < 4; i++){                      5497     for(i = 0; i < 4; i++){
5498       rgba2[0][i] = 0.5F * (rgba[0][i] + rgba    5498       rgba2[0][i] = 0.5F * (rgba[0][i] + rgba[2][i]);
5499       rgba2[1][i] = rgba[2][i];                  5499       rgba2[1][i] = rgba[2][i];
5500       rgba2[2][i] = 0.5F * (rgba[1][i] + rgba    5500       rgba2[2][i] = 0.5F * (rgba[1][i] + rgba[2][i]);
5501     }                                            5501     }
5502     tools_gl2psPrintSVGSmoothTriangle(gl2ps,     5502     tools_gl2psPrintSVGSmoothTriangle(gl2ps, xyz2, rgba2);
5503     for(i = 0; i < 3; i++){                      5503     for(i = 0; i < 3; i++){
5504       xyz2[0][i] = 0.5F * (xyz[0][i] + xyz[1]    5504       xyz2[0][i] = 0.5F * (xyz[0][i] + xyz[1][i]);
5505       xyz2[1][i] = 0.5F * (xyz[1][i] + xyz[2]    5505       xyz2[1][i] = 0.5F * (xyz[1][i] + xyz[2][i]);
5506       xyz2[2][i] = 0.5F * (xyz[0][i] + xyz[2]    5506       xyz2[2][i] = 0.5F * (xyz[0][i] + xyz[2][i]);
5507     }                                            5507     }
5508     for(i = 0; i < 4; i++){                      5508     for(i = 0; i < 4; i++){
5509       rgba2[0][i] = 0.5F * (rgba[0][i] + rgba    5509       rgba2[0][i] = 0.5F * (rgba[0][i] + rgba[1][i]);
5510       rgba2[1][i] = 0.5F * (rgba[1][i] + rgba    5510       rgba2[1][i] = 0.5F * (rgba[1][i] + rgba[2][i]);
5511       rgba2[2][i] = 0.5F * (rgba[0][i] + rgba    5511       rgba2[2][i] = 0.5F * (rgba[0][i] + rgba[2][i]);
5512     }                                            5512     }
5513     tools_gl2psPrintSVGSmoothTriangle(gl2ps,     5513     tools_gl2psPrintSVGSmoothTriangle(gl2ps, xyz2, rgba2);
5514   }                                              5514   }
5515 }                                                5515 }
5516                                                  5516 
5517 inline void tools_gl2psPrintSVGDash(tools_GL2    5517 inline void tools_gl2psPrintSVGDash(tools_GL2PScontext* gl2ps, tools_GLushort pattern, tools_GLint factor)
5518 {                                                5518 {
5519   int i, n, array[10];                           5519   int i, n, array[10];
5520                                                  5520 
5521   if(!pattern || !factor) return; /* solid li    5521   if(!pattern || !factor) return; /* solid line */
5522                                                  5522 
5523   tools_gl2psParseStipplePattern(pattern, fac    5523   tools_gl2psParseStipplePattern(pattern, factor, &n, array);
5524   tools_gl2psPrintf(gl2ps,"stroke-dasharray=\    5524   tools_gl2psPrintf(gl2ps,"stroke-dasharray=\"");
5525   for(i = 0; i < n; i++){                        5525   for(i = 0; i < n; i++){
5526     if(i) tools_gl2psPrintf(gl2ps,",");          5526     if(i) tools_gl2psPrintf(gl2ps,",");
5527     tools_gl2psPrintf(gl2ps,"%d", array[i]);     5527     tools_gl2psPrintf(gl2ps,"%d", array[i]);
5528   }                                              5528   }
5529   tools_gl2psPrintf(gl2ps,"\" ");                5529   tools_gl2psPrintf(gl2ps,"\" ");
5530 }                                                5530 }
5531                                                  5531 
5532 inline void tools_gl2psEndSVGLine(tools_GL2PS    5532 inline void tools_gl2psEndSVGLine(tools_GL2PScontext* gl2ps)
5533 {                                                5533 {
5534   int i;                                         5534   int i;
5535   if(gl2ps->lastvertex.rgba[0] >= 0.){           5535   if(gl2ps->lastvertex.rgba[0] >= 0.){
5536     tools_gl2psPrintf(gl2ps,"%g,%g\"/>\n", gl    5536     tools_gl2psPrintf(gl2ps,"%g,%g\"/>\n", gl2ps->lastvertex.xyz[0],
5537                 gl2ps->viewport[3] - gl2ps->l    5537                 gl2ps->viewport[3] - gl2ps->lastvertex.xyz[1]);
5538     for(i = 0; i < 3; i++)                       5538     for(i = 0; i < 3; i++)
5539       gl2ps->lastvertex.xyz[i] = -1.;            5539       gl2ps->lastvertex.xyz[i] = -1.;
5540     for(i = 0; i < 4; i++)                       5540     for(i = 0; i < 4; i++)
5541       gl2ps->lastvertex.rgba[i] = -1.;           5541       gl2ps->lastvertex.rgba[i] = -1.;
5542   }                                              5542   }
5543 }                                                5543 }
5544                                                  5544 
5545 inline void tools_gl2psPrintSVGPixmap(tools_G    5545 inline void tools_gl2psPrintSVGPixmap(tools_GL2PScontext* gl2ps, tools_GLfloat x, tools_GLfloat y, tools_GL2PSimage *pixmap)
5546 {                                                5546 {
5547 #if defined(TOOLS_GL2PS_HAVE_LIBPNG)             5547 #if defined(TOOLS_GL2PS_HAVE_LIBPNG)
5548   tools_GL2PSlist *png;                          5548   tools_GL2PSlist *png;
5549   unsigned char c;                               5549   unsigned char c;
5550   int i;                                         5550   int i;
5551                                                  5551 
5552   /* The only image types supported by the SV    5552   /* The only image types supported by the SVG standard are JPEG, PNG
5553      and SVG. Here we choose PNG, and since w    5553      and SVG. Here we choose PNG, and since we want to embed the image
5554      directly in the SVG stream (and not link    5554      directly in the SVG stream (and not link to an external image
5555      file), we need to encode the pixmap into    5555      file), we need to encode the pixmap into PNG in memory, then
5556      encode it into base64. */                   5556      encode it into base64. */
5557                                                  5557 
5558   png = tools_gl2psListCreate(pixmap->width *    5558   png = tools_gl2psListCreate(pixmap->width * pixmap->height * 3, 1000,
5559                         sizeof(unsigned char)    5559                         sizeof(unsigned char));
5560   tools_gl2psConvertPixmapToPNG(pixmap, png);    5560   tools_gl2psConvertPixmapToPNG(pixmap, png);
5561   tools_gl2psListEncodeBase64(png);              5561   tools_gl2psListEncodeBase64(png);
5562                                                  5562 
5563   /* Use "transform" attribute to scale and t    5563   /* Use "transform" attribute to scale and translate the image from
5564      the coordinates origin (0,0) */             5564      the coordinates origin (0,0) */
5565   y -= pixmap->zoom_y * (tools_GLfloat)pixmap    5565   y -= pixmap->zoom_y * (tools_GLfloat)pixmap->height;
5566   tools_gl2psPrintf(gl2ps,"<image x=\"%g\" y=    5566   tools_gl2psPrintf(gl2ps,"<image x=\"%g\" y=\"%g\" width=\"%d\" height=\"%d\"\n",
5567               0., 0., pixmap->width, pixmap->    5567               0., 0., pixmap->width, pixmap->height);
5568   tools_gl2psPrintf(gl2ps,"transform=\"matrix    5568   tools_gl2psPrintf(gl2ps,"transform=\"matrix(%g,0,0,%g,%g,%g)\"\n",
5569               pixmap->zoom_x, pixmap->zoom_y,    5569               pixmap->zoom_x, pixmap->zoom_y, x, y);
5570   tools_gl2psPrintf(gl2ps,"xlink:href=\"data:    5570   tools_gl2psPrintf(gl2ps,"xlink:href=\"data:image/png;base64,");
5571   for(i = 0; i < tools_gl2psListNbr(png); i++    5571   for(i = 0; i < tools_gl2psListNbr(png); i++){
5572     tools_gl2psListRead(png, i, &c);             5572     tools_gl2psListRead(png, i, &c);
5573     tools_gl2psPrintf(gl2ps,"%c", c);            5573     tools_gl2psPrintf(gl2ps,"%c", c);
5574   }                                              5574   }
5575   tools_gl2psPrintf(gl2ps,"\"/>\n");             5575   tools_gl2psPrintf(gl2ps,"\"/>\n");
5576   tools_gl2psListDelete(png);                    5576   tools_gl2psListDelete(png);
5577 #else                                            5577 #else
5578   (void) x; (void) y; (void) pixmap;  /* not     5578   (void) x; (void) y; (void) pixmap;  /* not used */
5579   tools_gl2psMsg(TOOLS_GL2PS_WARNING, "GL2PS     5579   tools_gl2psMsg(TOOLS_GL2PS_WARNING, "GL2PS must be compiled with PNG support in "
5580            "order to embed images in SVG stre    5580            "order to embed images in SVG streams");
5581 #endif                                           5581 #endif
5582   (void)gl2ps;                                   5582   (void)gl2ps;
5583 }                                                5583 }
5584                                                  5584 
5585 inline void tools_gl2psPrintSVGPrimitive(tool    5585 inline void tools_gl2psPrintSVGPrimitive(tools_GL2PScontext* gl2ps, void *data)
5586 {                                                5586 {
5587   tools_GL2PSprimitive *prim;                    5587   tools_GL2PSprimitive *prim;
5588   tools_GL2PSxyz xyz[4];                         5588   tools_GL2PSxyz xyz[4];
5589   tools_GL2PSrgba rgba[4];                       5589   tools_GL2PSrgba rgba[4];
5590   char col[32];                                  5590   char col[32];
5591   char lcap[7], ljoin[7];                        5591   char lcap[7], ljoin[7];
5592   int newline;                                   5592   int newline;
5593                                                  5593 
5594   prim = *(tools_GL2PSprimitive**)data;          5594   prim = *(tools_GL2PSprimitive**)data;
5595                                                  5595 
5596   if((gl2ps->options & TOOLS_GL2PS_OCCLUSION_    5596   if((gl2ps->options & TOOLS_GL2PS_OCCLUSION_CULL) && prim->culled) return;
5597                                                  5597 
5598   /* We try to draw connected lines as a sing    5598   /* We try to draw connected lines as a single path to get nice line
5599      joins and correct stippling. So if the p    5599      joins and correct stippling. So if the primitive to print is not
5600      a line we must first finish the current     5600      a line we must first finish the current line (if any): */
5601   if(prim->type != TOOLS_GL2PS_LINE) tools_gl    5601   if(prim->type != TOOLS_GL2PS_LINE) tools_gl2psEndSVGLine(gl2ps);
5602                                                  5602 
5603   tools_gl2psSVGGetCoordsAndColors(gl2ps, pri    5603   tools_gl2psSVGGetCoordsAndColors(gl2ps, prim->numverts, prim->verts, xyz, rgba);
5604                                                  5604 
5605   switch(prim->type){                            5605   switch(prim->type){
5606   case TOOLS_GL2PS_POINT :                       5606   case TOOLS_GL2PS_POINT :
5607     tools_gl2psSVGGetColorString(rgba[0], col    5607     tools_gl2psSVGGetColorString(rgba[0], col);
5608     tools_gl2psPrintf(gl2ps,"<circle fill=\"%    5608     tools_gl2psPrintf(gl2ps,"<circle fill=\"%s\" ", col);
5609     if(rgba[0][3] < 1.0F) tools_gl2psPrintf(g    5609     if(rgba[0][3] < 1.0F) tools_gl2psPrintf(gl2ps,"fill-opacity=\"%g\" ", rgba[0][3]);
5610     tools_gl2psPrintf(gl2ps,"cx=\"%g\" cy=\"%    5610     tools_gl2psPrintf(gl2ps,"cx=\"%g\" cy=\"%g\" r=\"%g\"/>\n",
5611                 xyz[0][0], xyz[0][1], 0.5 * p    5611                 xyz[0][0], xyz[0][1], 0.5 * prim->width);
5612     break;                                       5612     break;
5613   case TOOLS_GL2PS_LINE :                        5613   case TOOLS_GL2PS_LINE :
5614     if(!tools_gl2psSamePosition(gl2ps->lastve    5614     if(!tools_gl2psSamePosition(gl2ps->lastvertex.xyz, prim->verts[0].xyz) ||
5615        !tools_gl2psSameColor(gl2ps->lastrgba,    5615        !tools_gl2psSameColor(gl2ps->lastrgba, prim->verts[0].rgba) ||
5616        gl2ps->lastlinewidth != prim->width ||    5616        gl2ps->lastlinewidth != prim->width ||
5617        gl2ps->lastlinecap != prim->linecap ||    5617        gl2ps->lastlinecap != prim->linecap ||
5618        gl2ps->lastlinejoin != prim->linejoin     5618        gl2ps->lastlinejoin != prim->linejoin ||
5619        gl2ps->lastpattern != prim->pattern ||    5619        gl2ps->lastpattern != prim->pattern ||
5620        gl2ps->lastfactor != prim->factor){       5620        gl2ps->lastfactor != prim->factor){
5621       /* End the current line if the new segm    5621       /* End the current line if the new segment does not start where
5622          the last one ended, or if the color,    5622          the last one ended, or if the color, the width or the
5623          stippling have changed (we will need    5623          stippling have changed (we will need to use multi-point
5624          gradients for smooth-shaded lines) *    5624          gradients for smooth-shaded lines) */
5625       tools_gl2psEndSVGLine(gl2ps);              5625       tools_gl2psEndSVGLine(gl2ps);
5626       newline = 1;                               5626       newline = 1;
5627     }                                            5627     }
5628     else{                                        5628     else{
5629       newline = 0;                               5629       newline = 0;
5630     }                                            5630     }
5631     gl2ps->lastvertex = prim->verts[1];          5631     gl2ps->lastvertex = prim->verts[1];
5632     tools_gl2psSetLastColor(gl2ps, prim->vert    5632     tools_gl2psSetLastColor(gl2ps, prim->verts[0].rgba);
5633     gl2ps->lastlinewidth = prim->width;          5633     gl2ps->lastlinewidth = prim->width;
5634     gl2ps->lastlinecap = prim->linecap;          5634     gl2ps->lastlinecap = prim->linecap;
5635     gl2ps->lastlinejoin = prim->linejoin;        5635     gl2ps->lastlinejoin = prim->linejoin;
5636     gl2ps->lastpattern = prim->pattern;          5636     gl2ps->lastpattern = prim->pattern;
5637     gl2ps->lastfactor = prim->factor;            5637     gl2ps->lastfactor = prim->factor;
5638     if(newline){                                 5638     if(newline){
5639       tools_gl2psSVGGetColorString(rgba[0], c    5639       tools_gl2psSVGGetColorString(rgba[0], col);
5640       tools_gl2psPrintf(gl2ps,"<polyline fill    5640       tools_gl2psPrintf(gl2ps,"<polyline fill=\"none\" stroke=\"%s\" stroke-width=\"%g\" ",
5641                   col, prim->width);             5641                   col, prim->width);
5642       switch (prim->linecap){                    5642       switch (prim->linecap){
5643       case TOOLS_GL2PS_LINE_CAP_BUTT:            5643       case TOOLS_GL2PS_LINE_CAP_BUTT:
5644       //sprintf (lcap, "%s", "butt");  //G.Ba    5644       //sprintf (lcap, "%s", "butt");  //G.Barrand
5645         strcpy (lcap, "butt");         //G.Ba    5645         strcpy (lcap, "butt");         //G.Barrand
5646         break;                                   5646         break;
5647       case TOOLS_GL2PS_LINE_CAP_ROUND:           5647       case TOOLS_GL2PS_LINE_CAP_ROUND:
5648       //sprintf (lcap, "%s", "round"); //G.Ba    5648       //sprintf (lcap, "%s", "round"); //G.Barrand
5649         strcpy (lcap, "round");        //G.Ba    5649         strcpy (lcap, "round");        //G.Barrand
5650         break;                                   5650         break;
5651       case TOOLS_GL2PS_LINE_CAP_SQUARE:          5651       case TOOLS_GL2PS_LINE_CAP_SQUARE:
5652       //sprintf (lcap, "%s", "square"); //G.B    5652       //sprintf (lcap, "%s", "square"); //G.Barrand
5653         strcpy (lcap, "square");        //G.B    5653         strcpy (lcap, "square");        //G.Barrand
5654         break;                                   5654         break;
5655       default: /*G.Barrand : to quiet Coverit    5655       default: /*G.Barrand : to quiet Coverity :*/
5656       //sprintf (lcap, "%s", "butt");   //G.B    5656       //sprintf (lcap, "%s", "butt");   //G.Barrand
5657         strcpy (lcap, "butt");          //G.B    5657         strcpy (lcap, "butt");          //G.Barrand
5658         break;                                   5658         break;
5659       }                                          5659       }
5660       switch (prim->linejoin){                   5660       switch (prim->linejoin){
5661       case TOOLS_GL2PS_LINE_JOIN_MITER:          5661       case TOOLS_GL2PS_LINE_JOIN_MITER:
5662       //sprintf (ljoin, "%s", "miter");  //G.    5662       //sprintf (ljoin, "%s", "miter");  //G.Barrand
5663         strcpy (ljoin, "miter");         //G.    5663         strcpy (ljoin, "miter");         //G.Barrand 
5664         break;                                   5664         break;
5665       case TOOLS_GL2PS_LINE_JOIN_ROUND:          5665       case TOOLS_GL2PS_LINE_JOIN_ROUND:
5666       //sprintf (ljoin, "%s", "round");  //G.    5666       //sprintf (ljoin, "%s", "round");  //G.Barrand
5667         strcpy (ljoin, "round");         //G.    5667         strcpy (ljoin, "round");         //G.Barrand
5668         break;                                   5668         break;
5669       case TOOLS_GL2PS_LINE_JOIN_BEVEL:          5669       case TOOLS_GL2PS_LINE_JOIN_BEVEL:
5670       //sprintf (ljoin, "%s", "bevel");  //G.    5670       //sprintf (ljoin, "%s", "bevel");  //G.Barrand
5671         strcpy (ljoin, "bevel");         //G.    5671         strcpy (ljoin, "bevel");         //G.Barrand
5672         break;                                   5672         break;
5673       default: /*G.Barrand : to quiet Coverit    5673       default: /*G.Barrand : to quiet Coverity :*/
5674       //sprintf (ljoin, "%s", "miter");  //G.    5674       //sprintf (ljoin, "%s", "miter");  //G.Barrand 
5675         strcpy (ljoin, "miter");         //G.    5675         strcpy (ljoin, "miter");         //G.Barrand
5676         break;                                   5676         break;
5677       }                                          5677       }
5678       tools_gl2psPrintf(gl2ps,"stroke-linecap    5678       tools_gl2psPrintf(gl2ps,"stroke-linecap=\"%s\" stroke-linejoin=\"%s\" ",
5679                   lcap, ljoin);                  5679                   lcap, ljoin);
5680       if(rgba[0][3] < 1.0F) tools_gl2psPrintf    5680       if(rgba[0][3] < 1.0F) tools_gl2psPrintf(gl2ps,"stroke-opacity=\"%g\" ", rgba[0][3]);
5681       tools_gl2psPrintSVGDash(gl2ps, prim->pa    5681       tools_gl2psPrintSVGDash(gl2ps, prim->pattern, prim->factor);
5682       tools_gl2psPrintf(gl2ps,"points=\"%g,%g    5682       tools_gl2psPrintf(gl2ps,"points=\"%g,%g ", xyz[0][0], xyz[0][1]);
5683     }                                            5683     }
5684     else{                                        5684     else{
5685       tools_gl2psPrintf(gl2ps,"%g,%g ", xyz[0    5685       tools_gl2psPrintf(gl2ps,"%g,%g ", xyz[0][0], xyz[0][1]);
5686     }                                            5686     }
5687     break;                                       5687     break;
5688   case TOOLS_GL2PS_TRIANGLE :                    5688   case TOOLS_GL2PS_TRIANGLE :
5689     tools_gl2psPrintSVGSmoothTriangle(gl2ps,     5689     tools_gl2psPrintSVGSmoothTriangle(gl2ps, xyz, rgba);
5690     break;                                       5690     break;
5691   case TOOLS_GL2PS_QUADRANGLE :                  5691   case TOOLS_GL2PS_QUADRANGLE :
5692     tools_gl2psMsg(TOOLS_GL2PS_WARNING, "Ther    5692     tools_gl2psMsg(TOOLS_GL2PS_WARNING, "There should not be any quad left to print");
5693     break;                                       5693     break;
5694   case TOOLS_GL2PS_PIXMAP :                      5694   case TOOLS_GL2PS_PIXMAP :
5695     tools_gl2psPrintSVGPixmap(gl2ps,xyz[0][0]    5695     tools_gl2psPrintSVGPixmap(gl2ps,xyz[0][0], xyz[0][1], prim->data.image);
5696     break;                                       5696     break;
5697   case TOOLS_GL2PS_TEXT :                        5697   case TOOLS_GL2PS_TEXT :
5698     tools_gl2psSVGGetColorString(prim->verts[    5698     tools_gl2psSVGGetColorString(prim->verts[0].rgba, col);
5699     tools_gl2psPrintf(gl2ps,"<text fill=\"%s\    5699     tools_gl2psPrintf(gl2ps,"<text fill=\"%s\" x=\"%g\" y=\"%g\" font-size=\"%d\" ",
5700                 col, xyz[0][0], xyz[0][1], pr    5700                 col, xyz[0][0], xyz[0][1], prim->data.text->fontsize);
5701     if(prim->data.text->angle)                   5701     if(prim->data.text->angle)
5702       tools_gl2psPrintf(gl2ps,"transform=\"ro    5702       tools_gl2psPrintf(gl2ps,"transform=\"rotate(%g, %g, %g)\" ",
5703                   -prim->data.text->angle, xy    5703                   -prim->data.text->angle, xyz[0][0], xyz[0][1]);
5704     switch(prim->data.text->alignment){          5704     switch(prim->data.text->alignment){
5705     case TOOLS_GL2PS_TEXT_C:                     5705     case TOOLS_GL2PS_TEXT_C:
5706       tools_gl2psPrintf(gl2ps,"text-anchor=\"    5706       tools_gl2psPrintf(gl2ps,"text-anchor=\"middle\" dy=\"%d\" ",
5707                   prim->data.text->fontsize /    5707                   prim->data.text->fontsize / 2);
5708       break;                                     5708       break;
5709     case TOOLS_GL2PS_TEXT_CL:                    5709     case TOOLS_GL2PS_TEXT_CL:
5710       tools_gl2psPrintf(gl2ps,"text-anchor=\"    5710       tools_gl2psPrintf(gl2ps,"text-anchor=\"start\" dy=\"%d\" ",
5711                   prim->data.text->fontsize /    5711                   prim->data.text->fontsize / 2);
5712       break;                                     5712       break;
5713     case TOOLS_GL2PS_TEXT_CR:                    5713     case TOOLS_GL2PS_TEXT_CR:
5714       tools_gl2psPrintf(gl2ps,"text-anchor=\"    5714       tools_gl2psPrintf(gl2ps,"text-anchor=\"end\" dy=\"%d\" ",
5715                   prim->data.text->fontsize /    5715                   prim->data.text->fontsize / 2);
5716       break;                                     5716       break;
5717     case TOOLS_GL2PS_TEXT_B:                     5717     case TOOLS_GL2PS_TEXT_B:
5718       tools_gl2psPrintf(gl2ps,"text-anchor=\"    5718       tools_gl2psPrintf(gl2ps,"text-anchor=\"middle\" dy=\"0\" ");
5719       break;                                     5719       break;
5720     case TOOLS_GL2PS_TEXT_BR:                    5720     case TOOLS_GL2PS_TEXT_BR:
5721       tools_gl2psPrintf(gl2ps,"text-anchor=\"    5721       tools_gl2psPrintf(gl2ps,"text-anchor=\"end\" dy=\"0\" ");
5722       break;                                     5722       break;
5723     case TOOLS_GL2PS_TEXT_T:                     5723     case TOOLS_GL2PS_TEXT_T:
5724       tools_gl2psPrintf(gl2ps,"text-anchor=\"    5724       tools_gl2psPrintf(gl2ps,"text-anchor=\"middle\" dy=\"%d\" ",
5725                   prim->data.text->fontsize);    5725                   prim->data.text->fontsize);
5726       break;                                     5726       break;
5727     case TOOLS_GL2PS_TEXT_TL:                    5727     case TOOLS_GL2PS_TEXT_TL:
5728       tools_gl2psPrintf(gl2ps,"text-anchor=\"    5728       tools_gl2psPrintf(gl2ps,"text-anchor=\"start\" dy=\"%d\" ",
5729                   prim->data.text->fontsize);    5729                   prim->data.text->fontsize);
5730       break;                                     5730       break;
5731     case TOOLS_GL2PS_TEXT_TR:                    5731     case TOOLS_GL2PS_TEXT_TR:
5732       tools_gl2psPrintf(gl2ps,"text-anchor=\"    5732       tools_gl2psPrintf(gl2ps,"text-anchor=\"end\" dy=\"%d\" ",
5733                   prim->data.text->fontsize);    5733                   prim->data.text->fontsize);
5734       break;                                     5734       break;
5735     case TOOLS_GL2PS_TEXT_BL:                    5735     case TOOLS_GL2PS_TEXT_BL:
5736     default: /* same as TOOLS_GL2PS_TEXT_BL *    5736     default: /* same as TOOLS_GL2PS_TEXT_BL */
5737       tools_gl2psPrintf(gl2ps,"text-anchor=\"    5737       tools_gl2psPrintf(gl2ps,"text-anchor=\"start\" dy=\"0\" ");
5738       break;                                     5738       break;
5739     }                                            5739     }
5740     if(!strcmp(prim->data.text->fontname, "Ti    5740     if(!strcmp(prim->data.text->fontname, "Times-Roman"))
5741       tools_gl2psPrintf(gl2ps,"font-family=\"    5741       tools_gl2psPrintf(gl2ps,"font-family=\"Times\">");
5742     else if(!strcmp(prim->data.text->fontname    5742     else if(!strcmp(prim->data.text->fontname, "Times-Bold"))
5743       tools_gl2psPrintf(gl2ps,"font-family=\"    5743       tools_gl2psPrintf(gl2ps,"font-family=\"Times\" font-weight=\"bold\">");
5744     else if(!strcmp(prim->data.text->fontname    5744     else if(!strcmp(prim->data.text->fontname, "Times-Italic"))
5745       tools_gl2psPrintf(gl2ps,"font-family=\"    5745       tools_gl2psPrintf(gl2ps,"font-family=\"Times\" font-style=\"italic\">");
5746     else if(!strcmp(prim->data.text->fontname    5746     else if(!strcmp(prim->data.text->fontname, "Times-BoldItalic"))
5747       tools_gl2psPrintf(gl2ps,"font-family=\"    5747       tools_gl2psPrintf(gl2ps,"font-family=\"Times\" font-style=\"italic\" font-weight=\"bold\">");
5748     else if(!strcmp(prim->data.text->fontname    5748     else if(!strcmp(prim->data.text->fontname, "Helvetica-Bold"))
5749       tools_gl2psPrintf(gl2ps,"font-family=\"    5749       tools_gl2psPrintf(gl2ps,"font-family=\"Helvetica\" font-weight=\"bold\">");
5750     else if(!strcmp(prim->data.text->fontname    5750     else if(!strcmp(prim->data.text->fontname, "Helvetica-Oblique"))
5751       tools_gl2psPrintf(gl2ps,"font-family=\"    5751       tools_gl2psPrintf(gl2ps,"font-family=\"Helvetica\" font-style=\"oblique\">");
5752     else if(!strcmp(prim->data.text->fontname    5752     else if(!strcmp(prim->data.text->fontname, "Helvetica-BoldOblique"))
5753       tools_gl2psPrintf(gl2ps,"font-family=\"    5753       tools_gl2psPrintf(gl2ps,"font-family=\"Helvetica\" font-style=\"oblique\" font-weight=\"bold\">");
5754     else if(!strcmp(prim->data.text->fontname    5754     else if(!strcmp(prim->data.text->fontname, "Courier-Bold"))
5755       tools_gl2psPrintf(gl2ps,"font-family=\"    5755       tools_gl2psPrintf(gl2ps,"font-family=\"Courier\" font-weight=\"bold\">");
5756     else if(!strcmp(prim->data.text->fontname    5756     else if(!strcmp(prim->data.text->fontname, "Courier-Oblique"))
5757       tools_gl2psPrintf(gl2ps,"font-family=\"    5757       tools_gl2psPrintf(gl2ps,"font-family=\"Courier\" font-style=\"oblique\">");
5758     else if(!strcmp(prim->data.text->fontname    5758     else if(!strcmp(prim->data.text->fontname, "Courier-BoldOblique"))
5759       tools_gl2psPrintf(gl2ps,"font-family=\"    5759       tools_gl2psPrintf(gl2ps,"font-family=\"Courier\" font-style=\"oblique\" font-weight=\"bold\">");
5760     else                                         5760     else
5761       tools_gl2psPrintf(gl2ps,"font-family=\"    5761       tools_gl2psPrintf(gl2ps,"font-family=\"%s\">", prim->data.text->fontname);
5762     tools_gl2psPrintf(gl2ps,"%s</text>\n", pr    5762     tools_gl2psPrintf(gl2ps,"%s</text>\n", prim->data.text->str);
5763     break;                                       5763     break;
5764   case TOOLS_GL2PS_SPECIAL :                     5764   case TOOLS_GL2PS_SPECIAL :
5765     /* alignment contains the format for whic    5765     /* alignment contains the format for which the special output text
5766        is intended */                            5766        is intended */
5767     if(prim->data.text->alignment == TOOLS_GL    5767     if(prim->data.text->alignment == TOOLS_GL2PS_SVG)
5768       tools_gl2psPrintf(gl2ps,"%s\n", prim->d    5768       tools_gl2psPrintf(gl2ps,"%s\n", prim->data.text->str);
5769     break;                                       5769     break;
5770   default :                                      5770   default :
5771     break;                                       5771     break;
5772   }                                              5772   }
5773 }                                                5773 }
5774                                                  5774 
5775 inline void tools_gl2psPrintSVGFooter(tools_G    5775 inline void tools_gl2psPrintSVGFooter(tools_GL2PScontext* gl2ps)
5776 {                                                5776 {
5777   tools_gl2psPrintf(gl2ps,"</g>\n");             5777   tools_gl2psPrintf(gl2ps,"</g>\n");
5778   tools_gl2psPrintf(gl2ps,"</svg>\n");           5778   tools_gl2psPrintf(gl2ps,"</svg>\n");
5779                                                  5779 
5780   tools_gl2psPrintGzipFooter(gl2ps);             5780   tools_gl2psPrintGzipFooter(gl2ps);
5781 }                                                5781 }
5782                                                  5782 
5783 inline void tools_gl2psPrintSVGBeginViewport(    5783 inline void tools_gl2psPrintSVGBeginViewport(tools_GL2PScontext* gl2ps, tools_GLint viewport[4])
5784 {                                                5784 {
5785   tools_GLint idx;                               5785   tools_GLint idx;
5786   char col[32];                                  5786   char col[32];
5787   tools_GLfloat rgba[4];                         5787   tools_GLfloat rgba[4];
5788   int x = viewport[0], y = viewport[1], w = v    5788   int x = viewport[0], y = viewport[1], w = viewport[2], h = viewport[3];
5789                                                  5789 
5790   tools_glRenderMode(TOOLS_GL_FEEDBACK);         5790   tools_glRenderMode(TOOLS_GL_FEEDBACK);
5791                                                  5791 
5792   tools_gl2psResetLineProperties(gl2ps);         5792   tools_gl2psResetLineProperties(gl2ps);
5793                                                  5793 
5794   if(gl2ps->header){                             5794   if(gl2ps->header){
5795     tools_gl2psPrintSVGHeader(gl2ps);            5795     tools_gl2psPrintSVGHeader(gl2ps);
5796     gl2ps->header = TOOLS_GL_FALSE;              5796     gl2ps->header = TOOLS_GL_FALSE;
5797   }                                              5797   }
5798                                                  5798 
5799   if(gl2ps->options & TOOLS_GL2PS_DRAW_BACKGR    5799   if(gl2ps->options & TOOLS_GL2PS_DRAW_BACKGROUND){
5800     if(gl2ps->colormode == TOOLS_GL_RGBA || g    5800     if(gl2ps->colormode == TOOLS_GL_RGBA || gl2ps->colorsize == 0){
5801       tools_glGetFloatv(TOOLS_GL_COLOR_CLEAR_    5801       tools_glGetFloatv(TOOLS_GL_COLOR_CLEAR_VALUE, rgba);
5802     }                                            5802     }
5803     else{                                        5803     else{
5804       tools_glGetIntegerv(TOOLS_GL_INDEX_CLEA    5804       tools_glGetIntegerv(TOOLS_GL_INDEX_CLEAR_VALUE, &idx);
5805       rgba[0] = gl2ps->colormap[idx][0];         5805       rgba[0] = gl2ps->colormap[idx][0];
5806       rgba[1] = gl2ps->colormap[idx][1];         5806       rgba[1] = gl2ps->colormap[idx][1];
5807       rgba[2] = gl2ps->colormap[idx][2];         5807       rgba[2] = gl2ps->colormap[idx][2];
5808       rgba[3] = 1.0F;                            5808       rgba[3] = 1.0F;
5809     }                                            5809     }
5810     tools_gl2psSVGGetColorString(rgba, col);     5810     tools_gl2psSVGGetColorString(rgba, col);
5811     tools_gl2psPrintf(gl2ps,"<polygon fill=\"    5811     tools_gl2psPrintf(gl2ps,"<polygon fill=\"%s\" points=\"%d,%d %d,%d %d,%d %d,%d\" ", col,
5812                 x, gl2ps->viewport[3] - y,       5812                 x, gl2ps->viewport[3] - y,
5813                 x + w, gl2ps->viewport[3] - y    5813                 x + w, gl2ps->viewport[3] - y,
5814                 x + w, gl2ps->viewport[3] - (    5814                 x + w, gl2ps->viewport[3] - (y + h),
5815                 x, gl2ps->viewport[3] - (y +     5815                 x, gl2ps->viewport[3] - (y + h));
5816     tools_gl2psPrintf(gl2ps,"shape-rendering=    5816     tools_gl2psPrintf(gl2ps,"shape-rendering=\"crispEdges\"/>\n");
5817   }                                              5817   }
5818                                                  5818 
5819   tools_gl2psPrintf(gl2ps,"<clipPath id=\"cp%    5819   tools_gl2psPrintf(gl2ps,"<clipPath id=\"cp%d%d%d%d\">\n", x, y, w, h);
5820   tools_gl2psPrintf(gl2ps,"  <polygon points=    5820   tools_gl2psPrintf(gl2ps,"  <polygon points=\"%d,%d %d,%d %d,%d %d,%d\"/>\n",
5821               x, gl2ps->viewport[3] - y,         5821               x, gl2ps->viewport[3] - y,
5822               x + w, gl2ps->viewport[3] - y,     5822               x + w, gl2ps->viewport[3] - y,
5823               x + w, gl2ps->viewport[3] - (y     5823               x + w, gl2ps->viewport[3] - (y + h),
5824               x, gl2ps->viewport[3] - (y + h)    5824               x, gl2ps->viewport[3] - (y + h));
5825   tools_gl2psPrintf(gl2ps,"</clipPath>\n");      5825   tools_gl2psPrintf(gl2ps,"</clipPath>\n");
5826   tools_gl2psPrintf(gl2ps,"<g clip-path=\"url    5826   tools_gl2psPrintf(gl2ps,"<g clip-path=\"url(#cp%d%d%d%d)\">\n", x, y, w, h);
5827 }                                                5827 }
5828                                                  5828 
5829 inline tools_GLint tools_gl2psPrintSVGEndView    5829 inline tools_GLint tools_gl2psPrintSVGEndViewport(tools_GL2PScontext* gl2ps)
5830 {                                                5830 {
5831   tools_GLint res;                               5831   tools_GLint res;
5832                                                  5832 
5833   res = tools_gl2psPrintPrimitives(gl2ps);       5833   res = tools_gl2psPrintPrimitives(gl2ps);
5834   tools_gl2psPrintf(gl2ps,"</g>\n");             5834   tools_gl2psPrintf(gl2ps,"</g>\n");
5835   return res;                                    5835   return res;
5836 }                                                5836 }
5837                                                  5837 
5838 inline void tools_gl2psPrintSVGFinalPrimitive    5838 inline void tools_gl2psPrintSVGFinalPrimitive(tools_GL2PScontext* gl2ps)
5839 {                                                5839 {
5840   /* End any remaining line, if any */           5840   /* End any remaining line, if any */
5841   tools_gl2psEndSVGLine(gl2ps);                  5841   tools_gl2psEndSVGLine(gl2ps);
5842 }                                                5842 }
5843                                                  5843 
5844 /* definition of the SVG backend */              5844 /* definition of the SVG backend */
5845                                                  5845 
5846 static const tools_GL2PSbackend tools_gl2psSV    5846 static const tools_GL2PSbackend tools_gl2psSVG = {
5847   tools_gl2psPrintSVGHeader,                     5847   tools_gl2psPrintSVGHeader,
5848   tools_gl2psPrintSVGFooter,                     5848   tools_gl2psPrintSVGFooter,
5849   tools_gl2psPrintSVGBeginViewport,              5849   tools_gl2psPrintSVGBeginViewport,
5850   tools_gl2psPrintSVGEndViewport,                5850   tools_gl2psPrintSVGEndViewport,
5851   tools_gl2psPrintSVGPrimitive,                  5851   tools_gl2psPrintSVGPrimitive,
5852   tools_gl2psPrintSVGFinalPrimitive,             5852   tools_gl2psPrintSVGFinalPrimitive,
5853   "svg",                                         5853   "svg",
5854   "Scalable Vector Graphics"                     5854   "Scalable Vector Graphics"
5855 };                                               5855 };
5856                                                  5856 
5857 /********************************************    5857 /*********************************************************************
5858  *                                               5858  *
5859  * PGF routines                                  5859  * PGF routines
5860  *                                               5860  *
5861  ********************************************    5861  *********************************************************************/
5862                                                  5862 
5863 inline void tools_gl2psPrintPGFColor(tools_GL    5863 inline void tools_gl2psPrintPGFColor(tools_GL2PScontext* gl2ps, tools_GL2PSrgba rgba)
5864 {                                                5864 {
5865   if(!tools_gl2psSameColor(gl2ps->lastrgba, r    5865   if(!tools_gl2psSameColor(gl2ps->lastrgba, rgba)){
5866     tools_gl2psSetLastColor(gl2ps, rgba);        5866     tools_gl2psSetLastColor(gl2ps, rgba);
5867     fprintf(gl2ps->stream, "\\color[rgb]{%f,%    5867     fprintf(gl2ps->stream, "\\color[rgb]{%f,%f,%f}\n", rgba[0], rgba[1], rgba[2]);
5868   }                                              5868   }
5869 }                                                5869 }
5870                                                  5870 
5871 inline void tools_gl2psPrintPGFHeader(tools_G    5871 inline void tools_gl2psPrintPGFHeader(tools_GL2PScontext* gl2ps)
5872 {                                                5872 {
5873   time_t now;                                    5873   time_t now;
5874                                                  5874 
5875   time(&now);                                    5875   time(&now);
5876                                                  5876 
5877   fprintf(gl2ps->stream,                         5877   fprintf(gl2ps->stream,
5878           "%% Title: %s\n"                       5878           "%% Title: %s\n"
5879           "%% Creator: GL2PS %d.%d.%d%s, %s\n    5879           "%% Creator: GL2PS %d.%d.%d%s, %s\n"
5880           "%% For: %s\n"                         5880           "%% For: %s\n"
5881           "%% CreationDate: %s",                 5881           "%% CreationDate: %s",
5882           gl2ps->title, TOOLS_GL2PS_MAJOR_VER    5882           gl2ps->title, TOOLS_GL2PS_MAJOR_VERSION, TOOLS_GL2PS_MINOR_VERSION,
5883           TOOLS_GL2PS_PATCH_VERSION, TOOLS_GL    5883           TOOLS_GL2PS_PATCH_VERSION, TOOLS_GL2PS_EXTRA_VERSION, TOOLS_GL2PS_COPYRIGHT,
5884           gl2ps->producer, ctime(&now));         5884           gl2ps->producer, ctime(&now));
5885                                                  5885 
5886   fprintf(gl2ps->stream, "\\begin{pgfpicture}    5886   fprintf(gl2ps->stream, "\\begin{pgfpicture}\n");
5887   if(gl2ps->options & TOOLS_GL2PS_DRAW_BACKGR    5887   if(gl2ps->options & TOOLS_GL2PS_DRAW_BACKGROUND){
5888     tools_gl2psPrintPGFColor(gl2ps, gl2ps->bg    5888     tools_gl2psPrintPGFColor(gl2ps, gl2ps->bgcolor);
5889     fprintf(gl2ps->stream,                       5889     fprintf(gl2ps->stream,
5890             "\\pgfpathrectanglecorners{"         5890             "\\pgfpathrectanglecorners{"
5891             "\\pgfpoint{%dpt}{%dpt}}{\\pgfpoi    5891             "\\pgfpoint{%dpt}{%dpt}}{\\pgfpoint{%dpt}{%dpt}}\n"
5892             "\\pgfusepath{fill}\n",              5892             "\\pgfusepath{fill}\n",
5893             (int)gl2ps->viewport[0], (int)gl2    5893             (int)gl2ps->viewport[0], (int)gl2ps->viewport[1],
5894             (int)gl2ps->viewport[2], (int)gl2    5894             (int)gl2ps->viewport[2], (int)gl2ps->viewport[3]);
5895   }                                              5895   }
5896 }                                                5896 }
5897                                                  5897 
5898 inline void tools_gl2psPrintPGFDash(tools_GL2    5898 inline void tools_gl2psPrintPGFDash(tools_GL2PScontext* gl2ps, tools_GLushort pattern, tools_GLint factor)
5899 {                                                5899 {
5900   int i, n, array[10];                           5900   int i, n, array[10];
5901                                                  5901 
5902   if(pattern == gl2ps->lastpattern && factor     5902   if(pattern == gl2ps->lastpattern && factor == gl2ps->lastfactor)
5903     return;                                      5903     return;
5904                                                  5904 
5905   gl2ps->lastpattern = pattern;                  5905   gl2ps->lastpattern = pattern;
5906   gl2ps->lastfactor = factor;                    5906   gl2ps->lastfactor = factor;
5907                                                  5907 
5908   if(!pattern || !factor){                       5908   if(!pattern || !factor){
5909     /* solid line */                             5909     /* solid line */
5910     fprintf(gl2ps->stream, "\\pgfsetdash{}{0p    5910     fprintf(gl2ps->stream, "\\pgfsetdash{}{0pt}\n");
5911   }                                              5911   }
5912   else{                                          5912   else{
5913     tools_gl2psParseStipplePattern(pattern, f    5913     tools_gl2psParseStipplePattern(pattern, factor, &n, array);
5914     fprintf(gl2ps->stream, "\\pgfsetdash{");     5914     fprintf(gl2ps->stream, "\\pgfsetdash{");
5915     for(i = 0; i < n; i++) fprintf(gl2ps->str    5915     for(i = 0; i < n; i++) fprintf(gl2ps->stream, "{%dpt}", array[i]);
5916     fprintf(gl2ps->stream, "}{0pt}\n");          5916     fprintf(gl2ps->stream, "}{0pt}\n");
5917   }                                              5917   }
5918 }                                                5918 }
5919                                                  5919 
5920 inline const char *tools_gl2psPGFTextAlignmen    5920 inline const char *tools_gl2psPGFTextAlignment(int align)
5921 {                                                5921 {
5922   switch(align){                                 5922   switch(align){
5923   case TOOLS_GL2PS_TEXT_C  : return "center";    5923   case TOOLS_GL2PS_TEXT_C  : return "center";
5924   case TOOLS_GL2PS_TEXT_CL : return "west";      5924   case TOOLS_GL2PS_TEXT_CL : return "west";
5925   case TOOLS_GL2PS_TEXT_CR : return "east";      5925   case TOOLS_GL2PS_TEXT_CR : return "east";
5926   case TOOLS_GL2PS_TEXT_B  : return "south";     5926   case TOOLS_GL2PS_TEXT_B  : return "south";
5927   case TOOLS_GL2PS_TEXT_BR : return "south ea    5927   case TOOLS_GL2PS_TEXT_BR : return "south east";
5928   case TOOLS_GL2PS_TEXT_T  : return "north";     5928   case TOOLS_GL2PS_TEXT_T  : return "north";
5929   case TOOLS_GL2PS_TEXT_TL : return "north we    5929   case TOOLS_GL2PS_TEXT_TL : return "north west";
5930   case TOOLS_GL2PS_TEXT_TR : return "north ea    5930   case TOOLS_GL2PS_TEXT_TR : return "north east";
5931   case TOOLS_GL2PS_TEXT_BL :                     5931   case TOOLS_GL2PS_TEXT_BL :
5932   default            : return "south west";      5932   default            : return "south west";
5933   }                                              5933   }
5934 }                                                5934 }
5935                                                  5935 
5936 inline void tools_gl2psPrintPGFPrimitive(tool    5936 inline void tools_gl2psPrintPGFPrimitive(tools_GL2PScontext* gl2ps, void *data)
5937 {                                                5937 {
5938   tools_GL2PSprimitive *prim;                    5938   tools_GL2PSprimitive *prim;
5939                                                  5939 
5940   prim = *(tools_GL2PSprimitive**)data;          5940   prim = *(tools_GL2PSprimitive**)data;
5941                                                  5941 
5942   switch(prim->type){                            5942   switch(prim->type){
5943   case TOOLS_GL2PS_POINT :                       5943   case TOOLS_GL2PS_POINT :
5944     /* Points in openGL are rectangular */       5944     /* Points in openGL are rectangular */
5945     tools_gl2psPrintPGFColor(gl2ps, prim->ver    5945     tools_gl2psPrintPGFColor(gl2ps, prim->verts[0].rgba);
5946     fprintf(gl2ps->stream,                       5946     fprintf(gl2ps->stream,
5947             "\\pgfpathrectangle{\\pgfpoint{%f    5947             "\\pgfpathrectangle{\\pgfpoint{%fpt}{%fpt}}"
5948             "{\\pgfpoint{%fpt}{%fpt}}\n\\pgfu    5948             "{\\pgfpoint{%fpt}{%fpt}}\n\\pgfusepath{fill}\n",
5949             prim->verts[0].xyz[0]-0.5*prim->w    5949             prim->verts[0].xyz[0]-0.5*prim->width,
5950             prim->verts[0].xyz[1]-0.5*prim->w    5950             prim->verts[0].xyz[1]-0.5*prim->width,
5951             prim->width,prim->width);            5951             prim->width,prim->width);
5952     break;                                       5952     break;
5953   case TOOLS_GL2PS_LINE :                        5953   case TOOLS_GL2PS_LINE :
5954     tools_gl2psPrintPGFColor(gl2ps, prim->ver    5954     tools_gl2psPrintPGFColor(gl2ps, prim->verts[0].rgba);
5955     if(gl2ps->lastlinewidth != prim->width){     5955     if(gl2ps->lastlinewidth != prim->width){
5956       gl2ps->lastlinewidth = prim->width;        5956       gl2ps->lastlinewidth = prim->width;
5957       fprintf(gl2ps->stream, "\\pgfsetlinewid    5957       fprintf(gl2ps->stream, "\\pgfsetlinewidth{%fpt}\n", gl2ps->lastlinewidth);
5958     }                                            5958     }
5959     if(gl2ps->lastlinecap != prim->linecap){     5959     if(gl2ps->lastlinecap != prim->linecap){
5960       gl2ps->lastlinecap = prim->linecap;        5960       gl2ps->lastlinecap = prim->linecap;
5961       switch (prim->linecap){                    5961       switch (prim->linecap){
5962       case TOOLS_GL2PS_LINE_CAP_BUTT:            5962       case TOOLS_GL2PS_LINE_CAP_BUTT:
5963         fprintf(gl2ps->stream, "\\pgfset%s\n"    5963         fprintf(gl2ps->stream, "\\pgfset%s\n", "buttcap");
5964         break;                                   5964         break;
5965       case TOOLS_GL2PS_LINE_CAP_ROUND:           5965       case TOOLS_GL2PS_LINE_CAP_ROUND:
5966         fprintf(gl2ps->stream, "\\pgfset%s\n"    5966         fprintf(gl2ps->stream, "\\pgfset%s\n", "roundcap");
5967         break;                                   5967         break;
5968       case TOOLS_GL2PS_LINE_CAP_SQUARE:          5968       case TOOLS_GL2PS_LINE_CAP_SQUARE:
5969         fprintf(gl2ps->stream, "\\pgfset%s\n"    5969         fprintf(gl2ps->stream, "\\pgfset%s\n", "rectcap");
5970         break;                                   5970         break;
5971       }                                          5971       }
5972     }                                            5972     }
5973     if(gl2ps->lastlinejoin != prim->linejoin)    5973     if(gl2ps->lastlinejoin != prim->linejoin){
5974       gl2ps->lastlinejoin = prim->linejoin;      5974       gl2ps->lastlinejoin = prim->linejoin;
5975       switch (prim->linejoin){                   5975       switch (prim->linejoin){
5976       case TOOLS_GL2PS_LINE_JOIN_MITER:          5976       case TOOLS_GL2PS_LINE_JOIN_MITER:
5977         fprintf(gl2ps->stream, "\\pgfset%s\n"    5977         fprintf(gl2ps->stream, "\\pgfset%s\n", "miterjoin");
5978         break;                                   5978         break;
5979       case TOOLS_GL2PS_LINE_JOIN_ROUND:          5979       case TOOLS_GL2PS_LINE_JOIN_ROUND:
5980         fprintf(gl2ps->stream, "\\pgfset%s\n"    5980         fprintf(gl2ps->stream, "\\pgfset%s\n", "roundjoin");
5981         break;                                   5981         break;
5982       case TOOLS_GL2PS_LINE_JOIN_BEVEL:          5982       case TOOLS_GL2PS_LINE_JOIN_BEVEL:
5983         fprintf(gl2ps->stream, "\\pgfset%s\n"    5983         fprintf(gl2ps->stream, "\\pgfset%s\n", "beveljoin");
5984         break;                                   5984         break;
5985       }                                          5985       }
5986     }                                            5986     }
5987     tools_gl2psPrintPGFDash(gl2ps, prim->patt    5987     tools_gl2psPrintPGFDash(gl2ps, prim->pattern, prim->factor);
5988     fprintf(gl2ps->stream,                       5988     fprintf(gl2ps->stream,
5989             "\\pgfpathmoveto{\\pgfpoint{%fpt}    5989             "\\pgfpathmoveto{\\pgfpoint{%fpt}{%fpt}}\n"
5990             "\\pgflineto{\\pgfpoint{%fpt}{%fp    5990             "\\pgflineto{\\pgfpoint{%fpt}{%fpt}}\n"
5991             "\\pgfusepath{stroke}\n",            5991             "\\pgfusepath{stroke}\n",
5992             prim->verts[1].xyz[0], prim->vert    5992             prim->verts[1].xyz[0], prim->verts[1].xyz[1],
5993             prim->verts[0].xyz[0], prim->vert    5993             prim->verts[0].xyz[0], prim->verts[0].xyz[1]);
5994     break;                                       5994     break;
5995   case TOOLS_GL2PS_TRIANGLE :                    5995   case TOOLS_GL2PS_TRIANGLE :
5996     if(gl2ps->lastlinewidth != 0){               5996     if(gl2ps->lastlinewidth != 0){
5997       gl2ps->lastlinewidth = 0;                  5997       gl2ps->lastlinewidth = 0;
5998       fprintf(gl2ps->stream, "\\pgfsetlinewid    5998       fprintf(gl2ps->stream, "\\pgfsetlinewidth{0.01pt}\n");
5999     }                                            5999     }
6000     if(gl2ps->lastlinecap != prim->linecap){     6000     if(gl2ps->lastlinecap != prim->linecap){
6001       gl2ps->lastlinecap = prim->linecap;        6001       gl2ps->lastlinecap = prim->linecap;
6002       switch (prim->linecap){                    6002       switch (prim->linecap){
6003       case TOOLS_GL2PS_LINE_CAP_BUTT:            6003       case TOOLS_GL2PS_LINE_CAP_BUTT:
6004         fprintf(gl2ps->stream, "\\pgfset%s\n"    6004         fprintf(gl2ps->stream, "\\pgfset%s\n", "buttcap");
6005         break;                                   6005         break;
6006       case TOOLS_GL2PS_LINE_CAP_ROUND:           6006       case TOOLS_GL2PS_LINE_CAP_ROUND:
6007         fprintf(gl2ps->stream, "\\pgfset%s\n"    6007         fprintf(gl2ps->stream, "\\pgfset%s\n", "roundcap");
6008         break;                                   6008         break;
6009       case TOOLS_GL2PS_LINE_CAP_SQUARE:          6009       case TOOLS_GL2PS_LINE_CAP_SQUARE:
6010         fprintf(gl2ps->stream, "\\pgfset%s\n"    6010         fprintf(gl2ps->stream, "\\pgfset%s\n", "rectcap");
6011         break;                                   6011         break;
6012       }                                          6012       }
6013     }                                            6013     }
6014     if(gl2ps->lastlinejoin != prim->linejoin)    6014     if(gl2ps->lastlinejoin != prim->linejoin){
6015       gl2ps->lastlinejoin = prim->linejoin;      6015       gl2ps->lastlinejoin = prim->linejoin;
6016       switch (prim->linejoin){                   6016       switch (prim->linejoin){
6017       case TOOLS_GL2PS_LINE_JOIN_MITER:          6017       case TOOLS_GL2PS_LINE_JOIN_MITER:
6018         fprintf(gl2ps->stream, "\\pgfset%s\n"    6018         fprintf(gl2ps->stream, "\\pgfset%s\n", "miterjoin");
6019         break;                                   6019         break;
6020       case TOOLS_GL2PS_LINE_JOIN_ROUND:          6020       case TOOLS_GL2PS_LINE_JOIN_ROUND:
6021         fprintf(gl2ps->stream, "\\pgfset%s\n"    6021         fprintf(gl2ps->stream, "\\pgfset%s\n", "roundjoin");
6022         break;                                   6022         break;
6023       case TOOLS_GL2PS_LINE_JOIN_BEVEL:          6023       case TOOLS_GL2PS_LINE_JOIN_BEVEL:
6024         fprintf(gl2ps->stream, "\\pgfset%s\n"    6024         fprintf(gl2ps->stream, "\\pgfset%s\n", "beveljoin");
6025         break;                                   6025         break;
6026       }                                          6026       }
6027     }                                            6027     }
6028     tools_gl2psPrintPGFColor(gl2ps, prim->ver    6028     tools_gl2psPrintPGFColor(gl2ps, prim->verts[0].rgba);
6029     fprintf(gl2ps->stream,                       6029     fprintf(gl2ps->stream,
6030             "\\pgfpathmoveto{\\pgfpoint{%fpt}    6030             "\\pgfpathmoveto{\\pgfpoint{%fpt}{%fpt}}\n"
6031             "\\pgflineto{\\pgfpoint{%fpt}{%fp    6031             "\\pgflineto{\\pgfpoint{%fpt}{%fpt}}\n"
6032             "\\pgflineto{\\pgfpoint{%fpt}{%fp    6032             "\\pgflineto{\\pgfpoint{%fpt}{%fpt}}\n"
6033             "\\pgfpathclose\n"                   6033             "\\pgfpathclose\n"
6034             "\\pgfusepath{fill,stroke}\n",       6034             "\\pgfusepath{fill,stroke}\n",
6035             prim->verts[2].xyz[0], prim->vert    6035             prim->verts[2].xyz[0], prim->verts[2].xyz[1],
6036             prim->verts[1].xyz[0], prim->vert    6036             prim->verts[1].xyz[0], prim->verts[1].xyz[1],
6037             prim->verts[0].xyz[0], prim->vert    6037             prim->verts[0].xyz[0], prim->verts[0].xyz[1]);
6038     break;                                       6038     break;
6039   case TOOLS_GL2PS_TEXT :                        6039   case TOOLS_GL2PS_TEXT :
6040     fprintf(gl2ps->stream, "{\n\\pgftransform    6040     fprintf(gl2ps->stream, "{\n\\pgftransformshift{\\pgfpoint{%fpt}{%fpt}}\n",
6041             prim->verts[0].xyz[0], prim->vert    6041             prim->verts[0].xyz[0], prim->verts[0].xyz[1]);
6042                                                  6042 
6043     if(prim->data.text->angle)                   6043     if(prim->data.text->angle)
6044       fprintf(gl2ps->stream, "\\pgftransformr    6044       fprintf(gl2ps->stream, "\\pgftransformrotate{%f}{", prim->data.text->angle);
6045                                                  6045 
6046     fprintf(gl2ps->stream, "\\pgfnode{rectang    6046     fprintf(gl2ps->stream, "\\pgfnode{rectangle}{%s}{\\fontsize{%d}{0}\\selectfont",
6047             tools_gl2psPGFTextAlignment(prim-    6047             tools_gl2psPGFTextAlignment(prim->data.text->alignment),
6048             prim->data.text->fontsize);          6048             prim->data.text->fontsize);
6049                                                  6049 
6050     fprintf(gl2ps->stream, "\\textcolor[rgb]{    6050     fprintf(gl2ps->stream, "\\textcolor[rgb]{%g,%g,%g}{{%s}}",
6051             prim->verts[0].rgba[0], prim->ver    6051             prim->verts[0].rgba[0], prim->verts[0].rgba[1],
6052             prim->verts[0].rgba[2], prim->dat    6052             prim->verts[0].rgba[2], prim->data.text->str);
6053                                                  6053 
6054     fprintf(gl2ps->stream, "}{}{\\pgfusepath{    6054     fprintf(gl2ps->stream, "}{}{\\pgfusepath{discard}}");
6055                                                  6055 
6056     if(prim->data.text->angle)                   6056     if(prim->data.text->angle)
6057        fprintf(gl2ps->stream, "}");              6057        fprintf(gl2ps->stream, "}");
6058                                                  6058 
6059     fprintf(gl2ps->stream, "\n}\n");             6059     fprintf(gl2ps->stream, "\n}\n");
6060     break;                                       6060     break;
6061   case TOOLS_GL2PS_SPECIAL :                     6061   case TOOLS_GL2PS_SPECIAL :
6062     /* alignment contains the format for whic    6062     /* alignment contains the format for which the special output text
6063        is intended */                            6063        is intended */
6064     if (prim->data.text->alignment == TOOLS_G    6064     if (prim->data.text->alignment == TOOLS_GL2PS_PGF)
6065       fprintf(gl2ps->stream, "%s\n", prim->da    6065       fprintf(gl2ps->stream, "%s\n", prim->data.text->str);
6066     break;                                       6066     break;
6067   default :                                      6067   default :
6068     break;                                       6068     break;
6069   }                                              6069   }
6070 }                                                6070 }
6071                                                  6071 
6072 inline void tools_gl2psPrintPGFFooter(tools_G    6072 inline void tools_gl2psPrintPGFFooter(tools_GL2PScontext* gl2ps)
6073 {                                                6073 {
6074   fprintf(gl2ps->stream, "\\end{pgfpicture}\n    6074   fprintf(gl2ps->stream, "\\end{pgfpicture}\n");
6075 }                                                6075 }
6076                                                  6076 
6077 inline void tools_gl2psPrintPGFBeginViewport(    6077 inline void tools_gl2psPrintPGFBeginViewport(tools_GL2PScontext* gl2ps, tools_GLint viewport[4])
6078 {                                                6078 {
6079   tools_GLint idx;                               6079   tools_GLint idx;
6080   tools_GLfloat rgba[4];                         6080   tools_GLfloat rgba[4];
6081   int x = viewport[0], y = viewport[1], w = v    6081   int x = viewport[0], y = viewport[1], w = viewport[2], h = viewport[3];
6082                                                  6082 
6083   tools_glRenderMode(TOOLS_GL_FEEDBACK);         6083   tools_glRenderMode(TOOLS_GL_FEEDBACK);
6084                                                  6084 
6085   tools_gl2psResetLineProperties(gl2ps);         6085   tools_gl2psResetLineProperties(gl2ps);
6086                                                  6086 
6087   if(gl2ps->header){                             6087   if(gl2ps->header){
6088     tools_gl2psPrintPGFHeader(gl2ps);            6088     tools_gl2psPrintPGFHeader(gl2ps);
6089     gl2ps->header = TOOLS_GL_FALSE;              6089     gl2ps->header = TOOLS_GL_FALSE;
6090   }                                              6090   }
6091                                                  6091 
6092   fprintf(gl2ps->stream, "\\begin{pgfscope}\n    6092   fprintf(gl2ps->stream, "\\begin{pgfscope}\n");
6093   if(gl2ps->options & TOOLS_GL2PS_DRAW_BACKGR    6093   if(gl2ps->options & TOOLS_GL2PS_DRAW_BACKGROUND){
6094     if(gl2ps->colormode == TOOLS_GL_RGBA || g    6094     if(gl2ps->colormode == TOOLS_GL_RGBA || gl2ps->colorsize == 0){
6095       tools_glGetFloatv(TOOLS_GL_COLOR_CLEAR_    6095       tools_glGetFloatv(TOOLS_GL_COLOR_CLEAR_VALUE, rgba);
6096     }                                            6096     }
6097     else{                                        6097     else{
6098       tools_glGetIntegerv(TOOLS_GL_INDEX_CLEA    6098       tools_glGetIntegerv(TOOLS_GL_INDEX_CLEAR_VALUE, &idx);
6099       rgba[0] = gl2ps->colormap[idx][0];         6099       rgba[0] = gl2ps->colormap[idx][0];
6100       rgba[1] = gl2ps->colormap[idx][1];         6100       rgba[1] = gl2ps->colormap[idx][1];
6101       rgba[2] = gl2ps->colormap[idx][2];         6101       rgba[2] = gl2ps->colormap[idx][2];
6102       rgba[3] = 1.0F;                            6102       rgba[3] = 1.0F;
6103     }                                            6103     }
6104     tools_gl2psPrintPGFColor(gl2ps, rgba);       6104     tools_gl2psPrintPGFColor(gl2ps, rgba);
6105     fprintf(gl2ps->stream,                       6105     fprintf(gl2ps->stream,
6106             "\\pgfpathrectangle{\\pgfpoint{%d    6106             "\\pgfpathrectangle{\\pgfpoint{%dpt}{%dpt}}"
6107             "{\\pgfpoint{%dpt}{%dpt}}\n"         6107             "{\\pgfpoint{%dpt}{%dpt}}\n"
6108             "\\pgfusepath{fill}\n",              6108             "\\pgfusepath{fill}\n",
6109             x, y, w, h);                         6109             x, y, w, h);
6110   }                                              6110   }
6111                                                  6111 
6112   fprintf(gl2ps->stream,                         6112   fprintf(gl2ps->stream,
6113           "\\pgfpathrectangle{\\pgfpoint{%dpt    6113           "\\pgfpathrectangle{\\pgfpoint{%dpt}{%dpt}}"
6114           "{\\pgfpoint{%dpt}{%dpt}}\n"           6114           "{\\pgfpoint{%dpt}{%dpt}}\n"
6115           "\\pgfusepath{clip}\n",                6115           "\\pgfusepath{clip}\n",
6116           x, y, w, h);                           6116           x, y, w, h);
6117 }                                                6117 }
6118                                                  6118 
6119 inline tools_GLint tools_gl2psPrintPGFEndView    6119 inline tools_GLint tools_gl2psPrintPGFEndViewport(tools_GL2PScontext* gl2ps)
6120 {                                                6120 {
6121   tools_GLint res;                               6121   tools_GLint res;
6122   res = tools_gl2psPrintPrimitives(gl2ps);       6122   res = tools_gl2psPrintPrimitives(gl2ps);
6123   fprintf(gl2ps->stream, "\\end{pgfscope}\n")    6123   fprintf(gl2ps->stream, "\\end{pgfscope}\n");
6124   return res;                                    6124   return res;
6125 }                                                6125 }
6126                                                  6126 
6127 inline void tools_gl2psPrintPGFFinalPrimitive    6127 inline void tools_gl2psPrintPGFFinalPrimitive(tools_GL2PScontext*)
6128 {                                                6128 {
6129 }                                                6129 }
6130                                                  6130 
6131 /* definition of the PGF backend */              6131 /* definition of the PGF backend */
6132                                                  6132 
6133 static const tools_GL2PSbackend tools_gl2psPG    6133 static const tools_GL2PSbackend tools_gl2psPGF = {
6134   tools_gl2psPrintPGFHeader,                     6134   tools_gl2psPrintPGFHeader,
6135   tools_gl2psPrintPGFFooter,                     6135   tools_gl2psPrintPGFFooter,
6136   tools_gl2psPrintPGFBeginViewport,              6136   tools_gl2psPrintPGFBeginViewport,
6137   tools_gl2psPrintPGFEndViewport,                6137   tools_gl2psPrintPGFEndViewport,
6138   tools_gl2psPrintPGFPrimitive,                  6138   tools_gl2psPrintPGFPrimitive,
6139   tools_gl2psPrintPGFFinalPrimitive,             6139   tools_gl2psPrintPGFFinalPrimitive,
6140   "tex",                                         6140   "tex",
6141   "PGF Latex Graphics"                           6141   "PGF Latex Graphics"
6142 };                                               6142 };
6143                                                  6143 
6144 /********************************************    6144 /*********************************************************************
6145  *                                               6145  *
6146  * General primitive printing routine            6146  * General primitive printing routine
6147  *                                               6147  *
6148  ********************************************    6148  *********************************************************************/
6149                                                  6149 
6150 /* Warning: the ordering of the backends must    6150 /* Warning: the ordering of the backends must match the format
6151    #defines in gl2ps.h */                        6151    #defines in gl2ps.h */
6152                                                  6152 
6153 static const tools_GL2PSbackend *tools_gl2psb    6153 static const tools_GL2PSbackend *tools_gl2psbackends[] = {
6154   &tools_gl2psPS,  /* 0 */                       6154   &tools_gl2psPS,  /* 0 */
6155   &tools_gl2psEPS, /* 1 */                       6155   &tools_gl2psEPS, /* 1 */
6156   &tools_gl2psTEX, /* 2 */                       6156   &tools_gl2psTEX, /* 2 */
6157   &tools_gl2psPDF, /* 3 */                       6157   &tools_gl2psPDF, /* 3 */
6158   &tools_gl2psSVG, /* 4 */                       6158   &tools_gl2psSVG, /* 4 */
6159   &tools_gl2psPGF  /* 5 */                       6159   &tools_gl2psPGF  /* 5 */
6160 };                                               6160 };
6161                                                  6161 
6162 inline void tools_gl2psComputeTightBoundingBo    6162 inline void tools_gl2psComputeTightBoundingBox(tools_GL2PScontext* gl2ps, void *data)
6163 {                                                6163 {
6164   tools_GL2PSprimitive *prim;                    6164   tools_GL2PSprimitive *prim;
6165   int i;                                         6165   int i;
6166                                                  6166 
6167   prim = *(tools_GL2PSprimitive**)data;          6167   prim = *(tools_GL2PSprimitive**)data;
6168                                                  6168 
6169   for(i = 0; i < prim->numverts; i++){           6169   for(i = 0; i < prim->numverts; i++){
6170     if(prim->verts[i].xyz[0] < gl2ps->viewpor    6170     if(prim->verts[i].xyz[0] < gl2ps->viewport[0])
6171       gl2ps->viewport[0] = (tools_GLint)prim-    6171       gl2ps->viewport[0] = (tools_GLint)prim->verts[i].xyz[0];
6172     if(prim->verts[i].xyz[0] > gl2ps->viewpor    6172     if(prim->verts[i].xyz[0] > gl2ps->viewport[2])
6173       gl2ps->viewport[2] = (tools_GLint)(prim    6173       gl2ps->viewport[2] = (tools_GLint)(prim->verts[i].xyz[0] + 0.5F);
6174     if(prim->verts[i].xyz[1] < gl2ps->viewpor    6174     if(prim->verts[i].xyz[1] < gl2ps->viewport[1])
6175       gl2ps->viewport[1] = (tools_GLint)prim-    6175       gl2ps->viewport[1] = (tools_GLint)prim->verts[i].xyz[1];
6176     if(prim->verts[i].xyz[1] > gl2ps->viewpor    6176     if(prim->verts[i].xyz[1] > gl2ps->viewport[3])
6177       gl2ps->viewport[3] = (tools_GLint)(prim    6177       gl2ps->viewport[3] = (tools_GLint)(prim->verts[i].xyz[1] + 0.5F);
6178   }                                              6178   }
6179 }                                                6179 }
6180                                                  6180 
6181 inline tools_GLint tools_gl2psPrintPrimitives    6181 inline tools_GLint tools_gl2psPrintPrimitives(tools_GL2PScontext* gl2ps)
6182 {                                                6182 {
6183   tools_GL2PSbsptree *root;                      6183   tools_GL2PSbsptree *root;
6184   tools_GL2PSxyz eye = {0.0F, 0.0F, 100.0F *     6184   tools_GL2PSxyz eye = {0.0F, 0.0F, 100.0F * TOOLS_GL2PS_ZSCALE};
6185   tools_GLint used = 0;                          6185   tools_GLint used = 0;
6186                                                  6186 
6187   if ((gl2ps->options & TOOLS_GL2PS_NO_OPENGL    6187   if ((gl2ps->options & TOOLS_GL2PS_NO_OPENGL_CONTEXT) == TOOLS_GL2PS_NONE) {
6188     used = tools_glRenderMode(TOOLS_GL_RENDER    6188     used = tools_glRenderMode(TOOLS_GL_RENDER);
6189   }                                              6189   }
6190                                                  6190 
6191   if(used < 0){                                  6191   if(used < 0){
6192     tools_gl2psMsg(TOOLS_GL2PS_INFO, "OpenGL     6192     tools_gl2psMsg(TOOLS_GL2PS_INFO, "OpenGL feedback buffer overflow");
6193     return TOOLS_GL2PS_OVERFLOW;                 6193     return TOOLS_GL2PS_OVERFLOW;
6194   }                                              6194   }
6195                                                  6195 
6196   if(used > 0)                                   6196   if(used > 0)
6197     tools_gl2psParseFeedbackBuffer(gl2ps, use    6197     tools_gl2psParseFeedbackBuffer(gl2ps, used);
6198                                                  6198 
6199   tools_gl2psRescaleAndOffset(gl2ps);            6199   tools_gl2psRescaleAndOffset(gl2ps);
6200                                                  6200 
6201   if(gl2ps->header){                             6201   if(gl2ps->header){
6202     if(tools_gl2psListNbr(gl2ps->primitives)     6202     if(tools_gl2psListNbr(gl2ps->primitives) &&
6203        (gl2ps->options & TOOLS_GL2PS_TIGHT_BO    6203        (gl2ps->options & TOOLS_GL2PS_TIGHT_BOUNDING_BOX)){
6204       gl2ps->viewport[0] = gl2ps->viewport[1]    6204       gl2ps->viewport[0] = gl2ps->viewport[1] = 100000;
6205       gl2ps->viewport[2] = gl2ps->viewport[3]    6205       gl2ps->viewport[2] = gl2ps->viewport[3] = -100000;
6206       tools_gl2psListActionContext(gl2ps, gl2    6206       tools_gl2psListActionContext(gl2ps, gl2ps->primitives, tools_gl2psComputeTightBoundingBox);
6207     }                                            6207     }
6208     (tools_gl2psbackends[gl2ps->format]->prin    6208     (tools_gl2psbackends[gl2ps->format]->printHeader)(gl2ps);
6209     gl2ps->header = TOOLS_GL_FALSE;              6209     gl2ps->header = TOOLS_GL_FALSE;
6210   }                                              6210   }
6211                                                  6211 
6212   if(!tools_gl2psListNbr(gl2ps->primitives)){    6212   if(!tools_gl2psListNbr(gl2ps->primitives)){
6213     /* empty feedback buffer and/or nothing e    6213     /* empty feedback buffer and/or nothing else to print */
6214     return TOOLS_GL2PS_NO_FEEDBACK;              6214     return TOOLS_GL2PS_NO_FEEDBACK;
6215   }                                              6215   }
6216                                                  6216 
6217   switch(gl2ps->sort){                           6217   switch(gl2ps->sort){
6218   case TOOLS_GL2PS_NO_SORT :                     6218   case TOOLS_GL2PS_NO_SORT :
6219     tools_gl2psListActionContext(gl2ps, gl2ps    6219     tools_gl2psListActionContext(gl2ps, gl2ps->primitives, tools_gl2psbackends[gl2ps->format]->printPrimitive);
6220     tools_gl2psListAction(gl2ps->primitives,     6220     tools_gl2psListAction(gl2ps->primitives, tools_gl2psFreePrimitive);
6221     /* reset the primitive list, waiting for     6221     /* reset the primitive list, waiting for the next viewport */
6222     tools_gl2psListReset(gl2ps->primitives);     6222     tools_gl2psListReset(gl2ps->primitives);
6223     break;                                       6223     break;
6224   case TOOLS_GL2PS_SIMPLE_SORT :                 6224   case TOOLS_GL2PS_SIMPLE_SORT :
6225     tools_gl2psListAssignSortIds(gl2ps->primi    6225     tools_gl2psListAssignSortIds(gl2ps->primitives);
6226     tools_gl2psListSort(gl2ps, gl2ps->primiti    6226     tools_gl2psListSort(gl2ps, gl2ps->primitives, tools_gl2psCompareDepth);
6227     if(gl2ps->options & TOOLS_GL2PS_OCCLUSION    6227     if(gl2ps->options & TOOLS_GL2PS_OCCLUSION_CULL){
6228       tools_gl2psListActionInverseContext(gl2    6228       tools_gl2psListActionInverseContext(gl2ps, gl2ps->primitives, tools_gl2psAddInImageTree);
6229       tools_gl2psFreeBspImageTree(&gl2ps->ima    6229       tools_gl2psFreeBspImageTree(&gl2ps->imagetree);
6230     }                                            6230     }
6231     tools_gl2psListActionContext(gl2ps, gl2ps    6231     tools_gl2psListActionContext(gl2ps, gl2ps->primitives, tools_gl2psbackends[gl2ps->format]->printPrimitive);
6232     tools_gl2psListAction(gl2ps->primitives,     6232     tools_gl2psListAction(gl2ps->primitives, tools_gl2psFreePrimitive);
6233     /* reset the primitive list, waiting for     6233     /* reset the primitive list, waiting for the next viewport */
6234     tools_gl2psListReset(gl2ps->primitives);     6234     tools_gl2psListReset(gl2ps->primitives);
6235     break;                                       6235     break;
6236   case TOOLS_GL2PS_BSP_SORT :                    6236   case TOOLS_GL2PS_BSP_SORT :
6237     root = (tools_GL2PSbsptree*)tools_gl2psMa    6237     root = (tools_GL2PSbsptree*)tools_gl2psMalloc(sizeof(tools_GL2PSbsptree));
6238     tools_gl2psBuildBspTree(gl2ps, root, gl2p    6238     tools_gl2psBuildBspTree(gl2ps, root, gl2ps->primitives);
6239     if(TOOLS_GL_TRUE == gl2ps->boundary) tool    6239     if(TOOLS_GL_TRUE == gl2ps->boundary) tools_gl2psBuildPolygonBoundary(root);
6240     if(gl2ps->options & TOOLS_GL2PS_OCCLUSION    6240     if(gl2ps->options & TOOLS_GL2PS_OCCLUSION_CULL){
6241       tools_gl2psTraverseBspTree(gl2ps, root,    6241       tools_gl2psTraverseBspTree(gl2ps, root, eye, -TOOLS_GL2PS_EPSILON, tools_gl2psLess,
6242                            tools_gl2psAddInIm    6242                            tools_gl2psAddInImageTree, 1);
6243       tools_gl2psFreeBspImageTree(&gl2ps->ima    6243       tools_gl2psFreeBspImageTree(&gl2ps->imagetree);
6244     }                                            6244     }
6245     tools_gl2psTraverseBspTree(gl2ps, root, e    6245     tools_gl2psTraverseBspTree(gl2ps, root, eye, TOOLS_GL2PS_EPSILON, tools_gl2psGreater,
6246                          tools_gl2psbackends[    6246                          tools_gl2psbackends[gl2ps->format]->printPrimitive, 0);
6247     tools_gl2psFreeBspTree(&root);               6247     tools_gl2psFreeBspTree(&root);
6248     /* reallocate the primitive list (it's be    6248     /* reallocate the primitive list (it's been deleted by
6249        tools_gl2psBuildBspTree) in case there    6249        tools_gl2psBuildBspTree) in case there is another viewport */
6250     gl2ps->primitives = tools_gl2psListCreate    6250     gl2ps->primitives = tools_gl2psListCreate(500, 500, sizeof(tools_GL2PSprimitive*));
6251     break;                                       6251     break;
6252   }                                              6252   }
6253   tools_gl2psbackends[gl2ps->format]->printFi    6253   tools_gl2psbackends[gl2ps->format]->printFinalPrimitive(gl2ps);
6254                                                  6254 
6255   return TOOLS_GL2PS_SUCCESS;                    6255   return TOOLS_GL2PS_SUCCESS;
6256 }                                                6256 }
6257                                                  6257 
6258 inline tools_GLboolean tools_gl2psCheckOption    6258 inline tools_GLboolean tools_gl2psCheckOptions(tools_GLint options, tools_GLint colormode)
6259 {                                                6259 {
6260   if (options & TOOLS_GL2PS_NO_OPENGL_CONTEXT    6260   if (options & TOOLS_GL2PS_NO_OPENGL_CONTEXT) {
6261     if (options & TOOLS_GL2PS_DRAW_BACKGROUND    6261     if (options & TOOLS_GL2PS_DRAW_BACKGROUND) {
6262       tools_gl2psMsg(TOOLS_GL2PS_ERROR, "Opti    6262       tools_gl2psMsg(TOOLS_GL2PS_ERROR, "Options TOOLS_GL2PS_NO_OPENGL_CONTEXT and "
6263                             "TOOLS_GL2PS_DRAW    6263                             "TOOLS_GL2PS_DRAW_BACKGROUND are incompatible.");
6264       return TOOLS_GL_FALSE;                     6264       return TOOLS_GL_FALSE;
6265     }                                            6265     }
6266     if (options & TOOLS_GL2PS_USE_CURRENT_VIE    6266     if (options & TOOLS_GL2PS_USE_CURRENT_VIEWPORT) {
6267       tools_gl2psMsg(TOOLS_GL2PS_ERROR, "Opti    6267       tools_gl2psMsg(TOOLS_GL2PS_ERROR, "Options TOOLS_GL2PS_NO_OPENGL_CONTEXT and "
6268                             "TOOLS_GL2PS_USE_    6268                             "TOOLS_GL2PS_USE_CURRENT_VIEWPORT are incompatible.");
6269       return TOOLS_GL_FALSE;                     6269       return TOOLS_GL_FALSE;
6270     }                                            6270     }
6271     if ((options & TOOLS_GL2PS_NO_BLENDING) =    6271     if ((options & TOOLS_GL2PS_NO_BLENDING) == TOOLS_GL2PS_NONE) {
6272       tools_gl2psMsg(TOOLS_GL2PS_ERROR, "Opti    6272       tools_gl2psMsg(TOOLS_GL2PS_ERROR, "Option TOOLS_GL2PS_NO_OPENGL_CONTEXT requires "
6273                             "option TOOLS_GL2    6273                             "option TOOLS_GL2PS_NO_BLENDING.");
6274       return TOOLS_GL_FALSE;                     6274       return TOOLS_GL_FALSE;
6275     }                                            6275     }
6276     if (colormode != TOOLS_GL_RGBA) {            6276     if (colormode != TOOLS_GL_RGBA) {
6277       tools_gl2psMsg(TOOLS_GL2PS_ERROR, "Opti    6277       tools_gl2psMsg(TOOLS_GL2PS_ERROR, "Option TOOLS_GL2PS_NO_OPENGL_CONTEXT requires colormode "
6278                             "to be TOOLS_GL_R    6278                             "to be TOOLS_GL_RGBA.");
6279       return TOOLS_GL_FALSE;                     6279       return TOOLS_GL_FALSE;
6280     }                                            6280     }
6281   }                                              6281   }
6282                                                  6282 
6283   return TOOLS_GL_TRUE;                          6283   return TOOLS_GL_TRUE;
6284 }                                                6284 }
6285                                                  6285 
6286 /********************************************    6286 /*********************************************************************
6287  *                                               6287  *
6288  * Public routines                               6288  * Public routines
6289  *                                               6289  *
6290  ********************************************    6290  *********************************************************************/
6291                                                  6291 
6292 TOOLS_GL2PSDLL_API tools_GLint tools_gl2psBeg    6292 TOOLS_GL2PSDLL_API tools_GLint tools_gl2psBeginPage(tools_GL2PScontext* gl2ps, const char *title, const char *producer,
6293                                   tools_GLint    6293                                   tools_GLint viewport[4], tools_GLint format, tools_GLint sort,
6294                                   tools_GLint    6294                                   tools_GLint options, tools_GLint colormode,
6295                                   tools_GLint    6295                                   tools_GLint colorsize, tools_GL2PSrgba *colormap,
6296                                   tools_GLint    6296                                   tools_GLint nr, tools_GLint ng, tools_GLint nb, tools_GLint buffersize,
6297                                   FILE *strea    6297                                   FILE *stream, const char *filename)
6298 {                                                6298 {
6299   tools_GLint idx;                               6299   tools_GLint idx;
6300   int i;                                         6300   int i;
6301                                                  6301 
6302 /*G.Barrand: if(gl2ps){                          6302 /*G.Barrand: if(gl2ps){
6303     tools_gl2psMsg(TOOLS_GL2PS_ERROR, "tools_    6303     tools_gl2psMsg(TOOLS_GL2PS_ERROR, "tools_gl2psBeginPage called in wrong program state");
6304     return TOOLS_GL2PS_ERROR;                    6304     return TOOLS_GL2PS_ERROR;
6305   }                                              6305   }
6306                                                  6306 
6307   gl2ps = (tools_GL2PScontext*)tools_gl2psMal    6307   gl2ps = (tools_GL2PScontext*)tools_gl2psMalloc(sizeof(tools_GL2PScontext));
6308 */                                               6308 */
6309                                                  6309 
6310   /* Validate options */                         6310   /* Validate options */
6311   if (tools_gl2psCheckOptions(options, colorm    6311   if (tools_gl2psCheckOptions(options, colormode) == TOOLS_GL_FALSE) {
6312   /*tools_gl2psFree(gl2ps);                      6312   /*tools_gl2psFree(gl2ps);
6313     gl2ps = NULL;*/                              6313     gl2ps = NULL;*/
6314     return TOOLS_GL2PS_ERROR;                    6314     return TOOLS_GL2PS_ERROR;
6315   }                                              6315   }
6316                                                  6316 
6317   if(format >= 0 && format < (tools_GLint)(si    6317   if(format >= 0 && format < (tools_GLint)(sizeof(tools_gl2psbackends) / sizeof(tools_gl2psbackends[0]))){
6318     gl2ps->format = format;                      6318     gl2ps->format = format;
6319   }                                              6319   }
6320   else {                                         6320   else {
6321     tools_gl2psMsg(TOOLS_GL2PS_ERROR, "Unknow    6321     tools_gl2psMsg(TOOLS_GL2PS_ERROR, "Unknown output format: %d", format);
6322   /*tools_gl2psFree(gl2ps);                      6322   /*tools_gl2psFree(gl2ps);
6323     gl2ps = NULL;*/                              6323     gl2ps = NULL;*/
6324     return TOOLS_GL2PS_ERROR;                    6324     return TOOLS_GL2PS_ERROR;
6325   }                                              6325   }
6326                                                  6326 
6327   switch(sort){                                  6327   switch(sort){
6328   case TOOLS_GL2PS_NO_SORT :                     6328   case TOOLS_GL2PS_NO_SORT :
6329   case TOOLS_GL2PS_SIMPLE_SORT :                 6329   case TOOLS_GL2PS_SIMPLE_SORT :
6330   case TOOLS_GL2PS_BSP_SORT :                    6330   case TOOLS_GL2PS_BSP_SORT :
6331     gl2ps->sort = sort;                          6331     gl2ps->sort = sort;
6332     break;                                       6332     break;
6333   default :                                      6333   default :
6334     tools_gl2psMsg(TOOLS_GL2PS_ERROR, "Unknow    6334     tools_gl2psMsg(TOOLS_GL2PS_ERROR, "Unknown sorting algorithm: %d", sort);
6335   /*tools_gl2psFree(gl2ps);                      6335   /*tools_gl2psFree(gl2ps);
6336     gl2ps = NULL;*/                              6336     gl2ps = NULL;*/
6337     return TOOLS_GL2PS_ERROR;                    6337     return TOOLS_GL2PS_ERROR;
6338   }                                              6338   }
6339                                                  6339 
6340   if(stream){                                    6340   if(stream){
6341     gl2ps->stream = stream;                      6341     gl2ps->stream = stream;
6342   }                                              6342   }
6343   else{                                          6343   else{
6344     tools_gl2psMsg(TOOLS_GL2PS_ERROR, "Bad fi    6344     tools_gl2psMsg(TOOLS_GL2PS_ERROR, "Bad file pointer");
6345   /*tools_gl2psFree(gl2ps);                      6345   /*tools_gl2psFree(gl2ps);
6346     gl2ps = NULL;*/                              6346     gl2ps = NULL;*/
6347     return TOOLS_GL2PS_ERROR;                    6347     return TOOLS_GL2PS_ERROR;
6348   }                                              6348   }
6349                                                  6349 
6350   gl2ps->header = TOOLS_GL_TRUE;                 6350   gl2ps->header = TOOLS_GL_TRUE;
6351   gl2ps->forcerasterpos = TOOLS_GL_FALSE;        6351   gl2ps->forcerasterpos = TOOLS_GL_FALSE;
6352   gl2ps->maxbestroot = 10;                       6352   gl2ps->maxbestroot = 10;
6353   gl2ps->options = options;                      6353   gl2ps->options = options;
6354   gl2ps->compress = NULL;                        6354   gl2ps->compress = NULL;
6355   gl2ps->imagemap_head = NULL;                   6355   gl2ps->imagemap_head = NULL;
6356   gl2ps->imagemap_tail = NULL;                   6356   gl2ps->imagemap_tail = NULL;
6357                                                  6357 
6358   if(gl2ps->options & TOOLS_GL2PS_USE_CURRENT    6358   if(gl2ps->options & TOOLS_GL2PS_USE_CURRENT_VIEWPORT){
6359     tools_glGetIntegerv(TOOLS_GL_VIEWPORT, gl    6359     tools_glGetIntegerv(TOOLS_GL_VIEWPORT, gl2ps->viewport);
6360   }                                              6360   }
6361   else{                                          6361   else{
6362     for(i = 0; i < 4; i++){                      6362     for(i = 0; i < 4; i++){
6363       gl2ps->viewport[i] = viewport[i];          6363       gl2ps->viewport[i] = viewport[i];
6364     }                                            6364     }
6365   }                                              6365   }
6366                                                  6366 
6367   if(!gl2ps->viewport[2] || !gl2ps->viewport[    6367   if(!gl2ps->viewport[2] || !gl2ps->viewport[3]){
6368     tools_gl2psMsg(TOOLS_GL2PS_ERROR, "Incorr    6368     tools_gl2psMsg(TOOLS_GL2PS_ERROR, "Incorrect viewport (x=%d, y=%d, width=%d, height=%d)",
6369              gl2ps->viewport[0], gl2ps->viewp    6369              gl2ps->viewport[0], gl2ps->viewport[1],
6370              gl2ps->viewport[2], gl2ps->viewp    6370              gl2ps->viewport[2], gl2ps->viewport[3]);
6371   /*tools_gl2psFree(gl2ps);                      6371   /*tools_gl2psFree(gl2ps);
6372     gl2ps = NULL;*/                              6372     gl2ps = NULL;*/
6373     return TOOLS_GL2PS_ERROR;                    6373     return TOOLS_GL2PS_ERROR;
6374   }                                              6374   }
6375                                                  6375 
6376   gl2ps->threshold[0] = nr ? 1.0F / (tools_GL    6376   gl2ps->threshold[0] = nr ? 1.0F / (tools_GLfloat)nr : 0.064F;
6377   gl2ps->threshold[1] = ng ? 1.0F / (tools_GL    6377   gl2ps->threshold[1] = ng ? 1.0F / (tools_GLfloat)ng : 0.034F;
6378   gl2ps->threshold[2] = nb ? 1.0F / (tools_GL    6378   gl2ps->threshold[2] = nb ? 1.0F / (tools_GLfloat)nb : 0.100F;
6379   gl2ps->colormode = colormode;                  6379   gl2ps->colormode = colormode;
6380   gl2ps->buffersize = buffersize > 0 ? buffer    6380   gl2ps->buffersize = buffersize > 0 ? buffersize : 2048 * 2048;
6381   for(i = 0; i < 3; i++){                        6381   for(i = 0; i < 3; i++){
6382     gl2ps->lastvertex.xyz[i] = -1.0F;            6382     gl2ps->lastvertex.xyz[i] = -1.0F;
6383   }                                              6383   }
6384   for(i = 0; i < 4; i++){                        6384   for(i = 0; i < 4; i++){
6385     gl2ps->lastvertex.rgba[i] = -1.0F;           6385     gl2ps->lastvertex.rgba[i] = -1.0F;
6386     gl2ps->lastrgba[i] = -1.0F;                  6386     gl2ps->lastrgba[i] = -1.0F;
6387   }                                              6387   }
6388   gl2ps->lastlinewidth = -1.0F;                  6388   gl2ps->lastlinewidth = -1.0F;
6389   gl2ps->lastlinecap = 0;                        6389   gl2ps->lastlinecap = 0;
6390   gl2ps->lastlinejoin = 0;                       6390   gl2ps->lastlinejoin = 0;
6391   gl2ps->lastpattern = 0;                        6391   gl2ps->lastpattern = 0;
6392   gl2ps->lastfactor = 0;                         6392   gl2ps->lastfactor = 0;
6393   gl2ps->imagetree = NULL;                       6393   gl2ps->imagetree = NULL;
6394   gl2ps->primitivetoadd = NULL;                  6394   gl2ps->primitivetoadd = NULL;
6395   gl2ps->zerosurfacearea = TOOLS_GL_FALSE;       6395   gl2ps->zerosurfacearea = TOOLS_GL_FALSE;
6396   gl2ps->pdfprimlist = NULL;                     6396   gl2ps->pdfprimlist = NULL;
6397   gl2ps->pdfgrouplist = NULL;                    6397   gl2ps->pdfgrouplist = NULL;
6398   gl2ps->xreflist = NULL;                        6398   gl2ps->xreflist = NULL;
6399                                                  6399 
6400   /* get default blending mode from current O    6400   /* get default blending mode from current OpenGL state (enabled by
6401      default for SVG) */                         6401      default for SVG) */
6402   if ((gl2ps->options & TOOLS_GL2PS_NO_BLENDI    6402   if ((gl2ps->options & TOOLS_GL2PS_NO_BLENDING) == TOOLS_GL2PS_NONE) {
6403     gl2ps->blending = (gl2ps->format == TOOLS    6403     gl2ps->blending = (gl2ps->format == TOOLS_GL2PS_SVG) ? TOOLS_GL_TRUE
6404                                                  6404                                                    : tools_glIsEnabled(TOOLS_GL_BLEND);
6405     tools_glGetIntegerv(TOOLS_GL_BLEND_SRC, &    6405     tools_glGetIntegerv(TOOLS_GL_BLEND_SRC, &gl2ps->blendfunc[0]);
6406     tools_glGetIntegerv(TOOLS_GL_BLEND_DST, &    6406     tools_glGetIntegerv(TOOLS_GL_BLEND_DST, &gl2ps->blendfunc[1]);
6407   }                                              6407   }
6408   else {                                         6408   else {
6409     gl2ps->blending = TOOLS_GL_FALSE;            6409     gl2ps->blending = TOOLS_GL_FALSE;
6410   }                                              6410   }
6411                                                  6411 
6412   if(gl2ps->colormode == TOOLS_GL_RGBA){         6412   if(gl2ps->colormode == TOOLS_GL_RGBA){
6413     gl2ps->colorsize = 0;                        6413     gl2ps->colorsize = 0;
6414     gl2ps->colormap = NULL;                      6414     gl2ps->colormap = NULL;
6415     if ((gl2ps->options & TOOLS_GL2PS_NO_OPEN    6415     if ((gl2ps->options & TOOLS_GL2PS_NO_OPENGL_CONTEXT) == TOOLS_GL2PS_NONE) {
6416       tools_glGetFloatv(TOOLS_GL_COLOR_CLEAR_    6416       tools_glGetFloatv(TOOLS_GL_COLOR_CLEAR_VALUE, gl2ps->bgcolor);
6417     }                                            6417     }
6418   }                                              6418   }
6419   else if(gl2ps->colormode == TOOLS_GL_COLOR_    6419   else if(gl2ps->colormode == TOOLS_GL_COLOR_INDEX){
6420     if(!colorsize || !colormap){                 6420     if(!colorsize || !colormap){
6421       tools_gl2psMsg(TOOLS_GL2PS_ERROR, "Miss    6421       tools_gl2psMsg(TOOLS_GL2PS_ERROR, "Missing colormap for TOOLS_GL_COLOR_INDEX rendering");
6422     /*tools_gl2psFree(gl2ps);                    6422     /*tools_gl2psFree(gl2ps);
6423       gl2ps = NULL;*/                            6423       gl2ps = NULL;*/
6424       return TOOLS_GL2PS_ERROR;                  6424       return TOOLS_GL2PS_ERROR;
6425     }                                            6425     }
6426     gl2ps->colorsize = colorsize;                6426     gl2ps->colorsize = colorsize;
6427     gl2ps->colormap = (tools_GL2PSrgba*)tools    6427     gl2ps->colormap = (tools_GL2PSrgba*)tools_gl2psMalloc(gl2ps->colorsize * sizeof(tools_GL2PSrgba));
6428     memcpy(gl2ps->colormap, colormap, gl2ps->    6428     memcpy(gl2ps->colormap, colormap, gl2ps->colorsize * sizeof(tools_GL2PSrgba));
6429     tools_glGetIntegerv(TOOLS_GL_INDEX_CLEAR_    6429     tools_glGetIntegerv(TOOLS_GL_INDEX_CLEAR_VALUE, &idx);
6430     gl2ps->bgcolor[0] = gl2ps->colormap[idx][    6430     gl2ps->bgcolor[0] = gl2ps->colormap[idx][0];
6431     gl2ps->bgcolor[1] = gl2ps->colormap[idx][    6431     gl2ps->bgcolor[1] = gl2ps->colormap[idx][1];
6432     gl2ps->bgcolor[2] = gl2ps->colormap[idx][    6432     gl2ps->bgcolor[2] = gl2ps->colormap[idx][2];
6433     gl2ps->bgcolor[3] = 1.0F;                    6433     gl2ps->bgcolor[3] = 1.0F;
6434   }                                              6434   }
6435   else{                                          6435   else{
6436     tools_gl2psMsg(TOOLS_GL2PS_ERROR, "Unknow    6436     tools_gl2psMsg(TOOLS_GL2PS_ERROR, "Unknown color mode in tools_gl2psBeginPage");
6437   /*tools_gl2psFree(gl2ps);                      6437   /*tools_gl2psFree(gl2ps);
6438     gl2ps = NULL;*/                              6438     gl2ps = NULL;*/
6439     return TOOLS_GL2PS_ERROR;                    6439     return TOOLS_GL2PS_ERROR;
6440   }                                              6440   }
6441                                                  6441 
6442   if(!title){                                    6442   if(!title){
6443     gl2ps->title = (char*)tools_gl2psMalloc(s    6443     gl2ps->title = (char*)tools_gl2psMalloc(sizeof(char));
6444     gl2ps->title[0] = '\0';                      6444     gl2ps->title[0] = '\0';
6445   }                                              6445   }
6446   else{                                          6446   else{
6447     gl2ps->title = (char*)tools_gl2psMalloc((    6447     gl2ps->title = (char*)tools_gl2psMalloc((strlen(title)+1)*sizeof(char));
6448     strcpy(gl2ps->title, title);                 6448     strcpy(gl2ps->title, title);
6449   }                                              6449   }
6450                                                  6450 
6451   if(!producer){                                 6451   if(!producer){
6452     gl2ps->producer = (char*)tools_gl2psMallo    6452     gl2ps->producer = (char*)tools_gl2psMalloc(sizeof(char));
6453     gl2ps->producer[0] = '\0';                   6453     gl2ps->producer[0] = '\0';
6454   }                                              6454   }
6455   else{                                          6455   else{
6456     gl2ps->producer = (char*)tools_gl2psMallo    6456     gl2ps->producer = (char*)tools_gl2psMalloc((strlen(producer)+1)*sizeof(char));
6457     strcpy(gl2ps->producer, producer);           6457     strcpy(gl2ps->producer, producer);
6458   }                                              6458   }
6459                                                  6459 
6460   if(!filename){                                 6460   if(!filename){
6461     gl2ps->filename = (char*)tools_gl2psMallo    6461     gl2ps->filename = (char*)tools_gl2psMalloc(sizeof(char));
6462     gl2ps->filename[0] = '\0';                   6462     gl2ps->filename[0] = '\0';
6463   }                                              6463   }
6464   else{                                          6464   else{
6465     gl2ps->filename = (char*)tools_gl2psMallo    6465     gl2ps->filename = (char*)tools_gl2psMalloc((strlen(filename)+1)*sizeof(char));
6466     strcpy(gl2ps->filename, filename);           6466     strcpy(gl2ps->filename, filename);
6467   }                                              6467   }
6468                                                  6468 
6469   gl2ps->primitives = tools_gl2psListCreate(5    6469   gl2ps->primitives = tools_gl2psListCreate(500, 500, sizeof(tools_GL2PSprimitive*));
6470   gl2ps->auxprimitives = tools_gl2psListCreat    6470   gl2ps->auxprimitives = tools_gl2psListCreate(100, 100, sizeof(tools_GL2PSprimitive*));
6471                                                  6471 
6472   if ((gl2ps->options & TOOLS_GL2PS_NO_OPENGL    6472   if ((gl2ps->options & TOOLS_GL2PS_NO_OPENGL_CONTEXT) == TOOLS_GL2PS_NONE) {
6473     gl2ps->feedback = (tools_GLfloat*)tools_g    6473     gl2ps->feedback = (tools_GLfloat*)tools_gl2psMalloc(gl2ps->buffersize * sizeof(tools_GLfloat));
6474     tools_glFeedbackBuffer(gl2ps->buffersize,    6474     tools_glFeedbackBuffer(gl2ps->buffersize, TOOLS_GL_3D_COLOR, gl2ps->feedback);
6475     tools_glRenderMode(TOOLS_GL_FEEDBACK);       6475     tools_glRenderMode(TOOLS_GL_FEEDBACK);
6476   }                                              6476   }
6477   else {                                         6477   else {
6478     gl2ps->feedback = NULL;                      6478     gl2ps->feedback = NULL;
6479     gl2ps->buffersize = 0;                       6479     gl2ps->buffersize = 0;
6480   }                                              6480   }
6481                                                  6481 
6482   gl2ps->tex_scaling = 1.;                       6482   gl2ps->tex_scaling = 1.;
6483                                                  6483 
6484   return TOOLS_GL2PS_SUCCESS;                    6484   return TOOLS_GL2PS_SUCCESS;
6485 }                                                6485 }
6486                                                  6486 
6487 TOOLS_GL2PSDLL_API tools_GLint tools_gl2psEnd    6487 TOOLS_GL2PSDLL_API tools_GLint tools_gl2psEndPage(tools_GL2PScontext* gl2ps)
6488 {                                                6488 {
6489   tools_GLint res;                               6489   tools_GLint res;
6490                                                  6490 
6491 /*if(!gl2ps) return TOOLS_GL2PS_UNINITIALIZED    6491 /*if(!gl2ps) return TOOLS_GL2PS_UNINITIALIZED;*/
6492                                                  6492 
6493   res = tools_gl2psPrintPrimitives(gl2ps);       6493   res = tools_gl2psPrintPrimitives(gl2ps);
6494                                                  6494 
6495   if(res != TOOLS_GL2PS_OVERFLOW)                6495   if(res != TOOLS_GL2PS_OVERFLOW)
6496     (tools_gl2psbackends[gl2ps->format]->prin    6496     (tools_gl2psbackends[gl2ps->format]->printFooter)(gl2ps);
6497                                                  6497 
6498   fflush(gl2ps->stream);                         6498   fflush(gl2ps->stream);
6499                                                  6499 
6500   tools_gl2psListDelete(gl2ps->primitives);      6500   tools_gl2psListDelete(gl2ps->primitives);
6501   tools_gl2psListDelete(gl2ps->auxprimitives)    6501   tools_gl2psListDelete(gl2ps->auxprimitives);
6502   tools_gl2psFreeImagemap(gl2ps->imagemap_hea    6502   tools_gl2psFreeImagemap(gl2ps->imagemap_head);
6503   tools_gl2psFree(gl2ps->colormap);              6503   tools_gl2psFree(gl2ps->colormap);
6504   tools_gl2psFree(gl2ps->title);                 6504   tools_gl2psFree(gl2ps->title);
6505   tools_gl2psFree(gl2ps->producer);              6505   tools_gl2psFree(gl2ps->producer);
6506   tools_gl2psFree(gl2ps->filename);              6506   tools_gl2psFree(gl2ps->filename);
6507   tools_gl2psFree(gl2ps->feedback);              6507   tools_gl2psFree(gl2ps->feedback);
6508 /*tools_gl2psFree(gl2ps);                        6508 /*tools_gl2psFree(gl2ps);
6509   gl2ps = NULL;*/                                6509   gl2ps = NULL;*/
6510                                                  6510 
6511   return res;                                    6511   return res;
6512 }                                                6512 }
6513                                                  6513 
6514 TOOLS_GL2PSDLL_API tools_GLint tools_gl2psBeg    6514 TOOLS_GL2PSDLL_API tools_GLint tools_gl2psBeginViewport(tools_GL2PScontext* gl2ps, tools_GLint viewport[4])
6515 {                                                6515 {
6516 /*if(!gl2ps) return TOOLS_GL2PS_UNINITIALIZED    6516 /*if(!gl2ps) return TOOLS_GL2PS_UNINITIALIZED;*/
6517                                                  6517 
6518   (tools_gl2psbackends[gl2ps->format]->beginV    6518   (tools_gl2psbackends[gl2ps->format]->beginViewport)(gl2ps, viewport);
6519                                                  6519 
6520   return TOOLS_GL2PS_SUCCESS;                    6520   return TOOLS_GL2PS_SUCCESS;
6521 }                                                6521 }
6522                                                  6522 
6523 TOOLS_GL2PSDLL_API tools_GLint tools_gl2psEnd    6523 TOOLS_GL2PSDLL_API tools_GLint tools_gl2psEndViewport(tools_GL2PScontext* gl2ps)
6524 {                                                6524 {
6525   tools_GLint res;                               6525   tools_GLint res;
6526                                                  6526 
6527 /*if(!gl2ps) return TOOLS_GL2PS_UNINITIALIZED    6527 /*if(!gl2ps) return TOOLS_GL2PS_UNINITIALIZED;*/
6528                                                  6528 
6529   res = (tools_gl2psbackends[gl2ps->format]->    6529   res = (tools_gl2psbackends[gl2ps->format]->endViewport)(gl2ps);
6530                                                  6530 
6531   /* reset last used colors, line widths */      6531   /* reset last used colors, line widths */
6532   tools_gl2psResetLineProperties(gl2ps);         6532   tools_gl2psResetLineProperties(gl2ps);
6533                                                  6533 
6534   return res;                                    6534   return res;
6535 }                                                6535 }
6536                                                  6536 
6537 TOOLS_GL2PSDLL_API tools_GLint tools_gl2psSor    6537 TOOLS_GL2PSDLL_API tools_GLint tools_gl2psSorting(tools_GL2PScontext* gl2ps, tools_GLint mode)
6538 {                                                6538 {
6539   tools_GLint res;                               6539   tools_GLint res;
6540                                                  6540 
6541 /*if(!gl2ps) return TOOLS_GL2PS_UNINITIALIZED    6541 /*if(!gl2ps) return TOOLS_GL2PS_UNINITIALIZED;*/
6542                                                  6542 
6543   switch(mode){                                  6543   switch(mode){
6544   case TOOLS_GL2PS_NO_SORT :                     6544   case TOOLS_GL2PS_NO_SORT :
6545   case TOOLS_GL2PS_SIMPLE_SORT :                 6545   case TOOLS_GL2PS_SIMPLE_SORT :
6546   case TOOLS_GL2PS_BSP_SORT :                    6546   case TOOLS_GL2PS_BSP_SORT :
6547     gl2ps->sort = mode;                          6547     gl2ps->sort = mode;
6548     res = TOOLS_GL2PS_SUCCESS;                   6548     res = TOOLS_GL2PS_SUCCESS;
6549     break;                                       6549     break;
6550   default :                                      6550   default :
6551     tools_gl2psMsg(TOOLS_GL2PS_ERROR, "Unknow    6551     tools_gl2psMsg(TOOLS_GL2PS_ERROR, "Unknown sorting algorithm: %d", mode);
6552   /*tools_gl2psFree(gl2ps);                      6552   /*tools_gl2psFree(gl2ps);
6553     gl2ps = NULL;*/                              6553     gl2ps = NULL;*/
6554     res = TOOLS_GL2PS_ERROR;                     6554     res = TOOLS_GL2PS_ERROR;
6555   }                                              6555   }
6556                                                  6556 
6557   return res;                                    6557   return res;
6558 }                                                6558 }
6559                                                  6559 
6560 TOOLS_GL2PSDLL_API tools_GLint tools_gl2psTex    6560 TOOLS_GL2PSDLL_API tools_GLint tools_gl2psTextOptColor(tools_GL2PScontext* gl2ps, const char *str, const char *fontname,
6561                                      tools_GL    6561                                      tools_GLshort fontsize, tools_GLint alignment, tools_GLfloat angle,
6562                                      tools_GL    6562                                      tools_GL2PSrgba color)
6563 {                                                6563 {
6564   return tools_gl2psAddText(gl2ps, TOOLS_GL2P    6564   return tools_gl2psAddText(gl2ps, TOOLS_GL2PS_TEXT, str, fontname, fontsize, alignment, angle,
6565                       color, TOOLS_GL_FALSE,     6565                       color, TOOLS_GL_FALSE, 0, 0);
6566 }                                                6566 }
6567                                                  6567 
6568 /**                                              6568 /**
6569  * This version of tools_gl2psTextOptColor is    6569  * This version of tools_gl2psTextOptColor is used to go around the
6570  * fact that PDF does not support text alignm    6570  * fact that PDF does not support text alignment. The extra parameters
6571  * (blx, bly) represent the bottom left corne    6571  * (blx, bly) represent the bottom left corner of the text bounding box.
6572  */                                              6572  */
6573 TOOLS_GL2PSDLL_API tools_GLint tools_gl2psTex    6573 TOOLS_GL2PSDLL_API tools_GLint tools_gl2psTextOptColorBL(tools_GL2PScontext* gl2ps, const char *str, const char *fontname,
6574                                        tools_    6574                                        tools_GLshort fontsize, tools_GLint alignment, tools_GLfloat angle,
6575                                        tools_    6575                                        tools_GL2PSrgba color, tools_GLfloat blx, tools_GLfloat bly)
6576 {                                                6576 {
6577   return tools_gl2psAddText(gl2ps, TOOLS_GL2P    6577   return tools_gl2psAddText(gl2ps, TOOLS_GL2PS_TEXT, str, fontname, fontsize, alignment, angle,
6578                       color, TOOLS_GL_TRUE, b    6578                       color, TOOLS_GL_TRUE, blx, bly);
6579 }                                                6579 }
6580                                                  6580 
6581 TOOLS_GL2PSDLL_API tools_GLint tools_gl2psTex    6581 TOOLS_GL2PSDLL_API tools_GLint tools_gl2psTextOpt(tools_GL2PScontext* gl2ps, const char *str, const char *fontname,
6582                                 tools_GLshort    6582                                 tools_GLshort fontsize, tools_GLint alignment, tools_GLfloat angle)
6583 {                                                6583 {
6584   return tools_gl2psAddText(gl2ps, TOOLS_GL2P    6584   return tools_gl2psAddText(gl2ps, TOOLS_GL2PS_TEXT, str, fontname, fontsize, alignment, angle, NULL, TOOLS_GL_FALSE, 0, 0);
6585 }                                                6585 }
6586                                                  6586 
6587 TOOLS_GL2PSDLL_API tools_GLint tools_gl2psTex    6587 TOOLS_GL2PSDLL_API tools_GLint tools_gl2psText(tools_GL2PScontext* gl2ps, const char *str, const char *fontname, tools_GLshort fontsize)
6588 {                                                6588 {
6589   return tools_gl2psAddText(gl2ps, TOOLS_GL2P    6589   return tools_gl2psAddText(gl2ps, TOOLS_GL2PS_TEXT, str, fontname, fontsize, TOOLS_GL2PS_TEXT_BL, 0.0F,
6590                       NULL, TOOLS_GL_FALSE, 0    6590                       NULL, TOOLS_GL_FALSE, 0, 0);
6591 }                                                6591 }
6592                                                  6592 
6593 TOOLS_GL2PSDLL_API tools_GLint tools_gl2psSpe    6593 TOOLS_GL2PSDLL_API tools_GLint tools_gl2psSpecial(tools_GL2PScontext* gl2ps, tools_GLint format, const char *str)
6594 {                                                6594 {
6595   return tools_gl2psAddText(gl2ps, TOOLS_GL2P    6595   return tools_gl2psAddText(gl2ps, TOOLS_GL2PS_SPECIAL, str, "", 0, format, 0.0F, NULL, TOOLS_GL_FALSE, 0, 0);
6596 }                                                6596 }
6597                                                  6597 
6598 TOOLS_GL2PSDLL_API tools_GLint tools_gl2psSpe    6598 TOOLS_GL2PSDLL_API tools_GLint tools_gl2psSpecialColor(tools_GL2PScontext* gl2ps, tools_GLint format, const char *str, tools_GL2PSrgba rgba)
6599 {                                                6599 {
6600   return tools_gl2psAddText(gl2ps, TOOLS_GL2P    6600   return tools_gl2psAddText(gl2ps, TOOLS_GL2PS_SPECIAL, str, "", 0, format, 0.0F, rgba, TOOLS_GL_FALSE, 0, 0);
6601 }                                                6601 }
6602                                                  6602 
6603 TOOLS_GL2PSDLL_API tools_GLint tools_gl2psDra    6603 TOOLS_GL2PSDLL_API tools_GLint tools_gl2psDrawPixels(tools_GL2PScontext* gl2ps, tools_GLsizei width, tools_GLsizei height,
6604                                    tools_GLin    6604                                    tools_GLint xorig, tools_GLint yorig,
6605                                    tools_GLen    6605                                    tools_GLenum format, tools_GLenum type,
6606                                    const void    6606                                    const void *pixels)
6607 {                                                6607 {
6608   int size, i;                                   6608   int size, i;
6609   const tools_GLfloat *piv;                      6609   const tools_GLfloat *piv;
6610   tools_GLfloat pos[4], zoom_x, zoom_y;          6610   tools_GLfloat pos[4], zoom_x, zoom_y;
6611   tools_GL2PSprimitive *prim;                    6611   tools_GL2PSprimitive *prim;
6612   tools_GLboolean valid;                         6612   tools_GLboolean valid;
6613                                                  6613 
6614   if(/*!gl2ps ||*/ !pixels) return TOOLS_GL2P    6614   if(/*!gl2ps ||*/ !pixels) return TOOLS_GL2PS_UNINITIALIZED;
6615                                                  6615 
6616   if((width <= 0) || (height <= 0)) return TO    6616   if((width <= 0) || (height <= 0)) return TOOLS_GL2PS_ERROR;
6617                                                  6617 
6618   if(gl2ps->options & TOOLS_GL2PS_NO_PIXMAP)     6618   if(gl2ps->options & TOOLS_GL2PS_NO_PIXMAP) return TOOLS_GL2PS_SUCCESS;
6619                                                  6619 
6620   if((format != TOOLS_GL_RGB && format != TOO    6620   if((format != TOOLS_GL_RGB && format != TOOLS_GL_RGBA) || type != TOOLS_GL_FLOAT){
6621     tools_gl2psMsg(TOOLS_GL2PS_ERROR, "tools_    6621     tools_gl2psMsg(TOOLS_GL2PS_ERROR, "tools_gl2psDrawPixels only implemented for "
6622              "TOOLS_GL_RGB/TOOLS_GL_RGBA, TOO    6622              "TOOLS_GL_RGB/TOOLS_GL_RGBA, TOOLS_GL_FLOAT pixels");
6623     return TOOLS_GL2PS_ERROR;                    6623     return TOOLS_GL2PS_ERROR;
6624   }                                              6624   }
6625                                                  6625 
6626   if (gl2ps->forcerasterpos) {                   6626   if (gl2ps->forcerasterpos) {
6627     pos[0] = gl2ps->rasterpos.xyz[0];            6627     pos[0] = gl2ps->rasterpos.xyz[0];
6628     pos[1] = gl2ps->rasterpos.xyz[1];            6628     pos[1] = gl2ps->rasterpos.xyz[1];
6629     pos[2] = gl2ps->rasterpos.xyz[2];            6629     pos[2] = gl2ps->rasterpos.xyz[2];
6630     pos[3] = 1.f;                                6630     pos[3] = 1.f;
6631     /* Hardcode zoom factors (for now?) */       6631     /* Hardcode zoom factors (for now?) */
6632     zoom_x = 1.f;                                6632     zoom_x = 1.f;
6633     zoom_y = 1.f;                                6633     zoom_y = 1.f;
6634   }                                              6634   }
6635   else {                                         6635   else {
6636     tools_glGetBooleanv(TOOLS_GL_CURRENT_RAST    6636     tools_glGetBooleanv(TOOLS_GL_CURRENT_RASTER_POSITION_VALID, &valid);
6637     if(TOOLS_GL_FALSE == valid) return TOOLS_    6637     if(TOOLS_GL_FALSE == valid) return TOOLS_GL2PS_SUCCESS; /* the primitive is culled */
6638     tools_glGetFloatv(TOOLS_GL_CURRENT_RASTER    6638     tools_glGetFloatv(TOOLS_GL_CURRENT_RASTER_POSITION, pos);
6639     tools_glGetFloatv(TOOLS_GL_ZOOM_X, &zoom_    6639     tools_glGetFloatv(TOOLS_GL_ZOOM_X, &zoom_x);
6640     tools_glGetFloatv(TOOLS_GL_ZOOM_Y, &zoom_    6640     tools_glGetFloatv(TOOLS_GL_ZOOM_Y, &zoom_y);
6641   }                                              6641   }
6642                                                  6642 
6643   prim = (tools_GL2PSprimitive*)tools_gl2psMa    6643   prim = (tools_GL2PSprimitive*)tools_gl2psMalloc(sizeof(tools_GL2PSprimitive));
6644   prim->type = TOOLS_GL2PS_PIXMAP;               6644   prim->type = TOOLS_GL2PS_PIXMAP;
6645   prim->boundary = 0;                            6645   prim->boundary = 0;
6646   prim->numverts = 1;                            6646   prim->numverts = 1;
6647   prim->verts = (tools_GL2PSvertex*)tools_gl2    6647   prim->verts = (tools_GL2PSvertex*)tools_gl2psMalloc(sizeof(tools_GL2PSvertex));
6648   prim->verts[0].xyz[0] = pos[0] + xorig;        6648   prim->verts[0].xyz[0] = pos[0] + xorig;
6649   prim->verts[0].xyz[1] = pos[1] + yorig;        6649   prim->verts[0].xyz[1] = pos[1] + yorig;
6650   prim->verts[0].xyz[2] = pos[2];                6650   prim->verts[0].xyz[2] = pos[2];
6651   prim->culled = 0;                              6651   prim->culled = 0;
6652   prim->offset = 0;                              6652   prim->offset = 0;
6653   prim->ofactor = 0.0;                           6653   prim->ofactor = 0.0;
6654   prim->ounits = 0.0;                            6654   prim->ounits = 0.0;
6655   prim->pattern = 0;                             6655   prim->pattern = 0;
6656   prim->factor = 0;                              6656   prim->factor = 0;
6657   prim->width = 1;                               6657   prim->width = 1;
6658   if (gl2ps->forcerasterpos) {                   6658   if (gl2ps->forcerasterpos) {
6659     prim->verts[0].rgba[0] = gl2ps->rasterpos    6659     prim->verts[0].rgba[0] = gl2ps->rasterpos.rgba[0];
6660     prim->verts[0].rgba[1] = gl2ps->rasterpos    6660     prim->verts[0].rgba[1] = gl2ps->rasterpos.rgba[1];
6661     prim->verts[0].rgba[2] = gl2ps->rasterpos    6661     prim->verts[0].rgba[2] = gl2ps->rasterpos.rgba[2];
6662     prim->verts[0].rgba[3] = gl2ps->rasterpos    6662     prim->verts[0].rgba[3] = gl2ps->rasterpos.rgba[3];
6663   }                                              6663   }
6664   else {                                         6664   else {
6665     tools_glGetFloatv(TOOLS_GL_CURRENT_RASTER    6665     tools_glGetFloatv(TOOLS_GL_CURRENT_RASTER_COLOR, prim->verts[0].rgba);
6666   }                                              6666   }
6667   prim->data.image = (tools_GL2PSimage*)tools    6667   prim->data.image = (tools_GL2PSimage*)tools_gl2psMalloc(sizeof(tools_GL2PSimage));
6668   prim->data.image->width = width;               6668   prim->data.image->width = width;
6669   prim->data.image->height = height;             6669   prim->data.image->height = height;
6670   prim->data.image->zoom_x = zoom_x;             6670   prim->data.image->zoom_x = zoom_x;
6671   prim->data.image->zoom_y = zoom_y;             6671   prim->data.image->zoom_y = zoom_y;
6672   prim->data.image->format = format;             6672   prim->data.image->format = format;
6673   prim->data.image->type = type;                 6673   prim->data.image->type = type;
6674                                                  6674 
6675   gl2ps->forcerasterpos = TOOLS_GL_FALSE;        6675   gl2ps->forcerasterpos = TOOLS_GL_FALSE;
6676                                                  6676 
6677   switch(format){                                6677   switch(format){
6678   case TOOLS_GL_RGBA:                            6678   case TOOLS_GL_RGBA:
6679     if(gl2ps->options & TOOLS_GL2PS_NO_BLENDI    6679     if(gl2ps->options & TOOLS_GL2PS_NO_BLENDING || !gl2ps->blending){
6680       /* special case: blending turned off */    6680       /* special case: blending turned off */
6681       prim->data.image->format = TOOLS_GL_RGB    6681       prim->data.image->format = TOOLS_GL_RGB;
6682       size = height * width * 3;                 6682       size = height * width * 3;
6683       prim->data.image->pixels = (tools_GLflo    6683       prim->data.image->pixels = (tools_GLfloat*)tools_gl2psMalloc(size * sizeof(tools_GLfloat));
6684       piv = (const tools_GLfloat*)pixels;        6684       piv = (const tools_GLfloat*)pixels;
6685       for(i = 0; i < size; ++i, ++piv){          6685       for(i = 0; i < size; ++i, ++piv){
6686         prim->data.image->pixels[i] = *piv;      6686         prim->data.image->pixels[i] = *piv;
6687         if(!((i + 1) % 3))                       6687         if(!((i + 1) % 3))
6688           ++piv;                                 6688           ++piv;
6689       }                                          6689       }
6690     }                                            6690     }
6691     else{                                        6691     else{
6692       size = height * width * 4;                 6692       size = height * width * 4;
6693       prim->data.image->pixels = (tools_GLflo    6693       prim->data.image->pixels = (tools_GLfloat*)tools_gl2psMalloc(size * sizeof(tools_GLfloat));
6694       memcpy(prim->data.image->pixels, pixels    6694       memcpy(prim->data.image->pixels, pixels, size * sizeof(tools_GLfloat));
6695     }                                            6695     }
6696     break;                                       6696     break;
6697   case TOOLS_GL_RGB:                             6697   case TOOLS_GL_RGB:
6698   default:                                       6698   default:
6699     size = height * width * 3;                   6699     size = height * width * 3;
6700     prim->data.image->pixels = (tools_GLfloat    6700     prim->data.image->pixels = (tools_GLfloat*)tools_gl2psMalloc(size * sizeof(tools_GLfloat));
6701     memcpy(prim->data.image->pixels, pixels,     6701     memcpy(prim->data.image->pixels, pixels, size * sizeof(tools_GLfloat));
6702     break;                                       6702     break;
6703   }                                              6703   }
6704                                                  6704 
6705   /* If no OpenGL context, just add directly     6705   /* If no OpenGL context, just add directly to primitives */
6706   if ((gl2ps->options & TOOLS_GL2PS_NO_OPENGL    6706   if ((gl2ps->options & TOOLS_GL2PS_NO_OPENGL_CONTEXT) == TOOLS_GL2PS_NONE) {
6707     tools_gl2psListAdd(gl2ps->auxprimitives,     6707     tools_gl2psListAdd(gl2ps->auxprimitives, &prim);
6708     tools_glPassThrough(TOOLS_GL2PS_DRAW_PIXE    6708     tools_glPassThrough(TOOLS_GL2PS_DRAW_PIXELS_TOKEN);
6709   }                                              6709   }
6710   else {                                         6710   else {
6711     tools_gl2psListAdd(gl2ps->primitives, &pr    6711     tools_gl2psListAdd(gl2ps->primitives, &prim);
6712   }                                              6712   }
6713                                                  6713 
6714   return TOOLS_GL2PS_SUCCESS;                    6714   return TOOLS_GL2PS_SUCCESS;
6715 }                                                6715 }
6716                                                  6716 
6717 TOOLS_GL2PSDLL_API tools_GLint tools_gl2psDra    6717 TOOLS_GL2PSDLL_API tools_GLint tools_gl2psDrawImageMap(tools_GL2PScontext* gl2ps, tools_GLsizei width, tools_GLsizei height,
6718                                      const to    6718                                      const tools_GLfloat position[3],
6719                                      const un    6719                                      const unsigned char *imagemap){
6720   int size, i;                                   6720   int size, i;
6721   int sizeoffloat = sizeof(tools_GLfloat);       6721   int sizeoffloat = sizeof(tools_GLfloat);
6722                                                  6722 
6723   if(/*!gl2ps ||*/ !imagemap) return TOOLS_GL    6723   if(/*!gl2ps ||*/ !imagemap) return TOOLS_GL2PS_UNINITIALIZED;
6724                                                  6724 
6725   if((width <= 0) || (height <= 0)) return TO    6725   if((width <= 0) || (height <= 0)) return TOOLS_GL2PS_ERROR;
6726                                                  6726 
6727   size = height + height * ((width - 1) / 8);    6727   size = height + height * ((width - 1) / 8);
6728   tools_glPassThrough(TOOLS_GL2PS_IMAGEMAP_TO    6728   tools_glPassThrough(TOOLS_GL2PS_IMAGEMAP_TOKEN);
6729   tools_glBegin(TOOLS_GL_POINTS);                6729   tools_glBegin(TOOLS_GL_POINTS);
6730   tools_glVertex3f(position[0], position[1],p    6730   tools_glVertex3f(position[0], position[1],position[2]);
6731   tools_glEnd();                                 6731   tools_glEnd();
6732   tools_glPassThrough((tools_GLfloat)width);     6732   tools_glPassThrough((tools_GLfloat)width);
6733   tools_glPassThrough((tools_GLfloat)height);    6733   tools_glPassThrough((tools_GLfloat)height);
6734   for(i = 0; i < size; i += sizeoffloat){        6734   for(i = 0; i < size; i += sizeoffloat){
6735     const float *value = (const float*)imagem    6735     const float *value = (const float*)imagemap;
6736     tools_glPassThrough(*value);                 6736     tools_glPassThrough(*value);
6737     imagemap += sizeoffloat;                     6737     imagemap += sizeoffloat;
6738   }                                              6738   }
6739   return TOOLS_GL2PS_SUCCESS;                    6739   return TOOLS_GL2PS_SUCCESS;
6740 }                                                6740 }
6741                                                  6741 
6742 TOOLS_GL2PSDLL_API tools_GLint tools_gl2psEna    6742 TOOLS_GL2PSDLL_API tools_GLint tools_gl2psEnable(tools_GL2PScontext* gl2ps, tools_GLint mode)
6743 {                                                6743 {
6744   tools_GLint tmp;                               6744   tools_GLint tmp;
6745   tools_GLfloat tmp2;                            6745   tools_GLfloat tmp2;
6746                                                  6746 
6747 /*if(!gl2ps) return TOOLS_GL2PS_UNINITIALIZED    6747 /*if(!gl2ps) return TOOLS_GL2PS_UNINITIALIZED;*/
6748                                                  6748 
6749   switch(mode){                                  6749   switch(mode){
6750   case TOOLS_GL2PS_POLYGON_OFFSET_FILL :         6750   case TOOLS_GL2PS_POLYGON_OFFSET_FILL :
6751     tools_glPassThrough(TOOLS_GL2PS_BEGIN_OFF    6751     tools_glPassThrough(TOOLS_GL2PS_BEGIN_OFFSET_TOKEN);
6752     tools_glGetFloatv(TOOLS_GL_POLYGON_OFFSET    6752     tools_glGetFloatv(TOOLS_GL_POLYGON_OFFSET_FACTOR, &tmp2);
6753     tools_glPassThrough(tmp2);                   6753     tools_glPassThrough(tmp2);
6754     tools_glGetFloatv(TOOLS_GL_POLYGON_OFFSET    6754     tools_glGetFloatv(TOOLS_GL_POLYGON_OFFSET_UNITS, &tmp2);
6755     tools_glPassThrough(tmp2);                   6755     tools_glPassThrough(tmp2);
6756     break;                                       6756     break;
6757   case TOOLS_GL2PS_POLYGON_BOUNDARY :            6757   case TOOLS_GL2PS_POLYGON_BOUNDARY :
6758     tools_glPassThrough(TOOLS_GL2PS_BEGIN_BOU    6758     tools_glPassThrough(TOOLS_GL2PS_BEGIN_BOUNDARY_TOKEN);
6759     break;                                       6759     break;
6760   case TOOLS_GL2PS_LINE_STIPPLE :                6760   case TOOLS_GL2PS_LINE_STIPPLE :
6761     tools_glPassThrough(TOOLS_GL2PS_BEGIN_STI    6761     tools_glPassThrough(TOOLS_GL2PS_BEGIN_STIPPLE_TOKEN);
6762     tools_glGetIntegerv(TOOLS_GL_LINE_STIPPLE    6762     tools_glGetIntegerv(TOOLS_GL_LINE_STIPPLE_PATTERN, &tmp);
6763     tools_glPassThrough((tools_GLfloat)tmp);     6763     tools_glPassThrough((tools_GLfloat)tmp);
6764     tools_glGetIntegerv(TOOLS_GL_LINE_STIPPLE    6764     tools_glGetIntegerv(TOOLS_GL_LINE_STIPPLE_REPEAT, &tmp);
6765     tools_glPassThrough((tools_GLfloat)tmp);     6765     tools_glPassThrough((tools_GLfloat)tmp);
6766     break;                                       6766     break;
6767   case TOOLS_GL2PS_BLEND :                       6767   case TOOLS_GL2PS_BLEND :
6768     tools_glPassThrough(TOOLS_GL2PS_BEGIN_BLE    6768     tools_glPassThrough(TOOLS_GL2PS_BEGIN_BLEND_TOKEN);
6769     break;                                       6769     break;
6770   default :                                      6770   default :
6771     tools_gl2psMsg(TOOLS_GL2PS_WARNING, "Unkn    6771     tools_gl2psMsg(TOOLS_GL2PS_WARNING, "Unknown mode in tools_gl2psEnable: %d", mode);
6772     return TOOLS_GL2PS_WARNING;                  6772     return TOOLS_GL2PS_WARNING;
6773   }                                              6773   }
6774                                                  6774 
6775   return TOOLS_GL2PS_SUCCESS;                    6775   return TOOLS_GL2PS_SUCCESS;
6776 }                                                6776 }
6777                                                  6777 
6778 TOOLS_GL2PSDLL_API tools_GLint tools_gl2psDis    6778 TOOLS_GL2PSDLL_API tools_GLint tools_gl2psDisable(tools_GL2PScontext* gl2ps, tools_GLint mode)
6779 {                                                6779 {
6780 /*if(!gl2ps) return TOOLS_GL2PS_UNINITIALIZED    6780 /*if(!gl2ps) return TOOLS_GL2PS_UNINITIALIZED;*/
6781                                                  6781 
6782   switch(mode){                                  6782   switch(mode){
6783   case TOOLS_GL2PS_POLYGON_OFFSET_FILL :         6783   case TOOLS_GL2PS_POLYGON_OFFSET_FILL :
6784     tools_glPassThrough(TOOLS_GL2PS_END_OFFSE    6784     tools_glPassThrough(TOOLS_GL2PS_END_OFFSET_TOKEN);
6785     break;                                       6785     break;
6786   case TOOLS_GL2PS_POLYGON_BOUNDARY :            6786   case TOOLS_GL2PS_POLYGON_BOUNDARY :
6787     tools_glPassThrough(TOOLS_GL2PS_END_BOUND    6787     tools_glPassThrough(TOOLS_GL2PS_END_BOUNDARY_TOKEN);
6788     break;                                       6788     break;
6789   case TOOLS_GL2PS_LINE_STIPPLE :                6789   case TOOLS_GL2PS_LINE_STIPPLE :
6790     tools_glPassThrough(TOOLS_GL2PS_END_STIPP    6790     tools_glPassThrough(TOOLS_GL2PS_END_STIPPLE_TOKEN);
6791     break;                                       6791     break;
6792   case TOOLS_GL2PS_BLEND :                       6792   case TOOLS_GL2PS_BLEND :
6793     tools_glPassThrough(TOOLS_GL2PS_END_BLEND    6793     tools_glPassThrough(TOOLS_GL2PS_END_BLEND_TOKEN);
6794     break;                                       6794     break;
6795   default :                                      6795   default :
6796     tools_gl2psMsg(TOOLS_GL2PS_WARNING, "Unkn    6796     tools_gl2psMsg(TOOLS_GL2PS_WARNING, "Unknown mode in tools_gl2psDisable: %d", mode);
6797     return TOOLS_GL2PS_WARNING;                  6797     return TOOLS_GL2PS_WARNING;
6798   }                                              6798   }
6799                                                  6799 
6800   return TOOLS_GL2PS_SUCCESS;                    6800   return TOOLS_GL2PS_SUCCESS;
6801 }                                                6801 }
6802                                                  6802 
6803 TOOLS_GL2PSDLL_API tools_GLint tools_gl2psPoi    6803 TOOLS_GL2PSDLL_API tools_GLint tools_gl2psPointSize(tools_GL2PScontext* gl2ps, tools_GLfloat value)
6804 {                                                6804 {
6805 /*if(!gl2ps) return TOOLS_GL2PS_UNINITIALIZED    6805 /*if(!gl2ps) return TOOLS_GL2PS_UNINITIALIZED;*/
6806                                                  6806 
6807   tools_glPassThrough(TOOLS_GL2PS_POINT_SIZE_    6807   tools_glPassThrough(TOOLS_GL2PS_POINT_SIZE_TOKEN);
6808   tools_glPassThrough(value);                    6808   tools_glPassThrough(value);
6809                                                  6809 
6810   return TOOLS_GL2PS_SUCCESS;                    6810   return TOOLS_GL2PS_SUCCESS;
6811 }                                                6811 }
6812                                                  6812 
6813 TOOLS_GL2PSDLL_API tools_GLint tools_gl2psLin    6813 TOOLS_GL2PSDLL_API tools_GLint tools_gl2psLineCap(tools_GL2PScontext* gl2ps, tools_GLint value)
6814 {                                                6814 {
6815 /*if(!gl2ps) return TOOLS_GL2PS_UNINITIALIZED    6815 /*if(!gl2ps) return TOOLS_GL2PS_UNINITIALIZED;*/
6816                                                  6816 
6817   tools_glPassThrough(TOOLS_GL2PS_LINE_CAP_TO    6817   tools_glPassThrough(TOOLS_GL2PS_LINE_CAP_TOKEN);
6818   tools_glPassThrough(value);                    6818   tools_glPassThrough(value);
6819                                                  6819 
6820   return TOOLS_GL2PS_SUCCESS;                    6820   return TOOLS_GL2PS_SUCCESS;
6821 }                                                6821 }
6822                                                  6822 
6823 TOOLS_GL2PSDLL_API tools_GLint tools_gl2psLin    6823 TOOLS_GL2PSDLL_API tools_GLint tools_gl2psLineJoin(tools_GL2PScontext* gl2ps, tools_GLint value)
6824 {                                                6824 {
6825 /*if(!gl2ps) return TOOLS_GL2PS_UNINITIALIZED    6825 /*if(!gl2ps) return TOOLS_GL2PS_UNINITIALIZED;*/
6826                                                  6826 
6827   tools_glPassThrough(TOOLS_GL2PS_LINE_JOIN_T    6827   tools_glPassThrough(TOOLS_GL2PS_LINE_JOIN_TOKEN);
6828   tools_glPassThrough((tools_GLfloat)value);     6828   tools_glPassThrough((tools_GLfloat)value);  //G.Barrand : _MSC_VER : cast.
6829                                                  6829 
6830   return TOOLS_GL2PS_SUCCESS;                    6830   return TOOLS_GL2PS_SUCCESS;
6831 }                                                6831 }
6832                                                  6832 
6833 TOOLS_GL2PSDLL_API tools_GLint tools_gl2psLin    6833 TOOLS_GL2PSDLL_API tools_GLint tools_gl2psLineWidth(tools_GL2PScontext* gl2ps, tools_GLfloat value)
6834 {                                                6834 {
6835 /*if(!gl2ps) return TOOLS_GL2PS_UNINITIALIZED    6835 /*if(!gl2ps) return TOOLS_GL2PS_UNINITIALIZED;*/
6836                                                  6836 
6837   tools_glPassThrough(TOOLS_GL2PS_LINE_WIDTH_    6837   tools_glPassThrough(TOOLS_GL2PS_LINE_WIDTH_TOKEN);
6838   tools_glPassThrough(value);                    6838   tools_glPassThrough(value);
6839                                                  6839 
6840   return TOOLS_GL2PS_SUCCESS;                    6840   return TOOLS_GL2PS_SUCCESS;
6841 }                                                6841 }
6842                                                  6842 
6843 TOOLS_GL2PSDLL_API tools_GLint tools_gl2psBle    6843 TOOLS_GL2PSDLL_API tools_GLint tools_gl2psBlendFunc(tools_GL2PScontext* gl2ps, tools_GLenum sfactor, tools_GLenum dfactor)
6844 {                                                6844 {
6845 /*if(!gl2ps) return TOOLS_GL2PS_UNINITIALIZED    6845 /*if(!gl2ps) return TOOLS_GL2PS_UNINITIALIZED;*/
6846                                                  6846 
6847   if(TOOLS_GL_FALSE == tools_gl2psSupportedBl    6847   if(TOOLS_GL_FALSE == tools_gl2psSupportedBlendMode(sfactor, dfactor))
6848     return TOOLS_GL2PS_WARNING;                  6848     return TOOLS_GL2PS_WARNING;
6849                                                  6849 
6850   tools_glPassThrough(TOOLS_GL2PS_SRC_BLEND_T    6850   tools_glPassThrough(TOOLS_GL2PS_SRC_BLEND_TOKEN);
6851   tools_glPassThrough((tools_GLfloat)sfactor)    6851   tools_glPassThrough((tools_GLfloat)sfactor);
6852   tools_glPassThrough(TOOLS_GL2PS_DST_BLEND_T    6852   tools_glPassThrough(TOOLS_GL2PS_DST_BLEND_TOKEN);
6853   tools_glPassThrough((tools_GLfloat)dfactor)    6853   tools_glPassThrough((tools_GLfloat)dfactor);
6854                                                  6854 
6855   return TOOLS_GL2PS_SUCCESS;                    6855   return TOOLS_GL2PS_SUCCESS;
6856 }                                                6856 }
6857                                                  6857 
6858 TOOLS_GL2PSDLL_API tools_GLint tools_gl2psSet    6858 TOOLS_GL2PSDLL_API tools_GLint tools_gl2psSetOptions(tools_GL2PScontext* gl2ps, tools_GLint options)
6859 {                                                6859 {
6860 /*if(!gl2ps) return TOOLS_GL2PS_UNINITIALIZED    6860 /*if(!gl2ps) return TOOLS_GL2PS_UNINITIALIZED;*/
6861                                                  6861 
6862   if(tools_gl2psCheckOptions(options, gl2ps->    6862   if(tools_gl2psCheckOptions(options, gl2ps->colormode) == TOOLS_GL_FALSE) {
6863     return TOOLS_GL2PS_ERROR;                    6863     return TOOLS_GL2PS_ERROR;
6864   }                                              6864   }
6865                                                  6865 
6866   gl2ps->options = options;                      6866   gl2ps->options = options;
6867                                                  6867 
6868   return TOOLS_GL2PS_SUCCESS;                    6868   return TOOLS_GL2PS_SUCCESS;
6869 }                                                6869 }
6870                                                  6870 
6871 TOOLS_GL2PSDLL_API tools_GLint tools_gl2psGet    6871 TOOLS_GL2PSDLL_API tools_GLint tools_gl2psGetOptions(tools_GL2PScontext* gl2ps, tools_GLint *options)
6872 {                                                6872 {
6873 /*if(!gl2ps) {                                   6873 /*if(!gl2ps) {
6874     *options = 0;                                6874     *options = 0;
6875     return TOOLS_GL2PS_UNINITIALIZED;            6875     return TOOLS_GL2PS_UNINITIALIZED;
6876   }*/                                            6876   }*/
6877                                                  6877 
6878   *options = gl2ps->options;                     6878   *options = gl2ps->options;
6879                                                  6879 
6880   return TOOLS_GL2PS_SUCCESS;                    6880   return TOOLS_GL2PS_SUCCESS;
6881 }                                                6881 }
6882                                                  6882 
6883 TOOLS_GL2PSDLL_API const char *tools_gl2psGet    6883 TOOLS_GL2PSDLL_API const char *tools_gl2psGetFileExtension(tools_GLint format)
6884 {                                                6884 {
6885   if(format >= 0 && format < (tools_GLint)(si    6885   if(format >= 0 && format < (tools_GLint)(sizeof(tools_gl2psbackends) / sizeof(tools_gl2psbackends[0])))
6886     return tools_gl2psbackends[format]->file_    6886     return tools_gl2psbackends[format]->file_extension;
6887   else                                           6887   else
6888     return "Unknown format";                     6888     return "Unknown format";
6889 }                                                6889 }
6890                                                  6890 
6891 TOOLS_GL2PSDLL_API const char *tools_gl2psGet    6891 TOOLS_GL2PSDLL_API const char *tools_gl2psGetFormatDescription(tools_GLint format)
6892 {                                                6892 {
6893   if(format >= 0 && format < (tools_GLint)(si    6893   if(format >= 0 && format < (tools_GLint)(sizeof(tools_gl2psbackends) / sizeof(tools_gl2psbackends[0])))
6894     return tools_gl2psbackends[format]->descr    6894     return tools_gl2psbackends[format]->description;
6895   else                                           6895   else
6896     return "Unknown format";                     6896     return "Unknown format";
6897 }                                                6897 }
6898                                                  6898 
6899 TOOLS_GL2PSDLL_API tools_GLint tools_gl2psGet    6899 TOOLS_GL2PSDLL_API tools_GLint tools_gl2psGetFileFormat(tools_GL2PScontext* gl2ps)
6900 {                                                6900 {
6901 /*if(!gl2ps) {                                   6901 /*if(!gl2ps) {
6902     return TOOLS_GL2PS_UNINITIALIZED;            6902     return TOOLS_GL2PS_UNINITIALIZED;
6903   }*/                                            6903   }*/
6904                                                  6904 
6905   return gl2ps->format;                          6905   return gl2ps->format;
6906 }                                                6906 }
6907                                                  6907 
6908 TOOLS_GL2PSDLL_API tools_GLint tools_gl2psFor    6908 TOOLS_GL2PSDLL_API tools_GLint tools_gl2psForceRasterPos(tools_GL2PScontext* gl2ps, tools_GL2PSvertex *vert)
6909 {                                                6909 {
6910                                                  6910 
6911 /*if(!gl2ps) {                                   6911 /*if(!gl2ps) {
6912     return TOOLS_GL2PS_UNINITIALIZED;            6912     return TOOLS_GL2PS_UNINITIALIZED;
6913   }*/                                            6913   }*/
6914                                                  6914 
6915   gl2ps->forcerasterpos = TOOLS_GL_TRUE;         6915   gl2ps->forcerasterpos = TOOLS_GL_TRUE;
6916   gl2ps->rasterpos.xyz[0] = vert->xyz[0];        6916   gl2ps->rasterpos.xyz[0] = vert->xyz[0];
6917   gl2ps->rasterpos.xyz[1] = vert->xyz[1];        6917   gl2ps->rasterpos.xyz[1] = vert->xyz[1];
6918   gl2ps->rasterpos.xyz[2] = vert->xyz[2];        6918   gl2ps->rasterpos.xyz[2] = vert->xyz[2];
6919   gl2ps->rasterpos.rgba[0] = vert->rgba[0];      6919   gl2ps->rasterpos.rgba[0] = vert->rgba[0];
6920   gl2ps->rasterpos.rgba[1] = vert->rgba[1];      6920   gl2ps->rasterpos.rgba[1] = vert->rgba[1];
6921   gl2ps->rasterpos.rgba[2] = vert->rgba[2];      6921   gl2ps->rasterpos.rgba[2] = vert->rgba[2];
6922   gl2ps->rasterpos.rgba[3] = vert->rgba[3];      6922   gl2ps->rasterpos.rgba[3] = vert->rgba[3];
6923                                                  6923 
6924   return TOOLS_GL2PS_SUCCESS;                    6924   return TOOLS_GL2PS_SUCCESS;
6925 }                                                6925 }
6926                                                  6926 
6927 TOOLS_GL2PSDLL_API tools_GLint tools_gl2psSet    6927 TOOLS_GL2PSDLL_API tools_GLint tools_gl2psSetTexScaling(tools_GL2PScontext* gl2ps, tools_GLfloat scaling)
6928 {                                                6928 {
6929                                                  6929 
6930 /*if(!gl2ps) {                                   6930 /*if(!gl2ps) {
6931     return TOOLS_GL2PS_UNINITIALIZED;            6931     return TOOLS_GL2PS_UNINITIALIZED;
6932   }*/                                            6932   }*/
6933   gl2ps->tex_scaling = scaling;                  6933   gl2ps->tex_scaling = scaling;
6934                                                  6934 
6935   return TOOLS_GL2PS_SUCCESS;                    6935   return TOOLS_GL2PS_SUCCESS;
6936 }                                                6936 }
6937                                                  6937 
6938 TOOLS_GL2PSDLL_API tools_GLint tools_gl2psSet    6938 TOOLS_GL2PSDLL_API tools_GLint tools_gl2psSetBackgroundColor(tools_GL2PScontext* gl2ps, float a_r,float a_g,float a_b)
6939 {                                                6939 {
6940 /*if(!gl2ps) return TOOLS_GL2PS_UNINITIALIZED    6940 /*if(!gl2ps) return TOOLS_GL2PS_UNINITIALIZED;*/
6941                                                  6941 
6942   gl2ps->bgcolor[0] = a_r;                       6942   gl2ps->bgcolor[0] = a_r;
6943   gl2ps->bgcolor[1] = a_g;                       6943   gl2ps->bgcolor[1] = a_g;
6944   gl2ps->bgcolor[2] = a_b;                       6944   gl2ps->bgcolor[2] = a_b;
6945   gl2ps->bgcolor[3] = 1.0F;                      6945   gl2ps->bgcolor[3] = 1.0F;
6946                                                  6946 
6947   return TOOLS_GL2PS_SUCCESS;                    6947   return TOOLS_GL2PS_SUCCESS;
6948 }                                                6948 }
6949                                                  6949 
6950 #undef TOOLS_GL2PS_EPSILON                       6950 #undef TOOLS_GL2PS_EPSILON
6951 #undef TOOLS_GL2PS_ZSCALE                        6951 #undef TOOLS_GL2PS_ZSCALE
6952 #undef TOOLS_GL2PS_ZOFFSET                       6952 #undef TOOLS_GL2PS_ZOFFSET
6953 #undef TOOLS_GL2PS_ZOFFSET_LARGE                 6953 #undef TOOLS_GL2PS_ZOFFSET_LARGE
6954 #undef TOOLS_GL2PS_ZERO                          6954 #undef TOOLS_GL2PS_ZERO
6955 #undef TOOLS_GL2PS_COINCIDENT                    6955 #undef TOOLS_GL2PS_COINCIDENT
6956 #undef TOOLS_GL2PS_IN_FRONT_OF                   6956 #undef TOOLS_GL2PS_IN_FRONT_OF
6957 #undef TOOLS_GL2PS_IN_BACK_OF                    6957 #undef TOOLS_GL2PS_IN_BACK_OF
6958 #undef TOOLS_GL2PS_SPANNING                      6958 #undef TOOLS_GL2PS_SPANNING
6959 #undef TOOLS_GL2PS_POINT_COINCIDENT              6959 #undef TOOLS_GL2PS_POINT_COINCIDENT
6960 #undef TOOLS_GL2PS_POINT_INFRONT                 6960 #undef TOOLS_GL2PS_POINT_INFRONT
6961 #undef TOOLS_GL2PS_POINT_BACK                    6961 #undef TOOLS_GL2PS_POINT_BACK
6962 #undef TOOLS_GL2PS_BEGIN_OFFSET_TOKEN            6962 #undef TOOLS_GL2PS_BEGIN_OFFSET_TOKEN
6963 #undef TOOLS_GL2PS_END_OFFSET_TOKEN              6963 #undef TOOLS_GL2PS_END_OFFSET_TOKEN
6964 #undef TOOLS_GL2PS_BEGIN_BOUNDARY_TOKEN          6964 #undef TOOLS_GL2PS_BEGIN_BOUNDARY_TOKEN
6965 #undef TOOLS_GL2PS_END_BOUNDARY_TOKEN            6965 #undef TOOLS_GL2PS_END_BOUNDARY_TOKEN
6966 #undef TOOLS_GL2PS_BEGIN_STIPPLE_TOKEN           6966 #undef TOOLS_GL2PS_BEGIN_STIPPLE_TOKEN
6967 #undef TOOLS_GL2PS_END_STIPPLE_TOKEN             6967 #undef TOOLS_GL2PS_END_STIPPLE_TOKEN
6968 #undef TOOLS_GL2PS_POINT_SIZE_TOKEN              6968 #undef TOOLS_GL2PS_POINT_SIZE_TOKEN
6969 #undef TOOLS_GL2PS_LINE_CAP_TOKEN                6969 #undef TOOLS_GL2PS_LINE_CAP_TOKEN
6970 #undef TOOLS_GL2PS_LINE_JOIN_TOKEN               6970 #undef TOOLS_GL2PS_LINE_JOIN_TOKEN
6971 #undef TOOLS_GL2PS_LINE_WIDTH_TOKEN              6971 #undef TOOLS_GL2PS_LINE_WIDTH_TOKEN
6972 #undef TOOLS_GL2PS_BEGIN_BLEND_TOKEN             6972 #undef TOOLS_GL2PS_BEGIN_BLEND_TOKEN
6973 #undef TOOLS_GL2PS_END_BLEND_TOKEN               6973 #undef TOOLS_GL2PS_END_BLEND_TOKEN
6974 #undef TOOLS_GL2PS_SRC_BLEND_TOKEN               6974 #undef TOOLS_GL2PS_SRC_BLEND_TOKEN
6975 #undef TOOLS_GL2PS_DST_BLEND_TOKEN               6975 #undef TOOLS_GL2PS_DST_BLEND_TOKEN
6976 #undef TOOLS_GL2PS_IMAGEMAP_TOKEN                6976 #undef TOOLS_GL2PS_IMAGEMAP_TOKEN
6977 #undef TOOLS_GL2PS_DRAW_PIXELS_TOKEN             6977 #undef TOOLS_GL2PS_DRAW_PIXELS_TOKEN
6978 #undef TOOLS_GL2PS_TEXT_TOKEN                    6978 #undef TOOLS_GL2PS_TEXT_TOKEN
6979                                                  6979 
6980 #endif /*tools_gl2ps*/                           6980 #endif /*tools_gl2ps*/