1 //
2 // "$Id: file.cc,v 1.1.1.1 2005/05/31 06:29:21 vierinen Exp $"
3 //
4 // GLPfile class function for the GLP library, an OpenGL printing toolkit.
5 //
6 // The GLP library is distributed under the terms of the GNU Library
7 // General Public License which is described in the file "COPYING.LIB".
8 // If you use this library in your program, please include a line reading
9 // "OpenGL Printing Toolkit by Michael Sweet" in your version or copyright
10 // output.
11 //
12 // Contents:
13 //
14 // GLPfile, ~GLPfile, EndPage
15 //
16 // Revision History:
17 //
18 // $Log: file.cc,v $
19 // Revision 1.1.1.1 2005/05/31 06:29:21 vierinen
20 // ads
21 //
22 // Revision 1.2 2004/11/29 08:26:22 jpr
23 // *** empty log message ***
24 //
25 // Revision 1.1 2003/02/06 09:37:53 jpr
26 // *** empty log message ***
27 //
28 // 2003/02/01 Juha Ruokolainen / CSC - IT Center for Science Ltd., Finland
29 // Added code to handle primitives stored in a binary tree instead of
30 // a list. Separate routine for outputting primitives. Some changes
31 // to generated postscript code:
32 // - better splitting of shaded triangles
33 // - if shfill operator is known by the postscript interpreter
34 // (level3 postscript) use that, instead of splitting.
35 //
36 //
37 // Revision 1.2 1996/07/13 12:52:02 mike
38 // Fixed shaded triangle procedure in PostScript prolog (ST).
39 // Added auto-rotation for GLP_FIT_TO_PAGE option.
40 //
41 // Revision 1.1 1996/06/27 03:06:36 mike
42 // Initial revision
43 //
44
45 //
46 // Include necessary headers.
47 //
48
49
50 #include <../../config.h>
51
52 #include <stdio.h>
53 #include <stdlib.h>
54
55 #if defined(HAVE_STRINGS_H)
56 #include <strings.h>
57 #endif
58
59 #if defined(HAVE_STRING_H)
60 #include <string.h>
61 #endif
62
63 #include "glpfile.h"
64
65
66 double LLx, LLy, URx, URy;
67 extern GLPtext *texthead;
68
69 //#define DEBUG
70
71 //
72 // GLPfile constructor; this really doesn't do much, but instead you are
73 // expected to steal this code as the basis of your own GLP subclass...
74 //
75
GLPfile(char * print_name,int print_options,int print_size)76 GLPfile :: GLPfile(char *print_name, // I - Name of file/printer
77 int print_options, // I - Output options
78 int print_size) // I - Size of feedback buffer
79 {
80 // Initialize private class data and allocate a feedback buffer...
81
82 options = print_options;
83 bboxes = NULL;
84 tree = NULL;
85 feedsize = print_size > 0 ? print_size : 1024 * 1024 * 100;
86 feedback = new GLfloat[feedsize];
87 colorsize = 0;
88 colormap = NULL;
89 page_count = 0;
90 texthead = NULL;
91
92 #ifdef DEBUG
93 cout << "feedsize = " << feedsize << ", feedback = " << (int)feedback << "\n" << flush;
94 #endif /* DEBUG */
95
96 // Next open the indicated file...
97
98 outfile = new std::fstream(print_name, std::ios::out);
99 if (outfile == NULL)
100 return;
101
102 // Output the PostScript file header and prolog...
103
104 *outfile << "%!PS-Adobe-3.0\n";
105 *outfile << "%%LanguageLevel: 1\n";
106 *outfile << "%%Creator: GLP 0.1 by Michael Sweet (mike@easysw.com)\n";
107 *outfile << "%%Pages: (atend)\n";
108 *outfile << "%%BoundingBox: (atend)\n";
109 *outfile << "%%EndComments\n";
110
111 *outfile << "%%BeginProlog\n";
112
113 if (options & GLP_GREYSCALE)
114 {
115 *outfile << "% Greyscale color command - r g b C\n";
116 *outfile << "/C { 0.0820 mul exch 0.6094 mul add exch 0.3086 mul add neg 1.0 add setgray } bind def\n";
117 }
118 else
119 {
120 *outfile << "% RGB color command - r g b C\n";
121 *outfile << "/C { setrgbcolor } bind def\n";
122 };
123 *outfile << "\n";
124
125 *outfile << "% Point primitive - x y r g b P\n";
126 *outfile << "/P { C newpath 0.5 0.0 360.0 arc closepath fill } bind def\n";
127 *outfile << "\n";
128
129 *outfile << "% Flat-shaded line - x2 y2 x1 y1 r g b L\n";
130 *outfile << "/L { C moveto lineto stroke } bind def\n";
131 *outfile << "\n";
132
133 *outfile << "% Smooth-shaded line - x2 y2 r2 g2 b2 x1 y1 r1 g1 b1 SL\n";
134 *outfile << "/SL {\n";
135 *outfile << " /b1 exch def\n";
136 *outfile << " /g1 exch def\n";
137 *outfile << " /r1 exch def\n";
138 *outfile << " /y1 exch def\n";
139 *outfile << " /x1 exch def\n";
140 *outfile << " /b2 exch def\n";
141 *outfile << " /g2 exch def\n";
142 *outfile << " /r2 exch def\n";
143 *outfile << " /y2 exch def\n";
144 *outfile << " /x2 exch def\n";
145 *outfile << "\n";
146 *outfile << " b2 b1 sub abs 0.01 gt\n";
147 *outfile << " g2 g1 sub abs 0.005 gt\n";
148 *outfile << " r2 r1 sub abs 0.008 gt\n";
149 *outfile << " or or {\n";
150 *outfile << " /bm b1 b2 add 0.5 mul def\n";
151 *outfile << " /gm g1 g2 add 0.5 mul def\n";
152 *outfile << " /rm r1 r2 add 0.5 mul def\n";
153 *outfile << " /ym y1 y2 add 0.5 mul def\n";
154 *outfile << " /xm x1 x2 add 0.5 mul def\n";
155 *outfile << "\n";
156 *outfile << " save x1 y1 r1 g1 b1 xm ym rm gm bm SL restore\n";
157 *outfile << " save xm ym rm gm bm x2 y2 r2 g2 b2 SL restore\n";
158 *outfile << " } {\n";
159 *outfile << " x1 y1 x2 y2 r1 g1 b1 L\n";
160 *outfile << " } ifelse\n";
161 *outfile << "} bind def\n";
162 *outfile << "\n";
163
164 *outfile << "% Flat-shaded triangle - x3 y3 x2 y2 x1 y1 r g b T\n";
165 *outfile << "/T { C newpath moveto lineto lineto closepath fill } bind def\n";
166 *outfile << "\n";
167
168 *outfile << "% Smooth-shaded triangle - x3 y3 r3 g3 b3 x2 y2 r2 g2 b2 x1 y1 r1 g1 b1 ST\n";
169 *outfile << "/ST {\n";
170 *outfile << " /b1 exch def\n";
171 *outfile << " /g1 exch def\n";
172 *outfile << " /r1 exch def\n";
173 *outfile << " /y1 exch def\n";
174 *outfile << " /x1 exch def\n";
175 *outfile << " /b2 exch def\n";
176 *outfile << " /g2 exch def\n";
177 *outfile << " /r2 exch def\n";
178 *outfile << " /y2 exch def\n";
179 *outfile << " /x2 exch def\n";
180 *outfile << " /b3 exch def\n";
181 *outfile << " /g3 exch def\n";
182 *outfile << " /r3 exch def\n";
183 *outfile << " /y3 exch def\n";
184 *outfile << " /x3 exch def\n";
185 *outfile << "\n";
186 *outfile << "systemdict /shfill known {\n";
187 *outfile << " newpath \n";
188 *outfile << "<<\n";
189 *outfile << " /ShadingType 4\n";
190 *outfile << " /ColorSpace [/DeviceRGB]\n";
191 *outfile << " /DataSource [0 x1 y1 r1 g2 b1 0 x2 y2 r2 g2 b2 0 x3 y3 r3 g3 b3]\n";
192 *outfile << ">> shfill\n } {\n";
193 *outfile << " b2 b1 sub abs 0.05 gt\n";
194 *outfile << " g2 g1 sub abs 0.017 gt\n";
195 *outfile << " r2 r1 sub abs 0.032 gt\n";
196 *outfile << " b3 b1 sub abs 0.05 gt\n";
197 *outfile << " g3 g1 sub abs 0.017 gt\n";
198 *outfile << " r3 r1 sub abs 0.032 gt\n";
199 *outfile << " b2 b3 sub abs 0.05 gt\n";
200 *outfile << " g2 g3 sub abs 0.017 gt\n";
201 *outfile << " r2 r3 sub abs 0.032 gt\n";
202 *outfile << " or or or or or or or or {\n";
203 *outfile << " /b12 b1 b2 add 0.5 mul def\n";
204 *outfile << " /g12 g1 g2 add 0.5 mul def\n";
205 *outfile << " /r12 r1 r2 add 0.5 mul def\n";
206 *outfile << " /y12 y1 y2 add 0.5 mul def\n";
207 *outfile << " /x12 x1 x2 add 0.5 mul def\n";
208 *outfile << "\n";
209 *outfile << " /b13 b1 b3 add 0.5 mul def\n";
210 *outfile << " /g13 g1 g3 add 0.5 mul def\n";
211 *outfile << " /r13 r1 r3 add 0.5 mul def\n";
212 *outfile << " /y13 y1 y3 add 0.5 mul def\n";
213 *outfile << " /x13 x1 x3 add 0.5 mul def\n";
214 *outfile << "\n";
215 *outfile << " /b32 b3 b2 add 0.5 mul def\n";
216 *outfile << " /g32 g3 g2 add 0.5 mul def\n";
217 *outfile << " /r32 r3 r2 add 0.5 mul def\n";
218 *outfile << " /y32 y3 y2 add 0.5 mul def\n";
219 *outfile << " /x32 x3 x2 add 0.5 mul def\n";
220 *outfile << "\n";
221 *outfile << " /b132 b1 b3 b2 add add 3 div def\n";
222 *outfile << " /g132 g1 g3 g2 add add 3 div def\n";
223 *outfile << " /r132 r1 r3 r2 add add 3 div def\n";
224 *outfile << " /y132 y1 y3 y2 add add 3 div def\n";
225 *outfile << " /x132 x1 x3 x2 add add 3 div def\n";
226 *outfile << "\n";
227 *outfile << " save x1 y1 r1 g1 b1 x12 y12 r12 g12 b12 x132 y132 r132 g132 b132 ST restore\n";
228 *outfile << " save x1 y1 r1 g1 b1 x13 y13 r13 g13 b13 x132 y132 r132 g132 b132 ST restore\n";
229 *outfile << " save x2 y2 r2 g2 b2 x12 y12 r12 g12 b12 x132 y132 r132 g132 b132 ST restore\n";
230 *outfile << " save x2 y2 r2 g2 b2 x32 y32 r32 g32 b32 x132 y132 r132 g132 b132 ST restore\n";
231 *outfile << " save x3 y3 r3 g3 b3 x13 y13 r13 g13 b13 x132 y132 r132 g132 b132 ST restore\n";
232 *outfile << " save x3 y3 r3 g3 b3 x32 y32 r32 g32 b32 x132 y132 r132 g132 b132 ST restore\n";
233 *outfile << " } {\n";
234 *outfile << " x1 y1 x2 y2 x3 y3 r1 g1 b1 T\n";
235 *outfile << " } ifelse } ifelse\n";
236 *outfile << "} bind def\n";
237 *outfile << "\n";
238
239 *outfile << "%%EndProlog\n";
240 }
241
242
243 //
244 // GLPfile destructor; like the constructor, this just does the basics.
245 // You'll want to implement your own...
246 //
247
~GLPfile(void)248 GLPfile :: ~GLPfile(void)
249 {
250 // Free any memory we've allocated...
251 GLPtext *text, *nexttext;
252
253 for( text=texthead; text; text=nexttext )
254 {
255 nexttext = text->next;
256 free( text->string );
257 delete text;
258 }
259 texthead = NULL;
260
261 delete_all();
262
263 if (feedback != NULL) delete feedback;
264 if (colormap != NULL) delete colormap;
265
266 *outfile << "%%Pages: " << page_count << "\n";
267 *outfile << "%%BoundingBox: " << LLx << " " << LLy << " " << URx << " " << URy << "\n";
268 *outfile << "%%EOF\n";
269 delete outfile;
270 }
271
272
273 //
274 // 'EndPage' function; this does nothing except parse the bounding boxes
275 // and output any remaining primitives. It then frees the bounding box
276 // and primitive lists...
277 //
278
279 int
EndPage(void)280 GLPfile :: EndPage(void)
281 {
282 GLPbbox *bbox; // Current bounding box
283 GLPprimitive *prim; // Current primitive
284 int i; // Color index background...
285 GLfloat rgba[4]; // RGBA background...
286 GLint viewport[4];
287
288 GLPtext *text;
289
290 #ifdef DEBUG
291 cout << "EndPage()\n" << flush;
292 #endif /* DEBUG */
293
294 // Stop doing feedback...
295
296 UpdatePage(GL_FALSE);
297
298 // Return an error if there was no feedback data used...
299
300 if (bboxes == NULL) return (GLP_NO_FEEDBACK);
301
302 // Loop through all bounding boxes and primitives...
303 #define MAX(x,y) ((x)>(y)?(x):(y))
304
305
306 #ifdef DEBUG
307 cout << "EndPage() - writing page.\n" << flush;
308 #endif /* DEBUG */
309
310 glGetIntegerv(GL_VIEWPORT, viewport);
311
312 page_count ++;
313 *outfile << "%%Page: " << page_count << "\n";
314 *outfile << "%%PageBoundingBox: 0 0 " << viewport[2] << " " << viewport[3] << "\n";
315 LLx = 0;
316 LLy = 0;
317 URx = MAX( viewport[2], URx );
318 URy = MAX( viewport[3], URy );
319
320 *outfile << "gsave\n";
321
322 if (options & GLP_FIT_TO_PAGE)
323 {
324 *outfile << "% Fit to page...\n";
325 *outfile << "newpath clippath pathbbox\n";
326 *outfile << "/URy exch def\n";
327 *outfile << "/URx exch def\n";
328 *outfile << "/LLy exch def\n";
329 *outfile << "/LLx exch def\n";
330 *outfile << "/Width URx LLx sub 0.005 sub def\n";
331 *outfile << "/Height URy LLy sub 0.005 sub def\n";
332 *outfile << "LLx LLy translate\n";
333 *outfile << "/XZoom Width " << viewport[2] << " div def\n";
334 *outfile << "/YZoom Height " << viewport[3] << " div def\n";
335 *outfile << "Width YZoom mul Height XZoom mul gt {\n";
336 *outfile << " 90 rotate\n";
337 *outfile << " 0 Width neg translate\n";
338 *outfile << " Width Height /Width exch def /Height exch def\n";
339 *outfile << " /XZoom Width " << viewport[2] << " div def\n";
340 *outfile << " /YZoom Height " << viewport[3] << " div def\n";
341 *outfile << "} if\n";
342 *outfile << "XZoom YZoom gt {\n";
343 *outfile << " /YSize Height def\n";
344 *outfile << " /XSize " << viewport[2] << " YZoom mul def\n";
345 *outfile << " /Scale YZoom def\n";
346 *outfile << "} {\n";
347 *outfile << " /XSize Width def\n";
348 *outfile << " /YSize " << viewport[3] << " XZoom mul def\n";
349 *outfile << " /Scale XZoom def\n";
350 *outfile << "} ifelse\n";
351
352 *outfile << "Width XSize sub 2 div\n";
353 *outfile << "Height YSize sub 2 div translate\n";
354 *outfile << "Scale Scale scale\n";
355 *outfile << "\n";
356 };
357
358 if (options & GLP_DRAW_BACKGROUND)
359 {
360 if (feedmode == GL_RGBA || colorsize == 0)
361 glGetFloatv(GL_COLOR_CLEAR_VALUE, rgba);
362 else
363 {
364 glGetIntegerv(GL_INDEX_CLEAR_VALUE, &i);
365 rgba[0] = colormap[i][0];
366 rgba[1] = colormap[i][1];
367 rgba[2] = colormap[i][2];
368 };
369
370 *outfile << "% Draw background...\n";
371 *outfile << rgba[0] << " " << rgba[1] << " " << rgba[2] << " C\n";
372 *outfile << "newpath\n";
373 *outfile << " 0 0 moveto\n";
374 *outfile << " " << viewport[2] << " 0 lineto\n";
375 *outfile << " " << viewport[2] << " " << viewport[3] << " lineto\n";
376 *outfile << " 0 " << viewport[3] << " lineto\n";
377 *outfile << "closepath fill\n";
378 *outfile << "\n";
379 };
380
381 for (bbox = bboxes; bbox != NULL; bbox = bbox->next) {
382 output_tree( bbox->primitives );
383 }
384
385 *outfile << "1 1 1 C\n";
386 for( text=texthead; text; text = text->next ) DoOutputPS( text );
387
388 *outfile << "grestore\n";
389 *outfile << "showpage\n";
390 *outfile << "%%EndPage\n";
391 *outfile << std::flush;
392
393 // Delete everything from the bounding box and primitive lists...
394
395 delete_all();
396
397 #ifdef DEBUG
398 cout << "EndPage() - done.\n" << flush;
399 #endif /* DEBUG */
400
401 return (GLP_SUCCESS);
402 }
403
404
output_tree(GLPprimitive * tree)405 void GLPfile :: output_tree( GLPprimitive *tree )
406 {
407 if ( !tree ) return;
408 output_tree( tree->left );
409 output_prim( tree );
410 output_tree( tree->right );
411 }
412
output_prim(GLPprimitive * prim)413 void GLPfile :: output_prim( GLPprimitive *prim )
414 {
415 switch (prim->num_verts)
416 {
417 case 1 : /* Point */
418 *outfile << prim->verts[0].xyz[0] << " " << prim->verts[0].xyz[1] << " " <<
419 prim->verts[0].rgba[0] << " " << prim->verts[0].rgba[1] << " " <<
420 prim->verts[0].rgba[2] << " P\n";
421 break;
422 case 2 : /* Line */
423 if (prim->shade)
424 {
425 *outfile << prim->verts[1].xyz[0] << " " << prim->verts[1].xyz[1] << " " <<
426 prim->verts[1].rgba[0] << " " << prim->verts[1].rgba[1] << " " <<
427 prim->verts[1].rgba[2] << " " <<
428 prim->verts[0].xyz[0] << " " << prim->verts[0].xyz[1] << " " <<
429 prim->verts[0].rgba[0] << " " << prim->verts[0].rgba[1] << " " <<
430 prim->verts[0].rgba[2] <<
431 " SL\n";
432 }
433 else
434 {
435 *outfile << prim->verts[1].xyz[0] << " " << prim->verts[1].xyz[1] << " " <<
436 prim->verts[0].xyz[0] << " " << prim->verts[0].xyz[1] << " " <<
437 prim->verts[0].rgba[0] << " " << prim->verts[0].rgba[1] << " " <<
438 prim->verts[0].rgba[2] <<
439 " L\n";
440 }
441 break;
442 case 3 : /* Triangle */
443 if (prim->shade)
444 {
445 *outfile << prim->verts[2].xyz[0] << " " << prim->verts[2].xyz[1] << " " <<
446 prim->verts[2].rgba[0] << " " << prim->verts[2].rgba[1] << " " <<
447 prim->verts[2].rgba[2] << " " <<
448 prim->verts[1].xyz[0] << " " << prim->verts[1].xyz[1] << " " <<
449 prim->verts[1].rgba[0] << " " << prim->verts[1].rgba[1] << " " <<
450 prim->verts[1].rgba[2] << " " <<
451 prim->verts[0].xyz[0] << " " << prim->verts[0].xyz[1] << " " <<
452 prim->verts[0].rgba[0] << " " << prim->verts[0].rgba[1] << " " <<
453 prim->verts[0].rgba[2] <<
454 " ST\n";
455 }
456 else
457 {
458 *outfile << prim->verts[2].xyz[0] << " " << prim->verts[2].xyz[1] << " " <<
459 prim->verts[1].xyz[0] << " " << prim->verts[1].xyz[1] << " " <<
460 prim->verts[0].xyz[0] << " " << prim->verts[0].xyz[1] << " " <<
461 prim->verts[0].rgba[0] << " " << prim->verts[0].rgba[1] << " " <<
462 prim->verts[0].rgba[2] <<
463 " T\n";
464 }
465 break;
466 };
467 }
468
DoOutputPS(GLPtext * t)469 void GLPfile :: DoOutputPS( GLPtext *t )
470 {
471 *outfile << "/Times-Roman findfont " << t->h << " scalefont setfont\n";
472 *outfile << t->r << " " << t->g << " " << t->b << " C\n";
473 *outfile << t->x << " " << t->y << " moveto\n";
474 *outfile << "(" << t->string << ") show\n";
475 }
476
OutputPSString(double x,double y,double h,double r,double g,double b,char * string)477 extern "C" void OutputPSString( double x, double y, double h, double r, double g, double b, char *string )
478 {
479 GLPtext *text;
480
481 text = new GLPtext;
482
483 text->next = texthead;
484 texthead = text;
485
486 text->x = x;
487 text->y = y;
488 text->h = h;
489 text->r = r;
490 text->g = g;
491 text->b = b;
492 text->string = (char *)malloc( strlen(string)+1 );
493 strncpy( text->string, string, strlen(string)+1 );
494 }
495
496 //
497 // End of "$Id: file.cc,v 1.1.1.1 2005/05/31 06:29:21 vierinen Exp $".
498 //
499