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