/****************************************************************
 * fbps.c: FBM Release 1.2 02-Jun-93 Michael Mauldin
 *
 * Copyright (C) 1989-1993 by Michael Mauldin.  Permission is granted
 * to use this file in whole or in part for any purpose, educational,
 * recreational or commercial, provided that this copyright notice
 * is retained unchanged.  This software is available to all free of
 * charge by anonymous FTP and in the UUNET archives.
 *
 * fbps: Convert a grayscale image to a PostScript file
 *
 * USAGE
 *	% fbps < image > postscript
 *
 * EDITLOG
 *	LastEditDate = Mon Jun 25 00:04:03 1990 - Michael Mauldin
 *	LastFileName = /usr2/mlm/src/misc/fbm/fbps.c
 *
 * HISTORY
 * 02-Jun-93  Michael Mauldin (mlm@cs.cmu.edu) Carnegie Mellon
 *	Add ability to handle mapped/unmapped 1,4,8 bit grayscale and color.
 *
 * 25-Jun-90  Michael Mauldin (mlm@cs.cmu.edu) Carnegie Mellon
 *	Package for Release 1.0
 *
 * 26-Aug-89  Paul Milazzo (milazzo) at BBN
 *	Beta release (version 0.96)
 *	Added rotation, big paper option
 *
 * 07-Mar-89  Michael Mauldin (mlm) at Carnegie Mellon University
 *	Beta release (version 0.94) mlm@cs.cmu.edu
 *
 * 25-Apr-89  Paul Milazzo (milazzo) at BBN
 *	Added color postscript support
 *
 * 27-Aug-88  Michael Mauldin (mlm) at Carnegie-Mellon University
 *	Created.
 *****************************************************************/

# include <stdio.h>
# include <math.h>
# include "fbm.h"

# define PAPERWIDTH 8.5 /* inches */
# define BIGPAPERWIDTH 11 /* inches */
# define PAPERHEIGHT 11 /* inches */
# define BIGPAPERHEIGHT 14 /* inches */

char *ps_chars();

# define USAGE \
"Usage: fbps [-t<title> -c<credits> -b<banner> -d<dpi> [-pP] [ -rsL ] [ -w<width> ] < foo.fbm > foo.PS"

#ifndef lint
static char *fbmid =
"$FBM fbps.c <1.0> 25-Jun-90  (C) 1989,1990 by Michael Mauldin, source \
code available free from MLM@CS.CMU.EDU and from UUNET archives$";
#endif

int resolution = 300; /* dpi */

main (argc, argv)
char *argv[];
{ register int i, j;
  int rows, cols, rowlen;
  double paperwidth, paperheight;
  double maxwidth, maxheight;
  double width = -1, height, llx, lly, top, bottom;
  int bytcnt=0, bigpaper=0, dobanner=1, dotitle=1, docredits=1, dosize=1;
  int rotate=0, scribe=0, compressed=0;
  char buf[BUFSIZ];
  char *banner=NULL, *title=NULL, *credits=NULL, *creator=NULL;
  long clock = time ((long *) NULL);
  char *ctime ();
  FBM image;
  int iscolor, bits, padlen;

  /* Clear the memory pointer so alloc_fbm won't be confused */
  image.cm  = image.bm  = (unsigned char *) NULL;

  /* Get the options */
  while (--argc > 0 && (*++argv)[0] == '-')
  { while (*++(*argv))
    { switch (**argv)
      { case 'b':	banner = *argv+1; dobanner = 1; SKIPARG; break;
	case 'B':	dobanner = 0; break;
	case 't':	title = *argv+1; dotitle = 1; SKIPARG; break;
	case 'T':	dotitle = 0; break;
	case 'c':	credits = *argv+1; docredits = 1; SKIPARG; break;
	case 'C':	docredits = 0; break;
	case 'p':	dosize = 1; break;
	case 'P':	dosize = 0; break;
	case 'r':	rotate++; break;
	case 'd':	resolution = atoi (*argv+1); SKIPARG; break;
	case 'L':	bigpaper++; break;
	case 's':	scribe++; break;
	case 'w':	width = atof (*argv+1); SKIPARG; break;
	default:	fprintf (stderr, "%s\n", USAGE);
			exit (1);
      }
    }
  }

  if (!read_bitmap (&image, (char *) NULL))
  { exit (1); }

  /* Get title */
  if (!title && image.hdr.title && image.hdr.title[0])
  { title = image.hdr.title; }

  /* Get credits */
  if (!credits && image.hdr.credits && image.hdr.credits[0])
  { credits = image.hdr.credits; }

  /* Get width and height */
  rows = image.hdr.rows;
  cols = image.hdr.cols;
  rowlen = image.hdr.rowlen;

  paperwidth = bigpaper ? BIGPAPERWIDTH : PAPERWIDTH;
  paperheight = bigpaper ? BIGPAPERHEIGHT : PAPERHEIGHT;

  maxwidth = (rotate ? paperheight : paperwidth) - 1.49;
  maxheight = (rotate ? paperwidth : paperheight) - 1.49;

  analyze_image (&image, &iscolor, &bits, &padlen);

  /*==== Choose X and Y size, if width not specified ====*/
  if (bits == 1)
  { int scalex, scaley, rscale;
    double rwidth, rheight;
  
    scalex = (maxwidth * resolution) / cols;
    scaley = (maxheight * resolution) / rows;
    rscale = (scalex < scaley) ? scalex : scaley;
    
    if (rscale < 1)
    { fprintf (stderr,
	       "Error: image too large [%d,%d] to fit at %d dpi resolution\n",
	       cols, rows, resolution);
      exit (1);
    }
    
    width = (double) cols * rscale / (double) resolution;
    height = (double) rows * rscale / (double) resolution;
  }
  else
  { if (width < 0.0 || width > maxwidth)
    { width = maxwidth; }

    height = width * image.hdr.aspect * (double) rows / cols;

    if (height > maxheight)
    { width = width * maxheight / height; height = maxheight; }
  }

  /* Pick lower left corner */
  if (scribe)
  { llx = lly = 0.0;  }
  else
  { llx = (paperwidth - (rotate ? height : width)) / 2.0;
    lly = rotate ? width + ((paperheight - width) / 2.0) :
		   (paperheight - height) / 2.0;
  }

  fprintf (stderr,
	   "FBM to PS \"%s\" width %1.3lf inches, height %1.3lf inches\n",
	   title ? title : "(untitled)", width, height);

  /* Write out PostScript Header */
  if (scribe)
  { printf ("%%! Scribe @graphic style PostScript\n");
    if (title) { printf ("%%%%Title: %s\n", ps_chars (title)); }
    if (banner) { printf ("%%%%Banner: %s\n", ps_chars (banner)); }
    if (credits) { printf ("%%%%Credits: %s\n", ps_chars (credits)); }
    if (creator) { printf ("%%%%Creator:  %s\n", ps_chars (creator)); }
    printf ("%%%%CreationDate: %s", ctime (&clock));

    printf ("/inch { 72 mul } def\n");
    printf ("/picstr %d string def\n\n", BYTESPERLINE);
    dotitle = dosize = 0;
  }
  else
  { printf ("%%!PS-Adobe-1.0\n");
    if (title) { printf ("%%%%Title: %s\n", ps_chars (title)); }
    if (banner) { printf ("%%%%Banner: %s\n", ps_chars (banner)); }
    if (credits) { printf ("%%%%Credits: %s\n", ps_chars (credits)); }
    if (creator) { printf ("%%%%Creator:  %s\n", ps_chars (creator)); }
    printf ("%%%%CreationDate: %s", ctime (&clock));
    printf ("%%%%Pages: 1\n");
    printf ("%%%%DocumentFonts:%s%s\n",
	    dotitle ? " Times-Bold" : "",
	    dosize ?  " Times-Roman" : "");
    printf ("%%%%EndComments\n");
    printf ("%%%%EndProlog\n");
    printf ("%%%%Page: 1 1\n\n");

    printf ("/inch { 72 mul } def\n");
    printf ("/picstr %d string def\n\n", BYTESPERLINE);

  }

  printf ("gsave\n");

  if (llx != 0.0 || lly != 0.0)
  { printf ("%lg inch %lg inch translate", llx, lly); }

  if (rotate)
  { fputs (" -90 rotate", stdout);  }

  printf ("\n\n");

  top = height + 0.125; 
  bottom = -0.125;

  if (dotitle && title)
  { printf ("/Times-Bold findfont 14 scalefont setfont\n");
    printf ("%lg inch %lg inch moveto\n", width/2.0, top);
    printf ("(%s)\n", ps_chars (title));
    printf ("dup stringwidth pop 2 div 0 exch sub 0 rmoveto show\n\n");
    top += (14.0 / 72.0) + 0.125;
  }

  if (credits && docredits)  
  { bottom -= (8.0 / 72.0);
    printf ("/Times-Roman findfont 8 scalefont setfont\n");
    printf ("%lg inch %lg inch moveto\n", width, bottom);
    printf ("(%s)\n", ps_chars (credits));
    printf ("dup stringwidth pop 0 exch sub 0 rmoveto show\n\n");
  }
  else if (dosize)
  { bottom -= (8.0 / 72.0);
    printf ("/Times-Roman findfont 8 scalefont setfont\n");
    printf ("%lg inch %lg inch moveto\n", width, bottom);
    sprintf (buf, "[ %d by %d pixels, %1.3lf %s, %1.2lf by %1.2lf inches ]",
	     image.hdr.cols, image.hdr.rows, image.hdr.aspect,
	     "aspect ratio", width, height);
    printf ("(%s)\n", ps_chars (buf));
    printf ("dup stringwidth pop 0 exch sub 0 rmoveto show\n\n");
  }

  if (dobanner && banner)
  { printf ("/Times-Bold findfont 28 scalefont setfont\n");
    printf ("%lg inch %lg inch moveto\n", width/2.0, top);
    printf ("(%s)\n", ps_chars (banner));
    printf ("dup stringwidth pop 2 div 0 exch sub 0 rmoveto show\n\n");

    top += (28.0 / 72.0) + 0.125;
    bottom -= (28.0 / 72.0);

    printf ("%lg inch %lg inch moveto\n", width/2.0, bottom);
    printf ("(%s)\n", ps_chars (banner));
    printf ("dup stringwidth pop 2 div 0 exch sub 0 rmoveto show\n\n");
  }

  printf ("%lg inch %lg inch scale\n", width, height);
  write_simple_ps (&image, stdout, iscolor, bits, padlen);
  
  printf ("grestore\n");

  if (!scribe)
  { printf ("\nshowpage\n\n");
    printf ("%%%%Trailer\n");
  }

  exit (0);
}

/****************************************************************
 * ps_chars: Put in proper escapes so an arbitrary string works
 *	     according to the PostScript definition of a literal
 ****************************************************************/

char *ps_chars (txt)
char *txt;
{ static char buf[512];
  register char *s = buf;
  char *index ();
  
  for (; *txt; txt++)
  { if (index ("()\\", *txt))
    { *s++ = '\\'; *s++ = *txt; }
    else if (*txt < ' ' || *txt > '~')
    { sprintf (s, "\\%03o", *txt & 0377); s += 4; }
    else
    { *s++ = *txt; }
  }
  *s = '\0';
  s = buf;
  return (s);
}
