npage: fetch pages individualy for pdf

front
cinap_lenrek 2011-09-10 04:28:29 +02:00
parent faf8b47f41
commit e2c403d472
1 changed files with 117 additions and 47 deletions

View File

@ -132,14 +132,12 @@ pipeline(int fd, char *fmt, ...)
int pfd[2];
if(pipe(pfd) < 0){
fprint(2, "pipe: %r\n");
Err:
dup(nullfd, fd);
return;
}
switch(rfork(RFPROC|RFFDG|RFNOWAIT)){
case -1:
fprint(2, "rfork: %r\n");
close(pfd[0]);
close(pfd[1]);
goto Err;
@ -172,7 +170,6 @@ popenconv(Page *p)
int fd;
if((fd = dup(p->fd, -1)) < 0){
fprint(2, "popenconv: dup: %r\n");
close(p->fd);
p->fd = -1;
return -1;
@ -183,47 +180,100 @@ popenconv(Page *p)
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]);
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 @@ popengs(Page *p)
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 @@ popengs(Page *p)
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 @@ popengs(Page *p)
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 @@ void eresized(int new)
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);
}