post: support "x X PS"
[neatpost.git] / out.c
blobc20e86357511aeef6937a8e875d9ecaa537d553f
1 #include <ctype.h>
2 #include <stdarg.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include "post.h"
8 static int o_f, o_s; /* font and size */
9 static int o_h, o_v; /* current user position */
10 static int p_f, p_s; /* output postscript font */
11 static int o_qtype; /* queued character type */
12 static int o_qv, o_qh, o_qend; /* queued character position */
13 char o_fonts[FNLEN * NFONTS] = " ";
15 static void outvf(char *s, va_list ap)
17 vfprintf(stdout, s, ap);
20 void outf(char *s, ...)
22 va_list ap;
23 va_start(ap, s);
24 outvf(s, ap);
25 va_end(ap);
28 static void o_flush(void)
30 if (o_qtype == 1)
31 outf(") %d %d w\n", o_qh, o_qv);
32 if (o_qtype == 2)
33 outf("] %d %d g\n", o_qh, o_qv);
34 o_qtype = 0;
37 void outpage(void)
39 o_flush();
40 o_v = 0;
41 o_h = 0;
42 p_s = 0;
43 p_f = 0;
46 static void o_queue(struct glyph *g)
48 int type = 1 + !isdigit((g)->id[0]);
49 int num = atoi(g->id);
50 if (o_qtype != type || o_qend != o_h || o_qv != o_v) {
51 o_flush();
52 o_qh = o_h;
53 o_qv = o_v;
54 o_qtype = type;
55 outf(type == 1 ? "(" : "[");
57 if (o_qtype == 1) {
58 if (num >= ' ' && num <= '~')
59 outf("%s%c", strchr("()\\", num) ? "\\" : "", num);
60 else
61 outf("\\%d%d%d", (num >> 6) & 7, (num >> 3) & 7, num & 7);
62 } else {
63 outf("/%s", g->id);
65 o_qend = o_h + charwid(g->wid, o_s);
68 /* calls o_flush() if necessary */
69 void out(char *s, ...)
71 va_list ap;
72 o_flush();
73 va_start(ap, s);
74 outvf(s, ap);
75 va_end(ap);
78 /* glyph placement adjustments */
79 static struct fixlist {
80 char *name;
81 int dh, dv;
82 } fixlist[] = {
83 {"br", -5, 15},
84 {"lc", 20, 0},
85 {"lf", 20, 0},
86 {"rc", -11, 0},
87 {"rf", -11, 0},
88 {"rn", -50, 0},
91 static void fixpos(struct glyph *g, int *dh, int *dv)
93 struct font *fn = g->font;
94 int i;
95 *dh = 0;
96 *dv = 0;
97 if (!strcmp("S", fn->name)) {
98 for (i = 0; i < LEN(fixlist); i++) {
99 if (!strcmp(fixlist[i].name, g->name)) {
100 *dh = charwid(fixlist[i].dh, o_s);
101 *dv = charwid(fixlist[i].dv, o_s);
102 return;
108 static void out_fontup(int fid)
110 char fnname[FNLEN];
111 struct font *fn;
112 if (fid != p_f || o_s != p_s) {
113 fn = dev_font(fid);
114 out("%d /%s f\n", o_s, fn->psname);
115 p_f = fid;
116 p_s = o_s;
117 sprintf(fnname, " %s ", fn->psname);
118 if (!strstr(o_fonts, fnname))
119 sprintf(strchr(o_fonts, '\0'), "%s ", fn->psname);
123 void outc(char *c)
125 struct glyph *g;
126 struct font *fn;
127 int dh, dv;
128 g = dev_glyph(c, o_f);
129 fn = g ? g->font : dev_font(o_f);
130 if (!g) {
131 outrel(*c == ' ' && fn ? charwid(fn->spacewid, o_s) : 1, 0);
132 return;
134 out_fontup(dev_fontid(fn));
135 fixpos(g, &dh, &dv);
136 o_h += dh;
137 o_v += dv;
138 o_queue(g);
139 o_h -= dh;
140 o_v -= dv;
143 void outh(int h)
145 o_h = h;
148 void outv(int v)
150 o_v = v;
153 void outrel(int h, int v)
155 o_h += h;
156 o_v += v;
159 void outfont(int f)
161 o_f = f;
164 void outsize(int s)
166 o_s = s;
169 static int draw_path; /* number of path segments */
170 static int draw_point; /* point was set for postscript newpath */
172 static void drawmv(void)
174 if (!draw_point)
175 outf("%d %d m ", o_h, o_v);
176 draw_point = 1;
179 /* if s is not NULL, start a multi-segment path */
180 void drawbeg(char *s)
182 o_flush();
183 out_fontup(o_f);
184 if (draw_path)
185 return;
186 draw_path = s != NULL;
187 if (s)
188 outf("gsave newpath %s\n", s);
189 else
190 outf("newpath ");
193 void drawend(char *s)
195 if (draw_path && !s)
196 return;
197 draw_path = 0;
198 draw_point = 0;
199 if (s)
200 outf("%s grestore\n", s);
201 else
202 outf("stroke\n");
205 void drawl(int h, int v)
207 drawmv();
208 outrel(h, v);
209 outf("%d %d drawl ", o_h, o_v);
212 void drawc(int c)
214 drawmv();
215 outrel(c, 0);
216 outf("%d %d drawe ", c, c);
219 void drawe(int h, int v)
221 drawmv();
222 outrel(h, 0);
223 outf("%d %d drawe ", h, v);
226 void drawa(int h1, int v1, int h2, int v2)
228 drawmv();
229 outf("%d %d %d %d drawa ", h1, v1, h2, v2);
230 outrel(h1 + h2, v1 + v2);
233 void draws(int h1, int v1, int h2, int v2)
235 drawmv();
236 outf("%d %d %d %d %d %d draws ", o_h, o_v, o_h + h1, o_v + v1,
237 o_h + h1 + h2, o_v + v1 + v2);
238 outrel(h1, v1);