source: trunk/poppler/mypoppler/poppler/Catalog.cc @ 461

Last change on this file since 461 was 461, checked in by Silvan Scherrer, 11 years ago

poppler update to 0.14.2

File size: 21.1 KB
Line 
1//========================================================================
2//
3// Catalog.cc
4//
5// Copyright 1996-2007 Glyph & Cog, LLC
6//
7//========================================================================
8
9//========================================================================
10//
11// Modified under the Poppler project - http://poppler.freedesktop.org
12//
13// All changes made under the Poppler project to this file are licensed
14// under GPL version 2 or later
15//
16// Copyright (C) 2005 Kristian HÞgsberg <krh@redhat.com>
17// Copyright (C) 2005-2010 Albert Astals Cid <aacid@kde.org>
18// Copyright (C) 2005 Jeff Muizelaar <jrmuizel@nit.ca>
19// Copyright (C) 2005 Jonathan Blandford <jrb@redhat.com>
20// Copyright (C) 2005 Marco Pesenti Gritti <mpg@redhat.com>
21// Copyright (C) 2005, 2006, 2008 Brad Hards <bradh@frogmouth.net>
22// Copyright (C) 2006, 2008 Carlos Garcia Campos <carlosgc@gnome.org>
23// Copyright (C) 2007 Julien Rebetez <julienr@svn.gnome.org>
24// Copyright (C) 2008 Pino Toscano <pino@kde.org>
25// Copyright (C) 2009 Ilya Gorenbein <igorenbein@finjan.com>
26// Copyright (C) 2010 Hib Eris <hib@hiberis.nl>
27//
28// To see a description of the changes please see the Changelog file that
29// came with your tarball or type make ChangeLog if you are building from git
30//
31//========================================================================
32
33#include <config.h>
34
35#ifdef USE_GCC_PRAGMAS
36#pragma implementation
37#endif
38
39#include <stddef.h>
40#include <stdlib.h>
41#include "goo/gmem.h"
42#include "Object.h"
43#include "XRef.h"
44#include "Array.h"
45#include "Dict.h"
46#include "Page.h"
47#include "Error.h"
48#include "Link.h"
49#include "PageLabelInfo.h"
50#include "Catalog.h"
51#include "Form.h"
52#include "OptionalContent.h"
53
54//------------------------------------------------------------------------
55// Catalog
56//------------------------------------------------------------------------
57
58Catalog::Catalog(XRef *xrefA) {
59  Object catDict, pagesDict, pagesDictRef;
60  Object obj, obj2;
61  Object optContentProps;
62  char *alreadyRead;
63  int numPages0;
64  int i;
65
66  ok = gTrue;
67  xref = xrefA;
68  pages = NULL;
69  pageRefs = NULL;
70  numPages = pagesSize = 0;
71  baseURI = NULL;
72  pageLabelInfo = NULL;
73  form = NULL;
74  optContent = NULL;
75  pageMode = pageModeNull;
76  pageLayout = pageLayoutNull;
77  destNameTree = NULL;
78  embeddedFileNameTree = NULL;
79  jsNameTree = NULL;
80
81  xref->getCatalog(&catDict);
82  if (!catDict.isDict()) {
83    error(-1, "Catalog object is wrong type (%s)", catDict.getTypeName());
84    goto err1;
85  }
86  // get the AcroForm dictionary
87  catDict.dictLookup("AcroForm", &acroForm);
88
89  // read page tree
90  catDict.dictLookup("Pages", &pagesDict);
91  // This should really be isDict("Pages"), but I've seen at least one
92  // PDF file where the /Type entry is missing.
93  if (!pagesDict.isDict()) {
94    error(-1, "Top-level pages object is wrong type (%s)",
95          pagesDict.getTypeName());
96    goto err2;
97  }
98  pagesDict.dictLookup("Count", &obj);
99  // some PDF files actually use real numbers here ("/Count 9.0")
100  if (!obj.isNum()) {
101    error(-1, "Page count in top-level pages object is wrong type (%s)",
102          obj.getTypeName());
103    pagesSize = numPages0 = 0;
104  } else {
105    pagesSize = numPages0 = (int)obj.getNum();
106  }
107  obj.free();
108  pages = (Page **)gmallocn(pagesSize, sizeof(Page *));
109  pageRefs = (Ref *)gmallocn(pagesSize, sizeof(Ref));
110  for (i = 0; i < pagesSize; ++i) {
111    pages[i] = NULL;
112    pageRefs[i].num = -1;
113    pageRefs[i].gen = -1;
114  }
115  alreadyRead = (char *)gmalloc(xref->getNumObjects());
116  memset(alreadyRead, 0, xref->getNumObjects());
117  if (catDict.dictLookupNF("Pages", &pagesDictRef)->isRef() &&
118      pagesDictRef.getRefNum() >= 0 &&
119      pagesDictRef.getRefNum() < xref->getNumObjects()) {
120    alreadyRead[pagesDictRef.getRefNum()] = 1;
121  }
122  pagesDictRef.free();
123  numPages = readPageTree(pagesDict.getDict(), NULL, 0, alreadyRead);
124  gfree(alreadyRead);
125  if (numPages != numPages0) {
126    error(-1, "Page count in top-level pages object is incorrect");
127  }
128  pagesDict.free();
129
130  // read base URI
131  if (catDict.dictLookup("URI", &obj)->isDict()) {
132    if (obj.dictLookup("Base", &obj2)->isString()) {
133      baseURI = obj2.getString()->copy();
134    }
135    obj2.free();
136  }
137  obj.free();
138
139  // get the Optional Content dictionary
140  if (catDict.dictLookup("OCProperties", &optContentProps)->isDict()) {
141    optContent = new OCGs(&optContentProps, xref);
142    if (!optContent->isOk ()) {
143      delete optContent;
144      optContent = NULL;
145    }
146  }
147  optContentProps.free();
148
149  // perform form-related loading after all widgets have been loaded
150  if (getForm())
151    getForm()->postWidgetsLoad();
152
153  catDict.free();
154  return;
155
156 err2:
157  pagesDict.free();
158 err1:
159  catDict.free();
160  ok = gFalse;
161}
162
163Catalog::~Catalog() {
164  int i;
165
166  if (pages) {
167    for (i = 0; i < pagesSize; ++i) {
168      if (pages[i]) {
169        delete pages[i];
170      }
171    }
172    gfree(pages);
173    gfree(pageRefs);
174  }
175  dests.free();
176  delete destNameTree;
177  delete embeddedFileNameTree;
178  delete jsNameTree;
179  if (baseURI) {
180    delete baseURI;
181  }
182  delete pageLabelInfo;
183  delete form;
184  delete optContent;
185  metadata.free();
186  structTreeRoot.free();
187  outline.free();
188  acroForm.free();
189}
190
191GooString *Catalog::readMetadata() {
192  GooString *s;
193  Dict *dict;
194  Object obj;
195  int c;
196
197  if (metadata.isNone()) {
198    Object catDict;
199
200    xref->getCatalog(&catDict);
201    if (catDict.isDict()) {
202      catDict.dictLookup("Metadata", &metadata);
203    } else {
204      error(-1, "Catalog object is wrong type (%s)", catDict.getTypeName());
205      metadata.initNull();
206    }
207    catDict.free();
208  }
209
210  if (!metadata.isStream()) {
211    return NULL;
212  }
213  dict = metadata.streamGetDict();
214  if (!dict->lookup("Subtype", &obj)->isName("XML")) {
215    error(-1, "Unknown Metadata type: '%s'",
216          obj.isName() ? obj.getName() : "???");
217  }
218  obj.free();
219  s = new GooString();
220  metadata.streamReset();
221  while ((c = metadata.streamGetChar()) != EOF) {
222    s->append(c);
223  }
224  metadata.streamClose();
225  return s;
226}
227
228int Catalog::readPageTree(Dict *pagesDict, PageAttrs *attrs, int start,
229                          char *alreadyRead) {
230  Object kids;
231  Object kid;
232  Object kidRef;
233  PageAttrs *attrs1, *attrs2;
234  Page *page;
235  int i, j;
236
237  attrs1 = new PageAttrs(attrs, pagesDict);
238  pagesDict->lookup("Kids", &kids);
239  if (!kids.isArray()) {
240    error(-1, "Kids object (page %d) is wrong type (%s)",
241          start+1, kids.getTypeName());
242    return start;
243  }
244  for (i = 0; i < kids.arrayGetLength(); ++i) {
245    kids.arrayGetNF(i, &kidRef);
246    if (kidRef.isRef() &&
247        kidRef.getRefNum() >= 0 &&
248        kidRef.getRefNum() < xref->getNumObjects()) {
249      if (alreadyRead[kidRef.getRefNum()]) {
250        error(-1, "Loop in Pages tree");
251        kidRef.free();
252        continue;
253      }
254      alreadyRead[kidRef.getRefNum()] = 1;
255    }
256    kids.arrayGet(i, &kid);
257    if (kid.isDict("Page")) {
258      attrs2 = new PageAttrs(attrs1, kid.getDict());
259      page = new Page(xref, start+1, kid.getDict(), kidRef.getRef(), attrs2, getForm());
260      if (!page->isOk()) {
261        ++start;
262        goto err3;
263      }
264      if (start >= pagesSize) {
265        pagesSize += 32;
266        pages = (Page **)greallocn(pages, pagesSize, sizeof(Page *));
267        pageRefs = (Ref *)greallocn(pageRefs, pagesSize, sizeof(Ref));
268        for (j = pagesSize - 32; j < pagesSize; ++j) {
269          pages[j] = NULL;
270          pageRefs[j].num = -1;
271          pageRefs[j].gen = -1;
272        }
273      }
274      pages[start] = page;
275      if (kidRef.isRef()) {
276        pageRefs[start].num = kidRef.getRefNum();
277        pageRefs[start].gen = kidRef.getRefGen();
278      }
279      ++start;
280    // This should really be isDict("Pages"), but I've seen at least one
281    // PDF file where the /Type entry is missing.
282    } else if (kid.isDict()) {
283      if ((start = readPageTree(kid.getDict(), attrs1, start, alreadyRead))
284          < 0)
285        goto err2;
286    } else {
287      error(-1, "Kid object (page %d) is wrong type (%s)",
288            start+1, kid.getTypeName());
289    }
290    kid.free();
291    kidRef.free();
292  }
293  delete attrs1;
294  kids.free();
295  return start;
296
297 err3:
298  delete page;
299 err2:
300  kid.free();
301  kidRef.free();
302  kids.free();
303  delete attrs1;
304  ok = gFalse;
305  return -1;
306}
307
308int Catalog::findPage(int num, int gen) {
309  int i;
310
311  for (i = 0; i < numPages; ++i) {
312    if (pageRefs[i].num == num && pageRefs[i].gen == gen)
313      return i + 1;
314  }
315  return 0;
316}
317
318LinkDest *Catalog::findDest(GooString *name) {
319  LinkDest *dest;
320  Object obj1, obj2;
321  GBool found;
322
323  // try named destination dictionary then name tree
324  found = gFalse;
325  if (getDests()->isDict()) {
326    if (!getDests()->dictLookup(name->getCString(), &obj1)->isNull())
327      found = gTrue;
328    else
329      obj1.free();
330  }
331  if (!found) {
332    if (getDestNameTree()->lookup(name, &obj1))
333      found = gTrue;
334    else
335      obj1.free();
336  }
337  if (!found)
338    return NULL;
339
340  // construct LinkDest
341  dest = NULL;
342  if (obj1.isArray()) {
343    dest = new LinkDest(obj1.getArray());
344  } else if (obj1.isDict()) {
345    if (obj1.dictLookup("D", &obj2)->isArray())
346      dest = new LinkDest(obj2.getArray());
347    else
348      error(-1, "Bad named destination value");
349    obj2.free();
350  } else {
351    error(-1, "Bad named destination value");
352  }
353  obj1.free();
354  if (dest && !dest->isOk()) {
355    delete dest;
356    dest = NULL;
357  }
358
359  return dest;
360}
361
362EmbFile *Catalog::embeddedFile(int i)
363{
364    Object efDict;
365    Object obj;
366    obj = getEmbeddedFileNameTree()->getValue(i);
367    EmbFile *embeddedFile = 0;
368    if (obj.isRef()) {
369        GooString desc(getEmbeddedFileNameTree()->getName(i));
370        embeddedFile = new EmbFile(obj.fetch(xref, &efDict), &desc);
371        efDict.free();
372    } else {
373        Object null;
374        embeddedFile = new EmbFile(&null);
375    }
376    return embeddedFile;
377}
378
379GooString *Catalog::getJS(int i)
380{
381  Object obj = getJSNameTree()->getValue(i);
382  if (obj.isRef()) {
383    Ref r = obj.getRef();
384    obj.free();
385    xref->fetch(r.num, r.gen, &obj);
386  }
387
388  if (!obj.isDict()) {
389    obj.free();
390    return 0;
391  }
392  Object obj2;
393  if (!obj.dictLookup("S", &obj2)->isName()) {
394    obj2.free();
395    obj.free();
396    return 0;
397  }
398  if (strcmp(obj2.getName(), "JavaScript")) {
399    obj2.free();
400    obj.free();
401    return 0;
402  }
403  obj2.free();
404  obj.dictLookup("JS", &obj2);
405  GooString *js = 0;
406  if (obj2.isString()) {
407    js = new GooString(obj2.getString());
408  }
409  else if (obj2.isStream()) {
410    Stream *stream = obj2.getStream();
411    js = new GooString();
412    stream->reset();
413    int j;
414    while ((j = stream->getChar()) != EOF) {
415      js->append((char)j);
416    }
417  }
418  obj2.free();
419  obj.free();
420  return js;
421}
422
423Catalog::PageMode Catalog::getPageMode() {
424
425  if (pageMode == pageModeNull) {
426
427    Object catDict, obj;
428
429    pageMode = pageModeNone;
430
431    xref->getCatalog(&catDict);
432    if (!catDict.isDict()) {
433      error(-1, "Catalog object is wrong type (%s)", catDict.getTypeName());
434      catDict.free();
435      return pageMode;
436    }
437
438    if (catDict.dictLookup("PageMode", &obj)->isName()) {
439      if (obj.isName("UseNone"))
440        pageMode = pageModeNone;
441      else if (obj.isName("UseOutlines"))
442        pageMode = pageModeOutlines;
443      else if (obj.isName("UseThumbs"))
444        pageMode = pageModeThumbs;
445      else if (obj.isName("FullScreen"))
446        pageMode = pageModeFullScreen;
447      else if (obj.isName("UseOC"))
448        pageMode = pageModeOC;
449      else if (obj.isName("UseAttachments"))
450        pageMode = pageModeAttach;
451    }
452    obj.free();
453    catDict.free();
454  }
455  return pageMode;
456}
457
458Catalog::PageLayout Catalog::getPageLayout() {
459
460  if (pageLayout == pageLayoutNull) {
461
462    Object catDict, obj;
463
464    pageLayout = pageLayoutNone;
465
466    xref->getCatalog(&catDict);
467    if (!catDict.isDict()) {
468      error(-1, "Catalog object is wrong type (%s)", catDict.getTypeName());
469      catDict.free();
470      return pageLayout;
471    }
472
473    pageLayout = pageLayoutNone;
474    if (catDict.dictLookup("PageLayout", &obj)->isName()) {
475      if (obj.isName("SinglePage"))
476        pageLayout = pageLayoutSinglePage;
477      if (obj.isName("OneColumn"))
478        pageLayout = pageLayoutOneColumn;
479      if (obj.isName("TwoColumnLeft"))
480        pageLayout = pageLayoutTwoColumnLeft;
481      if (obj.isName("TwoColumnRight"))
482        pageLayout = pageLayoutTwoColumnRight;
483      if (obj.isName("TwoPageLeft"))
484        pageLayout = pageLayoutTwoPageLeft;
485      if (obj.isName("TwoPageRight"))
486        pageLayout = pageLayoutTwoPageRight;
487    }
488    obj.free();
489    catDict.free();
490  }
491  return pageLayout;
492}
493
494NameTree::NameTree()
495{
496  size = 0;
497  length = 0;
498  entries = NULL;
499}
500
501NameTree::~NameTree()
502{
503  int i;
504
505  for (i = 0; i < length; i++)
506    delete entries[i];
507
508  gfree(entries);
509}
510
511NameTree::Entry::Entry(Array *array, int index) {
512    if (!array->getString(index, &name) || !array->getNF(index + 1, &value)) {
513      Object aux;
514      array->get(index, &aux);
515      if (aux.isString() && array->getNF(index + 1, &value) )
516      {
517        name.append(aux.getString());
518      }
519      else
520        error(-1, "Invalid page tree");
521    }
522}
523
524NameTree::Entry::~Entry() {
525  value.free();
526}
527
528void NameTree::addEntry(Entry *entry)
529{
530  if (length == size) {
531    if (length == 0) {
532      size = 8;
533    } else {
534      size *= 2;
535    }
536    entries = (Entry **) grealloc (entries, sizeof (Entry *) * size);
537  }
538
539  entries[length] = entry;
540  ++length;
541}
542
543void NameTree::init(XRef *xrefA, Object *tree) {
544  xref = xrefA;
545  parse(tree);
546}
547
548void NameTree::parse(Object *tree) {
549  Object names;
550  Object kids, kid;
551  int i;
552
553  if (!tree->isDict())
554    return;
555
556  // leaf node
557  if (tree->dictLookup("Names", &names)->isArray()) {
558    for (i = 0; i < names.arrayGetLength(); i += 2) {
559      NameTree::Entry *entry;
560
561      entry = new Entry(names.getArray(), i);
562      addEntry(entry);
563    }
564  }
565  names.free();
566
567  // root or intermediate node
568  if (tree->dictLookup("Kids", &kids)->isArray()) {
569    for (i = 0; i < kids.arrayGetLength(); ++i) {
570      if (kids.arrayGet(i, &kid)->isDict())
571        parse(&kid);
572      kid.free();
573    }
574  }
575  kids.free();
576}
577
578int NameTree::Entry::cmp(const void *voidKey, const void *voidEntry)
579{
580  GooString *key = (GooString *) voidKey;
581  Entry *entry = *(NameTree::Entry **) voidEntry;
582
583  return key->cmp(&entry->name);
584}
585
586GBool NameTree::lookup(GooString *name, Object *obj)
587{
588  Entry **entry;
589
590  entry = (Entry **) bsearch(name, entries,
591                             length, sizeof(Entry *), Entry::cmp);
592  if (entry != NULL) {
593    (*entry)->value.fetch(xref, obj);
594    return gTrue;
595  } else {
596    printf("failed to look up %s\n", name->getCString());
597    obj->initNull();
598    return gFalse;
599  }
600}
601
602Object NameTree::getValue(int index)
603{
604  if (index < length) {
605    return entries[index]->value;
606  } else {
607    return Object();
608  }
609}
610
611GooString *NameTree::getName(int index)
612{
613    if (index < length) {
614        return &entries[index]->name;
615    } else {
616        return NULL;
617    }
618}
619
620GBool Catalog::labelToIndex(GooString *label, int *index)
621{
622  char *end;
623
624  PageLabelInfo *pli = getPageLabelInfo();
625  if (pli != NULL) {
626    if (!pli->labelToIndex(label, index))
627      return gFalse;
628  } else {
629    *index = strtol(label->getCString(), &end, 10) - 1;
630    if (*end != '\0')
631      return gFalse;
632  }
633
634  if (*index < 0 || *index >= numPages)
635    return gFalse;
636
637  return gTrue;
638}
639
640GBool Catalog::indexToLabel(int index, GooString *label)
641{
642  char buffer[32];
643
644  if (index < 0 || index >= numPages)
645    return gFalse;
646
647  PageLabelInfo *pli = getPageLabelInfo();
648  if (pli != NULL) {
649    return pli->indexToLabel(index, label);
650  } else {
651    snprintf(buffer, sizeof (buffer), "%d", index + 1);
652    label->append(buffer);           
653    return gTrue;
654  }
655}
656
657EmbFile::EmbFile(Object *efDict, GooString *description)
658{
659  m_name = 0;
660  m_description = 0;
661  if (description)
662    m_description = description->copy();
663  m_size = -1;
664  m_createDate = 0;
665  m_modDate = 0;
666  m_checksum = 0;
667  m_mimetype = 0;
668  if (efDict->isDict()) {
669    Object fileSpec;
670    Object fileDesc;
671    Object paramDict;
672    Object paramObj;
673    Object obj2;
674    Stream *efStream = NULL;
675    // efDict matches Table 3.40 in the PDF1.6 spec
676    efDict->dictLookup("F", &fileSpec);
677    if (fileSpec.isString()) {
678      m_name = new GooString(fileSpec.getString());
679    }
680    fileSpec.free();
681
682    // the logic here is that the description from the name
683    // dictionary is used if we don't have a more specific
684    // description - see the Note: on page 157 of the PDF1.6 spec
685    efDict->dictLookup("Desc", &fileDesc);
686    if (fileDesc.isString()) {
687      delete m_description;
688      m_description = new GooString(fileDesc.getString());
689    } else {
690      efDict->dictLookup("Description", &fileDesc);
691      if (fileDesc.isString()) {
692        delete m_description;
693        m_description = new GooString(fileDesc.getString());
694      }
695    }
696    fileDesc.free();
697
698    efDict->dictLookup("EF", &obj2);
699    if (obj2.isDict()) {
700      // This gives us the raw data stream bytes
701
702      obj2.dictLookup("F", &m_objStr);
703      if (m_objStr.isStream()) {
704        efStream = m_objStr.getStream();
705
706        // dataDict corresponds to Table 3.41 in the PDF1.6 spec.
707        Dict *dataDict = efStream->getDict();
708
709        // subtype is normally the mimetype
710        Object subtypeName;
711        if (dataDict->lookup("Subtype", &subtypeName)->isName()) {
712          m_mimetype = new GooString(subtypeName.getName());
713        }
714        subtypeName.free();
715
716        // paramDict corresponds to Table 3.42 in the PDF1.6 spec
717        Object paramDict;
718        dataDict->lookup( "Params", &paramDict );
719        if (paramDict.isDict()) {
720          paramDict.dictLookup("ModDate", &paramObj);
721          if (paramObj.isString()) {
722            m_modDate = new GooString(paramObj.getString());
723          }
724          paramObj.free();
725          paramDict.dictLookup("CreationDate", &paramObj);
726          if (paramObj.isString()) {
727            m_createDate = new GooString(paramObj.getString());
728          }
729          paramObj.free();
730          paramDict.dictLookup("Size", &paramObj);
731          if (paramObj.isInt()) {
732            m_size = paramObj.getInt();
733          }
734          paramObj.free();
735          paramDict.dictLookup("CheckSum", &paramObj);
736          if (paramObj.isString()) {
737            m_checksum = new GooString(paramObj.getString());
738          }
739          paramObj.free();
740        }
741        paramDict.free();
742      }
743    }
744    obj2.free();
745  }
746  if (!m_name)
747    m_name = new GooString();
748  if (!m_description)
749    m_description = new GooString();
750  if (!m_createDate)
751    m_createDate = new GooString();
752  if (!m_modDate)
753    m_modDate = new GooString();
754  if (!m_checksum)
755    m_checksum = new GooString();
756  if (!m_mimetype)
757    m_mimetype = new GooString();
758}
759
760PageLabelInfo *Catalog::getPageLabelInfo()
761{
762  if (!pageLabelInfo) {
763    Object catDict;
764    Object obj;
765
766    xref->getCatalog(&catDict);
767    if (!catDict.isDict()) {
768      error(-1, "Catalog object is wrong type (%s)", catDict.getTypeName());
769      catDict.free();
770      return NULL;
771    }
772
773    if (catDict.dictLookup("PageLabels", &obj)->isDict()) {
774      pageLabelInfo = new PageLabelInfo(&obj, getNumPages());
775    }
776    obj.free();
777    catDict.free();
778  }
779
780  return pageLabelInfo;
781}
782
783Object *Catalog::getStructTreeRoot()
784{
785  if (structTreeRoot.isNone())
786  {
787     Object catDict;
788
789     xref->getCatalog(&catDict);
790     if (catDict.isDict()) {
791       catDict.dictLookup("StructTreeRoot", &structTreeRoot);
792     } else {
793       error(-1, "Catalog object is wrong type (%s)", catDict.getTypeName());
794       structTreeRoot.initNull();
795     }
796     catDict.free();
797  }
798
799  return &structTreeRoot;
800}
801
802Object *Catalog::getOutline()
803{
804  if (outline.isNone())
805  {
806     Object catDict;
807
808     xref->getCatalog(&catDict);
809     if (catDict.isDict()) {
810       catDict.dictLookup("Outlines", &outline);
811     } else {
812       error(-1, "Catalog object is wrong type (%s)", catDict.getTypeName());
813       outline.initNull();
814     }
815     catDict.free();
816  }
817
818  return &outline;
819}
820
821Object *Catalog::getDests()
822{
823  if (dests.isNone())
824  {
825     Object catDict;
826
827     xref->getCatalog(&catDict);
828     if (catDict.isDict()) {
829       catDict.dictLookup("Dests", &dests);
830     } else {
831       error(-1, "Catalog object is wrong type (%s)", catDict.getTypeName());
832       dests.initNull();
833     }
834     catDict.free();
835  }
836
837  return &dests;
838}
839
840Form *Catalog::getForm()
841{
842  if (!form) {
843    if (acroForm.isDict()) {
844      form = new Form(xref,&acroForm);
845    }
846  }
847
848  return form;
849}
850
851Object *Catalog::getNames()
852{
853  if (names.isNone())
854  {
855     Object catDict;
856
857     xref->getCatalog(&catDict);
858     if (catDict.isDict()) {
859       catDict.dictLookup("Names", &names);
860     } else {
861       error(-1, "Catalog object is wrong type (%s)", catDict.getTypeName());
862       names.initNull();
863     }
864     catDict.free();
865  }
866
867  return &names;
868}
869
870NameTree *Catalog::getDestNameTree()
871{
872  if (!destNameTree) {
873
874    destNameTree = new NameTree();
875
876    if (getNames()->isDict()) {
877       Object obj;
878
879       getNames()->dictLookup("Dests", &obj);
880       destNameTree->init(xref, &obj);
881       obj.free();
882    }
883
884  }
885
886  return destNameTree;
887}
888
889NameTree *Catalog::getEmbeddedFileNameTree()
890{
891  if (!embeddedFileNameTree) {
892
893    embeddedFileNameTree = new NameTree();
894
895    if (getNames()->isDict()) {
896       Object obj;
897
898       getNames()->dictLookup("EmbeddedFiles", &obj);
899       embeddedFileNameTree->init(xref, &obj);
900       obj.free();
901    }
902
903  }
904
905  return embeddedFileNameTree;
906}
907
908NameTree *Catalog::getJSNameTree()
909{
910  if (!jsNameTree) {
911
912    jsNameTree = new NameTree();
913
914    if (getNames()->isDict()) {
915       Object obj;
916
917       getNames()->dictLookup("JavaScript", &obj);
918       jsNameTree->init(xref, &obj);
919       obj.free();
920    }
921
922  }
923
924  return jsNameTree;
925}
926
Note: See TracBrowser for help on using the repository browser.