shiva@well.sf.ca.us (Kenneth Porter) (11/02/90)
/*
Use %%BoundingBox specs in PostScript file to scale to fit
on an A-size sheet with 0.375" margins.
Author: Kenneth Porter (shiva@well.sf.ca.us)
1431 Madeline Rd.
San Pablo, CA 94806-1259
Compiles with Turbo C 2.0.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define FALSE 0
#define TRUE (!FALSE)
#define ERRSTRING sys_errlist[errno] /* DOS file error description */
char copyrt[] = "Copyright 1989 Kenneth Porter, all rights reserved\n";
/* printable area in points */
#define INCH 72.0
#define MARGIN 0.375
#define WIDTH ((8.5-(2*MARGIN)) * INCH)
#define HEIGHT ((11.0-(2*MARGIN)) * INCH)
/* file variables */
char *srcname = NULL, *dstname = NULL;
FILE *srcfile, *dstfile;
char inbuf[256];
/* Bounding Box info */
char BBs[] = "%%BoundingBox:";
#define BBSize (sizeof(BBs)-1)
char atend[] = "(atend)";
#define atSize (sizeof(atend)-1)
char trailer[] = "%%Trailer";
#define trailSize (sizeof(trailer)-1)
int llx,lly,urx,ury;
/* function prototypes */
void OpenSrcFile(char *name);
void OpenDstFile(char *name);
int FindBB(void);
void WriteProlog(void);
void CopySrcToOut(void);
void WriteTrailer(void);
void CloseFiles(void);
void main (int argc, char *argv[])
{
/* first print title and open files */
puts("PostScript Page-Fitting Utility\n");
puts(copyrt);
if (argc != 3) {
fputs("syntax: PSFIT <source> <destination>\n",stderr);
exit(1);
}
OpenSrcFile(argv[1]);
if (!FindBB()) {
fprintf(stderr,"No %%%%BoundingBox comment in %s",srcname);
exit(1);
}
OpenDstFile(argv[2]);
WriteProlog();
CopySrcToOut();
WriteTrailer();
CloseFiles();
exit(0);
}
void OpenSrcFile(char *name)
{
srcname = strupr(name);
srcfile = fopen(srcname,"rt");
if (!srcfile) {
fprintf(stderr,"Failed to open %s for reading: %s\n",
srcname,ERRSTRING);
exit(1);
}
}
void OpenDstFile(char *name)
{
dstname = strupr(name);
if (!strcmp(srcname,dstname)) {
fputs("Source file and destination file must be different\n",stderr);
exit(1);
}
dstfile = fopen(dstname,"wt");
if (!dstfile) {
fprintf(stderr,"Failed to open %s for writing: %s\n",
dstname,ERRSTRING);
exit(1);
}
}
int FindBB(void)
{
/*
Scan stdin for line beginning with %%BoundingBox or not a
prolog comment.
*/
int in_prolog, in_trailer, BB_in_trailer, nargs, BB_seen;
in_prolog = TRUE;
in_trailer = BB_in_trailer = BB_seen = FALSE;
fgets(inbuf,sizeof(inbuf),srcfile);
while (!(feof(srcfile) || ferror(srcfile))) {
if (in_prolog) {
if (inbuf[0] != '%' || (inbuf[1] != '%' && inbuf[1] != '!'))
in_prolog = FALSE;
else {
if (!strncmp(inbuf,BBs,BBSize)) {
if (!strncmp(&inbuf[BBSize+1],atend,atSize)) {
BB_in_trailer = TRUE;
}
else {
nargs = sscanf(&inbuf[BBSize],
" %d %d %d %d",
&llx,&lly,&urx,&ury);
if (nargs != 4) {
fprintf(stderr,
"Bad %%%%BoundingBox comment in header, %d args
parsed:\n",
nargs);
fprintf(stderr," \"%s\"",inbuf);
exit(1);
}
BB_seen = TRUE;
in_prolog = FALSE; /* only look at first */
}
}
}
}
else if (BB_in_trailer) {
/* not in prolog */
if (!strncmp(inbuf,trailer,trailSize))
in_trailer = TRUE;
if (in_trailer) {
if (!strncmp(inbuf,BBs,BBSize)) {
nargs = sscanf(&inbuf[BBSize],
" %d %d %d %d",
&llx,&lly,&urx,&ury);
if (nargs != 4) {
fprintf(stderr,
"Bad %%%%BoundingBox comment in trailer, %d args
parsed:\n",
nargs);
fprintf(stderr," \"%s\"",inbuf);
exit(1);
}
BB_seen = TRUE;
}
}
}
else break;
fgets(inbuf,sizeof(inbuf),srcfile);
} /* while (!eof) */
if (ferror(srcfile)) {
fprintf(stderr,"Error reading from %s: %s\n",srcname,ERRSTRING);
exit(1);
}
return(BB_seen);
}
char prolog[] =
"%%!PS-Adobe-2.0\n"
"%%%%Creator: PSFIT\n"
"%%%%BoundingBox: %d %d %d %d\n"
"%%%%EndComments\n"
"%%%%EndProlog\n"
"%%%%BeginSetup\n"
"%f %f translate\n"
"%f %f scale\n"
"%f %f translate\n"
"%f rotate\n"
"%%%%EndSetup\n"
"%%%%BeginDocument: %s\n";
void WriteProlog(void)
{
int new_llx,new_lly,new_urx,new_ury;
double scale,xscale,yscale;
int rotate;
if (urx-llx > ury-lly) {
rotate = 90;
/* rotate BB coords around origin */
new_llx = -ury;
new_lly = llx;
new_urx = -lly;
new_ury = urx;
/* copy back into original variables */
llx = new_llx;
lly = new_lly;
urx = new_urx;
ury = new_ury;
}
else rotate = 0;
new_llx = new_lly = MARGIN*INCH;
xscale = WIDTH / (double) (urx - llx);
yscale = HEIGHT / (double) (ury - lly);
scale = min(xscale,yscale);
new_urx = new_llx + scale*(urx-llx);
new_ury = new_lly + scale*(ury-lly);
fprintf(dstfile,prolog,
new_llx,new_lly, /* new BBox */
new_urx,new_ury,
(float)new_llx,(float)new_lly, /* translate */
(float)scale,(float)scale, /* scale */
(float)-llx,(float)-lly, /* translate */
(float) rotate, /* rotate */
srcname);
}
void CopySrcToOut(void)
{
rewind(srcfile);
fgets(inbuf,sizeof(inbuf),srcfile);
while(! (feof(srcfile) /* || ferror(srcfile) */ ) ) {
fputs(inbuf,dstfile);
fgets(inbuf,sizeof(inbuf),srcfile);
}
if (ferror(srcfile)) {
fprintf(stderr,"Error reading from %s: %s\n",srcname,ERRSTRING);
exit(1);
}
}
void WriteTrailer(void)
{
fputs("%%EndDocument\n",dstfile);
}
void CloseFiles(void)
{
fclose(srcfile);
fclose(dstfile);
}