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