Ignore:
Timestamp:
Mar 4, 2009, 3:13:51 PM (15 years ago)
Author:
garnier
Message:

Update gl2ps to 1.3.3 version of Feb 2009

Location:
trunk/source/visualization/externals/gl2ps
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/source/visualization/externals/gl2ps/History

    r930 r937  
    1 $Id: History,v 1.1 2009/02/18 09:54:12 lgarnier Exp $
     1$Id: History,v 1.2 2009/03/04 14:13:42 lgarnier Exp $
    22-------------------------------------------------------------------
    33
     
    1818     ----------------------------------------------------------
    1919
     204 March 2009, Laurent Garnier
     21 - Update gl2ps to 1.3.3 version (before it was 0.8)
     22
    202316 February 2009, Laurent Garnier
    2124 - Creation of this library in order to have a gl2ps for all viewers.
  • trunk/source/visualization/externals/gl2ps/include/Geant4_gl2ps.h

    r919 r937  
    2727#define Geant4_gl2ps_h
    2828
    29 // gl2ps-0.73.
     29// gl2ps-1.3.3
    3030// The gl2ps code is prefixed by Geant4_ in order
    3131// to avoid clashes with other gl2ps code that may come at link
     
    3939#define gl2psPointSize Geant4_gl2psPointSize
    4040#define gl2psLineWidth Geant4_gl2psLineWidth
    41 #define gl2psNumShadeColors Geant4_gl2psNumShadeColors
    4241#define gl2psDrawPixels Geant4_gl2psDrawPixels
    4342#define gl2psBeginViewport Geant4_gl2psBeginViewport
    4443#define gl2psEndViewport Geant4_gl2psEndViewport
     44#define gl2psTextOpt Geant4_gl2psTextOpt
     45#define gl2psSetOptions Geant4_gl2psSetOptions
     46#define gl2psGetOptions Geant4_gl2psGetOptions
     47#define gl2psSpecial Geant4_gl2psSpecial
     48#define gl2psBlendFunc Geant4_gl2psBlendFunc
     49#define gl2psDrawImageMap Geant4_gl2psDrawImageMap
     50#define gl2psGetFileExtension Geant4_gl2psGetFileExtension
     51#define gl2psGetFormatDescription Geant4_gl2psGetFormatDescription
    4552
    4653#define gl2psMsg Geant4_gl2psMsg
     
    4855#define gl2psRealloc Geant4_gl2psRealloc
    4956#define gl2psFree Geant4_gl2psFree
     57#define gl2psWriteBigEndian Geant4_gl2psWriteBigEndian
     58#define gl2psSetupCompress Geant4_gl2psSetupCompress
     59#define gl2psFreeCompress Geant4_gl2psFreeCompress
     60#define gl2psAllocCompress Geant4_gl2psAllocCompress
     61#define gl2psReallocCompress Geant4_gl2psReallocCompress
     62#define gl2psWriteBigEndianCompress Geant4_gl2psWriteBigEndianCompress
     63#define gl2psDeflate Geant4_gl2psDeflate
     64#define gl2psPrintf Geant4_gl2psPrintf
     65#define gl2psPrintGzipHeader Geant4_gl2psPrintGzipHeader
     66#define gl2psPrintGzipFooter Geant4_gl2psPrintGzipFooter
     67#define gl2psListReset Geant4_gl2psListReset
    5068#define gl2psListRealloc Geant4_gl2psListRealloc
    5169#define gl2psListCreate Geant4_gl2psListCreate
     
    5775#define gl2psListAction Geant4_gl2psListAction
    5876#define gl2psListActionInverse Geant4_gl2psListActionInverse
     77#define gl2psListRead Geant4_gl2psListRead
     78#define gl2psEncodeBase64Block Geant4_gl2psEncodeBase64Block
     79#define gl2psListEncodeBase64 Geant4_gl2psListEncodeBase64
     80#define gl2psSameColor Geant4_gl2psSameColor
     81#define gl2psVertsSameColor Geant4_gl2psVertsSameColor
     82#define gl2psSameColorThreshold Geant4_gl2psSameColorThreshold
     83#define gl2psSetLastColor Geant4_gl2psSetLastColor
     84#define gl2psGetRGB Geant4_gl2psGetRGB
     85#define gl2psCopyPixmap Geant4_gl2psCopyPixmap
     86#define gl2psFreePixmap Geant4_gl2psFreePixmap
     87#define gl2psUserWritePNG Geant4_gl2psUserWritePNG
     88#define gl2psUserFlushPNG Geant4_gl2psUserFlushPNG
     89#define gl2psConvertPixmapToPNG Geant4_gl2psConvertPixmapToPNG
     90#define gl2psAddText Geant4_gl2psAddText
     91#define gl2psCopyText Geant4_gl2psCopyText
     92#define gl2psFreeText Geant4_gl2psFreeText
     93#define gl2psSupportedBlendMode Geant4_gl2psSupportedBlendMode
     94#define gl2psAdaptVertexForBlending Geant4_gl2psAdaptVertexForBlending
     95#define gl2psAssignTriangleProperties Geant4_gl2psAssignTriangleProperties
     96#define gl2psFillTriangleFromPrimitive Geant4_gl2psFillTriangleFromPrimitive
     97#define gl2psInitTriangle Geant4_gl2psInitTriangle
     98#define gl2psCopyPrimitive Geant4_gl2psCopyPrimitive
     99#define gl2psSamePosition Geant4_gl2psSamePosition
    59100#define gl2psComparePointPlane Geant4_gl2psComparePointPlane
    60101#define gl2psPsca Geant4_gl2psPsca
     
    73114#define gl2psTrianglesFirst Geant4_gl2psTrianglesFirst
    74115#define gl2psFindRoot Geant4_gl2psFindRoot
     116#define gl2psFreeImagemap Geant4_gl2psFreeImagemap
    75117#define gl2psFreePrimitive Geant4_gl2psFreePrimitive
    76118#define gl2psAddPrimitiveInList Geant4_gl2psAddPrimitiveInList
     
    80122#define gl2psBuildBspTree Geant4_gl2psBuildBspTree
    81123#define gl2psTraverseBspTree Geant4_gl2psTraverseBspTree
     124#define gl2psRescaleAndOffset Geant4_gl2psRescaleAndOffset
    82125#define gl2psGetPlaneFromPoints Geant4_gl2psGetPlaneFromPoints
    83126#define gl2psFreeBspImageTree Geant4_gl2psFreeBspImageTree
     
    88131#define gl2psSplitPrimitive2D Geant4_gl2psSplitPrimitive2D
    89132#define gl2psAddInImageTree Geant4_gl2psAddInImageTree
    90 #define gl2psAddInImage Geant4_gl2psAddInImage
     133#define gl2psAddInBspImageTree Geant4_gl2psAddInBspImageTree
    91134#define gl2psAddBoundaryInList Geant4_gl2psAddBoundaryInList
    92135#define gl2psBuildPolygonBoundary Geant4_gl2psBuildPolygonBoundary
     
    94137#define gl2psGetVertex Geant4_gl2psGetVertex
    95138#define gl2psParseFeedbackBuffer Geant4_gl2psParseFeedbackBuffer
    96 #define gl2psSameColor Geant4_gl2psSameColor
    97 #define gl2psVertsSameColor Geant4_gl2psVertsSameColor
     139#define gl2psWriteByte Geant4_gl2psWriteByte
     140#define gl2psPrintPostScriptPixmap Geant4_gl2psPrintPostScriptPixmap
     141#define gl2psPrintPostScriptImagemap Geant4_gl2psPrintPostScriptImagemap
    98142#define gl2psPrintPostScriptHeader Geant4_gl2psPrintPostScriptHeader
    99143#define gl2psPrintPostScriptColor Geant4_gl2psPrintPostScriptColor
    100144#define gl2psResetPostScriptColor Geant4_gl2psResetPostScriptColor
     145#define gl2psEndPostScriptLine Geant4_gl2psEndPostScriptLine
     146#define gl2psParseStipplePattern Geant4_gl2psParseStipplePattern
     147#define gl2psPrintPostScriptDash Geant4_gl2psPrintPostScriptDash
    101148#define gl2psPrintPostScriptPrimitive Geant4_gl2psPrintPostScriptPrimitive
    102149#define gl2psPrintPostScriptFooter Geant4_gl2psPrintPostScriptFooter
     
    108155#define gl2psPrintPostScriptEndViewport Geant4_gl2psPrintPostScriptEndViewport
    109156
    110 #define gl2psWriteByte Geant4_gl2psWriteByte
    111 #define gl2psGetRGB Geant4_gl2psGetRGB
    112 #define gl2psPrintPostScriptPixmap Geant4_gl2psPrintPostScriptPixmap
    113 #define gl2psListReset Geant4_gl2psListReset
    114 #define gl2psAddInBspImageTree Geant4_gl2psAddInBspImageTree
     157#define gl2psPrintPostScriptFinalPrimitive Geant4_gl2psPrintPostScriptFinalPrimitive
    115158#define gl2psPrintPrimitives Geant4_gl2psPrintPrimitives
    116159#define gl2psPrintTeXBeginViewport Geant4_gl2psPrintTeXBeginViewport
    117160#define gl2psPrintTeXEndViewport Geant4_gl2psPrintTeXEndViewport
     161#define gl2psPrintTeXFinalPrimitive Geant4_gl2psPrintTeXFinalPrimitive
     162#define gl2psPrintPDFCompressorType Geant4_gl2psPrintPDFCompressorType
     163#define gl2psPrintPDFStrokeColor Geant4_gl2psPrintPDFStrokeColor
     164#define gl2psPrintPDFFillColor Geant4_gl2psPrintPDFFillColor
     165#define gl2psPrintPDFLineWidth Geant4_gl2psPrintPDFLineWidth
     166#define gl2psPutPDFText Geant4_gl2psPutPDFText
     167#define gl2psPutPDFImage Geant4_gl2psPutPDFImage
     168#define gl2psPDFstacksInit Geant4_gl2psPDFstacksInit
     169#define gl2psPDFgroupObjectInit Geant4_gl2psPDFgroupObjectInit
     170#define gl2psPDFgroupListInit Geant4_gl2psPDFgroupListInit
     171#define gl2psSortOutTrianglePDFgroup Geant4_gl2psSortOutTrianglePDFgroup
     172#define gl2psPDFgroupListWriteMainStream Geant4_gl2psPDFgroupListWriteMainStream
     173#define gl2psPDFgroupListWriteGStateResources Geant4_gl2psPDFgroupListWriteGStateResources
     174#define gl2psPDFgroupListWriteShaderResources Geant4_gl2psPDFgroupListWriteShaderResources
     175#define gl2psPDFgroupListWriteXObjectResources Geant4_gl2psPDFgroupListWriteXObjectResources
     176#define gl2psPDFgroupListWriteFontResources Geant4_gl2psPDFgroupListWriteFontResources
     177#define gl2psPDFgroupListDelete Geant4_gl2psPDFgroupListDelete
     178#define gl2psPrintPDFInfo Geant4_gl2psPrintPDFInfo
     179#define gl2psPrintPDFCatalog Geant4_gl2psPrintPDFCatalog
     180#define gl2psPrintPDFPages Geant4_gl2psPrintPDFPages
     181#define gl2psOpenPDFDataStream Geant4_gl2psOpenPDFDataStream
     182#define gl2psOpenPDFDataStreamWritePreface Geant4_gl2psOpenPDFDataStreamWritePreface
     183#define gl2psPrintPDFHeader Geant4_gl2psPrintPDFHeader
     184#define gl2psPrintPDFPrimitive Geant4_gl2psPrintPDFPrimitive
     185#define gl2psClosePDFDataStream Geant4_gl2psClosePDFDataStream
     186#define gl2psPrintPDFDataStreamLength Geant4_gl2psPrintPDFDataStreamLength
     187#define gl2psPrintPDFOpenPage Geant4_gl2psPrintPDFOpenPage
     188#define gl2psPDFgroupListWriteVariableResources Geant4_gl2psPDFgroupListWriteVariableResources
     189#define gl2psPrintPDFGSObject Geant4_gl2psPrintPDFGSObject
     190#define gl2psPrintPDFShaderStreamDataCoord Geant4_gl2psPrintPDFShaderStreamDataCoord
     191#define gl2psPrintPDFShaderStreamDataRGB Geant4_gl2psPrintPDFShaderStreamDataRGB
     192#define gl2psPrintPDFShaderStreamDataAlpha Geant4_gl2psPrintPDFShaderStreamDataAlpha
     193#define gl2psPrintPDFShaderStreamData Geant4_gl2psPrintPDFShaderStreamData
     194#define gl2psPDFRectHull Geant4_gl2psPDFRectHull
     195#define gl2psPrintPDFShader Geant4_gl2psPrintPDFShader
     196#define gl2psPrintPDFShaderMask Geant4_gl2psPrintPDFShaderMask
     197#define gl2psPrintPDFShaderExtGS Geant4_gl2psPrintPDFShaderExtGS
     198#define gl2psPrintPDFShaderSimpleExtGS Geant4_gl2psPrintPDFShaderSimpleExtGS
     199#define gl2psPrintPDFPixmapStreamData Geant4_gl2psPrintPDFPixmapStreamData
     200#define gl2psPrintPDFPixmap Geant4_gl2psPrintPDFPixmap
     201#define gl2psPrintPDFText Geant4_gl2psPrintPDFText
     202#define gl2psPDFgroupListWriteObjects Geant4_gl2psPDFgroupListWriteObjects
     203#define gl2psPrintPDFFooter Geant4_gl2psPrintPDFFooter
     204#define gl2psPrintPDFBeginViewport Geant4_gl2psPrintPDFBeginViewport
     205#define gl2psPrintPDFEndViewport Geant4_gl2psPrintPDFEndViewport
     206#define gl2psPrintPDFFinalPrimitive Geant4_gl2psPrintPDFFinalPrimitive
     207#define gl2psSVGGetCoordsAndColors Geant4_gl2psSVGGetCoordsAndColors
     208#define gl2psSVGGetColorString Geant4_gl2psSVGGetColorString
     209#define gl2psPrintSVGHeader Geant4_gl2psPrintSVGHeader
     210#define gl2psPrintSVGSmoothTriangle Geant4_gl2psPrintSVGSmoothTriangle
     211#define gl2psPrintSVGDash Geant4_gl2psPrintSVGDash
     212#define gl2psEndSVGLine Geant4_gl2psEndSVGLine
     213#define gl2psPrintSVGPixmap Geant4_gl2psPrintSVGPixmap
     214#define gl2psPrintSVGPrimitive Geant4_gl2psPrintSVGPrimitive
     215#define gl2psPrintSVGFooter Geant4_gl2psPrintSVGFooter
     216#define gl2psPrintSVGBeginViewport Geant4_gl2psPrintSVGBeginViewport
     217#define gl2psPrintSVGEndViewport Geant4_gl2psPrintSVGEndViewport
     218#define gl2psPrintSVGFinalPrimitive Geant4_gl2psPrintSVGFinalPrimitive
     219#define gl2psPrintPGFColor Geant4_gl2psPrintPGFColor
     220#define gl2psPrintPGFHeader Geant4_gl2psPrintPGFHeader
     221#define gl2psPrintPGFDash Geant4_gl2psPrintPGFDash
     222#define gl2psPGFTextAlignment Geant4_gl2psPGFTextAlignment
     223#define gl2psPrintPGFPrimitive Geant4_gl2psPrintPGFPrimitive
     224#define gl2psPrintPGFFooter Geant4_gl2psPrintPGFFooter
     225#define gl2psPrintPGFBeginViewport Geant4_gl2psPrintPGFBeginViewport
     226#define gl2psPrintPGFEndViewport Geant4_gl2psPrintPGFEndViewport
     227#define gl2psPrintPGFFinalPrimitive Geant4_gl2psPrintPGFFinalPrimitive
     228#define gl2psComputeTightBoundingBox Geant4_gl2psComputeTightBoundingBox
    118229
    119230#define gl2ps Geant4_gl2ps
  • trunk/source/visualization/externals/gl2ps/include/gl2ps.h

    r930 r937  
    2626/*
    2727 * GL2PS, an OpenGL to PostScript Printing Library
    28  * Copyright (C) 1999-2003  Christophe Geuzaine
    29  *
    30  * $Id: gl2ps.h,v 1.1 2009/02/18 09:54:12 lgarnier Exp $
    31  *
    32  * E-mail: geuz@geuz.org
    33  * URL: http://www.geuz.org/gl2ps/
    34  *
    35  * This library is free software; you can redistribute it and/or
    36  * modify it under the terms of the GNU Library General Public
    37  * License as published by the Free Software Foundation; either
     28 * Copyright (C) 1999-2009 C. Geuzaine
     29 *
     30 * This program is free software; you can redistribute it and/or
     31 * modify it under the terms of either:
     32 *
     33 * a) the GNU Library General Public License as published by the Free
     34 * Software Foundation, either version 2 of the License, or (at your
     35 * option) any later version; or
     36 *
     37 * b) the GL2PS License as published by Christophe Geuzaine, either
    3838 * version 2 of the License, or (at your option) any later version.
    3939 *
    40  * This library is distributed in the hope that it will be useful,
    41  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    42  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    43  * Library General Public License for more details.
     40 * This program is distributed in the hope that it will be useful, but
     41 * WITHOUT ANY WARRANTY; without even the implied warranty of
     42 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See either
     43 * the GNU Library General Public License or the GL2PS License for
     44 * more details.
    4445 *
    4546 * You should have received a copy of the GNU Library General Public
    46  * License along with this library; if not, write to the Free
    47  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
    48  *
     47 * License along with this library in the file named "COPYING.LGPL";
     48 * if not, write to the Free Software Foundation, Inc., 675 Mass Ave,
     49 * Cambridge, MA 02139, USA.
     50 *
     51 * You should have received a copy of the GL2PS License with this
     52 * library in the file named "COPYING.GL2PS"; if not, I will be glad
     53 * to provide one.
     54 *
     55 * For the latest info about gl2ps, see http://www.geuz.org/gl2ps/.
     56 * Please report all bugs and problems to <gl2ps@geuz.org>.
    4957 */
    5058
     
    5462#include <stdio.h>
    5563#include <stdlib.h>
    56 #include <cmath>
    57 
    58 /* To generate a Windows dll, you have to define GL2PSDLL at compile
    59    time */
    60 
    61 #ifdef WIN32
     64
     65/* Define GL2PSDLL at compile time to build a Windows DLL */
     66
     67#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
     68#  if defined(_MSC_VER)
     69#    pragma warning(disable:4115)
     70#  endif
    6271#  include <windows.h>
    63 #  ifdef GL2PSDLL
    64 #    ifdef GL2PSDLL_EXPORTS
     72#  if defined(GL2PSDLL)
     73#    if defined(GL2PSDLL_EXPORTS)
    6574#      define GL2PSDLL_API __declspec(dllexport)
    6675#    else
     
    7483#endif
    7584
    76 #ifdef __APPLE__
     85#if defined(__APPLE__) || defined(HAVE_OPENGL_GL_H)
    7786#  include <OpenGL/gl.h>
    7887#else
     
    8089#endif
    8190
    82 
    83 #define GL2PS_VERSION                    0.8
    84 #define GL2PS_NONE                       0
    85 
    86 /* Output file format */
    87 
    88 #define GL2PS_PS                         1
    89 #define GL2PS_EPS                        2
    90 #define GL2PS_TEX                        3
     91/* Support for compressed PostScript/PDF/SVG and for embedded PNG
     92   images in SVG */
     93
     94#if defined(HAVE_ZLIB) || defined(HAVE_LIBZ)
     95#  define GL2PS_HAVE_ZLIB
     96#  if defined(HAVE_LIBPNG) || defined(HAVE_PNG)
     97#    define GL2PS_HAVE_LIBPNG
     98#  endif
     99#endif
     100
     101/* Version number */
     102
     103#define GL2PS_MAJOR_VERSION 1
     104#define GL2PS_MINOR_VERSION 3
     105#define GL2PS_PATCH_VERSION 3
     106#define GL2PS_EXTRA_VERSION ""
     107
     108#define GL2PS_VERSION (GL2PS_MAJOR_VERSION + \
     109                       0.01 * GL2PS_MINOR_VERSION + \
     110                       0.0001 * GL2PS_PATCH_VERSION)
     111
     112#define GL2PS_COPYRIGHT "(C) 1999-2009 C. Geuzaine"
     113
     114/* Output file formats (the values and the ordering are important!) */
     115
     116#define GL2PS_PS  0
     117#define GL2PS_EPS 1
     118#define GL2PS_TEX 2
     119#define GL2PS_PDF 3
     120#define GL2PS_SVG 4
     121#define GL2PS_PGF 5
    91122
    92123/* Sorting algorithms */
    93124
    94 #define GL2PS_NO_SORT                    1
    95 #define GL2PS_SIMPLE_SORT                2
    96 #define GL2PS_BSP_SORT                   3
     125#define GL2PS_NO_SORT     1
     126#define GL2PS_SIMPLE_SORT 2
     127#define GL2PS_BSP_SORT    3
     128
     129/* Message levels and error codes */
     130
     131#define GL2PS_SUCCESS       0
     132#define GL2PS_INFO          1
     133#define GL2PS_WARNING       2
     134#define GL2PS_ERROR         3
     135#define GL2PS_NO_FEEDBACK   4
     136#define GL2PS_OVERFLOW      5
     137#define GL2PS_UNINITIALIZED 6
    97138
    98139/* Options for gl2psBeginPage */
    99140
    100 #define GL2PS_DRAW_BACKGROUND            (1<<0)
    101 #define GL2PS_SIMPLE_LINE_OFFSET         (1<<1)
    102 #define GL2PS_SILENT                     (1<<2)
    103 #define GL2PS_BEST_ROOT                  (1<<3)
    104 #define GL2PS_OCCLUSION_CULL             (1<<4)
    105 #define GL2PS_NO_TEXT                    (1<<5)
    106 #define GL2PS_LANDSCAPE                  (1<<6)
    107 #define GL2PS_NO_PS3_SHADING             (1<<7)
    108 #define GL2PS_NO_PIXMAP                  (1<<8)
     141#define GL2PS_NONE                 0
     142#define GL2PS_DRAW_BACKGROUND      (1<<0)
     143#define GL2PS_SIMPLE_LINE_OFFSET   (1<<1)
     144#define GL2PS_SILENT               (1<<2)
     145#define GL2PS_BEST_ROOT            (1<<3)
     146#define GL2PS_OCCLUSION_CULL       (1<<4)
     147#define GL2PS_NO_TEXT              (1<<5)
     148#define GL2PS_LANDSCAPE            (1<<6)
     149#define GL2PS_NO_PS3_SHADING       (1<<7)
     150#define GL2PS_NO_PIXMAP            (1<<8)
     151#define GL2PS_USE_CURRENT_VIEWPORT (1<<9)
     152#define GL2PS_COMPRESS             (1<<10)
     153#define GL2PS_NO_BLENDING          (1<<11)
     154#define GL2PS_TIGHT_BOUNDING_BOX   (1<<12)
    109155
    110156/* Arguments for gl2psEnable/gl2psDisable */
    111157
    112 #define GL2PS_POLYGON_OFFSET_FILL        1
    113 #define GL2PS_POLYGON_BOUNDARY           2
    114 #define GL2PS_LINE_STIPPLE               3
    115 
    116 /* Magic numbers */
    117 
    118 #define GL2PS_EPSILON                    5.e-3
    119 #define GL2PS_DEPTH_FACT                 1000.0
    120 #define GL2PS_SIMPLE_OFFSET              0.05
    121 #define GL2PS_SIMPLE_OFFSET_LARGE        1.0
    122 #define GL2PS_ZERO(arg)                  (std::fabs(arg)<1.e-20)
    123 /*#define GL2PS_ZERO(arg)                ((arg)==0.0)*/
    124 
    125 /* Message levels and error codes */
    126 
    127 #define GL2PS_SUCCESS                    0
    128 #define GL2PS_INFO                       1
    129 #define GL2PS_WARNING                    2
    130 #define GL2PS_ERROR                      3
    131 #define GL2PS_NO_FEEDBACK                4
    132 #define GL2PS_OVERFLOW                   5
    133 #define GL2PS_UNINITIALIZED              6
    134 
    135 /* Primitive types */
    136 
    137 #define GL2PS_TEXT                       1
    138 #define GL2PS_POINT                      2
    139 #define GL2PS_LINE                       3
    140 #define GL2PS_QUADRANGLE                 4
    141 #define GL2PS_TRIANGLE                   5
    142 #define GL2PS_PIXMAP                     6
    143 
    144 /* BSP tree primitive comparison */
    145 
    146 #define GL2PS_COINCIDENT                 1
    147 #define GL2PS_IN_FRONT_OF                2
    148 #define GL2PS_IN_BACK_OF                 3
    149 #define GL2PS_SPANNING                   4
    150 
    151 /* 2D BSP tree primitive comparison */
    152 
    153 #define GL2PS_POINT_COINCIDENT           0
    154 #define GL2PS_POINT_INFRONT              1
    155 #define GL2PS_POINT_BACK                 2
    156 
    157 /* Pass through options */
    158 
    159 #define GL2PS_BEGIN_POLYGON_OFFSET_FILL  1
    160 #define GL2PS_END_POLYGON_OFFSET_FILL    2
    161 #define GL2PS_BEGIN_POLYGON_BOUNDARY     3
    162 #define GL2PS_END_POLYGON_BOUNDARY       4
    163 #define GL2PS_BEGIN_LINE_STIPPLE         5
    164 #define GL2PS_END_LINE_STIPPLE           6
    165 #define GL2PS_SET_POINT_SIZE             7
    166 #define GL2PS_SET_LINE_WIDTH             8
     158#define GL2PS_POLYGON_OFFSET_FILL 1
     159#define GL2PS_POLYGON_BOUNDARY    2
     160#define GL2PS_LINE_STIPPLE        3
     161#define GL2PS_BLEND               4
     162
     163/* Text alignment (o=raster position; default mode is BL):
     164   +---+ +---+ +---+ +---+ +---+ +---+ +-o-+ o---+ +---o
     165   | o | o   | |   o |   | |   | |   | |   | |   | |   |
     166   +---+ +---+ +---+ +-o-+ o---+ +---o +---+ +---+ +---+
     167    C     CL    CR    B     BL    BR    T     TL    TR */
     168
     169#define GL2PS_TEXT_C  1
     170#define GL2PS_TEXT_CL 2
     171#define GL2PS_TEXT_CR 3
     172#define GL2PS_TEXT_B  4
     173#define GL2PS_TEXT_BL 5
     174#define GL2PS_TEXT_BR 6
     175#define GL2PS_TEXT_T  7
     176#define GL2PS_TEXT_TL 8
     177#define GL2PS_TEXT_TR 9
    167178
    168179typedef GLfloat GL2PSrgba[4];
    169 typedef GLfloat GL2PSxyz[3];
    170 typedef GLfloat GL2PSplane[4];
    171 
    172 typedef struct _GL2PSbsptree2d GL2PSbsptree2d;
    173 
    174 struct _GL2PSbsptree2d {
    175   GL2PSplane plane;
    176   GL2PSbsptree2d *front, *back;
    177 };
    178 
    179 typedef struct {
    180   GLint nmax, size, incr, n;
    181   char *array;
    182 } GL2PSlist;
    183 
    184 typedef struct _GL2PSbsptree GL2PSbsptree;
    185 
    186 struct _GL2PSbsptree {
    187   GL2PSplane plane;
    188   GL2PSlist *primitives;
    189   GL2PSbsptree *front, *back;
    190 };
    191 
    192 typedef struct {
    193   GL2PSxyz xyz;
    194   GL2PSrgba rgba;
    195 } GL2PSvertex;
    196 
    197 typedef struct {
    198   GLshort fontsize;
    199   char *str, *fontname;
    200 } GL2PSstring;
    201 
    202 typedef struct {
    203   GLsizei width, height;
    204   GLenum format, type;
    205   GLfloat *pixels;
    206 } GL2PSimage;
    207 
    208 typedef struct {
    209   GLshort type, numverts;
    210   char boundary, dash, culled;
    211   GLfloat width, depth;
    212   GL2PSvertex *verts;
    213   GL2PSstring *text;
    214   GL2PSimage *image;
    215 } GL2PSprimitive;
    216 
    217 typedef struct {
    218   GLint format, sort, options, colorsize, colormode, buffersize, maxbestroot;
    219   const char *title, *producer, *filename;
    220   GLboolean shade, boundary;
    221   GLfloat *feedback, offset[2];
    222   GLint viewport[4];
    223   GL2PSrgba *colormap, lastrgba, threshold;
    224   float lastlinewidth;
    225   GL2PSlist *primitives;
    226   GL2PSbsptree2d *imagetree;
    227   FILE *stream;
    228 } GL2PScontext;
    229 
    230 /* public functions */
    231 
    232 #ifdef __cplusplus
     180
     181#if defined(__cplusplus)
    233182extern "C" {
    234183#endif
    235184
    236185GL2PSDLL_API GLint gl2psBeginPage(const char *title, const char *producer,
    237                                   GLint viewport[4], GLint format, GLint sort,
    238                                   GLint options, GLint colormode,
    239                                   GLint colorsize, GL2PSrgba *colormap,
    240                                   GLint nr, GLint ng, GLint nb, GLint buffersize,
    241                                   FILE *stream, const char *filename);
     186                                  GLint viewport[4], GLint format, GLint sort,
     187                                  GLint options, GLint colormode,
     188                                  GLint colorsize, GL2PSrgba *colormap,
     189                                  GLint nr, GLint ng, GLint nb, GLint buffersize,
     190                                  FILE *stream, const char *filename);
    242191GL2PSDLL_API GLint gl2psEndPage(void);
     192GL2PSDLL_API GLint gl2psSetOptions(GLint options);
     193GL2PSDLL_API GLint gl2psGetOptions(GLint *options);
    243194GL2PSDLL_API GLint gl2psBeginViewport(GLint viewport[4]);
    244195GL2PSDLL_API GLint gl2psEndViewport(void);
    245 GL2PSDLL_API GLint gl2psText(const char *str, const char *fontname, GLshort fontsize);
     196GL2PSDLL_API GLint gl2psText(const char *str, const char *fontname,
     197                             GLshort fontsize);
     198GL2PSDLL_API GLint gl2psTextOpt(const char *str, const char *fontname,
     199                                GLshort fontsize, GLint align, GLfloat angle);
     200GL2PSDLL_API GLint gl2psSpecial(GLint format, const char *str);
    246201GL2PSDLL_API GLint gl2psDrawPixels(GLsizei width, GLsizei height,
    247                                    GLint xorig, GLint yorig,
    248                                    GLenum format, GLenum type, const void *pixels);
     202                                   GLint xorig, GLint yorig,
     203                                   GLenum format, GLenum type, const void *pixels);
    249204GL2PSDLL_API GLint gl2psEnable(GLint mode);
    250205GL2PSDLL_API GLint gl2psDisable(GLint mode);
    251206GL2PSDLL_API GLint gl2psPointSize(GLfloat value);
    252207GL2PSDLL_API GLint gl2psLineWidth(GLfloat value);
    253 
    254 #ifdef __cplusplus
     208GL2PSDLL_API GLint gl2psBlendFunc(GLenum sfactor, GLenum dfactor);
     209
     210/* undocumented */
     211GL2PSDLL_API GLint gl2psDrawImageMap(GLsizei width, GLsizei height,
     212                                     const GLfloat position[3],
     213                                     const unsigned char *imagemap);
     214GL2PSDLL_API const char *gl2psGetFileExtension(GLint format);
     215GL2PSDLL_API const char *gl2psGetFormatDescription(GLint format);
     216
     217#if defined(__cplusplus)
    255218}
    256219#endif
  • trunk/source/visualization/externals/gl2ps/src/gl2ps.cc

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