/* * pdf.c * * pdf file support for page */ #include #include #include #include #include #include #include "page.h" static Image* pdfdrawpage(Document *d, int page); static char* pdfpagename(Document*, int); char *pdfprolog = #include "pdfprolog.c" ; Rectangle pdfbbox(GSInfo *gs) { char *p; char *f[4]; Rectangle r; r = Rect(0,0,0,0); waitgs(gs); gscmd(gs, "/CropBox knownoget {} {[0 0 0 0]} ifelse PAGE==\n"); p = Brdline(&gs->gsrd, '\n'); p[Blinelen(&gs->gsrd)-1] ='\0'; if(p[0] != '[') return r; if(tokenize(p+1, f, 4) != 4) return r; r = Rect(atoi(f[0]), atoi(f[1]), atoi(f[2]), atoi(f[3])); waitgs(gs); return r; } Document* initpdf(Biobuf *b, int argc, char **argv, uchar *buf, int nbuf) { Document *d; PDFInfo *pdf; char *p; char *fn; char fdbuf[20]; int fd; int i, npage; Rectangle bbox; if(argc > 1) { fprint(2, "can only view one pdf file at a time\n"); return nil; } fprint(2, "reading through pdf...\n"); if(b == nil){ /* standard input; spool to disk (ouch) */ fd = spooltodisk(buf, nbuf, &fn); sprint(fdbuf, "/dev/fd/%d", fd); b = Bopen(fdbuf, OREAD); if(b == nil){ fprint(2, "cannot open disk spool file\n"); wexits("Bopen temp"); } }else fn = argv[0]; /* sanity check */ Bseek(b, 0, 0); if(!(p = Brdline(b, '\n')) && !(p = Brdline(b, '\r'))) { fprint(2, "cannot find end of first line\n"); wexits("initps"); } if(strncmp(p, "%PDF-", 5) != 0) { werrstr("not pdf"); return nil; } /* setup structures so one free suffices */ p = emalloc(sizeof(*d) + sizeof(*pdf)); d = (Document*) p; p += sizeof(*d); pdf = (PDFInfo*) p; d->extra = pdf; d->b = b; d->drawpage = pdfdrawpage; d->pagename = pdfpagename; d->fwdonly = 0; d->type = Tpdf; if(spawngs(&pdf->gs, "-dDELAYSAFER") < 0) return nil; gscmd(&pdf->gs, "%s", pdfprolog); waitgs(&pdf->gs); setdim(&pdf->gs, Rect(0,0,0,0), ppi, 0); gscmd(&pdf->gs, "(%s) (r) file { DELAYSAFER { .setsafe } if } stopped pop pdfopen begin\n", fn); gscmd(&pdf->gs, "pdfpagecount PAGE==\n"); p = Brdline(&pdf->gs.gsrd, '\n'); npage = atoi(p); if(npage < 1) { fprint(2, "no pages?\n"); return nil; } d->npage = npage; d->docname = argv[0]; gscmd(&pdf->gs, "Trailer\n"); bbox = pdfbbox(&pdf->gs); pdf->pagebbox = emalloc(sizeof(Rectangle)*npage); for(i=0; igs, "%d pdfgetpage\n", i+1); pdf->pagebbox[i] = pdfbbox(&pdf->gs); if(Dx(pdf->pagebbox[i]) <= 0) pdf->pagebbox[i] = bbox; } return d; } static Image* pdfdrawpage(Document *doc, int page) { PDFInfo *pdf = doc->extra; Image *im; gscmd(&pdf->gs, "%d DoPDFPage\n", page+1); im = convert(&pdf->gs.g); if(im == nil) { fprint(2, "fatal: readimage error %r\n"); wexits("readimage"); } waitgs(&pdf->gs); return im; } static char* pdfpagename(Document *d, int page) { static char str[15]; USED(d); sprint(str, "p %d", page+1); return str; }