Back to index

tetex-bin  3.0
Page.cc
Go to the documentation of this file.
00001 //========================================================================
00002 //
00003 // Page.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 <stddef.h>
00016 #include "GlobalParams.h"
00017 #include "Object.h"
00018 #include "Array.h"
00019 #include "Dict.h"
00020 #include "XRef.h"
00021 #include "Link.h"
00022 #include "OutputDev.h"
00023 #ifndef PDF_PARSER_ONLY
00024 #include "Gfx.h"
00025 #include "Annot.h"
00026 #endif
00027 #include "Error.h"
00028 #include "Page.h"
00029 
00030 //------------------------------------------------------------------------
00031 // PageAttrs
00032 //------------------------------------------------------------------------
00033 
00034 PageAttrs::PageAttrs(PageAttrs *attrs, Dict *dict) {
00035   Object obj1;
00036   double w, h;
00037 
00038   // get old/default values
00039   if (attrs) {
00040     mediaBox = attrs->mediaBox;
00041     cropBox = attrs->cropBox;
00042     haveCropBox = attrs->haveCropBox;
00043     rotate = attrs->rotate;
00044     attrs->resources.copy(&resources);
00045   } else {
00046     // set default MediaBox to 8.5" x 11" -- this shouldn't be necessary
00047     // but some (non-compliant) PDF files don't specify a MediaBox
00048     mediaBox.x1 = 0;
00049     mediaBox.y1 = 0;
00050     mediaBox.x2 = 612;
00051     mediaBox.y2 = 792;
00052     cropBox.x1 = cropBox.y1 = cropBox.x2 = cropBox.y2 = 0;
00053     haveCropBox = gFalse;
00054     rotate = 0;
00055     resources.initNull();
00056   }
00057 
00058   // media box
00059   readBox(dict, "MediaBox", &mediaBox);
00060 
00061   // crop box
00062   if (readBox(dict, "CropBox", &cropBox)) {
00063     haveCropBox = gTrue;
00064   }
00065   if (!haveCropBox) {
00066     cropBox = mediaBox;
00067   }
00068 
00069   // if the MediaBox is excessively larger than the CropBox,
00070   // just use the CropBox
00071   limitToCropBox = gFalse;
00072   if (haveCropBox) {
00073     w = 0.25 * (cropBox.x2 - cropBox.x1);
00074     h = 0.25 * (cropBox.y2 - cropBox.y1);
00075     if ((cropBox.x1 - mediaBox.x1) + (mediaBox.x2 - cropBox.x2) > w ||
00076        (cropBox.y1 - mediaBox.y1) + (mediaBox.y2 - cropBox.y2) > h) {
00077       limitToCropBox = gTrue;
00078     }
00079   }
00080 
00081   // other boxes
00082   bleedBox = cropBox;
00083   readBox(dict, "BleedBox", &bleedBox);
00084   trimBox = cropBox;
00085   readBox(dict, "TrimBox", &trimBox);
00086   artBox = cropBox;
00087   readBox(dict, "ArtBox", &artBox);
00088 
00089   // rotate
00090   dict->lookup("Rotate", &obj1);
00091   if (obj1.isInt()) {
00092     rotate = obj1.getInt();
00093   }
00094   obj1.free();
00095   while (rotate < 0) {
00096     rotate += 360;
00097   }
00098   while (rotate >= 360) {
00099     rotate -= 360;
00100   }
00101 
00102   // misc attributes
00103   dict->lookup("LastModified", &lastModified);
00104   dict->lookup("BoxColorInfo", &boxColorInfo);
00105   dict->lookup("Group", &group);
00106   dict->lookup("Metadata", &metadata);
00107   dict->lookup("PieceInfo", &pieceInfo);
00108   dict->lookup("SeparationInfo", &separationInfo);
00109 
00110   // resource dictionary
00111   dict->lookup("Resources", &obj1);
00112   if (obj1.isDict()) {
00113     resources.free();
00114     obj1.copy(&resources);
00115   }
00116   obj1.free();
00117 }
00118 
00119 PageAttrs::~PageAttrs() {
00120   lastModified.free();
00121   boxColorInfo.free();
00122   group.free();
00123   metadata.free();
00124   pieceInfo.free();
00125   separationInfo.free();
00126   resources.free();
00127 }
00128 
00129 GBool PageAttrs::readBox(Dict *dict, char *key, PDFRectangle *box) {
00130   PDFRectangle tmp;
00131   Object obj1, obj2;
00132   GBool ok;
00133 
00134   dict->lookup(key, &obj1);
00135   if (obj1.isArray() && obj1.arrayGetLength() == 4) {
00136     ok = gTrue;
00137     obj1.arrayGet(0, &obj2);
00138     if (obj2.isNum()) {
00139       tmp.x1 = obj2.getNum();
00140     } else {
00141       ok = gFalse;
00142     }
00143     obj2.free();
00144     obj1.arrayGet(1, &obj2);
00145     if (obj2.isNum()) {
00146       tmp.y1 = obj2.getNum();
00147     } else {
00148       ok = gFalse;
00149     }
00150     obj2.free();
00151     obj1.arrayGet(2, &obj2);
00152     if (obj2.isNum()) {
00153       tmp.x2 = obj2.getNum();
00154     } else {
00155       ok = gFalse;
00156     }
00157     obj2.free();
00158     obj1.arrayGet(3, &obj2);
00159     if (obj2.isNum()) {
00160       tmp.y2 = obj2.getNum();
00161     } else {
00162       ok = gFalse;
00163     }
00164     obj2.free();
00165     if (ok) {
00166       *box = tmp;
00167     }
00168   } else {
00169     ok = gFalse;
00170   }
00171   obj1.free();
00172   return ok;
00173 }
00174 
00175 //------------------------------------------------------------------------
00176 // Page
00177 //------------------------------------------------------------------------
00178 
00179 Page::Page(XRef *xrefA, int numA, Dict *pageDict, PageAttrs *attrsA) {
00180   ok = gTrue;
00181   xref = xrefA;
00182   num = numA;
00183 
00184   // get attributes
00185   attrs = attrsA;
00186 
00187   // annotations
00188   pageDict->lookupNF("Annots", &annots);
00189   if (!(annots.isRef() || annots.isArray() || annots.isNull())) {
00190     error(-1, "Page annotations object (page %d) is wrong type (%s)",
00191          num, annots.getTypeName());
00192     annots.free();
00193     goto err2;
00194   }
00195 
00196   // contents
00197   pageDict->lookupNF("Contents", &contents);
00198   if (!(contents.isRef() || contents.isArray() ||
00199        contents.isNull())) {
00200     error(-1, "Page contents object (page %d) is wrong type (%s)",
00201          num, contents.getTypeName());
00202     contents.free();
00203     goto err1;
00204   }
00205 
00206   return;
00207 
00208  err2:
00209   annots.initNull();
00210  err1:
00211   contents.initNull();
00212   ok = gFalse;
00213 }
00214 
00215 Page::~Page() {
00216   delete attrs;
00217   annots.free();
00218   contents.free();
00219 }
00220 
00221 void Page::display(OutputDev *out, double hDPI, double vDPI,
00222                  int rotate, GBool crop,
00223                  Links *links, Catalog *catalog,
00224                  GBool (*abortCheckCbk)(void *data),
00225                  void *abortCheckCbkData) {
00226   displaySlice(out, hDPI, vDPI, rotate, crop, -1, -1, -1, -1, links, catalog,
00227               abortCheckCbk, abortCheckCbkData);
00228 }
00229 
00230 void Page::displaySlice(OutputDev *out, double hDPI, double vDPI,
00231                      int rotate, GBool crop,
00232                      int sliceX, int sliceY, int sliceW, int sliceH,
00233                      Links *links, Catalog *catalog,
00234                      GBool (*abortCheckCbk)(void *data),
00235                      void *abortCheckCbkData) {
00236 #ifndef PDF_PARSER_ONLY
00237   PDFRectangle *mediaBox, *cropBox;
00238   PDFRectangle box;
00239   Gfx *gfx;
00240   Object obj;
00241   Link *link;
00242   Annots *annotList;
00243   double kx, ky;
00244   int i;
00245 
00246   rotate += getRotate();
00247   if (rotate >= 360) {
00248     rotate -= 360;
00249   } else if (rotate < 0) {
00250     rotate += 360;
00251   }
00252 
00253   mediaBox = getBox();
00254   if (sliceW >= 0 && sliceH >= 0) {
00255     kx = 72.0 / hDPI;
00256     ky = 72.0 / vDPI;
00257     if (rotate == 90) {
00258       if (out->upsideDown()) {
00259        box.x1 = mediaBox->x1 + ky * sliceY;
00260        box.x2 = mediaBox->x1 + ky * (sliceY + sliceH);
00261       } else {
00262        box.x1 = mediaBox->x2 - ky * (sliceY + sliceH);
00263        box.x2 = mediaBox->x2 - ky * sliceY;
00264       }
00265       box.y1 = mediaBox->y1 + kx * sliceX;
00266       box.y2 = mediaBox->y1 + kx * (sliceX + sliceW);
00267     } else if (rotate == 180) {
00268       box.x1 = mediaBox->x2 - kx * (sliceX + sliceW);
00269       box.x2 = mediaBox->x2 - kx * sliceX;
00270       if (out->upsideDown()) {
00271        box.y1 = mediaBox->y1 + ky * sliceY;
00272        box.y2 = mediaBox->y1 + ky * (sliceY + sliceH);
00273       } else {
00274        box.y1 = mediaBox->y2 - ky * (sliceY + sliceH);
00275        box.y2 = mediaBox->y2 - ky * sliceY;
00276       }
00277     } else if (rotate == 270) {
00278       if (out->upsideDown()) {
00279        box.x1 = mediaBox->x2 - ky * (sliceY + sliceH);
00280        box.x2 = mediaBox->x2 - ky * sliceY;
00281       } else {
00282        box.x1 = mediaBox->x1 + ky * sliceY;
00283        box.x2 = mediaBox->x1 + ky * (sliceY + sliceH);
00284       }
00285       box.y1 = mediaBox->y2 - kx * (sliceX + sliceW);
00286       box.y2 = mediaBox->y2 - kx * sliceX;
00287     } else {
00288       box.x1 = mediaBox->x1 + kx * sliceX;
00289       box.x2 = mediaBox->x1 + kx * (sliceX + sliceW);
00290       if (out->upsideDown()) {
00291        box.y1 = mediaBox->y2 - ky * (sliceY + sliceH);
00292        box.y2 = mediaBox->y2 - ky * sliceY;
00293       } else {
00294        box.y1 = mediaBox->y1 + ky * sliceY;
00295        box.y2 = mediaBox->y1 + ky * (sliceY + sliceH);
00296       }
00297     }
00298   } else {
00299     box = *mediaBox;
00300   }
00301   cropBox = getCropBox();
00302 
00303   if (globalParams->getPrintCommands()) {
00304     printf("***** MediaBox = ll:%g,%g ur:%g,%g\n",
00305           box.x1, box.y1, box.x2, box.y2);
00306     if (isCropped()) {
00307       printf("***** CropBox = ll:%g,%g ur:%g,%g\n",
00308             cropBox->x1, cropBox->y1, cropBox->x2, cropBox->y2);
00309     }
00310     printf("***** Rotate = %d\n", attrs->getRotate());
00311   }
00312 
00313   gfx = new Gfx(xref, out, num, attrs->getResourceDict(),
00314               hDPI, vDPI, &box, crop && isCropped(), cropBox, rotate,
00315               abortCheckCbk, abortCheckCbkData);
00316   contents.fetch(xref, &obj);
00317   if (!obj.isNull()) {
00318     gfx->saveState();
00319     gfx->display(&obj);
00320     gfx->restoreState();
00321   }
00322   obj.free();
00323 
00324   // draw links
00325   if (links) {
00326     gfx->saveState();
00327     for (i = 0; i < links->getNumLinks(); ++i) {
00328       link = links->getLink(i);
00329       out->drawLink(link, catalog);
00330     }
00331     gfx->restoreState();
00332     out->dump();
00333   }
00334 
00335   // draw non-link annotations
00336   annotList = new Annots(xref, annots.fetch(xref, &obj));
00337   obj.free();
00338   if (annotList->getNumAnnots() > 0) {
00339     if (globalParams->getPrintCommands()) {
00340       printf("***** Annotations\n");
00341     }
00342     for (i = 0; i < annotList->getNumAnnots(); ++i) {
00343       annotList->getAnnot(i)->draw(gfx);
00344     }
00345     out->dump();
00346   }
00347   delete annotList;
00348 
00349   delete gfx;
00350 #endif
00351 }