filters

Page.cc

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