1 //========================================================================
5 // Copyright 1996 Derek B. Noonburg
7 //========================================================================
10 #pragma implementation
23 //------------------------------------------------------------------------
25 //------------------------------------------------------------------------
27 Catalog::Catalog(Object *catDict) {
37 if (!catDict->isDict("Catalog")) {
38 error(-1, "Catalog object is wrong type (%s)", catDict->getTypeName());
43 catDict->dictLookup("Pages", &pagesDict);
44 if (!pagesDict.isDict("Pages")) {
45 error(-1, "Top-level pages object is wrong type (%s)",
46 pagesDict.getTypeName());
49 pagesDict.dictLookup("Count", &obj);
51 error(-1, "Page count in top-level pages object is wrong type (%s)",
55 numPages = obj.getInt();
57 pages = (Page **)gmalloc(numPages * sizeof(Page *));
58 pageRefs = (Ref *)gmalloc(numPages * sizeof(Ref));
59 for (i = 0; i < numPages; ++i) {
64 readPageTree(pagesDict.getDict(), NULL, 0);
67 // read named destination dictionary
68 catDict->dictLookup("Dests", &dests);
70 // read root of named destination tree
71 if (catDict->dictLookup("Names", &obj)->isDict())
72 obj.dictLookup("Dests", &nameTree);
93 for (i = 0; i < numPages; ++i) {
104 int Catalog::readPageTree(Dict *pagesDict, PageAttrs *attrs, int start) {
108 PageAttrs *attrs1, *attrs2;
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());
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);
129 kids.arrayGetNF(i, &kidRef);
130 if (kidRef.isRef()) {
131 pageRefs[start].num = kidRef.getRefNum();
132 pageRefs[start].gen = kidRef.getRefGen();
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)
142 error(-1, "Kid object (page %d) is wrong type (%s)",
143 start+1, kid.getTypeName());
163 int Catalog::findPage(int num, int gen) {
166 for (i = 0; i < numPages; ++i) {
167 if (pageRefs[i].num == num && pageRefs[i].gen == gen)
173 LinkDest *Catalog::findDest(GString *name) {
178 // try named destination dictionary then name tree
180 if (dests.isDict()) {
181 if (!dests.dictLookup(name->getCString(), &obj1)->isNull())
186 if (!found && nameTree.isDict()) {
187 if (!findDestInTree(&nameTree, name, &obj1)->isNull())
195 // construct LinkDest
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);
203 error(-1, "Bad named destination value");
206 error(-1, "Bad named destination value");
213 Object *Catalog::findDestInTree(Object *tree, GString *name, Object *obj) {
215 Object kids, kid, limits, low, high;
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());
226 names.arrayGet(i+1, obj);
229 } else if (cmp < 0) {
242 // root or intermediate node
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);
266 // name was outside of ranges of all kids