/*
	Writes out Flexowriter code containing CalComp plots on a PostScript printer.

	(C) Copyright 2001 by Mogens Kjaer


   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <signal.h>
#include <unistd.h>

#define READSIZE 1024
#define BUFFERSIZE 65536

static char code[16]={'0','1','2','3','4','5','6','7',
                      '8','9','a','b','c','d','e','f'};
static int dx[16]={  0,  0, -1, -1,  1,  1,  0,  0,
                     0,  0, -1,  0,  1,  0,  0,  0};
static int dy[16]={  0, -1,  0, -1,  0, -1,  0,  0,
                     1,  0,  1,  0,  1,  0,  0,  0};

static int xx, yy, state, nstroke, maxnstroke, xmin, xmax, ymin, ymax;

extern unsigned char remove_parity(unsigned char);

static void plot_init(int xmin, int xmax, int ymin, int ymax)
{
  int xsize, ysize;
  double paper_xsize,paper_ysize,xscale,yscale,scale;
  printf("%%!PS-Adobe-3.0\n");
  printf("%%%%Creator: flx2plot\n");
  printf("%%%%Pages: (atend)\n");
  printf("%%%%DocumentMedia: A4 595 842 0 white ()\n");
  printf("%%%%BoundingBox: %d %d %d %d\n", 0, 0, 595, 842);
  printf("%%%%Orientation: Portrait\n");
  printf("%%%%EndComments\n\n");

  printf("[{\n");
  printf("%%%%BeginFeature: *PageSize A4\n");
  printf("<</PageSize[595 842]/ImagingBBox null>>setpagedevice\n");
  printf("%%%%EndFeature\n");
  printf("} stopped cleartomark\n");

  paper_xsize = 2100;
  paper_ysize = 2970;
  
  printf("72 254 div dup scale\n");

  xsize = xmax-xmin;
  ysize = ymax-ymin;

  

  fprintf(stderr, "xmin: %d\n", xmin);
  fprintf(stderr, "xmax: %d\n", xmax);
  fprintf(stderr, "ymin: %d\n", ymin);
  fprintf(stderr, "ymax: %d\n", ymax);
  fprintf(stderr, "xsize: %d\n", xsize);
  fprintf(stderr, "ysize: %d\n", ysize);

  if(ysize > xsize)
  {
    xscale = paper_xsize/((double)xsize);
    yscale = paper_ysize/((double)ysize);
    scale = xscale;
    if(yscale < scale) scale=yscale;
    printf("%.4f dup scale\n", scale);
    printf("%d %d translate\n", -xmin, -ymin);
  }
  else
  {
    xscale = paper_ysize/((double)xsize);
    yscale = paper_xsize/((double)ysize);
    scale = xscale;
    if(yscale < scale) scale=yscale;
    printf("%.4f dup scale\n", scale);
    printf("90 rotate\n");
    printf("%d %d translate\n", -xmin, -ymax);
  }
  fprintf(stderr, "xscale: %g\n", xscale);
  fprintf(stderr, "yscale: %g\n", yscale);
  fprintf(stderr, "scale: %g\n", scale);

  printf("/p1 { 0 -1 rlineto} def\n");
  printf("/p3 {-1 -1 rlineto} def\n");
  printf("/p2 {-1  0 rlineto} def\n");
  printf("/pa {-1  1 rlineto} def\n");
  printf("/p8 { 0  1 rlineto} def\n");
  printf("/pc { 1  1 rlineto} def\n");
  printf("/p4 { 1  0 rlineto} def\n");
  printf("/p5 { 1 -1 rlineto} def\n");

  printf("1 setlinewidth\n");
  printf("0 0 0 setrgbcolor\n");

}

void plot_close()
{
  printf("stroke\n");
  printf("showpage\n");
  printf("%%%%Pages: 1\n");
  printf("%%%%EOF\n%c", (char) 4);
}

static void plot_symbol(char c)
{
  if(c == 16)
  {
    /* pen up */
    printf("stroke\n");
    state=0;
  }
  else if(c == 32)
  {
    /* pen down */
    if(state==0)
    {
      printf("newpath %d %d moveto\n", xx, yy);
      state=1;
      nstroke=0;
    }
  }
  else
  {
    xx += dx[c];
    yy += dy[c];
    if(state == 1)
    {
      printf("p%c ", code[c]);
      nstroke++;
      if(nstroke>maxnstroke) maxnstroke=nstroke;
      if(nstroke>1000)
      {
        printf("stroke newpath %d %d moveto\n", xx, yy);
        nstroke=0;
      }
    }
  }
}

static void box_symbol(char c)
{
  if(c == 16)
  {
    state=0;
  }
  else if(c == 32)
  {
    state=1;
  }
  else
  {
    xx += dx[c];
    yy += dy[c];
    if(state == 1)
    {
      if(xx < xmin) xmin=xx;
      if(xx > xmax) xmax=xx;
      if(yy < ymin) ymin=yy;
      if(yy > ymax) ymax=yy;
    }
  }
}

int main(int argc, char *argv[])
{
  int i,rlen,blen,bsize;
  char *buffer;
  char readbuffer[READSIZE];
  int opt;

  xx=0;
  yy=0;
  state=0;
  nstroke=0;
  maxnstroke=0;
  xmin = 1000000;
  ymin = 1000000;
  xmax = -1000000;
  ymax = -1000000;

  buffer = malloc(BUFFERSIZE);
  blen = 0;
  bsize = BUFFERSIZE;

  while( (rlen=read(0, readbuffer, READSIZE))>0 )
  {
    for(i=0; i<rlen; i++)
    {
      buffer[blen] = remove_parity(readbuffer[i]);
      box_symbol(buffer[blen]);
      blen++;
      if(blen >= bsize)
      {
        bsize += BUFFERSIZE;
        buffer = realloc(buffer, bsize);
      }
    }
  }

  plot_init(xmin, xmax, ymin, ymax);

  xx=0;
  yy=0;
  state=0;
  nstroke=0;
  for(i=0; i<blen; i++)
  {
    plot_symbol(buffer[i]);
  }

  plot_close();
  fprintf(stderr, "maxnstroke: %d\n", maxnstroke);
  return 0;
}

