upgrade to xpdf 3.00.
[swftools.git] / pdf2swf / xpdf / PDFDoc.cc
blobb5981d9be3203483780782c158f92c6d989f9036
1 //========================================================================
2 //
3 // PDFDoc.cc
4 //
5 // Copyright 1996-2003 Glyph & Cog, LLC
6 //
7 //========================================================================
9 #include <aconf.h>
11 #ifdef USE_GCC_PRAGMAS
12 #pragma implementation
13 #endif
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <stddef.h>
18 #include <string.h>
19 #include "GString.h"
20 #include "config.h"
21 #include "GlobalParams.h"
22 #include "Page.h"
23 #include "Catalog.h"
24 #include "Stream.h"
25 #include "XRef.h"
26 #include "Link.h"
27 #include "OutputDev.h"
28 #include "Error.h"
29 #include "ErrorCodes.h"
30 #include "Lexer.h"
31 #include "Parser.h"
32 #ifndef DISABLE_OUTLINE
33 #include "Outline.h"
34 #endif
35 #include "PDFDoc.h"
37 //------------------------------------------------------------------------
39 #define headerSearchSize 1024 // read this many bytes at beginning of
40 // file to look for '%PDF'
42 //------------------------------------------------------------------------
43 // PDFDoc
44 //------------------------------------------------------------------------
46 PDFDoc::PDFDoc(GString *fileNameA, GString *ownerPassword,
47 GString *userPassword) {
48 Object obj;
49 GString *fileName1, *fileName2;
51 ok = gFalse;
52 errCode = errNone;
54 file = NULL;
55 str = NULL;
56 xref = NULL;
57 catalog = NULL;
58 links = NULL;
59 #ifndef DISABLE_OUTLINE
60 outline = NULL;
61 #endif
63 fileName = fileNameA;
64 fileName1 = fileName;
67 // try to open file
68 fileName2 = NULL;
69 #ifdef VMS
70 if (!(file = fopen(fileName1->getCString(), "rb", "ctx=stm"))) {
71 error(-1, "Couldn't open file '%s'", fileName1->getCString());
72 errCode = errOpenFile;
73 return;
75 #else
76 if (!(file = fopen(fileName1->getCString(), "rb"))) {
77 fileName2 = fileName->copy();
78 fileName2->lowerCase();
79 if (!(file = fopen(fileName2->getCString(), "rb"))) {
80 fileName2->upperCase();
81 if (!(file = fopen(fileName2->getCString(), "rb"))) {
82 error(-1, "Couldn't open file '%s'", fileName->getCString());
83 delete fileName2;
84 errCode = errOpenFile;
85 return;
88 delete fileName2;
90 #endif
92 // create stream
93 obj.initNull();
94 str = new FileStream(file, 0, gFalse, 0, &obj);
96 ok = setup(ownerPassword, userPassword);
99 PDFDoc::PDFDoc(BaseStream *strA, GString *ownerPassword,
100 GString *userPassword) {
101 ok = gFalse;
102 errCode = errNone;
103 fileName = NULL;
104 file = NULL;
105 str = strA;
106 xref = NULL;
107 catalog = NULL;
108 links = NULL;
109 #ifndef DISABLE_OUTLINE
110 outline = NULL;
111 #endif
112 ok = setup(ownerPassword, userPassword);
115 GBool PDFDoc::setup(GString *ownerPassword, GString *userPassword) {
116 str->reset();
118 // check header
119 checkHeader();
121 // read xref table
122 xref = new XRef(str, ownerPassword, userPassword);
123 if (!xref->isOk()) {
124 error(-1, "Couldn't read xref table");
125 errCode = xref->getErrorCode();
126 return gFalse;
129 // read catalog
130 catalog = new Catalog(xref);
131 if (!catalog->isOk()) {
132 error(-1, "Couldn't read page catalog");
133 errCode = errBadCatalog;
134 return gFalse;
137 #ifndef DISABLE_OUTLINE
138 // read outline
139 outline = new Outline(catalog->getOutline(), xref);
140 #endif
142 // done
143 return gTrue;
146 PDFDoc::~PDFDoc() {
147 #ifndef DISABLE_OUTLINE
148 if (outline) {
149 delete outline;
151 #endif
152 if (catalog) {
153 delete catalog;
155 if (xref) {
156 delete xref;
158 if (str) {
159 delete str;
161 if (file) {
162 fclose(file);
164 if (fileName) {
165 delete fileName;
167 if (links) {
168 delete links;
172 // Check for a PDF header on this stream. Skip past some garbage
173 // if necessary.
174 void PDFDoc::checkHeader() {
175 char hdrBuf[headerSearchSize+1];
176 char *p;
177 int i;
179 pdfVersion = 0;
180 for (i = 0; i < headerSearchSize; ++i) {
181 hdrBuf[i] = str->getChar();
183 hdrBuf[headerSearchSize] = '\0';
184 for (i = 0; i < headerSearchSize - 5; ++i) {
185 if (!strncmp(&hdrBuf[i], "%PDF-", 5)) {
186 break;
189 if (i >= headerSearchSize - 5) {
190 error(-1, "May not be a PDF file (continuing anyway)");
191 return;
193 str->moveStart(i);
194 p = strtok(&hdrBuf[i+5], " \t\n\r");
195 pdfVersion = atof(p);
196 if (!(hdrBuf[i+5] >= '0' && hdrBuf[i+5] <= '9') ||
197 pdfVersion > supportedPDFVersionNum + 0.0001) {
198 error(-1, "PDF version %s -- xpdf supports version %s"
199 " (continuing anyway)", p, supportedPDFVersionStr);
203 void PDFDoc::displayPage(OutputDev *out, int page, double hDPI, double vDPI,
204 int rotate, GBool crop, GBool doLinks,
205 GBool (*abortCheckCbk)(void *data),
206 void *abortCheckCbkData) {
207 Page *p;
209 if (globalParams->getPrintCommands()) {
210 printf("***** page %d *****\n", page);
212 p = catalog->getPage(page);
213 if (doLinks) {
214 if (links) {
215 delete links;
217 getLinks(p);
218 p->display(out, hDPI, vDPI, rotate, crop, links, catalog,
219 abortCheckCbk, abortCheckCbkData);
220 } else {
221 p->display(out, hDPI, vDPI, rotate, crop, NULL, catalog,
222 abortCheckCbk, abortCheckCbkData);
226 void PDFDoc::displayPages(OutputDev *out, int firstPage, int lastPage,
227 double hDPI, double vDPI, int rotate,
228 GBool crop, GBool doLinks,
229 GBool (*abortCheckCbk)(void *data),
230 void *abortCheckCbkData) {
231 int page;
233 for (page = firstPage; page <= lastPage; ++page) {
234 displayPage(out, page, hDPI, vDPI, rotate, crop, doLinks,
235 abortCheckCbk, abortCheckCbkData);
239 void PDFDoc::displayPageSlice(OutputDev *out, int page,
240 double hDPI, double vDPI,
241 int rotate, GBool crop,
242 int sliceX, int sliceY, int sliceW, int sliceH,
243 GBool (*abortCheckCbk)(void *data),
244 void *abortCheckCbkData) {
245 Page *p;
247 p = catalog->getPage(page);
248 p->displaySlice(out, hDPI, vDPI, rotate, crop,
249 sliceX, sliceY, sliceW, sliceH,
250 NULL, catalog, abortCheckCbk, abortCheckCbkData);
253 GBool PDFDoc::isLinearized() {
254 Parser *parser;
255 Object obj1, obj2, obj3, obj4, obj5;
256 GBool lin;
258 lin = gFalse;
259 obj1.initNull();
260 parser = new Parser(xref,
261 new Lexer(xref,
262 str->makeSubStream(str->getStart(), gFalse, 0, &obj1)));
263 parser->getObj(&obj1);
264 parser->getObj(&obj2);
265 parser->getObj(&obj3);
266 parser->getObj(&obj4);
267 if (obj1.isInt() && obj2.isInt() && obj3.isCmd("obj") &&
268 obj4.isDict()) {
269 obj4.dictLookup("Linearized", &obj5);
270 if (obj5.isNum() && obj5.getNum() > 0) {
271 lin = gTrue;
273 obj5.free();
275 obj4.free();
276 obj3.free();
277 obj2.free();
278 obj1.free();
279 delete parser;
280 return lin;
283 GBool PDFDoc::saveAs(GString *name) {
284 FILE *f;
285 int c;
287 if (!(f = fopen(name->getCString(), "wb"))) {
288 error(-1, "Couldn't open file '%s'", name->getCString());
289 return gFalse;
291 str->reset();
292 while ((c = str->getChar()) != EOF) {
293 fputc(c, f);
295 str->close();
296 fclose(f);
297 return gTrue;
300 void PDFDoc::getLinks(Page *page) {
301 Object obj;
303 links = new Links(page->getAnnots(&obj), catalog->getBaseURI());
304 obj.free();