2
1
mirror of https://github.com/qpdf/qpdf.git synced 2024-09-19 16:49:13 +00:00
qpdf/libqpdf/QPDFOutlineDocumentHelper.cc
m-holger 87ee8ad071 In QPDFParser constructor add add parameter parse_pdf
Prepare for treating indirect references differently depending on whether
we are parsing a PDF file (in which case reference to objects not in the
xref table are null even if they are in the object cache) or whether parse
from user code (in which case an indirect reference can refer to a user
created object).
2024-08-06 10:02:07 +01:00

97 lines
2.8 KiB
C++

#include <qpdf/QPDFOutlineDocumentHelper.hh>
#include <qpdf/QTC.hh>
QPDFOutlineDocumentHelper::QPDFOutlineDocumentHelper(QPDF& qpdf) :
QPDFDocumentHelper(qpdf),
m(new Members())
{
QPDFObjectHandle root = qpdf.getRoot();
if (!root.hasKey("/Outlines")) {
return;
}
QPDFObjectHandle outlines = root.getKey("/Outlines");
if (!(outlines.isDictionary() && outlines.hasKey("/First"))) {
return;
}
QPDFObjectHandle cur = outlines.getKey("/First");
QPDFObjGen::set seen;
while (!cur.isNull() && seen.add(cur)) {
m->outlines.push_back(QPDFOutlineObjectHelper::Accessor::create(cur, *this, 1));
cur = cur.getKey("/Next");
}
}
bool
QPDFOutlineDocumentHelper::hasOutlines()
{
return !m->outlines.empty();
}
std::vector<QPDFOutlineObjectHelper>
QPDFOutlineDocumentHelper::getTopLevelOutlines()
{
return m->outlines;
}
void
QPDFOutlineDocumentHelper::initializeByPage()
{
std::list<QPDFOutlineObjectHelper> queue;
queue.insert(queue.end(), m->outlines.begin(), m->outlines.end());
while (!queue.empty()) {
QPDFOutlineObjectHelper oh = queue.front();
queue.pop_front();
m->by_page[oh.getDestPage().getObjGen()].push_back(oh);
std::vector<QPDFOutlineObjectHelper> kids = oh.getKids();
queue.insert(queue.end(), kids.begin(), kids.end());
}
}
std::vector<QPDFOutlineObjectHelper>
QPDFOutlineDocumentHelper::getOutlinesForPage(QPDFObjGen const& og)
{
if (m->by_page.empty()) {
initializeByPage();
}
std::vector<QPDFOutlineObjectHelper> result;
if (m->by_page.count(og)) {
result = m->by_page[og];
}
return result;
}
QPDFObjectHandle
QPDFOutlineDocumentHelper::resolveNamedDest(QPDFObjectHandle name)
{
QPDFObjectHandle result;
if (name.isName()) {
if (!m->dest_dict.isInitialized()) {
m->dest_dict = qpdf.getRoot().getKey("/Dests");
}
QTC::TC("qpdf", "QPDFOutlineDocumentHelper name named dest");
result = m->dest_dict.getKeyIfDict(name.getName());
} else if (name.isString()) {
if (!m->names_dest) {
auto dests = qpdf.getRoot().getKey("/Names").getKeyIfDict("/Dests");
if (dests.isDictionary()) {
m->names_dest = std::make_shared<QPDFNameTreeObjectHelper>(dests, qpdf);
}
}
if (m->names_dest) {
if (m->names_dest->findObject(name.getUTF8Value(), result)) {
QTC::TC("qpdf", "QPDFOutlineDocumentHelper string named dest");
}
}
}
if (!result.isInitialized()) {
return QPDFObjectHandle::newNull();
}
if (result.isDictionary()) {
QTC::TC("qpdf", "QPDFOutlineDocumentHelper named dest dictionary");
return result.getKey("/D");
}
return result;
}