Changeset 937 for trunk/source/visualization/externals
- Timestamp:
- Mar 4, 2009, 3:13:51 PM (15 years ago)
- 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 $ 2 2 ------------------------------------------------------------------- 3 3 … … 18 18 ---------------------------------------------------------- 19 19 20 4 March 2009, Laurent Garnier 21 - Update gl2ps to 1.3.3 version (before it was 0.8) 22 20 23 16 February 2009, Laurent Garnier 21 24 - Creation of this library in order to have a gl2ps for all viewers. -
trunk/source/visualization/externals/gl2ps/include/Geant4_gl2ps.h
r919 r937 27 27 #define Geant4_gl2ps_h 28 28 29 // gl2ps- 0.73.29 // gl2ps-1.3.3 30 30 // The gl2ps code is prefixed by Geant4_ in order 31 31 // to avoid clashes with other gl2ps code that may come at link … … 39 39 #define gl2psPointSize Geant4_gl2psPointSize 40 40 #define gl2psLineWidth Geant4_gl2psLineWidth 41 #define gl2psNumShadeColors Geant4_gl2psNumShadeColors42 41 #define gl2psDrawPixels Geant4_gl2psDrawPixels 43 42 #define gl2psBeginViewport Geant4_gl2psBeginViewport 44 43 #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 45 52 46 53 #define gl2psMsg Geant4_gl2psMsg … … 48 55 #define gl2psRealloc Geant4_gl2psRealloc 49 56 #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 50 68 #define gl2psListRealloc Geant4_gl2psListRealloc 51 69 #define gl2psListCreate Geant4_gl2psListCreate … … 57 75 #define gl2psListAction Geant4_gl2psListAction 58 76 #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 59 100 #define gl2psComparePointPlane Geant4_gl2psComparePointPlane 60 101 #define gl2psPsca Geant4_gl2psPsca … … 73 114 #define gl2psTrianglesFirst Geant4_gl2psTrianglesFirst 74 115 #define gl2psFindRoot Geant4_gl2psFindRoot 116 #define gl2psFreeImagemap Geant4_gl2psFreeImagemap 75 117 #define gl2psFreePrimitive Geant4_gl2psFreePrimitive 76 118 #define gl2psAddPrimitiveInList Geant4_gl2psAddPrimitiveInList … … 80 122 #define gl2psBuildBspTree Geant4_gl2psBuildBspTree 81 123 #define gl2psTraverseBspTree Geant4_gl2psTraverseBspTree 124 #define gl2psRescaleAndOffset Geant4_gl2psRescaleAndOffset 82 125 #define gl2psGetPlaneFromPoints Geant4_gl2psGetPlaneFromPoints 83 126 #define gl2psFreeBspImageTree Geant4_gl2psFreeBspImageTree … … 88 131 #define gl2psSplitPrimitive2D Geant4_gl2psSplitPrimitive2D 89 132 #define gl2psAddInImageTree Geant4_gl2psAddInImageTree 90 #define gl2psAddIn Image Geant4_gl2psAddInImage133 #define gl2psAddInBspImageTree Geant4_gl2psAddInBspImageTree 91 134 #define gl2psAddBoundaryInList Geant4_gl2psAddBoundaryInList 92 135 #define gl2psBuildPolygonBoundary Geant4_gl2psBuildPolygonBoundary … … 94 137 #define gl2psGetVertex Geant4_gl2psGetVertex 95 138 #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 98 142 #define gl2psPrintPostScriptHeader Geant4_gl2psPrintPostScriptHeader 99 143 #define gl2psPrintPostScriptColor Geant4_gl2psPrintPostScriptColor 100 144 #define gl2psResetPostScriptColor Geant4_gl2psResetPostScriptColor 145 #define gl2psEndPostScriptLine Geant4_gl2psEndPostScriptLine 146 #define gl2psParseStipplePattern Geant4_gl2psParseStipplePattern 147 #define gl2psPrintPostScriptDash Geant4_gl2psPrintPostScriptDash 101 148 #define gl2psPrintPostScriptPrimitive Geant4_gl2psPrintPostScriptPrimitive 102 149 #define gl2psPrintPostScriptFooter Geant4_gl2psPrintPostScriptFooter … … 108 155 #define gl2psPrintPostScriptEndViewport Geant4_gl2psPrintPostScriptEndViewport 109 156 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 115 158 #define gl2psPrintPrimitives Geant4_gl2psPrintPrimitives 116 159 #define gl2psPrintTeXBeginViewport Geant4_gl2psPrintTeXBeginViewport 117 160 #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 118 229 119 230 #define gl2ps Geant4_gl2ps -
trunk/source/visualization/externals/gl2ps/include/gl2ps.h
r930 r937 26 26 /* 27 27 * GL2PS, an OpenGL to PostScript Printing Library 28 * Copyright (C) 1999-200 3 ChristopheGeuzaine29 * 30 * $Id: gl2ps.h,v 1.1 2009/02/18 09:54:12 lgarnier Exp $31 * 32 * E-mail: geuz@geuz.org33 * URL: http://www.geuz.org/gl2ps/34 * 35 * This library is free software; you can redistribute it and/or36 * modify it under the terms of the GNU Library General Public37 * License as published by the Free Software Foundation;either28 * 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 38 38 * version 2 of the License, or (at your option) any later version. 39 39 * 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. 44 45 * 45 46 * 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>. 49 57 */ 50 58 … … 54 62 #include <stdio.h> 55 63 #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 62 71 # include <windows.h> 63 # if def GL2PSDLL64 # if def GL2PSDLL_EXPORTS72 # if defined(GL2PSDLL) 73 # if defined(GL2PSDLL_EXPORTS) 65 74 # define GL2PSDLL_API __declspec(dllexport) 66 75 # else … … 74 83 #endif 75 84 76 #if def __APPLE__85 #if defined(__APPLE__) || defined(HAVE_OPENGL_GL_H) 77 86 # include <OpenGL/gl.h> 78 87 #else … … 80 89 #endif 81 90 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 91 122 92 123 /* Sorting algorithms */ 93 124 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 97 138 98 139 /* Options for gl2psBeginPage */ 99 140 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) 109 155 110 156 /* Arguments for gl2psEnable/gl2psDisable */ 111 157 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 167 178 168 179 typedef 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) 233 182 extern "C" { 234 183 #endif 235 184 236 185 GL2PSDLL_API GLint gl2psBeginPage(const char *title, const char *producer, 237 238 239 240 241 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); 242 191 GL2PSDLL_API GLint gl2psEndPage(void); 192 GL2PSDLL_API GLint gl2psSetOptions(GLint options); 193 GL2PSDLL_API GLint gl2psGetOptions(GLint *options); 243 194 GL2PSDLL_API GLint gl2psBeginViewport(GLint viewport[4]); 244 195 GL2PSDLL_API GLint gl2psEndViewport(void); 245 GL2PSDLL_API GLint gl2psText(const char *str, const char *fontname, GLshort fontsize); 196 GL2PSDLL_API GLint gl2psText(const char *str, const char *fontname, 197 GLshort fontsize); 198 GL2PSDLL_API GLint gl2psTextOpt(const char *str, const char *fontname, 199 GLshort fontsize, GLint align, GLfloat angle); 200 GL2PSDLL_API GLint gl2psSpecial(GLint format, const char *str); 246 201 GL2PSDLL_API GLint gl2psDrawPixels(GLsizei width, GLsizei height, 247 248 202 GLint xorig, GLint yorig, 203 GLenum format, GLenum type, const void *pixels); 249 204 GL2PSDLL_API GLint gl2psEnable(GLint mode); 250 205 GL2PSDLL_API GLint gl2psDisable(GLint mode); 251 206 GL2PSDLL_API GLint gl2psPointSize(GLfloat value); 252 207 GL2PSDLL_API GLint gl2psLineWidth(GLfloat value); 253 254 #ifdef __cplusplus 208 GL2PSDLL_API GLint gl2psBlendFunc(GLenum sfactor, GLenum dfactor); 209 210 /* undocumented */ 211 GL2PSDLL_API GLint gl2psDrawImageMap(GLsizei width, GLsizei height, 212 const GLfloat position[3], 213 const unsigned char *imagemap); 214 GL2PSDLL_API const char *gl2psGetFileExtension(GLint format); 215 GL2PSDLL_API const char *gl2psGetFormatDescription(GLint format); 216 217 #if defined(__cplusplus) 255 218 } 256 219 #endif -
trunk/source/visualization/externals/gl2ps/src/gl2ps.cc
r930 r937 35 35 /* 36 36 * GL2PS, an OpenGL to PostScript Printing Library 37 * Copyright (C) 1999-200 3 Christophe Geuzaine37 * Copyright (C) 1999-2009 C. Geuzaine 38 38 * 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: 40 41 * 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 43 45 * 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 47 47 * version 2 of the License, or (at your option) any later version. 48 48 * 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. 53 54 * 54 55 * 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. 57 59 * 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>. 58 90 */ 59 91 92 #include "Geant4_gl2ps.h" 93 94 #include <math.h> 60 95 #include <string.h> 61 96 #include <sys/types.h> 62 97 #include <stdarg.h> 63 98 #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 170 typedef 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 179 typedef GLfloat GL2PSxyz[3]; 180 typedef GLfloat GL2PSplane[4]; 181 182 typedef struct _GL2PSbsptree2d GL2PSbsptree2d; 183 184 struct _GL2PSbsptree2d { 185 GL2PSplane plane; 186 GL2PSbsptree2d *front, *back; 187 }; 188 189 typedef struct { 190 GLint nmax, size, incr, n; 191 char *array; 192 } GL2PSlist; 193 194 typedef struct _GL2PSbsptree GL2PSbsptree; 195 196 struct _GL2PSbsptree { 197 GL2PSplane plane; 198 GL2PSlist *primitives; 199 GL2PSbsptree *front, *back; 200 }; 201 202 typedef struct { 203 GL2PSxyz xyz; 204 GL2PSrgba rgba; 205 } GL2PSvertex; 206 207 typedef struct { 208 GL2PSvertex vertex[3]; 209 int prop; 210 } GL2PStriangle; 211 212 typedef 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 221 typedef 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 230 typedef struct _GL2PSimagemap GL2PSimagemap; 231 232 struct _GL2PSimagemap { 233 GL2PSimage *image; 234 GL2PSimagemap *next; 235 }; 236 237 typedef 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 250 typedef 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 259 typedef struct{ 260 GL2PSlist* ptrlist; 261 int gsno, fontno, imno, shno, maskshno, trgroupno; 262 int gsobjno, fontobjno, imobjno, shobjno, maskshobjno, trgroupobjno; 263 } GL2PSpdfgroup; 264 265 typedef 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 305 typedef 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; 65 315 66 316 /* 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 319 static GL2PScontext *gl2ps = NULL; 320 321 /* Need to forward-declare this one */ 322 323 static GLint gl2psPrintPrimitives(void); 324 325 /********************************************************************* 326 * 327 * Utility routines 328 * 329 *********************************************************************/ 330 331 static void gl2psMsg(GLint level, const char *fmt, ...) 332 { 74 333 va_list args; 75 334 … … 85 344 fprintf(stderr, "\n"); 86 345 } 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 349 static void *gl2psMalloc(size_t size) 350 { 93 351 void *ptr; 94 352 … … 102 360 } 103 361 104 void *gl2psRealloc(void *ptr, size_t size){ 362 static void *gl2psRealloc(void *ptr, size_t size) 363 { 105 364 if(!size) return(NULL); 106 365 ptr = realloc(ptr, size); … … 112 371 } 113 372 114 void gl2psFree(void *ptr){ 373 static void gl2psFree(void *ptr) 374 { 115 375 if(!ptr) return; 116 376 free(ptr); 117 377 } 118 378 379 static 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 393 static 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 403 static 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 416 static 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 432 static 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 451 static 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 462 static 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 472 static 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 500 static 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 518 static 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 119 558 /* The list handling routines */ 120 559 121 void gl2psListRealloc(GL2PSlist *list, GLint n){ 560 static void gl2psListRealloc(GL2PSlist *list, GLint n) 561 { 562 if(!list){ 563 gl2psMsg(GL2PS_ERROR, "Cannot reallocate NULL list"); 564 return; 565 } 122 566 if(n <= 0) return; 123 567 if(!list->array){ 124 list->nmax = ((n - 1) / list->incr + 1) * list->incr;125 list->array = (char 568 list->nmax = n; 569 list->array = (char*)gl2psMalloc(list->nmax * list->size); 126 570 } 127 571 else{ 128 572 if(n > list->nmax){ 129 573 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 580 static GL2PSlist *gl2psListCreate(GLint n, GLint incr, GLint size) 581 { 137 582 GL2PSlist *list; 138 583 139 584 if(n < 0) n = 0; 140 585 if(incr <= 0) incr = 1; 141 list = (GL2PSlist 586 list = (GL2PSlist*)gl2psMalloc(sizeof(GL2PSlist)); 142 587 list->nmax = 0; 143 588 list->incr = incr; … … 149 594 } 150 595 151 void gl2psListReset(GL2PSlist *list){ 596 static void gl2psListReset(GL2PSlist *list) 597 { 598 if(!list) return; 152 599 list->n = 0; 153 600 } 154 601 155 void gl2psListDelete(GL2PSlist *list){ 602 static void gl2psListDelete(GL2PSlist *list) 603 { 604 if(!list) return; 156 605 gl2psFree(list->array); 157 606 gl2psFree(list); 158 607 } 159 608 160 void gl2psListAdd(GL2PSlist *list, void *data){ 609 static void gl2psListAdd(GL2PSlist *list, void *data) 610 { 611 if(!list){ 612 gl2psMsg(GL2PS_ERROR, "Cannot add into unallocated list"); 613 return; 614 } 161 615 list->n++; 162 616 gl2psListRealloc(list, list->n); … … 164 618 } 165 619 166 GLint gl2psListNbr(GL2PSlist *list){ 620 static int gl2psListNbr(GL2PSlist *list) 621 { 622 if(!list) 623 return 0; 167 624 return(list->n); 168 625 } 169 626 170 void *gl2psListPointer(GL2PSlist *list, GLint index){ 627 static void *gl2psListPointer(GL2PSlist *list, GLint index) 628 { 629 if(!list){ 630 gl2psMsg(GL2PS_ERROR, "Cannot point into unallocated list"); 631 return NULL; 632 } 171 633 if((index < 0) || (index >= list->n)){ 172 634 gl2psMsg(GL2PS_ERROR, "Wrong list index in gl2psListPointer"); 173 return (&list->array[0]);635 return NULL; 174 636 } 175 637 return(&list->array[index * list->size]); 176 638 } 177 639 178 void gl2psListSort(GL2PSlist *list, 179 int (*fcmp)(const void *a, const void *b)){ 640 static void gl2psListSort(GL2PSlist *list, 641 int (*fcmp)(const void *a, const void *b)) 642 { 643 if(!list) 644 return; 180 645 qsort(list->array, list->n, list->size, fcmp); 181 646 } 182 647 183 void gl2psListAction(GL2PSlist *list, 184 void (*action)(void *data, void *dummy)){185 GLint i , dummy;648 static void gl2psListAction(GL2PSlist *list, void (*action)(void *data)) 649 { 650 GLint i; 186 651 187 652 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 657 static void gl2psListActionInverse(GL2PSlist *list, void (*action)(void *data)) 658 { 659 GLint i; 195 660 196 661 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 668 static 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 675 static 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 686 static 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 722 static 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 731 static 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 743 static 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 760 static void gl2psSetLastColor(GL2PSrgba rgba) 761 { 762 int i; 763 for(i = 0; i < 3; ++i){ 764 gl2ps->lastrgba[i] = rgba[i]; 765 } 766 } 767 768 static 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 796 static 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 822 static 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 836 static 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 844 static void gl2psUserFlushPNG(png_structp png_ptr) 845 { 846 } 847 848 static 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 896 static 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 941 static 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 955 static 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 966 static 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 977 static 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 1001 static 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 1034 static 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 1044 static 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 1055 static 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 1092 static 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 1107 static GLfloat gl2psComparePointPlane(GL2PSxyz point, GL2PSplane plane) 1108 { 204 1109 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 1115 static GLfloat gl2psPsca(GLfloat *a, GLfloat *b) 1116 { 211 1117 return(a[0]*b[0] + a[1]*b[1] + a[2]*b[2]); 212 1118 } 213 1119 214 void gl2psPvec(GLfloat *a, GLfloat *b, GLfloat *c){ 1120 static void gl2psPvec(GLfloat *a, GLfloat *b, GLfloat *c) 1121 { 215 1122 c[0] = a[1]*b[2] - a[2]*b[1]; 216 1123 c[1] = a[2]*b[0] - a[0]*b[2]; … … 218 1125 } 219 1126 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){ 1127 static GLfloat gl2psNorm(GLfloat *a) 1128 { 1129 return (GLfloat)sqrt(a[0]*a[0] + a[1]*a[1] + a[2]*a[2]); 1130 } 1131 1132 static void gl2psGetNormal(GLfloat *a, GLfloat *b, GLfloat *c) 1133 { 225 1134 GLfloat norm; 226 1135 … … 232 1141 } 233 1142 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 1151 static void gl2psGetPlane(GL2PSprimitive *prim, GL2PSplane plane) 1152 { 1153 GL2PSxyz v = {0.0F, 0.0F, 0.0F}, w = {0.0F, 0.0F, 0.0F}; 244 1154 245 1155 switch(prim->type){ … … 254 1164 if((GL2PS_ZERO(v[0]) && GL2PS_ZERO(v[1]) && GL2PS_ZERO(v[2])) || 255 1165 (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; 258 1168 plane[3] = -prim->verts[0].xyz[2]; 259 1169 } … … 261 1171 gl2psGetNormal(v, w, plane); 262 1172 plane[3] = 263 264 265 1173 - plane[0] * prim->verts[0].xyz[0] 1174 - plane[1] * prim->verts[0].xyz[1] 1175 - plane[2] * prim->verts[0].xyz[2]; 266 1176 } 267 1177 break; … … 271 1181 v[2] = prim->verts[1].xyz[2] - prim->verts[0].xyz[2]; 272 1182 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; 275 1185 plane[3] = -prim->verts[0].xyz[2]; 276 1186 } 277 1187 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; 281 1191 gl2psGetNormal(v, w, plane); 282 1192 plane[3] = 283 284 285 1193 - plane[0] * prim->verts[0].xyz[0] 1194 - plane[1] * prim->verts[0].xyz[1] 1195 - plane[2] * prim->verts[0].xyz[2]; 286 1196 } 287 1197 break; … … 289 1199 case GL2PS_PIXMAP : 290 1200 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; 293 1205 plane[3] = -prim->verts[0].xyz[2]; 294 1206 break; 295 1207 default : 296 1208 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; 299 1211 break; 300 1212 } 301 1213 } 302 1214 303 void gl2psCutEdge(GL2PSvertex *a, GL2PSvertex *b, GL2PSplane plane, 304 GL2PSvertex *c){ 1215 static void gl2psCutEdge(GL2PSvertex *a, GL2PSvertex *b, GL2PSplane plane, 1216 GL2PSvertex *c) 1217 { 305 1218 GL2PSxyz v; 306 GLfloat sect ;1219 GLfloat sect, psca; 307 1220 308 1221 v[0] = b->xyz[0] - a->xyz[0]; 309 1222 v[1] = b->xyz[1] - a->xyz[1]; 310 1223 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 313 1230 c->xyz[0] = a->xyz[0] + v[0] * sect; 314 1231 c->xyz[1] = a->xyz[1] + v[1] * sect; 315 1232 c->xyz[2] = a->xyz[2] + v[2] * sect; 316 1233 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 1240 static void gl2psCreateSplitPrimitive(GL2PSprimitive *parent, GL2PSplane plane, 1241 GL2PSprimitive *child, GLshort numverts, 1242 GLshort *index0, GLshort *index1) 1243 { 326 1244 GLshort i; 327 1245 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! */ 341 1265 child->culled = parent->culled; 342 child->dash = parent->dash; 1266 child->offset = parent->offset; 1267 child->pattern = parent->pattern; 1268 child->factor = parent->factor; 343 1269 child->width = parent->width; 344 1270 child->numverts = numverts; 345 child->verts = (GL2PSvertex 1271 child->verts = (GL2PSvertex*)gl2psMalloc(numverts * sizeof(GL2PSvertex)); 346 1272 347 1273 for(i = 0; i < numverts; i++){ … … 351 1277 else{ 352 1278 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 1284 static void gl2psAddIndex(GLshort *index0, GLshort *index1, GLshort *nb, 1285 GLshort i, GLshort j) 1286 { 360 1287 GLint k; 361 1288 … … 369 1296 } 370 1297 371 GLshort gl2psGetIndex(GLshort i, GLshort num){ 372 return(i < num-1) ? i+1 : 0; 373 } 374 375 GLint gl2psTestSplitPrimitive(GL2PSprimitive *prim, GL2PSplane plane){ 1298 static GLshort gl2psGetIndex(GLshort i, GLshort num) 1299 { 1300 return (i < num - 1) ? i + 1 : 0; 1301 } 1302 1303 static GLint gl2psTestSplitPrimitive(GL2PSprimitive *prim, GL2PSplane plane) 1304 { 376 1305 GLint type = GL2PS_COINCIDENT; 377 1306 GLshort i, j; … … 389 1318 j = gl2psGetIndex(i, prim->numverts); 390 1319 if(d[j] > GL2PS_EPSILON){ 391 392 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; 394 1323 } 395 1324 else if(d[j] < -GL2PS_EPSILON){ 396 397 398 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; 399 1328 } 400 1329 } … … 403 1332 } 404 1333 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]; 1334 static 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]; 408 1338 GLint type; 409 1339 GLfloat d[5]; … … 425 1355 j = gl2psGetIndex(i, prim->numverts); 426 1356 if(d[j] > GL2PS_EPSILON){ 427 428 429 430 431 432 433 434 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); 435 1365 } 436 1366 else if(d[j] < -GL2PS_EPSILON){ 437 438 439 440 441 442 443 444 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); 445 1375 } 446 1376 else{ 447 448 1377 gl2psAddIndex(in0, in1, &in, j, -1); 1378 gl2psAddIndex(out0, out1, &out, j, -1); 449 1379 } 450 1380 } … … 462 1392 } 463 1393 464 void gl2psDivideQuad(GL2PSprimitive *quad, 465 GL2PSprimitive **t1, GL2PSprimitive **t2){ 1394 static void gl2psDivideQuad(GL2PSprimitive *quad, 1395 GL2PSprimitive **t1, GL2PSprimitive **t2) 1396 { 466 1397 *t1 = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive)); 467 1398 *t2 = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive)); 468 1399 (*t1)->type = (*t2)->type = GL2PS_TRIANGLE; 469 1400 (*t1)->numverts = (*t2)->numverts = 3; 470 (*t1)->depth = (*t2)->depth = quad->depth;471 1401 (*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; 473 1405 (*t1)->width = (*t2)->width = quad->width; 474 (*t1)->verts = (GL2PSvertex 475 (*t2)->verts = (GL2PSvertex 1406 (*t1)->verts = (GL2PSvertex*)gl2psMalloc(3 * sizeof(GL2PSvertex)); 1407 (*t2)->verts = (GL2PSvertex*)gl2psMalloc(3 * sizeof(GL2PSvertex)); 476 1408 (*t1)->verts[0] = quad->verts[0]; 477 1409 (*t1)->verts[1] = quad->verts[1]; … … 481 1413 (*t2)->verts[1] = quad->verts[2]; 482 1414 (*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 1418 static int gl2psCompareDepth(const void *a, const void *b) 1419 { 487 1420 GL2PSprimitive *q, *w; 488 GLfloat diff; 489 1421 GLfloat dq = 0.0F, dw = 0.0F, diff; 1422 int i; 1423 490 1424 q = *(GL2PSprimitive**)a; 491 1425 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; 493 1438 if(diff > 0.){ 1439 return -1; 1440 } 1441 else if(diff < 0.){ 494 1442 return 1; 495 }496 else if(diff < 0.){497 return -1;498 1443 } 499 1444 else{ … … 502 1447 } 503 1448 504 int gl2psTrianglesFirst(const void *a, const void *b){ 1449 static int gl2psTrianglesFirst(const void *a, const void *b) 1450 { 505 1451 GL2PSprimitive *q, *w; 506 1452 … … 510 1456 } 511 1457 512 GLint gl2psFindRoot(GL2PSlist *primitives, GL2PSprimitive **root){ 1458 static GLint gl2psFindRoot(GL2PSlist *primitives, GL2PSprimitive **root) 1459 { 513 1460 GLint i, j, count, best = 1000000, index = 0; 514 1461 GL2PSprimitive *prim1, *prim2; … … 516 1463 GLint maxp; 517 1464 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 518 1472 if(gl2ps->options & GL2PS_BEST_ROOT){ 519 *root = *(GL2PSprimitive**)gl2psListPointer(primitives, 0);520 1473 maxp = gl2psListNbr(primitives); 521 1474 if(maxp > gl2ps->maxbestroot){ … … 527 1480 count = 0; 528 1481 for(j = 0; j < gl2psListNbr(primitives); j++){ 529 530 531 532 533 1482 if(j != i){ 1483 prim2 = *(GL2PSprimitive**)gl2psListPointer(primitives, j); 1484 count += gl2psTestSplitPrimitive(prim2, plane); 1485 } 1486 if(count > best) break; 534 1487 } 535 1488 if(count < best){ 536 537 538 539 1489 best = count; 1490 index = i; 1491 *root = prim1; 1492 if(!count) return index; 540 1493 } 541 1494 } … … 544 1497 } 545 1498 else{ 546 *root = *(GL2PSprimitive**)gl2psListPointer(primitives, 0);547 1499 return 0; 548 1500 } 549 1501 } 550 1502 551 void gl2psFreePrimitive(void *a, void *){ 1503 static 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 1514 static void gl2psFreePrimitive(void *data) 1515 { 552 1516 GL2PSprimitive *q; 553 1517 554 q = *(GL2PSprimitive**) a;1518 q = *(GL2PSprimitive**)data; 555 1519 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); 564 1525 } 565 1526 gl2psFree(q); 566 1527 } 567 1528 568 void gl2psAddPrimitiveInList(GL2PSprimitive *prim, GL2PSlist *list){ 1529 static void gl2psAddPrimitiveInList(GL2PSprimitive *prim, GL2PSlist *list) 1530 { 569 1531 GL2PSprimitive *t1, *t2; 570 1532 … … 576 1538 gl2psListAdd(list, &t1); 577 1539 gl2psListAdd(list, &t2); 578 gl2psFreePrimitive(&prim, NULL); 579 } 580 581 } 582 583 void gl2psFreeBspTree(GL2PSbsptree **tree){ 1540 gl2psFreePrimitive(&prim); 1541 } 1542 1543 } 1544 1545 static void gl2psFreeBspTree(GL2PSbsptree **tree) 1546 { 584 1547 if(*tree){ 585 1548 if((*tree)->back) gl2psFreeBspTree(&(*tree)->back); … … 594 1557 } 595 1558 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; 1559 static GLboolean gl2psGreater(GLfloat f1, GLfloat f2) 1560 { 1561 if(f1 > f2) return GL_TRUE; 1562 else return GL_FALSE; 1563 } 1564 1565 static GLboolean gl2psLess(GLfloat f1, GLfloat f2) 1566 { 1567 if(f1 < f2) return GL_TRUE; 1568 else return GL_FALSE; 1569 } 1570 1571 static void gl2psBuildBspTree(GL2PSbsptree *tree, GL2PSlist *primitives) 1572 { 1573 GL2PSprimitive *prim, *frontprim = NULL, *backprim = NULL; 608 1574 GL2PSlist *frontlist, *backlist; 609 1575 GLint i, index; … … 624 1590 switch(gl2psSplitPrimitive(prim, tree->plane, &frontprim, &backprim)){ 625 1591 case GL2PS_COINCIDENT: 626 627 1592 gl2psAddPrimitiveInList(prim, tree->primitives); 1593 break; 628 1594 case GL2PS_IN_BACK_OF: 629 630 1595 gl2psAddPrimitiveInList(prim, backlist); 1596 break; 631 1597 case GL2PS_IN_FRONT_OF: 632 633 1598 gl2psAddPrimitiveInList(prim, frontlist); 1599 break; 634 1600 case GL2PS_SPANNING: 635 636 637 gl2psFreePrimitive(&prim, NULL);638 1601 gl2psAddPrimitiveInList(backprim, backlist); 1602 gl2psAddPrimitiveInList(frontprim, frontlist); 1603 gl2psFreePrimitive(&prim); 1604 break; 639 1605 } 640 1606 } … … 666 1632 } 667 1633 668 void gl2psTraverseBspTree(GL2PSbsptree *tree, GL2PSxyz eye, GLfloat epsilon, 669 GLboolean (*compare)(GLfloat f1, GLfloat f2), 670 void (*action)(void *data, void *dummy)){ 1634 static void gl2psTraverseBspTree(GL2PSbsptree *tree, GL2PSxyz eye, GLfloat epsilon, 1635 GLboolean (*compare)(GLfloat f1, GLfloat f2), 1636 void (*action)(void *data), int inverse) 1637 { 671 1638 GLfloat result; 672 1639 … … 675 1642 result = gl2psComparePointPlane(eye, tree->plane); 676 1643 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); 686 1663 } 687 1664 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 1670 static 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 1757 static GLint gl2psGetPlaneFromPoints(GL2PSxyz a, GL2PSxyz b, GL2PSplane plane) 1758 { 696 1759 GLfloat n; 697 1760 698 1761 plane[0] = b[1] - a[1]; 699 1762 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)){ 703 1766 plane[0] /= n; 704 1767 plane[1] /= n; … … 707 1770 } 708 1771 else{ 709 plane[0] = -1.0 ;710 plane[1] = 0. ;1772 plane[0] = -1.0F; 1773 plane[1] = 0.0F; 711 1774 plane[3] = a[0]; 712 1775 return 0; … … 714 1777 } 715 1778 716 void gl2psFreeBspImageTree(GL2PSbsptree2d **tree){ 1779 static void gl2psFreeBspImageTree(GL2PSbsptree2d **tree) 1780 { 717 1781 if(*tree){ 718 1782 if((*tree)->back) gl2psFreeBspImageTree(&(*tree)->back); … … 723 1787 } 724 1788 725 GLint gl2psCheckPoint(GL2PSxyz point, GL2PSplane plane){ 1789 static GLint gl2psCheckPoint(GL2PSxyz point, GL2PSplane plane) 1790 { 726 1791 GLfloat pt_dis; 727 1792 … … 732 1797 } 733 1798 734 void gl2psAddPlanesInBspTreeImage(GL2PSprimitive *prim, 735 GL2PSbsptree2d **tree){ 1799 static void gl2psAddPlanesInBspTreeImage(GL2PSprimitive *prim, 1800 GL2PSbsptree2d **tree) 1801 { 736 1802 GLint ret = 0; 737 1803 GLint i; … … 740 1806 741 1807 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 */ 742 1812 head = (GL2PSbsptree2d*)gl2psMalloc(sizeof(GL2PSbsptree2d)); 743 1813 for(i = 0; i < prim->numverts-1; i++){ 744 1814 if(!gl2psGetPlaneFromPoints(prim->verts[i].xyz, 745 1815 prim->verts[i+1].xyz, 746 1816 head->plane)){ 747 1817 if(prim->numverts-i > 3){ 748 749 750 751 752 753 1818 offset++; 1819 } 1820 else{ 1821 gl2psFree(head); 1822 return; 1823 } 754 1824 } 755 1825 else{ 756 1826 break; 757 1827 } 758 1828 } … … 769 1839 if(cur->front == NULL){ 770 1840 cur->front = (GL2PSbsptree2d*)gl2psMalloc(sizeof(GL2PSbsptree2d)); 771 1841 } 772 1842 if(gl2psGetPlaneFromPoints(prim->verts[i].xyz, 773 774 775 776 777 778 1843 prim->verts[i+1].xyz, 1844 cur->front->plane)){ 1845 cur = cur->front; 1846 cur->front = NULL; 1847 cur->back = NULL; 1848 } 779 1849 } 780 1850 if(cur->front == NULL){ … … 783 1853 if(gl2psGetPlaneFromPoints(prim->verts[i].xyz, 784 1854 prim->verts[offset].xyz, 785 786 787 1855 cur->front->plane)){ 1856 cur->front->front = NULL; 1857 cur->front->back = NULL; 788 1858 } 789 1859 else{ 790 1860 gl2psFree(cur->front); 791 1861 cur->front = NULL; 792 1862 } 793 1863 break; … … 800 1870 if(cur->front == NULL){ 801 1871 cur->front = (GL2PSbsptree2d*)gl2psMalloc(sizeof(GL2PSbsptree2d)); 802 1872 } 803 1873 if(gl2psGetPlaneFromPoints(prim->verts[i+1].xyz, 804 805 806 807 808 809 1874 prim->verts[i].xyz, 1875 cur->front->plane)){ 1876 cur = cur->front; 1877 cur->front = NULL; 1878 cur->back = NULL; 1879 } 810 1880 } 811 1881 if(cur->front == NULL){ … … 814 1884 if(gl2psGetPlaneFromPoints(prim->verts[offset].xyz, 815 1885 prim->verts[i].xyz, 816 817 818 1886 cur->front->plane)){ 1887 cur->front->front = NULL; 1888 cur->front->back = NULL; 819 1889 } 820 1890 else{ 821 1891 gl2psFree(cur->front); 822 1892 cur->front = NULL; 823 1893 } 824 1894 break; … … 831 1901 } 832 1902 833 GLint gl2psCheckPrimitive(GL2PSprimitive *prim, GL2PSplane plane){ 1903 static GLint gl2psCheckPrimitive(GL2PSprimitive *prim, GL2PSplane plane) 1904 { 834 1905 GLint i; 835 1906 GLint pos; … … 845 1916 } 846 1917 847 GL2PSprimitive* gl2psCreateSplitPrimitive2D(GL2PSprimitive *parent, 848 GLshort numverts, 849 GL2PSvertex *vertx){ 1918 static GL2PSprimitive *gl2psCreateSplitPrimitive2D(GL2PSprimitive *parent, 1919 GLshort numverts, 1920 GL2PSvertex *vertx) 1921 { 850 1922 GLint i; 851 1923 GL2PSprimitive *child = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive)); 852 1924 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! */ 861 1939 child->culled = parent->culled; 862 child->dash = parent->dash; 1940 child->offset = parent->offset; 1941 child->pattern = parent->pattern; 1942 child->factor = parent->factor; 863 1943 child->width = parent->width; 864 1944 child->numverts = numverts; 865 child->verts = (GL2PSvertex 1945 child->verts = (GL2PSvertex*)gl2psMalloc(numverts * sizeof(GL2PSvertex)); 866 1946 for(i = 0; i < numverts; i++){ 867 1947 child->verts[i] = vertx[i]; … … 870 1950 } 871 1951 872 void gl2psSplitPrimitive2D(GL2PSprimitive *prim, 873 874 875 GL2PSprimitive **back){ 876 877 /* cur will hold the position of current vertex878 prev will hold s the position ofprevious vertex879 prev0 will hold s the position ofvertex number 0880 v1 and v2 represent the current and previous vert exsrespectively881 flag will represents that should the currentbe checked against the plane */1952 static 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 */ 882 1962 GLint cur = -1, prev = -1, i, v1 = 0, v2 = 0, flag = 1, prev0 = -1; 883 1963 884 /* list of vert exs which will go in front and back Primitive */1964 /* list of vertices that will go in front and back primitive */ 885 1965 GL2PSvertex *front_list = NULL, *back_list = NULL; 886 1966 887 /* number of vert exin front and back list */888 GL int front_count = 0, back_count = 0;1967 /* number of vertices in front and back list */ 1968 GLshort front_count = 0, back_count = 0; 889 1969 890 1970 for(i = 0; i <= prim->numverts; i++){ … … 893 1973 if(prim->numverts < 3) break; 894 1974 v1 = 0; 895 v2 = prim->numverts -1;1975 v2 = prim->numverts - 1; 896 1976 cur = prev0; 897 1977 } … … 905 1985 (i < prim->numverts)){ 906 1986 if(cur == GL2PS_POINT_INFRONT){ 907 908 909 1987 front_count++; 1988 front_list = (GL2PSvertex*)gl2psRealloc(front_list, 1989 sizeof(GL2PSvertex)*front_count); 910 1990 front_list[front_count-1] = prim->verts[v1]; 911 1991 } 912 1992 else if(cur == GL2PS_POINT_BACK){ 913 914 915 1993 back_count++; 1994 back_list = (GL2PSvertex*)gl2psRealloc(back_list, 1995 sizeof(GL2PSvertex)*back_count); 916 1996 back_list[back_count-1] = prim->verts[v1]; 917 1997 } 918 1998 else{ 919 920 921 1999 front_count++; 2000 front_list = (GL2PSvertex*)gl2psRealloc(front_list, 2001 sizeof(GL2PSvertex)*front_count); 922 2002 front_list[front_count-1] = prim->verts[v1]; 923 924 925 2003 back_count++; 2004 back_list = (GL2PSvertex*)gl2psRealloc(back_list, 2005 sizeof(GL2PSvertex)*back_count); 926 2006 back_list[back_count-1] = prim->verts[v1]; 927 2007 } … … 930 2010 else if((prev != cur) && (cur != 0) && (prev != 0)){ 931 2011 if(v1 != 0){ 932 933 2012 v2 = v1-1; 2013 i--; 934 2014 } 935 2015 front_count++; 936 2016 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]); 942 2020 back_count++; 943 2021 back_list = (GL2PSvertex*)gl2psRealloc(back_list, 944 2022 sizeof(GL2PSvertex)*back_count); 945 2023 back_list[back_count-1] = front_list[front_count-1]; 946 2024 flag = 0; … … 954 2032 } 955 2033 956 GLint gl2psAddInBspImageTree(GL2PSprimitive *prim, GL2PSbsptree2d **tree){ 2034 static GLint gl2psAddInBspImageTree(GL2PSprimitive *prim, GL2PSbsptree2d **tree) 2035 { 957 2036 GLint ret = 0; 958 2037 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 } 959 2047 960 2048 if(*tree == NULL){ 961 gl2psAddPlanesInBspTreeImage(prim, tree); 2049 if((prim->type != GL2PS_IMAGEMAP) && (GL_FALSE == gl2ps->zerosurfacearea)){ 2050 gl2psAddPlanesInBspTreeImage(gl2ps->primitivetoadd, tree); 2051 } 962 2052 return 1; 963 2053 } … … 973 2063 if((*tree)->front != NULL){ 974 2064 if(gl2psAddInBspImageTree(frontprim, &(*tree)->front)){ 975 976 2065 ret = 1; 2066 } 977 2067 } 978 2068 gl2psFree(frontprim->verts); … … 982 2072 return ret; 983 2073 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; 986 2088 } 987 2089 } … … 989 2091 } 990 2092 991 void gl2psAddInImageTree(void *a, void *){ 992 GL2PSprimitive *prim = *(GL2PSprimitive **)a; 993 994 if(!gl2psAddInBspImageTree(prim, &gl2ps->imagetree)){ 2093 static 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){ 995 2098 prim->culled = 1; 996 2099 } 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 2110 static void gl2psAddBoundaryInList(GL2PSprimitive *prim, GL2PSlist *list) 2111 { 1002 2112 GL2PSprimitive *b; 1003 2113 GLshort i; 1004 2114 GL2PSxyz c; 1005 2115 1006 c[0] = c[1] = c[2] = 0. ;2116 c[0] = c[1] = c[2] = 0.0F; 1007 2117 for(i = 0; i < prim->numverts; i++){ 1008 2118 c[0] += prim->verts[i].xyz[0]; … … 1016 2126 b = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive)); 1017 2127 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; 1020 2131 b->culled = prim->culled; 1021 2132 b->width = prim->width; 1022 2133 b->boundary = 0; 1023 2134 b->numverts = 2; 1024 b->verts = (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... */ 1027 2138 v[0] = c[0] - prim->verts[i].xyz[0]; 1028 2139 v[1] = c[1] - prim->verts[i].xyz[1]; 1029 v[2] = 0. ;2140 v[2] = 0.0F; 1030 2141 norm = gl2psNorm(v); 1031 2142 v[0] /= norm; … … 1051 2162 #endif 1052 2163 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; 1061 2172 gl2psListAdd(list, &b); 1062 2173 } … … 1065 2176 } 1066 2177 1067 void gl2psBuildPolygonBoundary(GL2PSbsptree *tree){ 1068 GLint i, n; 2178 static void gl2psBuildPolygonBoundary(GL2PSbsptree *tree) 2179 { 2180 GLint i; 1069 2181 GL2PSprimitive *prim; 1070 2182 1071 2183 if(!tree) return; 1072 2184 gl2psBuildPolygonBoundary(tree->back); 1073 n = gl2psListNbr(tree->primitives); 1074 for(i = 0; i < n; i++){ 2185 for(i = 0; i < gl2psListNbr(tree->primitives); i++){ 1075 2186 prim = *(GL2PSprimitive**)gl2psListPointer(tree->primitives, i); 1076 2187 if(prim->boundary) gl2psAddBoundaryInList(prim, tree->primitives); … … 1079 2190 } 1080 2191 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 2198 static void gl2psAddPolyPrimitive(GLshort type, GLshort numverts, 2199 GL2PSvertex *verts, GLint offset, 2200 GLushort pattern, GLint factor, 2201 GLfloat width, char boundary) 2202 { 1089 2203 GL2PSprimitive *prim; 1090 2204 1091 prim = (GL2PSprimitive 2205 prim = (GL2PSprimitive*)gl2psMalloc(sizeof(GL2PSprimitive)); 1092 2206 prim->type = type; 1093 2207 prim->numverts = numverts; 1094 prim->verts = (GL2PSvertex 2208 prim->verts = (GL2PSvertex*)gl2psMalloc(numverts * sizeof(GL2PSvertex)); 1095 2209 memcpy(prim->verts, verts, numverts * sizeof(GL2PSvertex)); 1096 2210 prim->boundary = boundary; 1097 prim->dash = dash; 2211 prim->offset = offset; 2212 prim->pattern = pattern; 2213 prim->factor = factor; 1098 2214 prim->width = width; 1099 2215 prim->culled = 0; 1100 2216 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 1161 2220 gl2psListAdd(gl2ps->primitives, &prim); 1162 2221 } 1163 2222 1164 GLint gl2psGetVertex(GL2PSvertex *v, GLfloat *p){ 2223 static GLint gl2psGetVertex(GL2PSvertex *v, GLfloat *p) 2224 { 1165 2225 GLint i; 1166 2226 1167 2227 v->xyz[0] = p[0]; 1168 2228 v->xyz[1] = p[1]; 1169 v->xyz[2] = GL2PS_DEPTH_FACT *p[2];2229 v->xyz[2] = p[2]; 1170 2230 1171 2231 if(gl2ps->colormode == GL_COLOR_INDEX && gl2ps->colorsize > 0){ … … 1186 2246 } 1187 2247 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.; 2248 static 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; 1193 2255 GLfloat *current; 1194 2256 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; 1207 2259 1208 2260 current = gl2ps->feedback; 1209 boundary = gl2ps->boundary = 0;2261 boundary = gl2ps->boundary = GL_FALSE; 1210 2262 1211 2263 while(used > 0){ 1212 2264 1213 if( boundary) gl2ps->boundary = 1;2265 if(GL_TRUE == boundary) gl2ps->boundary = GL_TRUE; 1214 2266 1215 2267 switch((GLint)*current){ … … 1220 2272 current += i; 1221 2273 used -= i; 1222 gl2psAddPolyPrimitive(GL2PS_POINT, 1, vertices, 0, dash, psize, 0); 2274 gl2psAddPolyPrimitive(GL2PS_POINT, 1, vertices, 0, 2275 pattern, factor, psize, 0); 1223 2276 break; 1224 2277 case GL_LINE_TOKEN : … … 1232 2285 current += i; 1233 2286 used -= i; 1234 gl2psAddPolyPrimitive(GL2PS_LINE, 2, vertices, 0, dash, lwidth, 0); 2287 gl2psAddPolyPrimitive(GL2PS_LINE, 2, vertices, 0, 2288 pattern, factor, lwidth, 0); 1235 2289 break; 1236 2290 case GL_POLYGON_TOKEN : … … 1240 2294 v = vtot = 0; 1241 2295 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 ++; 1262 2317 } 1263 2318 break; … … 1273 2328 case GL_PASS_THROUGH_TOKEN : 1274 2329 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], ¤t[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; 1291 2437 } 1292 2438 current += 2; … … 1300 2446 } 1301 2447 } 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 2458 static void gl2psWriteByte(unsigned char byte) 2459 { 1332 2460 unsigned char h = byte / 16; 1333 2461 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 2465 static 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) */ 1361 2478 1362 2479 if((width <= 0) || (height <= 0)) return; 1363 2480 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"); 1376 2491 for(row = 0; row < height; row++){ 1377 2492 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"); 1385 2499 } 1386 2500 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"); 1402 2514 for(row = 0; row < height; row++){ 1403 2515 icase = 1; … … 1405 2517 b = 0; 1406 2518 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 { 1412 2524 dr = dg = db = 0; 1413 2525 } 1414 2526 col++; 1415 red = (Uchar)(3. * dr);1416 green = (Uchar)(3. * dg);1417 blue = (Uchar)(3. * db);1418 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 { 1425 2537 dr = dg = db = 0; 1426 2538 } 1427 2539 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); 1433 2545 b = 0; 1434 2546 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 { 1442 2555 dr = dg = db = 0; 1443 2556 } 1444 2557 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); 1451 2564 b = 0; 1452 2565 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 { 1459 2573 dr = dg = db = 0; 1460 2574 } 1461 2575 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); 1469 2583 b = 0; 1470 2584 icase = 1; 1471 2585 } 1472 2586 } 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"); 1489 2601 for(row = 0; row < height; row++){ 1490 2602 col = 0; 1491 2603 icase = 1; 1492 2604 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 { 1498 2610 dr = dg = db = 0; 1499 2611 } 1500 2612 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); 1504 2616 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 { 1511 2624 dr = dg = db = 0; 1512 2625 } 1513 2626 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); 1516 2629 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); 1521 2635 icase = 1; 1522 2636 } 1523 2637 } 1524 fprintf(stream,"\n");1525 } 1526 } 1527 else{ 2638 gl2psPrintf("\n"); 2639 } 2640 } 2641 else{ /* 8 bit for r and g and b */ 1528 2642 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"); 1536 2649 for(row = 0; row < height; row++){ 1537 2650 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 2666 static 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 2686 static void gl2psPrintPostScriptHeader(void) 2687 { 1560 2688 time_t now; 1561 2689 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 1562 2695 time(&now); 1563 2696 1564 2697 if(gl2ps->format == GL2PS_PS){ 1565 fprintf(gl2ps->stream,"%%!PS-Adobe-3.0\n");2698 gl2psPrintf("%%!PS-Adobe-3.0\n"); 1566 2699 } 1567 2700 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)); 1580 2714 1581 2715 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]); 1598 2735 1599 2736 /* RGB color: r g b C (replace C by G in output to change from rgb to gray) 1600 2737 Grayscale: r g b G 1601 2738 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 1603 2741 Point primitive: x y size P 1604 2742 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 1607 2746 Flat-shaded triangle: x3 y3 x2 y2 x1 y1 T 1608 2747 Smooth-shaded triangle: x3 y3 r3 g3 b3 x2 y2 r2 g2 b2 x1 y1 r1 g1 b1 ST */ 1609 2748 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 1631 2795 /* Smooth-shaded triangle with PostScript level 3 shfill operator: 1632 2796 x3 y3 r3 g3 b3 x2 y2 r2 g2 b2 x1 y1 r1 g1 b1 STshfill */ 1633 2797 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"); 1642 2805 1643 2806 /* Flat-shaded triangle with middle color: 1644 2807 x3 y3 r3 g3 b3 x2 y2 r2 g2 b2 x1 y1 r1 g1 b1 Tm */ 1645 2808 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"); 1655 2817 1656 2818 /* Split triangle in four sub-triangles (at sides middle points) and call the … … 1659 2821 (in procedure comments key: (Vi) = xi yi ri gi bi) */ 1660 2822 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 1686 2853 /* Gouraud shaded triangle using recursive subdivision until the difference 1687 2854 between corner colors does not exceed the thresholds: 1688 2855 x3 y3 r3 g3 b3 x2 y2 r2 g2 b2 x1 y1 r1 g1 b1 STnoshfill */ 1689 2856 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 1740 2904 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 2925 static 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 2933 static void gl2psResetPostScriptColor(void) 2934 { 2935 gl2ps->lastrgba[0] = gl2ps->lastrgba[1] = gl2ps->lastrgba[2] = -1.; 2936 } 2937 2938 static 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 2950 static 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 2984 static 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 3011 static 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 3150 static 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 3163 static 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 1752 3179 if(gl2ps->options & GL2PS_DRAW_BACKGROUND){ 1753 3180 if(gl2ps->colormode == GL_RGBA || gl2ps->colorsize == 0){ … … 1759 3186 rgba[1] = gl2ps->colormap[index][1]; 1760 3187 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 3203 static GLint gl2psPrintPostScriptEndViewport(void) 3204 { 3205 GLint res; 3206 3207 res = gl2psPrintPrimitives(); 3208 gl2psPrintf("grestore\n"); 3209 return res; 3210 } 3211 3212 static 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 3220 static GL2PSbackend gl2psPS = { 3221 gl2psPrintPostScriptHeader, 3222 gl2psPrintPostScriptFooter, 3223 gl2psPrintPostScriptBeginViewport, 3224 gl2psPrintPostScriptEndViewport, 3225 gl2psPrintPostScriptPrimitive, 3226 gl2psPrintPostScriptFinalPrimitive, 3227 "ps", 3228 "Postscript" 3229 }; 3230 3231 static 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 3248 static 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 3289 static void gl2psPrintTeXPrimitive(void *data) 3290 { 1788 3291 GL2PSprimitive *prim; 1789 3292 1790 prim = *(GL2PSprimitive**)a; 1791 1792 if(gl2ps->options & GL2PS_OCCLUSION_CULL && prim->culled) return; 3293 prim = *(GL2PSprimitive**)data; 1793 3294 1794 3295 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"); 1800 3339 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); 1862 3345 break; 1863 3346 default : 1864 gl2psMsg(GL2PS_ERROR, "Unknown type of primitive to print");1865 3347 break; 1866 3348 } 1867 3349 } 1868 3350 1869 void gl2psPrintPostScriptFooter(void){ 3351 static void gl2psPrintTeXFooter(void) 3352 { 3353 fprintf(gl2ps->stream, "\\end{picture}%s\n", 3354 (gl2ps->options & GL2PS_LANDSCAPE) ? "}" : ""); 3355 } 3356 3357 static 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 3367 static GLint gl2psPrintTeXEndViewport(void) 3368 { 3369 return gl2psPrintPrimitives(); 3370 } 3371 3372 static void gl2psPrintTeXFinalPrimitive(void) 3373 { 3374 } 3375 3376 /* definition of the LaTeX backend */ 3377 3378 static 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 3395 static 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 3405 static 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 3422 static 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 3438 static 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 3448 static 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 3459 static 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 3469 static 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 3480 static 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 3493 static 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 3589 static 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 3643 static 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 3831 static 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 3852 static 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 3874 static 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 3910 static 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 3930 static 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 3949 static 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 3990 static 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 4001 static 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 4015 static 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 4032 static 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 4050 static 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 4083 static 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 4096 static 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 4121 static 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 4131 static 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 4160 static 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 4186 static 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 4206 static 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 4253 static 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 4278 static 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 4304 static 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 4332 static 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 4362 static 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 4449 static 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 4488 static 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 4509 static 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 4525 static 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 4563 static 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 4630 static 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 4650 static 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 4726 static 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! */ 1870 4755 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 4791 static void gl2psPrintPDFBeginViewport(GLint viewport[4]) 4792 { 4793 int offs = 0; 1881 4794 GLint index; 1882 4795 GLfloat rgba[4]; 1883 4796 int x = viewport[0], y = viewport[1], w = viewport[2], h = viewport[3]; 1884 4797 1885 4798 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 1891 4807 if(gl2ps->options & GL2PS_DRAW_BACKGROUND){ 1892 4808 if(gl2ps->colormode == GL_RGBA || gl2ps->colorsize == 0){ … … 1898 4814 rgba[1] = gl2ps->colormap[index][1]; 1899 4815 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 4834 static GLint gl2psPrintPDFEndViewport(void) 4835 { 1917 4836 GLint res; 1918 4837 1919 4838 res = gl2psPrintPrimitives(); 1920 fprintf(gl2ps->stream, "grestore\n");4839 gl2ps->streamlength += gl2psPrintf("Q\n"); 1921 4840 return res; 1922 4841 } 1923 4842 1924 /* The LaTeX routines */ 1925 1926 void gl2psPrintTeXHeader(void){ 1927 char name[256]; 4843 static void gl2psPrintPDFFinalPrimitive(void) 4844 { 4845 } 4846 4847 /* definition of the PDF backend */ 4848 4849 static 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 4866 static 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 4880 static 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 4891 static 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 4944 static void gl2psPrintSVGSmoothTriangle(GL2PSxyz xyz[3], GL2PSrgba rgba[3]) 4945 { 1928 4946 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]); 1939 4961 } 1940 4962 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 5011 static 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 5026 static 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 5039 static 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 5071 static void gl2psPrintSVGPrimitive(void *data) 5072 { 1955 5073 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); 1958 5089 1959 5090 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; 1960 5140 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); 1963 5173 break; 1964 5174 default : … … 1967 5177 } 1968 5178 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){ 5179 static void gl2psPrintSVGFooter(void) 5180 { 5181 gl2psPrintf("</g>\n"); 5182 gl2psPrintf("</svg>\n"); 5183 5184 gl2psPrintGzipFooter(); 5185 } 5186 5187 static 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 5230 static GLint gl2psPrintSVGEndViewport(void) 5231 { 5232 GLint res; 5233 5234 res = gl2psPrintPrimitives(); 5235 gl2psPrintf("</g>\n"); 5236 return res; 5237 } 5238 5239 static void gl2psPrintSVGFinalPrimitive(void) 5240 { 5241 /* End any remaining line, if any */ 5242 gl2psEndSVGLine(); 5243 } 5244 5245 /* definition of the SVG backend */ 5246 5247 static 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 5264 static 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 5272 static 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 5299 static 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 5321 static 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 5337 static 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 5412 static void gl2psPrintPGFFooter(void) 5413 { 5414 fprintf(gl2ps->stream, "\\end{pgfpicture}\n"); 5415 } 5416 5417 static 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 5457 static GLint gl2psPrintPGFEndViewport(void) 5458 { 5459 GLint res; 5460 res = gl2psPrintPrimitives(); 5461 fprintf(gl2ps->stream, "\\end{pgfscope}\n"); 5462 return res; 5463 } 5464 5465 static void gl2psPrintPGFFinalPrimitive(void) 5466 { 5467 } 5468 5469 /* definition of the PGF backend */ 5470 5471 static 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 5491 static GL2PSbackend *gl2psbackends[] = { 5492 &gl2psPS, /* 0 */ 5493 &gl2psEPS, /* 1 */ 5494 &gl2psTEX, /* 2 */ 5495 &gl2psPDF, /* 3 */ 5496 &gl2psSVG, /* 4 */ 5497 &gl2psPGF /* 5 */ 5498 }; 5499 5500 static 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 5519 static 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 1978 5590 return GL2PS_SUCCESS; 1979 5591 } 1980 5592 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 5599 GL2PSDLL_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; 1994 5641 } 1995 5642 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; 2068 5650 gl2ps->maxbestroot = 10; 2069 gl2ps->format = format;2070 gl2ps->title = title;2071 gl2ps->producer = producer;2072 gl2ps->filename = filename;2073 gl2ps->sort = sort;2074 5651 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; 2081 5677 gl2ps->colormode = colormode; 2082 5678 gl2ps->buffersize = buffersize > 0 ? buffersize : 2048 * 2048; 5679 for(i = 0; i < 3; i++){ 5680 gl2ps->lastvertex.xyz[i] = -1.0F; 5681 } 2083 5682 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; 2087 5689 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]); 2088 5701 2089 5702 if(gl2ps->colormode == GL_RGBA){ 2090 5703 gl2ps->colorsize = 0; 2091 5704 gl2ps->colormap = NULL; 5705 glGetFloatv(GL_COLOR_CLEAR_VALUE, gl2ps->bgcolor); 2092 5706 } 2093 5707 else if(gl2ps->colormode == GL_COLOR_INDEX){ … … 2101 5715 gl2ps->colormap = (GL2PSrgba*)gl2psMalloc(gl2ps->colorsize * sizeof(GL2PSrgba)); 2102 5716 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; 2103 5722 } 2104 5723 else{ … … 2109 5728 } 2110 5729 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'; 2116 5733 } 2117 5734 else{ 2118 gl2ps-> stream = stream;2119 /* In case gl2psEndPage failed (e.g. due to a GL2PS_OVERFLOW) and2120 we didn't reopen the stream before calling gl2psBeginPage2121 again, we need to rewind the stream */2122 rewind(gl2ps->stream);2123 }2124 2125 switch(gl2ps->format){2126 case GL2PS_TEX :2127 gl2ps PrintTeXHeader();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); 2138 5755 } 2139 5756 2140 5757 gl2ps->primitives = gl2psListCreate(500, 500, sizeof(GL2PSprimitive*)); 5758 gl2ps->auxprimitives = gl2psListCreate(100, 100, sizeof(GL2PSprimitive*)); 2141 5759 gl2ps->feedback = (GLfloat*)gl2psMalloc(gl2ps->buffersize * sizeof(GLfloat)); 2142 5760 glFeedbackBuffer(gl2ps->buffersize, GL_3D_COLOR, gl2ps->feedback); … … 2146 5764 } 2147 5765 2148 GL2PSDLL_API GLint gl2psEndPage(void){ 5766 GL2PSDLL_API GLint gl2psEndPage(void) 5767 { 2149 5768 GLint res; 2150 5769 … … 2153 5772 res = gl2psPrintPrimitives(); 2154 5773 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 2167 5777 fflush(gl2ps->stream); 2168 5778 2169 5779 gl2psListDelete(gl2ps->primitives); 5780 gl2psListDelete(gl2ps->auxprimitives); 5781 gl2psFreeImagemap(gl2ps->imagemap_head); 2170 5782 gl2psFree(gl2ps->colormap); 5783 gl2psFree(gl2ps->title); 5784 gl2psFree(gl2ps->producer); 5785 gl2psFree(gl2ps->filename); 2171 5786 gl2psFree(gl2ps->feedback); 2172 5787 gl2psFree(gl2ps); … … 2176 5791 } 2177 5792 2178 GL2PSDLL_API GLint gl2psBeginViewport(GLint viewport[4]){ 5793 GL2PSDLL_API GLint gl2psBeginViewport(GLint viewport[4]) 5794 { 2179 5795 if(!gl2ps) return GL2PS_UNINITIALIZED; 2180 5796 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); 2189 5798 2190 5799 return GL2PS_SUCCESS; 2191 5800 } 2192 5801 2193 GL2PSDLL_API GLint gl2psEndViewport(void){ 5802 GL2PSDLL_API GLint gl2psEndViewport(void) 5803 { 2194 5804 GLint res; 2195 5805 2196 5806 if(!gl2ps) return GL2PS_UNINITIALIZED; 2197 5807 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; 2207 5812 2208 5813 return res; 2209 5814 } 2210 5815 2211 GL2PSDLL_API GLint gl2psText(const char *str, const char *fontname, GLshort fontsize){ 2212 GLfloat pos[4]; 5816 GL2PSDLL_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 5822 GL2PSDLL_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 5827 GL2PSDLL_API GLint gl2psSpecial(GLint format, const char *str) 5828 { 5829 return gl2psAddText(GL2PS_SPECIAL, str, "", 0, format, 0.0F); 5830 } 5831 5832 GL2PSDLL_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; 2213 5839 GL2PSprimitive *prim; 2214 5840 GLboolean valid; 2215 5841 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 } 2219 5853 2220 5854 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 */ 2222 5856 2223 5857 glGetFloatv(GL_CURRENT_RASTER_POSITION, pos); 2224 5858 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)); 2276 5860 prim->type = GL2PS_PIXMAP; 2277 5861 prim->boundary = 0; 2278 5862 prim->numverts = 1; 2279 prim->verts = (GL2PSvertex 5863 prim->verts = (GL2PSvertex*)gl2psMalloc(sizeof(GL2PSvertex)); 2280 5864 prim->verts[0].xyz[0] = pos[0] + xorig; 2281 5865 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]; 2284 5867 prim->culled = 0; 2285 prim->dash = 0; 5868 prim->offset = 0; 5869 prim->pattern = 0; 5870 prim->factor = 0; 2286 5871 prim->width = 1; 2287 5872 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); 2298 5909 2299 5910 return GL2PS_SUCCESS; 2300 5911 } 2301 5912 2302 GL2PSDLL_API GLint gl2psEnable(GLint mode){ 5913 GL2PSDLL_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 5938 GL2PSDLL_API GLint gl2psEnable(GLint mode) 5939 { 5940 GLint tmp; 5941 2303 5942 if(!gl2ps) return GL2PS_UNINITIALIZED; 2304 5943 2305 5944 switch(mode){ 2306 5945 case GL2PS_POLYGON_OFFSET_FILL : 2307 glPassThrough(GL2PS_BEGIN_ POLYGON_OFFSET_FILL);5946 glPassThrough(GL2PS_BEGIN_OFFSET_TOKEN); 2308 5947 glGetFloatv(GL_POLYGON_OFFSET_FACTOR, &gl2ps->offset[0]); 2309 5948 glGetFloatv(GL_POLYGON_OFFSET_UNITS, &gl2ps->offset[1]); 2310 5949 break; 2311 5950 case GL2PS_POLYGON_BOUNDARY : 2312 glPassThrough(GL2PS_BEGIN_ POLYGON_BOUNDARY);5951 glPassThrough(GL2PS_BEGIN_BOUNDARY_TOKEN); 2313 5952 break; 2314 5953 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); 2316 5962 break; 2317 5963 default : … … 2323 5969 } 2324 5970 2325 GL2PSDLL_API GLint gl2psDisable(GLint mode){ 5971 GL2PSDLL_API GLint gl2psDisable(GLint mode) 5972 { 2326 5973 if(!gl2ps) return GL2PS_UNINITIALIZED; 2327 5974 2328 5975 switch(mode){ 2329 5976 case GL2PS_POLYGON_OFFSET_FILL : 2330 glPassThrough(GL2PS_END_ POLYGON_OFFSET_FILL);5977 glPassThrough(GL2PS_END_OFFSET_TOKEN); 2331 5978 break; 2332 5979 case GL2PS_POLYGON_BOUNDARY : 2333 glPassThrough(GL2PS_END_ POLYGON_BOUNDARY);5980 glPassThrough(GL2PS_END_BOUNDARY_TOKEN); 2334 5981 break; 2335 5982 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); 2337 5987 break; 2338 5988 default : … … 2344 5994 } 2345 5995 2346 GL2PSDLL_API GLint gl2psPointSize(GLfloat value){ 5996 GL2PSDLL_API GLint gl2psPointSize(GLfloat value) 5997 { 2347 5998 if(!gl2ps) return GL2PS_UNINITIALIZED; 2348 5999 2349 glPassThrough(GL2PS_ SET_POINT_SIZE);6000 glPassThrough(GL2PS_POINT_SIZE_TOKEN); 2350 6001 glPassThrough(value); 2351 6002 … … 2353 6004 } 2354 6005 2355 GL2PSDLL_API GLint gl2psLineWidth(GLfloat value){ 6006 GL2PSDLL_API GLint gl2psLineWidth(GLfloat value) 6007 { 2356 6008 if(!gl2ps) return GL2PS_UNINITIALIZED; 2357 6009 2358 glPassThrough(GL2PS_ SET_LINE_WIDTH);6010 glPassThrough(GL2PS_LINE_WIDTH_TOKEN); 2359 6011 glPassThrough(value); 2360 6012 … … 2362 6014 } 2363 6015 6016 GL2PSDLL_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 6031 GL2PSDLL_API GLint gl2psSetOptions(GLint options) 6032 { 6033 if(!gl2ps) return GL2PS_UNINITIALIZED; 6034 6035 gl2ps->options = options; 6036 6037 return GL2PS_SUCCESS; 6038 } 6039 6040 GL2PSDLL_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 6052 GL2PSDLL_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 6060 GL2PSDLL_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 } 2364 6067 #endif
Note: See TracChangeset
for help on using the changeset viewer.