/src/qpdf/libqpdf/QPDFOutlineDocumentHelper.cc
Line | Count | Source (jump to first uncovered line) |
1 | | #include <qpdf/QPDFOutlineDocumentHelper.hh> |
2 | | |
3 | | #include <qpdf/QTC.hh> |
4 | | |
5 | | QPDFOutlineDocumentHelper::QPDFOutlineDocumentHelper(QPDF& qpdf) : |
6 | 6.96k | QPDFDocumentHelper(qpdf), |
7 | 6.96k | m(new Members()) |
8 | 6.96k | { |
9 | 6.96k | QPDFObjectHandle root = qpdf.getRoot(); |
10 | 6.96k | if (!root.hasKey("/Outlines")) { |
11 | 6.23k | return; |
12 | 6.23k | } |
13 | 729 | QPDFObjectHandle outlines = root.getKey("/Outlines"); |
14 | 729 | if (!(outlines.isDictionary() && outlines.hasKey("/First"))) { |
15 | 65 | return; |
16 | 65 | } |
17 | 664 | QPDFObjectHandle cur = outlines.getKey("/First"); |
18 | 664 | QPDFObjGen::set seen; |
19 | 1.75k | while (!cur.isNull() && seen.add(cur)) { |
20 | 1.09k | m->outlines.push_back(QPDFOutlineObjectHelper::Accessor::create(cur, *this, 1)); |
21 | 1.09k | cur = cur.getKey("/Next"); |
22 | 1.09k | } |
23 | 664 | } |
24 | | |
25 | | bool |
26 | | QPDFOutlineDocumentHelper::hasOutlines() |
27 | 0 | { |
28 | 0 | return !m->outlines.empty(); |
29 | 0 | } |
30 | | |
31 | | std::vector<QPDFOutlineObjectHelper> |
32 | | QPDFOutlineDocumentHelper::getTopLevelOutlines() |
33 | 0 | { |
34 | 0 | return m->outlines; |
35 | 0 | } |
36 | | |
37 | | void |
38 | | QPDFOutlineDocumentHelper::initializeByPage() |
39 | 9.04k | { |
40 | 9.04k | std::list<QPDFOutlineObjectHelper> queue; |
41 | 9.04k | queue.insert(queue.end(), m->outlines.begin(), m->outlines.end()); |
42 | | |
43 | 13.7k | while (!queue.empty()) { |
44 | 4.68k | QPDFOutlineObjectHelper oh = queue.front(); |
45 | 4.68k | queue.pop_front(); |
46 | 4.68k | m->by_page[oh.getDestPage().getObjGen()].push_back(oh); |
47 | 4.68k | std::vector<QPDFOutlineObjectHelper> kids = oh.getKids(); |
48 | 4.68k | queue.insert(queue.end(), kids.begin(), kids.end()); |
49 | 4.68k | } |
50 | 9.04k | } |
51 | | |
52 | | std::vector<QPDFOutlineObjectHelper> |
53 | | QPDFOutlineDocumentHelper::getOutlinesForPage(QPDFObjGen og) |
54 | 9.42k | { |
55 | 9.42k | if (m->by_page.empty()) { |
56 | 9.04k | initializeByPage(); |
57 | 9.04k | } |
58 | 9.42k | std::vector<QPDFOutlineObjectHelper> result; |
59 | 9.42k | if (m->by_page.contains(og)) { |
60 | 192 | result = m->by_page[og]; |
61 | 192 | } |
62 | 9.42k | return result; |
63 | 9.42k | } |
64 | | |
65 | | QPDFObjectHandle |
66 | | QPDFOutlineDocumentHelper::resolveNamedDest(QPDFObjectHandle name) |
67 | 1.11k | { |
68 | 1.11k | QPDFObjectHandle result; |
69 | 1.11k | if (name.isName()) { |
70 | 185 | if (!m->dest_dict) { |
71 | 46 | m->dest_dict = qpdf.getRoot().getKey("/Dests"); |
72 | 46 | } |
73 | 185 | QTC::TC("qpdf", "QPDFOutlineDocumentHelper name named dest"); |
74 | 185 | result = m->dest_dict.getKeyIfDict(name.getName()); |
75 | 934 | } else if (name.isString()) { |
76 | 934 | if (!m->names_dest) { |
77 | 629 | auto dests = qpdf.getRoot().getKey("/Names").getKeyIfDict("/Dests"); |
78 | 629 | if (dests.isDictionary()) { |
79 | 353 | m->names_dest = std::make_shared<QPDFNameTreeObjectHelper>(dests, qpdf); |
80 | 353 | } |
81 | 629 | } |
82 | 934 | if (m->names_dest) { |
83 | 658 | if (m->names_dest->findObject(name.getUTF8Value(), result)) { |
84 | 116 | QTC::TC("qpdf", "QPDFOutlineDocumentHelper string named dest"); |
85 | 116 | } |
86 | 658 | } |
87 | 934 | } |
88 | 1.11k | if (!result) { |
89 | 601 | return QPDFObjectHandle::newNull(); |
90 | 601 | } |
91 | 518 | if (result.isDictionary()) { |
92 | 41 | QTC::TC("qpdf", "QPDFOutlineDocumentHelper named dest dictionary"); |
93 | 41 | return result.getKey("/D"); |
94 | 41 | } |
95 | 477 | return result; |
96 | 518 | } |