/*
 * Copyright 1988 Anant Agarwal
 *
 * Permission to use, copy, modify, and distribute this software and its
 * documentation for any purpose and without fee is hereby granted, provided
 * that the above copyright notice appear in all copies and that both that
 * copyright notice and this permission notice appear in supporting
 * documentation.  No representations about the suitability of this software
 * for any purpose.  It is provided "as is" without express or implied 
 * warranty.
 *
 * Author:  Anant Agarwal, MIT Laboratory for Computer Science
 */

#include <stdio.h>
#include "defs.h"
#include "plotio.h"
#include "structs.h"
#include "plot.h"

extern FILE *fout;
static char*     currFont = NULL;
static int       currSize = -1;
static LineType  currLine = none;
static double	 currThick = -2.0;
static double	 currGray = 0.0;
static InterpType currInterp = linearinterp;
static char*     symbFont = "SYM";

static double currSSfreq=30.0, currSSang = 0.0; /* for setscreen */
static int currSSfnIndex = 0;
static boolean currShowLine = TRUE;
char SSpop[] = "pop", SScross[] = "cross";
char *SSFNS[MAXSSFNS] = {
SSpop, SScross
};

private boolean FirstFill = FALSE;
private boolean AxisLine = FALSE;/* for axis join */
private double  v[2];/* to hold curpoint for objcurtext */

private double fp[2];/* to hold first point of a curve  */
private double lp[2];/* to hold last point of a curve  */

sendpsf(p)
LocalObjectType *p;
{
  switch( p->name )
  {
  case objline :
	if( currLine != p->un.line.line || currThick != p->un.line.thick 
		|| currGray != p->gray) setConstsForCurve(p);
		/* set currLine, currThick, currGray, and */
		/*  currInterp (unused in objline) 	  */
       	if ((currLine != none)&&(currLine != fill))
       	{
         	if (AxisLine) fprintf(fout,"2 setlinecap\n");
         	fprintf( fout,"%lg %lg ", p->from[xpt], p->from[ypt] );
	        fprintf( fout,"%lg %lg \n", 
			p->un.line.to[xpt], p->un.line.to[ypt]);
		 if (currGray > 0)
			fprintf( fout,"%f G9 L9 %f G9\n", currGray, 0.0);
		 else
			fprintf( fout,"L9\n");
	         if (AxisLine)
		 {
			 fprintf(fout,"0 setlinecap\n");
			 AxisLine = FALSE;
		 }
	}
       	else if (currLine == fill) dofill(p, currGray);
  break;
  case objCurLine :/* delta points only sent */
       	if( currLine != p->un.line.line || currThick != p->un.line.thick 
		|| currGray != p->gray || currInterp != p->un.line.interp)
		setConstsForCurve(p);
	lp[xpt] = p->un.line.to[xpt];
	lp[ypt] = p->un.line.to[ypt];
	if( currLine != none )
       	{
	 	switch(currInterp)
	 	{
	  	case smooth:
            		fprintf( fout,"%lg %lg ns\n",
			p->un.line.to[xpt], p->un.line.to[ypt]);
	  	break;
	  	default:
            		fprintf( fout,"%lg %lg M9\n",
			p->un.line.to[xpt], p->un.line.to[ypt]);
	  	break;
	 	}
	 	/* note that "from" is still available, although unused here*/
       	}
	break;
  case objsymbol :
       	if( currFont != symbFont || currSize != p->un.symbol.fontsize )
		setConstsForSymbol(p);
       	if (p->un.symbol.symbol != nonesymbol)
       	{
		fprintf( fout, "<%02x> ", (int) (p->un.symbol.symbol ) );
	       	fprintf( fout,"%lg %lg SY\n", p->from[xpt], p->from[ypt] );
       	}
  break;
  case objtext :
       	if( currFont != p->un.text.FF || currSize != p->un.text.fontsize )
		setConstsForText(p);
       	fprintf( fout, "(%s) %lg ", p->un.text.StrPtr, p->un.text.angle );
       	fprintf( fout,"%lg %lg ", p->from[xpt], p->from[ypt] );
       	v[xpt] = p->from[xpt];/* store start point for objCurText */
       	v[ypt] = p->from[ypt];
       	switch( p->un.text.align )
       	{
	case left:
	   	fprintf( fout, "TXL\n" );
	break;
	case center:
	   	fprintf( fout, "TXC\n" );
	break;
	case right:
	   	fprintf( fout, "TXR\n" );
	break;
       	}
  break;
  case objCurText :
       	if( currFont != p->un.text.FF || currSize != p->un.text.fontsize )
		setConstsForText(p);
 	fprintf( fout, "%d /%s SetTxt\n", currSize, currFont );
       	fprintf( fout, "(%s) %lg ", p->un.text.StrPtr, p->un.text.angle );
        fprintf( fout,"%lg %lg ", v[xpt], v[ypt] );

       	if ((p->un.text.Sp == pls)||(p->un.text.Sp == mns))
       	  	fprintf( fout, "/psy psy %lg add def ", p->un.text.up);
       	fprintf( fout, "TXREL\n" );
       	if ((p->un.text.Sp == pls)||(p->un.text.Sp == mns))
       	  	fprintf( fout, "/psy psy %lg sub def\n", p->un.text.up);
  break;
  case objLineStartFlag :
        fp[xpt] = p->from[xpt];
        fp[ypt] = p->from[ypt];
	switch(p->un.line.interp)
	{
	case smooth:
	    	fprintf(   fout,"%lg %lg ms\n",p->from[xpt], p->from[ypt]);
	break;
	default: 
	    	fprintf(   fout,"%lg %lg S9\n",p->from[xpt], p->from[ypt]);
	break;
	}
	/* set screen constants for this curve if fill */
	if (p->un.line.line == fill)
		setConstsForScreen(p);
  break;
  case objLineEndFlag :
	currGray = p->gray;
	if ((currLine != none)&&(currLine != fill))
	if (currGray > 0) /* note D9 same as fs = stroke */
		if (p->un.line.interp == smooth)
			fprintf   (fout,"nsend\n%f G9 D9 0.0 G9\n",currGray);
		else
			fprintf   (fout,"%f G9 D9 0.0 G9\n",currGray);
	else
		if (p->un.line.interp == smooth) fprintf(fout,"nsend\nD9\n");
		else fprintf(fout,"D9\n");

	/*  fill stuff  */
	if (currLine == fill) dofillcur(p, currGray);
  break;
  case objflagaxes: 
	AxisLine = TRUE;
  break;
  case objflagcurves: 
  case objflagkey: 
	InitScreenConsts();
  break;
  case objflag: 
  case objflagtext: 
  case objTextStartFlag: 
  case objTextEndFlag: 
  case objdummy: 
  break;
  default:
       	fprintf( stderr, "sendpsf: Internal Error\n" );
  }
}

WhiteOut()
{
double x,y;
	x = translate;
	y = translate;
	fprintf(fout,"%f %f ",x,y);

	x = translate + graphsize[xpt] * 72.0 / 2.54;
	y = translate;
	fprintf(fout,"%f %f ",x,y);

	x = translate + graphsize[xpt] * 72.0 / 2.54;
	y = translate + graphsize[ypt] * 72.0 / 2.54;
	fprintf(fout,"%f %f ",x,y);

	x = translate;
	y = translate + graphsize[ypt] * 72.0 / 2.54;
	fprintf(fout,"%f %f ",x,y);

	fprintf(fout,"1.0 G9\n");/* white paint */
	fprintf(fout,"newpath moveto lineto lineto lineto closepath fill\n");
	fprintf(fout,"0.0 G9\n");/* back to  black paint */
	FirstFill = TRUE;
}

/*at the start of each curve sets the global curve parameters */
setConstsForCurve(p)
LocalObjectType *p;
{
  	currLine = p->un.line.line;
  	currThick = p->un.line.thick;
  	currGray = p->gray;
  	currInterp = p->un.line.interp;
  	switch( currLine )
  	{
    	case solid:
    	case fill:
      		fprintf( fout, "[]" );
      	break;
    	case dashes:
      		fprintf( fout, "[6 6]" );
      	break;
    	case stipple:
      		fprintf( fout, "[7 5 1 4]" );
      	break;
    	case dots:
      		fprintf( fout, "[%f %f]", currThick, 4.0*currThick );
      	break;
        case pat:
		fprintf( fout, "[6 3 1 3 1 3]") ;
    	default:
      	break;
  	}
	if (currLine != none) fprintf( fout, " %f SL\n", currThick );
}


/* draws the curve segment and fills the lower region with gray */
dofill(p, currGray)
LocalObjectType *p;
double currGray;
{
 	/*first shade */
       	fprintf( fout,"%lg %lg ", p->from[xpt], p->from[ypt] );
       	fprintf( fout,"%lg %lg \n", p->un.line.to[xpt], p->un.line.to[ypt]);
       	fprintf( fout,"%lg %lg \n", p->un.line.to[xpt], translate);
       	fprintf( fout,"%lg %lg \n", p->from[xpt], translate);

	if (currSSfnIndex >= MAXSSFNS)
	{
		fprintf(stderr,	"Error: in mat index, defaulting to 0\n");
		currSSfnIndex = 0;
	}
 	if (currGray > 0)
		fprintf( fout,"%f %f {%s} SS9 %f G9 F9 %f G9\n", currSSfreq, 
			currSSang, SSFNS[currSSfnIndex], currGray, 0.0);
 	else
		fprintf( fout,"F9\n");

 	/*then black line */
       	fprintf( fout,"%lg %lg ", p->from[xpt], p->from[ypt] );
       	fprintf( fout,"%lg %lg \n", p->un.line.to[xpt], p->un.line.to[ypt]);
 	fprintf( fout,"L9\n");
}

dofillcur(p, currGray)
LocalObjectType *p;
double currGray;
{   
/* this version only prints the shade, and does not do outline */
	/* currently smooth does not allow fill */	
	if (p->un.line.interp == smooth)
		fprintf(fout,"nsend\n");

	/*
	 * if you want the filled region stroked, insert
	 * gsave D9 grestore 
	 * here
	 */
	if (currShowLine) fprintf(fout,"gsave\nD9\ngrestore\n");

	/* if begin = end then fill within curve and not to x axis */
	/* if not, then fill to X axis */
	if ((fp[xpt] != lp[xpt])||(fp[ypt] != lp[ypt]))
	{
       		fprintf(fout,"%lg %lg M9\n",lp[xpt],translate);
	       	fprintf(fout,"%lg %lg M9\n",fp[xpt],translate);
	}
	if (currSSfnIndex >= MAXSSFNS)
	{
		fprintf(stderr, "Error: in mat index, defaulting to 0\n");
		currSSfnIndex = 0;
	}
	if (currGray > 0)
		fprintf( fout,"%f %f {%s} SS9 %f G9 E9 %f G9\n", 
	    	currSSfreq,currSSang,SSFNS[currSSfnIndex],currGray,0.0);
	else
		fprintf( fout,"E9\n");
}

setConstsForText(p)
LocalObjectType *p;
{
 	currFont = p->un.text.FF;
 	currSize = p->un.text.fontsize;
 	fprintf( fout, "%d /%s SetTxt\n", currSize, currFont );
}

setConstsForSymbol(p)
LocalObjectType *p;
{
 	currFont = symbFont;
 	currSize = p->un.symbol.fontsize;
 	fprintf( fout, "%d SetSym\n", currSize );
}

	
setConstsForScreen(p)
LocalObjectType *p;
{
	currSSang = p->un.line.mat.ang;
	currSSfreq = p->un.line.mat.freq;
	currSSfnIndex = p->un.line.mat.indx;
	currShowLine = p->un.line.mat.showline;
}

InitScreenConsts()
{
	currSSang = 0.0;
	currSSfnIndex = 0;
	currSSfreq = 30;
	currShowLine = TRUE;
}

