/* postscript output routine */
#include <stdio.h>
#include <math.h>
#include <string.h>
#define ABS(x) ((x)>=0?(x):-(x))
#define	MIN(a,b) (((a)<(b))?(a):(b))
#define	MAX(a,b) (((a)>(b))?(a):(b))
 extern	int	ifont;
 extern	float	fsized;
 extern int	landscape;
 int	ipen = 7, current_font;
 float	current_font_size;
 static	int	ipost = 0, nline = 0, icnt = 0, vecflag = 0;
 static	float	xq, yq;
 static char	*dname = {"junk.eps"};
 static FILE	*fp=NULL;
 FILE	*fopen();
 int postrawout(char *s);
 int postxlabel(float x, float y, char *label);
 int postylabel(float x, float y, char *label);
 int postytitle(float x, float y, char *label);
 void postfontsize(float x);
 /* added 4/28/2010 */
 int	epsbbx0 = 0, epsbbx1 = 612, epsbby0 = 0, epsbby1 = 792;
 /*------------------------------------------------------------------------*/
int postreset()
 {
 /* used when a postscript command is given before an explicit setup */
 if (ipost == 0) {	/* check if already started up */
   post_startup(dname);
 }
 return 1;
 }
 /*------------------------------------------------------------------------*/
int post_startup(fname)
 char *fname;
 {
 char buf[256];
 if (fname == NULL) fname = dname;
 /* some systems don't like to close non-open files */
 if (fp) fclose(fp);
 if ( (fp = fopen(fname,"w")) == NULL) {
	 printf("can't open the postscript file %s\n", fname); return -1; }
 ipost = 1;
 printf(" postreset, landscape = %d\n", landscape);
 /* some preambles */
 //fputs("%!PS-Adobe-1.0\n", fp);
 /* go to 3.0 so that bounding box is processed by Preview */
 fputs("%!PS-Adobe-3.0 EPSF-3.0\n", fp);
 fputs("%%Creator: ANA generated plot image\n", fp);
 /* allow a different bb, 4/28/2010 */
 snprintf(buf, 255, "%%%%BoundingBox: %04d %04d %04d %04d\n",epsbbx0,epsbby0,epsbbx1,epsbby1);
 fputs(buf, fp);
 //fputs("%%BoundingBox: 0000 0000 0612 0792\n", fp);
 fputs("%%EndComments\n", fp);
 fputs("/M {moveto} bind def /L {lineto} bind def\n", fp);
 fputs("/S {stroke} bind def\n", fp);
 fputs("1 setlinecap 1 setlinejoin 720 720 scale\n", fp);
 /* 4/19/96 changed borders by .25", this was done to have a uniform
 0.5" border for both modes */
 /* the old origin was:
 if (landscape == 0) fputs(".05 .025 translate\n", fp); else
	 fputs("90 rotate .05 -.825 translate\n", fp);
 */
 if (landscape == 0) fputs(".05 .05 translate\n", fp); else
	 fputs("90 rotate .05 -.80 translate\n", fp);
 fputs(".00233 setlinewidth\n", fp);
 /* setup a default font, 24 pt Courier (subject to change) */
 fputs("/Helvetica findfont 0.03333333 scalefont setfont\n", fp);
 /* initialize some variables in PS that are used for plots */
 fputs("/leftmost 1.0 def\n", fp);
 fputs("/botmost 1.0 def\n", fp);
 /* define some special string write routines */
 /* R writes right justified strings */
 fputs("/R {dup stringwidth pop 0 exch sub 0 rmoveto show} bind def\n", fp);
 /* YL writes right justified strings and updates leftmost */
 fputs("/YL {dup stringwidth pop 0 exch sub 0 rmoveto currentpoint pop\n", fp);
 fputs("leftmost lt {/leftmost currentpoint pop def} if show} bind def\n", fp);
 /* C writes centered strings */
 fputs("/C {dup stringwidth pop 2 div 0 exch sub 0 rmoveto show} bind def\n", fp);
 
 icnt = 0;	current_font_size = 1;	current_font = 5;	nline = 0;
 return 1;
 }
 /*------------------------------------------------------------------------*/
void postfontsize(float x)
 {
 if (current_font_size != x) {
 if (nline) { fputs("\n", fp); xyup(); fputs(" S\n", fp); icnt = 0; nline = 0;}
  fprintf(fp, "/Helvetica findfont %f scalefont setfont\n", x*.03333333);
  current_font_size = x; }
 }
 /*------------------------------------------------------------------------*/
int postpen(pen)
 float	pen;
 {
 postreset();	/* start up if not already */
 if (nline) { fputs("\n", fp); xyup(); fputs(" S\n", fp); icnt = 0; nline = 0;}
 fprintf(fp, " %f setlinewidth \n", pen*.00033333);
 /* xyup(); */
 return 1;
 }
 /*------------------------------------------------------------------------*/
int postcolorpen(red, green, blue)
 float	red, green, blue;
 {
 postreset();	/* start up if not already */
 if (nline) { fputs("\n", fp); xyup(); fputs(" S\n", fp); icnt = 0; nline = 0;}
 fprintf(fp, " %f %f %f setrgbcolor \n", red, green, blue);
 /* xyup(); */
 return 1;
 }
 /*------------------------------------------------------------------------*/
int postvec(xin, yin, mode)
 float	xin, yin;
 int	mode;
 {
 postreset();	/* start up if not already */
 vecflag = 1;	/* a flag to allow interleaved plots and images */
 xq = MAX(0., xin);  xq = MIN(xq, .9998);
 yq = MAX(0., yin);  yq = MIN(yq, .9998);
 if (mode == 1) xydown(); else xyup();
 nline++;
 if (nline > 500) {	/* time for a stroke */
 nline = 0;  fputs("\n", fp);  fputs("S\n", fp); icnt = 0;  xyup(); }
 if (icnt > 55) {  fputs("\n", fp); icnt = 0; }
 return 1;
 }
 /*------------------------------------------------------------------------*/
int xyup()
 {
 fprintf(fp," %5.4f %5.4f M", xq, yq);
 icnt += 14;
 }
 /*------------------------------------------------------------------------*/
int xydown()
 {
 fprintf(fp," %5.4f %5.4f L", xq, yq);
 icnt += 14;
 }
 /*------------------------------------------------------------------------*/
int postcopy()
 {
 postreset();	/* start up if not already */
 fputs("\n", fp); icnt = 0;
 if (nline) { fputs(" S\n", fp); }
 fputs(" gsave\n", fp);
 fputs(" showpage\n", fp);
 fputs(" grestore\n", fp);
 return 	1;
 }
 /*------------------------------------------------------------------------*/
int postrawout(char *s)
 {
 postreset();	/* start up if not already */
 if (nline) { fputs("\n", fp); xyup(); fputs(" S\n", fp); icnt = 0; nline = 0;}
 fputs(s, fp);
 nline = 0;  fputs("\n", fp);
 return 	1;
 }
 /*------------------------------------------------------------------------*/
int postxlabel(float x, float y, char *label)
 {
 /*
 printf("postxlabel x,y = %f %f\n",x, y);
 printf("label = %s\n", label);
 */
 postreset();	/* start up if not already */
 if (nline) { fputs(" S\n", fp); }
 nline = 0;
 postfontsize(fsized);	/* check font size */
 fprintf(fp, " %f %f moveto (%s) C \n", x, y, label);
 return 	1;
 }
 /*------------------------------------------------------------------------*/
int postylabel(float x, float y, char *label)
 {
 /*
 printf("postylabel x,y = %f %f\n",x, y);
 printf("label address in postylabel = %d\n",  label);
 printf("label = %s\n", label);
 */
 postreset();	/* start up if not already */
 if (nline) { fputs(" S\n", fp); }
 nline = 0;
 postfontsize(fsized);	/* check font size */
 fprintf(fp, " %f %f moveto (%s) YL \n", x, y, label);
 return 	1;
 }
 /*------------------------------------------------------------------------*/
int postytitle(float x, float y, char *label)
 {
 postreset();	/* start up if not already */
 if (nline) { fputs(" S\n", fp); }
 nline = 0;
 postfontsize(fsized);	/* check font size */
 fprintf(fp, " %f leftmost add %f moveto 90 rotate (%s) C -90 rotate\n"
	 , x, y, label);
 return 	1;
 }
 /*------------------------------------------------------------------------*/
int postgray( barray,nx,ny,xbot,xtop,ybot,ytop,iorder)
 char	*barray;
 int	nx,ny,iorder;
 float	xbot,xtop,ybot,ytop;
 {
 int	matrx[6], i;
 int	c;
 for (i=0;i<6;i++) matrx[i] = 0;
 if (xbot > xtop || ybot > ytop) { printf("illegal image window\n");
	 return -1; }
 postreset();	/* start up if not already */
 if (nline) { fputs("\n", fp); xyup(); fputs(" S\n", fp); icnt = 0; nline = 0;}
 fputs(" gsave\n", fp);
 fprintf(fp," /picstr %d string def ",nx);
 fprintf(fp,"%7.4f %7.4f translate\n",xbot,ybot);
 fprintf(fp,"%7.4f %7.4f scale ",xtop-xbot,ytop-ybot);
 fprintf(fp,"%d %d 8\n",nx,ny);
 switch (iorder) {
 case 0: matrx[0] = nx;	matrx[3] = ny;	break;
 case 1: matrx[1] = ny;	matrx[2] = nx;	break;
 case 2: matrx[0] = nx;	matrx[5] = ny;	matrx[3] = -ny;	break;
 case 3: matrx[1] = ny;	matrx[4] = nx;	matrx[2] = -nx;	break;
 case 4: matrx[4] = nx;	matrx[3] = ny;	matrx[0] = -nx;	break;
 case 5: matrx[5] = ny;	matrx[2] = nx;	matrx[1] = -ny;	break;
 case 6: matrx[4] = nx;	matrx[5] = ny;	matrx[3] = -ny;	matrx[0] = -nx;	break;
 case 7: matrx[5] = ny;	matrx[1] = -nx;	matrx[2] = -nx;	matrx[4] = ny;	break;
 }
 fprintf(fp,"[ %d %d %d %d %d %d ]\n",matrx[0],matrx[1],matrx[2],matrx[3],
	 matrx[4],matrx[5]);
 fputs(" {currentfile picstr readhexstring pop} image\n", fp);
 for (i=1;i<=(nx*ny);i++) {c = *barray++; c &= 0xff; fprintf(fp,"%02.2x",c);
	 if (i%40 == 0) fprintf(fp, "\n");}
 if (i%40 != 0) fprintf(fp, "\n");
 fputs(" grestore\n", fp);
 return 1;
 }
 /*------------------------------------------------------------------------*/
// int postcolor_nonlaced( rarray,garray,barray,nx,ny,xbot,xtop,ybot,ytop,iorder)
//  /* color postscript image */
//  char	*rarray,*garray,*barray;
//  int	nx,ny,iorder;
//  float	xbot,xtop,ybot,ytop;
//  {
//  int	matrx[6], i;
//  int	c;
//  for (i=0;i<6;i++) matrx[i] = 0;
//  if (xbot > xtop || ybot > ytop) { printf("illegal image window\n");
// 	 return -1; }
//  postreset();	/* start up if not already */
//  if (nline) { fputs("\n", fp); xyup(); fputs(" S\n", fp); icnt = 0; nline = 0;}
//  fputs(" gsave\n", fp);
//  fprintf(fp," /picstrr %d string def\n",nx);
//  fprintf(fp," /picstrg %d string def\n",nx);
//  fprintf(fp," /picstrb %d string def\n",nx);
//  fprintf(fp,"%7.4f %7.4f translate\n",xbot,ybot);
//  fprintf(fp,"%7.4f %7.4f scale ",xtop-xbot,ytop-ybot);
//  fprintf(fp,"%d %d 8\n",nx,ny); /* 8 bits per color */
//  switch (iorder) {
//  case 0: matrx[0] = nx;	matrx[3] = ny;	break;
//  case 1: matrx[1] = ny;	matrx[2] = nx;	break;
//  case 2: matrx[0] = nx;	matrx[5] = ny;	matrx[3] = -ny;	break;
//  case 3: matrx[1] = ny;	matrx[4] = nx;	matrx[2] = -nx;	break;
//  case 4: matrx[4] = nx;	matrx[3] = ny;	matrx[0] = -nx;	break;
//  case 5: matrx[5] = ny;	matrx[2] = nx;	matrx[1] = -ny;	break;
//  case 6: matrx[4] = nx;	matrx[5] = ny;	matrx[3] = -ny;	matrx[0] = -nx;	break;
//  case 7: matrx[5] = ny;	matrx[1] = -nx;	matrx[2] = -nx;	matrx[4] = ny;	break;
//  }
//  fprintf(fp,"[ %d %d %d %d %d %d ]\n",matrx[0],matrx[1],matrx[2],matrx[3],
// 	 matrx[4],matrx[5]);
//  fputs(" {currentfile picstrr readhexstring pop}\n", fp);
//  fputs(" {currentfile picstrg readhexstring pop}\n", fp);
//  fputs(" {currentfile picstrb readhexstring pop} true 3 colorimage\n", fp);
//  /* non-interlaced */
//  for (i=1;i<=(nx*ny);i++) {c = *rarray++; c &= 0xff; fprintf(fp,"%02.2x",c);
//  if (i%40 == 0) fprintf(fp, "\n");}
//  if (i%40 != 0) fprintf(fp, "\n");
//  for (i=1;i<=(nx*ny);i++) {c = *garray++; c &= 0xff; fprintf(fp,"%02.2x",c);
//  if (i%40 == 0) fprintf(fp, "\n");}
//  if (i%40 != 0) fprintf(fp, "\n");
//  for (i=1;i<=(nx*ny);i++) {c = *barray++; c &= 0xff; fprintf(fp,"%02.2x",c);
//  if (i%40 == 0) fprintf(fp, "\n");}
//  if (i%40 != 0) fprintf(fp, "\n");
//  fputs(" grestore\n", fp);
//  return 1;
//  }
 /*------------------------------------------------------------------------*/
int postcolor(rarray,garray,barray,nx,ny,xbot,xtop,ybot,ytop,iorder,mode)
 /* color postscript image */
 unsigned char	*rarray, *garray, *barray;
 int	nx, ny, iorder, mode;
 float	xbot, xtop, ybot, ytop;
 {
 int	matrx[6], i;
 unsigned char	c;
 //int	c;
 for (i=0;i<6;i++) matrx[i] = 0;
 if (xbot > xtop || ybot > ytop) { printf("illegal image window\n");
	 return -1; }
 postreset();	/* start up if not already */
 if (nline) { fputs("\n", fp); xyup(); fputs(" S\n", fp); icnt = 0; nline = 0;}
 fputs(" gsave\n", fp);
 fprintf(fp," /picstr %d string def ",nx);
 fprintf(fp,"%7.4f %7.4f translate\n",xbot,ybot);
 fprintf(fp,"%7.4f %7.4f scale ",xtop-xbot,ytop-ybot);
 fprintf(fp,"%d %d 8\n",nx,ny); /* 8 bits per color */
 switch (iorder) {
 case 0: matrx[0] = nx;	matrx[3] = ny;	break;
 case 1: matrx[1] = ny;	matrx[2] = nx;	break;
 case 2: matrx[0] = nx;	matrx[5] = ny;	matrx[3] = -ny;	break;
 case 3: matrx[1] = ny;	matrx[4] = nx;	matrx[2] = -nx;	break;
 case 4: matrx[4] = nx;	matrx[3] = ny;	matrx[0] = -nx;	break;
 case 5: matrx[5] = ny;	matrx[2] = nx;	matrx[1] = -ny;	break;
 case 6: matrx[4] = nx;	matrx[5] = ny;	matrx[3] = -ny;	matrx[0] = -nx;	break;
 case 7: matrx[5] = ny;	matrx[1] = -nx;	matrx[2] = -nx;	matrx[4] = ny;	break;
 }
 fprintf(fp,"[ %d %d %d %d %d %d ]\n",matrx[0],matrx[1],matrx[2],matrx[3],
	 matrx[4],matrx[5]);
 fputs(" {currentfile picstr readhexstring pop} false 3 colorimage\n", fp);
 /* interlaced */
 /* support 2 input variations */
 switch (mode) {
 case 0:
   for (i=1;i<=(nx*ny);i++) {
   c = *rarray++; fprintf(fp,"%02.2x",c);
   c = *garray++; fprintf(fp,"%02.2x",c);
   c = *barray++; fprintf(fp,"%02.2x",c);
// 	c = *rarray++; c &= 0xff; fprintf(fp,"%02.2x",c);
// 	c = *garray++; c &= 0xff; fprintf(fp,"%02.2x",c);
// 	c = *barray++; c &= 0xff; fprintf(fp,"%02.2x",c);
   if (i%12 == 0) fprintf(fp, "\n");
   }
   if (i%12 != 0) fprintf(fp, "\n");
   break;
 case 1:
   for (i=1;i<=(3*nx*ny);i++) {
   c = *rarray++; fprintf(fp,"%02.2x",c);
//	c = *rarray++; c &= 0xff; fprintf(fp,"%02.2x",c);
   if (i%72 == 0) fprintf(fp, "\n");
   }
   if (i%72 != 0) fprintf(fp, "\n");
   break;
 }
 fputs(" grestore\n", fp);
 return 1;
 }
 /*------------------------------------------------------------------------*/
int postrelease()
 {
 if (ipost) {
 fputs("\n", fp); icnt = 0;
 if (nline) { fputs(" stroke\n", fp); }
 fputs(" showpage\n", fp);
 fclose(fp);
 }
 ipost = 0;
 return 	1;
 }
 /*------------------------------------------------------------------------*/
