post: extend Dp command to include arcs or splines
[neatpost.git] / out.c
blob6a55e0f76c593923e24125ba291fe4da5fad19fc
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 */
13 static int o_gname; /* use glyphshow for all glyphs */
15 char o_fonts[FNLEN * NFONTS] = " ";
17 static void outvf(char *s, va_list ap)
19 vfprintf(stdout, s, ap);
22 static void outf(char *s, ...)
24 va_list ap;
25 va_start(ap, s);
26 outvf(s, ap);
27 va_end(ap);
30 static void o_flush(void)
32 if (o_qtype == 1)
33 outf(") %d %d w\n", o_qh, o_qv);
34 if (o_qtype == 2)
35 outf("] %d %d g\n", o_qh, o_qv);
36 o_qtype = 0;
39 void outgname(int g)
41 o_gname = g;
44 void outpage(void)
46 o_flush();
47 o_v = 0;
48 o_h = 0;
49 p_s = 0;
50 p_f = 0;
51 p_m = 0;
52 o_rdeg = 0;
55 static void o_queue(struct glyph *g)
57 int type = 1 + (g->pos <= 0 || o_gname);
58 if (o_qtype != type || o_qend != o_h || o_qv != o_v) {
59 o_flush();
60 o_qh = o_h;
61 o_qv = o_v;
62 o_qtype = type;
63 outf(type == 1 ? "(" : "[");
65 if (o_qtype == 1) {
66 if (g->pos >= ' ' && g->pos <= '~')
67 outf("%s%c", strchr("()\\", g->pos) ? "\\" : "", g->pos);
68 else
69 outf("\\%d%d%d", (g->pos >> 6) & 7,
70 (g->pos >> 3) & 7, g->pos & 7);
71 } else {
72 outf("/%s", g->id);
74 o_qend = o_h + font_wid(g->font, o_s, g->wid);
77 /* calls o_flush() if necessary */
78 void out(char *s, ...)
80 va_list ap;
81 o_flush();
82 va_start(ap, s);
83 outvf(s, ap);
84 va_end(ap);
87 static void out_fontup(int fid)
89 char fnname[FNLEN];
90 struct font *fn;
91 if (o_m != p_m) {
92 out("%d %d %d rgb\n", CLR_R(o_m), CLR_G(o_m), CLR_B(o_m));
93 p_m = o_m;
95 if (fid != p_f || o_s != p_s) {
96 fn = dev_font(fid);
97 out("%d /%s f\n", o_s, font_name(fn));
98 p_f = fid;
99 p_s = o_s;
100 sprintf(fnname, " %s ", font_name(fn));
101 if (!strstr(o_fonts, fnname))
102 sprintf(strchr(o_fonts, '\0'), "%s ", font_name(fn));
106 void outc(char *c)
108 struct glyph *g;
109 struct font *fn;
110 g = dev_glyph(c, o_f);
111 fn = g ? g->font : dev_font(o_f);
112 if (!g) {
113 outrel(*c == ' ' && fn ? font_swid(fn, o_s) : 1, 0);
114 return;
116 out_fontup(dev_fontid(fn));
117 o_queue(g);
120 void outh(int h)
122 o_h = h;
125 void outv(int v)
127 o_v = v;
130 void outrel(int h, int v)
132 o_h += h;
133 o_v += v;
136 void outfont(int f)
138 if (dev_font(f))
139 o_f = f;
142 /* a font was mounted at pos f */
143 void outmnt(int f)
145 if (p_f == f)
146 p_f = -1;
149 void outsize(int s)
151 if (s > 0)
152 o_s = s;
155 void outcolor(int c)
157 o_m = c;
160 void outrotate(int deg)
162 o_flush();
163 out_fontup(o_f);
164 if (o_rdeg)
165 outf("%d %d %d rot\n", -o_rdeg, o_rh, o_rv);
166 o_rdeg = deg;
167 o_rh = o_h;
168 o_rv = o_v;
169 outf("%d %d %d rot\n", deg, o_h, o_v);
172 static int draw_path; /* number of path segments */
173 static int draw_point; /* point was set for postscript newpath */
175 static void drawmv(void)
177 if (!draw_point)
178 outf("%d %d m ", o_h, o_v);
179 draw_point = 1;
182 /* start a multi-segment path */
183 void drawmbeg(char *s)
185 o_flush();
186 out_fontup(o_f);
187 draw_path = 1;
188 outf("gsave newpath %s\n", s);
191 /* end a multi-segment path */
192 void drawmend(char *s)
194 draw_path = 0;
195 draw_point = 0;
196 outf("%s grestore\n", s);
199 void drawbeg(void)
201 o_flush();
202 out_fontup(o_f);
203 if (draw_path)
204 return;
205 outf("newpath ");
208 void drawend(int close, int fill)
210 if (draw_path)
211 return;
212 draw_point = 0;
213 if (close)
214 outf("closepath ");
215 if (fill)
216 outf("fill\n");
217 else
218 outf("stroke\n");
221 void drawl(int h, int v)
223 drawmv();
224 outrel(h, v);
225 outf("%d %d drawl ", o_h, o_v);
228 void drawc(int c)
230 drawmv();
231 outrel(c, 0);
232 outf("%d %d drawe ", c, c);
235 void drawe(int h, int v)
237 drawmv();
238 outrel(h, 0);
239 outf("%d %d drawe ", h, v);
242 void drawa(int h1, int v1, int h2, int v2)
244 drawmv();
245 outf("%d %d %d %d drawa ", h1, v1, h2, v2);
246 outrel(h1 + h2, v1 + v2);
249 void draws(int h1, int v1, int h2, int v2)
251 drawmv();
252 outf("%d %d %d %d %d %d draws ", o_h, o_v, o_h + h1, o_v + v1,
253 o_h + h1 + h2, o_v + v1 + v2);
254 outrel(h1, v1);
257 void outeps(char *spec)
259 char eps[1 << 12];
260 char buf[1 << 12];
261 int llx, lly, urx, ury;
262 int hwid, vwid;
263 FILE *filp;
264 int nspec, nbb;
265 if ((nspec = sscanf(spec, "%s %d %d", eps, &hwid, &vwid)) < 1)
266 return;
267 if (nspec < 2)
268 hwid = 0;
269 if (nspec < 3)
270 vwid = 0;
271 if (!(filp = fopen(eps, "r")))
272 return;
273 if (!fgets(buf, sizeof(buf), filp) ||
274 (strcmp(buf, "%!PS-Adobe-2.0 EPSF-1.2\n") &&
275 strcmp(buf, "%!PS-Adobe-2.0 EPSF-2.0\n") &&
276 strcmp(buf, "%!PS-Adobe-3.0 EPSF-3.0\n"))) {
277 fclose(filp);
278 return;
280 nbb = 0;
281 while (fgets(buf, sizeof(buf), filp))
282 if (!strncmp(buf, "%%BoundingBox: ", 15))
283 if ((nbb = sscanf(buf + 15, "%d %d %d %d",
284 &llx, &lly, &urx, &ury)) == 4)
285 break;
286 fclose(filp);
287 if (nbb < 4) /* no BoundingBox comment */
288 return;
289 if (hwid <= 0 && vwid <= 0)
290 hwid = (urx - llx) * dev_res / 72;
291 if (vwid <= 0)
292 vwid = (ury - lly) * hwid / (urx - llx);
293 if (hwid <= 0)
294 hwid = (urx - llx) * vwid / (ury - lly);
295 /* output the EPS file */
296 o_flush();
297 out_fontup(o_f);
298 outf("%d %d %d %d %d %d %d %d EPSFBEG\n",
299 llx, lly, hwid, urx - llx, vwid, ury - lly, o_h, o_v);
300 outf("%%%%BeginDocument: %s\n", eps);
301 filp = fopen(eps, "r");
302 while (fgets(buf, sizeof(buf), filp))
303 out("%s", buf);
304 fclose(filp);
305 outf("%%%%EndDocument\n");
306 outf("EPSFEND\n");