blob: 82f286633e7a818dc9e1c3c54c6b9c0fdae66c07 [file] [log] [blame]
//========================================================================
//
// Outline.cc
//
// Copyright 2002-2003 Glyph & Cog, LLC
//
//========================================================================
//========================================================================
//
// Modified under the Poppler project - http://poppler.freedesktop.org
//
// All changes made under the Poppler project to this file are licensed
// under GPL version 2 or later
//
// Copyright (C) 2005 Marco Pesenti Gritti <mpg@redhat.com>
// Copyright (C) 2008, 2016, 2017 Albert Astals Cid <aacid@kde.org>
// Copyright (C) 2009 Nick Jones <nick.jones@network-box.com>
// Copyright (C) 2016 Jason Crain <jason@aquaticape.us>
// Copyright (C) 2017 Adrian Johnson <ajohnson@redneon.com>
//
// To see a description of the changes please see the Changelog file that
// came with your tarball or type make ChangeLog if you are building from git
//
//========================================================================
#include <config.h>
#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
#include "goo/gmem.h"
#include "goo/GooString.h"
#include "goo/GooList.h"
#include "XRef.h"
#include "Link.h"
#include "PDFDocEncoding.h"
#include "Outline.h"
#include "UTF.h"
//------------------------------------------------------------------------
Outline::Outline(Object *outlineObj, XRef *xref) {
items = nullptr;
if (!outlineObj->isDict()) {
return;
}
Object first = outlineObj->dictLookupNF("First");
items = OutlineItem::readItemList(&first, xref);
}
Outline::~Outline() {
if (items) {
deleteGooList(items, OutlineItem);
}
}
//------------------------------------------------------------------------
OutlineItem::OutlineItem(Dict *dict, XRef *xrefA) {
Object obj1;
xref = xrefA;
title = NULL;
action = NULL;
kids = NULL;
obj1 = dict->lookup("Title");
if (obj1.isString()) {
GooString *s = obj1.getString();
titleLen = TextStringToUCS4(s, &title);
} else {
titleLen = 0;
}
obj1 = dict->lookup("Dest");
if (!obj1.isNull()) {
action = LinkAction::parseDest(&obj1);
} else {
obj1 = dict->lookup("A");
if (!obj1.isNull()) {
action = LinkAction::parseAction(&obj1);
}
}
firstRef = dict->lookupNF("First");
lastRef = dict->lookupNF("Last");
nextRef = dict->lookupNF("Next");
startsOpen = gFalse;
obj1 = dict->lookup("Count");
if (obj1.isInt()) {
if (obj1.getInt() > 0) {
startsOpen = gTrue;
}
}
}
OutlineItem::~OutlineItem() {
close();
if (title) {
gfree(title);
}
if (action) {
delete action;
}
}
GooList *OutlineItem::readItemList(Object *firstItemRef, XRef *xrefA) {
GooList *items;
char* alreadyRead;
OutlineItem *item;
Object *p;
items = new GooList();
alreadyRead = (char *)gmalloc(xrefA->getNumObjects());
memset(alreadyRead, 0, xrefA->getNumObjects());
p = firstItemRef;
while (p->isRef() &&
(p->getRefNum() >= 0) &&
(p->getRefNum() < xrefA->getNumObjects()) &&
!alreadyRead[p->getRefNum()]) {
Object obj = p->fetch(xrefA);
if (!obj.isDict()) {
break;
}
alreadyRead[p->getRefNum()] = 1;
item = new OutlineItem(obj.getDict(), xrefA);
items->append(item);
p = &item->nextRef;
}
gfree(alreadyRead);
if (!items->getLength()) {
delete items;
items = NULL;
}
return items;
}
void OutlineItem::open() {
if (!kids) {
kids = readItemList(&firstRef, xref);
}
}
void OutlineItem::close() {
if (kids) {
deleteGooList(kids, OutlineItem);
kids = NULL;
}
}