ref: e2c403d472c36127b088c79dc8725eafa5ef5543
parent: faf8b47f415acb6c1492798d86d4e2fa6eb500c6
author: cinap_lenrek <cinap_lenrek@centraldogma>
date: Sat Sep 10 00:28:29 EDT 2011
npage: fetch pages individualy for pdf
--- a/sys/src/cmd/npage.c
+++ b/sys/src/cmd/npage.c
@@ -132,7 +132,6 @@
int pfd[2];
if(pipe(pfd) < 0){
- fprint(2, "pipe: %r\n");
Err:
dup(nullfd, fd);
return;
@@ -139,7 +138,6 @@
}
switch(rfork(RFPROC|RFFDG|RFNOWAIT)){
case -1:
- fprint(2, "rfork: %r\n");
close(pfd[0]);
close(pfd[1]);
goto Err;
@@ -172,7 +170,6 @@
int fd;
if((fd = dup(p->fd, -1)) < 0){
- fprint(2, "popenconv: dup: %r\n");
close(p->fd);
p->fd = -1;
return -1;
@@ -183,26 +180,73 @@
return fd;
}
+typedef struct Ghost Ghost;
+struct Ghost
+{
+ QLock;
+
+ int pin;
+ int pout;
+ int pdat;
+};
+
int
+popenpdf(Page *p)
+{
+ char buf[8*1024];
+ int n, pfd[2];
+ Ghost *gs;
+
+ if(pipe(pfd) < 0)
+ return -1;
+ switch(rfork(RFFDG|RFPROC|RFMEM|RFNOWAIT)){
+ case -1:
+ close(pfd[0]);
+ close(pfd[1]);
+ return -1;
+ case 0:
+ close(pfd[0]);
+ gs = p->data;
+ qlock(gs);
+ fprint(gs->pin, "%s DoPDFPage\n"
+ "(/fd/3) (w) file "
+ "dup flushfile "
+ "dup (THIS IS NOT AN INFERNO BITMAP\\n) writestring "
+ "flushfile\n", p->label);
+ while((n = read(gs->pdat, buf, sizeof buf)) > 0){
+ if(memcmp(buf, "THIS IS NOT AN INFERNO BITMAP\n", 30) == 0)
+ break;
+ write(pfd[1], buf, n);
+ }
+ qunlock(gs);
+ exits(nil);
+ }
+ close(pfd[1]);
+ return pfd[0];
+}
+
+int
popengs(Page *p)
{
- int n, i, ifd, ofd, pin[2], pout[2], pdat[2];
+ int n, i, pdf, ifd, ofd, pin[2], pout[2], pdat[2];
char buf[8*1024], nam[32], *argv[12];
+ pdf = 0;
ifd = p->fd;
- seek(ifd, 0, 0);
p->fd = -1;
+ seek(ifd, 0, 0);
+ if(read(ifd, buf, 5) != 5)
+ goto Err0;
+ seek(ifd, 0, 0);
+ if(memcmp(buf, "%PDF-", 5) == 0)
+ pdf = 1;
p->text = strdup(p->label);
- if(p->data)
- pipeline(ifd, "%s", (char*)p->data);
if(pipe(pin) < 0){
- fprint(2, "popengs: pipe: %r\n");
Err0:
close(ifd);
return -1;
}
if(pipe(pout) < 0){
- fprint(2, "popengs: pipe: %r\n");
Err1:
close(pin[0]);
close(pin[1]);
@@ -209,21 +253,27 @@
goto Err0;
}
if(pipe(pdat) < 0){
- fprint(2, "popengs: pipe: %r\n");
Err2:
close(pdat[0]);
close(pdat[1]);
goto Err1;
}
+
switch(rfork(RFPROC|RFFDG)){
case -1:
- fprint(2, "popengs: rfork: %r\n");
goto Err2;
case 0:
- if(dup(pin[1], 0)<0)
- exits("dup");
- if(dup(pout[1], 1)<0)
- exits("dup");
+ if(pdf){
+ if(dup(pin[1], 0)<0)
+ exits("dup");
+ if(dup(pout[1], 1)<0)
+ exits("dup");
+ } else {
+ if(dup(nullfd, 0)<0)
+ exits("dup");
+ if(dup(nullfd, 1)<0)
+ exits("dup");
+ }
if(dup(nullfd, 2)<0)
exits("dup");
if(dup(pdat[1], 3)<0)
@@ -239,17 +289,20 @@
close(pdat[1]);
close(ifd);
+ if(p->data)
+ pipeline(4, "%s", (char*)p->data);
+
argv[0] = "gs";
argv[1] = "-q";
argv[2] = "-sDEVICE=plan9";
argv[3] = "-sOutputFile=/fd/3";
argv[4] = "-dBATCH";
- argv[5] = "-dSAFER";
+ argv[5] = pdf ? "-dDELAYSAFER" : "-dSAFER";
argv[6] = "-dQUIET";
argv[7] = "-dTextAlphaBits=4";
argv[8] = "-dGraphicsAlphaBits=4";
argv[9] = "-r100";
- argv[10] = "/fd/4";
+ argv[10] = pdf ? "-" : "/fd/4";
argv[11] = nil;
exec("/bin/gs", argv);
exits("exec");
@@ -260,7 +313,47 @@
close(pdat[1]);
close(ifd);
- if(rfork(RFMEM|RFPROC) == 0){
+ if(pdf){
+ Ghost *gs;
+ char *prolog =
+ "/PAGEOUT (/fd/1) (w) file def\n"
+ "/PAGE== { PAGEOUT exch write==only PAGEOUT (\\n) writestring PAGEOUT flushfile } def\n"
+ "\n"
+ "/Page null def\n"
+ "/Page# 0 def\n"
+ "/PDFSave null def\n"
+ "/DSCPageCount 0 def\n"
+ "/DoPDFPage {dup /Page# exch store pdfgetpage pdfshowpage } def\n"
+ "\n"
+ "GS_PDF_ProcSet begin\n"
+ "pdfdict begin\n"
+ "(/fd/4) (r) file { DELAYSAFER { .setsafe } if } stopped pop pdfopen begin\n"
+ "\n"
+ "pdfpagecount PAGE==\n";
+
+ n = strlen(prolog);
+ if(write(pin[0], prolog, n) != n)
+ goto Out;
+ if((n = read(pout[0], buf, sizeof(buf)-1)) < 0)
+ goto Out;
+ buf[n] = 0;
+ n = atoi(buf);
+ if(n <= 0){
+ werrstr("no pages");
+ goto Out;
+ }
+ gs = mallocz(sizeof(*gs), 1);
+ gs->pin = pin[0];
+ gs->pout = pout[0];
+ gs->pdat = pdat[0];
+ for(i=1; i<=n; i++){
+ snprint(nam, sizeof nam, "%d", i);
+ addpage(p, nam, popenpdf, gs, -1);
+ }
+
+ /* keep ghostscript arround */
+ return -1;
+ } else {
i = 0;
ofd = -1;
while((n = read(pdat[0], buf, sizeof(buf))) >= 0){
@@ -273,40 +366,19 @@
break;
if(ofd < 0){
snprint(nam, sizeof nam, "%.4d", ++i);
- if((ofd = createtmp((ulong)p, nam)) < 0){
- fprint(2, "popengs: createtmp: %r\n");
+ if((ofd = createtmp((ulong)p, nam)) < 0)
ofd = dup(nullfd, -1);
- }
}
- if(write(ofd, buf, n) != n)
- fprint(2, "popengs: write tmp: %r\n");
+ write(ofd, buf, n);
}
if(ofd >= 0)
close(ofd);
- close(pdat[0]);
- exits(nil);
}
-
- for(;;){
- if((n = read(pout[0], buf, sizeof(buf)-1)) <= 0){
- if(n < 0)
- fprint(2, "popengs: read: %r\n");
- break;
- }
- buf[n] = 0;
- if(strstr(buf, "showpage") == 0)
- continue;
- if(write(pin[0], "\n", 1) != 1){
- fprint(2, "popengs: write: %r\n");
- break;
- }
- }
+Out:
close(pin[0]);
close(pout[0]);
-
+ close(pdat[0]);
waitpid();
- waitpid();
-
return -1;
}
@@ -610,10 +682,8 @@
if(new){
lockdisplay(display);
- if(getwindow(display, Refnone) == -1) {
- fprint(2, "getwindow: %r\n");
- exits("getwindow");
- }
+ if(getwindow(display, Refnone) == -1)
+ sysfatal("getwindow: %r");
unlockdisplay(display);
}