beta-0.89.2
[luatex.git] / source / libs / poppler / poppler-src / poppler / Outline.cc
blobbd4e6d01b6d2c1518b31917fb0173181f5815caa
1 //========================================================================
2 //
3 // Outline.cc
4 //
5 // Copyright 2002-2003 Glyph & Cog, LLC
6 //
7 //========================================================================
9 //========================================================================
11 // Modified under the Poppler project - http://poppler.freedesktop.org
13 // All changes made under the Poppler project to this file are licensed
14 // under GPL version 2 or later
16 // Copyright (C) 2005 Marco Pesenti Gritti <mpg@redhat.com>
17 // Copyright (C) 2008 Albert Astals Cid <aacid@kde.org>
18 // Copyright (C) 2009 Nick Jones <nick.jones@network-box.com>
20 // To see a description of the changes please see the Changelog file that
21 // came with your tarball or type make ChangeLog if you are building from git
23 //========================================================================
25 #include <config.h>
27 #ifdef USE_GCC_PRAGMAS
28 #pragma implementation
29 #endif
31 #include "goo/gmem.h"
32 #include "goo/GooString.h"
33 #include "goo/GooList.h"
34 #include "XRef.h"
35 #include "Link.h"
36 #include "PDFDocEncoding.h"
37 #include "Outline.h"
39 //------------------------------------------------------------------------
41 Outline::Outline(Object *outlineObj, XRef *xref) {
42 Object first, last;
44 items = NULL;
45 if (!outlineObj->isDict()) {
46 return;
48 items = OutlineItem::readItemList(outlineObj->dictLookupNF("First", &first),
49 outlineObj->dictLookupNF("Last", &last),
50 xref);
51 first.free();
52 last.free();
55 Outline::~Outline() {
56 if (items) {
57 deleteGooList(items, OutlineItem);
61 //------------------------------------------------------------------------
63 OutlineItem::OutlineItem(Dict *dict, XRef *xrefA) {
64 Object obj1;
65 GooString *s;
66 int i;
68 xref = xrefA;
69 title = NULL;
70 action = NULL;
71 kids = NULL;
73 if (dict->lookup("Title", &obj1)->isString()) {
74 s = obj1.getString();
75 if ((s->getChar(0) & 0xff) == 0xfe &&
76 (s->getChar(1) & 0xff) == 0xff) {
77 titleLen = (s->getLength() - 2) / 2;
78 title = (Unicode *)gmallocn(titleLen, sizeof(Unicode));
79 for (i = 0; i < titleLen; ++i) {
80 title[i] = ((s->getChar(2 + 2*i) & 0xff) << 8) |
81 (s->getChar(3 + 2*i) & 0xff);
83 } else {
84 titleLen = s->getLength();
85 title = (Unicode *)gmallocn(titleLen, sizeof(Unicode));
86 for (i = 0; i < titleLen; ++i) {
87 title[i] = pdfDocEncoding[s->getChar(i) & 0xff];
90 } else {
91 titleLen = 0;
93 obj1.free();
95 if (!dict->lookup("Dest", &obj1)->isNull()) {
96 action = LinkAction::parseDest(&obj1);
97 } else {
98 obj1.free();
99 if (!dict->lookup("A", &obj1)->isNull()) {
100 action = LinkAction::parseAction(&obj1);
103 obj1.free();
105 dict->lookupNF("First", &firstRef);
106 dict->lookupNF("Last", &lastRef);
107 dict->lookupNF("Next", &nextRef);
109 startsOpen = gFalse;
110 if (dict->lookup("Count", &obj1)->isInt()) {
111 if (obj1.getInt() > 0) {
112 startsOpen = gTrue;
115 obj1.free();
118 OutlineItem::~OutlineItem() {
119 close();
120 if (title) {
121 gfree(title);
123 if (action) {
124 delete action;
126 firstRef.free();
127 lastRef.free();
128 nextRef.free();
131 GooList *OutlineItem::readItemList(Object *firstItemRef, Object *lastItemRef,
132 XRef *xrefA) {
133 GooList *items;
134 char* alreadyRead;
135 OutlineItem *item;
136 Object obj;
137 Object *p;
139 if (!lastItemRef->isRef())
140 return NULL;
142 items = new GooList();
144 alreadyRead = (char *)gmalloc(xrefA->getNumObjects());
145 memset(alreadyRead, 0, xrefA->getNumObjects());
147 p = firstItemRef;
148 while (p->isRef() &&
149 (p->getRefNum() >= 0) &&
150 (p->getRefNum() < xrefA->getNumObjects()) &&
151 !alreadyRead[p->getRefNum()]) {
152 if (!p->fetch(xrefA, &obj)->isDict()) {
153 obj.free();
154 break;
156 alreadyRead[p->getRefNum()] = 1;
157 item = new OutlineItem(obj.getDict(), xrefA);
158 obj.free();
159 items->append(item);
160 if (p->getRef().num == lastItemRef->getRef().num &&
161 p->getRef().gen == lastItemRef->getRef().gen) {
162 break;
164 p = &item->nextRef;
167 gfree(alreadyRead);
169 if (!items->getLength()) {
170 delete items;
171 items = NULL;
174 return items;
177 void OutlineItem::open() {
178 if (!kids) {
179 kids = readItemList(&firstRef, &lastRef, xref);
183 void OutlineItem::close() {
184 if (kids) {
185 deleteGooList(kids, OutlineItem);
186 kids = NULL;