Commit 4fbffdf8ed3992bd1bdd0d742d101202fd462835
1 parent
d5d179f4
Rewrite bookmark example to use outline helpers
Now uses QPDFOutlineDocumentHelper and QPDFOutlineObjectHelper.
Showing
1 changed file
with
89 additions
and
100 deletions
examples/pdf-bookmarks.cc
| ... | ... | @@ -3,6 +3,7 @@ |
| 3 | 3 | #include <stdlib.h> |
| 4 | 4 | #include <qpdf/QPDF.hh> |
| 5 | 5 | #include <qpdf/QPDFPageDocumentHelper.hh> |
| 6 | +#include <qpdf/QPDFOutlineDocumentHelper.hh> | |
| 6 | 7 | #include <qpdf/QUtil.hh> |
| 7 | 8 | #include <qpdf/QTC.hh> |
| 8 | 9 | |
| ... | ... | @@ -56,111 +57,99 @@ void generate_page_map(QPDF& qpdf) |
| 56 | 57 | } |
| 57 | 58 | } |
| 58 | 59 | |
| 59 | -void extract_bookmarks(QPDFObjectHandle outlines, std::vector<int>& numbers) | |
| 60 | +void show_bookmark_details(QPDFOutlineObjectHelper outline, | |
| 61 | + std::vector<int> numbers) | |
| 60 | 62 | { |
| 61 | - if (outlines.hasKey("/Title")) | |
| 63 | + // No default so gcc will warn on missing tag | |
| 64 | + switch (style) | |
| 62 | 65 | { |
| 63 | - // No default so gcc will warn on missing tag | |
| 64 | - switch (style) | |
| 65 | - { | |
| 66 | - case st_none: | |
| 67 | - QTC::TC("examples", "pdf-bookmarks none"); | |
| 68 | - break; | |
| 69 | - | |
| 70 | - case st_numbers: | |
| 71 | - QTC::TC("examples", "pdf-bookmarks numbers"); | |
| 72 | - for (std::vector<int>::iterator iter = numbers.begin(); | |
| 73 | - iter != numbers.end(); ++iter) | |
| 74 | - { | |
| 75 | - std::cout << *iter << "."; | |
| 76 | - } | |
| 77 | - std::cout << " "; | |
| 78 | - break; | |
| 79 | - | |
| 80 | - case st_lines: | |
| 81 | - QTC::TC("examples", "pdf-bookmarks lines"); | |
| 82 | - print_lines(numbers); | |
| 83 | - std::cout << "|" << std::endl; | |
| 84 | - print_lines(numbers); | |
| 85 | - std::cout << "+-+ "; | |
| 86 | - break; | |
| 87 | - } | |
| 88 | - | |
| 89 | - if (show_open) | |
| 90 | - { | |
| 91 | - if (outlines.hasKey("/Count")) | |
| 92 | - { | |
| 93 | - QTC::TC("examples", "pdf-bookmarks has count"); | |
| 94 | - int count = outlines.getKey("/Count").getIntValue(); | |
| 95 | - if (count > 0) | |
| 96 | - { | |
| 97 | - // hierarchy is open at this point | |
| 98 | - QTC::TC("examples", "pdf-bookmarks open"); | |
| 99 | - std::cout << "(v) "; | |
| 100 | - } | |
| 101 | - else | |
| 102 | - { | |
| 103 | - QTC::TC("examples", "pdf-bookmarks closed"); | |
| 104 | - std::cout << "(>) "; | |
| 105 | - } | |
| 106 | - } | |
| 107 | - else | |
| 108 | - { | |
| 109 | - QTC::TC("examples", "pdf-bookmarks no count"); | |
| 110 | - std::cout << "( ) "; | |
| 111 | - } | |
| 112 | - } | |
| 113 | - | |
| 114 | - if (show_targets) | |
| 115 | - { | |
| 116 | - QTC::TC("examples", "pdf-bookmarks targets"); | |
| 117 | - std::string target = "unknown"; | |
| 118 | - // Only explicit destinations supported for now | |
| 119 | - if (outlines.hasKey("/Dest")) | |
| 120 | - { | |
| 121 | - QTC::TC("examples", "pdf-bookmarks dest"); | |
| 122 | - QPDFObjectHandle dest = outlines.getKey("/Dest"); | |
| 123 | - if ((dest.isArray()) && (dest.getArrayNItems() > 0)) | |
| 124 | - { | |
| 125 | - QPDFObjectHandle first = dest.getArrayItem(0); | |
| 126 | - QPDFObjGen og = first.getObjGen(); | |
| 127 | - if (page_map.count(og)) | |
| 128 | - { | |
| 129 | - target = QUtil::int_to_string(page_map[og]); | |
| 130 | - } | |
| 131 | - } | |
| 66 | + case st_none: | |
| 67 | + QTC::TC("examples", "pdf-bookmarks none"); | |
| 68 | + break; | |
| 69 | + | |
| 70 | + case st_numbers: | |
| 71 | + QTC::TC("examples", "pdf-bookmarks numbers"); | |
| 72 | + for (std::vector<int>::iterator iter = numbers.begin(); | |
| 73 | + iter != numbers.end(); ++iter) | |
| 74 | + { | |
| 75 | + std::cout << *iter << "."; | |
| 76 | + } | |
| 77 | + std::cout << " "; | |
| 78 | + break; | |
| 79 | + | |
| 80 | + case st_lines: | |
| 81 | + QTC::TC("examples", "pdf-bookmarks lines"); | |
| 82 | + print_lines(numbers); | |
| 83 | + std::cout << "|" << std::endl; | |
| 84 | + print_lines(numbers); | |
| 85 | + std::cout << "+-+ "; | |
| 86 | + break; | |
| 87 | + } | |
| 132 | 88 | |
| 133 | - std::cout << "[ -> " << target << " ] "; | |
| 134 | - } | |
| 135 | - } | |
| 89 | + if (show_open) | |
| 90 | + { | |
| 91 | + int count = outline.getCount(); | |
| 92 | + if (count) | |
| 93 | + { | |
| 94 | + QTC::TC("examples", "pdf-bookmarks has count"); | |
| 95 | + if (count > 0) | |
| 96 | + { | |
| 97 | + // hierarchy is open at this point | |
| 98 | + QTC::TC("examples", "pdf-bookmarks open"); | |
| 99 | + std::cout << "(v) "; | |
| 100 | + } | |
| 101 | + else | |
| 102 | + { | |
| 103 | + QTC::TC("examples", "pdf-bookmarks closed"); | |
| 104 | + std::cout << "(>) "; | |
| 105 | + } | |
| 106 | + } | |
| 107 | + else | |
| 108 | + { | |
| 109 | + QTC::TC("examples", "pdf-bookmarks no count"); | |
| 110 | + std::cout << "( ) "; | |
| 111 | + } | |
| 112 | + } | |
| 136 | 113 | |
| 137 | - std::cout << outlines.getKey("/Title").getUTF8Value() << std::endl; | |
| 114 | + if (show_targets) | |
| 115 | + { | |
| 116 | + QTC::TC("examples", "pdf-bookmarks targets"); | |
| 117 | + std::string target = "unknown"; | |
| 118 | + QPDFObjectHandle dest_page = outline.getDestPage(); | |
| 119 | + if (! dest_page.isNull()) | |
| 120 | + { | |
| 121 | + QTC::TC("examples", "pdf-bookmarks dest"); | |
| 122 | + QPDFObjGen og = dest_page.getObjGen(); | |
| 123 | + if (page_map.count(og)) | |
| 124 | + { | |
| 125 | + target = QUtil::int_to_string(page_map[og]); | |
| 126 | + } | |
| 127 | + } | |
| 128 | + std::cout << "[ -> " << target << " ] "; | |
| 138 | 129 | } |
| 139 | 130 | |
| 140 | - if (outlines.hasKey("/First")) | |
| 131 | + std::cout << outline.getTitle() << std::endl; | |
| 132 | +} | |
| 133 | + | |
| 134 | +void extract_bookmarks(std::list<QPDFOutlineObjectHelper> outlines, | |
| 135 | + std::vector<int>& numbers) | |
| 136 | +{ | |
| 137 | + numbers.push_back(0); | |
| 138 | + for (std::list<QPDFOutlineObjectHelper>::iterator iter = outlines.begin(); | |
| 139 | + iter != outlines.end(); ++iter) | |
| 141 | 140 | { |
| 142 | - numbers.push_back(0); | |
| 143 | - QPDFObjectHandle child = outlines.getKey("/First"); | |
| 144 | - while (1) | |
| 145 | - { | |
| 146 | - ++(numbers.back()); | |
| 147 | - bool has_next = child.hasKey("/Next"); | |
| 148 | - if ((style == st_lines) && (! has_next)) | |
| 149 | - { | |
| 150 | - numbers.back() = 0; | |
| 151 | - } | |
| 152 | - extract_bookmarks(child, numbers); | |
| 153 | - if (has_next) | |
| 154 | - { | |
| 155 | - child = child.getKey("/Next"); | |
| 156 | - } | |
| 157 | - else | |
| 158 | - { | |
| 159 | - break; | |
| 160 | - } | |
| 161 | - } | |
| 162 | - numbers.pop_back(); | |
| 141 | + ++(numbers.back()); | |
| 142 | + show_bookmark_details(*iter, numbers); | |
| 143 | + std::list<QPDFOutlineObjectHelper>::iterator next = iter; | |
| 144 | + ++next; | |
| 145 | + bool has_next = (next != outlines.end()); | |
| 146 | + if ((style == st_lines) && (! has_next)) | |
| 147 | + { | |
| 148 | + numbers.back() = 0; | |
| 149 | + } | |
| 150 | + extract_bookmarks((*iter).getKids(), numbers); | |
| 163 | 151 | } |
| 152 | + numbers.pop_back(); | |
| 164 | 153 | } |
| 165 | 154 | |
| 166 | 155 | int main(int argc, char* argv[]) |
| ... | ... | @@ -233,15 +222,15 @@ int main(int argc, char* argv[]) |
| 233 | 222 | QPDF qpdf; |
| 234 | 223 | qpdf.processFile(filename, password); |
| 235 | 224 | |
| 236 | - QPDFObjectHandle root = qpdf.getRoot(); | |
| 237 | - if (root.hasKey("/Outlines")) | |
| 225 | + QPDFOutlineDocumentHelper odh(qpdf); | |
| 226 | + if (odh.hasOutlines()) | |
| 238 | 227 | { |
| 239 | 228 | std::vector<int> numbers; |
| 240 | 229 | if (show_targets) |
| 241 | 230 | { |
| 242 | 231 | generate_page_map(qpdf); |
| 243 | 232 | } |
| 244 | - extract_bookmarks(root.getKey("/Outlines"), numbers); | |
| 233 | + extract_bookmarks(odh.getTopLevelOutlines(), numbers); | |
| 245 | 234 | } |
| 246 | 235 | else |
| 247 | 236 | { | ... | ... |