Commit 1fec40454ef72c6e2f079b599e9c807ce69a4bec
1 parent
ce19ec5c
Add example of name/number trees and dictionary/array iteration
Showing
10 changed files
with
502 additions
and
1 deletions
ChangeLog
examples/build.mk
examples/pdf-name-number-tree.cc
0 → 100644
| 1 | +#include <qpdf/QPDF.hh> | |
| 2 | +#include <qpdf/QPDFNameTreeObjectHelper.hh> | |
| 3 | +#include <qpdf/QPDFNumberTreeObjectHelper.hh> | |
| 4 | +#include <qpdf/QPDFWriter.hh> | |
| 5 | +#include <qpdf/QUtil.hh> | |
| 6 | +#include <iostream> | |
| 7 | +#include <cstring> | |
| 8 | + | |
| 9 | +static char const* whoami = 0; | |
| 10 | + | |
| 11 | +void usage() | |
| 12 | +{ | |
| 13 | + std::cerr << "Usage: " << whoami << " outfile.pdf" | |
| 14 | + << std::endl | |
| 15 | + << "Create some name/number trees and write to a file" | |
| 16 | + << std::endl; | |
| 17 | + exit(2); | |
| 18 | +} | |
| 19 | + | |
| 20 | +int main(int argc, char* argv[]) | |
| 21 | +{ | |
| 22 | + whoami = QUtil::getWhoami(argv[0]); | |
| 23 | + | |
| 24 | + // For libtool's sake.... | |
| 25 | + if (strncmp(whoami, "lt-", 3) == 0) | |
| 26 | + { | |
| 27 | + whoami += 3; | |
| 28 | + } | |
| 29 | + | |
| 30 | + if (argc != 2) | |
| 31 | + { | |
| 32 | + usage(); | |
| 33 | + } | |
| 34 | + | |
| 35 | + char const* outfilename = argv[1]; | |
| 36 | + | |
| 37 | + QPDF qpdf; | |
| 38 | + qpdf.emptyPDF(); | |
| 39 | + | |
| 40 | + // This example doesn't do anything particularly useful other than | |
| 41 | + // just illustrate how to use the APIs for name and number trees. | |
| 42 | + // It also demonstrates use of the iterators for dictionaries and | |
| 43 | + // arrays introduced at the same time with qpdf 10.2. | |
| 44 | + | |
| 45 | + // To use this example, compile it and run it. Study the output | |
| 46 | + // and compare it to what you expect. When done, look at the | |
| 47 | + // generated output file in a text editor to inspect the structure | |
| 48 | + // of the trees as left in the file. | |
| 49 | + | |
| 50 | + // We're just going to create some name and number trees, hang | |
| 51 | + // them off the document catalog (root), and write an empty PDF to | |
| 52 | + // a file. The PDF will have no pages and won't be viewable, but | |
| 53 | + // you can look at it in a text editor to see the resulting | |
| 54 | + // structure of the PDF. | |
| 55 | + | |
| 56 | + // Create a dictionary off the root where we will hang our name | |
| 57 | + // and number tree. | |
| 58 | + auto root = qpdf.getRoot(); | |
| 59 | + auto example = QPDFObjectHandle::newDictionary(); | |
| 60 | + root.replaceKey("/Example", example); | |
| 61 | + | |
| 62 | + // Create a name tree, attach it to the file, and add some items. | |
| 63 | + auto name_tree = QPDFNameTreeObjectHelper::newEmpty(qpdf); | |
| 64 | + auto name_tree_oh = name_tree.getObjectHandle(); | |
| 65 | + example.replaceKey("/NameTree", name_tree_oh); | |
| 66 | + name_tree.insert("K", QPDFObjectHandle::newUnicodeString("king")); | |
| 67 | + name_tree.insert("Q", QPDFObjectHandle::newUnicodeString("queen")); | |
| 68 | + name_tree.insert("R", QPDFObjectHandle::newUnicodeString("rook")); | |
| 69 | + name_tree.insert("B", QPDFObjectHandle::newUnicodeString("bishop")); | |
| 70 | + name_tree.insert("N", QPDFObjectHandle::newUnicodeString("knight")); | |
| 71 | + auto iter = name_tree.insert( | |
| 72 | + "P", QPDFObjectHandle::newUnicodeString("pawn")); | |
| 73 | + // Look at the iterator | |
| 74 | + std::cout << "just inserted " << iter->first << " -> " | |
| 75 | + << iter->second.unparse() << std::endl; | |
| 76 | + --iter; | |
| 77 | + std::cout << "predecessor: " << iter->first << " -> " | |
| 78 | + << iter->second.unparse() << std::endl; | |
| 79 | + ++iter; | |
| 80 | + ++iter; | |
| 81 | + std::cout << "successor: " << iter->first << " -> " | |
| 82 | + << iter->second.unparse() << std::endl; | |
| 83 | + | |
| 84 | + // Use range-for iteration | |
| 85 | + std::cout << "Name tree items:" << std::endl; | |
| 86 | + for (auto i: name_tree) | |
| 87 | + { | |
| 88 | + std::cout << " " << i.first << " -> " | |
| 89 | + << i.second.unparse() << std::endl; | |
| 90 | + } | |
| 91 | + | |
| 92 | + // This is a small tree, so everything will be at the root. We can | |
| 93 | + // look at it using dictionary and array iterators. | |
| 94 | + std::cout << "Keys in name tree object:" << std::endl; | |
| 95 | + QPDFObjectHandle names; | |
| 96 | + for (auto const& i: QPDFDictItems(name_tree_oh)) | |
| 97 | + { | |
| 98 | + std::cout << i.first << std::endl; | |
| 99 | + if (i.first == "/Names") | |
| 100 | + { | |
| 101 | + names = i.second; | |
| 102 | + } | |
| 103 | + } | |
| 104 | + // Values in names array: | |
| 105 | + std::cout << "Values in names:" << std::endl; | |
| 106 | + for (auto& i: QPDFArrayItems(names)) | |
| 107 | + { | |
| 108 | + std::cout << " " << i.unparse() << std::endl; | |
| 109 | + } | |
| 110 | + | |
| 111 | + // pre 10.2 API | |
| 112 | + std::cout << "Has Q?: " << name_tree.hasName("Q") << std::endl; | |
| 113 | + std::cout << "Has W?: " << name_tree.hasName("W") << std::endl; | |
| 114 | + QPDFObjectHandle obj; | |
| 115 | + std::cout << "Found W?: " << name_tree.findObject("W", obj) << std::endl; | |
| 116 | + std::cout << "Found Q?: " << name_tree.findObject("Q", obj) << std::endl; | |
| 117 | + std::cout << "Q: " << obj.unparse() << std::endl; | |
| 118 | + | |
| 119 | + // 10.2 API | |
| 120 | + iter = name_tree.find("Q"); | |
| 121 | + std::cout << "Q: " << iter->first << " -> " | |
| 122 | + << iter->second.unparse() << std::endl; | |
| 123 | + iter = name_tree.find("W"); | |
| 124 | + std::cout << "W found: " << (iter != name_tree.end()) << std::endl; | |
| 125 | + // Allow find to return predecessor | |
| 126 | + iter = name_tree.find("W", true); | |
| 127 | + std::cout << "W's predecessor: " << iter->first << " -> " | |
| 128 | + << iter->second.unparse() << std::endl; | |
| 129 | + | |
| 130 | + // We can also remove items | |
| 131 | + std::cout << "Remove P: " << name_tree.remove("P", &obj) << std::endl; | |
| 132 | + std::cout << "Value removed: " << obj.unparse() << std::endl; | |
| 133 | + std::cout << "Has P?: " << name_tree.hasName("P") << std::endl; | |
| 134 | + // Or we can remove using an iterator | |
| 135 | + iter = name_tree.find("K"); | |
| 136 | + std::cout << "Find K: " << iter->second.unparse() << std::endl; | |
| 137 | + iter.remove(); | |
| 138 | + std::cout << "Iter after removing K: " << iter->first << " -> " | |
| 139 | + << iter->second.unparse() << std::endl; | |
| 140 | + std::cout << "Has K?: " << name_tree.hasName("K") << std::endl; | |
| 141 | + | |
| 142 | + // Illustrate some more advanced usage using number trees. These | |
| 143 | + // calls work for name trees too. | |
| 144 | + | |
| 145 | + // The safe way to populate a tree is to call insert repeatedly as | |
| 146 | + // above, but if you know you are definitely inserting items in | |
| 147 | + // order, it is more efficient to insert them using insertAfter, | |
| 148 | + // which avoids doing a binary search through the tree for each | |
| 149 | + // insertion. Note that if you don't insert items in order using | |
| 150 | + // this method, you will create an invalid tree. | |
| 151 | + auto number_tree = QPDFNumberTreeObjectHelper::newEmpty(qpdf); | |
| 152 | + auto number_tree_oh = number_tree.getObjectHandle(); | |
| 153 | + example.replaceKey("/NumberTree", number_tree_oh); | |
| 154 | + auto iter2 = number_tree.begin(); | |
| 155 | + for (int i = 7; i <= 350; i += 7) | |
| 156 | + { | |
| 157 | + iter2.insertAfter(i, QPDFObjectHandle::newString( | |
| 158 | + "-" + QUtil::int_to_string(i) + "-")); | |
| 159 | + } | |
| 160 | + std::cout << "Numbers:" << std::endl; | |
| 161 | + int n = 1; | |
| 162 | + for (auto& i: number_tree) | |
| 163 | + { | |
| 164 | + std::cout << i.first << " -> " << i.second.getUTF8Value(); | |
| 165 | + if (n % 5) | |
| 166 | + { | |
| 167 | + std::cout << ", "; | |
| 168 | + } | |
| 169 | + else | |
| 170 | + { | |
| 171 | + std::cout << std::endl; | |
| 172 | + } | |
| 173 | + ++n; | |
| 174 | + } | |
| 175 | + | |
| 176 | + // When you remove an item with an iterator, the iterator | |
| 177 | + // advances. This makes it possible to filter while iterating. | |
| 178 | + // Remove all items that are multiples of 5. | |
| 179 | + iter2 = number_tree.begin(); | |
| 180 | + while (iter2 != number_tree.end()) | |
| 181 | + { | |
| 182 | + if (iter2->first % 5 == 0) | |
| 183 | + { | |
| 184 | + iter2.remove(); // also advances | |
| 185 | + } | |
| 186 | + else | |
| 187 | + { | |
| 188 | + ++iter2; | |
| 189 | + } | |
| 190 | + } | |
| 191 | + std::cout << "Numbers after filtering:" << std::endl; | |
| 192 | + n = 1; | |
| 193 | + for (auto& i: number_tree) | |
| 194 | + { | |
| 195 | + std::cout << i.first << " -> " << i.second.getUTF8Value(); | |
| 196 | + if (n % 5) | |
| 197 | + { | |
| 198 | + std::cout << ", "; | |
| 199 | + } | |
| 200 | + else | |
| 201 | + { | |
| 202 | + std::cout << std::endl; | |
| 203 | + } | |
| 204 | + ++n; | |
| 205 | + } | |
| 206 | + | |
| 207 | + // Write to an output file | |
| 208 | + QPDFWriter w(qpdf, outfilename); | |
| 209 | + w.setQDFMode(true); | |
| 210 | + w.setStaticID(true); // for testing only | |
| 211 | + w.write(); | |
| 212 | + | |
| 213 | + return 0; | |
| 214 | +} | ... | ... |
examples/qtest/name-number-tree.test
0 → 100644
| 1 | +#!/usr/bin/env perl | |
| 2 | +require 5.008; | |
| 3 | +BEGIN { $^W = 1; } | |
| 4 | +use strict; | |
| 5 | + | |
| 6 | +chdir("name-number-tree") or die "chdir testdir failed: $!\n"; | |
| 7 | + | |
| 8 | +require TestDriver; | |
| 9 | + | |
| 10 | +my $td = new TestDriver('name-number-tree'); | |
| 11 | + | |
| 12 | +cleanup(); | |
| 13 | + | |
| 14 | +$td->runtest("name/number tree", | |
| 15 | + {$td->COMMAND => 'pdf-name-number-tree a.pdf'}, | |
| 16 | + {$td->FILE => 'nn.out', $td->EXIT_STATUS => 0}, | |
| 17 | + $td->NORMALIZE_NEWLINES); | |
| 18 | + | |
| 19 | +$td->runtest("check output", | |
| 20 | + {$td->FILE => "a.pdf"}, | |
| 21 | + {$td->FILE => "out.pdf"}); | |
| 22 | + | |
| 23 | +cleanup(); | |
| 24 | + | |
| 25 | +$td->report(2); | |
| 26 | + | |
| 27 | +sub cleanup | |
| 28 | +{ | |
| 29 | + unlink 'a.pdf'; | |
| 30 | +} | ... | ... |
examples/qtest/name-number-tree/nn.out
0 → 100644
| 1 | +just inserted P -> (pawn) | |
| 2 | +predecessor: N -> (knight) | |
| 3 | +successor: Q -> (queen) | |
| 4 | +Name tree items: | |
| 5 | + B -> (bishop) | |
| 6 | + K -> (king) | |
| 7 | + N -> (knight) | |
| 8 | + P -> (pawn) | |
| 9 | + Q -> (queen) | |
| 10 | + R -> (rook) | |
| 11 | +Keys in name tree object: | |
| 12 | +/Names | |
| 13 | +Values in names: | |
| 14 | + (B) | |
| 15 | + (bishop) | |
| 16 | + (K) | |
| 17 | + (king) | |
| 18 | + (N) | |
| 19 | + (knight) | |
| 20 | + (P) | |
| 21 | + (pawn) | |
| 22 | + (Q) | |
| 23 | + (queen) | |
| 24 | + (R) | |
| 25 | + (rook) | |
| 26 | +Has Q?: 1 | |
| 27 | +Has W?: 0 | |
| 28 | +Found W?: 0 | |
| 29 | +Found Q?: 1 | |
| 30 | +Q: (queen) | |
| 31 | +Q: Q -> (queen) | |
| 32 | +W found: 0 | |
| 33 | +W's predecessor: R -> (rook) | |
| 34 | +Remove P: 1 | |
| 35 | +Value removed: (pawn) | |
| 36 | +Has P?: 0 | |
| 37 | +Find K: (king) | |
| 38 | +Iter after removing K: N -> (knight) | |
| 39 | +Has K?: 0 | |
| 40 | +Numbers: | |
| 41 | +7 -> -7-, 14 -> -14-, 21 -> -21-, 28 -> -28-, 35 -> -35- | |
| 42 | +42 -> -42-, 49 -> -49-, 56 -> -56-, 63 -> -63-, 70 -> -70- | |
| 43 | +77 -> -77-, 84 -> -84-, 91 -> -91-, 98 -> -98-, 105 -> -105- | |
| 44 | +112 -> -112-, 119 -> -119-, 126 -> -126-, 133 -> -133-, 140 -> -140- | |
| 45 | +147 -> -147-, 154 -> -154-, 161 -> -161-, 168 -> -168-, 175 -> -175- | |
| 46 | +182 -> -182-, 189 -> -189-, 196 -> -196-, 203 -> -203-, 210 -> -210- | |
| 47 | +217 -> -217-, 224 -> -224-, 231 -> -231-, 238 -> -238-, 245 -> -245- | |
| 48 | +252 -> -252-, 259 -> -259-, 266 -> -266-, 273 -> -273-, 280 -> -280- | |
| 49 | +287 -> -287-, 294 -> -294-, 301 -> -301-, 308 -> -308-, 315 -> -315- | |
| 50 | +322 -> -322-, 329 -> -329-, 336 -> -336-, 343 -> -343-, 350 -> -350- | |
| 51 | +Numbers after filtering: | |
| 52 | +7 -> -7-, 14 -> -14-, 21 -> -21-, 28 -> -28-, 42 -> -42- | |
| 53 | +49 -> -49-, 56 -> -56-, 63 -> -63-, 77 -> -77-, 84 -> -84- | |
| 54 | +91 -> -91-, 98 -> -98-, 112 -> -112-, 119 -> -119-, 126 -> -126- | |
| 55 | +133 -> -133-, 147 -> -147-, 154 -> -154-, 161 -> -161-, 168 -> -168- | |
| 56 | +182 -> -182-, 189 -> -189-, 196 -> -196-, 203 -> -203-, 217 -> -217- | |
| 57 | +224 -> -224-, 231 -> -231-, 238 -> -238-, 252 -> -252-, 259 -> -259- | |
| 58 | +266 -> -266-, 273 -> -273-, 287 -> -287-, 294 -> -294-, 301 -> -301- | |
| 59 | +308 -> -308-, 322 -> -322-, 329 -> -329-, 336 -> -336-, 343 -> -343- | ... | ... |
examples/qtest/name-number-tree/out.pdf
0 → 100644
| 1 | +%PDF-1.3 | |
| 2 | +%¿÷¢þ | |
| 3 | +%QDF-1.0 | |
| 4 | + | |
| 5 | +%% Original object ID: 1 0 | |
| 6 | +1 0 obj | |
| 7 | +<< | |
| 8 | + /Example << | |
| 9 | + /NameTree << | |
| 10 | + /Names [ | |
| 11 | + (B) | |
| 12 | + (bishop) | |
| 13 | + (N) | |
| 14 | + (knight) | |
| 15 | + (Q) | |
| 16 | + (queen) | |
| 17 | + (R) | |
| 18 | + (rook) | |
| 19 | + ] | |
| 20 | + >> | |
| 21 | + /NumberTree << | |
| 22 | + /Kids [ | |
| 23 | + 2 0 R | |
| 24 | + 3 0 R | |
| 25 | + 4 0 R | |
| 26 | + ] | |
| 27 | + /Limits [ | |
| 28 | + 7 | |
| 29 | + 343 | |
| 30 | + ] | |
| 31 | + >> | |
| 32 | + >> | |
| 33 | + /Pages 5 0 R | |
| 34 | + /Type /Catalog | |
| 35 | +>> | |
| 36 | +endobj | |
| 37 | + | |
| 38 | +%% Original object ID: 3 0 | |
| 39 | +2 0 obj | |
| 40 | +<< | |
| 41 | + /Limits [ | |
| 42 | + 7 | |
| 43 | + 112 | |
| 44 | + ] | |
| 45 | + /Nums [ | |
| 46 | + 7 | |
| 47 | + (-7-) | |
| 48 | + 14 | |
| 49 | + (-14-) | |
| 50 | + 21 | |
| 51 | + (-21-) | |
| 52 | + 28 | |
| 53 | + (-28-) | |
| 54 | + 42 | |
| 55 | + (-42-) | |
| 56 | + 49 | |
| 57 | + (-49-) | |
| 58 | + 56 | |
| 59 | + (-56-) | |
| 60 | + 63 | |
| 61 | + (-63-) | |
| 62 | + 77 | |
| 63 | + (-77-) | |
| 64 | + 84 | |
| 65 | + (-84-) | |
| 66 | + 91 | |
| 67 | + (-91-) | |
| 68 | + 98 | |
| 69 | + (-98-) | |
| 70 | + 112 | |
| 71 | + (-112-) | |
| 72 | + ] | |
| 73 | +>> | |
| 74 | +endobj | |
| 75 | + | |
| 76 | +%% Original object ID: 4 0 | |
| 77 | +3 0 obj | |
| 78 | +<< | |
| 79 | + /Limits [ | |
| 80 | + 119 | |
| 81 | + 224 | |
| 82 | + ] | |
| 83 | + /Nums [ | |
| 84 | + 119 | |
| 85 | + (-119-) | |
| 86 | + 126 | |
| 87 | + (-126-) | |
| 88 | + 133 | |
| 89 | + (-133-) | |
| 90 | + 147 | |
| 91 | + (-147-) | |
| 92 | + 154 | |
| 93 | + (-154-) | |
| 94 | + 161 | |
| 95 | + (-161-) | |
| 96 | + 168 | |
| 97 | + (-168-) | |
| 98 | + 182 | |
| 99 | + (-182-) | |
| 100 | + 189 | |
| 101 | + (-189-) | |
| 102 | + 196 | |
| 103 | + (-196-) | |
| 104 | + 203 | |
| 105 | + (-203-) | |
| 106 | + 217 | |
| 107 | + (-217-) | |
| 108 | + 224 | |
| 109 | + (-224-) | |
| 110 | + ] | |
| 111 | +>> | |
| 112 | +endobj | |
| 113 | + | |
| 114 | +%% Original object ID: 5 0 | |
| 115 | +4 0 obj | |
| 116 | +<< | |
| 117 | + /Limits [ | |
| 118 | + 231 | |
| 119 | + 343 | |
| 120 | + ] | |
| 121 | + /Nums [ | |
| 122 | + 231 | |
| 123 | + (-231-) | |
| 124 | + 238 | |
| 125 | + (-238-) | |
| 126 | + 252 | |
| 127 | + (-252-) | |
| 128 | + 259 | |
| 129 | + (-259-) | |
| 130 | + 266 | |
| 131 | + (-266-) | |
| 132 | + 273 | |
| 133 | + (-273-) | |
| 134 | + 287 | |
| 135 | + (-287-) | |
| 136 | + 294 | |
| 137 | + (-294-) | |
| 138 | + 301 | |
| 139 | + (-301-) | |
| 140 | + 308 | |
| 141 | + (-308-) | |
| 142 | + 322 | |
| 143 | + (-322-) | |
| 144 | + 329 | |
| 145 | + (-329-) | |
| 146 | + 336 | |
| 147 | + (-336-) | |
| 148 | + 343 | |
| 149 | + (-343-) | |
| 150 | + ] | |
| 151 | +>> | |
| 152 | +endobj | |
| 153 | + | |
| 154 | +%% Original object ID: 2 0 | |
| 155 | +5 0 obj | |
| 156 | +<< | |
| 157 | + /Count 0 | |
| 158 | + /Kids [ | |
| 159 | + ] | |
| 160 | + /Type /Pages | |
| 161 | +>> | |
| 162 | +endobj | |
| 163 | + | |
| 164 | +xref | |
| 165 | +0 6 | |
| 166 | +0000000000 65535 f | |
| 167 | +0000000052 00000 n | |
| 168 | +0000000448 00000 n | |
| 169 | +0000000775 00000 n | |
| 170 | +0000001130 00000 n | |
| 171 | +0000001505 00000 n | |
| 172 | +trailer << | |
| 173 | + /Root 1 0 R | |
| 174 | + /Size 6 | |
| 175 | + /ID [<31415926535897932384626433832795><31415926535897932384626433832795>] | |
| 176 | +>> | |
| 177 | +startxref | |
| 178 | +1567 | |
| 179 | +%%EOF | ... | ... |
include/qpdf/QPDFNameTreeObjectHelper.hh
| ... | ... | @@ -35,6 +35,9 @@ |
| 35 | 35 | // up items in the name tree, use UTF-8 strings. All names are |
| 36 | 36 | // normalized for lookup purposes. |
| 37 | 37 | |
| 38 | +// See examples/pdf-name-number-tree.cc for a demonstration of using | |
| 39 | +// QPDFNameTreeObjectHelper. | |
| 40 | + | |
| 38 | 41 | class NNTreeImpl; |
| 39 | 42 | class NNTreeIterator; |
| 40 | 43 | class NNTreeDetails; | ... | ... |
include/qpdf/QPDFNumberTreeObjectHelper.hh
| ... | ... | @@ -32,6 +32,9 @@ |
| 32 | 32 | // This is an object helper for number trees. See section 7.9.7 in the |
| 33 | 33 | // PDF spec (ISO 32000) for a description of number trees. |
| 34 | 34 | |
| 35 | +// See examples/pdf-name-number-tree.cc for a demonstration of using | |
| 36 | +// QPDFNumberTreeObjectHelper. | |
| 37 | + | |
| 35 | 38 | class NNTreeImpl; |
| 36 | 39 | class NNTreeIterator; |
| 37 | 40 | class NNTreeDetails; | ... | ... |
include/qpdf/QPDFObjectHandle.hh
| ... | ... | @@ -1237,6 +1237,9 @@ class QPDFDictItems |
| 1237 | 1237 | // // iter.second is a QPDFObjectHandle |
| 1238 | 1238 | // } |
| 1239 | 1239 | |
| 1240 | + // See examples/pdf-name-number-tree.cc for a demonstration of | |
| 1241 | + // using this API. | |
| 1242 | + | |
| 1240 | 1243 | public: |
| 1241 | 1244 | QPDF_DLL |
| 1242 | 1245 | QPDFDictItems(QPDFObjectHandle& oh); |
| ... | ... | @@ -1324,6 +1327,9 @@ class QPDFArrayItems |
| 1324 | 1327 | // // iter is a QPDFObjectHandle |
| 1325 | 1328 | // } |
| 1326 | 1329 | |
| 1330 | + // See examples/pdf-name-number-tree.cc for a demonstration of | |
| 1331 | + // using this API. | |
| 1332 | + | |
| 1327 | 1333 | public: |
| 1328 | 1334 | QPDF_DLL |
| 1329 | 1335 | QPDFArrayItems(QPDFObjectHandle& oh); | ... | ... |
manual/qpdf-manual.xml
| ... | ... | @@ -4854,7 +4854,8 @@ print "\n"; |
| 4854 | 4854 | <classname>QPDFObjectHandle</classname>, allowing C++-style |
| 4855 | 4855 | iteration, including range-for iteration, over dictionary |
| 4856 | 4856 | and array QPDFObjectHandles. See comments in |
| 4857 | - <filename>include/qpdf/QPDFObjectHandle.hh</filename> for | |
| 4857 | + <filename>include/qpdf/QPDFObjectHandle.hh</filename> and | |
| 4858 | + <filename>examples/pdf-name-number-tree.cc</filename> for | |
| 4858 | 4859 | details. |
| 4859 | 4860 | </para> |
| 4860 | 4861 | </listitem> | ... | ... |