From 6ef9e31233723f2e73a4ed9bc3cd1fcaa6c69b5d Mon Sep 17 00:00:00 2001 From: Jay Berkenbilt Date: Tue, 18 Dec 2018 11:29:00 -0500 Subject: [PATCH] Add QPDFPageLabelDocumentHelper --- ChangeLog | 7 + include/qpdf/QPDFPageLabelDocumentHelper.hh | 100 ++ libqpdf/QPDFPageLabelDocumentHelper.cc | 125 ++ libqpdf/build.mk | 1 + qpdf/qtest/qpdf.test | 18 + qpdf/qtest/qpdf/no-page-labels.out | 2 + qpdf/qtest/qpdf/page-labels-no-zero.out | 15 + qpdf/qtest/qpdf/page-labels-no-zero.pdf | 1364 ++++++++++++++++++ qpdf/qtest/qpdf/page-labels-num-tree.out | 15 + qpdf/qtest/qpdf/page-labels-num-tree.pdf | 1417 +++++++++++++++++++ qpdf/test_driver.cc | 16 + 11 files changed, 3080 insertions(+) create mode 100644 include/qpdf/QPDFPageLabelDocumentHelper.hh create mode 100644 libqpdf/QPDFPageLabelDocumentHelper.cc create mode 100644 qpdf/qtest/qpdf/no-page-labels.out create mode 100644 qpdf/qtest/qpdf/page-labels-no-zero.out create mode 100644 qpdf/qtest/qpdf/page-labels-no-zero.pdf create mode 100644 qpdf/qtest/qpdf/page-labels-num-tree.out create mode 100644 qpdf/qtest/qpdf/page-labels-num-tree.pdf diff --git a/ChangeLog b/ChangeLog index 27f790f2..75fad549 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,12 @@ 2018-12-18 Jay Berkenbilt + * Add QPDFPageLabelDocumentHelper class. This is a document helper + class that provides useful methods for dealing with page labels. + It abstracts the fact that they are stored as number trees and + deals with interpolating intermediate values that are not in the + tree. It also has helper functions used by the qpdf command line + tool to preserve page labels when merging and splitting files. + * Add QPDFNumberTreeObjectHelper class. This class provides useful methods for dealing with number trees, which are discussed in section 7.9.7 of the PDF spec (ISO-32000). Page label dictionaries diff --git a/include/qpdf/QPDFPageLabelDocumentHelper.hh b/include/qpdf/QPDFPageLabelDocumentHelper.hh new file mode 100644 index 00000000..a5a13ff2 --- /dev/null +++ b/include/qpdf/QPDFPageLabelDocumentHelper.hh @@ -0,0 +1,100 @@ +// Copyright (c) 2005-2018 Jay Berkenbilt +// +// This file is part of qpdf. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Versions of qpdf prior to version 7 were released under the terms +// of version 2.0 of the Artistic License. At your option, you may +// continue to consider qpdf to be licensed under those terms. Please +// see the manual for additional information. + +#ifndef QPDFPAGELABELDOCUMENTHELPER_HH +#define QPDFPAGELABELDOCUMENTHELPER_HH + +#include + +#include +#include +#include + +#include + +// Page labels are discussed in the PDF spec (ISO-32000) in section +// 12.4.2. +// +// Page labels are implemented as a number tree. Each key is a page +// index, numbered from 0. The values are dictionaries with the +// following keys, all optional: +// +// * /Type: if present, must be /PageLabel +// * /S: one of /D, /R, /r, /A, or /a for decimal, upper-case and +// lower-case Roman numeral, or upper-case and lower-case alphabetic +// * /P: if present, a fixed prefix string that is prepended to each +// page number +// * /St: the starting number, or 1 if not specified + +class QPDFPageLabelDocumentHelper: public QPDFDocumentHelper +{ + public: + QPDF_DLL + QPDFPageLabelDocumentHelper(QPDF&); + + QPDF_DLL + bool hasPageLabels(); + + // Return a page label dictionary representing the page label for + // the given page. The page does not need to appear explicitly in + // the page label dictionary. This method will adjust /St as + // needed to produce a label that is suitable for the page. + QPDF_DLL + QPDFObjectHandle getLabelForPage(long long page_idx); + + // Append to the incoming vector a list of objects suitable for + // inclusion in a /PageLabels dictionary's /Nums field. start_idx + // and end_idx are the indexes to the starting and ending pages + // (inclusive) in the original file, and new_start_idx is the + // index to the first page in the new file. For example, if pages + // 10 through 12 of one file are being copied to a new file as + // pages 6 through 8, you would call getLabelsForPageRange(10, 12, + // 6), which would return as many entries as are required to add + // to the new file's PageLabels. This method fabricates a suitable + // entry even if the original document has no page labels. This + // behavior facilitates using this function to incrementally build + // up a page labels tree when merging files. + QPDF_DLL + void + getLabelsForPageRange(long long start_idx, long long end_idx, + long long new_start_idx, + std::vector& new_labels); + + private: + class Members + { + friend class QPDFPageLabelDocumentHelper; + + public: + QPDF_DLL + ~Members(); + + private: + Members(); + Members(Members const&); + + PointerHolder labels; + }; + + PointerHolder m; +}; + +#endif // QPDFPAGELABELDOCUMENTHELPER_HH diff --git a/libqpdf/QPDFPageLabelDocumentHelper.cc b/libqpdf/QPDFPageLabelDocumentHelper.cc new file mode 100644 index 00000000..63be5809 --- /dev/null +++ b/libqpdf/QPDFPageLabelDocumentHelper.cc @@ -0,0 +1,125 @@ +#include +#include + +QPDFPageLabelDocumentHelper::Members::~Members() +{ +} + +QPDFPageLabelDocumentHelper::Members::Members() +{ +} + +QPDFPageLabelDocumentHelper::QPDFPageLabelDocumentHelper(QPDF& qpdf) : + QPDFDocumentHelper(qpdf), + m(new Members()) +{ + QPDFObjectHandle root = qpdf.getRoot(); + if (root.hasKey("/PageLabels")) + { + this->m->labels = new QPDFNumberTreeObjectHelper( + root.getKey("/PageLabels")); + } +} + +bool +QPDFPageLabelDocumentHelper::hasPageLabels() +{ + return 0 != this->m->labels.getPointer(); +} + +QPDFObjectHandle +QPDFPageLabelDocumentHelper::getLabelForPage(long long page_idx) +{ + QPDFObjectHandle result(QPDFObjectHandle::newNull()); + if (! hasPageLabels()) + { + return result; + } + QPDFNumberTreeObjectHelper::numtree_number offset = 0; + QPDFObjectHandle label; + if (! this->m->labels->findObjectAtOrBelow(page_idx, label, offset)) + { + return result; + } + if (! label.isDictionary()) + { + return result; + } + QPDFObjectHandle S = label.getKey("/S"); // type (D, R, r, A, a) + QPDFObjectHandle P = label.getKey("/P"); // prefix + QPDFObjectHandle St = label.getKey("/St"); // starting number + long long start = 1; + if (St.isInteger()) + { + start = St.getIntValue(); + } + start += offset; + result = QPDFObjectHandle::newDictionary(); + result.replaceOrRemoveKey("/S", S); + result.replaceOrRemoveKey("/P", P); + result.replaceOrRemoveKey("/St", QPDFObjectHandle::newInteger(start)); + return result; +} + +void +QPDFPageLabelDocumentHelper::getLabelsForPageRange( + long long start_idx, long long end_idx, long long new_start_idx, + std::vector& new_labels) +{ + // Start off with a suitable label for the first page. For every + // remaining page, if that page has an explicit entry, copy it. + // Otherwise, let the subsequent page just sequence from the prior + // entry. If there is no entry for the first page, fabricate one + // that would match how the page would look in a new file in which + // it also didn't have an explicit label. + QPDFObjectHandle label = getLabelForPage(start_idx); + if (label.isNull()) + { + label = QPDFObjectHandle::newDictionary(); + label.replaceKey( + "/St", QPDFObjectHandle::newInteger(1 + new_start_idx)); + } + // See if the new label is redundant based on the previous entry + // in the vector. If so, don't add it. + size_t size = new_labels.size(); + bool skip_first = false; + if (size >= 2) + { + QPDFObjectHandle last = new_labels[size - 1]; + QPDFObjectHandle last_idx = new_labels[size - 2]; + if (last_idx.isInteger() && last.isDictionary() && + (label.getKey("/S").unparse() == last.getKey("/S").unparse()) && + (label.getKey("/P").unparse() == last.getKey("/P").unparse()) && + label.getKey("/St").isInteger() && + last.getKey("/St").isInteger()) + { + long long int st_delta = + label.getKey("/St").getIntValue() - + last.getKey("/St").getIntValue(); + long long int idx_delta = + new_start_idx - last_idx.getIntValue(); + if (st_delta == idx_delta) + { + QTC::TC("qpdf", "QPDFPageLabelDocumentHelper skip first"); + skip_first = true; + } + } + } + if (! skip_first) + { + new_labels.push_back(QPDFObjectHandle::newInteger(new_start_idx)); + new_labels.push_back(label); + } + + long long int idx_offset = new_start_idx - start_idx; + for (long long i = start_idx + 1; i <= end_idx; ++i) + { + if (this->m->labels->hasIndex(i) && + (label = getLabelForPage(i)).isDictionary()) + { + new_labels.push_back(QPDFObjectHandle::newInteger(i + idx_offset)); + new_labels.push_back(label); + } + } +} + diff --git a/libqpdf/build.mk b/libqpdf/build.mk index 147bb16a..8a2030d1 100644 --- a/libqpdf/build.mk +++ b/libqpdf/build.mk @@ -45,6 +45,7 @@ SRCS_libqpdf = \ libqpdf/QPDFObject.cc \ libqpdf/QPDFObjectHandle.cc \ libqpdf/QPDFPageDocumentHelper.cc \ + libqpdf/QPDFPageLabelDocumentHelper.cc \ libqpdf/QPDFPageObjectHelper.cc \ libqpdf/QPDFSystemError.cc \ libqpdf/QPDFTokenizer.cc \ diff --git a/qpdf/qtest/qpdf.test b/qpdf/qtest/qpdf.test index 9ea5b61d..aba78938 100644 --- a/qpdf/qtest/qpdf.test +++ b/qpdf/qtest/qpdf.test @@ -234,6 +234,24 @@ $td->runtest("number trees", {$td->FILE => "number-tree.out", $td->EXIT_STATUS => 0}, $td->NORMALIZE_NEWLINES); +show_ntests(); +# ---------- +$td->notify("--- Page Labels ---"); +$n_tests += 3; + +$td->runtest("complex page labels", + {$td->COMMAND => "test_driver 47 page-labels-num-tree.pdf"}, + {$td->FILE => "page-labels-num-tree.out", $td->EXIT_STATUS => 0}, + $td->NORMALIZE_NEWLINES); +$td->runtest("no zero entry for page labels", + {$td->COMMAND => "test_driver 47 page-labels-no-zero.pdf"}, + {$td->FILE => "page-labels-no-zero.out", $td->EXIT_STATUS => 0}, + $td->NORMALIZE_NEWLINES); +$td->runtest("no page labels", + {$td->COMMAND => "test_driver 47 minimal.pdf"}, + {$td->FILE => "no-page-labels.out", $td->EXIT_STATUS => 0}, + $td->NORMALIZE_NEWLINES); + show_ntests(); # ---------- $td->notify("--- Page API Tests ---"); diff --git a/qpdf/qtest/qpdf/no-page-labels.out b/qpdf/qtest/qpdf/no-page-labels.out new file mode 100644 index 00000000..f8ebd91d --- /dev/null +++ b/qpdf/qtest/qpdf/no-page-labels.out @@ -0,0 +1,2 @@ +1 << /St 2 >> +test 47 done diff --git a/qpdf/qtest/qpdf/page-labels-no-zero.out b/qpdf/qtest/qpdf/page-labels-no-zero.out new file mode 100644 index 00000000..7d9c926e --- /dev/null +++ b/qpdf/qtest/qpdf/page-labels-no-zero.out @@ -0,0 +1,15 @@ +1 << /St 2 >> +3 << /P (blank) /St 1 >> +4 << /P (X-) /S /A /St 17 >> +6 << /P () /St 1 >> +7 << /S /R /St 3 >> +10 << /S /D /St 1 >> +12 << /S /a /St 1 >> +13 << /S /a /St 3 >> +16 << /P (q.) /S /D /St 6 >> +20 << /P (www) /St 1 >> +21 << /S /D /St 12 >> +23 << /S /D /St 16059 >> +24 << /S /R /St 50 >> +30 << /S /r /St 54 >> +test 47 done diff --git a/qpdf/qtest/qpdf/page-labels-no-zero.pdf b/qpdf/qtest/qpdf/page-labels-no-zero.pdf new file mode 100644 index 00000000..1d106988 --- /dev/null +++ b/qpdf/qtest/qpdf/page-labels-no-zero.pdf @@ -0,0 +1,1364 @@ +%PDF-1.3 +%¿÷¢þ +%QDF-1.0 + +1 0 obj +<< + /PageLabels 2 0 R + /Pages 3 0 R + /Type /Catalog +>> +endobj + +2 0 obj +<< + /Nums [ + 2 << /P (blank) >> + 3 << /P (X-) /S /A /St 17 >> + 5 << /P () >> + 6 << /S /R /St 3 >> + 9 << /S /D >> + 11 << /S /a >> + 12 << /S /a /St 3 >> + 15 << /P (q.) /S /D /St 6 >> + 19 << /P (www) >> + 20 << /S /D /St 12 >> + 22 << /S /D /St 16059 >> + 23 << /S /R /St 50 >> + 29 << /S /r /St 54 >> + ] +>> +endobj + +3 0 obj +<< + /Count 30 + /Kids [ + 4 0 R + 5 0 R + 6 0 R + 7 0 R + 8 0 R + 9 0 R + 10 0 R + 11 0 R + 12 0 R + 13 0 R + 14 0 R + 15 0 R + 16 0 R + 17 0 R + 18 0 R + 19 0 R + 20 0 R + 21 0 R + 22 0 R + 23 0 R + 24 0 R + 25 0 R + 26 0 R + 27 0 R + 28 0 R + 29 0 R + 30 0 R + 31 0 R + 32 0 R + 33 0 R + ] + /Type /Pages +>> +endobj + +%% Page 1 +4 0 obj +<< + /Contents 34 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 3 0 R + /Resources << + /Font << + /F1 36 0 R + >> + /ProcSet 37 0 R + >> + /Type /Page +>> +endobj + +%% Page 2 +5 0 obj +<< + /Contents 38 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 3 0 R + /Resources << + /Font << + /F1 36 0 R + >> + /ProcSet 37 0 R + >> + /Type /Page +>> +endobj + +%% Page 3 +6 0 obj +<< + /Contents 40 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 3 0 R + /Resources << + /Font << + /F1 36 0 R + >> + /ProcSet 37 0 R + >> + /Type /Page +>> +endobj + +%% Page 4 +7 0 obj +<< + /Contents 42 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 3 0 R + /Resources << + /Font << + /F1 36 0 R + >> + /ProcSet 37 0 R + >> + /Type /Page +>> +endobj + +%% Page 5 +8 0 obj +<< + /Contents 44 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 3 0 R + /Resources << + /Font << + /F1 36 0 R + >> + /ProcSet 37 0 R + >> + /Type /Page +>> +endobj + +%% Page 6 +9 0 obj +<< + /Contents 46 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 3 0 R + /Resources << + /Font << + /F1 36 0 R + >> + /ProcSet 37 0 R + >> + /Type /Page +>> +endobj + +%% Page 7 +10 0 obj +<< + /Contents 48 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 3 0 R + /Resources << + /Font << + /F1 36 0 R + >> + /ProcSet 37 0 R + >> + /Type /Page +>> +endobj + +%% Page 8 +11 0 obj +<< + /Contents 50 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 3 0 R + /Resources << + /Font << + /F1 36 0 R + >> + /ProcSet 37 0 R + >> + /Type /Page +>> +endobj + +%% Page 9 +12 0 obj +<< + /Contents 52 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 3 0 R + /Resources << + /Font << + /F1 36 0 R + >> + /ProcSet 37 0 R + >> + /Type /Page +>> +endobj + +%% Page 10 +13 0 obj +<< + /Contents 54 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 3 0 R + /Resources << + /Font << + /F1 36 0 R + >> + /ProcSet 37 0 R + >> + /Type /Page +>> +endobj + +%% Page 11 +14 0 obj +<< + /Contents 56 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 3 0 R + /Resources << + /Font << + /F1 36 0 R + >> + /ProcSet 37 0 R + >> + /Type /Page +>> +endobj + +%% Page 12 +15 0 obj +<< + /Contents 58 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 3 0 R + /Resources << + /Font << + /F1 36 0 R + >> + /ProcSet 37 0 R + >> + /Type /Page +>> +endobj + +%% Page 13 +16 0 obj +<< + /Contents 60 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 3 0 R + /Resources << + /Font << + /F1 36 0 R + >> + /ProcSet 37 0 R + >> + /Type /Page +>> +endobj + +%% Page 14 +17 0 obj +<< + /Contents 62 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 3 0 R + /Resources << + /Font << + /F1 36 0 R + >> + /ProcSet 37 0 R + >> + /Type /Page +>> +endobj + +%% Page 15 +18 0 obj +<< + /Contents 64 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 3 0 R + /Resources << + /Font << + /F1 36 0 R + >> + /ProcSet 37 0 R + >> + /Type /Page +>> +endobj + +%% Page 16 +19 0 obj +<< + /Contents 66 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 3 0 R + /Resources << + /Font << + /F1 36 0 R + >> + /ProcSet 37 0 R + >> + /Type /Page +>> +endobj + +%% Page 17 +20 0 obj +<< + /Contents 68 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 3 0 R + /Resources << + /Font << + /F1 36 0 R + >> + /ProcSet 37 0 R + >> + /Type /Page +>> +endobj + +%% Page 18 +21 0 obj +<< + /Contents 70 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 3 0 R + /Resources << + /Font << + /F1 36 0 R + >> + /ProcSet 37 0 R + >> + /Type /Page +>> +endobj + +%% Page 19 +22 0 obj +<< + /Contents 72 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 3 0 R + /Resources << + /Font << + /F1 36 0 R + >> + /ProcSet 37 0 R + >> + /Type /Page +>> +endobj + +%% Page 20 +23 0 obj +<< + /Contents 74 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 3 0 R + /Resources << + /Font << + /F1 36 0 R + >> + /ProcSet 37 0 R + >> + /Type /Page +>> +endobj + +%% Page 21 +24 0 obj +<< + /Contents 76 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 3 0 R + /Resources << + /Font << + /F1 36 0 R + >> + /ProcSet 37 0 R + >> + /Type /Page +>> +endobj + +%% Page 22 +25 0 obj +<< + /Contents 78 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 3 0 R + /Resources << + /Font << + /F1 36 0 R + >> + /ProcSet 37 0 R + >> + /Type /Page +>> +endobj + +%% Page 23 +26 0 obj +<< + /Contents 80 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 3 0 R + /Resources << + /Font << + /F1 36 0 R + >> + /ProcSet 37 0 R + >> + /Type /Page +>> +endobj + +%% Page 24 +27 0 obj +<< + /Contents 82 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 3 0 R + /Resources << + /Font << + /F1 36 0 R + >> + /ProcSet 37 0 R + >> + /Type /Page +>> +endobj + +%% Page 25 +28 0 obj +<< + /Contents 84 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 3 0 R + /Resources << + /Font << + /F1 36 0 R + >> + /ProcSet 37 0 R + >> + /Type /Page +>> +endobj + +%% Page 26 +29 0 obj +<< + /Contents 86 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 3 0 R + /Resources << + /Font << + /F1 36 0 R + >> + /ProcSet 37 0 R + >> + /Type /Page +>> +endobj + +%% Page 27 +30 0 obj +<< + /Contents 88 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 3 0 R + /Resources << + /Font << + /F1 36 0 R + >> + /ProcSet 37 0 R + >> + /Type /Page +>> +endobj + +%% Page 28 +31 0 obj +<< + /Contents 90 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 3 0 R + /Resources << + /Font << + /F1 36 0 R + >> + /ProcSet 37 0 R + >> + /Type /Page +>> +endobj + +%% Page 29 +32 0 obj +<< + /Contents 92 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 3 0 R + /Resources << + /Font << + /F1 36 0 R + >> + /ProcSet 37 0 R + >> + /Type /Page +>> +endobj + +%% Page 30 +33 0 obj +<< + /Contents 94 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 3 0 R + /Resources << + /Font << + /F1 36 0 R + >> + /ProcSet 37 0 R + >> + /Type /Page +>> +endobj + +%% Contents for page 1 +34 0 obj +<< + /Length 35 0 R +>> +stream +BT + /F1 24 Tf + 72 720 Td + (Potato 0) Tj +ET +endstream +endobj + +35 0 obj +46 +endobj + +36 0 obj +<< + /BaseFont /Helvetica + /Encoding /WinAnsiEncoding + /Name /F1 + /Subtype /Type1 + /Type /Font +>> +endobj + +37 0 obj +[ + /PDF + /Text +] +endobj + +%% Contents for page 2 +38 0 obj +<< + /Length 39 0 R +>> +stream +BT + /F1 24 Tf + 72 720 Td + (Potato 1) Tj +ET +endstream +endobj + +39 0 obj +46 +endobj + +%% Contents for page 3 +40 0 obj +<< + /Length 41 0 R +>> +stream +BT + /F1 24 Tf + 72 720 Td + (Potato 2) Tj +ET +endstream +endobj + +41 0 obj +46 +endobj + +%% Contents for page 4 +42 0 obj +<< + /Length 43 0 R +>> +stream +BT + /F1 24 Tf + 72 720 Td + (Potato 3) Tj +ET +endstream +endobj + +43 0 obj +46 +endobj + +%% Contents for page 5 +44 0 obj +<< + /Length 45 0 R +>> +stream +BT + /F1 24 Tf + 72 720 Td + (Potato 4) Tj +ET +endstream +endobj + +45 0 obj +46 +endobj + +%% Contents for page 6 +46 0 obj +<< + /Length 47 0 R +>> +stream +BT + /F1 24 Tf + 72 720 Td + (Potato 5) Tj +ET +endstream +endobj + +47 0 obj +46 +endobj + +%% Contents for page 7 +48 0 obj +<< + /Length 49 0 R +>> +stream +BT + /F1 24 Tf + 72 720 Td + (Potato 6) Tj +ET +endstream +endobj + +49 0 obj +46 +endobj + +%% Contents for page 8 +50 0 obj +<< + /Length 51 0 R +>> +stream +BT + /F1 24 Tf + 72 720 Td + (Potato 7) Tj +ET +endstream +endobj + +51 0 obj +46 +endobj + +%% Contents for page 9 +52 0 obj +<< + /Length 53 0 R +>> +stream +BT + /F1 24 Tf + 72 720 Td + (Potato 8) Tj +ET +endstream +endobj + +53 0 obj +46 +endobj + +%% Contents for page 10 +54 0 obj +<< + /Length 55 0 R +>> +stream +BT + /F1 24 Tf + 72 720 Td + (Potato 9) Tj +ET +endstream +endobj + +55 0 obj +46 +endobj + +%% Contents for page 11 +56 0 obj +<< + /Length 57 0 R +>> +stream +BT + /F1 24 Tf + 72 720 Td + (Potato 10) Tj +ET +endstream +endobj + +57 0 obj +47 +endobj + +%% Contents for page 12 +58 0 obj +<< + /Length 59 0 R +>> +stream +BT + /F1 24 Tf + 72 720 Td + (Potato 11) Tj +ET +endstream +endobj + +59 0 obj +47 +endobj + +%% Contents for page 13 +60 0 obj +<< + /Length 61 0 R +>> +stream +BT + /F1 24 Tf + 72 720 Td + (Potato 12) Tj +ET +endstream +endobj + +61 0 obj +47 +endobj + +%% Contents for page 14 +62 0 obj +<< + /Length 63 0 R +>> +stream +BT + /F1 24 Tf + 72 720 Td + (Potato 13) Tj +ET +endstream +endobj + +63 0 obj +47 +endobj + +%% Contents for page 15 +64 0 obj +<< + /Length 65 0 R +>> +stream +BT + /F1 24 Tf + 72 720 Td + (Potato 14) Tj +ET +endstream +endobj + +65 0 obj +47 +endobj + +%% Contents for page 16 +66 0 obj +<< + /Length 67 0 R +>> +stream +BT + /F1 24 Tf + 72 720 Td + (Potato 15) Tj +ET +endstream +endobj + +67 0 obj +47 +endobj + +%% Contents for page 17 +68 0 obj +<< + /Length 69 0 R +>> +stream +BT + /F1 24 Tf + 72 720 Td + (Potato 16) Tj +ET +endstream +endobj + +69 0 obj +47 +endobj + +%% Contents for page 18 +70 0 obj +<< + /Length 71 0 R +>> +stream +BT + /F1 24 Tf + 72 720 Td + (Potato 17) Tj +ET +endstream +endobj + +71 0 obj +47 +endobj + +%% Contents for page 19 +72 0 obj +<< + /Length 73 0 R +>> +stream +BT + /F1 24 Tf + 72 720 Td + (Potato 18) Tj +ET +endstream +endobj + +73 0 obj +47 +endobj + +%% Contents for page 20 +74 0 obj +<< + /Length 75 0 R +>> +stream +BT + /F1 24 Tf + 72 720 Td + (Potato 19) Tj +ET +endstream +endobj + +75 0 obj +47 +endobj + +%% Contents for page 21 +76 0 obj +<< + /Length 77 0 R +>> +stream +BT + /F1 24 Tf + 72 720 Td + (Potato 20) Tj +ET +endstream +endobj + +77 0 obj +47 +endobj + +%% Contents for page 22 +78 0 obj +<< + /Length 79 0 R +>> +stream +BT + /F1 24 Tf + 72 720 Td + (Potato 21) Tj +ET +endstream +endobj + +79 0 obj +47 +endobj + +%% Contents for page 23 +80 0 obj +<< + /Length 81 0 R +>> +stream +BT + /F1 24 Tf + 72 720 Td + (Potato 22) Tj +ET +endstream +endobj + +81 0 obj +47 +endobj + +%% Contents for page 24 +82 0 obj +<< + /Length 83 0 R +>> +stream +BT + /F1 24 Tf + 72 720 Td + (Potato 23) Tj +ET +endstream +endobj + +83 0 obj +47 +endobj + +%% Contents for page 25 +84 0 obj +<< + /Length 85 0 R +>> +stream +BT + /F1 24 Tf + 72 720 Td + (Potato 24) Tj +ET +endstream +endobj + +85 0 obj +47 +endobj + +%% Contents for page 26 +86 0 obj +<< + /Length 87 0 R +>> +stream +BT + /F1 24 Tf + 72 720 Td + (Potato 25) Tj +ET +endstream +endobj + +87 0 obj +47 +endobj + +%% Contents for page 27 +88 0 obj +<< + /Length 89 0 R +>> +stream +BT + /F1 24 Tf + 72 720 Td + (Potato 26) Tj +ET +endstream +endobj + +89 0 obj +47 +endobj + +%% Contents for page 28 +90 0 obj +<< + /Length 91 0 R +>> +stream +BT + /F1 24 Tf + 72 720 Td + (Potato 27) Tj +ET +endstream +endobj + +91 0 obj +47 +endobj + +%% Contents for page 29 +92 0 obj +<< + /Length 93 0 R +>> +stream +BT + /F1 24 Tf + 72 720 Td + (Potato 28) Tj +ET +endstream +endobj + +93 0 obj +47 +endobj + +%% Contents for page 30 +94 0 obj +<< + /Length 95 0 R +>> +stream +BT + /F1 24 Tf + 72 720 Td + (Potato 29) Tj +ET +endstream +endobj + +95 0 obj +47 +endobj + +xref +0 96 +0000000000 65535 f +0000000025 00000 n +0000000099 00000 n +0000000457 00000 n +0000000854 00000 n +0000001059 00000 n +0000001264 00000 n +0000001469 00000 n +0000001674 00000 n +0000001879 00000 n +0000002084 00000 n +0000002290 00000 n +0000002496 00000 n +0000002703 00000 n +0000002910 00000 n +0000003117 00000 n +0000003324 00000 n +0000003531 00000 n +0000003738 00000 n +0000003945 00000 n +0000004152 00000 n +0000004359 00000 n +0000004566 00000 n +0000004773 00000 n +0000004980 00000 n +0000005187 00000 n +0000005394 00000 n +0000005601 00000 n +0000005808 00000 n +0000006015 00000 n +0000006222 00000 n +0000006429 00000 n +0000006636 00000 n +0000006843 00000 n +0000007062 00000 n +0000007165 00000 n +0000007185 00000 n +0000007304 00000 n +0000007363 00000 n +0000007466 00000 n +0000007509 00000 n +0000007612 00000 n +0000007655 00000 n +0000007758 00000 n +0000007801 00000 n +0000007904 00000 n +0000007947 00000 n +0000008050 00000 n +0000008093 00000 n +0000008196 00000 n +0000008239 00000 n +0000008342 00000 n +0000008385 00000 n +0000008488 00000 n +0000008532 00000 n +0000008635 00000 n +0000008679 00000 n +0000008783 00000 n +0000008827 00000 n +0000008931 00000 n +0000008975 00000 n +0000009079 00000 n +0000009123 00000 n +0000009227 00000 n +0000009271 00000 n +0000009375 00000 n +0000009419 00000 n +0000009523 00000 n +0000009567 00000 n +0000009671 00000 n +0000009715 00000 n +0000009819 00000 n +0000009863 00000 n +0000009967 00000 n +0000010011 00000 n +0000010115 00000 n +0000010159 00000 n +0000010263 00000 n +0000010307 00000 n +0000010411 00000 n +0000010455 00000 n +0000010559 00000 n +0000010603 00000 n +0000010707 00000 n +0000010751 00000 n +0000010855 00000 n +0000010899 00000 n +0000011003 00000 n +0000011047 00000 n +0000011151 00000 n +0000011195 00000 n +0000011299 00000 n +0000011343 00000 n +0000011447 00000 n +0000011491 00000 n +0000011595 00000 n +trailer << + /Root 1 0 R + /Size 96 + /ID [<90f919de7874f3bc5cb7afbd1e9537bb><55983ed25b1ed15804ad4831bad000da>] +>> +startxref +11615 +%%EOF diff --git a/qpdf/qtest/qpdf/page-labels-num-tree.out b/qpdf/qtest/qpdf/page-labels-num-tree.out new file mode 100644 index 00000000..0f3ccdbc --- /dev/null +++ b/qpdf/qtest/qpdf/page-labels-num-tree.out @@ -0,0 +1,15 @@ +1 << /S /r /St 1 >> +3 << /P (blank) /St 1 >> +4 << /P (X-) /S /A /St 17 >> +6 << /P () /St 1 >> +7 << /S /R /St 3 >> +10 << /S /D /St 1 >> +12 << /S /a /St 1 >> +13 << /S /a /St 3 >> +16 << /P (q.) /S /D /St 6 >> +20 << /P (www) /St 1 >> +21 << /S /D /St 12 >> +23 << /S /D /St 16059 >> +24 << /S /R /St 50 >> +30 << /S /r /St 54 >> +test 47 done diff --git a/qpdf/qtest/qpdf/page-labels-num-tree.pdf b/qpdf/qtest/qpdf/page-labels-num-tree.pdf new file mode 100644 index 00000000..ad0ad0fc --- /dev/null +++ b/qpdf/qtest/qpdf/page-labels-num-tree.pdf @@ -0,0 +1,1417 @@ +%PDF-1.3 +%¿÷¢þ +%QDF-1.0 + +1 0 obj +<< + /PageLabels 2 0 R + /Pages 3 0 R + /Type /Catalog +>> +endobj + +2 0 obj +<< + /Kids [ + 4 0 R + 5 0 R + ] +>> +endobj + +3 0 obj +<< + /Count 30 + /Kids [ + 6 0 R + 7 0 R + 8 0 R + 9 0 R + 10 0 R + 11 0 R + 12 0 R + 13 0 R + 14 0 R + 15 0 R + 16 0 R + 17 0 R + 18 0 R + 19 0 R + 20 0 R + 21 0 R + 22 0 R + 23 0 R + 24 0 R + 25 0 R + 26 0 R + 27 0 R + 28 0 R + 29 0 R + 30 0 R + 31 0 R + 32 0 R + 33 0 R + 34 0 R + 35 0 R + ] + /Type /Pages +>> +endobj + +4 0 obj +<< + /Kids [ + 36 0 R + 37 0 R + ] + /Limits [ + 0 + 19 + ] +>> +endobj + +5 0 obj +<< + /Limits [ + 20 + 29 + ] + /Nums [ + 20 << /S /D /St 12 >> + 22 << /S /D /St 16059 >> + 23 << /S /R /St 50 >> + 29 << /S /r /St 54 >> + ] +>> +endobj + +%% Page 1 +6 0 obj +<< + /Contents 38 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 3 0 R + /Resources << + /Font << + /F1 40 0 R + >> + /ProcSet 41 0 R + >> + /Type /Page +>> +endobj + +%% Page 2 +7 0 obj +<< + /Contents 42 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 3 0 R + /Resources << + /Font << + /F1 40 0 R + >> + /ProcSet 41 0 R + >> + /Type /Page +>> +endobj + +%% Page 3 +8 0 obj +<< + /Contents 44 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 3 0 R + /Resources << + /Font << + /F1 40 0 R + >> + /ProcSet 41 0 R + >> + /Type /Page +>> +endobj + +%% Page 4 +9 0 obj +<< + /Contents 46 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 3 0 R + /Resources << + /Font << + /F1 40 0 R + >> + /ProcSet 41 0 R + >> + /Type /Page +>> +endobj + +%% Page 5 +10 0 obj +<< + /Contents 48 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 3 0 R + /Resources << + /Font << + /F1 40 0 R + >> + /ProcSet 41 0 R + >> + /Type /Page +>> +endobj + +%% Page 6 +11 0 obj +<< + /Contents 50 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 3 0 R + /Resources << + /Font << + /F1 40 0 R + >> + /ProcSet 41 0 R + >> + /Type /Page +>> +endobj + +%% Page 7 +12 0 obj +<< + /Contents 52 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 3 0 R + /Resources << + /Font << + /F1 40 0 R + >> + /ProcSet 41 0 R + >> + /Type /Page +>> +endobj + +%% Page 8 +13 0 obj +<< + /Contents 54 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 3 0 R + /Resources << + /Font << + /F1 40 0 R + >> + /ProcSet 41 0 R + >> + /Type /Page +>> +endobj + +%% Page 9 +14 0 obj +<< + /Contents 56 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 3 0 R + /Resources << + /Font << + /F1 40 0 R + >> + /ProcSet 41 0 R + >> + /Type /Page +>> +endobj + +%% Page 10 +15 0 obj +<< + /Contents 58 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 3 0 R + /Resources << + /Font << + /F1 40 0 R + >> + /ProcSet 41 0 R + >> + /Type /Page +>> +endobj + +%% Page 11 +16 0 obj +<< + /Contents 60 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 3 0 R + /Resources << + /Font << + /F1 40 0 R + >> + /ProcSet 41 0 R + >> + /Type /Page +>> +endobj + +%% Page 12 +17 0 obj +<< + /Contents 62 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 3 0 R + /Resources << + /Font << + /F1 40 0 R + >> + /ProcSet 41 0 R + >> + /Type /Page +>> +endobj + +%% Page 13 +18 0 obj +<< + /Contents 64 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 3 0 R + /Resources << + /Font << + /F1 40 0 R + >> + /ProcSet 41 0 R + >> + /Type /Page +>> +endobj + +%% Page 14 +19 0 obj +<< + /Contents 66 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 3 0 R + /Resources << + /Font << + /F1 40 0 R + >> + /ProcSet 41 0 R + >> + /Type /Page +>> +endobj + +%% Page 15 +20 0 obj +<< + /Contents 68 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 3 0 R + /Resources << + /Font << + /F1 40 0 R + >> + /ProcSet 41 0 R + >> + /Type /Page +>> +endobj + +%% Page 16 +21 0 obj +<< + /Contents 70 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 3 0 R + /Resources << + /Font << + /F1 40 0 R + >> + /ProcSet 41 0 R + >> + /Type /Page +>> +endobj + +%% Page 17 +22 0 obj +<< + /Contents 72 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 3 0 R + /Resources << + /Font << + /F1 40 0 R + >> + /ProcSet 41 0 R + >> + /Type /Page +>> +endobj + +%% Page 18 +23 0 obj +<< + /Contents 74 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 3 0 R + /Resources << + /Font << + /F1 40 0 R + >> + /ProcSet 41 0 R + >> + /Type /Page +>> +endobj + +%% Page 19 +24 0 obj +<< + /Contents 76 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 3 0 R + /Resources << + /Font << + /F1 40 0 R + >> + /ProcSet 41 0 R + >> + /Type /Page +>> +endobj + +%% Page 20 +25 0 obj +<< + /Contents 78 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 3 0 R + /Resources << + /Font << + /F1 40 0 R + >> + /ProcSet 41 0 R + >> + /Type /Page +>> +endobj + +%% Page 21 +26 0 obj +<< + /Contents 80 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 3 0 R + /Resources << + /Font << + /F1 40 0 R + >> + /ProcSet 41 0 R + >> + /Type /Page +>> +endobj + +%% Page 22 +27 0 obj +<< + /Contents 82 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 3 0 R + /Resources << + /Font << + /F1 40 0 R + >> + /ProcSet 41 0 R + >> + /Type /Page +>> +endobj + +%% Page 23 +28 0 obj +<< + /Contents 84 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 3 0 R + /Resources << + /Font << + /F1 40 0 R + >> + /ProcSet 41 0 R + >> + /Type /Page +>> +endobj + +%% Page 24 +29 0 obj +<< + /Contents 86 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 3 0 R + /Resources << + /Font << + /F1 40 0 R + >> + /ProcSet 41 0 R + >> + /Type /Page +>> +endobj + +%% Page 25 +30 0 obj +<< + /Contents 88 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 3 0 R + /Resources << + /Font << + /F1 40 0 R + >> + /ProcSet 41 0 R + >> + /Type /Page +>> +endobj + +%% Page 26 +31 0 obj +<< + /Contents 90 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 3 0 R + /Resources << + /Font << + /F1 40 0 R + >> + /ProcSet 41 0 R + >> + /Type /Page +>> +endobj + +%% Page 27 +32 0 obj +<< + /Contents 92 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 3 0 R + /Resources << + /Font << + /F1 40 0 R + >> + /ProcSet 41 0 R + >> + /Type /Page +>> +endobj + +%% Page 28 +33 0 obj +<< + /Contents 94 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 3 0 R + /Resources << + /Font << + /F1 40 0 R + >> + /ProcSet 41 0 R + >> + /Type /Page +>> +endobj + +%% Page 29 +34 0 obj +<< + /Contents 96 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 3 0 R + /Resources << + /Font << + /F1 40 0 R + >> + /ProcSet 41 0 R + >> + /Type /Page +>> +endobj + +%% Page 30 +35 0 obj +<< + /Contents 98 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 3 0 R + /Resources << + /Font << + /F1 40 0 R + >> + /ProcSet 41 0 R + >> + /Type /Page +>> +endobj + +36 0 obj +<< + /Limits [ + 0 + 9 + ] + /Nums [ + 0 << /S /r >> + 2 << /P (blank) >> + 3 << /P (X-) /S /A /St 17 >> + 5 << /P () >> + 6 << /S /R /St 3 >> + 9 << /S /D >> + ] +>> +endobj + +37 0 obj +<< + /Limits [ + 11 + 19 + ] + /Nums [ + 11 << /S /a >> + 12 << /S /a /St 3 >> + 15 << /P (q.) /S /D /St 6 >> + 19 << /P (www) >> + ] +>> +endobj + +%% Contents for page 1 +38 0 obj +<< + /Length 39 0 R +>> +stream +BT + /F1 24 Tf + 72 720 Td + (Potato 0) Tj +ET +endstream +endobj + +39 0 obj +46 +endobj + +40 0 obj +<< + /BaseFont /Helvetica + /Encoding /WinAnsiEncoding + /Name /F1 + /Subtype /Type1 + /Type /Font +>> +endobj + +41 0 obj +[ + /PDF + /Text +] +endobj + +%% Contents for page 2 +42 0 obj +<< + /Length 43 0 R +>> +stream +BT + /F1 24 Tf + 72 720 Td + (Potato 1) Tj +ET +endstream +endobj + +43 0 obj +46 +endobj + +%% Contents for page 3 +44 0 obj +<< + /Length 45 0 R +>> +stream +BT + /F1 24 Tf + 72 720 Td + (Potato 2) Tj +ET +endstream +endobj + +45 0 obj +46 +endobj + +%% Contents for page 4 +46 0 obj +<< + /Length 47 0 R +>> +stream +BT + /F1 24 Tf + 72 720 Td + (Potato 3) Tj +ET +endstream +endobj + +47 0 obj +46 +endobj + +%% Contents for page 5 +48 0 obj +<< + /Length 49 0 R +>> +stream +BT + /F1 24 Tf + 72 720 Td + (Potato 4) Tj +ET +endstream +endobj + +49 0 obj +46 +endobj + +%% Contents for page 6 +50 0 obj +<< + /Length 51 0 R +>> +stream +BT + /F1 24 Tf + 72 720 Td + (Potato 5) Tj +ET +endstream +endobj + +51 0 obj +46 +endobj + +%% Contents for page 7 +52 0 obj +<< + /Length 53 0 R +>> +stream +BT + /F1 24 Tf + 72 720 Td + (Potato 6) Tj +ET +endstream +endobj + +53 0 obj +46 +endobj + +%% Contents for page 8 +54 0 obj +<< + /Length 55 0 R +>> +stream +BT + /F1 24 Tf + 72 720 Td + (Potato 7) Tj +ET +endstream +endobj + +55 0 obj +46 +endobj + +%% Contents for page 9 +56 0 obj +<< + /Length 57 0 R +>> +stream +BT + /F1 24 Tf + 72 720 Td + (Potato 8) Tj +ET +endstream +endobj + +57 0 obj +46 +endobj + +%% Contents for page 10 +58 0 obj +<< + /Length 59 0 R +>> +stream +BT + /F1 24 Tf + 72 720 Td + (Potato 9) Tj +ET +endstream +endobj + +59 0 obj +46 +endobj + +%% Contents for page 11 +60 0 obj +<< + /Length 61 0 R +>> +stream +BT + /F1 24 Tf + 72 720 Td + (Potato 10) Tj +ET +endstream +endobj + +61 0 obj +47 +endobj + +%% Contents for page 12 +62 0 obj +<< + /Length 63 0 R +>> +stream +BT + /F1 24 Tf + 72 720 Td + (Potato 11) Tj +ET +endstream +endobj + +63 0 obj +47 +endobj + +%% Contents for page 13 +64 0 obj +<< + /Length 65 0 R +>> +stream +BT + /F1 24 Tf + 72 720 Td + (Potato 12) Tj +ET +endstream +endobj + +65 0 obj +47 +endobj + +%% Contents for page 14 +66 0 obj +<< + /Length 67 0 R +>> +stream +BT + /F1 24 Tf + 72 720 Td + (Potato 13) Tj +ET +endstream +endobj + +67 0 obj +47 +endobj + +%% Contents for page 15 +68 0 obj +<< + /Length 69 0 R +>> +stream +BT + /F1 24 Tf + 72 720 Td + (Potato 14) Tj +ET +endstream +endobj + +69 0 obj +47 +endobj + +%% Contents for page 16 +70 0 obj +<< + /Length 71 0 R +>> +stream +BT + /F1 24 Tf + 72 720 Td + (Potato 15) Tj +ET +endstream +endobj + +71 0 obj +47 +endobj + +%% Contents for page 17 +72 0 obj +<< + /Length 73 0 R +>> +stream +BT + /F1 24 Tf + 72 720 Td + (Potato 16) Tj +ET +endstream +endobj + +73 0 obj +47 +endobj + +%% Contents for page 18 +74 0 obj +<< + /Length 75 0 R +>> +stream +BT + /F1 24 Tf + 72 720 Td + (Potato 17) Tj +ET +endstream +endobj + +75 0 obj +47 +endobj + +%% Contents for page 19 +76 0 obj +<< + /Length 77 0 R +>> +stream +BT + /F1 24 Tf + 72 720 Td + (Potato 18) Tj +ET +endstream +endobj + +77 0 obj +47 +endobj + +%% Contents for page 20 +78 0 obj +<< + /Length 79 0 R +>> +stream +BT + /F1 24 Tf + 72 720 Td + (Potato 19) Tj +ET +endstream +endobj + +79 0 obj +47 +endobj + +%% Contents for page 21 +80 0 obj +<< + /Length 81 0 R +>> +stream +BT + /F1 24 Tf + 72 720 Td + (Potato 20) Tj +ET +endstream +endobj + +81 0 obj +47 +endobj + +%% Contents for page 22 +82 0 obj +<< + /Length 83 0 R +>> +stream +BT + /F1 24 Tf + 72 720 Td + (Potato 21) Tj +ET +endstream +endobj + +83 0 obj +47 +endobj + +%% Contents for page 23 +84 0 obj +<< + /Length 85 0 R +>> +stream +BT + /F1 24 Tf + 72 720 Td + (Potato 22) Tj +ET +endstream +endobj + +85 0 obj +47 +endobj + +%% Contents for page 24 +86 0 obj +<< + /Length 87 0 R +>> +stream +BT + /F1 24 Tf + 72 720 Td + (Potato 23) Tj +ET +endstream +endobj + +87 0 obj +47 +endobj + +%% Contents for page 25 +88 0 obj +<< + /Length 89 0 R +>> +stream +BT + /F1 24 Tf + 72 720 Td + (Potato 24) Tj +ET +endstream +endobj + +89 0 obj +47 +endobj + +%% Contents for page 26 +90 0 obj +<< + /Length 91 0 R +>> +stream +BT + /F1 24 Tf + 72 720 Td + (Potato 25) Tj +ET +endstream +endobj + +91 0 obj +47 +endobj + +%% Contents for page 27 +92 0 obj +<< + /Length 93 0 R +>> +stream +BT + /F1 24 Tf + 72 720 Td + (Potato 26) Tj +ET +endstream +endobj + +93 0 obj +47 +endobj + +%% Contents for page 28 +94 0 obj +<< + /Length 95 0 R +>> +stream +BT + /F1 24 Tf + 72 720 Td + (Potato 27) Tj +ET +endstream +endobj + +95 0 obj +47 +endobj + +%% Contents for page 29 +96 0 obj +<< + /Length 97 0 R +>> +stream +BT + /F1 24 Tf + 72 720 Td + (Potato 28) Tj +ET +endstream +endobj + +97 0 obj +47 +endobj + +%% Contents for page 30 +98 0 obj +<< + /Length 99 0 R +>> +stream +BT + /F1 24 Tf + 72 720 Td + (Potato 29) Tj +ET +endstream +endobj + +99 0 obj +47 +endobj + +xref +0 100 +0000000000 65535 f +0000000025 00000 n +0000000099 00000 n +0000000155 00000 n +0000000544 00000 n +0000000631 00000 n +0000000814 00000 n +0000001019 00000 n +0000001224 00000 n +0000001429 00000 n +0000001634 00000 n +0000001840 00000 n +0000002046 00000 n +0000002252 00000 n +0000002458 00000 n +0000002665 00000 n +0000002872 00000 n +0000003079 00000 n +0000003286 00000 n +0000003493 00000 n +0000003700 00000 n +0000003907 00000 n +0000004114 00000 n +0000004321 00000 n +0000004528 00000 n +0000004735 00000 n +0000004942 00000 n +0000005149 00000 n +0000005356 00000 n +0000005563 00000 n +0000005770 00000 n +0000005977 00000 n +0000006184 00000 n +0000006391 00000 n +0000006598 00000 n +0000006805 00000 n +0000007001 00000 n +0000007200 00000 n +0000007389 00000 n +0000007492 00000 n +0000007512 00000 n +0000007631 00000 n +0000007690 00000 n +0000007793 00000 n +0000007836 00000 n +0000007939 00000 n +0000007982 00000 n +0000008085 00000 n +0000008128 00000 n +0000008231 00000 n +0000008274 00000 n +0000008377 00000 n +0000008420 00000 n +0000008523 00000 n +0000008566 00000 n +0000008669 00000 n +0000008712 00000 n +0000008815 00000 n +0000008859 00000 n +0000008962 00000 n +0000009006 00000 n +0000009110 00000 n +0000009154 00000 n +0000009258 00000 n +0000009302 00000 n +0000009406 00000 n +0000009450 00000 n +0000009554 00000 n +0000009598 00000 n +0000009702 00000 n +0000009746 00000 n +0000009850 00000 n +0000009894 00000 n +0000009998 00000 n +0000010042 00000 n +0000010146 00000 n +0000010190 00000 n +0000010294 00000 n +0000010338 00000 n +0000010442 00000 n +0000010486 00000 n +0000010590 00000 n +0000010634 00000 n +0000010738 00000 n +0000010782 00000 n +0000010886 00000 n +0000010930 00000 n +0000011034 00000 n +0000011078 00000 n +0000011182 00000 n +0000011226 00000 n +0000011330 00000 n +0000011374 00000 n +0000011478 00000 n +0000011522 00000 n +0000011626 00000 n +0000011670 00000 n +0000011774 00000 n +0000011818 00000 n +0000011922 00000 n +trailer << + /Root 1 0 R + /Size 100 + /ID [<90f919de7874f3bc5cb7afbd1e9537bb><0dfe18a94cde0f4bfdc86c03af19010e>] +>> +startxref +11942 +%%EOF diff --git a/qpdf/test_driver.cc b/qpdf/test_driver.cc index 3bcb173e..89dd1d02 100644 --- a/qpdf/test_driver.cc +++ b/qpdf/test_driver.cc @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -1690,6 +1691,21 @@ void runtest(int n, char const* filename1, char const* arg2) assert("six" == oh.getStringValue()); assert(2 == offset); } + else if (n == 47) + { + // Test page labels. + QPDFPageLabelDocumentHelper pldh(pdf); + size_t npages = pdf.getRoot().getKey("/Pages"). + getKey("/Count").getIntValue(); + std::vector labels; + pldh.getLabelsForPageRange(0, npages - 1, 1, labels); + assert(labels.size() % 2 == 0); + for (size_t i = 0; i < labels.size(); i+= 2) + { + std::cout << labels.at(i).getIntValue() << " " + << labels.at(i+1).unparse() << std::endl; + } + } else { throw std::runtime_error(std::string("invalid test ") +