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