Back to index

tetex-bin  3.0
PDFDoc.cc
Go to the documentation of this file.
00001 //========================================================================
00002 //
00003 // PDFDoc.cc
00004 //
00005 // Copyright 1996-2003 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 "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   str->reset();
00117 
00118   // check header
00119   checkHeader();
00120 
00121   // read xref table
00122   xref = new XRef(str, ownerPassword, userPassword);
00123   if (!xref->isOk()) {
00124     error(-1, "Couldn't read xref table");
00125     errCode = xref->getErrorCode();
00126     return gFalse;
00127   }
00128 
00129   // read catalog
00130   catalog = new Catalog(xref);
00131   if (!catalog->isOk()) {
00132     error(-1, "Couldn't read page catalog");
00133     errCode = errBadCatalog;
00134     return gFalse;
00135   }
00136 
00137 #ifndef DISABLE_OUTLINE
00138   // read outline
00139   outline = new Outline(catalog->getOutline(), xref);
00140 #endif
00141 
00142   // done
00143   return gTrue;
00144 }
00145 
00146 PDFDoc::~PDFDoc() {
00147 #ifndef DISABLE_OUTLINE
00148   if (outline) {
00149     delete outline;
00150   }
00151 #endif
00152   if (catalog) {
00153     delete catalog;
00154   }
00155   if (xref) {
00156     delete xref;
00157   }
00158   if (str) {
00159     delete str;
00160   }
00161   if (file) {
00162     fclose(file);
00163   }
00164   if (fileName) {
00165     delete fileName;
00166   }
00167   if (links) {
00168     delete links;
00169   }
00170 }
00171 
00172 // Check for a PDF header on this stream.  Skip past some garbage
00173 // if necessary.
00174 void PDFDoc::checkHeader() {
00175   char hdrBuf[headerSearchSize+1];
00176   char *p;
00177   int i;
00178 
00179   pdfVersion = 0;
00180   for (i = 0; i < headerSearchSize; ++i) {
00181     hdrBuf[i] = str->getChar();
00182   }
00183   hdrBuf[headerSearchSize] = '\0';
00184   for (i = 0; i < headerSearchSize - 5; ++i) {
00185     if (!strncmp(&hdrBuf[i], "%PDF-", 5)) {
00186       break;
00187     }
00188   }
00189   if (i >= headerSearchSize - 5) {
00190     error(-1, "May not be a PDF file (continuing anyway)");
00191     return;
00192   }
00193   str->moveStart(i);
00194   p = strtok(&hdrBuf[i+5], " \t\n\r");
00195   pdfVersion = atof(p);
00196   if (!(hdrBuf[i+5] >= '0' && hdrBuf[i+5] <= '9') ||
00197       pdfVersion > supportedPDFVersionNum + 0.0001) {
00198     error(-1, "PDF version %s -- xpdf supports version %s"
00199          " (continuing anyway)", p, supportedPDFVersionStr);
00200   }
00201 }
00202 
00203 void PDFDoc::displayPage(OutputDev *out, int page, double hDPI, double vDPI,
00204                       int rotate, GBool crop, GBool doLinks,
00205                       GBool (*abortCheckCbk)(void *data),
00206                       void *abortCheckCbkData) {
00207   Page *p;
00208 
00209   if (globalParams->getPrintCommands()) {
00210     printf("***** page %d *****\n", page);
00211   }
00212   p = catalog->getPage(page);
00213   if (doLinks) {
00214     if (links) {
00215       delete links;
00216     }
00217     getLinks(p);
00218     p->display(out, hDPI, vDPI, rotate, crop, links, catalog,
00219               abortCheckCbk, abortCheckCbkData);
00220   } else {
00221     p->display(out, hDPI, vDPI, rotate, crop, NULL, catalog,
00222               abortCheckCbk, abortCheckCbkData);
00223   }
00224 }
00225 
00226 void PDFDoc::displayPages(OutputDev *out, int firstPage, int lastPage,
00227                        double hDPI, double vDPI, int rotate,
00228                        GBool crop, GBool doLinks,
00229                        GBool (*abortCheckCbk)(void *data),
00230                        void *abortCheckCbkData) {
00231   int page;
00232 
00233   for (page = firstPage; page <= lastPage; ++page) {
00234     displayPage(out, page, hDPI, vDPI, rotate, crop, doLinks,
00235               abortCheckCbk, abortCheckCbkData);
00236   }
00237 }
00238 
00239 void PDFDoc::displayPageSlice(OutputDev *out, int page,
00240                            double hDPI, double vDPI,
00241                            int rotate, GBool crop,
00242                            int sliceX, int sliceY, int sliceW, int sliceH,
00243                            GBool (*abortCheckCbk)(void *data),
00244                            void *abortCheckCbkData) {
00245   Page *p;
00246 
00247   p = catalog->getPage(page);
00248   p->displaySlice(out, hDPI, vDPI, rotate, crop,
00249                 sliceX, sliceY, sliceW, sliceH,
00250                 NULL, catalog, abortCheckCbk, abortCheckCbkData);
00251 }
00252 
00253 GBool PDFDoc::isLinearized() {
00254   Parser *parser;
00255   Object obj1, obj2, obj3, obj4, obj5;
00256   GBool lin;
00257 
00258   lin = gFalse;
00259   obj1.initNull();
00260   parser = new Parser(xref,
00261             new Lexer(xref,
00262               str->makeSubStream(str->getStart(), gFalse, 0, &obj1)));
00263   parser->getObj(&obj1);
00264   parser->getObj(&obj2);
00265   parser->getObj(&obj3);
00266   parser->getObj(&obj4);
00267   if (obj1.isInt() && obj2.isInt() && obj3.isCmd("obj") &&
00268       obj4.isDict()) {
00269     obj4.dictLookup("Linearized", &obj5);
00270     if (obj5.isNum() && obj5.getNum() > 0) {
00271       lin = gTrue;
00272     }
00273     obj5.free();
00274   }
00275   obj4.free();
00276   obj3.free();
00277   obj2.free();
00278   obj1.free();
00279   delete parser;
00280   return lin;
00281 }
00282 
00283 GBool PDFDoc::saveAs(GString *name) {
00284   FILE *f;
00285   int c;
00286 
00287   if (!(f = fopen(name->getCString(), "wb"))) {
00288     error(-1, "Couldn't open file '%s'", name->getCString());
00289     return gFalse;
00290   }
00291   str->reset();
00292   while ((c = str->getChar()) != EOF) {
00293     fputc(c, f);
00294   }
00295   str->close();
00296   fclose(f);
00297   return gTrue;
00298 }
00299 
00300 void PDFDoc::getLinks(Page *page) {
00301   Object obj;
00302 
00303   links = new Links(page->getAnnots(&obj), catalog->getBaseURI());
00304   obj.free();
00305 }