dpost.ps: increase linewidth to match groff
[troff.git] / tr2ps / ps_include.c
blob739d658fac14797fd52b24829739d9bcc62f7215
1 #include <stdio.h>
2 #include <string.h>
3 #include <stdlib.h>
4 #include "ustr.h"
5 #include "common.h"
7 static char *ps_head[] = {
8 "%ps_include: begin\n",
9 "save\n",
10 "/ed {exch def} def\n",
11 "{} /showpage ed\n",
12 "{} /copypage ed\n",
13 "{} /erasepage ed\n",
14 "{} /letter ed\n",
15 "currentdict /findfont known systemdict /findfont known and {\n",
16 " /findfont systemdict /findfont get def\n",
17 "} if\n",
18 "36 dict dup /PS-include-dict-dw ed begin\n",
19 "/context ed\n",
20 "count array astore /o-stack ed\n",
21 "%ps_include: variables begin\n",
22 NULL
25 static char *ps_setup[] = {
26 "%ps_include: variables end\n",
27 "{llx lly urx ury} /bbox ed\n",
28 "{newpath 2 index exch 2 index exch dup 6 index exch\n",
29 " moveto 3 {lineto} repeat closepath} /boxpath ed\n",
30 "{dup mul exch dup mul add sqrt} /len ed\n",
31 "{2 copy gt {exch} if pop} /min ed\n",
32 "{2 copy lt {exch} if pop} /max ed\n",
33 "{transform round exch round exch A itransform} /nice ed\n",
34 "{6 array} /n ed\n",
35 "n defaultmatrix n currentmatrix n invertmatrix n concatmatrix /A ed\n",
36 "urx llx sub 0 A dtransform len /Sx ed\n",
37 "0 ury lly sub A dtransform len /Sy ed\n",
38 "llx urx add 2 div lly ury add 2 div A transform /Cy ed /Cx ed\n",
39 "rot dup sin abs /S ed cos abs /C ed\n",
40 "Sx S mul Sy C mul add /H ed\n",
41 "Sx C mul Sy S mul add /W ed\n",
42 "sy H div /Scaley ed\n",
43 "sx W div /Scalex ed\n",
44 "s 0 eq {Scalex Scaley min dup /Scalex ed /Scaley ed} if\n",
45 "sx Scalex W mul sub 0 max ax 0.5 sub mul cx add /cx ed\n",
46 "sy Scaley H mul sub 0 max ay 0.5 sub mul cy add /cy ed\n",
47 "urx llx sub 0 A dtransform exch atan rot exch sub /rot ed\n",
48 "n currentmatrix initgraphics setmatrix\n",
49 "cx cy translate\n",
50 "Scalex Scaley scale\n",
51 "rot rotate\n",
52 "Cx neg Cy neg translate\n",
53 "A concat\n",
54 "bbox boxpath clip newpath\n",
55 "w 0 ne {gsave bbox boxpath 1 setgray fill grestore} if\n",
56 "end\n",
57 "gsave\n",
58 "%ps_include: inclusion begin\n",
59 NULL
62 static char *ps_tail[] = {
63 "%ps_include: inclusion end\n",
64 "grestore\n",
65 "PS-include-dict-dw begin\n",
66 "o 0 ne {gsave A defaultmatrix /A ed llx lly nice urx ury nice\n",
67 " initgraphics 0.1 setlinewidth boxpath stroke grestore} if\n",
68 "clear o-stack aload pop\n",
69 "context end restore\n",
70 "%ps_include: end\n",
71 NULL
74 extern int curpostfontid;
75 extern int curfontsize;
77 typedef struct {long start, end;} Section;
78 static char buf[1 << 12];
80 static void copy(struct ustr *ustr, FILE *fout, Section *s)
82 if (s->end <= s->start)
83 return;
84 ustr_seek(ustr, s->start);
86 * We have to be careful here, because % can legitimately appear
87 * in Ascii85 encodings, and must not be elided.
88 * The goal here is to make any DSC comments impotent without
89 * actually changing the behavior of the Postscript.
90 * Since stripping ``comments'' breaks Ascii85, we can instead just
91 * indent comments a space, which turns DSC comments into non-DSC comments
92 * and has no effect on binary encodings, which are whitespace-blind.
94 while (ustr_pos(ustr) < s->end && ustr_line(ustr, buf, sizeof(buf)) > 0) {
95 if (buf[0] == '%')
96 fputc(' ', fout);
97 fputs(buf, fout);
103 * Reads a PostScript file (*fin), and uses structuring comments to locate the
104 * prologue, trailer, global definitions, and the requested page. After the whole
105 * file is scanned, the special ps_include PostScript definitions are copied to
106 * *fout, followed by the prologue, global definitions, the requested page, and
107 * the trailer. Before returning the initial environment (saved in ps_head) is
108 * restored.
110 * By default we assume the picture is 8.5 by 11 inches, but the BoundingBox
111 * comment, if found, takes precedence.
113 * *fin, *fout; input and output files
114 * page_no; physical page number from *fin
115 * whiteout; erase picture area
116 * outline; draw a box around it and
117 * scaleboth; scale both dimensions - if not zero
118 * cx, cy; center of the picture and
119 * sx, sy; its size - in current coordinates
120 * ax, ay; left-right, up-down adjustment
121 * rot; rotation - in clockwise degrees
123 void ps_include(struct ustr *ustr, FILE *fout, int page_no, int whiteout,
124 int outline, int scaleboth, double cx, double cy, double sx, double sy,
125 double ax, double ay, double rot)
127 char **strp;
128 int foundpage = 0; /* found the page when non zero */
129 int foundpbox = 0; /* found the page bounding box */
130 int nglobal = 0; /* number of global defs so far */
131 int maxglobal = 0; /* and the number we've got room for */
132 Section prolog, page, trailer; /* prologue, page, and trailer offsets */
133 Section *global; /* offsets for all global definitions */
134 double llx, lly; /* lower left and */
135 double urx, ury; /* upper right corners - default coords */
136 double w = whiteout != 0; /* mostly for the var() macro */
137 double o = outline != 0;
138 double s = scaleboth != 0;
139 int i;
141 #define has(word) (strncmp(buf, word, strlen(word)) == 0)
142 #define grab(n) ((Section *)(nglobal \
143 ? realloc((char *)global, n*sizeof(Section)) \
144 : calloc(n, sizeof(Section))))
146 llx = lly = 0; /* default BoundingBox - 8.5x11 inches */
147 urx = 72 * 8.5;
148 ury = 72 * 11.0;
150 /* section boundaries and bounding box */
152 prolog.start = prolog.end = 0;
153 page.start = page.end = 0;
154 trailer.start = 0;
155 ustr_seek(ustr, 0);
156 global = NULL;
158 while (ustr_line(ustr, buf, sizeof(buf)) > 0) {
159 if (!has("%%"))
160 continue;
161 else if (has("%%Page: ")) {
162 if (!foundpage)
163 page.start = ustr_pos(ustr);
164 sscanf(buf, "%*s %*s %d", &i);
165 if (i == page_no)
166 foundpage = 1;
167 else if (foundpage && page.end <= page.start)
168 page.end = ustr_pos(ustr);
169 } else if (has("%%EndPage: ")) {
170 sscanf(buf, "%*s %*s %d", &i);
171 if (i == page_no) {
172 foundpage = 1;
173 page.end = ustr_pos(ustr);
175 if (!foundpage)
176 page.start = ustr_pos(ustr);
177 } else if (has("%%PageBoundingBox: ")) {
178 if (i == page_no) {
179 foundpbox = 1;
180 sscanf(buf, "%*s %lf %lf %lf %lf",
181 &llx, &lly, &urx, &ury);
183 } else if (has("%%BoundingBox: ")) {
184 if (!foundpbox)
185 sscanf(buf,"%*s %lf %lf %lf %lf",
186 &llx, &lly, &urx, &ury);
187 } else if (has("%%EndProlog") || has("%%EndSetup") || has("%%EndDocumentSetup"))
188 prolog.end = page.start = ustr_pos(ustr);
189 else if (has("%%Trailer"))
190 trailer.start = ustr_pos(ustr);
191 else if (has("%%BeginGlobal")) {
192 if (page.end <= page.start) {
193 if (nglobal >= maxglobal) {
194 maxglobal += 20;
195 global = grab(maxglobal);
197 global[nglobal].start = ustr_pos(ustr);
199 } else if (has("%%EndGlobal"))
200 if (page.end <= page.start)
201 global[nglobal++].end = ustr_pos(ustr);
203 if (trailer.start == 0)
204 trailer.start = ustr_pos(ustr);
205 trailer.end = ustr_pos(ustr);
207 if (page.end <= page.start)
208 page.end = trailer.start;
210 /* all output here */
211 for (strp = ps_head; *strp != NULL; strp++)
212 fputs(*strp, fout);
214 fprintf(fout, "/llx %g def\n", llx);
215 fprintf(fout, "/lly %g def\n", lly);
216 fprintf(fout, "/urx %g def\n", urx);
217 fprintf(fout, "/ury %g def\n", ury);
218 fprintf(fout, "/w %g def\n", w);
219 fprintf(fout, "/o %g def\n", o);
220 fprintf(fout, "/s %g def\n", s);
221 fprintf(fout, "/cx %g def\n", cx);
222 fprintf(fout, "/cy %g def\n", cy);
223 fprintf(fout, "/sx %g def\n", sx);
224 fprintf(fout, "/sy %g def\n", sy);
225 fprintf(fout, "/ax %g def\n", ax);
226 fprintf(fout, "/ay %g def\n", ay);
227 fprintf(fout, "/rot %g def\n", rot);
229 for (strp = ps_setup; *strp != NULL; strp++)
230 fputs(*strp, fout);
232 copy(ustr, fout, &prolog);
233 for(i = 0; i < nglobal; i++)
234 copy(ustr, fout, &global[i]);
235 copy(ustr, fout, &page);
236 copy(ustr, fout, &trailer);
237 for (strp = ps_tail; *strp != NULL; strp++)
238 fputs(*strp, fout);
240 if(nglobal)
241 free(global);
243 /* force the program to reestablish its state */
244 curpostfontid = -1;
245 curfontsize = -1;