2 * NEATPOST: NEATROFF'S POSTSCRIPT/PDF POSTPROCESSOR
4 * Copyright (C) 2013-2018 Ali Gholami Rudi <ali at rudi dot ir>
6 * Permission to use, copy, modify, and/or distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
24 static char *ps_title
; /* document title */
25 static int ps_pagewidth
= 2159; /* page width (tenths of a millimetre) */
26 static int ps_pageheight
= 2794;/* page height (tenths of a millimetre) */
27 static int ps_linewidth
= 40; /* drawing line thickness in thousandths of an em */
28 static int o_pages
; /* output pages */
35 static void back(int c
)
40 static int utf8len(int c
)
57 static int nextutf8(char *s
)
65 for (i
= 1; i
< l
; i
++)
72 static void nextskip(void)
81 static int nextnum(void)
89 if (!n
&& (c
== '-' || c
== '+')) {
95 if (c
< 0 || !isdigit(c
))
102 static int readnum(int *n
)
109 if (c
== '-' || c
== '+' || (c
>= '0' && c
<= '9')) {
116 static int iseol(void)
126 /* skip until the end of line */
127 static void nexteol(void)
132 } while (c
>= 0 && c
!= '\n');
135 static void nextword(char *s
)
140 while (c
>= 0 && !isspace(c
)) {
150 static void readln(char *s
)
154 while (c
> 0 && c
!= '\n') {
163 static void postline(void)
166 while (!readnum(&h
) && !readnum(&v
))
170 static void postarc(void)
173 if (!readnum(&h1
) && !readnum(&v1
) && !readnum(&h2
) && !readnum(&v2
))
174 drawa(h1
, v1
, h2
, v2
);
177 static void postspline(void)
186 while (!readnum(&h2
) && !readnum(&v2
)) {
187 draws(h1
, v1
, h2
, v2
);
194 static void postpoly(void)
198 while (!iseol() && (l
== 'l' || l
== '~' || l
== 'a')) {
203 if (c
!= '-' && c
!= '+' && (c
< '0' || c
> '9')) {
205 while (c
>= 0 && !isspace(c
))
218 static void postdraw(void)
223 switch (tolower(c
)) {
247 drawend(c
== 'p' || c
== 'P', c
== 'E' || c
== 'C' || c
== 'P');
251 static void postps(void)
257 if (!strcmp("PS", cmd
) || !strcmp("ps", cmd
))
259 if (!strcmp("rotate", cmd
))
260 outrotate(atoi(arg
));
261 if (!strcmp("eps", cmd
))
263 if (!strcmp("pdf", cmd
))
265 if (!strcmp("link", cmd
))
267 if (!strcmp("BeginObject", cmd
))
269 if (!strcmp("EndObject", cmd
))
273 static char postdir
[PATHLEN
] = TROFFFDIR
; /* output device directory */
274 static char postdev
[PATHLEN
] = "utf"; /* output device name */
276 static void postx(void)
286 dev_mnt(pos
, font
, font
);
290 if (dev_open(postdir
, postdev
)) {
291 fprintf(stderr
, "neatpost: cannot open device %s\n", postdev
);
294 ps_header(ps_title
, ps_pagewidth
, ps_pageheight
, ps_linewidth
);
308 static void postcmd(int c
)
312 outrel((c
- '0') * 10 + next() - '0', 0);
331 outrel(nextnum(), 0);
334 outrel(0, nextnum());
342 outcolor(clr_get(cs
));
374 fprintf(stderr
, "neatpost: unknown command %c\n", c
);
379 static void post(void)
382 while ((c
= next()) >= 0)
389 static struct paper
{
393 {"letter", 2159, 2794},
394 {"legal", 2159, 3556},
395 {"ledger", 4318, 2794},
396 {"tabloid", 2794, 4318},
399 static void setpagesize(char *s
)
402 /* predefined paper sizes */
403 for (i
= 0; i
< LEN(papers
); i
++) {
404 if (!strcmp(papers
[i
].name
, s
)) {
405 ps_pagewidth
= papers
[i
].w
;
406 ps_pageheight
= papers
[i
].h
;
410 /* custom paper size in mm, like 2100x2970 for a4 */
411 if (isdigit(s
[0]) && strchr(s
, 'x')) {
412 ps_pagewidth
= atoi(s
);
413 ps_pageheight
= atoi(strchr(s
, 'x') + 1);
416 /* ISO paper sizes */
417 if (!strchr("abcABC", s
[0]) || !isdigit(s
[1]))
419 if (tolower(s
[0]) == 'a') {
423 if (tolower(s
[0]) == 'b') {
427 if (tolower(s
[0]) == 'c') {
432 ps_pagewidth
= ((n
& 1) ? d2
: d1
) >> ((n
+ 1) >> 1);
433 ps_pageheight
= ((n
& 1) ? d1
: d2
) >> (n
>> 1);
434 ps_pagewidth
-= ps_pagewidth
% 10;
435 ps_pageheight
-= ps_pageheight
% 10;
438 void *mextend(void *old
, long oldsz
, long newsz
, int memsz
)
440 void *new = malloc(newsz
* memsz
);
441 memcpy(new, old
, oldsz
* memsz
);
442 memset(new + oldsz
* memsz
, 0, (newsz
- oldsz
) * memsz
);
448 "Usage: neatpost [options] <input >output\n"
450 " -F dir \tset font directory (" TROFFFDIR
")\n"
451 " -p size \tset paper size (letter); e.g., a4, 2100x2970\n"
452 " -t title\tspecify document title\n"
453 " -w lwid \tdrawing line thickness in thousandths of an em (40)\n"
454 " -n \talways draw glyphs by name (ps glyphshow)\n";
456 int main(int argc
, char *argv
[])
459 for (i
= 1; i
< argc
; i
++) {
460 if (argv
[i
][0] == '-' && argv
[i
][1] == 'F') {
461 strcpy(postdir
, argv
[i
][2] ? argv
[i
] + 2 : argv
[++i
]);
462 } else if (argv
[i
][0] == '-' && argv
[i
][1] == 'p') {
463 setpagesize(argv
[i
][2] ? argv
[i
] + 2 : argv
[++i
]);
464 } else if (argv
[i
][0] == '-' && argv
[i
][1] == 'w') {
465 ps_linewidth
= atoi(argv
[i
][2] ? argv
[i
] + 2 : argv
[++i
]);
466 } else if (argv
[i
][0] == '-' && argv
[i
][1] == 'n') {
468 } else if (argv
[i
][0] == '-' && argv
[i
][1] == 't') {
469 ps_title
= argv
[i
][2] ? argv
[i
] + 2 : argv
[++i
];