out: ignore invalid size requests
[neatpost.git] / out.c
blob4d70edb580f2bee39eaaca0b569478fc36321230
1 #include <stdarg.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include "post.h"
7 static int o_f, o_s, o_m; /* font and size */
8 static int o_h, o_v; /* current user position */
9 static int p_f, p_s, p_m; /* output postscript font */
10 static int o_qtype; /* queued character type */
11 static int o_qv, o_qh, o_qend; /* queued character position */
12 static int o_rh, o_rv, o_rdeg; /* previous rotation position and degree */
14 char o_fonts[FNLEN * NFONTS] = " ";
16 static void outvf(char *s, va_list ap)
18 vfprintf(stdout, s, ap);
21 static void outf(char *s, ...)
23 va_list ap;
24 va_start(ap, s);
25 outvf(s, ap);
26 va_end(ap);
29 static void o_flush(void)
31 if (o_qtype == 1)
32 outf(") %d %d w\n", o_qh, o_qv);
33 if (o_qtype == 2)
34 outf("] %d %d g\n", o_qh, o_qv);
35 o_qtype = 0;
38 void outpage(void)
40 o_flush();
41 o_v = 0;
42 o_h = 0;
43 p_s = 0;
44 p_f = 0;
45 p_m = 0;
46 o_rdeg = 0;
49 static void o_queue(struct glyph *g)
51 int type = 1 + (g->pos <= 0);
52 if (o_qtype != type || o_qend != o_h || o_qv != o_v) {
53 o_flush();
54 o_qh = o_h;
55 o_qv = o_v;
56 o_qtype = type;
57 outf(type == 1 ? "(" : "[");
59 if (o_qtype == 1) {
60 if (g->pos >= ' ' && g->pos <= '~')
61 outf("%s%c", strchr("()\\", g->pos) ? "\\" : "", g->pos);
62 else
63 outf("\\%d%d%d", (g->pos >> 6) & 7,
64 (g->pos >> 3) & 7, g->pos & 7);
65 } else {
66 outf("/%s", g->id);
68 o_qend = o_h + font_wid(g->font, o_s, g->wid);
71 /* calls o_flush() if necessary */
72 void out(char *s, ...)
74 va_list ap;
75 o_flush();
76 va_start(ap, s);
77 outvf(s, ap);
78 va_end(ap);
81 static void out_fontup(int fid)
83 char fnname[FNLEN];
84 struct font *fn;
85 if (o_m != p_m) {
86 out("%d %d %d rgb\n", CLR_R(o_m), CLR_G(o_m), CLR_B(o_m));
87 p_m = o_m;
89 if (fid != p_f || o_s != p_s) {
90 fn = dev_font(fid);
91 out("%d /%s f\n", o_s, font_name(fn));
92 p_f = fid;
93 p_s = o_s;
94 sprintf(fnname, " %s ", font_name(fn));
95 if (!strstr(o_fonts, fnname))
96 sprintf(strchr(o_fonts, '\0'), "%s ", font_name(fn));
100 void outc(char *c)
102 struct glyph *g;
103 struct font *fn;
104 g = dev_glyph(c, o_f);
105 fn = g ? g->font : dev_font(o_f);
106 if (!g) {
107 outrel(*c == ' ' && fn ? font_swid(fn, o_s) : 1, 0);
108 return;
110 out_fontup(dev_fontid(fn));
111 o_queue(g);
114 void outh(int h)
116 o_h = h;
119 void outv(int v)
121 o_v = v;
124 void outrel(int h, int v)
126 o_h += h;
127 o_v += v;
130 void outfont(int f)
132 if (dev_font(f))
133 o_f = f;
136 /* a font was mounted at pos f */
137 void outmnt(int f)
139 if (p_f == f)
140 p_f = -1;
143 void outsize(int s)
145 if (s > 0)
146 o_s = s;
149 void outcolor(int c)
151 o_m = c;
154 void outrotate(int deg)
156 o_flush();
157 out_fontup(o_f);
158 if (o_rdeg)
159 outf("%d %d %d rot\n", -o_rdeg, o_rh, o_rv);
160 o_rdeg = deg;
161 o_rh = o_h;
162 o_rv = o_v;
163 outf("%d %d %d rot\n", deg, o_h, o_v);
166 static int draw_path; /* number of path segments */
167 static int draw_point; /* point was set for postscript newpath */
169 static void drawmv(void)
171 if (!draw_point)
172 outf("%d %d m ", o_h, o_v);
173 draw_point = 1;
176 /* start a multi-segment path */
177 void drawmbeg(char *s)
179 o_flush();
180 out_fontup(o_f);
181 draw_path = 1;
182 outf("gsave newpath %s\n", s);
185 /* end a multi-segment path */
186 void drawmend(char *s)
188 draw_path = 0;
189 draw_point = 0;
190 outf("%s grestore\n", s);
193 void drawbeg(void)
195 o_flush();
196 out_fontup(o_f);
197 if (draw_path)
198 return;
199 outf("newpath ");
202 void drawend(int close, int fill)
204 if (draw_path)
205 return;
206 draw_point = 0;
207 if (close)
208 outf("closepath ");
209 if (fill)
210 outf("fill\n");
211 else
212 outf("stroke\n");
215 void drawl(int h, int v)
217 drawmv();
218 outrel(h, v);
219 outf("%d %d drawl ", o_h, o_v);
222 void drawc(int c)
224 drawmv();
225 outrel(c, 0);
226 outf("%d %d drawe ", c, c);
229 void drawe(int h, int v)
231 drawmv();
232 outrel(h, 0);
233 outf("%d %d drawe ", h, v);
236 void drawa(int h1, int v1, int h2, int v2)
238 drawmv();
239 outf("%d %d %d %d drawa ", h1, v1, h2, v2);
240 outrel(h1 + h2, v1 + v2);
243 void draws(int h1, int v1, int h2, int v2)
245 drawmv();
246 outf("%d %d %d %d %d %d draws ", o_h, o_v, o_h + h1, o_v + v1,
247 o_h + h1 + h2, o_v + v1 + v2);
248 outrel(h1, v1);
251 void outeps(char *spec)
253 char eps[1 << 12];
254 char buf[1 << 12];
255 int llx, lly, urx, ury;
256 int hwid, vwid;
257 FILE *filp;
258 int nspec, nbb;
259 if ((nspec = sscanf(spec, "%s %d %d", eps, &hwid, &vwid)) < 1)
260 return;
261 if (nspec < 2)
262 hwid = 0;
263 if (nspec < 3)
264 vwid = 0;
265 if (!(filp = fopen(eps, "r")))
266 return;
267 if (!fgets(buf, sizeof(buf), filp) ||
268 (strcmp(buf, "%!PS-Adobe-2.0 EPSF-2.0\n") &&
269 strcmp(buf, "%!PS-Adobe-3.0 EPSF-3.0\n"))) {
270 fclose(filp);
271 return;
273 nbb = 0;
274 while (fgets(buf, sizeof(buf), filp))
275 if (!strncmp(buf, "%%BoundingBox: ", 15))
276 if ((nbb = sscanf(buf + 15, "%d %d %d %d",
277 &llx, &lly, &urx, &ury)) == 4)
278 break;
279 fclose(filp);
280 if (nbb < 4) /* no BoundingBox comment */
281 return;
282 if (hwid <= 0 && vwid <= 0)
283 hwid = urx - llx;
284 if (vwid <= 0)
285 vwid = (ury - lly) * hwid / (urx - llx);
286 if (hwid <= 0)
287 hwid = (urx - llx) * vwid / (ury - lly);
288 /* output the EPS file */
289 o_flush();
290 out_fontup(o_f);
291 outf("%d %d %d %d %d %d %d %d EPSFBEG\n",
292 llx, lly, hwid, urx - llx, vwid, ury - lly, o_h, o_v);
293 outf("%%%%BeginDocument: %s\n", eps);
294 filp = fopen(eps, "r");
295 while (fgets(buf, sizeof(buf), filp))
296 out("%s", buf);
297 fclose(filp);
298 outf("%%%%EndDocument\n");
299 outf("EPSFEND\n");