
/*
 * irisio.c - Nina Amenta, Aug. 1989
 * kaliprint.c - Nina Amenta, Aug. 1989 *
 *
 * modified: merged kaliprint and irisio into io,
 * so can print directly from kali as well as kaliprint.
 * 7/94 Tamara Munzner 
 *
 * entirely rewritten by Ed H. Chi
 * 
 * $Id: psio.c,v 1.1 1996/06/11 04:59:37 slevy Exp $
 * $Log: psio.c,v $
 * Revision 1.1  1996/06/11  04:59:37  slevy
 * Initial revision
 *
 * Revision 1.4  1994/09/12  23:14:41  chi
 * version 3.0 changes
 * header file recreated
 *
 * Revision 1.3  1994/08/26  16:29:02  chi
 * rewritten by Ed H. Chi (chi@geom)
 * start of a port to X11
 *
 * Revision 1.2  1994/08/15  20:05:38  chi
 * significant code cleanup.
 * header files created.
 * main.h created
 * changed #defines in main.h from DRAW to KALIDRAW, CUT to .... etc
 */

#include <math.h>
#include <stdio.h>
#include <ctype.h>

#include "main.h"
#include "symmetry.h"
#include "io.h"
#include "kali.h"

#define WID 1.2
#define PSSTACKSIZE 40

FILE *f = NULL;

RECTANGLE clip_rect;


/*----------------------------------------------------*/

void PrintOut(FILE *outfile,SYMMETRY *sym, RECTANGLE win_rect, LINE *Lines)
{
  float xforms[5][4];
  RECTANGLE bounds;
  POINT *sym_pts = NULL;
  LINE *obj = NULL;
  int count;
  int i;
  
  f = outfile;
  init_postscript(&win_rect);
  PSDraw.data = f;
  count = SetUpSymmetry(sym,&sym_pts,xforms,&win_rect, NULL);
  DrawClippingRectangle(&win_rect);
  obj = MakeCurrentObject(Lines,sym,xforms,&bounds);
  /* Draw the object in pieces if necessary, to avoid
     overflowing the Postscript stack */
  while (obj != NULL)    {
    obj = SpewObject(obj);
    ReplicateObject(&win_rect,obj,sym_pts,count,&bounds,
		    sym,&PSDraw);
  }
  close_postscript();
}

void PSPush(DRAWER *drawer) {
  fprintf(f, "gsave\n");
}

void PSTranslate(DRAWER *drawer, double x, double y) {
  fprintf(f,"%6.3f %6.3f translate\n",x,y);
}

void PSPop(DRAWER *drawer) {
  fprintf(f,"grestore\n");
}

void PSDrawLine(DRAWER *drawer, LINE *l) {
  fprintf(f,"%6.3f %6.3f moveto\n",l->m[EX],l->m[EY]);
  fprintf(f,"%6.3f %6.3f lineto\n",l->m[SX],l->m[SY]);
}  

void PSDrawLines(DRAWER *drawer, LINE *l) {
  fprintf(f, "pattern\n");	/* Already created by SpewObject below */
}

void PSDrawPoints(DRAWER *drawer, POINT *p, int count) {
  int i;
  fprintf(f, "gsave 1 setlinecap  /pt { moveto currentpoint lineto stroke } def\n");
  for(i = 0; i < count; i++)
	fprintf(f, "%.3f %.3f pt\n", p[i].x, p[i].y);
  fprintf(f, "grestore\n");
}

DRAWER PSDraw = {
	"PS",
	PSDrawLines,
	PSPush,
	PSTranslate,
	PSPop,
	PSDrawLine,
	PSDrawPoints,
	NULL
};


void DrawClippingRectangle(RECTANGLE *rec)
{
  fprintf(f,"%6.3f %6.3f moveto\n",rec->x,rec->y);
  fprintf(f,"%6.3f %6.3f lineto\n",rec->x,rec->height);
  fprintf(f,"%6.3f %6.3f lineto\n",rec->width,rec->height);
  fprintf(f,"%6.3f %6.3f lineto\n",rec->width,rec->y);
  fprintf(f,"%6.3f %6.3f lineto\n",rec->x,rec->y);
  fprintf(f,"closepath gsave stroke grestore\n");
  fprintf(f,"clip newpath\n");
}


void init_postscript(RECTANGLE *rec)
{
  float horiz,vert,units, x0, y0;
  horiz = 7.5/rec->width;
  vert = 10.0/rec->height;
  units = (vert<horiz) ? vert : horiz;
  horiz = (8.5-(units*rec->width))/2.0;
  vert = (11.0-(units*rec->height))/2.0;
  x0 = 72*(rec->x * units + horiz);
  y0 = 72*(rec->y * units + vert);

  fprintf(f,"%%!PS-Adobe-2.0 EPSF-1.2\n");
  fprintf(f,"%%%%BoundingBox: %d %d %d %d\n",
	    (int)floor(x0), (int)floor(y0),
	    (int)ceil(x0+72*units*rec->width), (int)ceil(y0+72*units*rec->height));
  fprintf(f,"/inch {72 mul} def\n");
  fprintf(f,"0 setgray\n");
  fprintf(f,"/Times-Roman findfont 2 scalefont setfont\n");
  fprintf(f,"%4.3f inch %4.3f inch translate\n",horiz,vert);
  fprintf(f,"%4.3f inch %4.3f inch scale\n",units,units);
  fprintf(f,"%2.1f setlinewidth\n",WID);
  fprintf(f,"1 setlinecap\n");
  fprintf(f,"1 setlinejoin\n");
  fprintf(f,"\n");
  CopyRectangle(rec,&clip_rect);
}

void close_postscript()
{
  fprintf(f,"showpage\n");
}


LINE *SpewObject(LINE *obj)
{
  int i;
  fprintf(f,"/pattern { \n");
  fprintf(f,"   newpath \n");
  i = 0;
  while ((i++ < PSSTACKSIZE) && (obj != NULL))    {
    PSDrawLine(&PSDraw, obj);
    obj = obj->next;
  }
  fprintf(f," stroke } def\n");
  return(obj);
}
