URI:
       tpdf.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       tpdf.c (3167B)
       ---
            1 /*
            2  * pdf.c
            3  *
            4  * pdf file support for page
            5  */
            6 
            7 #include <u.h>
            8 #include <libc.h>
            9 #include <draw.h>
           10 #include <cursor.h>
           11 #include <thread.h>
           12 #include <bio.h>
           13 #include "page.h"
           14 
           15 static Image*        pdfdrawpage(Document *d, int page);
           16 static char*        pdfpagename(Document*, int);
           17 
           18 char *pdfprolog =
           19 #include "pdfprolog.c"
           20         ;
           21 
           22 Rectangle
           23 pdfbbox(GSInfo *gs)
           24 {
           25         char *p;
           26         char *f[4];
           27         Rectangle r;
           28 
           29         r = Rect(0,0,0,0);
           30         waitgs(gs);
           31         gscmd(gs, "/CropBox knownoget {} {[0 0 0 0]} ifelse PAGE==\n");
           32         p = Brdline(&gs->gsrd, '\n');
           33         p[Blinelen(&gs->gsrd)-1] ='\0';
           34         if(p[0] != '[')
           35                 return r;
           36         if(tokenize(p+1, f, 4) != 4)
           37                 return r;
           38         r = Rect(atoi(f[0]), atoi(f[1]), atoi(f[2]), atoi(f[3]));
           39         waitgs(gs);
           40         return r;
           41 }
           42 
           43 Document*
           44 initpdf(Biobuf *b, int argc, char **argv, uchar *buf, int nbuf)
           45 {
           46         Document *d;
           47         PDFInfo *pdf;
           48         char *p;
           49         char *fn;
           50         char fdbuf[20];
           51         int fd;
           52         int i, npage;
           53         Rectangle bbox;
           54 
           55         if(argc > 1) {
           56                 fprint(2, "can only view one pdf file at a time\n");
           57                 return nil;
           58         }
           59 
           60         fprint(2, "reading through pdf...\n");
           61         if(b == nil){        /* standard input; spool to disk (ouch) */
           62                 fd = spooltodisk(buf, nbuf, &fn);
           63                 sprint(fdbuf, "/dev/fd/%d", fd);
           64                 b = Bopen(fdbuf, OREAD);
           65                 if(b == nil){
           66                         fprint(2, "cannot open disk spool file\n");
           67                         wexits("Bopen temp");
           68                 }
           69         }else
           70                 fn = argv[0];
           71 
           72         /* sanity check */
           73         Bseek(b, 0, 0);
           74         if(!(p = Brdline(b, '\n')) && !(p = Brdline(b, '\r'))) {
           75                 fprint(2, "cannot find end of first line\n");
           76                 wexits("initps");
           77         }
           78         if(strncmp(p, "%PDF-", 5) != 0) {
           79                 werrstr("not pdf");
           80                 return nil;
           81         }
           82 
           83         /* setup structures so one free suffices */
           84         p = emalloc(sizeof(*d) + sizeof(*pdf));
           85         d = (Document*) p;
           86         p += sizeof(*d);
           87         pdf = (PDFInfo*) p;
           88 
           89         d->extra = pdf;
           90         d->b = b;
           91         d->drawpage = pdfdrawpage;
           92         d->pagename = pdfpagename;
           93         d->fwdonly = 0;
           94         d->type = Tpdf;
           95 
           96         if(spawngs(&pdf->gs, "-dDELAYSAFER") < 0)
           97                 return nil;
           98 
           99         gscmd(&pdf->gs, "%s", pdfprolog);
          100         waitgs(&pdf->gs);
          101 
          102         setdim(&pdf->gs, Rect(0,0,0,0), ppi, 0);
          103         gscmd(&pdf->gs, "(%s) (r) file { DELAYSAFER { .setsafe } if } stopped pop pdfopen begin\n", fn);
          104         gscmd(&pdf->gs, "pdfpagecount PAGE==\n");
          105         p = Brdline(&pdf->gs.gsrd, '\n');
          106         if(p == nil) {
          107                 if(Blinelen(&pdf->gs.gsrd) > 0) {
          108                         fprint(2, "unexpected output (too long) from gs\n");
          109                         return nil;
          110                 }
          111                 fprint(2, "early EOF from gs - is ghostscript installed?\n");
          112                 return nil;
          113         }
          114         npage = atoi(p);
          115         if(npage < 1) {
          116                 fprint(2, "no pages?\n");
          117                 return nil;
          118         }
          119         d->npage = npage;
          120         d->docname = argv[0];
          121 
          122         gscmd(&pdf->gs, "Trailer\n");
          123         bbox = pdfbbox(&pdf->gs);
          124 
          125         pdf->pagebbox = emalloc(sizeof(Rectangle)*npage);
          126         for(i=0; i<npage; i++) {
          127                 gscmd(&pdf->gs, "%d pdfgetpage\n", i+1);
          128                 pdf->pagebbox[i] = pdfbbox(&pdf->gs);
          129                 if(Dx(pdf->pagebbox[i]) <= 0)
          130                         pdf->pagebbox[i] = bbox;
          131         }
          132         return d;
          133 }
          134 
          135 static Image*
          136 pdfdrawpage(Document *doc, int page)
          137 {
          138         PDFInfo *pdf = doc->extra;
          139         Image *im;
          140 
          141         gscmd(&pdf->gs, "%d DoPDFPage\n", page+1);
          142         im = convert(&pdf->gs.g);
          143         if(im == nil) {
          144                 fprint(2, "fatal: readimage error %r\n");
          145                 wexits("readimage");
          146         }
          147         waitgs(&pdf->gs);
          148         return im;
          149 }
          150 
          151 static char*
          152 pdfpagename(Document *d, int page)
          153 {
          154         static char str[15];
          155 
          156         USED(d);
          157         sprint(str, "p %d", page+1);
          158         return str;
          159 }