2 * NEATPOST: NEATROFF'S POSTSCRIPT POSTPROCESSOR
4 * Copyright (C) 2013-2017 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("link", cmd
))
265 if (!strcmp("BeginObject", cmd
))
267 if (!strcmp("EndObject", cmd
))
271 static char postdir
[PATHLEN
] = TROFFFDIR
; /* output device directory */
272 static char postdev
[PATHLEN
] = "utf"; /* output device name */
274 static void postx(void)
284 dev_mnt(pos
, font
, font
);
288 if (dev_open(postdir
, postdev
)) {
289 fprintf(stderr
, "neatpost: cannot open device %s\n", postdev
);
292 ps_header(ps_title
, ps_pagewidth
, ps_pageheight
, ps_linewidth
);
306 static void postcmd(int c
)
310 outrel((c
- '0') * 10 + next() - '0', 0);
329 outrel(nextnum(), 0);
332 outrel(0, nextnum());
340 outcolor(clr_get(cs
));
372 fprintf(stderr
, "neatpost: unknown command %c\n", c
);
377 static void post(void)
380 while ((c
= next()) >= 0)
387 static struct paper
{
391 {"letter", 2159, 2794},
392 {"legal", 2159, 3556},
393 {"ledger", 4318, 2794},
394 {"tabloid", 2794, 4318},
397 static void setpagesize(char *s
)
400 /* predefined paper sizes */
401 for (i
= 0; i
< LEN(papers
); i
++) {
402 if (!strcmp(papers
[i
].name
, s
)) {
403 ps_pagewidth
= papers
[i
].w
;
404 ps_pageheight
= papers
[i
].h
;
408 /* custom paper size in mm, like 2100x2970 for a4 */
409 if (isdigit(s
[0]) && strchr(s
, 'x')) {
410 ps_pagewidth
= atoi(s
);
411 ps_pageheight
= atoi(strchr(s
, 'x') + 1);
414 /* ISO paper sizes */
415 if (!strchr("abcABC", s
[0]) || !isdigit(s
[1]))
417 if (tolower(s
[0]) == 'a') {
421 if (tolower(s
[0]) == 'b') {
425 if (tolower(s
[0]) == 'c') {
430 ps_pagewidth
= ((n
& 1) ? d2
: d1
) >> ((n
+ 1) >> 1);
431 ps_pageheight
= ((n
& 1) ? d1
: d2
) >> (n
>> 1);
432 ps_pagewidth
-= ps_pagewidth
% 10;
433 ps_pageheight
-= ps_pageheight
% 10;
436 static void errdie(char *msg
)
438 fprintf(stderr
, msg
);
442 void *mextend(void *old
, long oldsz
, long newsz
, int memsz
)
444 void *new = xmalloc(newsz
* memsz
);
445 memcpy(new, old
, oldsz
* memsz
);
446 memset(new + oldsz
* memsz
, 0, (newsz
- oldsz
) * memsz
);
451 void *xmalloc(long len
)
453 void *m
= malloc(len
);
455 errdie("neatroff: malloc() failed\n");
460 "Usage: neatpost [options] <input >output\n"
462 " -F dir \tset font directory (" TROFFFDIR
")\n"
463 " -p size \tset paper size (letter); e.g., a4, 2100x2970\n"
464 " -t title\tspecify document title\n"
465 " -w lwid \tdrawing line thickness in thousandths of an em (40)\n"
466 " -n \talways draw glyphs by name (ps glyphshow)\n";
468 int main(int argc
, char *argv
[])
471 for (i
= 1; i
< argc
; i
++) {
472 if (argv
[i
][0] == '-' && argv
[i
][1] == 'F') {
473 strcpy(postdir
, argv
[i
][2] ? argv
[i
] + 2 : argv
[++i
]);
474 } else if (argv
[i
][0] == '-' && argv
[i
][1] == 'p') {
475 setpagesize(argv
[i
][2] ? argv
[i
] + 2 : argv
[++i
]);
476 } else if (argv
[i
][0] == '-' && argv
[i
][1] == 'w') {
477 ps_linewidth
= atoi(argv
[i
][2] ? argv
[i
] + 2 : argv
[++i
]);
478 } else if (argv
[i
][0] == '-' && argv
[i
][1] == 'n') {
480 } else if (argv
[i
][0] == '-' && argv
[i
][1] == 't') {
481 ps_title
= argv
[i
][2] ? argv
[i
] + 2 : argv
[++i
];
488 ps_trailer(o_pages
, o_fonts
);