1 /* epsffit.c
2  * Copyright (C) Angus J. C. Duggan 1991-1995
3  * See file LICENSE for details.
4  *
5  * fit epsf file into constrained size
6  * Usage:
7  *       epsffit [-c] [-r] [-a] [-s] llx lly urx ury [infile [outfile]]
8  *               -c centres the image in the bounding box given
9  *               -r rotates the image by 90 degrees anti-clockwise
10  *               -a alters the aspect ratio to fit the bounding box
11  *               -s adds a showpage at the end of the image
12  *
13  * Added filename spec (from Larry Weissman) 5 Feb 93
14  * Accepts double %%BoundingBox input, outputs proper BB, 4 Jun 93. (I don't
15  * like this; developers should read the Big Red Book before writing code which
16  * outputs PostScript.
17  */
18 
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <ctype.h>
23 
24 #include "pserror.h"
25 #include "patchlev.h"
26 #include "config.h"
27 
28 #define MIN(x,y) ((x) > (y) ? (y) : (x))
29 #define MAX(x,y) ((x) > (y) ? (x) : (y))
30 
31 char *program;
32 
usage(void)33 static void usage(void)
34 {
35    fprintf(stderr, "%s release %d patchlevel %d\n", program, RELEASE, PATCHLEVEL);
36    fprintf(stderr, "Copyright (C) Angus J. C. Duggan, 1991-1995. See file LICENSE for details.\n");
37    fprintf(stderr, "Usage: %s [-c] [-r] [-a] [-s] llx lly urx ury [infile [outfile]]\n",
38 	   program);
39    exit(1);
40 }
41 
main(int argc,char ** argv)42 int main(int argc, char **argv)
43 {
44    int bbfound = 0;              /* %%BoundingBox: found */
45    int urx = 0, ury = 0, llx = 0, lly = 0;
46    int furx, fury, fllx, flly;
47    int showpage = 0, centre = 0, rotate = 0, aspect = 0, maximise = 0;
48    char buf[BUFSIZ];
49    FILE *input;
50    FILE *output;
51 
52    program = *argv++; argc--;
53 
54    while (argc > 0 && argv[0][0] == '-') {
55       switch (argv[0][1]) {
56       case 'c': centre = 1; break;
57       case 's': showpage = 1; break;
58       case 'r': rotate = 1; break;
59       case 'a': aspect = 1; break;
60       case 'm': maximise = 1; break;
61       case 'v':
62       default:  usage();
63       }
64       argc--;
65       argv++;
66    }
67 
68    if (argc < 4 || argc > 6) usage();
69    fllx = atoi(argv[0]);
70    flly = atoi(argv[1]);
71    furx = atoi(argv[2]);
72    fury = atoi(argv[3]);
73 
74    if (argc > 4) {
75       if(!(input = fopen(argv[4], OPEN_READ)))
76 	 message(FATAL, "can't open input file %s\n", argv[4]);
77    } else {
78 #if defined(MSDOS) || defined(WINNT)
79       int fd = fileno(stdin) ;
80       if ( setmode(fd, O_BINARY) < 0 )
81          message(FATAL, "can't reset stdin to binary mode\n");
82 #endif
83       input = stdin ;
84     }
85 
86    if (argc > 5) {
87       if(!(output = fopen(argv[5], OPEN_WRITE)))
88 	 message(FATAL, "can't open output file %s\n", argv[5]);
89    } else {
90 #if defined(MSDOS) || defined(WINNT)
91       int fd = fileno(stdout) ;
92       if ( setmode(fd, O_BINARY) < 0 )
93          message(FATAL, "can't reset stdout to binary mode\n");
94 #endif
95       output = stdout ;
96     }
97 
98    while (fgets(buf, BUFSIZ, input)) {
99       if (buf[0] == '%' && (buf[1] == '%' || buf[1] == '!')) {
100 	 /* still in comment section */
101 	 if (!strncmp(buf, "%%BoundingBox:", 14)) {
102 	    double illx, illy, iurx, iury;	/* input bbox parameters */
103 	    if (sscanf(buf, "%%%%BoundingBox:%lf %lf %lf %lf\n",
104 		       &illx, &illy, &iurx, &iury) == 4) {
105 	       bbfound = 1;
106 	       llx = (int)illx;	/* accept doubles, but convert to int */
107 	       lly = (int)illy;
108 	       urx = (int)(iurx+0.5);
109 	       ury = (int)(iury+0.5);
110 	    }
111 	 } else if (!strncmp(buf, "%%EndComments", 13)) {
112 	    strcpy(buf, "\n"); /* don't repeat %%EndComments */
113 	    break;
114 	 } else fputs(buf, output);
115       } else break;
116    }
117 
118    if (bbfound) { /* put BB, followed by scale&translate */
119       int fwidth, fheight;
120       double xscale, yscale;
121       double xoffset = fllx, yoffset = flly;
122       double width = urx-llx, height = ury-lly;
123 
124       if (maximise)
125 	 if ((width > height && fury-flly > furx-fllx) ||
126 	     (width < height && fury-flly < furx-fllx))
127 	    rotate = 1;
128 
129       if (rotate) {
130 	 fwidth = fury - flly;
131 	 fheight = furx - fllx;
132       } else {
133 	 fwidth = furx - fllx;
134 	 fheight = fury - flly;
135       }
136 
137       xscale = fwidth/width;
138       yscale = fheight/height;
139 
140       if (!aspect) {       /* preserve aspect ratio ? */
141 	 xscale = yscale = MIN(xscale,yscale);
142       }
143       width *= xscale;     /* actual width and height after scaling */
144       height *= yscale;
145       if (centre) {
146 	 if (rotate) {
147 	    xoffset += (fheight - height)/2;
148 	    yoffset += (fwidth - width)/2;
149 	 } else {
150 	    xoffset += (fwidth - width)/2;
151 	    yoffset += (fheight - height)/2;
152 	 }
153       }
154       fprintf(output,
155 	      "%%%%BoundingBox: %d %d %d %d\n", (int)xoffset, (int)yoffset,
156 	     (int)(xoffset+(rotate ? height : width)),
157 	     (int)(yoffset+(rotate ? width : height)));
158       if (rotate) {  /* compensate for original image shift */
159 	 xoffset += height + lly * yscale;  /* displacement for rotation */
160 	 yoffset -= llx * xscale;
161       } else {
162 	 xoffset -= llx * xscale;
163 	 yoffset -= lly * yscale;
164       }
165       fputs("%%EndComments\n", output);
166       if (showpage)
167 	 fputs("save /showpage{}def /copypage{}def /erasepage{}def\n", output);
168       else
169 	 fputs("%%BeginProcSet: epsffit 1 0\n", output);
170       fputs("gsave\n", output);
171       fprintf(output, "%.3f %.3f translate\n", xoffset, yoffset);
172       if (rotate)
173 	 fputs("90 rotate\n", output);
174       fprintf(output, "%.3f %.3f scale\n", xscale, yscale);
175       if (!showpage)
176 	 fputs("%%EndProcSet\n", output);
177    }
178    do {
179       fputs(buf, output);
180    } while (fgets(buf, BUFSIZ, input));
181    if (bbfound) {
182       fputs("grestore\n", output);
183       if (showpage)
184 	 fputs("restore showpage\n", output); /* just in case */
185    } else
186       message(FATAL, "no %%%%BoundingBox:\n");
187 
188    return (0);
189 }
190