filters

PDFDoc.cc

00001 //========================================================================
00002 //
00003 // PDFDoc.cc
00004 //
00005 // Copyright 1996-2002 Glyph & Cog, LLC
00006 //
00007 //========================================================================
00008 
00009 #include <aconf.h>
00010 
00011 #ifdef USE_GCC_PRAGMAS
00012 #pragma implementation
00013 #endif
00014 
00015 #include <stdio.h>
00016 #include <stdlib.h>
00017 #include <stddef.h>
00018 #include <string.h>
00019 #include "GString.h"
00020 #include "xpdf_config.h"
00021 #include "GlobalParams.h"
00022 #include "Page.h"
00023 #include "Catalog.h"
00024 #include "Stream.h"
00025 #include "XRef.h"
00026 #include "Link.h"
00027 #include "OutputDev.h"
00028 #include "Error.h"
00029 #include "ErrorCodes.h"
00030 #include "Lexer.h"
00031 #include "Parser.h"
00032 #ifndef DISABLE_OUTLINE
00033 #include "Outline.h"
00034 #endif
00035 #include "PDFDoc.h"
00036 
00037 //------------------------------------------------------------------------
00038 
00039 #define headerSearchSize 1024   // read this many bytes at beginning of
00040                 //   file to look for '%PDF'
00041 
00042 //------------------------------------------------------------------------
00043 // PDFDoc
00044 //------------------------------------------------------------------------
00045 
00046 PDFDoc::PDFDoc(GString *fileNameA, GString *ownerPassword,
00047            GString *userPassword) {
00048   Object obj;
00049   GString *fileName1, *fileName2;
00050 
00051   ok = gFalse;
00052   errCode = errNone;
00053 
00054   file = NULL;
00055   str = NULL;
00056   xref = NULL;
00057   catalog = NULL;
00058   links = NULL;
00059 #ifndef DISABLE_OUTLINE
00060   outline = NULL;
00061 #endif
00062 
00063   fileName = fileNameA;
00064   fileName1 = fileName;
00065 
00066 
00067   // try to open file
00068   fileName2 = NULL;
00069 #ifdef VMS
00070   if (!(file = fopen(fileName1->getCString(), "rb", "ctx=stm"))) {
00071     error(-1, "Couldn't open file '%s'", fileName1->getCString());
00072     errCode = errOpenFile;
00073     return;
00074   }
00075 #else
00076   if (!(file = fopen(fileName1->getCString(), "rb"))) {
00077     fileName2 = fileName->copy();
00078     fileName2->lowerCase();
00079     if (!(file = fopen(fileName2->getCString(), "rb"))) {
00080       fileName2->upperCase();
00081       if (!(file = fopen(fileName2->getCString(), "rb"))) {
00082     error(-1, "Couldn't open file '%s'", fileName->getCString());
00083     delete fileName2;
00084     errCode = errOpenFile;
00085     return;
00086       }
00087     }
00088     delete fileName2;
00089   }
00090 #endif
00091 
00092   // create stream
00093   obj.initNull();
00094   str = new FileStream(file, 0, gFalse, 0, &obj);
00095 
00096   ok = setup(ownerPassword, userPassword);
00097 }
00098 
00099 PDFDoc::PDFDoc(BaseStream *strA, GString *ownerPassword,
00100            GString *userPassword) {
00101   ok = gFalse;
00102   errCode = errNone;
00103   fileName = NULL;
00104   file = NULL;
00105   str = strA;
00106   xref = NULL;
00107   catalog = NULL;
00108   links = NULL;
00109 #ifndef DISABLE_OUTLINE
00110   outline = NULL;
00111 #endif
00112   ok = setup(ownerPassword, userPassword);
00113 }
00114 
00115 GBool PDFDoc::setup(GString *ownerPassword, GString *userPassword) {
00116   // check header
00117   checkHeader();
00118 
00119   // read xref table
00120   xref = new XRef(str, ownerPassword, userPassword);
00121   if (!xref->isOk()) {
00122     error(-1, "Couldn't read xref table");
00123     errCode = xref->getErrorCode();
00124     return gFalse;
00125   }
00126 
00127   // read catalog
00128   catalog = new Catalog(xref);
00129   if (!catalog->isOk()) {
00130     error(-1, "Couldn't read page catalog");
00131     errCode = errBadCatalog;
00132     return gFalse;
00133   }
00134 
00135 #ifndef DISABLE_OUTLINE
00136   // read outline
00137   outline = new Outline(catalog->getOutline(), xref);
00138 #endif
00139 
00140   // done
00141   return gTrue;
00142 }
00143 
00144 PDFDoc::~PDFDoc() {
00145 #ifndef DISABLE_OUTLINE
00146     delete outline;
00147 #endif
00148     delete catalog;
00149     delete xref;
00150     delete str;
00151     if (file) {
00152         fclose(file);
00153     }
00154     delete fileName;
00155     delete links;
00156 }
00157 
00158 // Check for a PDF header on this stream.  Skip past some garbage
00159 // if necessary.
00160 void PDFDoc::checkHeader() {
00161   char hdrBuf[headerSearchSize+1];
00162   char *p;
00163   int i;
00164 
00165   pdfVersion = 0;
00166   for (i = 0; i < headerSearchSize; ++i) {
00167     hdrBuf[i] = str->getChar();
00168   }
00169   hdrBuf[headerSearchSize] = '\0';
00170   for (i = 0; i < headerSearchSize - 5; ++i) {
00171     if (!strncmp(&hdrBuf[i], "%PDF-", 5)) {
00172       break;
00173     }
00174   }
00175   if (i >= headerSearchSize - 5) {
00176     error(-1, "May not be a PDF file (continuing anyway)");
00177     return;
00178   }
00179   str->moveStart(i);
00180   p = strtok(&hdrBuf[i+5], " \t\n\r");
00181   pdfVersion = atof(p);
00182   if (!(hdrBuf[i+5] >= '0' && hdrBuf[i+5] <= '9') ||
00183       pdfVersion > supportedPDFVersionNum + 0.0001) {
00184     error(-1, "PDF version %s -- xpdf supports version %s"
00185       " (continuing anyway)", p, supportedPDFVersionStr);
00186   }
00187 }
00188 
00189 void PDFDoc::displayPage(OutputDev *out, int page, double zoom,
00190              int rotate, GBool doLinks,
00191              GBool (*abortCheckCbk)(void *data),
00192              void *abortCheckCbkData) {
00193   Page *p;
00194 
00195   if (globalParams->getPrintCommands()) {
00196     printf("***** page %d *****\n", page);
00197   }
00198   p = catalog->getPage(page);
00199   if (doLinks) {
00200     if (links) {
00201       delete links;
00202     }
00203     getLinks(p);
00204     p->display(out, zoom, rotate, links, catalog,
00205            abortCheckCbk, abortCheckCbkData);
00206   } else {
00207     p->display(out, zoom, rotate, NULL, catalog,
00208            abortCheckCbk, abortCheckCbkData);
00209   }
00210 }
00211 
00212 void PDFDoc::displayPages(OutputDev *out, int firstPage, int lastPage,
00213               int zoom, int rotate, GBool doLinks,
00214               GBool (*abortCheckCbk)(void *data),
00215               void *abortCheckCbkData) {
00216   int page;
00217 
00218   for (page = firstPage; page <= lastPage; ++page) {
00219     displayPage(out, page, zoom, rotate, doLinks,
00220         abortCheckCbk, abortCheckCbkData);
00221   }
00222 }
00223 
00224 void PDFDoc::displayPageSlice(OutputDev *out, int page, double zoom,
00225                   int rotate, int sliceX, int sliceY,
00226                   int sliceW, int sliceH,
00227                   GBool (*abortCheckCbk)(void *data),
00228                   void *abortCheckCbkData) {
00229   Page *p;
00230 
00231   p = catalog->getPage(page);
00232   p->displaySlice(out, zoom, rotate, sliceX, sliceY, sliceW, sliceH,
00233           NULL, catalog, abortCheckCbk, abortCheckCbkData);
00234 }
00235 
00236 GBool PDFDoc::isLinearized() {
00237   Parser *parser;
00238   Object obj1, obj2, obj3, obj4, obj5;
00239   GBool lin;
00240 
00241   lin = gFalse;
00242   obj1.initNull();
00243   parser = new Parser(xref,
00244          new Lexer(xref,
00245            str->makeSubStream(str->getStart(), gFalse, 0, &obj1)));
00246   parser->getObj(&obj1);
00247   parser->getObj(&obj2);
00248   parser->getObj(&obj3);
00249   parser->getObj(&obj4);
00250   if (obj1.isInt() && obj2.isInt() && obj3.isCmd("obj") &&
00251       obj4.isDict()) {
00252     obj4.dictLookup("Linearized", &obj5);
00253     if (obj5.isNum() && obj5.getNum() > 0) {
00254       lin = gTrue;
00255     }
00256     obj5.free();
00257   }
00258   obj4.free();
00259   obj3.free();
00260   obj2.free();
00261   obj1.free();
00262   delete parser;
00263   return lin;
00264 }
00265 
00266 GBool PDFDoc::saveAs(GString *name) {
00267   FILE *f;
00268   int c;
00269 
00270   if (!(f = fopen(name->getCString(), "wb"))) {
00271     error(-1, "Couldn't open file '%s'", name->getCString());
00272     return gFalse;
00273   }
00274   str->reset();
00275   while ((c = str->getChar()) != EOF) {
00276     fputc(c, f);
00277   }
00278   str->close();
00279   fclose(f);
00280   return gTrue;
00281 }
00282 
00283 void PDFDoc::getLinks(Page *page) {
00284   Object obj;
00285 
00286   links = new Links(page->getAnnots(&obj), catalog->getBaseURI());
00287   obj.free();
00288 }
KDE Home | KDE Accessibility Home | Description of Access Keys