]> www.fi.muni.cz Git - evince.git/blob - pdf/xpdf/PDFDoc.cc
disable font embedding hack introduced on 2002-12-09 to fix build with
[evince.git] / pdf / xpdf / PDFDoc.cc
1 //========================================================================
2 //
3 // PDFDoc.cc
4 //
5 // Copyright 1996-2002 Glyph & Cog, LLC
6 //
7 //========================================================================
8
9 #ifdef __GNUC__
10 #pragma implementation
11 #endif
12
13 #include <aconf.h>
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <stddef.h>
17 #include <string.h>
18 #include "GString.h"
19 #include "config.h"
20 #include "Page.h"
21 #include "Catalog.h"
22 #include "Stream.h"
23 #include "XRef.h"
24 #include "Link.h"
25 #include "OutputDev.h"
26 #include "Error.h"
27 #include "ErrorCodes.h"
28 #include "Lexer.h"
29 #include "Parser.h"
30 #include "PDFDoc.h"
31
32 //------------------------------------------------------------------------
33
34 #define headerSearchSize 1024   // read this many bytes at beginning of
35                                 //   file to look for '%PDF'
36
37 //------------------------------------------------------------------------
38 // PDFDoc
39 //------------------------------------------------------------------------
40
41 PDFDoc::PDFDoc(GString *fileNameA, GString *ownerPassword,
42                GString *userPassword, GBool printCommandsA) {
43   Object obj;
44   GString *fileName2;
45
46   ok = gFalse;
47   errCode = errNone;
48
49   file = NULL;
50   str = NULL;
51   xref = NULL;
52   catalog = NULL;
53   links = NULL;
54   printCommands = printCommandsA;
55
56   // try to open file
57   fileName = fileNameA;
58   fileName2 = NULL;
59 #ifdef VMS
60   if (!(file = fopen(fileName->getCString(), "rb", "ctx=stm"))) {
61     error(-1, "Couldn't open file '%s'", fileName->getCString());
62     errCode = errOpenFile;
63     return;
64   }
65 #else
66   if (!(file = fopen(fileName->getCString(), "rb"))) {
67     fileName2 = fileName->copy();
68     fileName2->lowerCase();
69     if (!(file = fopen(fileName2->getCString(), "rb"))) {
70       fileName2->upperCase();
71       if (!(file = fopen(fileName2->getCString(), "rb"))) {
72         error(-1, "Couldn't open file '%s'", fileName->getCString());
73         delete fileName2;
74         errCode = errOpenFile;
75         return;
76       }
77     }
78     delete fileName2;
79   }
80 #endif
81
82   // create stream
83   obj.initNull();
84   str = new FileStream(file, 0, gFalse, 0, &obj);
85
86   ok = setup(ownerPassword, userPassword);
87 }
88
89 PDFDoc::PDFDoc(BaseStream *strA, GString *ownerPassword,
90                GString *userPassword, GBool printCommandsA) {
91   ok = gFalse;
92   errCode = errNone;
93   fileName = NULL;
94   file = NULL;
95   str = strA;
96   xref = NULL;
97   catalog = NULL;
98   links = NULL;
99   printCommands = printCommandsA;
100   ok = setup(ownerPassword, userPassword);
101 }
102
103 GBool PDFDoc::setup(GString *ownerPassword, GString *userPassword) {
104   // check header
105   checkHeader();
106
107   // read xref table
108   xref = new XRef(str, ownerPassword, userPassword);
109   if (!xref->isOk()) {
110     error(-1, "Couldn't read xref table");
111     errCode = xref->getErrorCode();
112     return gFalse;
113   }
114
115   // read catalog
116   catalog = new Catalog(xref, printCommands);
117   if (!catalog->isOk()) {
118     error(-1, "Couldn't read page catalog");
119     errCode = errBadCatalog;
120     return gFalse;
121   }
122
123   // done
124   return gTrue;
125 }
126
127 PDFDoc::~PDFDoc() {
128   if (catalog) {
129     delete catalog;
130   }
131   if (xref) {
132     delete xref;
133   }
134   if (str) {
135     delete str;
136   }
137   if (file) {
138     fclose(file);
139   }
140   if (fileName) {
141     delete fileName;
142   }
143   if (links) {
144     delete links;
145   }
146 }
147
148 // Check for a PDF header on this stream.  Skip past some garbage
149 // if necessary.
150 void PDFDoc::checkHeader() {
151   char hdrBuf[headerSearchSize+1];
152   char *p;
153   int i;
154
155   pdfVersion = 0;
156   for (i = 0; i < headerSearchSize; ++i) {
157     hdrBuf[i] = str->getChar();
158   }
159   hdrBuf[headerSearchSize] = '\0';
160   for (i = 0; i < headerSearchSize - 5; ++i) {
161     if (!strncmp(&hdrBuf[i], "%PDF-", 5)) {
162       break;
163     }
164   }
165   if (i >= headerSearchSize - 5) {
166     error(-1, "May not be a PDF file (continuing anyway)");
167     return;
168   }
169   str->moveStart(i);
170   p = strtok(&hdrBuf[i+5], " \t\n\r");
171   pdfVersion = atof(p);
172   if (!(hdrBuf[i+5] >= '0' && hdrBuf[i+5] <= '9') ||
173       pdfVersion > supportedPDFVersionNum + 0.0001) {
174     error(-1, "PDF version %s -- xpdf supports version %s"
175           " (continuing anyway)", p, supportedPDFVersionStr);
176   }
177 }
178
179 void PDFDoc::displayPage(OutputDev *out, int page, double zoom,
180                          int rotate, GBool doLinks) {
181   Page *p;
182
183   if (printCommands) {
184     printf("***** page %d *****\n", page);
185   }
186   p = catalog->getPage(page);
187   if (doLinks) {
188     if (links) {
189       delete links;
190       links = NULL;
191     }
192     getLinks(p);
193     p->display(out, zoom, rotate, links, catalog);
194   } else {
195     p->display(out, zoom, rotate, NULL, catalog);
196   }
197 }
198
199 void PDFDoc::displayPages(OutputDev *out, int firstPage, int lastPage,
200                           int zoom, int rotate, GBool doLinks) {
201   int page;
202
203   for (page = firstPage; page <= lastPage; ++page) {
204     displayPage(out, page, zoom, rotate, doLinks);
205   }
206 }
207
208 GBool PDFDoc::isLinearized() {
209   Parser *parser;
210   Object obj1, obj2, obj3, obj4, obj5;
211   GBool lin;
212
213   lin = gFalse;
214   obj1.initNull();
215   parser = new Parser(xref,
216              new Lexer(xref,
217                str->makeSubStream(str->getStart(), gFalse, 0, &obj1)));
218   parser->getObj(&obj1);
219   parser->getObj(&obj2);
220   parser->getObj(&obj3);
221   parser->getObj(&obj4);
222   if (obj1.isInt() && obj2.isInt() && obj3.isCmd("obj") &&
223       obj4.isDict()) {
224     obj4.dictLookup("Linearized", &obj5);
225     if (obj5.isNum() && obj5.getNum() > 0) {
226       lin = gTrue;
227     }
228     obj5.free();
229   }
230   obj4.free();
231   obj3.free();
232   obj2.free();
233   obj1.free();
234   delete parser;
235   return lin;
236 }
237
238 GBool PDFDoc::saveAs(GString *name) {
239   FILE *f;
240   int c;
241
242   if (!(f = fopen(name->getCString(), "wb"))) {
243     error(-1, "Couldn't open file '%s'", name->getCString());
244     return gFalse;
245   }
246   str->reset();
247   while ((c = str->getChar()) != EOF) {
248     fputc(c, f);
249   }
250   str->close();
251   fclose(f);
252   return gTrue;
253 }
254
255 void PDFDoc::getLinks(Page *page) {
256   Object obj;
257
258   links = new Links(page->getAnnots(&obj), catalog->getBaseURI());
259   obj.free();
260 }