]> www.fi.muni.cz Git - evince.git/blob - pdf/xpdf/PDFDoc.cc
06b1cd7926f3e5f5fb64bae980544862a5e691d0
[evince.git] / pdf / xpdf / PDFDoc.cc
1 //========================================================================
2 //
3 // PDFDoc.cc
4 //
5 // Copyright 1996 Derek B. Noonburg
6 //
7 //========================================================================
8
9 #ifdef __GNUC__
10 #pragma implementation
11 #endif
12
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <stddef.h>
16 #include <string.h>
17 #include "GString.h"
18 #include "config.h"
19 #include "Page.h"
20 #include "Catalog.h"
21 #include "Stream.h"
22 #include "XRef.h"
23 #include "Link.h"
24 #include "OutputDev.h"
25 #include "Params.h"
26 #include "Error.h"
27 #include "PDFDoc.h"
28
29 //------------------------------------------------------------------------
30
31 #define headerSearchSize 1024   // read this many bytes at beginning of
32                                 //   file to look for '%PDF'
33
34 //------------------------------------------------------------------------
35 // PDFDoc
36 //------------------------------------------------------------------------
37
38 PDFDoc::PDFDoc(GString *fileName1) {
39   Object obj;
40   GString *fileName2;
41
42   ok = gFalse;
43
44   file = NULL;
45   str = NULL;
46
47   // try to open file
48   fileName = fileName1;
49   fileName2 = NULL;
50 #ifdef VMS
51   if (!(file = fopen(fileName->getCString(), "rb", "ctx=stm"))) {
52     error(-1, "Couldn't open file '%s'", fileName->getCString());
53     return;
54   }
55 #else
56   if (!(file = fopen(fileName->getCString(), "rb"))) {
57     fileName2 = fileName->copy();
58     fileName2->lowerCase();
59     if (!(file = fopen(fileName2->getCString(), "rb"))) {
60       fileName2->upperCase();
61       if (!(file = fopen(fileName2->getCString(), "rb"))) {
62         error(-1, "Couldn't open file '%s'", fileName->getCString());
63         delete fileName2;
64         return;
65       }
66     }
67     delete fileName2;
68   }
69 #endif
70
71   // create stream
72   obj.initNull();
73   str = new FileStream(file, 0, -1, &obj);
74
75   ok = setup();
76 }
77
78 PDFDoc::PDFDoc(BaseStream *str) {
79   ok = gFalse;
80   fileName = NULL;
81   file = NULL;
82   this->str = str;
83   ok = setup();
84 }
85
86 GBool PDFDoc::setup() {
87   Object catObj;
88
89   xref = NULL;
90   catalog = NULL;
91   links = NULL;
92
93   // check header
94   checkHeader();
95
96   // read xref table
97   xref = new XRef(str);
98   if (!xref->isOk()) {
99     error(-1, "Couldn't read xref table");
100     return gFalse;
101   }
102
103   // read catalog
104   catalog = new Catalog(xref->getCatalog(&catObj));
105   catObj.free();
106   if (!catalog->isOk()) {
107     error(-1, "Couldn't read page catalog");
108     return gFalse;
109   }
110
111   // done
112   return gTrue;
113 }
114
115 PDFDoc::~PDFDoc() {
116   if (catalog) {
117     delete catalog;
118   }
119   if (xref) {
120     delete xref;
121   }
122   if (str) {
123     delete str;
124   }
125   if (file) {
126     fclose(file);
127   }
128   if (fileName) {
129     delete fileName;
130   }
131   if (links) {
132     delete links;
133   }
134 }
135
136 // Check for a PDF header on this stream.  Skip past some garbage
137 // if necessary.
138 void PDFDoc::checkHeader() {
139   char hdrBuf[headerSearchSize+1];
140   char *p;
141   double version;
142   int i;
143
144   for (i = 0; i < headerSearchSize; ++i) {
145     hdrBuf[i] = str->getChar();
146   }
147   hdrBuf[headerSearchSize] = '\0';
148   for (i = 0; i < headerSearchSize - 5; ++i) {
149     if (!strncmp(&hdrBuf[i], "%PDF-", 5)) {
150       break;
151     }
152   }
153   if (i >= headerSearchSize - 5) {
154     error(-1, "May not be a PDF file (continuing anyway)");
155     return;
156   }
157   str->moveStart(i);
158   p = strtok(&hdrBuf[i+5], " \t\n\r");
159   version = atof(p);
160   if (!(hdrBuf[i+5] >= '0' && hdrBuf[i+5] <= '9') ||
161       version > pdfVersionNum + 0.0001) {
162     error(-1, "PDF version %s -- xpdf supports version %s"
163           " (continuing anyway)", p, pdfVersion);
164   }
165 }
166
167 void PDFDoc::displayPage(OutputDev *out, int page, int zoom, int rotate,
168                          GBool doLinks) {
169   Link *link;
170   double x1, y1, x2, y2;
171   double w;
172   int i;
173
174   if (printCommands)
175     printf("***** page %d *****\n", page);
176   catalog->getPage(page)->display(out, zoom, rotate);
177   if (doLinks) {
178     if (links)
179       delete links;
180     getLinks(page);
181     for (i = 0; i < links->getNumLinks(); ++i) {
182       link = links->getLink(i);
183       link->getBorder(&x1, &y1, &x2, &y2, &w);
184       if (w > 0)
185         out->drawLinkBorder(x1, y1, x2, y2, w);
186     }
187     out->dump();
188   }
189 }
190
191 void PDFDoc::displayPages(OutputDev *out, int firstPage, int lastPage,
192                           int zoom, int rotate) {
193   Page *p;
194   int page;
195
196   for (page = firstPage; page <= lastPage; ++page) {
197     if (printCommands)
198       printf("***** page %d *****\n", page);
199     p = catalog->getPage(page);
200     p->display(out, zoom, rotate);
201   }
202 }
203
204 GBool PDFDoc::saveAs(GString *name) {
205   FILE *f;
206   int c;
207
208   if (!(f = fopen(name->getCString(), "wb"))) {
209     error(-1, "Couldn't open file '%s'", name->getCString());
210     return gFalse;
211   }
212   str->reset();
213   while ((c = str->getChar()) != EOF) {
214     fputc(c, f);
215   }
216   fclose(f);
217   return gTrue;
218 }
219
220 void PDFDoc::getLinks(int page) {
221   Object obj;
222
223   links = new Links(catalog->getPage(page)->getAnnots(&obj),
224                     catalog->getBaseURI());
225   obj.free();
226 }