/src/qpdf/libqpdf/QPDFOutlineObjectHelper.cc
Line | Count | Source (jump to first uncovered line) |
1 | | #include <qpdf/QPDFOutlineObjectHelper.hh> |
2 | | |
3 | | #include <qpdf/QPDFOutlineDocumentHelper.hh> |
4 | | #include <qpdf/QTC.hh> |
5 | | |
6 | | QPDFOutlineObjectHelper::Members::Members(QPDFOutlineDocumentHelper& dh) : |
7 | | dh(dh) |
8 | 2.34k | { |
9 | 2.34k | } |
10 | | |
11 | | QPDFOutlineObjectHelper::QPDFOutlineObjectHelper( |
12 | | QPDFObjectHandle oh, QPDFOutlineDocumentHelper& dh, int depth) : |
13 | | QPDFObjectHelper(oh), |
14 | | m(new Members(dh)) |
15 | 2.34k | { |
16 | 2.34k | if (depth > 50) { |
17 | | // Not exercised in test suite, but was tested manually by temporarily changing max depth |
18 | | // to 1. |
19 | 0 | return; |
20 | 0 | } |
21 | 2.34k | if (QPDFOutlineDocumentHelper::Accessor::checkSeen(m->dh, this->oh.getObjGen())) { |
22 | 66 | QTC::TC("qpdf", "QPDFOutlineObjectHelper loop"); |
23 | 66 | return; |
24 | 66 | } |
25 | | |
26 | 2.28k | QPDFObjGen::set children; |
27 | 2.28k | QPDFObjectHandle cur = oh.getKey("/First"); |
28 | 3.92k | while (!cur.isNull() && children.add(cur)) { |
29 | 1.63k | QPDFOutlineObjectHelper new_ooh(cur, dh, 1 + depth); |
30 | 1.63k | new_ooh.m->parent = std::make_shared<QPDFOutlineObjectHelper>(*this); |
31 | 1.63k | m->kids.push_back(new_ooh); |
32 | 1.63k | cur = cur.getKey("/Next"); |
33 | 1.63k | } |
34 | 2.28k | } |
35 | | |
36 | | std::shared_ptr<QPDFOutlineObjectHelper> |
37 | | QPDFOutlineObjectHelper::getParent() |
38 | 0 | { |
39 | 0 | return m->parent; |
40 | 0 | } |
41 | | |
42 | | std::vector<QPDFOutlineObjectHelper> |
43 | | QPDFOutlineObjectHelper::getKids() |
44 | 2.11k | { |
45 | 2.11k | return m->kids; |
46 | 2.11k | } |
47 | | |
48 | | QPDFObjectHandle |
49 | | QPDFOutlineObjectHelper::getDest() |
50 | 2.39k | { |
51 | 2.39k | QPDFObjectHandle dest; |
52 | 2.39k | QPDFObjectHandle A; |
53 | 2.39k | if (this->oh.hasKey("/Dest")) { |
54 | 1.93k | QTC::TC("qpdf", "QPDFOutlineObjectHelper direct dest"); |
55 | 1.93k | dest = this->oh.getKey("/Dest"); |
56 | 1.93k | } else if ( |
57 | 463 | (A = this->oh.getKey("/A")).isDictionary() && A.getKey("/S").isName() && |
58 | 463 | (A.getKey("/S").getName() == "/GoTo") && A.hasKey("/D")) { |
59 | 182 | QTC::TC("qpdf", "QPDFOutlineObjectHelper action dest"); |
60 | 182 | dest = A.getKey("/D"); |
61 | 182 | } |
62 | 2.39k | if (!dest.isInitialized()) { |
63 | 169 | dest = QPDFObjectHandle::newNull(); |
64 | 169 | } |
65 | | |
66 | 2.39k | if (dest.isName() || dest.isString()) { |
67 | 338 | QTC::TC("qpdf", "QPDFOutlineObjectHelper named dest"); |
68 | 338 | dest = m->dh.resolveNamedDest(dest); |
69 | 338 | } |
70 | | |
71 | 2.39k | return dest; |
72 | 2.39k | } |
73 | | |
74 | | QPDFObjectHandle |
75 | | QPDFOutlineObjectHelper::getDestPage() |
76 | 2.39k | { |
77 | 2.39k | QPDFObjectHandle dest = getDest(); |
78 | 2.39k | if ((dest.isArray()) && (dest.getArrayNItems() > 0)) { |
79 | 1.81k | return dest.getArrayItem(0); |
80 | 1.81k | } |
81 | 586 | return QPDFObjectHandle::newNull(); |
82 | 2.39k | } |
83 | | |
84 | | int |
85 | | QPDFOutlineObjectHelper::getCount() |
86 | 0 | { |
87 | 0 | int count = 0; |
88 | 0 | if (this->oh.hasKey("/Count")) { |
89 | 0 | count = this->oh.getKey("/Count").getIntValueAsInt(); |
90 | 0 | } |
91 | 0 | return count; |
92 | 0 | } |
93 | | |
94 | | std::string |
95 | | QPDFOutlineObjectHelper::getTitle() |
96 | 0 | { |
97 | 0 | std::string result; |
98 | 0 | if (this->oh.hasKey("/Title")) { |
99 | 0 | result = this->oh.getKey("/Title").getUTF8Value(); |
100 | 0 | } |
101 | 0 | return result; |
102 | 0 | } |