home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 110 / EnigmaAmiga110CD.iso / indispensabili / utility / apdf / xpdf-0.80 / xpdf / catalog.cc < prev    next >
C/C++ Source or Header  |  1998-11-27  |  6KB  |  272 lines

  1. //========================================================================
  2. //
  3. // Catalog.cc
  4. //
  5. // Copyright 1996 Derek B. Noonburg
  6. //
  7. //========================================================================
  8.  
  9. #ifdef __GNUC__
  10. #pragma implementation
  11. #endif
  12.  
  13. #include <stddef.h>
  14. #include "gmem.h"
  15. #include "Object.h"
  16. #include "Array.h"
  17. #include "Dict.h"
  18. #include "Page.h"
  19. #include "Error.h"
  20. #include "Link.h"
  21. #include "Catalog.h"
  22.  
  23. //------------------------------------------------------------------------
  24. // Catalog
  25. //------------------------------------------------------------------------
  26.  
  27. Catalog::Catalog(Object *catDict) {
  28.   Object pagesDict;
  29.   Object obj;
  30.   int i;
  31.  
  32.   ok = gTrue;
  33.   pages = NULL;
  34.   pageRefs = NULL;
  35.   numPages = 0;
  36.  
  37.   if (!catDict->isDict("Catalog")) {
  38.     error(-1, "Catalog object is wrong type (%s)", catDict->getTypeName());
  39.     goto err1;
  40.   }
  41.  
  42.   // read page tree
  43.   catDict->dictLookup("Pages", &pagesDict);
  44.   if (!pagesDict.isDict("Pages")) {
  45.     error(-1, "Top-level pages object is wrong type (%s)",
  46.       pagesDict.getTypeName());
  47.     goto err2;
  48.   }
  49.   pagesDict.dictLookup("Count", &obj);
  50.   if (!obj.isInt()) {
  51.     error(-1, "Page count in top-level pages object is wrong type (%s)",
  52.       obj.getTypeName());
  53.     goto err3;
  54.   }
  55.   numPages = obj.getInt();
  56.   obj.free();
  57.   pages = (Page **)gmalloc(numPages * sizeof(Page *));
  58.   pageRefs = (Ref *)gmalloc(numPages * sizeof(Ref));
  59.   for (i = 0; i < numPages; ++i) {
  60.     pages[i] = NULL;
  61.     pageRefs[i].num = -1;
  62.     pageRefs[i].gen = -1;
  63.   }
  64.   readPageTree(pagesDict.getDict(), NULL, 0);
  65.   pagesDict.free();
  66.  
  67.   // read named destination dictionary
  68.   catDict->dictLookup("Dests", &dests);
  69.  
  70.   // read root of named destination tree
  71.   if (catDict->dictLookup("Names", &obj)->isDict())
  72.     obj.dictLookup("Dests", &nameTree);
  73.   else
  74.     nameTree.initNull();
  75.   obj.free();
  76.  
  77.   return;
  78.  
  79.  err3:
  80.   obj.free();
  81.  err2:
  82.   pagesDict.free();
  83.  err1:
  84.   dests.initNull();
  85.   nameTree.initNull();
  86.   ok = gFalse;
  87. }
  88.  
  89. Catalog::~Catalog() {
  90.   int i;
  91.  
  92.   if (pages) {
  93.     for (i = 0; i < numPages; ++i) {
  94.       if (pages[i])
  95.     delete pages[i];
  96.     }
  97.     gfree(pages);
  98.     gfree(pageRefs);
  99.   }
  100.   dests.free();
  101.   nameTree.free();
  102. }
  103.  
  104. int Catalog::readPageTree(Dict *pagesDict, PageAttrs *attrs, int start) {
  105.   Object kids;
  106.   Object kid;
  107.   Object kidRef;
  108.   PageAttrs *attrs1, *attrs2;
  109.   Page *page;
  110.   int i;
  111.  
  112.   attrs1 = new PageAttrs(attrs, pagesDict);
  113.   pagesDict->lookup("Kids", &kids);
  114.   if (!kids.isArray()) {
  115.     error(-1, "Kids object (page %d) is wrong type (%s)",
  116.       start+1, kids.getTypeName());
  117.     goto err1;
  118.   }
  119.   for (i = 0; i < kids.arrayGetLength(); ++i) {
  120.     kids.arrayGet(i, &kid);
  121.     if (kid.isDict("Page")) {
  122.       attrs2 = new PageAttrs(attrs1, kid.getDict());
  123.       page = new Page(start+1, kid.getDict(), attrs2);
  124.       if (!page->isOk()) {
  125.     ++start;
  126.     goto err3;
  127.       }
  128.       pages[start] = page;
  129.       kids.arrayGetNF(i, &kidRef);
  130.       if (kidRef.isRef()) {
  131.     pageRefs[start].num = kidRef.getRefNum();
  132.     pageRefs[start].gen = kidRef.getRefGen();
  133.       }
  134.       kidRef.free();
  135.       ++start;
  136.     //~ found one PDF file where a Pages object is missing the /Type entry
  137.     // } else if (kid.isDict("Pages")) {
  138.     } else if (kid.isDict()) {
  139.       if ((start = readPageTree(kid.getDict(), attrs1, start)) < 0)
  140.     goto err2;
  141.     } else {
  142.       error(-1, "Kid object (page %d) is wrong type (%s)",
  143.         start+1, kid.getTypeName());
  144.       goto err2;
  145.     }
  146.     kid.free();
  147.   }
  148.   delete attrs1;
  149.   kids.free();
  150.   return start;
  151.  
  152.  err3:
  153.   delete page;
  154.  err2:
  155.   kid.free();
  156.  err1:
  157.   kids.free();
  158.   delete attrs1;
  159.   ok = gFalse;
  160.   return -1;
  161. }
  162.  
  163. int Catalog::findPage(int num, int gen) {
  164.   int i;
  165.  
  166.   for (i = 0; i < numPages; ++i) {
  167.     if (pageRefs[i].num == num && pageRefs[i].gen == gen)
  168.       return i + 1;
  169.   }
  170.   return 0;
  171. }
  172.  
  173. LinkDest *Catalog::findDest(GString *name) {
  174.   LinkDest *dest;
  175.   Object obj1, obj2;
  176.   GBool found;
  177.  
  178.   // try named destination dictionary then name tree
  179.   found = gFalse;
  180.   if (dests.isDict()) {
  181.     if (!dests.dictLookup(name->getCString(), &obj1)->isNull())
  182.       found = gTrue;
  183.     else
  184.       obj1.free();
  185.   }
  186.   if (!found && nameTree.isDict()) {
  187.     if (!findDestInTree(&nameTree, name, &obj1)->isNull())
  188.       found = gTrue;
  189.     else
  190.       obj1.free();
  191.   }
  192.   if (!found)
  193.     return NULL;
  194.  
  195.   // construct LinkDest
  196.   dest = NULL;
  197.   if (obj1.isArray()) {
  198.     dest = new LinkDest(obj1.getArray(), gTrue);
  199.   } else if (obj1.isDict()) {
  200.     if (obj1.dictLookup("D", &obj2)->isArray())
  201.       dest = new LinkDest(obj2.getArray(), gTrue);
  202.     else
  203.       error(-1, "Bad named destination value");
  204.     obj2.free();
  205.   } else {
  206.     error(-1, "Bad named destination value");
  207.   }
  208.   obj1.free();
  209.  
  210.   return dest;
  211. }
  212.  
  213. Object *Catalog::findDestInTree(Object *tree, GString *name, Object *obj) {
  214.   Object names, name1;
  215.   Object kids, kid, limits, low, high;
  216.   GBool done, found;
  217.   int cmp, i;
  218.  
  219.   // leaf node
  220.   if (tree->dictLookup("Names", &names)->isArray()) {
  221.     done = found = gFalse;
  222.     for (i = 0; !done && i < names.arrayGetLength(); i += 2) {
  223.       if (names.arrayGet(i, &name1)->isString()) {
  224.     cmp = name->cmp(name1.getString());
  225.     if (cmp == 0) {
  226.       names.arrayGet(i+1, obj);
  227.       found = gTrue;
  228.       done = gTrue;
  229.     } else if (cmp < 0) {
  230.       done = gTrue;
  231.     }
  232.     name1.free();
  233.       }
  234.     }
  235.     names.free();
  236.     if (!found)
  237.       obj->initNull();
  238.     return obj;
  239.   }
  240.   names.free();
  241.  
  242.   // root or intermediate node
  243.   done = gFalse;
  244.   if (tree->dictLookup("Kids", &kids)->isArray()) {
  245.     for (i = 0; !done && i < kids.arrayGetLength(); ++i) {
  246.       if (kids.arrayGet(i, &kid)->isDict()) {
  247.     if (kid.dictLookup("Limits", &limits)->isArray()) {
  248.       if (limits.arrayGet(0, &low)->isString() &&
  249.           name->cmp(low.getString()) >= 0) {
  250.         if (limits.arrayGet(1, &high)->isString() &&
  251.         name->cmp(high.getString()) <= 0) {
  252.           findDestInTree(&kid, name, obj);
  253.           done = gTrue;
  254.         }
  255.         high.free();
  256.       }
  257.       low.free();
  258.     }
  259.     limits.free();
  260.       }
  261.       kid.free();
  262.     }
  263.   }
  264.   kids.free();
  265.  
  266.   // name was outside of ranges of all kids
  267.   if (!done)
  268.     obj->initNull();
  269.  
  270.   return obj;
  271. }
  272.