2 * gs interface for page.
3 * ps.c and pdf.c both use these routines.
4 * a caveat: if you run more than one gs, only the last
5 * one gets killed by killgs
15 static int gspid; /* globals for atexit */
17 static void killgs(void);
25 postnote(PNGROUP, getpid(), "die");
28 * from ghostscript's use.txt:
29 * ``Ghostscript currently doesn't do a very good job of deleting temporary
30 * files when it exits; you may have to delete them manually from time to
33 sprint(tmpfile, "/tmp/gs_%.5da", (gspid+300000)%100000);
34 if(chatty) fprint(2, "remove %s...\n", tmpfile);
37 postnote(PNPROC, gspid, "die yankee pig dog");
49 wexits("pipe failed");
53 while((n=read(pfd[0], buf, sizeof buf)) > 0) {
63 spawnmonitor(void *cp)
74 out = open("/dev/tty", OWRITE);
78 xbuf = buf; /* for ease of acid */
80 while((n = read(fd, xbuf, sizeof buf)) > 0){
83 fprint(2, "Ghostscript Error:\n");
92 spawngs(GSInfo *g, char *safer)
107 * gs's standard input is fed from stdinout.
108 * gs output written to fd-2 (i.e. output we generate intentionally) is fed to stdinout.
109 * gs output written to fd 1 (i.e. ouptut gs generates on error) is fed to errout.
110 * gs data output is written to fd 3, which is dataout.
112 if(pipe(stdinp)<0 || pipe(stdoutp)<0 || pipe(dataout)<0 || pipe(errout)<0)
116 args[nargs++] = "gs";
117 args[nargs++] = "-dNOPAUSE";
118 args[nargs++] = "-dDELAYSAFER";
119 args[nargs++] = "-sDEVICE=bmp16m";
120 args[nargs++] = "-sOutputFile=/dev/fd/3";
121 args[nargs++] = "-dQUIET";
122 args[nargs++] = "-r100";
123 sprint(tb, "-dTextAlphaBits=%d", textbits);
124 sprint(gb, "-dGraphicsAlphaBits=%d", gfxbits);
140 * Horrible problem: we want to dup fd's 0-4 below,
141 * but some of the source fd's might have those small numbers.
142 * So we need to reallocate those. In order to not step on
143 * anything else, we'll dup the fd's to higher ones using
144 * dup(x, -1), but we need to use up the lower ones first.
146 while((devnull = open("/dev/null", ORDWR)) < 5)
149 stdinp[0] = dup(stdinp[0], -1);
150 stdoutp[1] = dup(stdoutp[1], -1);
151 errout[1] = dup(errout[1], -1);
152 dataout[1] = dup(dataout[1], -1);
156 dup(errout[1], devnull); /* never anything useful */
170 cp = chancreate(sizeof(int), 0);
172 proccreate(spawnreader, cp, mainstacksize);
173 send(cp, &stdoutp[0]);
174 recv(cp, &stdoutp[0]);
177 gsfd = g->gsfd = stdinp[1];
179 g->g.fd = dataout[0];
180 g->g.name = "gs pipe";
183 proccreate(spawnmonitor, cp, mainstacksize);
184 send(cp, &errout[0]);
187 Binit(&g->gsrd, stdoutp[0], OREAD);
189 gscmd(g, "/PAGEOUT (/dev/fd/4) (w) file def\n");
190 if(!strcmp(safer, "-dSAFER"))
191 gscmd(g, ".setsafe\n");
192 gscmd(g, "/PAGE== { PAGEOUT exch write==only PAGEOUT (\\n) writestring PAGEOUT flushfile } def\n");
199 gscmd(GSInfo *gs, char *fmt, ...)
206 n = vseprint(buf, buf+sizeof buf, fmt, v) - buf;
215 if(write(gs->gsfd, buf, n) != 0)
222 * set the dimensions of the bitmap we expect to get back from GS.
225 setdim(GSInfo *gs, Rectangle bbox, int ppi, int landscape)
230 fprint(2, "setdim: bbox=%R\n", bbox);
237 gscmd(gs, "/HWResolution [%d %d]\n", ppi, ppi);
240 bbox = Rect(0, 0, 612, 792); /* 8½×11 */
247 pbox = Rect(bbox.min.y, bbox.min.x, bbox.max.y, bbox.max.x);
250 gscmd(gs, "/PageSize [%d %d]\n", Dx(pbox), Dy(pbox));
251 gscmd(gs, "/Margins [%d %d]\n", -pbox.min.x, -pbox.min.y);
252 gscmd(gs, "currentdevice putdeviceprops pop\n");
253 gscmd(gs, "/#copies 1 store\n");
255 if(!eqpt(bbox.min, ZP))
256 gscmd(gs, "%d %d translate\n", -bbox.min.x, -bbox.min.y);
262 gscmd(gs, "%d 0 translate\n", Dy(bbox));
263 gscmd(gs, "90 rotate\n");
273 /* we figure out that gs is done by telling it to
274 * print something and waiting until it does.
277 Biobuf *b = &gs->gsrd;
281 // gscmd(gs, "(\\n**bstack\\n) print flush\n");
282 // gscmd(gs, "stack flush\n");
283 // gscmd(gs, "(**estack\\n) print flush\n");
284 gscmd(gs, "(\\n//GO.SYSIN DD\\n) PAGE==\n");
288 p = Brdline(b, '\n');
298 p[Blinelen(b)-1] = 0;
299 if(chatty) fprint(2, "p: ");
300 if(chatty) write(2, p, Blinelen(b)-1);
301 if(chatty) fprint(2, "\n");
302 if(strstr(p, "Error:")) {
304 fprint(2, "ghostscript error: %s\n", p);
308 if(strstr(p, "//GO.SYSIN DD")) {