diff options
-rw-r--r-- | ChangeLog | 6 | ||||
-rw-r--r-- | manual/qpdf-manual.xml | 38 | ||||
-rw-r--r-- | qpdf/qpdf.cc | 52 | ||||
-rw-r--r-- | qpdf/qpdf.testcov | 1 | ||||
-rw-r--r-- | qpdf/qtest/qpdf.test | 29 | ||||
-rw-r--r-- | qpdf/qtest/qpdf/11-pages-with-labels.pdf | bin | 0 -> 4215 bytes | |||
-rw-r--r-- | qpdf/qtest/qpdf/labels-split-01-06.pdf | 324 | ||||
-rw-r--r-- | qpdf/qtest/qpdf/labels-split-07-11.pdf | 280 | ||||
-rw-r--r-- | qpdf/qtest/qpdf/merge-implicit-ranges.pdf | 220 | ||||
-rw-r--r-- | qpdf/qtest/qpdf/merge-multiple-labels.pdf | bin | 0 -> 3452 bytes | |||
-rw-r--r-- | qpdf/qtest/qpdf/merge-three-files-1.pdf | bin | 8495 -> 8396 bytes | |||
-rw-r--r-- | qpdf/qtest/qpdf/merge-three-files-2.pdf | bin | 6036 -> 6196 bytes |
12 files changed, 806 insertions, 144 deletions
@@ -1,5 +1,11 @@ 2018-12-18 Jay Berkenbilt <ejb@ql.org> + * Preserve page labels when merging and splitting files. Prior + versions of qpdf simply preserved the page label information from + the first file, which usually wouldn't make any sense in the + merged file. Now any page that had a page number in any original + file will have the same page number after merging or splitting. + * 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 diff --git a/manual/qpdf-manual.xml b/manual/qpdf-manual.xml index 8185b848..e327eb95 100644 --- a/manual/qpdf-manual.xml +++ b/manual/qpdf-manual.xml @@ -911,23 +911,23 @@ make </itemizedlist> </para> <para> - Note that qpdf doesn't presently do anything special about other - constructs in a PDF file that may know about pages, so semantics - of splitting and merging vary across features. For example, the - document's outlines (bookmarks) point to actual page objects, so - if you select some pages and not others, bookmarks that point to - pages that are in the output file will work, and remaining - bookmarks will not work. On the other hand, page labels (page - numbers specified in the file) are just sequential, so page labels - will be messed up in the output file. A future version of - <command>qpdf</command> may do a better job at handling these - issues. (Note that the qpdf library already contains all of the - APIs required in order to implement this in your own application - if you need it.) In the mean time, you can always use - <option>--empty</option> as the primary input file to avoid - copying all of that from the first file. For example, to take - pages 1 through 5 from a <filename>infile.pdf</filename> while - preserving all metadata associated with that file, you could use + Starting in qpdf version 8.3, when you split and merge files, any + page labels (page numbers) are preserved in the final file. It is + expected that more document features will be preserved by + splitting and merging. In the mean time, semantics of splitting + and merging vary across features. For example, the document's + outlines (bookmarks) point to actual page objects, so if you + select some pages and not others, bookmarks that point to pages + that are in the output file will work, and remaining bookmarks + will not work. A future version of <command>qpdf</command> may do + a better job at handling these issues. (Note that the qpdf library + already contains all of the APIs required in order to implement + this in your own application if you need it.) In the mean time, + you can always use <option>--empty</option> as the primary input + file to avoid copying all of that from the first file. For + example, to take pages 1 through 5 from a + <filename>infile.pdf</filename> while preserving all metadata + associated with that file, you could use <programlisting><command>qpdf</command> <option>infile.pdf --pages infile.pdf 1-5 -- outfile.pdf</option> </programlisting> @@ -946,8 +946,8 @@ make If, for some reason, you wanted to take the first page of an encrypted file called <filename>encrypted.pdf</filename> with password <literal>pass</literal> and repeat it twice in an output - file, and if you wanted to drop metadata (like page numbers and - outlines) but preserve encryption, you would use + file, and if you wanted to drop document-level metadata but + preserve encryption, you would use <programlisting><command>qpdf</command> <option>--empty --copy-encryption=encrypted.pdf --encryption-file-password=pass --pages encrypted.pdf --password=pass 1 ./encrypted.pdf --password=pass 1 -- diff --git a/qpdf/qpdf.cc b/qpdf/qpdf.cc index 19d46acc..b6762aab 100644 --- a/qpdf/qpdf.cc +++ b/qpdf/qpdf.cc @@ -16,6 +16,7 @@ #include <qpdf/QPDF.hh> #include <qpdf/QPDFPageDocumentHelper.hh> #include <qpdf/QPDFPageObjectHelper.hh> +#include <qpdf/QPDFPageLabelDocumentHelper.hh> #include <qpdf/QPDFExc.hh> #include <qpdf/QPDFWriter.hh> @@ -2296,11 +2297,25 @@ static void handle_page_specs(QPDF& pdf, Options& o, // Keep track of any pages from the original file that we are // selecting. std::set<int> selected_from_orig; + std::vector<QPDFObjectHandle> new_labels; + bool any_page_labels = false; + int out_pageno = 0; for (std::vector<QPDFPageData>::iterator iter = parsed_specs.begin(); iter != parsed_specs.end(); ++iter) { QPDFPageData& page_data = *iter; + ClosedFileInputSource* cis = 0; + if (page_spec_cfis.count(page_data.filename)) + { + cis = page_spec_cfis[page_data.filename]; + cis->stayOpen(true); + } + QPDFPageLabelDocumentHelper pldh(*page_data.qpdf); + if (pldh.hasPageLabels()) + { + any_page_labels = true; + } if (o.verbose) { std::cout << whoami << ": adding pages from " @@ -2309,22 +2324,14 @@ static void handle_page_specs(QPDF& pdf, Options& o, for (std::vector<int>::iterator pageno_iter = page_data.selected_pages.begin(); pageno_iter != page_data.selected_pages.end(); - ++pageno_iter) + ++pageno_iter, ++out_pageno) { // Pages are specified from 1 but numbered from 0 in the // vector int pageno = *pageno_iter - 1; - ClosedFileInputSource* cis = 0; - if (page_spec_cfis.count(page_data.filename)) - { - cis = page_spec_cfis[page_data.filename]; - cis->stayOpen(true); - } + pldh.getLabelsForPageRange(pageno, pageno, out_pageno, + new_labels); dh.addPage(page_data.orig_pages.at(pageno), false); - if (cis) - { - cis->stayOpen(false); - } if (page_data.qpdf == &pdf) { // This is a page from the original file. Keep track @@ -2332,6 +2339,18 @@ static void handle_page_specs(QPDF& pdf, Options& o, selected_from_orig.insert(pageno); } } + if (cis) + { + cis->stayOpen(false); + } + } + if (any_page_labels) + { + QPDFObjectHandle page_labels = + QPDFObjectHandle::newDictionary(); + page_labels.replaceKey( + "/Nums", QPDFObjectHandle::newArray(new_labels)); + pdf.getRoot().replaceKey("/PageLabels", page_labels); } // Delete page objects for unused page in primary. This prevents @@ -2574,6 +2593,7 @@ static void write_outfile(QPDF& pdf, Options& o) dh.pushInheritedAttributesToPage(); dh.removeUnreferencedResources(); } + QPDFPageLabelDocumentHelper pldh(pdf); std::vector<QPDFObjectHandle> const& pages = pdf.getAllPages(); int pageno_len = QUtil::int_to_string(pages.size()).length(); unsigned int num_pages = pages.size(); @@ -2592,6 +2612,16 @@ static void write_outfile(QPDF& pdf, Options& o) QPDFObjectHandle page = pages.at(pageno - 1); outpdf.addPage(page, false); } + if (pldh.hasPageLabels()) + { + std::vector<QPDFObjectHandle> labels; + pldh.getLabelsForPageRange(first - 1, last - 1, 0, labels); + QPDFObjectHandle page_labels = + QPDFObjectHandle::newDictionary(); + page_labels.replaceKey( + "/Nums", QPDFObjectHandle::newArray(labels)); + outpdf.getRoot().replaceKey("/PageLabels", page_labels); + } std::string page_range = QUtil::int_to_string(first, pageno_len); if (o.split_pages > 1) { diff --git a/qpdf/qpdf.testcov b/qpdf/qpdf.testcov index 6f06ab05..71858eec 100644 --- a/qpdf/qpdf.testcov +++ b/qpdf/qpdf.testcov @@ -360,3 +360,4 @@ qpdf disable keep files open 0 qpdf keep files open n 0 qpdf keep files open y 0 qpdf don't disable keep files open 0 +QPDFPageLabelDocumentHelper skip first 0 diff --git a/qpdf/qtest/qpdf.test b/qpdf/qtest/qpdf.test index aba78938..cf5b2ab5 100644 --- a/qpdf/qtest/qpdf.test +++ b/qpdf/qtest/qpdf.test @@ -1137,7 +1137,7 @@ my @sp_cases = ( [11, 'pdf extension', '', 'split-out.Pdf'], [4, 'fallback', '--pages 11-pages.pdf 1-3 minimal.pdf --', 'split-out'], ); -$n_tests += 9; +$n_tests += 12; for (@sp_cases) { $n_tests += 1 + $_->[0]; @@ -1171,6 +1171,17 @@ foreach my $i (qw(01-04 05-08 09-10)) {$td->FILE => "shared-split-$i.pdf"}); } +$td->runtest("split page with labels", + {$td->COMMAND => "qpdf --qdf --static-id --split-pages=6". + " 11-pages-with-labels.pdf split-out-labels.pdf"}, + {$td->STRING => "", $td->EXIT_STATUS => 0}); +foreach my $i (qw(01-06 07-11)) +{ + $td->runtest("check output ($i)", + {$td->FILE => "split-out-labels-$i.pdf"}, + {$td->FILE => "labels-split-$i.pdf"}); +} + foreach my $d (@sp_cases) { my ($n, $description, $xargs, $out) = @$d; @@ -1335,7 +1346,7 @@ foreach my $d (@nrange_tests) show_ntests(); # ---------- $td->notify("--- Merging and Splitting ---"); -$n_tests += 16; +$n_tests += 18; # Select pages from the same file multiple times including selecting # twice from an encrypted file and specifying the password only the @@ -1368,8 +1379,7 @@ $td->runtest("merge three files", " $pages_options --static-id"}, {$td->STRING => "", $td->EXIT_STATUS => 0}); # Manually verified about this file: it has the same pages but does -# not contain outlines, page labels, or other things from the original -# file. +# not contain outlines or other things from the original file. $td->runtest("check output", {$td->FILE => "a.pdf"}, {$td->FILE => "merge-three-files-2.pdf"}); @@ -1392,6 +1402,17 @@ $td->runtest("merge with implicit ranges", $td->runtest("check output", {$td->FILE => "a.pdf"}, {$td->FILE => "merge-implicit-ranges.pdf"}); +$td->runtest("merge with multiple labels", + {$td->COMMAND => + "qpdf --empty a.pdf" . + " --pages 11-pages-with-labels.pdf 8-11" . + " minimal.pdf " . + " page-labels-and-outlines.pdf 17-19 --" . + " --static-id"}, + {$td->STRING => "", $td->EXIT_STATUS => 0}); +$td->runtest("check output", + {$td->FILE => "a.pdf"}, + {$td->FILE => "merge-multiple-labels.pdf"}); $td->runtest("split with shared resources", {$td->COMMAND => diff --git a/qpdf/qtest/qpdf/11-pages-with-labels.pdf b/qpdf/qtest/qpdf/11-pages-with-labels.pdf Binary files differnew file mode 100644 index 00000000..962b1b0e --- /dev/null +++ b/qpdf/qtest/qpdf/11-pages-with-labels.pdf diff --git a/qpdf/qtest/qpdf/labels-split-01-06.pdf b/qpdf/qtest/qpdf/labels-split-01-06.pdf new file mode 100644 index 00000000..1058eba1 --- /dev/null +++ b/qpdf/qtest/qpdf/labels-split-01-06.pdf @@ -0,0 +1,324 @@ +%PDF-1.3 +%¿÷¢þ +%QDF-1.0 + +%% Original object ID: 1 0 +1 0 obj +<< + /PageLabels << + /Nums [ + 0 + << + /P (pre-) + /St 1 + >> + 4 + << + /S /r + /St 4 + >> + ] + >> + /Pages 2 0 R + /Type /Catalog +>> +endobj + +%% Original object ID: 2 0 +2 0 obj +<< + /Count 6 + /Kids [ + 3 0 R + 4 0 R + 5 0 R + 6 0 R + 7 0 R + 8 0 R + ] + /Type /Pages +>> +endobj + +%% Page 1 +%% Original object ID: 3 0 +3 0 obj +<< + /Contents 9 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 2 0 R + /Resources << + /Font << + /F1 11 0 R + >> + /ProcSet [ + /PDF + /Text + ] + >> + /Type /Page +>> +endobj + +%% Page 2 +%% Original object ID: 6 0 +4 0 obj +<< + /Contents 12 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 2 0 R + /Resources << + /Font << + /F1 11 0 R + >> + /ProcSet [ + /PDF + /Text + ] + >> + /Type /Page +>> +endobj + +%% Page 3 +%% Original object ID: 8 0 +5 0 obj +<< + /Contents 14 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 2 0 R + /Resources << + /Font << + /F1 11 0 R + >> + /ProcSet [ + /PDF + /Text + ] + >> + /Type /Page +>> +endobj + +%% Page 4 +%% Original object ID: 10 0 +6 0 obj +<< + /Contents 16 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 2 0 R + /Resources << + /Font << + /F1 11 0 R + >> + /ProcSet [ + /PDF + /Text + ] + >> + /Type /Page +>> +endobj + +%% Page 5 +%% Original object ID: 12 0 +7 0 obj +<< + /Contents 18 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 2 0 R + /Resources << + /Font << + /F1 11 0 R + >> + /ProcSet [ + /PDF + /Text + ] + >> + /Type /Page +>> +endobj + +%% Page 6 +%% Original object ID: 14 0 +8 0 obj +<< + /Contents 20 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 2 0 R + /Resources << + /Font << + /F1 11 0 R + >> + /ProcSet [ + /PDF + /Text + ] + >> + /Type /Page +>> +endobj + +%% Contents for page 1 +%% Original object ID: 4 0 +9 0 obj +<< + /Length 10 0 R +>> +stream +BT /F1 15 Tf 72 720 Td (Original page 1) Tj ET +endstream +endobj + +10 0 obj +47 +endobj + +%% Original object ID: 5 0 +11 0 obj +<< + /BaseFont /Times-Roman + /Encoding /WinAnsiEncoding + /Subtype /Type1 + /Type /Font +>> +endobj + +%% Contents for page 2 +%% Original object ID: 7 0 +12 0 obj +<< + /Length 13 0 R +>> +stream +BT /F1 15 Tf 72 720 Td (Original page 2) Tj ET +endstream +endobj + +13 0 obj +47 +endobj + +%% Contents for page 3 +%% Original object ID: 9 0 +14 0 obj +<< + /Length 15 0 R +>> +stream +BT /F1 15 Tf 72 720 Td (Original page 3) Tj ET +endstream +endobj + +15 0 obj +47 +endobj + +%% Contents for page 4 +%% Original object ID: 11 0 +16 0 obj +<< + /Length 17 0 R +>> +stream +BT /F1 15 Tf 72 720 Td (Original page 4) Tj ET +endstream +endobj + +17 0 obj +47 +endobj + +%% Contents for page 5 +%% Original object ID: 13 0 +18 0 obj +<< + /Length 19 0 R +>> +stream +BT /F1 15 Tf 72 720 Td (Original page 5) Tj ET +endstream +endobj + +19 0 obj +47 +endobj + +%% Contents for page 6 +%% Original object ID: 15 0 +20 0 obj +<< + /Length 21 0 R +>> +stream +BT /F1 15 Tf 72 720 Td (Original page 6) Tj ET +endstream +endobj + +21 0 obj +47 +endobj + +xref +0 22 +0000000000 65535 f +0000000052 00000 n +0000000285 00000 n +0000000444 00000 n +0000000699 00000 n +0000000955 00000 n +0000001212 00000 n +0000001469 00000 n +0000001726 00000 n +0000001995 00000 n +0000002098 00000 n +0000002145 00000 n +0000002304 00000 n +0000002408 00000 n +0000002478 00000 n +0000002582 00000 n +0000002653 00000 n +0000002757 00000 n +0000002828 00000 n +0000002932 00000 n +0000003003 00000 n +0000003107 00000 n +trailer << + /Root 1 0 R + /Size 22 + /ID [<31415926535897932384626433832795><31415926535897932384626433832795>] +>> +startxref +3127 +%%EOF diff --git a/qpdf/qtest/qpdf/labels-split-07-11.pdf b/qpdf/qtest/qpdf/labels-split-07-11.pdf new file mode 100644 index 00000000..42120fed --- /dev/null +++ b/qpdf/qtest/qpdf/labels-split-07-11.pdf @@ -0,0 +1,280 @@ +%PDF-1.3 +%¿÷¢þ +%QDF-1.0 + +%% Original object ID: 1 0 +1 0 obj +<< + /PageLabels << + /Nums [ + 0 + << + /S /r + /St 6 + >> + 2 + << + /S /a + /St 16 + >> + ] + >> + /Pages 2 0 R + /Type /Catalog +>> +endobj + +%% Original object ID: 2 0 +2 0 obj +<< + /Count 5 + /Kids [ + 3 0 R + 4 0 R + 5 0 R + 6 0 R + 7 0 R + ] + /Type /Pages +>> +endobj + +%% Page 1 +%% Original object ID: 3 0 +3 0 obj +<< + /Contents 8 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 2 0 R + /Resources << + /Font << + /F1 10 0 R + >> + /ProcSet [ + /PDF + /Text + ] + >> + /Type /Page +>> +endobj + +%% Page 2 +%% Original object ID: 6 0 +4 0 obj +<< + /Contents 11 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 2 0 R + /Resources << + /Font << + /F1 10 0 R + >> + /ProcSet [ + /PDF + /Text + ] + >> + /Type /Page +>> +endobj + +%% Page 3 +%% Original object ID: 8 0 +5 0 obj +<< + /Contents 13 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 2 0 R + /Resources << + /Font << + /F1 10 0 R + >> + /ProcSet [ + /PDF + /Text + ] + >> + /Type /Page +>> +endobj + +%% Page 4 +%% Original object ID: 10 0 +6 0 obj +<< + /Contents 15 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 2 0 R + /Resources << + /Font << + /F1 10 0 R + >> + /ProcSet [ + /PDF + /Text + ] + >> + /Type /Page +>> +endobj + +%% Page 5 +%% Original object ID: 12 0 +7 0 obj +<< + /Contents 17 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 2 0 R + /Resources << + /Font << + /F1 10 0 R + >> + /ProcSet [ + /PDF + /Text + ] + >> + /Type /Page +>> +endobj + +%% Contents for page 1 +%% Original object ID: 4 0 +8 0 obj +<< + /Length 9 0 R +>> +stream +BT /F1 15 Tf 72 720 Td (Original page 7) Tj ET +endstream +endobj + +9 0 obj +47 +endobj + +%% Original object ID: 5 0 +10 0 obj +<< + /BaseFont /Times-Roman + /Encoding /WinAnsiEncoding + /Subtype /Type1 + /Type /Font +>> +endobj + +%% Contents for page 2 +%% Original object ID: 7 0 +11 0 obj +<< + /Length 12 0 R +>> +stream +BT /F1 15 Tf 72 720 Td (Original page 8) Tj ET +endstream +endobj + +12 0 obj +47 +endobj + +%% Contents for page 3 +%% Original object ID: 9 0 +13 0 obj +<< + /Length 14 0 R +>> +stream +BT /F1 15 Tf 72 720 Td (Original page 9) Tj ET +endstream +endobj + +14 0 obj +47 +endobj + +%% Contents for page 4 +%% Original object ID: 11 0 +15 0 obj +<< + /Length 16 0 R +>> +stream +BT /F1 15 Tf 72 720 Td (Original page 10) Tj ET +endstream +endobj + +16 0 obj +48 +endobj + +%% Contents for page 5 +%% Original object ID: 13 0 +17 0 obj +<< + /Length 18 0 R +>> +stream +BT /F1 15 Tf 72 720 Td (Original page 11) Tj ET +endstream +endobj + +18 0 obj +48 +endobj + +xref +0 19 +0000000000 65535 f +0000000052 00000 n +0000000282 00000 n +0000000431 00000 n +0000000686 00000 n +0000000942 00000 n +0000001199 00000 n +0000001456 00000 n +0000001725 00000 n +0000001827 00000 n +0000001873 00000 n +0000002032 00000 n +0000002136 00000 n +0000002206 00000 n +0000002310 00000 n +0000002381 00000 n +0000002486 00000 n +0000002557 00000 n +0000002662 00000 n +trailer << + /Root 1 0 R + /Size 19 + /ID [<31415926535897932384626433832795><31415926535897932384626433832795>] +>> +startxref +2682 +%%EOF diff --git a/qpdf/qtest/qpdf/merge-implicit-ranges.pdf b/qpdf/qtest/qpdf/merge-implicit-ranges.pdf index da523cad..be17bf46 100644 --- a/qpdf/qtest/qpdf/merge-implicit-ranges.pdf +++ b/qpdf/qtest/qpdf/merge-implicit-ranges.pdf @@ -1,7 +1,7 @@ %PDF-1.3 %¿÷¢þ 1 0 obj -<< /Pages 2 0 R /Type /Catalog >> +<< /PageLabels << /Nums [ 0 << /St 1 >> 21 << /P () /St 1 >> 23 << /S /r /St 1 >> 28 << /P () /St 1 >> 30 << /S /r /St 6 >> 32 << /P () /St 1 >> 33 << /S /D /St 2 >> 36 << /S /D /St 6 >> 40 << /P () /St 1 >> 41 << /S /D /St 12 >> 43 << /S /D /St 16059 >> 44 << /S /r /St 50 >> 50 << /S /r /St 54 >> ] >> /Pages 2 0 R /Type /Catalog >> endobj 2 0 obj << /Count 51 /Kids [ 3 0 R 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 34 0 R 35 0 R 36 0 R 37 0 R 38 0 R 39 0 R 40 0 R 41 0 R 42 0 R 43 0 R 44 0 R 45 0 R 46 0 R 47 0 R 48 0 R 49 0 R 50 0 R 51 0 R 52 0 R 53 0 R ] /Type /Pages >> @@ -514,115 +514,115 @@ xref 0 110 0000000000 65535 f 0000000015 00000 n -0000000064 00000 n -0000000468 00000 n -0000000614 00000 n -0000000768 00000 n -0000000922 00000 n -0000001076 00000 n -0000001230 00000 n -0000001384 00000 n -0000001538 00000 n -0000001693 00000 n -0000001848 00000 n -0000002003 00000 n -0000002158 00000 n -0000002313 00000 n -0000002468 00000 n -0000002623 00000 n -0000002778 00000 n -0000002933 00000 n -0000003088 00000 n -0000003243 00000 n -0000003398 00000 n -0000003553 00000 n -0000003708 00000 n -0000003855 00000 n -0000004002 00000 n -0000004149 00000 n -0000004296 00000 n -0000004443 00000 n -0000004590 00000 n -0000004737 00000 n -0000004884 00000 n -0000005031 00000 n -0000005178 00000 n -0000005325 00000 n -0000005472 00000 n -0000005619 00000 n -0000005766 00000 n -0000005913 00000 n -0000006060 00000 n -0000006207 00000 n -0000006354 00000 n -0000006501 00000 n -0000006648 00000 n -0000006796 00000 n -0000006944 00000 n -0000007092 00000 n -0000007240 00000 n -0000007388 00000 n -0000007536 00000 n -0000007684 00000 n -0000007832 00000 n -0000007980 00000 n -0000008128 00000 n -0000008247 00000 n -0000008355 00000 n -0000008386 00000 n -0000008510 00000 n -0000008610 00000 n -0000008734 00000 n -0000008858 00000 n -0000008982 00000 n -0000009106 00000 n -0000009230 00000 n -0000009354 00000 n -0000009478 00000 n -0000009602 00000 n -0000009726 00000 n -0000009851 00000 n -0000009976 00000 n -0000010101 00000 n -0000010226 00000 n -0000010351 00000 n -0000010475 00000 n -0000010600 00000 n -0000010725 00000 n -0000010850 00000 n -0000010975 00000 n -0000011096 00000 n -0000011204 00000 n -0000011235 00000 n -0000011356 00000 n -0000011477 00000 n -0000011598 00000 n -0000011719 00000 n -0000011840 00000 n -0000011961 00000 n -0000012082 00000 n -0000012203 00000 n -0000012324 00000 n -0000012446 00000 n -0000012568 00000 n -0000012690 00000 n -0000012812 00000 n -0000012934 00000 n -0000013056 00000 n -0000013178 00000 n -0000013300 00000 n -0000013422 00000 n -0000013544 00000 n -0000013667 00000 n -0000013790 00000 n -0000013913 00000 n -0000014036 00000 n -0000014158 00000 n -0000014281 00000 n -0000014404 00000 n -0000014527 00000 n -0000014650 00000 n +0000000365 00000 n +0000000769 00000 n +0000000915 00000 n +0000001069 00000 n +0000001223 00000 n +0000001377 00000 n +0000001531 00000 n +0000001685 00000 n +0000001839 00000 n +0000001994 00000 n +0000002149 00000 n +0000002304 00000 n +0000002459 00000 n +0000002614 00000 n +0000002769 00000 n +0000002924 00000 n +0000003079 00000 n +0000003234 00000 n +0000003389 00000 n +0000003544 00000 n +0000003699 00000 n +0000003854 00000 n +0000004009 00000 n +0000004156 00000 n +0000004303 00000 n +0000004450 00000 n +0000004597 00000 n +0000004744 00000 n +0000004891 00000 n +0000005038 00000 n +0000005185 00000 n +0000005332 00000 n +0000005479 00000 n +0000005626 00000 n +0000005773 00000 n +0000005920 00000 n +0000006067 00000 n +0000006214 00000 n +0000006361 00000 n +0000006508 00000 n +0000006655 00000 n +0000006802 00000 n +0000006949 00000 n +0000007097 00000 n +0000007245 00000 n +0000007393 00000 n +0000007541 00000 n +0000007689 00000 n +0000007837 00000 n +0000007985 00000 n +0000008133 00000 n +0000008281 00000 n +0000008429 00000 n +0000008548 00000 n +0000008656 00000 n +0000008687 00000 n +0000008811 00000 n +0000008911 00000 n +0000009035 00000 n +0000009159 00000 n +0000009283 00000 n +0000009407 00000 n +0000009531 00000 n +0000009655 00000 n +0000009779 00000 n +0000009903 00000 n +0000010027 00000 n +0000010152 00000 n +0000010277 00000 n +0000010402 00000 n +0000010527 00000 n +0000010652 00000 n +0000010776 00000 n +0000010901 00000 n +0000011026 00000 n +0000011151 00000 n +0000011276 00000 n +0000011397 00000 n +0000011505 00000 n +0000011536 00000 n +0000011657 00000 n +0000011778 00000 n +0000011899 00000 n +0000012020 00000 n +0000012141 00000 n +0000012262 00000 n +0000012383 00000 n +0000012504 00000 n +0000012625 00000 n +0000012747 00000 n +0000012869 00000 n +0000012991 00000 n +0000013113 00000 n +0000013235 00000 n +0000013357 00000 n +0000013479 00000 n +0000013601 00000 n +0000013723 00000 n +0000013845 00000 n +0000013968 00000 n +0000014091 00000 n +0000014214 00000 n +0000014337 00000 n +0000014459 00000 n +0000014582 00000 n +0000014705 00000 n +0000014828 00000 n +0000014951 00000 n trailer << /Root 1 0 R /Size 110 /ID [<31415926535897932384626433832795><31415926535897932384626433832795>] >> startxref -14773 +15074 %%EOF diff --git a/qpdf/qtest/qpdf/merge-multiple-labels.pdf b/qpdf/qtest/qpdf/merge-multiple-labels.pdf Binary files differnew file mode 100644 index 00000000..d767e760 --- /dev/null +++ b/qpdf/qtest/qpdf/merge-multiple-labels.pdf diff --git a/qpdf/qtest/qpdf/merge-three-files-1.pdf b/qpdf/qtest/qpdf/merge-three-files-1.pdf Binary files differindex 709f21ed..d90b97d7 100644 --- a/qpdf/qtest/qpdf/merge-three-files-1.pdf +++ b/qpdf/qtest/qpdf/merge-three-files-1.pdf diff --git a/qpdf/qtest/qpdf/merge-three-files-2.pdf b/qpdf/qtest/qpdf/merge-three-files-2.pdf Binary files differindex c8b717e6..2d472ac6 100644 --- a/qpdf/qtest/qpdf/merge-three-files-2.pdf +++ b/qpdf/qtest/qpdf/merge-three-files-2.pdf |