1 /*  Copyright (C) 1988-2005 by Brian Doty and the Institute
2                   of Global Environment and Society (IGES).
3 
4     See file COPYRIGHT for more information.   */
5 
6 /* Routines related to hardcopy (metafile) output. */
7 /* kk 020624 --- change for 64bit seek K.Komine mf */
8 
9 #ifdef HAVE_CONFIG_H
10 #include <config.h>
11 
12 /* If autoconfed, only include malloc.h when it's presen */
13 #ifdef HAVE_MALLOC_H
14 #include <malloc.h>
15 #endif
16 
17 #else /* undef HAVE_CONFIG_H */
18 
19 #include <malloc.h>
20 
21 #endif /* HAVE_CONFIG_H */
22 
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <math.h>
26 #include "gx.h"
27 
28 static int bopt=BUFOPT;                   /* Buffering option   */
29 static long buffsz;                       /* metafile buffer size, formerly known as HBUFSZ */
30 static int bflag;                         /* Buffering disabled */
31 static int hflag;                         /* File output enabled*/
32 static int herr;                          /* Fatal error        */
33 static int hferr;                         /* File I/O error     */
34 static int hpflg;                         /* User printed frame */
35 static short *hbuff, *hpnt, *hend;        /* Current buffer ptrs*/
36 static FILE *hfile;                       /* meta file pointer  */
37 static int hpos;                          /* Frame pos in metafi*/
38 static short *bufs[250];                  /* Buffer stuff       */
39 static short *bufs2[250];                 /*   Enough for 50MB  */
40 static int lens[250],lens2[250];
41 static int pnt,pnt2,pntf;
42 
43 static int dbmode;                        /* Double Buffer mode */
44 
45 static float xrsize,yrsize;
46 
47 void xycnv (short, short, float *, float *);
48 
49 /* Specify on startup what sort of buffering we want.
50    We can do memory buffering (the default on UNIX machines)
51    or file buffering, done only when print is enabled */
52 
gxhopt(int flag)53 void gxhopt (int flag) {
54   bopt = flag;
55 }
56 
57 /* Initialize any buffering, etc. when GrADS starts up */
58 
gxhnew(float xsiz,float ysiz,int hbufsz)59 void gxhnew (float xsiz, float ysiz, int hbufsz) {
60   buffsz = hbufsz;
61   xrsize = xsiz;
62   yrsize = ysiz;
63   hflag = 0;
64   herr = 0;
65   hferr = 0;
66   hpflg = 0;
67   dbmode = 0;
68   if (bopt) bflag = 1;
69   else {
70     hbuff = (short *)malloc(sizeof(short)*buffsz);
71     if (hbuff==NULL) {
72       printf ("Unable to allocate memory for metafile operations.\n");
73       herr = 1;
74       bufs[0] = NULL;
75     } else {
76       bflag = 0;
77       pnt = 1;
78       bufs[0] = hbuff;
79       hpnt = hbuff;
80       hend = hbuff+(buffsz-10L);
81     }
82   }
83   pnt2 = 0;
84 }
85 
86 /* Enable hardcopy (metafile) output.   */
87 
gxhbgn(char * fname)88 int gxhbgn (char *fname) {
89 int i,xx,rc;
90 short bb[3];
91 
92   if (hferr) {
93     printf ("Metafile error state is positive.\n");
94     printf ("Disable Print before attempting an Enable Print.\n");
95     return (0);
96   }
97 
98   /* Open metafile if not already open.  */
99 
100   if (hflag) {
101     printf ("Metafile already open\n");
102     return(0);
103   }
104 
105   hfile = fopen(fname,"wb");
106   if (hfile==NULL) {
107     printf ("Error opening meta file %s \n", fname);
108     return (1);
109   }
110 
111   /* Allocate the memory buffer if we are doing file buffering.  */
112 
113   if (bopt) {
114     hbuff = (short *)malloc(sizeof(short)*buffsz);
115     if (hbuff==NULL) {
116       printf ("Unable to allocate memory for metafile operations.\n");
117       fclose(hfile);
118       return (1);
119     }
120     hpnt = hbuff;
121     hend = hbuff+(buffsz-10L);
122     bflag = 0;
123   }
124 
125   /* Write physical page size to output metafile */
126 
127   bb[0] = -1;
128   xx = (int)(xrsize*1000.0+0.5);
129   if (xx<0) xx=0;
130   if (xx>32760) xx=32760;
131   bb[1] = xx;
132   xx = (int)(yrsize*1000.0+0.5);
133   if (xx<0) xx=0;
134   if (xx>32760) xx=32760;
135   bb[2] = xx;
136   rc = gxhwri(bb, 3);
137   if (rc) return (1);
138   hpos = ftell(hfile);
139   herr = 0;
140   hpflg = 0;
141   hferr = 0;
142   hflag = 1;
143   if (bopt) {
144     printf ("File buffering enabled. ");
145     printf ("Issue CLEAR command to start buffering.\n");
146   }
147   return (0);
148 }
149 
150 /* Metafile output, command with 0 args */
151 
hout0(int cmd)152 void hout0 (int cmd) {
153   if (bflag||herr) return;
154   *hpnt = cmd;
155   hpnt++;
156   if (hpnt>hend) hfull();
157 }
158 
159 /* Metafile output, command plus one integer argument */
160 
hout1(int cmd,int opt)161 void hout1 (int cmd, int opt) {
162   if (bflag||herr) return;
163   *hpnt = cmd;
164   hpnt++;
165   *hpnt = opt;
166   hpnt++;
167   if (hpnt>hend) hfull();
168 }
169 
170 /* Metafile output, command plus two floating point args */
171 
hout2(int cmd,float x,float y)172 void hout2 (int cmd, float x, float y) {
173 int xx,yy;
174   if (bflag||herr) return;
175   *hpnt = cmd;
176   hpnt++;
177   xx = (int)(x*1000.0+0.5);
178   if (xx<0) xx=0;
179   if (xx>32760) xx=32760;
180   *hpnt = xx;
181   hpnt++;
182   yy = (int)(y*1000.0+0.5);
183   if (yy<0) yy=0;
184   if (yy>32760) yy=32760;
185   *hpnt = yy;
186   hpnt++;
187   if (hpnt>hend) hfull();
188 }
189 
190 /* Metafile output, command plus two integer args */
191 
hout2i(int cmd,int i1,int i2)192 void hout2i (int cmd, int i1, int i2) {
193 
194   if (bflag||herr) return;
195   *hpnt = cmd;
196   hpnt++;
197   *hpnt = i1;
198   hpnt++;
199   *hpnt = i2;
200   hpnt++;
201   if (hpnt>hend) hfull();
202 }
203 
204 /* Metafile output, command plus three integer args */
205 
hout3i(int cmd,int i1,int i2,int i3)206 void hout3i (int cmd, int i1, int i2, int i3) {
207 
208   if (bflag||herr) return;
209   *hpnt = cmd;
210   hpnt++;
211   *hpnt = i1;
212   hpnt++;
213   *hpnt = i2;
214   hpnt++;
215   *hpnt = i3;
216   hpnt++;
217   if (hpnt>hend) hfull();
218 }
219 
220 /* Metafile output, command plus four integer args */
221 
hout4i(int cmd,int i1,int i2,int i3,int i4)222 void hout4i (int cmd, int i1, int i2, int i3, int i4) {
223 
224   if (bflag||herr) return;
225   *hpnt = cmd;
226   hpnt++;
227   *hpnt = i1;
228   hpnt++;
229   *hpnt = i2;
230   hpnt++;
231   *hpnt = i3;
232   hpnt++;
233   *hpnt = i4;
234   hpnt++;
235   if (hpnt>hend) hfull();
236 }
237 
238 /* Metafile output, command plus four floating args */
239 
hout4(int cmd,float xl,float xh,float yl,float yh)240 void hout4 (int cmd, float xl, float xh, float yl, float yh) {
241 int vv;
242   if (bflag||herr) return;
243   *hpnt = cmd;
244   hpnt++;
245   vv = (int)(xl*1000.0+0.5);
246   if (vv<0) vv=0;
247   if (vv>32760) vv=32760;
248   *hpnt = vv;
249   hpnt++;
250   vv = (int)(xh*1000.0+0.5);
251   if (vv<0) vv=0;
252   if (vv>32760) vv=32760;
253   *hpnt = vv;
254   hpnt++;
255   vv = (int)(yl*1000.0+0.5);
256   if (vv<0) vv=0;
257   if (vv>32760) vv=32760;
258   *hpnt = vv;
259   hpnt++;
260   vv = (int)(yh*1000.0+0.5);
261   if (vv<0) vv=0;
262   if (vv>32760) vv=32760;
263   *hpnt = vv;
264   hpnt++;
265   if (hpnt>hend) hfull();
266 }
267 
268 /* Handle situation where memory buffer is full.  Either output
269    to the temporary file buffer, or disable additional input
270    into the memory buffer. */
271 
hfull(void)272 void hfull (void) {
273 int len,rc;
274 
275   if (bopt) {
276     len = hpnt - hbuff;
277     rc = gxhwri(hbuff, len);
278     if (rc) return;
279     else hpnt = hbuff;
280   } else {
281     if (dbmode && pntf==1) {
282       lens2[pnt2-1] = hpnt-hbuff;
283       if (pnt2>249) {
284         printf ("Out of buffer space\n");
285         herr=1;
286         return;
287       }
288       hbuff = (short *)malloc(sizeof(short)*buffsz);
289       if (hbuff==NULL) {
290         printf ("Memory allocation error for metafile buffers.\n");
291         herr = 1;
292       } else {
293         bufs2[pnt2] = hbuff;
294         hpnt = hbuff;
295         hend = hbuff+(buffsz-10L);
296         pnt2++;
297       }
298     } else {
299       if (pnt>249) {
300         printf ("Out of buffer space\n");
301         herr=1;
302         return;
303       }
304       lens[pnt-1] = hpnt-hbuff;
305       hbuff = (short *)malloc(sizeof(short)*buffsz);
306       if (hbuff==NULL) {
307         printf ("Memory allocation error for metafile buffers.\n");
308         herr = 1;
309       } else {
310         bufs[pnt] = hbuff;
311         hpnt = hbuff;
312         hend = hbuff+(buffsz-10L);
313         pnt++;
314       }
315     }
316   }
317 }
318 
319 /* Output the current frame to the metafile.   Empty the metafile
320    buffer, and set things so that the frame will be marked on a
321    frame action */
322 
323 #ifdef PRINT_EPS
gxhprt(char * cmd)324 void gxhprt (char *cmd) {
325 #else
326 void gxhprt (void) {
327 #endif
328 int len,i,rc;
329 short hbf[256];
330 
331 #ifdef PRINT_EPS
332   if (bopt && dbmode) {
333     printf ("Cannot print while in double-buffer mode ");
334     printf ("when using file buffering\n");
335     return;
336   }
337 #ifndef STNDALN
338   if(!hflag) { /* No metafile open write a EPS file using gxeps */
339     gxheps(cmd);
340     return;
341   }
342 #endif
343 #endif
344   if (herr||hferr) {
345     printf ("Error status on print metafile is positive.\n");
346     printf ("Cannot print current frame.\n");
347     return;
348   }
349   if (!hflag) {
350     printf ("Metafile not currently open\n");
351     return;
352   }
353 #ifndef PRINT_EPS
354   if (bopt && dbmode) {
355     printf ("Cannot print while in double-buffer mode ");
356     printf ("when using file buffering\n");
357     return;
358   }
359 #endif
360   if (bopt) {
361     len = hpnt - hbuff;
362     rc = gxhwri(hbuff,len);
363     if (rc) return;
364     else hpnt = hbuff;
365   } else {
366     if (dbmode && pntf==0) {
367       i = 0;
368       while (i<pnt2) {
369         rc = gxhwri(bufs2[i],lens2[i]);
370         if (rc) return;
371         i++;
372       }
373     } else {
374       if (!dbmode) lens[pnt-1] = hpnt-hbuff;
375       i = 0;
376       while (i<pnt) {
377         rc = gxhwri(bufs[i],lens[i]);
378         if (rc) return;
379         i++;
380       }
381     }
382   }
383   hpflg = 1;
384   hpos = ftell(hfile);
385   return;
386 }
387 
388 /* Write to output metafile */
389 
390 int gxhwri (void *buf, int len) {
391 /* kk 020624 --- s */
392 /*  if (len>0) fwrite (buf, sizeof(short), len, hfile); */
393   if (len>0) fwrite (buf, sizeof(short)*len, 1, hfile);
394 /* kk 020624 --- e */
395   if (ferror(hfile)) {
396     printf ("I/O Error writing to print metafile.\n");
397     fclose(hfile);
398     hferr = 1;
399     hflag = 0;
400     hpflg = 0;
401     if (bopt) {
402       free(hbuff);
403       herr = 1;
404       bflag = 1;
405     }
406     return (1);
407   }
408   return (0);
409 }
410 
411 /* Close the metafile output file without further output */
412 
413 void gxhend (void) {
414 short bb[2];
415 int rc;
416   if (hferr) {
417     printf ("Resetting print metafile error status.\n");
418     hferr = 0;
419     if (bopt) herr = 0;
420     return;
421   }
422   if (!hflag) {
423     printf ("No hardcopy metafile open\n");
424     return;
425   }
426   fseek(hfile,hpos,0L);
427   if (hpflg) {
428     bb[0] = -2;
429     bb[1] = -9;
430     rc = gxhwri(bb,2);
431   } else {
432     bb[0] = -9;
433     rc = gxhwri(bb,1);
434   }
435   if (!rc) {
436     fclose(hfile);
437     printf ("Hardcopy output file is closed \n");
438     hflag = 0;
439     if (bopt) {
440       free(hbuff);
441       bflag = 1;
442     }
443   }
444 }
445 
446 /* User has issued a clear.  Mark an end of frame if needed in
447    the output file; free buffers if we are in memory buffering
448    mode */
449 
450 void gxhfrm (int iact) {
451 short bb;
452 int rc,i;
453 
454   if (hflag) {
455     fseek(hfile,hpos,0L);
456     if (hpflg) {
457       bb = -2;
458       rc = gxhwri(&bb, 1);
459       hpflg = 0;
460       if (!rc) hpos = ftell(hfile);
461     }
462   }
463   if (iact==2 && dbmode==0) {
464     dbmode = 1;
465     if (bopt==0) {
466       hbuff = (short *)malloc(sizeof(short)*buffsz);
467       if (hbuff==NULL) {
468         printf ("Memory allocation error for metafile buffers.\n");
469         herr = 1;
470         pnt2 = 0;
471         bufs2[0] = NULL;
472       } else {
473         pnt2 = 1;
474         pntf = 1;
475         bufs2[0] = hbuff;
476       }
477     }
478   }
479   if (iact!=2 && dbmode==1) {
480     dbmode = 0;
481     if (bopt==0) {
482       for (i=0; i<pnt2; i++) free(bufs2[i]);
483       pnt2 = 0;
484     }
485   }
486   if (bopt==0) {
487     if (dbmode) {
488       if (pntf==0) {
489         lens[pnt-1] = hpnt-hbuff;
490         for (i=1; i<pnt2; i++) free(bufs2[i]);
491         pntf = 1;
492         pnt2 = 1;
493         hbuff = bufs2[0];
494         hpnt = hbuff;
495         hend = hbuff+(buffsz-10L);
496       } else {
497         lens2[pnt2-1] = hpnt-hbuff;
498         for (i=1; i<pnt; i++) free(bufs[i]);
499         pntf = 0;
500         pnt = 1;
501         hbuff = bufs[0];
502         hpnt = hbuff;
503         hend = hbuff+(buffsz-10L);
504       }
505     } else {
506       for (i=1; i<pnt; i++) {
507         free(bufs[i]);
508       }
509       pnt = 1;
510       hbuff = bufs[0];
511       hpnt = hbuff;
512       hend = hbuff+(buffsz-10L);
513     }
514     if (herr && bufs[0] && !dbmode) herr = 0;
515   } else hpnt = hbuff;
516 }
517 
518 /* Redraw based on contents of current buffers */
519 
520 void gxhdrw (int dbflg) {
521 short *poi,*pend;
522 int cmd, i, j, cnt, flag, ii, siz;
523 int lcolor,lwide,fflag,xyc;
524 float xlo,xhi,ylo,yhi,xpos,ypos,*xybuf;
525 
526   if (dbflg && !dbmode) {
527     printf ("Logic error 0 in Redraw.  Contact Developer.\n");
528     return;
529   }
530 
531   if (dbmode && pntf==1) {
532     lens2[pnt2-1] = hpnt-hbuff;
533     cnt = pnt2; flag = 1;
534     if (dbflg) {cnt = pnt; flag = 0;}
535   } else {
536     lens[pnt-1] = hpnt-hbuff;
537     cnt = pnt; flag = 0;
538     if (dbflg) {cnt = pnt2; flag = 1;}
539   }
540 
541   gxsfrm ();
542   fflag = 0;
543 
544   for (ii=0; ii<cnt; ii++) {
545     if (flag) {
546       poi = bufs2[ii];
547       pend = poi + lens2[ii];
548     } else {
549       poi = bufs[ii];
550       pend = poi + lens[ii];
551     }
552 
553     while (poi<pend) {
554 
555       /* Get message type */
556 
557       cmd = *poi;
558 
559       /* Handle various message types */
560       /* -9 is end of file.  Should not happen. */
561 
562       if (cmd==-9) {
563         printf ("Logic Error 4 in Redraw.  Notify Developer\n");
564         return;
565       }
566 
567       /*  -1 indicates start of file.  Should not ocurr. */
568 
569       else if (cmd==-1) {
570         printf ("Logic Error 8 in Redraw.  Notify Developer\n");
571         return;
572       }
573 
574       /* -2 indicates new frame.  Also should not ocurr */
575 
576       else if (cmd==-2) {
577         printf ("Logic Error 12 in Redraw.  Notify Developer\n");
578         return;
579       }
580 
581       /* -3 indicates new color.  One arg; color number.  */
582 
583       else if (cmd==-3) {
584         lcolor = *(poi+1);
585         gxdcol (lcolor);
586         poi += 2;
587       }
588 
589       /* -4 indicates new line thickness.  It has two arguments */
590 
591       else if (cmd==-4) {
592         i = *(poi+2);
593         gxdwid(i);
594         poi += 3;
595       }
596 
597       /*  -5 defines a new color, in rgb.  It has four int args */
598 
599       else if (cmd==-5){
600         gxdacl ((int)*(poi+1),(int)*(poi+2),(int)*(poi+3),(int)*(poi+4));
601         poi += 5;
602       }
603 
604       /* -6 is for a filled rectangle.  It has four float args. */
605 
606       else if (cmd==-6){
607         xycnv (*(poi+1),*(poi+3),&xlo,&ylo);
608         xycnv (*(poi+2),*(poi+4),&xhi,&yhi);
609         gxdrec(xlo,xhi,ylo,yhi);
610         poi += 5;
611       }
612 
613       /* -7 indicates the start of a polygon fill.  It has one arg. */
614 
615       else if (cmd==-7){
616         siz = *(poi+1);
617         xybuf = (float *)malloc(sizeof(float)*siz*2);
618         if (xybuf==NULL) {
619           printf ("Memory allocation error: Redraw\n");
620           return;
621         }
622         fflag = 1;
623         xyc = 0;
624         poi += 2;
625       }
626 
627       /* -8 is to terminate polygon fill.  It has no args */
628 
629       else if (cmd==-8){
630         gxdfil (xybuf,xyc);
631         if (xybuf==NULL) {
632           printf ("Logic Error 16 in Redraw.  Notify Developer\n");
633           return;
634         } else free (xybuf);
635         fflag = 0;
636         poi += 1;
637       }
638 
639       /* -10 is a move to instruction.  It has two float args */
640 
641       else if (cmd==-10){
642         xycnv (*(poi+1),*(poi+2),&xpos,&ypos);
643         if (fflag) {
644           *(xybuf+xyc*2) = xpos;
645           *(xybuf+xyc*2+1) = ypos;
646           xyc++;
647         } else gxdmov(xpos,ypos);
648         poi += 3;
649       }
650 
651       /*  -11 is draw to.  It has two float args. */
652 
653       else if (cmd==-11){
654         xycnv (*(poi+1),*(poi+2),&xpos,&ypos);
655         if (fflag) {
656           xybuf[xyc*2] = xpos;
657           xybuf[xyc*2+1] = ypos;
658           xyc++;
659         } else gxddrw(xpos,ypos);
660         poi += 3;
661       }
662 
663       /* -12 indicates new fill pattern.  It has three arguments. */
664 
665       else if (cmd==-12) {
666         gxdptn ((int)*(poi+1),(int)*(poi+2),(int)*(poi+3));
667         poi += 4;
668       }
669 
670       /* -20 is a draw widget.  We will redraw it in current state. */
671 
672       else if (cmd==-20) {
673         gxdpbn ((int)*(poi+1),NULL,1,0,-1);
674         poi += 2;
675       }
676 
677       /* Any other command would be invalid */
678 
679       else {
680         printf ("Logic Error 20 in Redraw.  Notify Developer\n");
681         return;
682       }
683     }
684   }
685 }
686 
687 void xycnv (short ix, short iy, float *x, float *y) {
688 
689   *x = ((float)ix)/1000.0;
690   *y = ((float)iy)/1000.0;
691 }
692 
693 #if GXPNG==1
694 #include "gxhpng.c"
695 #endif
696 #ifdef PRINT_EPS
697 #ifndef STNDALN
698 #  define GXHEPS
699 #  include "gxeps.c"
700 
701 #endif
702 #endif /* PRINT_EPS */
703