ps: put the findfont call near scalefont and setfont calls
[neatpost.git] / post.c
bloba1316572cdf5b39615cff58ae9ca9eb566d13b34
1 /*
2 * neatpost troff postscript postprocessor
4 * Copyright (C) 2013 Ali Gholami Rudi <ali at rudi dot ir>
6 * This program is released under the Modified BSD license.
7 */
8 #include <ctype.h>
9 #include <stdio.h>
10 #include <string.h>
11 #include "post.h"
13 static int o_pg;
15 static int next(void)
17 return getc(stdin);
20 static void back(int c)
22 ungetc(c, stdin);
25 static int utf8len(int c)
27 if (c <= 0x7f)
28 return 1;
29 if (c >= 0xfc)
30 return 6;
31 if (c >= 0xf8)
32 return 5;
33 if (c >= 0xf0)
34 return 4;
35 if (c >= 0xe0)
36 return 3;
37 if (c >= 0xc0)
38 return 2;
39 return 1;
42 static int nextutf8(char *s)
44 int c = next();
45 int l = utf8len(c);
46 int i;
47 if (c < 0)
48 return 0;
49 s[0] = c;
50 for (i = 1; i < l; i++)
51 s[i] = next();
52 s[l] = '\0';
53 return l;
56 /* skip blanks */
57 static void nextskip(void)
59 int c;
60 do {
61 c = next();
62 } while (isspace(c));
63 back(c);
66 static int nextnum(void)
68 int c;
69 int n = 0;
70 int neg = 0;
71 nextskip();
72 while (1) {
73 c = next();
74 if (!n && c == '-') {
75 neg = 1;
76 continue;
78 if (!isdigit(c))
79 back(c);
80 if (c < 0 || !isdigit(c))
81 break;
82 n = n * 10 + c - '0';
84 return neg ? -n : n;
87 static int iseol(void)
89 int c;
90 do {
91 c = next();
92 } while (c == ' ');
93 back(c);
94 return c == '\n';
97 /* skip until the end of line */
98 static void nexteol(void)
100 int c;
101 do {
102 c = next();
103 } while (c >= 0 && c != '\n');
106 static void nextword(char *s)
108 int c;
109 nextskip();
110 c = next();
111 while (c >= 0 && !isspace(c)) {
112 *s++ = c;
113 c = next();
115 if (c >= 0)
116 back(c);
117 *s = '\0';
120 /* read until eol */
121 static void readln(char *s)
123 int c;
124 c = next();
125 while (c > 0 && c != '\n') {
126 *s++ = c;
127 c = next();
129 if (c == '\n')
130 back(c);
131 *s = '\0';
134 static void postspline(int h1, int v1)
136 int h2, v2;
137 while (!iseol()) {
138 h2 = nextnum();
139 v2 = nextnum();
140 draws(h1, v1, h2, v2);
141 h1 = h2;
142 v1 = v2;
144 draws(h1, v1, 0, 0);
147 static void postdraw(void)
149 int h1, h2, v1, v2;
150 int c = next();
151 drawbeg(NULL);
152 switch (c) {
153 case 'l':
154 h1 = nextnum();
155 v1 = nextnum();
156 drawl(h1, v1);
157 break;
158 case 'c':
159 drawc(nextnum());
160 break;
161 case 'e':
162 h1 = nextnum();
163 v1 = nextnum();
164 drawe(h1, v1);
165 break;
166 case 'a':
167 h1 = nextnum();
168 v1 = nextnum();
169 h2 = nextnum();
170 v2 = nextnum();
171 drawa(h1, v1, h2, v2);
172 break;
173 case '~':
174 h1 = nextnum();
175 v1 = nextnum();
176 if (iseol())
177 drawl(h1, v1);
178 else
179 postspline(h1, v1);
180 break;
182 drawend(NULL);
183 nexteol();
186 static void postps(void)
188 char cmd[ILNLEN];
189 char arg[ILNLEN];
190 nextword(cmd);
191 readln(arg);
192 if (!strcmp("PS", cmd) || !strcmp("ps", cmd))
193 out("%s\n", arg);
194 if (!strcmp("BeginObject", cmd))
195 drawbeg(arg);
196 if (!strcmp("EndObject", cmd))
197 drawend(arg);
200 static char devpath[PATHLEN] = "devutf";
202 static void postx(void)
204 char cmd[128];
205 char dev[128];
206 int pos;
207 nextword(cmd);
208 switch (cmd[0]) {
209 case 'f':
210 pos = nextnum();
211 nextword(dev);
212 dev_mnt(pos, dev, dev);
213 outmnt(pos);
214 break;
215 case 'i':
216 dev_open(devpath);
217 break;
218 case 'T':
219 nextword(dev);
220 sprintf(devpath, "%s/font/dev%s", TROFFROOT, dev);
221 break;
222 case 's':
223 break;
224 case 'X':
225 postps();
226 break;
228 nexteol();
231 static void postcmd(int c)
233 char cs[GNLEN];
234 if (isdigit(c)) {
235 outrel((c - '0') * 10 + next() - '0', 0);
236 nextutf8(cs);
237 outc(cs);
238 return;
240 switch (c) {
241 case 's':
242 outsize(nextnum());
243 break;
244 case 'f':
245 outfont(nextnum());
246 break;
247 case 'H':
248 outh(nextnum());
249 break;
250 case 'V':
251 outv(nextnum());
252 break;
253 case 'h':
254 outrel(nextnum(), 0);
255 break;
256 case 'v':
257 outrel(0, nextnum());
258 break;
259 case 'c':
260 nextutf8(cs);
261 outc(cs);
262 break;
263 case 'm':
264 nextword(cs);
265 outcolor(clr_get(cs));
266 break;
267 case 'N':
268 nextnum();
269 break;
270 case 'C':
271 nextword(cs);
272 outc(cs);
273 break;
274 case 'p':
275 if (o_pg)
276 ps_pageend(o_pg);
277 o_pg = nextnum();
278 ps_pagebeg(o_pg);
279 outpage();
280 break;
281 case 'w':
282 break;
283 case 'n':
284 nextnum();
285 nextnum();
286 break;
287 case 'D':
288 postdraw();
289 break;
290 case 'x':
291 postx();
292 break;
293 case '#':
294 nexteol();
295 break;
296 default:
297 fprintf(stderr, "unknown command: %c\n", c);
301 static void post(void)
303 int c;
304 while ((c = next()) >= 0)
305 if (!isspace(c))
306 postcmd(c);
307 if (o_pg)
308 ps_pageend(o_pg);
311 int main(void)
313 ps_header();
314 post();
315 ps_trailer(o_pg, o_fonts);
316 return 0;