1 |
/* |
/* |
2 |
* GL2PS, an OpenGL to PostScript Printing Library |
* GL2PS, an OpenGL to PostScript Printing Library |
3 |
* Copyright (C) 1999-2003 Christophe Geuzaine |
* Copyright (C) 1999-2003 Christophe Geuzaine <geuz@geuz.org> |
4 |
* |
* |
5 |
* $Id$ |
* $Id$ |
6 |
* |
* |
|
* E-mail: geuz@geuz.org |
|
|
* URL: http://www.geuz.org/gl2ps/ |
|
|
* |
|
7 |
* This library is free software; you can redistribute it and/or |
* This library is free software; you can redistribute it and/or |
8 |
* modify it under the terms of the GNU Library General Public |
* modify it under the terms of the GNU Library General Public |
9 |
* License as published by the Free Software Foundation; either |
* License as published by the Free Software Foundation; either |
18 |
* License along with this library; if not, write to the Free |
* License along with this library; if not, write to the Free |
19 |
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
20 |
* |
* |
21 |
* Contributor(s): |
* Contributors: |
22 |
* Michael Sweet <mike@easysw.com> |
* Michael Sweet <mike@easysw.com> |
23 |
* Marc Ume <marc.ume@digitalgraphics.be> |
* Marc Ume <marc.ume@digitalgraphics.be> |
24 |
* Jean-Francois Remacle <remacle@scorec.rpi.edu> |
* Jean-Francois Remacle <remacle@scorec.rpi.edu> |
32 |
* Shahzad Muzaffar <Shahzad.Muzaffar@cern.ch> |
* Shahzad Muzaffar <Shahzad.Muzaffar@cern.ch> |
33 |
* Lassi Tuura <lassi.tuura@cern.ch> |
* Lassi Tuura <lassi.tuura@cern.ch> |
34 |
* Guy Barrand <barrand@lal.in2p3.fr> |
* Guy Barrand <barrand@lal.in2p3.fr> |
35 |
|
* Micha Bieber <bieber@traits.de> |
36 |
|
* |
37 |
|
* For the latest info about gl2ps, see http://www.geuz.org/gl2ps/ |
38 |
*/ |
*/ |
39 |
|
|
40 |
#ifdef HAVE_CONFIG_H /* XMakemol */ |
#ifdef HAVE_CONFIG_H /* XMakemol */ |
47 |
#include <sys/types.h> |
#include <sys/types.h> |
48 |
#include <stdarg.h> |
#include <stdarg.h> |
49 |
#include <time.h> |
#include <time.h> |
50 |
|
#include <float.h> |
51 |
#include "gl2ps.h" |
#include "gl2ps.h" |
52 |
|
|
53 |
/* The gl2ps context. gl2ps is not thread safe (we should create a |
/* The gl2ps context. gl2ps is not thread safe (we should create a |
55 |
|
|
56 |
GL2PScontext *gl2ps = NULL; |
GL2PScontext *gl2ps = NULL; |
57 |
|
|
58 |
/* Some 'system' utility routines */ |
/********************************************************************* |
59 |
|
* |
60 |
|
* Utility routines |
61 |
|
* |
62 |
|
*********************************************************************/ |
63 |
|
|
64 |
void gl2psMsg(GLint level, char *fmt, ...){ |
void gl2psMsg(GLint level, char *fmt, ...){ |
65 |
va_list args; |
va_list args; |
105 |
free(ptr); |
free(ptr); |
106 |
} |
} |
107 |
|
|
108 |
|
void gl2psWriteByte(FILE *stream, unsigned char byte){ |
109 |
|
unsigned char h = byte / 16; |
110 |
|
unsigned char l = byte % 16; |
111 |
|
fprintf(stream, "%x%x", h, l); |
112 |
|
} |
113 |
|
|
114 |
|
size_t gl2psWriteBigEndian(unsigned long data, size_t bytes, FILE* fp){ |
115 |
|
size_t i; |
116 |
|
size_t size = sizeof(unsigned long); |
117 |
|
for(i = 1; i <= bytes; ++i){ |
118 |
|
fputc(0xff & (data >> (size-i) * 8), fp); |
119 |
|
} |
120 |
|
return bytes; |
121 |
|
} |
122 |
|
|
123 |
/* The list handling routines */ |
/* The list handling routines */ |
124 |
|
|
125 |
void gl2psListRealloc(GL2PSlist *list, GLint n){ |
void gl2psListRealloc(GL2PSlist *list, GLint n){ |
167 |
memcpy(&list->array[(list->n - 1) * list->size], data, list->size); |
memcpy(&list->array[(list->n - 1) * list->size], data, list->size); |
168 |
} |
} |
169 |
|
|
170 |
GLint gl2psListNbr(GL2PSlist *list){ |
int gl2psListNbr(GL2PSlist *list){ |
171 |
return(list->n); |
return(list->n); |
172 |
} |
} |
173 |
|
|
179 |
return(&list->array[index * list->size]); |
return(&list->array[index * list->size]); |
180 |
} |
} |
181 |
|
|
182 |
|
void gl2psListRead(GL2PSlist *list, GLint index, void *data){ |
183 |
|
if((index < 0) || (index >= list->n)){ |
184 |
|
gl2psMsg(GL2PS_ERROR, "Wrong list index in gl2psListRead"); |
185 |
|
data = 0; |
186 |
|
} |
187 |
|
else{ |
188 |
|
memcpy(data, &list->array[index * list->size], list->size); |
189 |
|
} |
190 |
|
} |
191 |
|
|
192 |
void gl2psListSort(GL2PSlist *list, |
void gl2psListSort(GL2PSlist *list, |
193 |
int (*fcmp)(const void *a, const void *b)){ |
int (*fcmp)(const void *a, const void *b)){ |
194 |
qsort(list->array, list->n, list->size, fcmp); |
qsort(list->array, list->n, list->size, fcmp); |
212 |
} |
} |
213 |
} |
} |
214 |
|
|
215 |
/* The 3D sorting routines */ |
/* Helper for pixmaps and strings */ |
216 |
|
|
217 |
|
GL2PSimage* gl2psCopyPixmap(GL2PSimage* im){ |
218 |
|
int size; |
219 |
|
GL2PSimage* image = (GL2PSimage*)gl2psMalloc(sizeof(GL2PSimage)); |
220 |
|
|
221 |
|
image->width = im->width; |
222 |
|
image->height = im->height; |
223 |
|
image->format = im->format; |
224 |
|
image->type = im->type; |
225 |
|
|
226 |
|
/* FIXME: handle other types/formats */ |
227 |
|
size = image->height*image->width*3*sizeof(GLfloat); |
228 |
|
|
229 |
|
image->pixels = (GLfloat*)gl2psMalloc(size); |
230 |
|
memcpy(image->pixels, im->pixels, size); |
231 |
|
|
232 |
|
return image; |
233 |
|
} |
234 |
|
|
235 |
|
void gl2psFreePixmap(GL2PSimage* im){ |
236 |
|
if(!im) |
237 |
|
return; |
238 |
|
if(im->pixels) |
239 |
|
gl2psFree(im->pixels); |
240 |
|
gl2psFree(im); |
241 |
|
} |
242 |
|
|
243 |
|
GL2PSstring* gl2psCopyText(GL2PSstring* t){ |
244 |
|
GL2PSstring* text = (GL2PSstring*)gl2psMalloc(sizeof(GL2PSstring)); |
245 |
|
text->str = (char*)gl2psMalloc((strlen(t->str)+1)*sizeof(char)); |
246 |
|
strcpy(text->str, t->str); |
247 |
|
text->fontname = (char*)gl2psMalloc((strlen(t->fontname)+1)*sizeof(char)); |
248 |
|
strcpy(text->fontname, t->fontname); |
249 |
|
text->fontsize = t->fontsize; |
250 |
|
text->alignment = t->alignment; |
251 |
|
|
252 |
|
return text; |
253 |
|
} |
254 |
|
|
255 |
|
void gl2psFreeText(GL2PSstring* text){ |
256 |
|
if(!text) |
257 |
|
return; |
258 |
|
if(text->str) |
259 |
|
gl2psFree(text->str); |
260 |
|
if(text->fontname) |
261 |
|
gl2psFree(text->fontname); |
262 |
|
gl2psFree(text); |
263 |
|
} |
264 |
|
|
265 |
|
/* Helpers for rgba colors */ |
266 |
|
|
267 |
|
float gl2psColorDiff(GL2PSrgba rgba1, GL2PSrgba rgba2){ |
268 |
|
int i; |
269 |
|
float res = 0; |
270 |
|
for(i = 0; i < 3; ++i){ |
271 |
|
res += (rgba1[i] - rgba2[i]) * (rgba1[i] - rgba2[i]); |
272 |
|
} |
273 |
|
return res; |
274 |
|
} |
275 |
|
|
276 |
|
GLboolean gl2psSameColor(GL2PSrgba rgba1, GL2PSrgba rgba2){ |
277 |
|
return !(rgba1[0] != rgba2[0] || |
278 |
|
rgba1[1] != rgba2[1] || |
279 |
|
rgba1[2] != rgba2[2]); |
280 |
|
} |
281 |
|
|
282 |
|
GLboolean gl2psVertsSameColor(const GL2PSprimitive *prim){ |
283 |
|
int i; |
284 |
|
|
285 |
|
for(i = 1; i < prim->numverts; i++){ |
286 |
|
if(!gl2psSameColor(prim->verts[0].rgba, prim->verts[i].rgba)){ |
287 |
|
return 0; |
288 |
|
} |
289 |
|
} |
290 |
|
return 1; |
291 |
|
} |
292 |
|
|
293 |
|
void gl2psSetLastColor(GL2PSrgba rgba){ |
294 |
|
int i; |
295 |
|
for(i = 0; i < 3; ++i){ |
296 |
|
gl2ps->lastrgba[i] = rgba[i]; |
297 |
|
} |
298 |
|
} |
299 |
|
|
300 |
|
/********************************************************************* |
301 |
|
* |
302 |
|
* 3D sorting routines |
303 |
|
* |
304 |
|
*********************************************************************/ |
305 |
|
|
306 |
GLfloat gl2psComparePointPlane(GL2PSxyz point, GL2PSplane plane){ |
GLfloat gl2psComparePointPlane(GL2PSxyz point, GL2PSplane plane){ |
307 |
return(plane[0] * point[0] + |
return(plane[0] * point[0] + |
803 |
} |
} |
804 |
} |
} |
805 |
|
|
806 |
/* The 2D sorting routines (for occlusion culling) */ |
/********************************************************************* |
807 |
|
* |
808 |
|
* 2D sorting routines (for occlusion culling) |
809 |
|
* |
810 |
|
*********************************************************************/ |
811 |
|
|
812 |
GLint gl2psGetPlaneFromPoints(GL2PSxyz a, GL2PSxyz b, GL2PSplane plane){ |
GLint gl2psGetPlaneFromPoints(GL2PSxyz a, GL2PSxyz b, GL2PSplane plane){ |
813 |
GLfloat n; |
GLfloat n; |
1216 |
gl2psBuildPolygonBoundary(tree->front); |
gl2psBuildPolygonBoundary(tree->front); |
1217 |
} |
} |
1218 |
|
|
1219 |
/* The feedback buffer parser */ |
/********************************************************************* |
1220 |
|
* |
1221 |
|
* Feedback buffer parser |
1222 |
|
* |
1223 |
|
*********************************************************************/ |
1224 |
|
|
1225 |
void gl2psAddPolyPrimitive(GLshort type, GLshort numverts, |
void gl2psAddPolyPrimitive(GLshort type, GLshort numverts, |
1226 |
GL2PSvertex *verts, GLint offset, |
GL2PSvertex *verts, GLint offset, |
1431 |
} |
} |
1432 |
} |
} |
1433 |
|
|
1434 |
GLboolean gl2psSameColor(GL2PSrgba rgba1, GL2PSrgba rgba2){ |
/********************************************************************* |
1435 |
return !(rgba1[0] != rgba2[0] || |
* |
1436 |
rgba1[1] != rgba2[1] || |
* PostScript routines |
1437 |
rgba1[2] != rgba2[2]); |
* |
1438 |
} |
*********************************************************************/ |
|
|
|
|
GLboolean gl2psVertsSameColor(const GL2PSprimitive *prim){ |
|
|
int i; |
|
|
|
|
|
for(i = 1; i < prim->numverts; i++){ |
|
|
if(!gl2psSameColor(prim->verts[0].rgba, prim->verts[i].rgba)){ |
|
|
return 0; |
|
|
} |
|
|
} |
|
|
return 1; |
|
|
} |
|
|
|
|
|
/* The PostScript routines. Other (vector) image formats should be |
|
|
easy to generate by creating the three corresponding routines |
|
|
(gl2psPrintXXXHeader, gl2psPrintXXXPrimitive, gl2psPrintXXXFooter, |
|
|
gl2psPrintXXXBeginViewport and gl2psPrintXXXEndViewport) for the |
|
|
new format. */ |
|
|
|
|
|
void gl2psWriteByte(FILE *stream, unsigned char byte){ |
|
|
unsigned char h = byte / 16; |
|
|
unsigned char l = byte % 16; |
|
|
fprintf(stream, "%x%x", h, l); |
|
|
} |
|
1439 |
|
|
1440 |
void gl2psGetRGB(GLfloat *pixels, GLsizei width, GLsizei height, GLuint x, GLuint y, |
void gl2psGetRGB(GLfloat *pixels, GLsizei width, GLsizei height, GLuint x, GLuint y, |
1441 |
GLfloat *red, GLfloat *green, GLfloat *blue){ |
GLfloat *red, GLfloat *green, GLfloat *blue){ |
1463 |
|
|
1464 |
fprintf(stream, "gsave\n"); |
fprintf(stream, "gsave\n"); |
1465 |
fprintf(stream, "%.2f %.2f translate\n", x, y); |
fprintf(stream, "%.2f %.2f translate\n", x, y); |
1466 |
fprintf(stream, "%d %d scale\n", width, height); |
fprintf(stream, "%d %d scale\n", (int)width, (int)height); |
1467 |
|
|
1468 |
if(greyscale){ /* greyscale, 8 bits per pixel */ |
if(greyscale){ /* greyscale, 8 bits per pixel */ |
1469 |
fprintf(stream, "/picstr %d string def\n", width); |
fprintf(stream, "/picstr %d string def\n", (int)width); |
1470 |
fprintf(stream, "%d %d %d\n", width, height, 8); |
fprintf(stream, "%d %d %d\n", (int)width, (int)height, 8); |
1471 |
fprintf(stream, "[ %d 0 0 -%d 0 %d ]\n", width, height, height); |
fprintf(stream, "[ %d 0 0 -%d 0 %d ]\n", (int)width, (int)height, (int)height); |
1472 |
fprintf(stream, "{ currentfile picstr readhexstring pop }\n"); |
fprintf(stream, "{ currentfile picstr readhexstring pop }\n"); |
1473 |
fprintf(stream, "image\n"); |
fprintf(stream, "image\n"); |
1474 |
for(row = 0; row < height; row++){ |
for(row = 0; row < height; row++){ |
1489 |
nbyte2 *=3; |
nbyte2 *=3; |
1490 |
col_max = (nbyte2 * 4)/3; |
col_max = (nbyte2 * 4)/3; |
1491 |
fprintf(stream, "/rgbstr %d string def\n", nbyte2); |
fprintf(stream, "/rgbstr %d string def\n", nbyte2); |
1492 |
fprintf(stream, "%d %d %d\n", col_max, height, 2); |
fprintf(stream, "%d %d %d\n", (int)col_max, (int)height, 2); |
1493 |
fprintf(stream, "[ %d 0 0 -%d 0 %d ]\n", col_max, height, height); |
fprintf(stream, "[ %d 0 0 -%d 0 %d ]\n", (int)col_max, (int)height, (int)height); |
1494 |
fprintf(stream, "{ currentfile rgbstr readhexstring pop }\n" ); |
fprintf(stream, "{ currentfile rgbstr readhexstring pop }\n" ); |
1495 |
fprintf(stream, "false 3\n" ); |
fprintf(stream, "false 3\n" ); |
1496 |
fprintf(stream, "colorimage\n" ); |
fprintf(stream, "colorimage\n" ); |
1537 |
nbyte4 *=3; |
nbyte4 *=3; |
1538 |
col_max = (nbyte4 * 2)/3; |
col_max = (nbyte4 * 2)/3; |
1539 |
fprintf(stream, "/rgbstr %d string def\n", nbyte4); |
fprintf(stream, "/rgbstr %d string def\n", nbyte4); |
1540 |
fprintf(stream, "%d %d %d\n", col_max, height, 4); |
fprintf(stream, "%d %d %d\n", (int)col_max, (int)height, 4); |
1541 |
fprintf(stream, "[ %d 0 0 -%d 0 %d ]\n", col_max, height, height); |
fprintf(stream, "[ %d 0 0 -%d 0 %d ]\n", (int)col_max, (int)height, (int)height); |
1542 |
fprintf(stream, "{ currentfile rgbstr readhexstring pop }\n"); |
fprintf(stream, "{ currentfile rgbstr readhexstring pop }\n"); |
1543 |
fprintf(stream, "false 3\n"); |
fprintf(stream, "false 3\n"); |
1544 |
fprintf(stream, "colorimage\n"); |
fprintf(stream, "colorimage\n"); |
1562 |
else{ /* color, 8 bits for r and g and b; rgbs following each other */ |
else{ /* color, 8 bits for r and g and b; rgbs following each other */ |
1563 |
nbyte8 = width * 3; |
nbyte8 = width * 3; |
1564 |
fprintf(stream, "/rgbstr %d string def\n", nbyte8); |
fprintf(stream, "/rgbstr %d string def\n", nbyte8); |
1565 |
fprintf(stream, "%d %d %d\n", width, height, 8); |
fprintf(stream, "%d %d %d\n", (int)width, (int)height, 8); |
1566 |
fprintf(stream, "[ %d 0 0 -%d 0 %d ]\n", width, height, height); |
fprintf(stream, "[ %d 0 0 -%d 0 %d ]\n", (int)width, (int)height, (int)height); |
1567 |
fprintf(stream, "{ currentfile rgbstr readhexstring pop }\n"); |
fprintf(stream, "{ currentfile rgbstr readhexstring pop }\n"); |
1568 |
fprintf(stream, "false 3\n"); |
fprintf(stream, "false 3\n"); |
1569 |
fprintf(stream, "colorimage\n"); |
fprintf(stream, "colorimage\n"); |
1600 |
|
|
1601 |
fprintf(gl2ps->stream, |
fprintf(gl2ps->stream, |
1602 |
"%%%%Title: %s\n" |
"%%%%Title: %s\n" |
1603 |
"%%%%Creator: GL2PS %d.%d.%d, an OpenGL to PostScript Printing Library\n" |
"%%%%Creator: GL2PS %d.%d.%d, (C) 1999-2003 Christophe Geuzaine <geuz@geuz.org>\n" |
1604 |
"%%%%For: %s\n" |
"%%%%For: %s\n" |
1605 |
"%%%%CreationDate: %s" |
"%%%%CreationDate: %s" |
1606 |
"%%%%LanguageLevel: 3\n" |
"%%%%LanguageLevel: 3\n" |
1614 |
"%%%%Orientation: %s\n" |
"%%%%Orientation: %s\n" |
1615 |
"%%%%DocumentMedia: Default %d %d 0 () ()\n", |
"%%%%DocumentMedia: Default %d %d 0 () ()\n", |
1616 |
(gl2ps->options & GL2PS_LANDSCAPE) ? "Landscape" : "Portrait", |
(gl2ps->options & GL2PS_LANDSCAPE) ? "Landscape" : "Portrait", |
1617 |
(gl2ps->options & GL2PS_LANDSCAPE) ? gl2ps->viewport[3] : gl2ps->viewport[2], |
(gl2ps->options & GL2PS_LANDSCAPE) ? (int)gl2ps->viewport[3] : |
1618 |
(gl2ps->options & GL2PS_LANDSCAPE) ? gl2ps->viewport[2] : gl2ps->viewport[3]); |
(int)gl2ps->viewport[2], |
1619 |
|
(gl2ps->options & GL2PS_LANDSCAPE) ? (int)gl2ps->viewport[2] : |
1620 |
|
(int)gl2ps->viewport[3]); |
1621 |
} |
} |
1622 |
|
|
1623 |
fprintf(gl2ps->stream, |
fprintf(gl2ps->stream, |
1624 |
"%%%%BoundingBox: %d %d %d %d\n" |
"%%%%BoundingBox: %d %d %d %d\n" |
|
"%%%%Copyright: GNU LGPL (C) 1999-2003 Christophe Geuzaine <geuz@geuz.org>\n" |
|
1625 |
"%%%%EndComments\n", |
"%%%%EndComments\n", |
1626 |
(gl2ps->options & GL2PS_LANDSCAPE) ? gl2ps->viewport[1] : gl2ps->viewport[0], |
(gl2ps->options & GL2PS_LANDSCAPE) ? (int)gl2ps->viewport[1] : |
1627 |
(gl2ps->options & GL2PS_LANDSCAPE) ? gl2ps->viewport[0] : gl2ps->viewport[1], |
(int)gl2ps->viewport[0], |
1628 |
(gl2ps->options & GL2PS_LANDSCAPE) ? gl2ps->viewport[3] : gl2ps->viewport[2], |
(gl2ps->options & GL2PS_LANDSCAPE) ? (int)gl2ps->viewport[0] : |
1629 |
(gl2ps->options & GL2PS_LANDSCAPE) ? gl2ps->viewport[2] : gl2ps->viewport[3]); |
(int)gl2ps->viewport[1], |
1630 |
|
(gl2ps->options & GL2PS_LANDSCAPE) ? (int)gl2ps->viewport[3] : |
1631 |
|
(int)gl2ps->viewport[2], |
1632 |
|
(gl2ps->options & GL2PS_LANDSCAPE) ? (int)gl2ps->viewport[2] : |
1633 |
|
(int)gl2ps->viewport[3]); |
1634 |
|
|
1635 |
/* RGB color: r g b C (replace C by G in output to change from rgb to gray) |
/* RGB color: r g b C (replace C by G in output to change from rgb to gray) |
1636 |
Grayscale: r g b G |
Grayscale: r g b G |
1776 |
if(gl2ps->options & GL2PS_LANDSCAPE){ |
if(gl2ps->options & GL2PS_LANDSCAPE){ |
1777 |
fprintf(gl2ps->stream, |
fprintf(gl2ps->stream, |
1778 |
"%d 0 translate 90 rotate\n", |
"%d 0 translate 90 rotate\n", |
1779 |
gl2ps->viewport[3]); |
(int)gl2ps->viewport[3]); |
1780 |
} |
} |
1781 |
|
|
1782 |
fprintf(gl2ps->stream, |
fprintf(gl2ps->stream, |
1801 |
"newpath %d %d moveto %d %d lineto %d %d lineto %d %d lineto\n" |
"newpath %d %d moveto %d %d lineto %d %d lineto %d %d lineto\n" |
1802 |
"closepath fill\n", |
"closepath fill\n", |
1803 |
rgba[0], rgba[1], rgba[2], |
rgba[0], rgba[1], rgba[2], |
1804 |
gl2ps->viewport[0], gl2ps->viewport[1], gl2ps->viewport[2], |
(int)gl2ps->viewport[0], (int)gl2ps->viewport[1], (int)gl2ps->viewport[2], |
1805 |
gl2ps->viewport[1], gl2ps->viewport[2], gl2ps->viewport[3], |
(int)gl2ps->viewport[1], (int)gl2ps->viewport[2], (int)gl2ps->viewport[3], |
1806 |
gl2ps->viewport[0], gl2ps->viewport[3]); |
(int)gl2ps->viewport[0], (int)gl2ps->viewport[3]); |
1807 |
} |
} |
1808 |
} |
} |
1809 |
|
|
1810 |
void gl2psPrintPostScriptColor(GL2PSrgba rgba){ |
void gl2psPrintPostScriptColor(GL2PSrgba rgba){ |
1811 |
if(!gl2psSameColor(gl2ps->lastrgba, rgba)){ |
if(!gl2psSameColor(gl2ps->lastrgba, rgba)){ |
1812 |
gl2ps->lastrgba[0] = rgba[0]; |
gl2psSetLastColor(rgba); |
|
gl2ps->lastrgba[1] = rgba[1]; |
|
|
gl2ps->lastrgba[2] = rgba[2]; |
|
1813 |
fprintf(gl2ps->stream, "%g %g %g C\n", rgba[0], rgba[1], rgba[2]); |
fprintf(gl2ps->stream, "%g %g %g C\n", rgba[0], rgba[1], rgba[2]); |
1814 |
} |
} |
1815 |
} |
} |
1956 |
return res; |
return res; |
1957 |
} |
} |
1958 |
|
|
1959 |
/* The LaTeX routines */ |
/********************************************************************* |
1960 |
|
* |
1961 |
|
* LaTeX routines |
1962 |
|
* |
1963 |
|
*********************************************************************/ |
1964 |
|
|
1965 |
void gl2psPrintTeXHeader(void){ |
void gl2psPrintTeXHeader(void){ |
1966 |
char name[256]; |
char name[256]; |
1987 |
"\\end{picture}%%\n" |
"\\end{picture}%%\n" |
1988 |
"%s\\begin{picture}(%d,%d)(0,0)\n", |
"%s\\begin{picture}(%d,%d)(0,0)\n", |
1989 |
name, (gl2ps->options & GL2PS_LANDSCAPE) ? "\\rotatebox{90}{" : "", |
name, (gl2ps->options & GL2PS_LANDSCAPE) ? "\\rotatebox{90}{" : "", |
1990 |
gl2ps->viewport[2], gl2ps->viewport[3]); |
(int)gl2ps->viewport[2], (int)gl2ps->viewport[3]); |
1991 |
} |
} |
1992 |
|
|
1993 |
void gl2psPrintTeXPrimitive(void *a, void *b){ |
void gl2psPrintTeXPrimitive(void *a, void *b){ |
1997 |
|
|
1998 |
switch(prim->type){ |
switch(prim->type){ |
1999 |
case GL2PS_TEXT : |
case GL2PS_TEXT : |
2000 |
|
#if 0 /* old code: */ |
2001 |
fprintf(gl2ps->stream, "\\put(%g,%g){\\makebox(0,0)[lb]{%s}}\n", |
fprintf(gl2ps->stream, "\\put(%g,%g){\\makebox(0,0)[lb]{%s}}\n", |
2002 |
prim->verts[0].xyz[0], prim->verts[0].xyz[1], prim->text->str); |
prim->verts[0].xyz[0], prim->verts[0].xyz[1], prim->text->str); |
2003 |
|
#endif |
2004 |
|
fprintf(gl2ps->stream, "\\fontsize{%d}{0}\n\\selectfont", |
2005 |
|
prim->text->fontsize); |
2006 |
|
fprintf(gl2ps->stream, "\\put(%g,%g){\\makebox(0,0)", |
2007 |
|
prim->verts[0].xyz[0], prim->verts[0].xyz[1]); |
2008 |
|
switch (prim->text->alignment) { |
2009 |
|
case GL2PS_TEXT_CL: |
2010 |
|
fprintf(gl2ps->stream, "[l]"); |
2011 |
|
break; |
2012 |
|
case GL2PS_TEXT_CR: |
2013 |
|
fprintf(gl2ps->stream, "[r]"); |
2014 |
|
break; |
2015 |
|
case GL2PS_TEXT_B: |
2016 |
|
fprintf(gl2ps->stream, "[b]"); |
2017 |
|
break; |
2018 |
|
case GL2PS_TEXT_BL: |
2019 |
|
fprintf(gl2ps->stream, "[bl]"); |
2020 |
|
break; |
2021 |
|
case GL2PS_TEXT_BR: |
2022 |
|
fprintf(gl2ps->stream, "[br]"); |
2023 |
|
break; |
2024 |
|
case GL2PS_TEXT_T: |
2025 |
|
fprintf(gl2ps->stream, "[t]"); |
2026 |
|
break; |
2027 |
|
case GL2PS_TEXT_TL: |
2028 |
|
fprintf(gl2ps->stream, "[tl]"); |
2029 |
|
break; |
2030 |
|
case GL2PS_TEXT_TR: |
2031 |
|
fprintf(gl2ps->stream, "[tr]"); |
2032 |
|
break; |
2033 |
|
default: |
2034 |
|
break; |
2035 |
|
} |
2036 |
|
fprintf(gl2ps->stream, "{\\textcolor[rgb]{%f,%f,%f}{", |
2037 |
|
prim->verts[0].rgba[0], prim->verts[0].rgba[1], prim->verts[0].rgba[2]); |
2038 |
|
fprintf(gl2ps->stream, "{%s}}}}\n", prim->text->str); |
2039 |
break; |
break; |
2040 |
default : |
default : |
2041 |
break; |
break; |
2054 |
return GL2PS_SUCCESS; |
return GL2PS_SUCCESS; |
2055 |
} |
} |
2056 |
|
|
2057 |
/* The general primitive printing routine */ |
/********************************************************************* |
2058 |
|
* |
2059 |
|
* PDF routines |
2060 |
|
* |
2061 |
|
*********************************************************************/ |
2062 |
|
|
2063 |
|
int gl2psPrintPDFCompressorType(){ |
2064 |
|
if(gl2ps->options & GL2PS_DEFLATE){ |
2065 |
|
return fprintf(gl2ps->stream, "/Filter [/FlateDecode]\n"); |
2066 |
|
} |
2067 |
|
return 0; |
2068 |
|
} |
2069 |
|
|
2070 |
|
int gl2psPrintPDFStrokeColor(GL2PSrgba rgba){ |
2071 |
|
int offs = 0; |
2072 |
|
int i; |
2073 |
|
|
2074 |
|
gl2psSetLastColor(rgba); |
2075 |
|
for(i = 0; i < 3; ++i){ |
2076 |
|
if(GL2PS_ZERO(rgba[i])) |
2077 |
|
offs += fprintf(gl2ps->stream, "%.0f ", 0.); |
2078 |
|
else if(rgba[i] < 1e-4 || rgba[i] > 1e6) /* avoid %e formatting */ |
2079 |
|
offs += fprintf(gl2ps->stream, "%f ", rgba[i]); |
2080 |
|
else |
2081 |
|
offs += fprintf(gl2ps->stream, "%g ", rgba[i]); |
2082 |
|
} |
2083 |
|
offs += fprintf(gl2ps->stream, "RG\n"); |
2084 |
|
return offs; |
2085 |
|
} |
2086 |
|
|
2087 |
|
int gl2psPrintPDFFillColor(GL2PSrgba rgba){ |
2088 |
|
int offs = 0; |
2089 |
|
int i; |
2090 |
|
|
2091 |
|
for(i = 0; i < 3; ++i){ |
2092 |
|
if(GL2PS_ZERO(rgba[i])) |
2093 |
|
offs += fprintf(gl2ps->stream, "%.0f ", 0.); |
2094 |
|
else if(rgba[i] < 1e-4 || rgba[i] > 1e6) /* avoid %e formatting */ |
2095 |
|
offs += fprintf(gl2ps->stream, "%f ", rgba[i]); |
2096 |
|
else |
2097 |
|
offs += fprintf(gl2ps->stream, "%g ", rgba[i]); |
2098 |
|
} |
2099 |
|
offs += fprintf(gl2ps->stream, "rg\n"); |
2100 |
|
return offs; |
2101 |
|
} |
2102 |
|
|
2103 |
|
int gl2psPrintPDFLineWidth(float lw){ |
2104 |
|
if(GL2PS_ZERO(lw)) |
2105 |
|
return fprintf(gl2ps->stream, "%.0f w\n", 0.); |
2106 |
|
else if(lw < 1e-4 || lw > 1e6) /* avoid %e formatting */ |
2107 |
|
return fprintf(gl2ps->stream, "%f w\n", lw); |
2108 |
|
else |
2109 |
|
return fprintf(gl2ps->stream, "%g w\n", lw); |
2110 |
|
} |
2111 |
|
|
2112 |
|
/* Print 1st PDF object - file info */ |
2113 |
|
|
2114 |
|
int gl2psPrintPDFInfo(){ |
2115 |
|
int offs; |
2116 |
|
time_t now; |
2117 |
|
struct tm *newtime; |
2118 |
|
|
2119 |
|
time(&now); |
2120 |
|
newtime = gmtime(&now); |
2121 |
|
|
2122 |
|
offs = fprintf(gl2ps->stream, |
2123 |
|
"1 0 obj\n" |
2124 |
|
"<<\n" |
2125 |
|
"/Title (%s)\n" |
2126 |
|
"/Creator (%s)\n" |
2127 |
|
"/Producer (GL2PS %d.%d.%d, (C) 1999-2003 Christophe Geuzaine <geuz@geuz.org>)\n", |
2128 |
|
gl2ps->title, gl2ps->producer, |
2129 |
|
GL2PS_MAJOR_VERSION, GL2PS_MINOR_VERSION, GL2PS_PATCH_VERSION); |
2130 |
|
|
2131 |
|
if(!newtime){ |
2132 |
|
offs += fprintf(gl2ps->stream, |
2133 |
|
">>\n" |
2134 |
|
"endobj\n"); |
2135 |
|
return offs; |
2136 |
|
} |
2137 |
|
|
2138 |
|
offs += fprintf(gl2ps->stream, |
2139 |
|
"/CreationDate (D:%d%02d%02d%02d%02d%02d)\n" |
2140 |
|
">>\n" |
2141 |
|
"endobj\n", |
2142 |
|
newtime->tm_year+1900, |
2143 |
|
newtime->tm_mon+1, |
2144 |
|
newtime->tm_mday, |
2145 |
|
newtime->tm_hour, |
2146 |
|
newtime->tm_min, |
2147 |
|
newtime->tm_sec); |
2148 |
|
return offs; |
2149 |
|
} |
2150 |
|
|
2151 |
|
/* Create catalog and page structure - 2nd and 3th PDF object */ |
2152 |
|
|
2153 |
|
int gl2psPrintPDFCatalog(){ |
2154 |
|
return fprintf(gl2ps->stream, |
2155 |
|
"2 0 obj\n" |
2156 |
|
"<<\n" |
2157 |
|
"/Type /Catalog\n" |
2158 |
|
"/Pages 3 0 R\n" |
2159 |
|
">>\n" |
2160 |
|
"endobj\n"); |
2161 |
|
} |
2162 |
|
|
2163 |
|
int gl2psPrintPDFPages(){ |
2164 |
|
return fprintf(gl2ps->stream, |
2165 |
|
"3 0 obj\n" |
2166 |
|
"<<\n" |
2167 |
|
"/Type /Pages\n" |
2168 |
|
"/Kids [6 0 R]\n" |
2169 |
|
"/Count 1\n" |
2170 |
|
">>\n" |
2171 |
|
"endobj\n"); |
2172 |
|
} |
2173 |
|
|
2174 |
|
/* Open stream for data - graphical objects, fonts etc. PDF object 4*/ |
2175 |
|
|
2176 |
|
int gl2psOpenPDFDataStream(){ |
2177 |
|
int offs = 0; |
2178 |
|
|
2179 |
|
offs += fprintf(gl2ps->stream, |
2180 |
|
"4 0 obj\n" |
2181 |
|
"<<\n" |
2182 |
|
"/Length 5 0 R\n" ); |
2183 |
|
offs += gl2psPrintPDFCompressorType(); |
2184 |
|
offs += fprintf(gl2ps->stream, |
2185 |
|
">>\n" |
2186 |
|
"stream\n"); |
2187 |
|
return offs; |
2188 |
|
} |
2189 |
|
|
2190 |
|
/* Stream setup - Graphics state, fill background if allowed */ |
2191 |
|
|
2192 |
|
int gl2psOpenPDFDataStreamWritePreface(){ |
2193 |
|
int offs; |
2194 |
|
GLint index; |
2195 |
|
GLfloat rgba[4]; |
2196 |
|
|
2197 |
|
offs = fprintf(gl2ps->stream, "/GS1 gs\n"); |
2198 |
|
|
2199 |
|
if(gl2ps->options & GL2PS_DRAW_BACKGROUND){ |
2200 |
|
if(gl2ps->colormode == GL_RGBA || gl2ps->colorsize == 0){ |
2201 |
|
glGetFloatv(GL_COLOR_CLEAR_VALUE, rgba); |
2202 |
|
} |
2203 |
|
else{ |
2204 |
|
glGetIntegerv(GL_INDEX_CLEAR_VALUE, &index); |
2205 |
|
rgba[0] = gl2ps->colormap[index][0]; |
2206 |
|
rgba[1] = gl2ps->colormap[index][1]; |
2207 |
|
rgba[2] = gl2ps->colormap[index][2]; |
2208 |
|
rgba[3] = 0.; |
2209 |
|
} |
2210 |
|
offs += gl2psPrintPDFFillColor(rgba); |
2211 |
|
offs += fprintf(gl2ps->stream, "%d %d %d %d re\n", |
2212 |
|
(int)gl2ps->viewport[0], (int)gl2ps->viewport[1], |
2213 |
|
(int)gl2ps->viewport[2], (int)gl2ps->viewport[3]); |
2214 |
|
offs += fprintf(gl2ps->stream, "f\n"); |
2215 |
|
} |
2216 |
|
return offs; |
2217 |
|
} |
2218 |
|
|
2219 |
|
/* Use the functions above to create the first part of the PDF*/ |
2220 |
|
|
2221 |
|
void gl2psPrintPDFHeader(){ |
2222 |
|
int offs; |
2223 |
|
|
2224 |
|
/* tlist, tidxlist, ilist and slist contain triangles, indexes for |
2225 |
|
consecutive triangles, images and strings */ |
2226 |
|
gl2ps->tlist = gl2psListCreate(100, 100, sizeof(GL2PStriangle)); |
2227 |
|
gl2ps->tidxlist = gl2psListCreate(100, 100, sizeof(int)); |
2228 |
|
gl2ps->ilist = gl2psListCreate(100, 100, sizeof(GL2PSimage*)); |
2229 |
|
gl2ps->slist = gl2psListCreate(100, 100, sizeof(GL2PSstring*)); |
2230 |
|
|
2231 |
|
gl2ps->lasttype = GL2PS_NOTYPE; |
2232 |
|
gl2ps->consec_cnt = 0; |
2233 |
|
gl2ps->consec_inner_cnt = 0; |
2234 |
|
|
2235 |
|
offs = fprintf(gl2ps->stream, "%%PDF-1.3\n"); |
2236 |
|
gl2ps->cref[0] = offs; |
2237 |
|
|
2238 |
|
offs += gl2psPrintPDFInfo(); |
2239 |
|
gl2ps->cref[1] = offs; |
2240 |
|
|
2241 |
|
offs += gl2psPrintPDFCatalog(); |
2242 |
|
gl2ps->cref[2] = offs; |
2243 |
|
|
2244 |
|
offs += gl2psPrintPDFPages(); |
2245 |
|
gl2ps->cref[3] = offs; |
2246 |
|
|
2247 |
|
offs += gl2psOpenPDFDataStream(); |
2248 |
|
gl2ps->cref[4] = offs; /* finished in gl2psPrintPDFFooter */ |
2249 |
|
gl2ps->streamlength = gl2psOpenPDFDataStreamWritePreface(); |
2250 |
|
} |
2251 |
|
|
2252 |
|
int gl2psFlushPDFTriangles(){ |
2253 |
|
int offs = 0; |
2254 |
|
|
2255 |
|
if(gl2ps->lasttype == GL2PS_TRIANGLE && !gl2ps->last_triangle_finished){ |
2256 |
|
gl2psListAdd(gl2ps->tidxlist, &gl2ps->consec_inner_cnt); |
2257 |
|
offs = fprintf(gl2ps->stream, "/Sh%d sh\n", gl2ps->consec_cnt++); |
2258 |
|
gl2ps->consec_inner_cnt = 0; |
2259 |
|
gl2ps->streamlength += offs; |
2260 |
|
gl2ps->last_triangle_finished = 1; |
2261 |
|
} |
2262 |
|
return offs; |
2263 |
|
} |
2264 |
|
|
2265 |
|
int gl2psFlushPDFLines(){ |
2266 |
|
int offs = 0; |
2267 |
|
|
2268 |
|
if(gl2ps->lasttype == GL2PS_LINE && !gl2ps->last_line_finished){ |
2269 |
|
offs = fprintf(gl2ps->stream, "S\n"); |
2270 |
|
gl2ps->streamlength += offs; |
2271 |
|
gl2ps->last_line_finished = 1; |
2272 |
|
} |
2273 |
|
return offs; |
2274 |
|
} |
2275 |
|
|
2276 |
|
/* The central primitive drawing */ |
2277 |
|
|
2278 |
|
void gl2psPrintPDFPrimitive(void *a, void *b){ |
2279 |
|
GL2PSprimitive *prim; |
2280 |
|
GL2PStriangle t; |
2281 |
|
GL2PSimage* image; |
2282 |
|
GL2PSstring* str; |
2283 |
|
|
2284 |
|
prim = *(GL2PSprimitive**)a; |
2285 |
|
|
2286 |
|
if((gl2ps->options & GL2PS_OCCLUSION_CULL) && prim->culled) return; |
2287 |
|
|
2288 |
|
if(prim->type != GL2PS_TRIANGLE) |
2289 |
|
gl2psFlushPDFTriangles(); |
2290 |
|
if(prim->type != GL2PS_LINE) |
2291 |
|
gl2psFlushPDFLines(); |
2292 |
|
|
2293 |
|
switch(prim->type){ |
2294 |
|
case GL2PS_PIXMAP : |
2295 |
|
image = gl2psCopyPixmap(prim->image); |
2296 |
|
gl2psListAdd(gl2ps->ilist, &image); |
2297 |
|
gl2ps->streamlength += fprintf(gl2ps->stream, |
2298 |
|
"q\n" |
2299 |
|
"%d 0 0 %d %f %f cm\n" |
2300 |
|
"/Im%d Do\n" |
2301 |
|
"Q\n", |
2302 |
|
(int)prim->image->width, (int)prim->image->height, |
2303 |
|
prim->verts[0].xyz[0], prim->verts[0].xyz[1], |
2304 |
|
gl2psListNbr(gl2ps->ilist)-1); |
2305 |
|
break; |
2306 |
|
case GL2PS_TEXT : |
2307 |
|
str = gl2psCopyText(prim->text); |
2308 |
|
gl2psListAdd(gl2ps->slist, &str); |
2309 |
|
gl2ps->streamlength += gl2psPrintPDFFillColor(prim->verts[0].rgba); |
2310 |
|
gl2ps->streamlength += fprintf(gl2ps->stream, |
2311 |
|
"BT\n" |
2312 |
|
"/F%d %d Tf\n" |
2313 |
|
"%f %f Td\n" |
2314 |
|
"(%s) Tj\n" |
2315 |
|
"ET\n", |
2316 |
|
gl2psListNbr(gl2ps->slist)-1, |
2317 |
|
prim->text->fontsize, prim->verts[0].xyz[0], |
2318 |
|
prim->verts[0].xyz[1], prim->text->str); |
2319 |
|
break; |
2320 |
|
case GL2PS_POINT : |
2321 |
|
if(gl2ps->lastlinewidth != prim->width){ |
2322 |
|
gl2ps->lastlinewidth = prim->width; |
2323 |
|
gl2ps->streamlength += gl2psPrintPDFLineWidth(gl2ps->lastlinewidth); |
2324 |
|
} |
2325 |
|
gl2ps->streamlength += fprintf(gl2ps->stream, "1 J\n"); |
2326 |
|
gl2ps->streamlength += gl2psPrintPDFStrokeColor(prim->verts[0].rgba); |
2327 |
|
gl2ps->streamlength += fprintf(gl2ps->stream, "%f %f m %f %f l S\n", |
2328 |
|
prim->verts[0].xyz[0], prim->verts[0].xyz[1], |
2329 |
|
prim->verts[0].xyz[0], prim->verts[0].xyz[1]); |
2330 |
|
gl2ps->streamlength += fprintf(gl2ps->stream, "0 J\n"); |
2331 |
|
break; |
2332 |
|
case GL2PS_LINE : |
2333 |
|
gl2ps->line_width_diff = gl2ps->lastlinewidth != prim->width; |
2334 |
|
gl2ps->line_rgb_diff = !GL2PS_ZERO(gl2psColorDiff(prim->verts[0].rgba, gl2ps->lastrgba)); |
2335 |
|
|
2336 |
|
if(gl2ps->line_width_diff || gl2ps->line_rgb_diff || prim->dash){ |
2337 |
|
gl2psFlushPDFLines(); |
2338 |
|
} |
2339 |
|
if(gl2ps->line_width_diff){ |
2340 |
|
gl2ps->lastlinewidth = prim->width; |
2341 |
|
gl2ps->streamlength += gl2psPrintPDFLineWidth(gl2ps->lastlinewidth); |
2342 |
|
} |
2343 |
|
if(gl2ps->line_rgb_diff){ |
2344 |
|
gl2ps->streamlength += gl2psPrintPDFStrokeColor(prim->verts[0].rgba); |
2345 |
|
} |
2346 |
|
if(prim->dash){ |
2347 |
|
gl2ps->streamlength += fprintf(gl2ps->stream, "[%d] 0 d\n", prim->dash); |
2348 |
|
} |
2349 |
|
gl2ps->streamlength += fprintf(gl2ps->stream, "%f %f m %f %f l \n", |
2350 |
|
prim->verts[0].xyz[0], prim->verts[0].xyz[1], |
2351 |
|
prim->verts[1].xyz[0], prim->verts[1].xyz[1]); |
2352 |
|
gl2ps->last_line_finished = 0; |
2353 |
|
|
2354 |
|
if(prim->dash){ |
2355 |
|
gl2ps->streamlength += fprintf(gl2ps->stream, "S\n[] 0 d\n"); |
2356 |
|
gl2ps->last_line_finished = 1; |
2357 |
|
} |
2358 |
|
break; |
2359 |
|
case GL2PS_TRIANGLE : |
2360 |
|
t[0] = prim->verts[0]; |
2361 |
|
t[1] = prim->verts[1]; |
2362 |
|
t[2] = prim->verts[2]; |
2363 |
|
|
2364 |
|
gl2psListAdd(gl2ps->tlist, t); |
2365 |
|
++gl2ps->consec_inner_cnt; |
2366 |
|
gl2ps->last_triangle_finished = 0; |
2367 |
|
break; |
2368 |
|
case GL2PS_QUADRANGLE : |
2369 |
|
gl2psMsg(GL2PS_WARNING, "There should not be any quad left to print"); |
2370 |
|
break; |
2371 |
|
default : |
2372 |
|
gl2psMsg(GL2PS_ERROR, "Unknown type of primitive to print"); |
2373 |
|
break; |
2374 |
|
} |
2375 |
|
gl2ps->lasttype = prim->type; |
2376 |
|
} |
2377 |
|
|
2378 |
|
/* close stream and ... */ |
2379 |
|
|
2380 |
|
int gl2psClosePDFDataStream(){ |
2381 |
|
int offs = 0; |
2382 |
|
|
2383 |
|
offs += gl2psFlushPDFTriangles(); |
2384 |
|
offs += gl2psFlushPDFLines(); |
2385 |
|
offs += fprintf(gl2ps->stream, |
2386 |
|
"endstream\n" |
2387 |
|
"endobj\n"); |
2388 |
|
return offs; |
2389 |
|
} |
2390 |
|
|
2391 |
|
/* ... write the now known length object */ |
2392 |
|
|
2393 |
|
int gl2psPrintPDFDataStreamLength(int val){ |
2394 |
|
return fprintf(gl2ps->stream, |
2395 |
|
"5 0 obj\n" |
2396 |
|
"%d\n" |
2397 |
|
"endobj\n", val); |
2398 |
|
} |
2399 |
|
|
2400 |
|
/* Create named shader objects */ |
2401 |
|
|
2402 |
|
int gl2psPrintPDFShaderResources(int firstObject, int size){ |
2403 |
|
int offs = 0; |
2404 |
|
int i; |
2405 |
|
|
2406 |
|
offs += fprintf(gl2ps->stream, |
2407 |
|
"/Shading\n" |
2408 |
|
"<<\n"); |
2409 |
|
for(i = 0; i < size; ++i){ |
2410 |
|
offs += fprintf(gl2ps->stream, "/Sh%d %d 0 R\n", i, firstObject+i); |
2411 |
|
} |
2412 |
|
offs += fprintf(gl2ps->stream, ">>\n"); |
2413 |
|
return offs; |
2414 |
|
} |
2415 |
|
|
2416 |
|
/* Create named pixmap objects */ |
2417 |
|
|
2418 |
|
int gl2psPrintPDFPixmapResources(int firstObject, int size){ |
2419 |
|
int offs = 0; |
2420 |
|
int i; |
2421 |
|
|
2422 |
|
offs += fprintf(gl2ps->stream, |
2423 |
|
"/XObject\n" |
2424 |
|
"<<\n"); |
2425 |
|
for(i = 0; i < size; ++i){ |
2426 |
|
offs += fprintf(gl2ps->stream, "/Im%d %d 0 R\n", i, firstObject + i); |
2427 |
|
} |
2428 |
|
offs += fprintf(gl2ps->stream, ">>\n"); |
2429 |
|
return offs; |
2430 |
|
} |
2431 |
|
|
2432 |
|
/* Create named font objects */ |
2433 |
|
|
2434 |
|
int gl2psPrintPDFTextResources(int firstObject, int size){ |
2435 |
|
int offs = 0; |
2436 |
|
int i; |
2437 |
|
|
2438 |
|
offs += fprintf(gl2ps->stream, |
2439 |
|
"/Font\n" |
2440 |
|
"<<\n"); |
2441 |
|
for(i = 0; i < size; ++i){ |
2442 |
|
offs += fprintf(gl2ps->stream, "/F%d %d 0 R\n", i, firstObject + i); |
2443 |
|
} |
2444 |
|
offs += fprintf(gl2ps->stream, ">>\n"); |
2445 |
|
return offs; |
2446 |
|
} |
2447 |
|
|
2448 |
|
/* Put the info created before in PDF objects */ |
2449 |
|
|
2450 |
|
int gl2psPrintPDFSinglePage(){ |
2451 |
|
int offs; |
2452 |
|
|
2453 |
|
offs = fprintf(gl2ps->stream, |
2454 |
|
"6 0 obj\n" |
2455 |
|
"<<\n" |
2456 |
|
"/Type /Page\n" |
2457 |
|
"/Parent 3 0 R\n" |
2458 |
|
"/MediaBox [%d %d %d %d]\n", |
2459 |
|
(int)gl2ps->viewport[0], (int)gl2ps->viewport[1], |
2460 |
|
(int)gl2ps->viewport[2], (int)gl2ps->viewport[3]); |
2461 |
|
|
2462 |
|
if(gl2ps->options & GL2PS_LANDSCAPE) |
2463 |
|
offs += fprintf(gl2ps->stream, "/Rotate -90\n"); |
2464 |
|
|
2465 |
|
offs += fprintf(gl2ps->stream, |
2466 |
|
"/Contents 4 0 R\n" |
2467 |
|
"/Resources\n" |
2468 |
|
"<<\n" |
2469 |
|
"/ProcSet [/PDF /Text /ImageB /ImageC] %%/ImageI\n" |
2470 |
|
"/Length 5 0 R\n" |
2471 |
|
"/ExtGState\n" |
2472 |
|
"<<\n" |
2473 |
|
"/GS1 7 0 R\n" |
2474 |
|
">>\n"); |
2475 |
|
|
2476 |
|
offs += gl2psPrintPDFShaderResources(GL2PS_FIXED_XREF_ENTRIES + 1, |
2477 |
|
gl2psListNbr(gl2ps->tidxlist)); |
2478 |
|
offs += gl2psPrintPDFPixmapResources(GL2PS_FIXED_XREF_ENTRIES + 1 |
2479 |
|
+ gl2psListNbr(gl2ps->tidxlist), |
2480 |
|
gl2psListNbr(gl2ps->ilist)); |
2481 |
|
offs += gl2psPrintPDFTextResources(GL2PS_FIXED_XREF_ENTRIES + 1 |
2482 |
|
+ gl2psListNbr(gl2ps->tidxlist) |
2483 |
|
+ gl2psListNbr(gl2ps->ilist), |
2484 |
|
gl2psListNbr(gl2ps->slist)); |
2485 |
|
offs += fprintf(gl2ps->stream, |
2486 |
|
">>\n" |
2487 |
|
">>\n" |
2488 |
|
"endobj\n"); |
2489 |
|
return offs; |
2490 |
|
} |
2491 |
|
|
2492 |
|
/* Extended graphics state for shading */ |
2493 |
|
|
2494 |
|
int gl2psPrintPDFExtGState(){ |
2495 |
|
return fprintf(gl2ps->stream, |
2496 |
|
"7 0 obj\n" |
2497 |
|
"<<\n" |
2498 |
|
"/Type /ExtGState\n" |
2499 |
|
"/SA false\n" |
2500 |
|
"/SM 0.02\n" |
2501 |
|
"/OP false\n" |
2502 |
|
"/op false\n" |
2503 |
|
"/OPM 0\n" |
2504 |
|
"/BG2 /Default\n" |
2505 |
|
"/UCR2 /Default\n" |
2506 |
|
"/TR2 /Default\n" |
2507 |
|
">>\n" |
2508 |
|
"endobj\n"); |
2509 |
|
} |
2510 |
|
|
2511 |
|
/* Put a triangles uncompressed raw data in shader stream */ |
2512 |
|
|
2513 |
|
int gl2psPrintPDFShaderStreamData(GL2PStriangle triangle){ |
2514 |
|
int offs = 0; |
2515 |
|
int i; |
2516 |
|
unsigned long imap; |
2517 |
|
GLfloat diff, dx, dy; |
2518 |
|
char edgeflag = 0; |
2519 |
|
double dmax = ~1UL; |
2520 |
|
|
2521 |
|
dx = gl2ps->viewport[2]-gl2ps->viewport[0]; |
2522 |
|
dy = gl2ps->viewport[3]-gl2ps->viewport[1]; |
2523 |
|
|
2524 |
|
for(i = 0; i < 3; ++i){ |
2525 |
|
offs += fwrite (&edgeflag, sizeof(char), 1, gl2ps->stream); |
2526 |
|
|
2527 |
|
/* In unfiltered mode the Shader stream in PDF requires to be in a |
2528 |
|
'big-endian' order */ |
2529 |
|
|
2530 |
|
if(fabs(dx*dy) < FLT_MIN){ |
2531 |
|
offs += gl2psWriteBigEndian(0, 4, gl2ps->stream); |
2532 |
|
offs += gl2psWriteBigEndian(0, 4, gl2ps->stream); |
2533 |
|
} |
2534 |
|
else{ |
2535 |
|
diff = (triangle[i].xyz[0] - gl2ps->viewport[0]) / dx; |
2536 |
|
if(diff > 1) |
2537 |
|
diff = 1; |
2538 |
|
else if(diff < 0) |
2539 |
|
diff = 0; |
2540 |
|
imap = (unsigned long)(diff * dmax); |
2541 |
|
offs += gl2psWriteBigEndian(imap, 4, gl2ps->stream); |
2542 |
|
|
2543 |
|
diff = (triangle[i].xyz[1] - gl2ps->viewport[1]) / dy; |
2544 |
|
if(diff > 1) |
2545 |
|
diff = 1; |
2546 |
|
else if(diff < 0) |
2547 |
|
diff = 0; |
2548 |
|
imap = (unsigned long)(diff * dmax); |
2549 |
|
offs += gl2psWriteBigEndian(imap, 4, gl2ps->stream); |
2550 |
|
} |
2551 |
|
|
2552 |
|
imap = (unsigned long)(triangle[i].rgba[0] * dmax); |
2553 |
|
offs += gl2psWriteBigEndian(imap, 1, gl2ps->stream); |
2554 |
|
|
2555 |
|
imap = (unsigned long)(triangle[i].rgba[1] * dmax); |
2556 |
|
offs += gl2psWriteBigEndian(imap, 1, gl2ps->stream); |
2557 |
|
|
2558 |
|
imap = (unsigned long)(triangle[i].rgba[2] * dmax); |
2559 |
|
offs += gl2psWriteBigEndian(imap, 1, gl2ps->stream); |
2560 |
|
} |
2561 |
|
return offs; |
2562 |
|
} |
2563 |
|
|
2564 |
|
/* Writes shaded triangle */ |
2565 |
|
|
2566 |
|
int gl2psPrintPDFShader(int obj, GL2PSlist* triangles, int idx, int cnt ){ |
2567 |
|
int offs = 0; |
2568 |
|
int vertexbytes = 1+4+4+1+1+1; |
2569 |
|
int i; |
2570 |
|
|
2571 |
|
offs += fprintf(gl2ps->stream, |
2572 |
|
"%d 0 obj\n" |
2573 |
|
"<< " |
2574 |
|
"/ShadingType 4 " |
2575 |
|
"/ColorSpace /DeviceRGB " |
2576 |
|
"/BitsPerCoordinate 32 " |
2577 |
|
"/BitsPerComponent 8 " |
2578 |
|
"/BitsPerFlag 8 " |
2579 |
|
"/Decode [%d %d %d %d 0 1 0 1 0 1] ", |
2580 |
|
obj, |
2581 |
|
(int)gl2ps->viewport[0], (int)gl2ps->viewport[2], |
2582 |
|
(int)gl2ps->viewport[1], (int)gl2ps->viewport[3]); |
2583 |
|
|
2584 |
|
offs += gl2psPrintPDFCompressorType(); |
2585 |
|
|
2586 |
|
offs += fprintf(gl2ps->stream, |
2587 |
|
"/Length %d " |
2588 |
|
">>\n" |
2589 |
|
"stream\n", |
2590 |
|
vertexbytes * 3 * cnt); |
2591 |
|
for(i = 0; i < cnt; ++i) |
2592 |
|
offs += gl2psPrintPDFShaderStreamData((GL2PSvertex*)gl2psListPointer(triangles, idx+i)); |
2593 |
|
|
2594 |
|
offs += fprintf(gl2ps->stream, |
2595 |
|
"\nendstream\n" |
2596 |
|
"endobj\n"); |
2597 |
|
return offs; |
2598 |
|
} |
2599 |
|
|
2600 |
|
/* Writes all triangles and returns field of offsets for the PDF cross |
2601 |
|
reference table */ |
2602 |
|
|
2603 |
|
int* gl2psPrintPDFShaderObjects(int firstObjnumber, int firstOffs){ |
2604 |
|
int size; |
2605 |
|
int* offs; |
2606 |
|
int i; |
2607 |
|
int idx = 0; |
2608 |
|
int tmp; |
2609 |
|
|
2610 |
|
size = gl2psListNbr(gl2ps->tidxlist); |
2611 |
|
offs = (int*)gl2psMalloc(sizeof(int) * (size+1)); |
2612 |
|
|
2613 |
|
offs[0] = firstOffs; |
2614 |
|
|
2615 |
|
for(i = 0; i < size; ++i){ |
2616 |
|
gl2psListRead(gl2ps->tidxlist, i, &tmp); |
2617 |
|
firstOffs += gl2psPrintPDFShader(i+firstObjnumber, gl2ps->tlist, idx, tmp); |
2618 |
|
offs[i+1] = firstOffs; |
2619 |
|
idx += tmp; |
2620 |
|
} |
2621 |
|
return offs; |
2622 |
|
} |
2623 |
|
|
2624 |
|
/* Similar groups of functions for pixmaps and text */ |
2625 |
|
|
2626 |
|
int gl2psPrintPDFPixmapStreamData(GL2PSimage* im){ |
2627 |
|
int x, y; |
2628 |
|
GLfloat r, g, b; |
2629 |
|
|
2630 |
|
for(y = 0; y < im->height; ++y) |
2631 |
|
for(x = 0; x < im->width; ++x){ |
2632 |
|
gl2psGetRGB(im->pixels, im->width, im->height, x, y, &r, &g, &b); |
2633 |
|
fputc((int)(r*255),gl2ps->stream); |
2634 |
|
fputc((int)(g*255),gl2ps->stream); |
2635 |
|
fputc((int)(b*255),gl2ps->stream); |
2636 |
|
} |
2637 |
|
return 3 * im->width * im->height; |
2638 |
|
} |
2639 |
|
|
2640 |
|
int gl2psPrintPDFPixmap(int obj, GL2PSimage* im){ |
2641 |
|
int offs = 0; |
2642 |
|
|
2643 |
|
offs += fprintf(gl2ps->stream, |
2644 |
|
"%d 0 obj\n" |
2645 |
|
"<<\n" |
2646 |
|
"/Type /XObject\n" |
2647 |
|
"/Subtype /Image\n" |
2648 |
|
"/Width %d\n" |
2649 |
|
"/Height %d\n" |
2650 |
|
"/ColorSpace /DeviceRGB\n" |
2651 |
|
"/BitsPerComponent 8\n" |
2652 |
|
"/Length %d\n" |
2653 |
|
">>\n" |
2654 |
|
"stream\n", |
2655 |
|
obj, (int)im->width, (int)im->height, |
2656 |
|
(int)(im->width * im->height * 3)); |
2657 |
|
|
2658 |
|
offs += gl2psPrintPDFPixmapStreamData(im); |
2659 |
|
|
2660 |
|
offs += fprintf(gl2ps->stream, |
2661 |
|
"\nendstream\n" |
2662 |
|
"endobj\n"); |
2663 |
|
return offs; |
2664 |
|
} |
2665 |
|
|
2666 |
|
int* gl2psPrintPDFPixmapObjects(int firstObjnumber, int firstOffs){ |
2667 |
|
int size; |
2668 |
|
int* offs; |
2669 |
|
int i; |
2670 |
|
|
2671 |
|
size = gl2psListNbr(gl2ps->ilist); |
2672 |
|
offs = (int*)gl2psMalloc(sizeof(int) * (size+1)); |
2673 |
|
|
2674 |
|
offs[0] = firstOffs; |
2675 |
|
|
2676 |
|
for(i = 0; i < size; ++i){ |
2677 |
|
firstOffs += gl2psPrintPDFPixmap(i+firstObjnumber, |
2678 |
|
*(GL2PSimage**)gl2psListPointer(gl2ps->ilist, i)); |
2679 |
|
offs[i+1] = firstOffs; |
2680 |
|
} |
2681 |
|
return offs; |
2682 |
|
} |
2683 |
|
|
2684 |
|
int gl2psPrintPDFText(int obj, GL2PSstring* s, int fontnumber ){ |
2685 |
|
int offs = 0; |
2686 |
|
|
2687 |
|
offs += fprintf(gl2ps->stream, |
2688 |
|
"%d 0 obj\n" |
2689 |
|
"<<\n" |
2690 |
|
"/Type /Font\n" |
2691 |
|
"/Subtype /Type1\n" |
2692 |
|
"/Name /F%d\n" |
2693 |
|
"/BaseFont /%s\n" |
2694 |
|
"/Encoding /MacRomanEncoding\n" |
2695 |
|
">>\n" |
2696 |
|
"endobj\n", |
2697 |
|
obj, fontnumber, s->fontname); |
2698 |
|
return offs; |
2699 |
|
} |
2700 |
|
|
2701 |
|
int* gl2psPrintPDFTextObjects(int firstObjnumber, int firstOffs){ |
2702 |
|
int size; |
2703 |
|
int* offs; |
2704 |
|
int i; |
2705 |
|
|
2706 |
|
size = gl2psListNbr(gl2ps->slist); |
2707 |
|
offs = (int*)gl2psMalloc(sizeof(int) * (size+1)); |
2708 |
|
|
2709 |
|
offs[0] = firstOffs; |
2710 |
|
|
2711 |
|
for(i = 0; i < size; ++i){ |
2712 |
|
firstOffs += gl2psPrintPDFText(i+firstObjnumber, |
2713 |
|
*(GL2PSstring**)gl2psListPointer(gl2ps->slist, i),i); |
2714 |
|
offs[i+1] = firstOffs; |
2715 |
|
} |
2716 |
|
return offs; |
2717 |
|
} |
2718 |
|
|
2719 |
|
/* All variable data is written at this point and all required |
2720 |
|
functioninality has been gathered: Writes file footer with cross |
2721 |
|
reference table and trailer */ |
2722 |
|
|
2723 |
|
void gl2psPrintPDFFooter(){ |
2724 |
|
int offs; |
2725 |
|
int i; |
2726 |
|
int *shader_offs, *image_offs, *text_offs; |
2727 |
|
int shader_size, image_size, text_size, objnumber, lastoffset; |
2728 |
|
|
2729 |
|
offs = gl2ps->cref[4] + gl2ps->streamlength; |
2730 |
|
offs += gl2psClosePDFDataStream(); |
2731 |
|
gl2ps->cref[4] = offs; |
2732 |
|
|
2733 |
|
offs += gl2psPrintPDFDataStreamLength(gl2ps->streamlength); |
2734 |
|
gl2ps->cref[5] = offs; |
2735 |
|
gl2ps->streamlength = 0; |
2736 |
|
|
2737 |
|
offs += gl2psPrintPDFSinglePage(); |
2738 |
|
gl2ps->cref[6] = offs; |
2739 |
|
|
2740 |
|
offs += gl2psPrintPDFExtGState(); |
2741 |
|
|
2742 |
|
shader_size = gl2psListNbr(gl2ps->tidxlist); |
2743 |
|
image_size = gl2psListNbr(gl2ps->ilist); |
2744 |
|
text_size = gl2psListNbr(gl2ps->slist); |
2745 |
|
|
2746 |
|
shader_offs = gl2psPrintPDFShaderObjects(GL2PS_FIXED_XREF_ENTRIES + 1, offs); |
2747 |
|
image_offs = gl2psPrintPDFPixmapObjects(GL2PS_FIXED_XREF_ENTRIES + 1 + shader_size, |
2748 |
|
shader_offs[shader_size]); |
2749 |
|
text_offs = gl2psPrintPDFTextObjects(GL2PS_FIXED_XREF_ENTRIES + 1 + shader_size + image_size, |
2750 |
|
image_offs[image_size]); |
2751 |
|
|
2752 |
|
lastoffset = text_offs[text_size]; |
2753 |
|
objnumber = GL2PS_FIXED_XREF_ENTRIES + shader_size + image_size + text_size + 1; |
2754 |
|
|
2755 |
|
/* Start cross reference table. The file has to been opened in |
2756 |
|
binary mode to preserve the 20 digit string length! */ |
2757 |
|
fprintf(gl2ps->stream, |
2758 |
|
"xref\n" |
2759 |
|
"0 %d\n" |
2760 |
|
"%010d 65535 f \n", objnumber, 0); |
2761 |
|
|
2762 |
|
for(i = 0; i < GL2PS_FIXED_XREF_ENTRIES; ++i){ |
2763 |
|
fprintf(gl2ps->stream, "%010d 00000 n \n", gl2ps->cref[i]); |
2764 |
|
} |
2765 |
|
for(i = 0; i < shader_size; ++i){ |
2766 |
|
fprintf(gl2ps->stream, "%010d 00000 n \n", shader_offs[i]); |
2767 |
|
} |
2768 |
|
for(i = 0; i < image_size; ++i){ |
2769 |
|
fprintf(gl2ps->stream, "%010d 00000 n \n", image_offs[i]); |
2770 |
|
} |
2771 |
|
for(i = 0; i < text_size; ++i){ |
2772 |
|
fprintf(gl2ps->stream, "%010d 00000 n \n", text_offs[i]); |
2773 |
|
} |
2774 |
|
|
2775 |
|
fprintf(gl2ps->stream, |
2776 |
|
"trailer\n" |
2777 |
|
"<<\n" |
2778 |
|
"/Size %d\n" |
2779 |
|
"/Info 1 0 R\n" |
2780 |
|
"/Root 2 0 R\n" |
2781 |
|
">>\n" |
2782 |
|
"startxref\n%d\n" |
2783 |
|
"%%%%EOF\n", |
2784 |
|
objnumber, lastoffset); |
2785 |
|
|
2786 |
|
/* Free auxiliary lists and arrays */ |
2787 |
|
gl2psFree(shader_offs); |
2788 |
|
gl2psFree(image_offs); |
2789 |
|
gl2psFree(text_offs); |
2790 |
|
gl2psListDelete(gl2ps->tlist); |
2791 |
|
gl2psListDelete(gl2ps->tidxlist); |
2792 |
|
for(i = 0; i < gl2psListNbr(gl2ps->ilist); ++i) |
2793 |
|
gl2psFreePixmap(*(GL2PSimage**)gl2psListPointer(gl2ps->ilist, i)); |
2794 |
|
gl2psListDelete(gl2ps->ilist); |
2795 |
|
for(i = 0; i < gl2psListNbr(gl2ps->slist); ++i) |
2796 |
|
gl2psFreeText(*(GL2PSstring**)gl2psListPointer(gl2ps->slist, i)); |
2797 |
|
gl2psListDelete(gl2ps->slist); |
2798 |
|
} |
2799 |
|
|
2800 |
|
/* PDF begin viewport */ |
2801 |
|
|
2802 |
|
void gl2psPrintPDFBeginViewport(GLint viewport[4]){ |
2803 |
|
int offs; |
2804 |
|
GLint index; |
2805 |
|
GLfloat rgba[4]; |
2806 |
|
int x = viewport[0], y = viewport[1], w = viewport[2], h = viewport[3]; |
2807 |
|
|
2808 |
|
offs = 0; |
2809 |
|
|
2810 |
|
glRenderMode(GL_FEEDBACK); |
2811 |
|
|
2812 |
|
offs += fprintf(gl2ps->stream, "q\n"); |
2813 |
|
|
2814 |
|
if(gl2ps->options & GL2PS_DRAW_BACKGROUND){ |
2815 |
|
if(gl2ps->colormode == GL_RGBA || gl2ps->colorsize == 0){ |
2816 |
|
glGetFloatv(GL_COLOR_CLEAR_VALUE, rgba); |
2817 |
|
} |
2818 |
|
else{ |
2819 |
|
glGetIntegerv(GL_INDEX_CLEAR_VALUE, &index); |
2820 |
|
rgba[0] = gl2ps->colormap[index][0]; |
2821 |
|
rgba[1] = gl2ps->colormap[index][1]; |
2822 |
|
rgba[2] = gl2ps->colormap[index][2]; |
2823 |
|
rgba[3] = 0.; |
2824 |
|
} |
2825 |
|
offs += fprintf(gl2ps->stream, |
2826 |
|
"%f %f %f rg\n" |
2827 |
|
"%d %d %d %d re\n" |
2828 |
|
"W\n" |
2829 |
|
"f\n", |
2830 |
|
rgba[0], rgba[1], rgba[2], x, y, w, h); |
2831 |
|
} |
2832 |
|
else{ |
2833 |
|
offs += fprintf(gl2ps->stream, |
2834 |
|
"%d %d %d %d re\n" |
2835 |
|
"W\n" |
2836 |
|
"n\n", |
2837 |
|
x, y, w, h); |
2838 |
|
} |
2839 |
|
|
2840 |
|
gl2ps->streamlength += offs; |
2841 |
|
} |
2842 |
|
|
2843 |
|
GLint gl2psPrintPDFEndViewport(){ |
2844 |
|
GLint res; |
2845 |
|
GLint gl2psPrintPrimitives(void); |
2846 |
|
|
2847 |
|
res = gl2psPrintPrimitives(); |
2848 |
|
res += gl2psFlushPDFTriangles(); |
2849 |
|
res += gl2psFlushPDFLines(); |
2850 |
|
|
2851 |
|
gl2ps->streamlength += fprintf(gl2ps->stream, "Q\n"); |
2852 |
|
|
2853 |
|
return res; |
2854 |
|
} |
2855 |
|
|
2856 |
|
/********************************************************************* |
2857 |
|
* |
2858 |
|
* General primitive printing routine |
2859 |
|
* |
2860 |
|
*********************************************************************/ |
2861 |
|
|
2862 |
GLint gl2psPrintPrimitives(void){ |
GLint gl2psPrintPrimitives(void){ |
2863 |
GL2PSbsptree *root; |
GL2PSbsptree *root; |
2876 |
return GL2PS_NO_FEEDBACK; /* Empty feedback buffer */ |
return GL2PS_NO_FEEDBACK; /* Empty feedback buffer */ |
2877 |
} |
} |
2878 |
|
|
2879 |
if(gl2ps->format == GL2PS_PS || gl2ps->format == GL2PS_EPS){ |
if(gl2ps->format == GL2PS_PS || |
2880 |
|
gl2ps->format == GL2PS_EPS || |
2881 |
|
gl2ps->format == GL2PS_PDF){ |
2882 |
gl2psParseFeedbackBuffer(used); |
gl2psParseFeedbackBuffer(used); |
2883 |
} |
} |
2884 |
|
|
2894 |
case GL2PS_EPS : |
case GL2PS_EPS : |
2895 |
pprim = gl2psPrintPostScriptPrimitive; |
pprim = gl2psPrintPostScriptPrimitive; |
2896 |
break; |
break; |
2897 |
|
case GL2PS_PDF : |
2898 |
|
pprim = gl2psPrintPDFPrimitive; |
2899 |
|
break; |
2900 |
} |
} |
2901 |
|
|
2902 |
switch(gl2ps->sort){ |
switch(gl2ps->sort){ |
2943 |
return GL2PS_SUCCESS; |
return GL2PS_SUCCESS; |
2944 |
} |
} |
2945 |
|
|
2946 |
/* The public routines */ |
/********************************************************************* |
2947 |
|
* |
2948 |
|
* Public routines |
2949 |
|
* |
2950 |
|
*********************************************************************/ |
2951 |
|
|
2952 |
GL2PSDLL_API GLint gl2psBeginPage(const char *title, const char *producer, |
GL2PSDLL_API GLint gl2psBeginPage(const char *title, const char *producer, |
2953 |
GLint viewport[4], GLint format, GLint sort, |
GLint viewport[4], GLint format, GLint sort, |
3023 |
rewind(gl2ps->stream); |
rewind(gl2ps->stream); |
3024 |
} |
} |
3025 |
|
|
3026 |
|
/* only used for PDF output... */ |
3027 |
|
gl2ps->lasttype = -1; |
3028 |
|
gl2ps->consec_cnt = 0; |
3029 |
|
gl2ps->consec_inner_cnt = 1; |
3030 |
|
gl2ps->line_width_diff = 1; |
3031 |
|
gl2ps->line_rgb_diff = 1; |
3032 |
|
gl2ps->last_line_finished = 0; |
3033 |
|
gl2ps->last_triangle_finished = 0; |
3034 |
|
|
3035 |
switch(gl2ps->format){ |
switch(gl2ps->format){ |
3036 |
case GL2PS_TEX : |
case GL2PS_TEX : |
3037 |
gl2psPrintTeXHeader(); |
gl2psPrintTeXHeader(); |
3040 |
case GL2PS_EPS : |
case GL2PS_EPS : |
3041 |
gl2psPrintPostScriptHeader(); |
gl2psPrintPostScriptHeader(); |
3042 |
break; |
break; |
3043 |
|
case GL2PS_PDF : |
3044 |
|
gl2psPrintPDFHeader(); |
3045 |
|
break; |
3046 |
default : |
default : |
3047 |
gl2psMsg(GL2PS_ERROR, "Unknown output format: %d", gl2ps->format); |
gl2psMsg(GL2PS_ERROR, "Unknown output format: %d", gl2ps->format); |
3048 |
gl2psFree(gl2ps); |
gl2psFree(gl2ps); |
3075 |
case GL2PS_EPS : |
case GL2PS_EPS : |
3076 |
gl2psPrintPostScriptFooter(); |
gl2psPrintPostScriptFooter(); |
3077 |
break; |
break; |
3078 |
|
case GL2PS_PDF : |
3079 |
|
gl2psPrintPDFFooter(); |
3080 |
|
break; |
3081 |
} |
} |
3082 |
|
|
3083 |
fflush(gl2ps->stream); |
fflush(gl2ps->stream); |
3095 |
if(!gl2ps) return GL2PS_UNINITIALIZED; |
if(!gl2ps) return GL2PS_UNINITIALIZED; |
3096 |
|
|
3097 |
switch(gl2ps->format){ |
switch(gl2ps->format){ |
3098 |
|
case GL2PS_PS : |
3099 |
case GL2PS_EPS : |
case GL2PS_EPS : |
3100 |
gl2psPrintPostScriptBeginViewport(viewport); |
gl2psPrintPostScriptBeginViewport(viewport); |
3101 |
break; |
break; |
3102 |
|
case GL2PS_PDF : |
3103 |
|
gl2psPrintPDFBeginViewport(viewport); |
3104 |
|
break; |
3105 |
default : |
default : |
3106 |
/* FIXME: handle other formats */ |
/* FIXME: handle other formats */ |
3107 |
break; |
break; |
3116 |
if(!gl2ps) return GL2PS_UNINITIALIZED; |
if(!gl2ps) return GL2PS_UNINITIALIZED; |
3117 |
|
|
3118 |
switch(gl2ps->format){ |
switch(gl2ps->format){ |
3119 |
|
case GL2PS_PS : |
3120 |
case GL2PS_EPS : |
case GL2PS_EPS : |
3121 |
res = gl2psPrintPostScriptEndViewport(); |
res = gl2psPrintPostScriptEndViewport(); |
3122 |
break; |
break; |
3123 |
|
case GL2PS_PDF : |
3124 |
|
res = gl2psPrintPDFEndViewport(); |
3125 |
|
break; |
3126 |
default : |
default : |
3127 |
/* FIXME: handle other formats */ |
/* FIXME: handle other formats */ |
3128 |
res = GL2PS_SUCCESS; |
res = GL2PS_SUCCESS; |
3132 |
return res; |
return res; |
3133 |
} |
} |
3134 |
|
|
3135 |
GL2PSDLL_API GLint gl2psText(const char *str, const char *fontname, GLshort fontsize){ |
GL2PSDLL_API GLint gl2psTextOpt(const char *str, const char *fontname, GLshort fontsize, |
3136 |
|
GLint alignment, GL2PSrgba rgba){ |
3137 |
GLfloat pos[4]; |
GLfloat pos[4]; |
3138 |
GL2PSprimitive *prim; |
GL2PSprimitive *prim; |
3139 |
GLboolean valid; |
GLboolean valid; |
3159 |
prim->culled = 0; |
prim->culled = 0; |
3160 |
prim->dash = 0; |
prim->dash = 0; |
3161 |
prim->width = 1; |
prim->width = 1; |
3162 |
glGetFloatv(GL_CURRENT_RASTER_COLOR, prim->verts[0].rgba); |
if(rgba){ |
3163 |
|
prim->verts[0].rgba[0] = rgba[0]; |
3164 |
|
prim->verts[0].rgba[1] = rgba[1]; |
3165 |
|
prim->verts[0].rgba[2] = rgba[2]; |
3166 |
|
prim->verts[0].rgba[3] = rgba[3]; |
3167 |
|
} |
3168 |
|
else{ |
3169 |
|
glGetFloatv(GL_CURRENT_RASTER_COLOR, prim->verts[0].rgba); |
3170 |
|
} |
3171 |
prim->text = (GL2PSstring*)gl2psMalloc(sizeof(GL2PSstring)); |
prim->text = (GL2PSstring*)gl2psMalloc(sizeof(GL2PSstring)); |
3172 |
prim->text->str = (char*)gl2psMalloc((strlen(str)+1)*sizeof(char)); |
prim->text->str = (char*)gl2psMalloc((strlen(str)+1)*sizeof(char)); |
3173 |
strcpy(prim->text->str, str); |
strcpy(prim->text->str, str); |
3174 |
prim->text->fontname = (char*)gl2psMalloc((strlen(fontname)+1)*sizeof(char)); |
prim->text->fontname = (char*)gl2psMalloc((strlen(fontname)+1)*sizeof(char)); |
3175 |
strcpy(prim->text->fontname, fontname); |
strcpy(prim->text->fontname, fontname); |
3176 |
prim->text->fontsize = fontsize; |
prim->text->fontsize = fontsize; |
3177 |
|
prim->text->alignment = alignment; |
3178 |
|
|
3179 |
gl2psListAdd(gl2ps->primitives, &prim); |
gl2psListAdd(gl2ps->primitives, &prim); |
3180 |
|
|
3181 |
return GL2PS_SUCCESS; |
return GL2PS_SUCCESS; |
3182 |
} |
} |
3183 |
|
|
3184 |
|
GL2PSDLL_API GLint gl2psText(const char *str, const char *fontname, GLshort fontsize){ |
3185 |
|
return gl2psTextOpt(str, fontname, fontsize, GL2PS_TEXT_BL, NULL); |
3186 |
|
} |
3187 |
|
|
3188 |
GL2PSDLL_API GLint gl2psDrawPixels(GLsizei width, GLsizei height, |
GL2PSDLL_API GLint gl2psDrawPixels(GLsizei width, GLsizei height, |
3189 |
GLint xorig, GLint yorig, |
GLint xorig, GLint yorig, |
3190 |
GLenum format, GLenum type, |
GLenum format, GLenum type, |