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