1 /* SCCS-info %W% %E% */
2 
3 /*--------------------------------------------------------------------*/
4 /*								      */
5 /*		VCG : Visualization of Compiler Graphs		      */
6 /*		--------------------------------------		      */
7 /*								      */
8 /*   file:	   PSDev.c   					      */
9 /*   version:	   1.00.00					      */
10 /*   creation:	   14.4.93					      */
11 /*   author:	   G. Sander (Version 1.00.00-...)		      */
12 /*		   Universitaet des Saarlandes, 66041 Saarbruecken    */
13 /*		   ESPRIT Project #5399 Compare 		      */
14 /*   description:  PostScript Device: Print bitmap into a file in     */
15 /*		   PostScript format    			      */
16 /*   status:	   in work					      */
17 /*								      */
18 /*--------------------------------------------------------------------*/
19 
20 
21 #ifndef lint
22 static char *id_string="$Id: PSdev.c,v 1.8 1995/02/08 11:11:14 sander Exp $";
23 #endif
24 
25 
26 /*
27  *   Copyright (C) 1993-2005 Saarland University
28  *
29  *  This program and documentation is free software; you can redistribute
30  *  it under the terms of the  GNU General Public License as published by
31  *  the  Free Software Foundation;  either version 2  of the License,  or
32  *  (at your option) any later version.
33  *
34  *  This  program  is  distributed  in  the hope that it will be useful,
35  *  but  WITHOUT ANY WARRANTY;  without  even  the  implied  warranty of
36  *  MERCHANTABILITY  or  FITNESS  FOR  A  PARTICULAR  PURPOSE.  See  the
37  *  GNU General Public License for more details.
38  *
39  *  You  should  have  received a copy of the GNU General Public License
40  *  along  with  this  program;  if  not,  write  to  the  Free Software
41  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
42  *
43  *  The software is available per anonymous ftp at ftp.cs.uni-sb.de.
44  *  Contact  sander@cs.uni-sb.de  for additional information.
45  */
46 
47 
48 /*
49  * $Log: PSdev.c,v $
50  * Revision 1.8  1995/02/08  11:11:14  sander
51  * Distribution version 1.3.
52  *
53  * Revision 1.7  1994/12/23  18:12:45  sander
54  * Manhatten layout added.
55  * Option interface cleared.
56  * infobox behaviour improved.
57  * First version of fisheye (carthesian).
58  * Options Noedge and nonode.
59  * Titles in the node title box are now sorted.
60  *
61  * Revision 1.6  1994/11/25  15:43:29  sander
62  * Printer interface added to allow to use VCG as a converter.
63  *
64  * Revision 1.5  1994/08/02  15:36:12  sander
65  * Bounding box for landscape format corrected.
66  *
67  * Revision 1.4  1994/06/07  14:09:59  sander
68  * Splines implemented.
69  * HP-UX, Linux, AIX, Sun-Os, IRIX compatibility tested.
70  * The tool is now ready to be distributed.
71  *
72  * Revision 1.3  1994/05/16  08:56:03  sander
73  * shape attribute (boxes, rhombs, ellipses, triangles) added.
74  *
75  * Revision 1.2  1994/05/05  08:20:30  sander
76  * Small corrections.
77  *
78  * Revision 1.1  1994/04/27  16:05:19  sander
79  * Initial revision
80  *
81  *
82  */
83 
84 /************************************************************************
85  *  This file allows to write the graph into a PostScript file. These
86  *  routines are called, if the "export"-menu was selected.
87  *
88  *  The implementation idea is a little bit ugly: We use the same
89  *  drawing driver "draw.c" and "drawlib.c" and only redefine the
90  *  device dependent functions. This duplication of code ensures that
91  *  the speed is reasonable. All global function names must be mapped
92  *  to new names, otherwise we have linking conflicts.
93  *
94  *  Basically, the following function are in this file:
95  *    print_all_ps	     prints the PostScript to a file
96  ************************************************************************/
97 
98 
99 /* Mapping of global names of draw.c, drawstr.c, drawlib.c
100  * =======================================================
101  */
102 
103 #define INCLUDE_DRAW
104 #define POSTSCRIPT_DEVICE
105 
106 #define draw_main      ps_draw_main
107 #define draw_one_node  ps_draw_one_node
108 #define gs_stringw     ps_stringw
109 #define gs_stringh     ps_stringh
110 #define gs_boxw        ps_boxw
111 #define gs_boxh        ps_boxh
112 
113 #define gs_printstr          ps_printstr
114 #define gs_calcstringsize    ps_calcstringsize
115 #define gs_setto             ps_setto
116 #define gs_setshrink         ps_setshrink
117 #define gs_calctextboxsize   ps_calctextboxsize
118 #define gs_anchornode        ps_anchornode
119 #define gs_textbox           ps_textbox
120 #define gs_reverttextbox     ps_reverttextbox
121 #define gs_halfreverttextbox ps_halfreverttextbox
122 #define gs_stringbox         ps_stringbox
123 #define gs_calcrhombsize     ps_calcrhombsize
124 #define gs_rhomb             ps_rhomb
125 #define gs_revertrhomb       ps_revertrhomb
126 #define gs_halfrevertrhomb   ps_halfrevertrhomb
127 #define gs_calctrianglesize  ps_calctrianglesize
128 #define gs_triangle          ps_triangle
129 #define gs_reverttriangle    ps_reverttriangle
130 #define gs_halfreverttriangle ps_halfreverttriangle
131 #define gs_calcellipsesize   ps_calcellipsesize
132 #define gs_ellipse           ps_ellipse
133 #define gs_revertellipse     ps_revertellipse
134 #define gs_halfrevertellipse ps_halfrevertellipse
135 #define gs_solidarrow        ps_solidarrow
136 #define gs_dashedarrow       ps_dashedarrow
137 #define gs_dottedarrow       ps_dottedarrow
138 #define gs_line              ps_line
139 #define gs_rectangle         ps_rectangle
140 #define gs_actbackground     ps_actbackground
141 
142 #define mystretch            ps_mystretch
143 #define myshrink             ps_myshrink
144 #define myxpos               ps_myxpos
145 #define myypos               ps_myypos
146 #define gs_stlimit           ps_stlimit
147 #define gs_shlimit           ps_shlimit
148 
149 
150 /* Includes, Prototypes, Variables
151  * ===============================
152  * We must include globals.h before everything, otherwise we cannot
153  * define the prototypes.
154  * Even if globals.h is included in draw.c and drawlib.c again, this
155  * is correct, because of the include-security mechanism, that prevents
156  * second inclusion of a file from having ugly effects.
157  */
158 
159 #include <stdio.h>
160 #include <stdlib.h>
161 #include <math.h>
162 #include "globals.h"
163 
164 
165 /* Prototypes
166  * ----------
167  */
168 
169 static int print_ps
170    _PP((char *fname, int a,int b,int c,int d, float scale, float lm, float bm,
171 float tm, int   form, int col, int numpag));
172 
173 static FILE *check_and_open_file  _PP((char *fname));
174 
175 void ps_line
176 		_PP((int fx,int fy,int tx,int ty,int c));
177 void ps_thickline
178 		_PP((int fx,int fy,int tx,int ty,int t,int c));
179 static void ps_dashedthickline
180 		_PP((int fx,int fy,int tx,int ty,int t,int c,int d));
181 static void ps_dottedthickline
182 		_PP((int fx,int fy,int tx,int ty,int t,int c,int d));
183 static void ps_bezierspline
184 		_PP((int x0,int y0,int x1,int y1,int x2,int y2,int x3,int y3,int t,int c,int m));
185 static void ps_rectangle
186 		_PP((int x,int y,int w,int h,int c));
187 static void ps_fillrhomb
188 		_PP((int x,int y,int w,int h,int c));
189 static void ps_filltriangle
190 		_PP((int x,int y,int w,int h,int c));
191 static void ps_fillellipse
192 		_PP((int x,int y,int w,int h,int c));
193 static void ps_freearrowpoint
194 		_PP((int x1,int y1,int rx1,int ry1,int rx2,int ry2,int c));
195 static void ps_w_arrowpoint
196 		_PP((int x,int y,int size,int c));
197 static void ps_s_arrowpoint
198 		_PP((int x,int y,int size,int c));
199 static void ps_n_arrowpoint
200 		_PP((int x,int y,int size,int c));
201 static void ps_e_arrowpoint
202 		_PP((int x,int y,int size,int c));
203 static void ps_sw_arrowpoint
204 		_PP((int x,int y,int size,int c));
205 static void ps_nw_arrowpoint
206 		_PP((int x,int y,int size,int c));
207 static void ps_ne_arrowpoint
208 		_PP((int x,int y,int size,int c));
209 static void ps_se_arrowpoint
210 		_PP((int x,int y,int size,int c));
211 
212 static void portrait_header
213 	_PP((int a,int  b,int  c,int  d,float scale,float lm, float bm));
214 static void landscape_header
215 	_PP((int a,int  b,int  c,int  d,float scale,float lm, float bm));
216 
217 static void common_header _PP((void));
218 
219 static void init_postscriptpage _PP((void));
220 static void calc_paper_width	_PP((void));
221 
222 static void ps_setcolor _PP((int c));
223 
224 
225 
226 /* Variables
227  * ---------
228  */
229 
230 static char *mfilename;
231 
232 /* Flag, wether cps (2), gps (1) or bps (0)
233  */
234 
235 static int bps_flag;
236 static FILE *fptr;
237 
238 static int dist;
239 
240 /* from X11devpb.c */
241 
242 extern int   act_output_type;
243 extern int   act_color_type;
244 extern int   act_ori_type;
245 extern int   act_paper_num;
246 extern int   act_paper_type;
247 extern float act_width;
248 extern float act_height;
249 extern float act_left_margin;
250 extern float act_right_margin;
251 extern float act_top_margin;
252 extern float act_bottom_margin;
253 extern int   act_xdpi;
254 extern int   act_ydpi;
255 extern float act_scaling;
256 extern int   act_bbox;
257 
258 /* Counter for the wait message */
259 
260 static int wait_cntr;
261 
262 static int mreg_xmin;
263 static int mreg_xmax;
264 static int mreg_ymin;
265 static int mreg_ymax;
266 static int maxxdist;
267 static int maxydist;
268 static int maxover;
269 
270 
271 /* Modules
272  * -------
273  * We use this ugly trick to reuse the files draw.c and drawlib.c
274  */
275 
276 #include "draw.c"
277 #include "drawlib.c"
278 #include "PSdev.h"
279 
280 
281 /*--------------------------------------------------------------------*/
282 /*  Print all nodes into a file, Entry point                          */
283 /*--------------------------------------------------------------------*/
284 
285 /*  We take the arguments that are setup in X11devpb, recalculate
286  *  the measures, and output the graph.
287  */
288 
289 #ifdef ANSI_C
print_all_ps(char * fname,int a,int b,int c,int d)290 void print_all_ps(char *fname, int a, int b, int c, int d)
291 #else
292 void print_all_ps(fname, a, b, c, d)
293 char *fname;
294 int a, b, c, d;
295 #endif
296 {
297 	int form;
298 	float scale, lm, bm, tm;
299 
300 	assert((act_output_type==3));
301 
302 
303 	wait_cntr  = 0;
304 	if (a>c)  { form = a; a = c; c = form; }
305 	if (b>d)  { form = b; b = d; d = form; }
306 	mreg_xmin = a;
307 	mreg_xmax = c;
308 	mreg_ymin = b;
309 	mreg_ymax = d;
310 
311 	switch (act_ori_type) {
312 	case 1: form = 0; break;
313 	case 2: form = 1; break;
314 	}
315 
316 	scale = (float)(act_xdpi)/act_scaling;
317 	lm = act_left_margin/2.54;
318 	bm = act_bottom_margin/2.54;
319 	tm = act_top_margin/2.54;
320 
321 	switch (act_color_type) {
322 	case 1: print_ps(fname, a, b, c, d,scale,lm,bm,tm,form,2,act_paper_num);
323 		break;
324 	case 2: print_ps(fname, a, b, c, d,scale,lm,bm,tm,form,1,act_paper_num);
325 		break;
326 	case 3: print_ps(fname, a, b, c, d,scale,lm,bm,tm,form,0,act_paper_num);
327 		break;
328 	}
329 }
330 
331 
332 
333 /*--------------------------------------------------------------------*/
334 /*  Print all nodes into a file, driver                               */
335 /*--------------------------------------------------------------------*/
336 
337 /*  Print ps-file
338  *  =============
339  *  This is the black and white driver. No colors, no grayscales.
340  *  The region (a,b)-(c,d) is printed to the file.
341  *  The scaling is scale, however different as before, it gives the
342  *  scaling of 1 inch. E.g. scale = 300 means we have 300 units per
343  *  inch, i.e. 300 dpi.
344  *  lm,bm are the left margin, bottom margin in inches.
345  *
346  *  We follow the Adobe 2.0 PostScript format with Bounding Box.
347  *  Note: the bounding box gives the true size of the picture in 72dpi,
348  *  E.g.  BoundingBox: 72 72 518 762  is a picture that is on a din A 4
349  *  1 inc far from the border.
350  *      A 4 maximal:     0 0 590 834
351  *      Letter maximal:  0 0 590 864
352  *  form gives the format: 1 is landscape, 0 is portrait
353  *  We return 1 on success.
354  */
355 
356 
357 #ifdef ANSI_C
print_ps(char * fname,int a,int b,int c,int d,float scale,float lm,float bm,float tm,int form,int col,int numpag)358 static int print_ps(char *fname,int a,int b,int c,int d,float scale,float lm,float bm,float tm,int form,int col,int numpag)
359 #else
360 static int print_ps(fname, a, b, c, d,scale,lm,bm,tm,form,col,numpag)
361 char *fname;
362 int   a,b,c,d;
363 float scale;
364 float lm,bm,tm;
365 int   form;
366 int col;
367 int numpag;
368 #endif
369 {
370 	int Vs_xmin, Vs_ymin, Vs_xmax, Vs_ymax;
371 	int s_stretch, s_shrink, oldcol;
372 	int i, j;
373 	int oldx, oldy;
374 
375 	mfilename = fname;
376 	bps_flag = col;
377 
378 	if (c<=a) return(0);
379 	if (d<=b) return(0);
380 
381 	if (act_paper_num > 1) {
382 		lm = 1.0/2.54;
383 		bm = 1.0/2.54;
384 		tm = 1.0/2.54;
385 		calc_paper_width();
386 		act_bbox = 0;
387 	}
388 
389 	fptr = check_and_open_file(fname);
390 	if (fptr==NULL)  return(0);
391 
392 	/* save old values */
393 	Vs_xmin = V_xmin;     Vs_ymin = V_ymin;
394 	Vs_xmax = V_xmax;     Vs_ymax = V_ymax;
395 	s_shrink  = G_shrink; s_stretch = G_stretch;
396 	oldcol       = colored;
397 
398 	/* install printout values. We leave the scaling to postscript */
399 	V_xmin = a;     V_ymin = b;
400 	V_xmax = c;     V_ymax = d;
401 	G_shrink  = 1; G_stretch = 1;
402 
403 	switch (bps_flag) {
404 	case 2: colored   = 1; break;
405 	case 1: colored   = 1; break;
406 	case 0: colored   = 0; break;
407 	}
408 
409 	wait_cntr  = 0;
410 
411 	/* Header */
412 	if (form == 1) 	landscape_header(a, b, c, d, scale, lm, tm);
413 	else		portrait_header( a, b, c, d, scale, lm, bm);
414 
415 	oldx = mreg_xmin;
416 	for (i=1; i<=numpag; i++) {
417 		if (numpag!=1) {
418 			a = oldx;
419 			if (a>=mreg_xmax) break;
420 			c = a + maxxdist + maxover;
421 			oldx = a + maxxdist;
422 			if (c>=mreg_xmax) {
423 				oldx = mreg_xmax;
424 				c = mreg_xmax;
425 			}
426 			oldy = mreg_ymin;
427 		}
428 		for (j=1; j<=numpag; j++) {
429 
430 			gs_wait_message('y');
431 
432 			if (numpag==1) {
433 				a = mreg_xmin;
434 				c = mreg_xmax;
435 				b = mreg_ymin;
436 				d = mreg_ymax;
437 			}
438 			else {
439 				b = oldy;
440 				if (b>=mreg_ymax) break;
441 
442 				d = b + maxydist + maxover;
443 				oldy = b + maxydist;
444 				if (d>=mreg_ymax) {
445 					oldy = mreg_ymax;
446 					d = mreg_ymax;
447 				}
448 			}
449 			V_xmin = a;
450 			V_xmax = c;
451 			V_ymin = b;
452 			V_ymax = d;
453 			dist = V_ymax-V_ymin;
454 
455 			FPRINTF(fptr,"%%%%Page: %d %d\n",
456 				(i-1)*numpag+j, (i-1)*numpag+j);
457 			/* if (numpag>1) init_postscriptpage(); */
458 			FPRINTF(fptr,"72 %3.2f div dup scale\n",scale);
459 			if (numpag == 1) {
460 				if (form == 1) {
461 					FPRINTF(fptr,"90 rotate\n");
462 					FPRINTF(fptr,"%f %f translate\n",
463 						lm*scale,
464 						-tm*scale
465 					        -(float)(d-b));
466 				}
467 				else {
468 					FPRINTF(fptr,"%f %f translate\n",
469 						lm*scale,bm*scale);
470 				}
471 			}
472 			else {
473 				if (form == 1) {
474 					FPRINTF(fptr,"90 rotate\n");
475 					FPRINTF(fptr,"%f %f translate\n",
476 						0.39*scale,
477 						-0.39*scale
478 					        -(float)(d-b));
479 				}
480 				else {
481 					FPRINTF(fptr,"%f %f translate\n",
482 						0.39*scale,0.39*scale);
483 				}
484 			}
485 
486 			/* draw to file */
487 
488 			if (colored) {
489 				ps_rectangle(V_xmin, V_ymin, V_xmax-V_xmin, V_ymax-V_ymin, G_color);
490 			}
491 			else {
492 				ps_rectangle(V_xmin, V_ymin, V_xmax-V_xmin, V_ymax-V_ymin, WHITE);
493 			}
494 			ps_draw_main();
495 
496 			FPRINTF(fptr,"showpage\n");
497 			FPRINTF(fptr,"%%%%PageTrailer\n");
498 		}
499 	}
500 	FPRINTF(fptr,"%%%%Trailer\n");
501 	FPRINTF(fptr,"%%%%EOF\n");
502 
503 	if (fptr) fclose(fptr);
504 	fptr = NULL;
505 
506 	/* restore old values */
507 	V_xmin = Vs_xmin;     V_ymin = Vs_ymin;
508 	V_xmax = Vs_xmax;     V_ymax = Vs_ymax;
509 	G_shrink  = s_shrink; G_stretch = s_stretch;
510 	colored   = oldcol;
511 	return(1);
512 }
513 
514 
515 
516 
517 
518 /* Check a file
519  * ------------
520  * Try to open a file `fname' for writing.
521  * If the file exists already, or the filename is not appropriate,
522  * it is an error.
523  * On error, we return NULL, otherwise the opend file.
524  */
525 
526 #ifdef ANSI_C
check_and_open_file(char * fname)527 static FILE *check_and_open_file(char *fname)
528 #else
529 static FILE *check_and_open_file(fname)
530 char *fname;
531 #endif
532 {
533 	FILE *f;
534         char *c;
535 
536         c = fname;
537         while (*c) c++;
538         if (c>fname) c--;
539 #ifdef VMS
540         if (*c==']') {
541 #else
542         if (*c=='/') {
543 #endif
544                 return(NULL);
545         }
546 
547 	/* check whether filename is useful */
548 	if (!fname)  return(NULL);
549 	if (!*fname) return(NULL);
550 
551 	/* check whether file already exists */
552 	f = fopen(fname,"r");
553 	if (f) { fclose(f); return(NULL); }
554 
555 	f = fopen(fname,"w");
556 	return(f);
557 }
558 
559 
560 /*--------------------------------------------------------------------*/
561 /*  Initializing sequences for PostScript                             */
562 /*--------------------------------------------------------------------*/
563 
564 /*  Portrait format
565  *  ---------------
566  */
567 
568 #ifdef ANSI_C
portrait_header(int a,int b,int c,int d,float scale,float lm,float bm)569 static void portrait_header(int a,int b,int c,int d,float scale,float lm,float bm)
570 #else
571 static void portrait_header(a, b, c, d, scale, lm, bm)
572 int a, b, c, d;
573 float scale, lm, bm;
574 #endif
575 {
576 	float numxunits, numyunits;
577 
578 	assert((c>a));
579 	assert((d>b));
580 
581 	numxunits = (float)(c-a);
582 	numyunits = (float)(d-b);
583 
584 	FPRINTF(fptr,"%%!PS-Adobe-2.0 EPSF-1.2\n");
585 	FPRINTF(fptr,"%%%%Creator: %s (P)\n", short_banner);
586 	FPRINTF(fptr,"%%%%Title: %s\n", mfilename);
587 	FPRINTF(fptr,"%%%%RCS-info: $I");
588 	FPRINTF(fptr,"d$\n");
589         FPRINTF(fptr,"%%%%SCCS-info: %%W");
590         FPRINTF(fptr,"%% %%E");
591         FPRINTF(fptr,"%%\n");
592 	if (act_bbox) FPRINTF(fptr,"%%%%BoundingBox: ");
593 	else          FPRINTF(fptr,"%%%%ProposedBoundings: ");
594 	FPRINTF(fptr," %d %d %d %d\n",
595 		gstoint(lm*72),gstoint(bm*72),
596 		gstoint(lm*72)+gstoint(72*numxunits/scale),
597 		gstoint(bm*72)+gstoint(72*numyunits/scale));
598 
599 	FPRINTF(fptr,"%%%%EndComments\n");
600 
601 	common_header();
602 }
603 
604 
605 /*  Landscape format
606  *  ----------------
607  */
608 
609 #ifdef ANSI_C
landscape_header(int a,int b,int c,int d,float scale,float lm,float tm)610 static void landscape_header(int a,int b,int c,int d,float scale,float lm,float tm)
611 #else
612 static void landscape_header(a, b, c, d, scale, lm, tm)
613 int a, b, c, d;
614 float scale, lm, tm;
615 #endif
616 {
617 	float numxunits, numyunits;
618 
619 	assert((c>a));
620 	assert((d>b));
621 
622 	numxunits = (float)(c-a);
623 	numyunits = (float)(d-b);
624 
625 	FPRINTF(fptr,"%%!PS-Adobe-2.0 EPSF-1.2\n");
626 	FPRINTF(fptr,"%%%%Creator: %s (L)\n", short_banner);
627 	FPRINTF(fptr,"%%%%Title: %s\n", mfilename);
628 	FPRINTF(fptr,"%%%%RCS-info: $I");
629 	FPRINTF(fptr,"d$\n");
630         FPRINTF(fptr,"%%%%SCCS-info: %%W");
631         FPRINTF(fptr,"%% %%E");
632         FPRINTF(fptr,"%%\n");
633 	if (act_bbox) FPRINTF(fptr,"%%%%BoundingBox: ");
634 	else          FPRINTF(fptr,"%%%%ProposedBoundings: ");
635 	FPRINTF(fptr," %d %d %d %d\n",
636 		gstoint(tm*72),gstoint(lm*72),
637 		gstoint(tm*72)+gstoint(72*numyunits/scale),
638 		gstoint(lm*72)+gstoint(72*numxunits/scale));
639 	FPRINTF(fptr,"%%%%EndComments\n");
640 
641 	common_header();
642 }
643 
644 
645 /*  Common Header for both formats
646  */
647 
648 #ifdef ANSI_C
common_header(void)649 static void common_header(void)
650 #else
651 static void common_header()
652 #endif
653 {
654 	FPRINTF(fptr,"1 setlinecap\n");
655 	FPRINTF(fptr,"1 setlinejoin\n");
656 
657 	/* Position turtle without drawing */
658 
659 	FPRINTF(fptr,"/M /moveto load def\n");
660 
661 	/* Draw linw from actual point to specified point */
662 
663 	FPRINTF(fptr,"/D { lineto currentpoint stroke moveto } def\n");
664 
665 	/* Define line from actual point to specified point without drawing */
666 
667 	FPRINTF(fptr,"/P /lineto load def\n");
668 
669 	/* Text print command (currently not used) */
670 
671 	FPRINTF(fptr,"/S /show load def\n");
672 
673 	/* Set gray value color. 0 = Black */
674 
675 	FPRINTF(fptr,"/G /setgray load def\n");
676 
677 	/* Set real RGB color */
678 
679 	FPRINTF(fptr,"/C /setrgbcolor load def\n");
680 
681 	/* Set line width */
682 
683 	FPRINTF(fptr,"/LW /setlinewidth load def\n");
684 
685 	/* Define a new path (for filling) */
686 
687 	FPRINTF(fptr,"/NP /newpath load def\n");
688 
689 	/* Close a path, i.e. combine start and end point */
690 
691 	FPRINTF(fptr,"/CP /closepath load def\n");
692 
693 	/* Set Dashing mode */
694 
695 	FPRINTF(fptr,"/SD /setdash load def\n");
696 
697 	/* Default line thickness is 1 */
698 
699 	FPRINTF(fptr,"1 LW\n");
700 }
701 
702 
703 /*  Initialize a page, i.e. fill the whole page with the background color
704  *  ---------------------------------------------------------------------
705  */
706 
707 #ifdef ANSI_C
init_postscriptpage(void)708 static void init_postscriptpage(void)
709 #else
710 static void init_postscriptpage()
711 #endif
712 {
713 	int a, b, h;
714 
715 	switch (act_paper_type) {
716 	case 1: a = 595;  b = 850;  break;
717 	case 2: a = 525;  b = 765;  break;
718 	case 3: a = 425;  b = 595;  break;
719 	case 4: a = 792;  b = 1224; break;
720 	case 5: a = 612;  b = 792;  break;
721 	case 6: a = 612;  b = 1008; break;
722 	}
723 
724 	if (colored) ps_setcolor(G_color);
725 	else ps_setcolor(WHITE);
726 
727 	FPRINTF(fptr,"NP %d %d M %d %d P %d %d P %d %d P CP fill\n",
728 		0,   0,  0,  b,  a,  b,  a,  0);
729 }
730 
731 
732 
733 /*  Calculate the maximal number of pixels on a page
734  *  ------------------------------------------------
735  *  This is used for multipage output only.
736  */
737 
738 #ifdef ANSI_C
calc_paper_width(void)739 static void calc_paper_width(void)
740 #else
741 static void calc_paper_width()
742 #endif
743 {
744 	float mx, my;
745 
746 	assert((act_paper_num>1));
747         switch (act_paper_type) {
748         case 1:
749                 if (act_ori_type==1)    { mx = 21.0; my = 30.0; }
750                 else                    { mx = 30.0; my = 21.0; }
751                 break;
752         case 2:
753                 if (act_ori_type==1)    { mx = 18.5; my = 27.0; }
754                 else                    { mx = 27.0; my = 18.5; }
755                 break;
756         case 3:
757                 if (act_ori_type==1)    { mx = 15.0; my = 21.0; }
758                 else                    { mx = 21.0; my = 15.0; }
759                 break;
760         case 4:
761                 if (act_ori_type==1)    { mx = 27.94; my = 43.18; }
762                 else                    { mx = 43.18; my = 27.94; }
763                 break;
764         case 5:
765                 if (act_ori_type==1)    { mx = 21.59; my = 27.94; }
766                 else                    { mx = 27.94; my = 21.59; }
767                 break;
768         case 6:
769                 if (act_ori_type==1)    { mx = 21.59; my = 35.56; }
770                 else                    { mx = 35.56; my = 21.59; }
771                 break;
772         }
773         mx = (mx-3.0);
774         my = (my-3.0);
775 	maxxdist = (int)(mx * act_xdpi / act_scaling / 2.54);
776 	maxydist = (int)(my * act_ydpi / act_scaling / 2.54);
777 	maxover =  (int)(1.0 * act_ydpi / act_scaling / 2.54);
778 }
779 
780 
781 /*--------------------------------------------------------------------*/
782 /*  Device driver for pbm and ppm Files                               */
783 /*--------------------------------------------------------------------*/
784 
785 #ifdef ANSI_C
ps_setcolor(int c)786 static void 	ps_setcolor(int c)
787 #else
788 static void 	ps_setcolor(c)
789 int c;
790 #endif
791 {
792 	float col;
793 
794         wait_cntr++;
795         if (wait_cntr > 40)  { gs_wait_message('x'); wait_cntr = 0; }
796 
797 	switch(bps_flag) {
798 	case 0:
799 		if (c==WHITE) FPRINTF(fptr,"1.0 G ");
800 		else 	      FPRINTF(fptr,"0.0 G ");
801 		break;
802 	case 1:
803 		col = (float)(299*redmap[c]+587*greenmap[c]+114*bluemap[c]);
804 		FPRINTF(fptr,"%3.2f G ", col/1000.0/255.0);
805 		break;
806 	case 2:
807 		FPRINTF(fptr,"%3.2f %3.2f %3.2f C ",
808 			redmap[c]/255.0, greenmap[c]/255.0, bluemap[c]/255.0);
809 		break;
810 	}
811 }
812 
813 
814 /* Draw a rectangle
815  * ----------------
816  * at (x,y) with width w, height h and color c
817  */
818 
819 #ifdef ANSI_C
ps_rectangle(int x,int y,int w,int h,int c)820 static void    ps_rectangle(int x,int y,int w,int h,int c)
821 #else
822 static void    ps_rectangle(x, y, w, h, c)
823 int     x, y, w, h, c;
824 #endif
825 {
826 	ps_setcolor(c);
827 
828 	FPRINTF(fptr,"NP %d %d M %d %d P %d %d P %d %d P CP fill\n",
829 		x-V_xmin,   dist - (y-V_ymin),
830 		x-V_xmin+w, dist - (y-V_ymin),
831 		x-V_xmin+w, dist - (y-V_ymin+h),
832 		x-V_xmin,   dist - (y-V_ymin+h));
833 }
834 
835 
836 /* Draw a rhomb
837  * ------------
838  * at (x,y) with width w, height h and color c
839  */
840 
841 #ifdef ANSI_C
ps_fillrhomb(int x,int y,int w,int h,int c)842 static void    ps_fillrhomb(int x,int y,int w,int h,int c)
843 #else
844 static void    ps_fillrhomb(x, y, w, h, c)
845 int     x, y, w, h, c;
846 #endif
847 {
848 	ps_setcolor(c);
849 
850 	FPRINTF(fptr,"NP %d %d M %d %d P %d %d P %d %d P CP fill\n",
851 		x-V_xmin,     dist - (y-V_ymin+h/2),
852 		x-V_xmin+w/2, dist - (y-V_ymin),
853 		x-V_xmin+w,   dist - (y-V_ymin+h/2),
854 		x-V_xmin+w/2, dist - (y-V_ymin+h));
855 }
856 
857 
858 /* Draw a triangle
859  * ---------------
860  * at (x,y) with width w, height h and color c
861  */
862 
863 #ifdef ANSI_C
ps_filltriangle(int x,int y,int w,int h,int c)864 static void    ps_filltriangle(int x,int y,int w,int h,int c)
865 #else
866 static void    ps_filltriangle(x, y, w, h, c)
867 int     x, y, w, h, c;
868 #endif
869 {
870 	ps_setcolor(c);
871 
872 	switch (G_orientation) {
873 	case LEFT_TO_RIGHT:
874 		FPRINTF(fptr,"NP %d %d M %d %d P %d %d P CP fill\n",
875 			x-V_xmin+w  , dist - (y-V_ymin),
876 			x-V_xmin+w  , dist - (y-V_ymin+h),
877 			x-V_xmin    , dist - (y-V_ymin+h/2));
878 		return;
879 	case RIGHT_TO_LEFT:
880 		FPRINTF(fptr,"NP %d %d M %d %d P %d %d P CP fill\n",
881 			x-V_xmin  , dist - (y-V_ymin),
882 			x-V_xmin  , dist - (y-V_ymin+h),
883 			x-V_xmin+w, dist - (y-V_ymin+h/2));
884 		return;
885 	case BOTTOM_TO_TOP:
886 		FPRINTF(fptr,"NP %d %d M %d %d P %d %d P CP fill\n",
887 			x-V_xmin+w/2, dist - (y-V_ymin+h),
888 			x-V_xmin+w  , dist - (y-V_ymin),
889 			x-V_xmin    , dist - (y-V_ymin));
890 		return;
891 	case TOP_TO_BOTTOM:
892 		FPRINTF(fptr,"NP %d %d M %d %d P %d %d P CP fill\n",
893 			x-V_xmin+w/2, dist - (y-V_ymin),
894 			x-V_xmin+w  , dist - (y-V_ymin+h),
895 			x-V_xmin    , dist - (y-V_ymin+h));
896 		return;
897 	}
898 }
899 
900 
901 /* Draw an ellipse
902  * ---------------
903  * at (x,y) with width w, height h and color c
904  */
905 
906 #ifdef ANSI_C
ps_fillellipse(int x,int y,int w,int h,int c)907 static void    ps_fillellipse(int x,int y,int w,int h,int c)
908 #else
909 static void    ps_fillellipse(x, y, w, h, c)
910 int     x, y, w, h, c;
911 #endif
912 {
913         int i,j;
914 
915 	ps_setcolor(c);
916 
917 	FPRINTF(fptr,"NP %d %d M\n", x+w/2-V_xmin, dist-(y+h-V_ymin));
918         for (i=0; i<=(w+1)/2; i++) {
919                 j = h*h/4 - i*h/w * i*h/w;
920                 if (j>=0) j = gstoint(sqrt((double)j));
921                 else j = 0;
922 		FPRINTF(fptr,"%d %d P\n",
923 				x+w/2+i-V_xmin, dist-(y+h/2+j-V_ymin));
924 	}
925         for (i=(w+1)/2; i>0; i--) {
926                 j = h*h/4 - i*h/w * i*h/w;
927                 if (j>=0) j = gstoint(sqrt((double)j));
928                 else j = 0;
929 		FPRINTF(fptr,"%d %d P\n",
930 				x+w/2+i-V_xmin, dist-(y+h/2-j-V_ymin));
931 	}
932         for (i=0; i<=(w+1)/2; i++) {
933                 j = h*h/4 - i*h/w * i*h/w;
934                 if (j>=0) j = gstoint(sqrt((double)j));
935                 else j = 0;
936 		FPRINTF(fptr,"%d %d P\n",
937 				x+w/2-i-V_xmin, dist-(y+h/2-j-V_ymin));
938 	}
939         for (i=(w+1)/2; i>0; i--) {
940                 j = h*h/4 - i*h/w * i*h/w;
941                 if (j>=0) j = gstoint(sqrt((double)j));
942                 else j = 0;
943 		FPRINTF(fptr,"%d %d P\n",
944 				x+w/2-i-V_xmin, dist-(y+h/2+j-V_ymin));
945 	}
946 
947 	FPRINTF(fptr,"CP fill\n");
948 }
949 
950 
951 /* Draw a line
952  * -----------
953  * from fx,fy to tx,ty with color c.
954  */
955 
956 #ifdef ANSI_C
ps_line(int fx,int fy,int tx,int ty,int c)957 void    ps_line(int fx,int fy,int tx,int ty,int c)
958 #else
959 void    ps_line(fx, fy, tx, ty, c)
960 int     fx, fy, tx, ty, c;
961 #endif
962 {
963 	ps_setcolor(c);
964 
965 	FPRINTF(fptr,"%d %d M %d %d D\n",
966 	 	fx-V_xmin, dist - (fy-V_ymin),
967 		tx-V_xmin, dist - (ty-V_ymin));
968 
969 }
970 
971 
972 /* Draw a solid line of thickness t
973  * --------------------------------
974  * from fx,fy to tx,ty with color c.
975  */
976 
977 #ifdef ANSI_C
ps_thickline(int fx,int fy,int tx,int ty,int t,int c)978 void    ps_thickline(int fx,int fy,int tx,int ty,int t,int c)
979 #else
980 void    ps_thickline(fx, fy, tx, ty, t, c)
981 int     fx, fy, tx, ty, t, c;
982 #endif
983 {
984         ps_setcolor(c);
985 
986 	FPRINTF(fptr,"%d LW ",t);
987         FPRINTF(fptr,"%d %d M %d %d D 1 LW\n",
988                 fx-V_xmin, dist - (fy-V_ymin),
989 		tx-V_xmin, dist - (ty-V_ymin));
990 }
991 
992 
993 /* Draw a dashed line of thickness t
994  * ---------------------------------
995  * from fx,fy to tx,ty with color c.
996  */
997 
998 #ifdef ANSI_C
ps_dashedthickline(int fx,int fy,int tx,int ty,int t,int c,int d)999 static void    ps_dashedthickline(int fx,int fy,int tx,int ty,int t,int c,int d)
1000 #else
1001 static void    ps_dashedthickline(fx, fy, tx, ty, t, c, d)
1002 int     fx, fy, tx, ty, t, c, d;
1003 #endif
1004 {
1005         ps_setcolor(c);
1006 
1007 	FPRINTF(fptr,"[ %d %d ] 0 SD %d LW ",d,d,t);
1008         FPRINTF(fptr,"%d %d M %d %d D [ 100 0 ] 0 SD 1 LW\n",
1009                 fx-V_xmin, dist - (fy-V_ymin),
1010 		tx-V_xmin, dist - (ty-V_ymin));
1011 }
1012 
1013 
1014 /* Draw a dotted line of thickness t
1015  * ---------------------------------
1016  * from fx,fy to tx,ty with color c.
1017  */
1018 
1019 #ifdef ANSI_C
ps_dottedthickline(int fx,int fy,int tx,int ty,int t,int c,int d)1020 static void    ps_dottedthickline(int fx,int fy,int tx,int ty,int t,int c,int d)
1021 #else
1022 static void    ps_dottedthickline(fx, fy, tx, ty, t, c, d)
1023 int     fx, fy, tx, ty, t, c, d;
1024 #endif
1025 {
1026         ps_setcolor(c);
1027 
1028 	FPRINTF(fptr,"[ 1 %d ] 0 SD %d LW ",d,t);
1029         FPRINTF(fptr,"%d %d M %d %d D [ 100 0 ] 0 SD 1 LW\n",
1030                 fx-V_xmin, dist - (fy-V_ymin),
1031 		tx-V_xmin, dist - (ty-V_ymin));
1032 }
1033 
1034 
1035 /* Draw a bezier spline of thickness t
1036  * -----------------------------------
1037  * with color c and mode m.
1038  */
1039 
1040 #ifdef ANSI_C
ps_bezierspline(int x0,int y0,int x1,int y1,int x2,int y2,int x3,int y3,int t,int c,int m)1041 static void ps_bezierspline(
1042 	int x0,int y0,int x1,int y1,int x2,int y2,int x3,int y3,
1043 	int t,int c,int m)
1044 #else
1045 static void ps_bezierspline(x0,y0,x1,y1,x2,y2,x3,y3,t,c,m)
1046 int x0,y0,x1,y1,x2,y2,x3,y3,t,c,m;
1047 #endif
1048 {
1049 	int d;
1050 
1051         ps_setcolor(c);
1052 
1053 	switch (m) {
1054 	case SOLID:
1055 		FPRINTF(fptr,"%d LW ",t);
1056 		break;
1057 	case DOTTED:
1058 		d = 15*3*G_stretch/12/G_shrink;
1059 		FPRINTF(fptr,"[ 1 %d ] 0 SD %d LW ",d,t);
1060 		break;
1061 	case DASHED:
1062 		d = 15*G_stretch/G_shrink;
1063 		FPRINTF(fptr,"[ %d %d ] 0 SD %d LW ",d,d,t);
1064 		break;
1065 	case UNVISIBLE:
1066 		return;
1067 	}
1068         FPRINTF(fptr,"%d %d M %d %d ",
1069                 x0-V_xmin, dist - (y0-V_ymin),
1070 		x1-V_xmin, dist - (y1-V_ymin));
1071         FPRINTF(fptr,"%d %d %d %d curveto stroke\n",
1072                 x2-V_xmin, dist - (y2-V_ymin),
1073 		x3-V_xmin, dist - (y3-V_ymin));
1074 	FPRINTF(fptr,"[ 100 0] 0 SD 1 LW\n");
1075 }
1076 
1077 
1078 /* Draw a free arrowhead
1079  * ---------------------
1080  * i.e. draw a triangle between (x1, y1), (rx1, ry1), (rx2, ry2)
1081  */
1082 
1083 
1084 #ifdef ANSI_C
ps_freearrowpoint(int x1,int y1,int rx1,int ry1,int rx2,int ry2,int c)1085 static void ps_freearrowpoint(int x1,int y1,int rx1,int ry1,int rx2,int ry2,
1086 		int c)
1087 #else
1088 static void ps_freearrowpoint(x1, y1, rx1, ry1, rx2, ry2, c)
1089 int x1, y1, rx1, ry1, rx2, ry2, c;
1090 #endif
1091 {
1092 	ps_setcolor(c);
1093 	FPRINTF(fptr,"NP %d %d M %d %d P %d %d P CP fill\n",
1094 		x1-V_xmin, dist - (y1-V_ymin),
1095 		rx1-V_xmin,dist - (ry1-V_ymin),
1096 		rx2-V_xmin,dist - (ry2-V_ymin));
1097 }
1098 
1099 
1100 
1101 /* Draw an arrowhead to the north
1102  * ------------------------------
1103  * with `size' of katheses and color
1104  */
1105 
1106 #ifdef ANSI_C
ps_n_arrowpoint(int x,int y,int size,int c)1107 static void ps_n_arrowpoint(int x,int y,int size,int c)
1108 #else
1109 static void ps_n_arrowpoint(x, y, size, c)
1110 int     x, y, size, c;
1111 #endif
1112 {
1113 	int k;
1114 
1115 	ps_setcolor(c);
1116 
1117 	k = 7*size/10 - 1;
1118 
1119 	FPRINTF(fptr,"NP %d %d M %d %d P %d %d P CP fill\n",
1120 		x-k-V_xmin, dist - (y+k-V_ymin),
1121 		x-V_xmin,   dist - (y-V_ymin),
1122 		x+k-V_xmin, dist - (y+k-V_ymin));
1123 }
1124 
1125 
1126 /* Draw an arrowhead to the south
1127  * ------------------------------
1128  * with `size' of katheses and color
1129  */
1130 
1131 #ifdef ANSI_C
ps_s_arrowpoint(int x,int y,int size,int c)1132 static void ps_s_arrowpoint(int x,int y,int size,int c)
1133 #else
1134 static void ps_s_arrowpoint(x, y, size, c)
1135 int     x, y, size, c;
1136 #endif
1137 {
1138 	int k;
1139 
1140 	ps_setcolor(c);
1141 
1142 	k = 7*size/10 - 1;
1143 
1144 	FPRINTF(fptr,"NP %d %d M %d %d P %d %d P CP fill\n",
1145 		x-k-V_xmin, dist - (y-k-V_ymin),
1146 		x-V_xmin,   dist - (y-V_ymin),
1147 		x+k-V_xmin, dist - (y-k-V_ymin));
1148 }
1149 
1150 
1151 
1152 /* Draw an arrowhead to the east
1153  * -----------------------------
1154  * with `size' of katheses and color
1155  */
1156 
1157 #ifdef ANSI_C
ps_e_arrowpoint(int x,int y,int size,int c)1158 static void ps_e_arrowpoint(int x,int y,int size,int c)
1159 #else
1160 static void ps_e_arrowpoint(x, y, size, c)
1161 int     x, y, size, c;
1162 #endif
1163 {
1164 	int k;
1165 
1166 	ps_setcolor(c);
1167 
1168 	k = 7*size/10 - 1;
1169 
1170 	FPRINTF(fptr,"NP %d %d M %d %d P %d %d P CP fill\n",
1171 		x-k-V_xmin,   dist - (y-k-V_ymin),
1172 		x-V_xmin,     dist - (y-V_ymin),
1173 		x-k-V_xmin,   dist - (y+k-V_ymin));
1174 }
1175 
1176 
1177 
1178 /* Draw an arrowhead to the west
1179  * -----------------------------
1180  * with `size' of katheses and color
1181  */
1182 
1183 #ifdef ANSI_C
ps_w_arrowpoint(int x,int y,int size,int c)1184 static void ps_w_arrowpoint(int x,int y,int size,int c)
1185 #else
1186 static void ps_w_arrowpoint(x, y, size, c)
1187 int     x, y, size, c;
1188 #endif
1189 {
1190 	int k;
1191 
1192 	ps_setcolor(c);
1193 
1194 	k = 7*size/10 - 1;
1195 
1196 	FPRINTF(fptr,"NP %d %d M %d %d P %d %d P CP fill\n",
1197 		x+k-V_xmin,   dist - (y-k-V_ymin),
1198 		x-V_xmin,     dist - (y-V_ymin),
1199 		x+k-V_xmin,   dist - (y+k-V_ymin));
1200 }
1201 
1202 
1203 /* Draw an arrowhead to the northeast
1204  * ----------------------------------
1205  * with `size' of katheses and color
1206  */
1207 
1208 #ifdef ANSI_C
ps_ne_arrowpoint(int x,int y,int size,int c)1209 static void ps_ne_arrowpoint(int x,int y,int size,int c)
1210 #else
1211 static void ps_ne_arrowpoint(x, y, size, c)
1212 int     x, y, size, c;
1213 #endif
1214 {
1215 	ps_setcolor(c);
1216 
1217 	FPRINTF(fptr,"NP %d %d M %d %d P %d %d P CP fill\n",
1218 		x-size+1-V_xmin, dist - (y-V_ymin),
1219 		x-V_xmin,        dist - (y-V_ymin),
1220 		x-V_xmin,        dist - (y+size-1-V_ymin));
1221 }
1222 
1223 
1224 /* Draw an arrowhead to the northwest
1225  * ----------------------------------
1226  * with `size' of katheses and color
1227  */
1228 
1229 #ifdef ANSI_C
ps_nw_arrowpoint(int x,int y,int size,int c)1230 static void ps_nw_arrowpoint(int x,int y,int size,int c)
1231 #else
1232 static void ps_nw_arrowpoint(x, y, size, c)
1233 int     x, y, size, c;
1234 #endif
1235 {
1236 	ps_setcolor(c);
1237 
1238 	FPRINTF(fptr,"NP %d %d M %d %d P %d %d P CP fill\n",
1239 		x+size-1-V_xmin, dist - (y-V_ymin),
1240 		x-V_xmin,        dist - (y-V_ymin),
1241 		x-V_xmin,        dist - (y+size-1-V_ymin));
1242 }
1243 
1244 
1245 /* Draw an arrowhead to the southeast
1246  * ----------------------------------
1247  * with `size' of katheses and color
1248  */
1249 
1250 #ifdef ANSI_C
ps_se_arrowpoint(int x,int y,int size,int c)1251 static void ps_se_arrowpoint(int x,int y,int size,int c)
1252 #else
1253 static void ps_se_arrowpoint(x, y, size, c)
1254 int     x, y, size, c;
1255 #endif
1256 {
1257 	ps_setcolor(c);
1258 
1259 	FPRINTF(fptr,"NP %d %d M %d %d P %d %d P CP fill\n",
1260 		x-size+1-V_xmin, dist - (y-V_ymin),
1261 		x-V_xmin,        dist - (y-V_ymin),
1262 		x-V_xmin,        dist - (y-size+1-V_ymin));
1263 }
1264 
1265 
1266 /* Draw an arrowhead to the southwest
1267  * ----------------------------------
1268  * with `size' of katheses and color
1269  */
1270 
1271 #ifdef ANSI_C
ps_sw_arrowpoint(int x,int y,int size,int c)1272 static void ps_sw_arrowpoint(int x,int y,int size,int c)
1273 #else
1274 static void ps_sw_arrowpoint(x, y, size, c)
1275 int     x, y, size, c;
1276 #endif
1277 {
1278 	ps_setcolor(c);
1279 
1280 	FPRINTF(fptr,"NP %d %d M %d %d P %d %d P CP fill\n",
1281 		x+size-1-V_xmin, dist - (y-V_ymin),
1282 		x-V_xmin,        dist - (y-V_ymin),
1283 		x-V_xmin,        dist - (y-size+1-V_ymin));
1284 }
1285 
1286 
1287 
1288 /*--------------------------------------------------------------------*/
1289 
1290