From 654c0e8caf5e75119534de5d93d1ee28bd13325a Mon Sep 17 00:00:00 2001 From: Jay Berkenbilt Date: Sat, 12 Jan 2019 09:14:20 -0500 Subject: [PATCH] Allow adding the same page more than once in --pages (fixes #272) --- ChangeLog | 16 + include/qpdf/QPDF.hh | 10 + include/qpdf/QPDFPageObjectHelper.hh | 13 + libqpdf/QPDF.cc | 6 + libqpdf/QPDFPageObjectHelper.cc | 15 + manual/qpdf-manual.xml | 15 +- qpdf/qpdf.cc | 16 +- qpdf/qpdf.testcov | 1 + qpdf/qtest/qpdf.test | 24 +- qpdf/qtest/qpdf/duplicate-pages.pdf | 335 ++++++++++++++++++ .../qpdf/really-shared-images-pages-out.pdf | 288 +++++++++++++++ 11 files changed, 727 insertions(+), 12 deletions(-) create mode 100644 qpdf/qtest/qpdf/duplicate-pages.pdf create mode 100644 qpdf/qtest/qpdf/really-shared-images-pages-out.pdf diff --git a/ChangeLog b/ChangeLog index d74e9b01..8edf51c3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,21 @@ 2019-01-12 Jay Berkenbilt + * In the --pages option, allow the same page to be specified more + than once. You can now do "--pages A.pdf 1,1 --" or + "--pages A.pdf 1 A.pdf 1" instead of having to use two different + paths to specify A.pdf. Fixes #272. + + * Add QPDFPageObjectHelper::shallowCopyPage(). This method creates + a new page object that is a "shallow copy" of the given page as + described in the comments in QPDFPageObjectHelper. The resulting + object has not been added anywhere but is ready to be passed to + QPDFPageDocumentHelper::addPage of its own QPDF or another QPDF + object. + + * Add QPDF::getUniqueId() method to return an identifier that is + intended to be unique within the scope of all QPDF objects created + by the calling application in a single run. + * In --pages, allow "." as a replacement for the current input file, making it possible to say "qpdf A.pdf --pages . 1-3 --" instead of having to repeat the input filename. diff --git a/include/qpdf/QPDF.hh b/include/qpdf/QPDF.hh index 8a79b6a3..ef0f0eb7 100644 --- a/include/qpdf/QPDF.hh +++ b/include/qpdf/QPDF.hh @@ -203,6 +203,16 @@ class QPDF QPDF_DLL std::vector getWarnings(); + // Return an application-scoped unique ID for this QPDF object. + // This is not a globally unique ID. It is constructing using a + // timestamp and a random number and is intended to be unique + // among QPDF objects that are created by a single run of an + // application. While it's very likely that these are actually + // globally unique, it is not recommended to use them for + // long-term purposes. + QPDF_DLL + unsigned long long getUniqueId() const; + QPDF_DLL std::string getFilename() const; QPDF_DLL diff --git a/include/qpdf/QPDFPageObjectHelper.hh b/include/qpdf/QPDFPageObjectHelper.hh index 5238fa30..e17453fa 100644 --- a/include/qpdf/QPDFPageObjectHelper.hh +++ b/include/qpdf/QPDFPageObjectHelper.hh @@ -140,6 +140,19 @@ class QPDFPageObjectHelper: public QPDFObjectHelper QPDF_DLL void removeUnreferencedResources(); + // Return a new QPDFPageDocumentHelper that is a duplicate of the + // page. The returned object is an indirect object that is ready + // to be inserted into the same or a different QPDF object using + // any of the addPage methods in QPDFPageDocumentHelper or QPDF. + // Without calling one of those methods, the page will not be + // added anywhere. Thew new page object shares all content streams + // and indirect objet resources with the original page, so if you + // are going to modify the contents or other aspects of the page, + // you will need to handling copying of the component parts + // separately. + QPDF_DLL + QPDFPageObjectHelper shallowCopyPage(); + private: class Members { diff --git a/libqpdf/QPDF.cc b/libqpdf/QPDF.cc index 95ae9cab..0dbce669 100644 --- a/libqpdf/QPDF.cc +++ b/libqpdf/QPDF.cc @@ -2470,6 +2470,12 @@ QPDF::swapObjects(int objid1, int generation1, int objid2, int generation2) this->m->obj_cache[og2] = t; } +unsigned long long +QPDF::getUniqueId() const +{ + return this->m->unique_id; +} + std::string QPDF::getFilename() const { diff --git a/libqpdf/QPDFPageObjectHelper.cc b/libqpdf/QPDFPageObjectHelper.cc index 4093622d..611f33ea 100644 --- a/libqpdf/QPDFPageObjectHelper.cc +++ b/libqpdf/QPDFPageObjectHelper.cc @@ -1,5 +1,6 @@ #include #include +#include QPDFPageObjectHelper::Members::~Members() { @@ -167,3 +168,17 @@ QPDFPageObjectHelper::removeUnreferencedResources() } } } + +QPDFPageObjectHelper +QPDFPageObjectHelper::shallowCopyPage() +{ + QPDF* qpdf = this->oh.getOwningQPDF(); + if (! qpdf) + { + throw std::runtime_error( + "QPDFPageObjectHelper::shallowCopyPage" + " called with a direct objet"); + } + QPDFObjectHandle new_page = this->oh.shallowCopy(); + return QPDFPageObjectHelper(qpdf->makeIndirectObject(new_page)); +} diff --git a/manual/qpdf-manual.xml b/manual/qpdf-manual.xml index f7c528b7..034111c2 100644 --- a/manual/qpdf-manual.xml +++ b/manual/qpdf-manual.xml @@ -982,15 +982,6 @@ make easily combine all pages in a set of files with a command like qpdf --empty out.pdf --pages *.pdf --. - - It is not presently possible to specify the same page from the - same file directly more than once, but you can make this work by - specifying two different paths to the same file (such as by - putting ./ somewhere in the path). This can - also be used if you want to repeat a page from one of the input - files in the output file. This may be made more convenient in a - future version of qpdf if there is enough demand for this feature. - The page range is a set of numbers separated by commas, ranges of numbers separated dashes, or combinations of those. The character @@ -1112,6 +1103,12 @@ outfile.pdf are all corner cases that most users should hopefully never have to be bothered with. + + Prior to version 8.4, it was not possible to specify the same page + from the same file directly more than once, and the workaround of + specifying the same file in more than one way was required. + Version 8.4 removes this limitation. + Advanced Parsing Options diff --git a/qpdf/qpdf.cc b/qpdf/qpdf.cc index db3193d5..81ccdd0f 100644 --- a/qpdf/qpdf.cc +++ b/qpdf/qpdf.cc @@ -3731,6 +3731,7 @@ static void handle_page_specs(QPDF& pdf, Options& o) std::map page_spec_cfis; page_spec_qpdfs[o.infilename] = &pdf; std::vector parsed_specs; + std::map > copied_pages; for (std::vector::iterator iter = o.page_specs.begin(); iter != o.page_specs.end(); ++iter) { @@ -3905,7 +3906,20 @@ static void handle_page_specs(QPDF& pdf, Options& o) int pageno = *pageno_iter - 1; pldh.getLabelsForPageRange(pageno, pageno, out_pageno, new_labels); - dh.addPage(page_data.orig_pages.at(pageno), false); + QPDFPageObjectHelper to_copy = page_data.orig_pages.at(pageno); + QPDFObjGen to_copy_og = to_copy.getObjectHandle().getObjGen(); + unsigned long long from_uuid = page_data.qpdf->getUniqueId(); + if (copied_pages[from_uuid].count(to_copy_og)) + { + QTC::TC("qpdf", "qpdf copy same page more than once", + (page_data.qpdf == &pdf) ? 0 : 1); + to_copy = to_copy.shallowCopyPage(); + } + else + { + copied_pages[from_uuid].insert(to_copy_og); + } + dh.addPage(to_copy, false); if (page_data.qpdf == &pdf) { // This is a page from the original file. Keep track diff --git a/qpdf/qpdf.testcov b/qpdf/qpdf.testcov index 43f5c5a7..58f2cdca 100644 --- a/qpdf/qpdf.testcov +++ b/qpdf/qpdf.testcov @@ -411,3 +411,4 @@ QPDF pipe foreign encrypted stream 0 QPDF copy foreign stream with provider 0 QPDF copy foreign stream with buffer 0 QPDF immediate copy stream data 0 +qpdf copy same page more than once 1 diff --git a/qpdf/qtest/qpdf.test b/qpdf/qtest/qpdf.test index b45f32a1..15b73e5f 100644 --- a/qpdf/qtest/qpdf.test +++ b/qpdf/qtest/qpdf.test @@ -1624,7 +1624,7 @@ foreach my $f (qw(screen print)) show_ntests(); # ---------- $td->notify("--- Merging and Splitting ---"); -$n_tests += 18; +$n_tests += 22; # Select pages from the same file multiple times including selecting # twice from an encrypted file and specifying the password only the @@ -1692,7 +1692,7 @@ $td->runtest("check output", {$td->FILE => "a.pdf"}, {$td->FILE => "merge-multiple-labels.pdf"}); -$td->runtest("split with shared resources", # QXXXQ +$td->runtest("split with shared resources", {$td->COMMAND => "qpdf --qdf --static-id" . " shared-images.pdf --pages . 1,3" . @@ -1702,6 +1702,16 @@ $td->runtest("check output", {$td->FILE => "a.pdf"}, {$td->FILE => "shared-images-pages-out.pdf"}); +$td->runtest("split with really shared resources", + {$td->COMMAND => + "qpdf --qdf --static-id" . + " shared-images.pdf --pages . 1,3" . + " . 1,2 -- a.pdf"}, + {$td->STRING => "", $td->EXIT_STATUS => 0}); +$td->runtest("check output", + {$td->FILE => "a.pdf"}, + {$td->FILE => "really-shared-images-pages-out.pdf"}); + $td->runtest("shared resources relevant errors", {$td->COMMAND => "qpdf --qdf --static-id" . @@ -1733,6 +1743,16 @@ $td->runtest("check output", {$td->FILE => "a.pdf"}, {$td->FILE => "shared-images-errors-1-3-out.pdf"}); +$td->runtest("duplicate pages", + {$td->COMMAND => + "qpdf --qdf --static-id 11-pages-with-labels.pdf" . + " --pages . 6,5,6 . 5 minimal.pdf 1,1 minimal.pdf 1 --" . + " a.pdf"}, + {$td->STRING => "", $td->EXIT_STATUS => 0}); +$td->runtest("check output", + {$td->FILE => "a.pdf"}, + {$td->FILE => "duplicate-pages.pdf"}); + show_ntests(); # ---------- $td->notify("--- Collating ---"); diff --git a/qpdf/qtest/qpdf/duplicate-pages.pdf b/qpdf/qtest/qpdf/duplicate-pages.pdf new file mode 100644 index 00000000..7119ef58 --- /dev/null +++ b/qpdf/qtest/qpdf/duplicate-pages.pdf @@ -0,0 +1,335 @@ +%PDF-1.4 +%¿÷¢þ +%QDF-1.0 + +%% Original object ID: 1 0 +1 0 obj +<< + /PageLabels << + /Nums [ + 0 + << + /S /r + /St 5 + >> + 1 + << + /S /r + /St 4 + >> + 3 + << + /S /r + /St 4 + >> + 4 + << + /St 5 + >> + ] + >> + /Pages 3 0 R + /Type /Catalog +>> +endobj + +%% Original object ID: 2 0 +2 0 obj +<< + /CreationDate (D:20120721200217) + /Producer (Apex PDFWriter) +>> +endobj + +%% Original object ID: 3 0 +3 0 obj +<< + /Count 7 + /Kids [ + 4 0 R + 5 0 R + 6 0 R + 7 0 R + 8 0 R + 9 0 R + 10 0 R + ] + /Type /Pages +>> +endobj + +%% Page 1 +%% Original object ID: 9 0 +4 0 obj +<< + /Contents 11 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 3 0 R + /Resources << + /Font << + /F1 13 0 R + >> + /ProcSet [ + /PDF + /Text + ] + >> + /Type /Page +>> +endobj + +%% Page 2 +%% Original object ID: 8 0 +5 0 obj +<< + /Contents 14 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 3 0 R + /Resources << + /Font << + /F1 13 0 R + >> + /ProcSet [ + /PDF + /Text + ] + >> + /Type /Page +>> +endobj + +%% Page 3 +%% Original object ID: 27 0 +6 0 obj +<< + /Contents 11 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 3 0 R + /Resources << + /Font << + /F1 13 0 R + >> + /ProcSet [ + /PDF + /Text + ] + >> + /Type /Page +>> +endobj + +%% Page 4 +%% Original object ID: 28 0 +7 0 obj +<< + /Contents 14 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 3 0 R + /Resources << + /Font << + /F1 13 0 R + >> + /ProcSet [ + /PDF + /Text + ] + >> + /Type /Page +>> +endobj + +%% Page 5 +%% Original object ID: 29 0 +8 0 obj +<< + /Contents 16 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 3 0 R + /Resources << + /Font << + /F1 18 0 R + >> + /ProcSet 19 0 R + >> + /Type /Page +>> +endobj + +%% Page 6 +%% Original object ID: 33 0 +9 0 obj +<< + /Contents 16 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 3 0 R + /Resources << + /Font << + /F1 18 0 R + >> + /ProcSet 19 0 R + >> + /Type /Page +>> +endobj + +%% Page 7 +%% Original object ID: 34 0 +10 0 obj +<< + /Contents 16 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 3 0 R + /Resources << + /Font << + /F1 18 0 R + >> + /ProcSet 19 0 R + >> + /Type /Page +>> +endobj + +%% Contents for page 3 +%% Original object ID: 21 0 +11 0 obj +<< + /Length 12 0 R +>> +stream +BT /F1 15 Tf 72 720 Td (Original page 6) Tj ET +endstream +endobj + +12 0 obj +47 +endobj + +%% Original object ID: 16 0 +13 0 obj +<< + /BaseFont /Times-Roman + /Encoding /WinAnsiEncoding + /Subtype /Type1 + /Type /Font +>> +endobj + +%% Contents for page 4 +%% Original object ID: 20 0 +14 0 obj +<< + /Length 15 0 R +>> +stream +BT /F1 15 Tf 72 720 Td (Original page 5) Tj ET +endstream +endobj + +15 0 obj +47 +endobj + +%% Contents for page 7 +%% Original object ID: 30 0 +16 0 obj +<< + /Length 17 0 R +>> +stream +BT + /F1 24 Tf + 72 720 Td + (Potato) Tj +ET +endstream +endobj + +17 0 obj +44 +endobj + +%% Original object ID: 31 0 +18 0 obj +<< + /BaseFont /Helvetica + /Encoding /WinAnsiEncoding + /Name /F1 + /Subtype /Type1 + /Type /Font +>> +endobj + +%% Original object ID: 32 0 +19 0 obj +[ + /PDF + /Text +] +endobj + +xref +0 20 +0000000000 65535 f +0000000052 00000 n +0000000375 00000 n +0000000488 00000 n +0000000658 00000 n +0000000914 00000 n +0000001171 00000 n +0000001428 00000 n +0000001685 00000 n +0000001918 00000 n +0000002151 00000 n +0000002398 00000 n +0000002502 00000 n +0000002550 00000 n +0000002710 00000 n +0000002814 00000 n +0000002885 00000 n +0000002986 00000 n +0000003034 00000 n +0000003181 00000 n +trailer << + /Info 2 0 R + /Root 1 0 R + /Size 20 + /ID [<31415926535897932384626433832795>] +>> +startxref +3217 +%%EOF diff --git a/qpdf/qtest/qpdf/really-shared-images-pages-out.pdf b/qpdf/qtest/qpdf/really-shared-images-pages-out.pdf new file mode 100644 index 00000000..616532aa --- /dev/null +++ b/qpdf/qtest/qpdf/really-shared-images-pages-out.pdf @@ -0,0 +1,288 @@ +%PDF-1.3 +%¿÷¢þ +%QDF-1.0 + +%% Original object ID: 1 0 +1 0 obj +<< + /Pages 2 0 R + /Type /Catalog +>> +endobj + +%% Original object ID: 2 0 +2 0 obj +<< + /Count 4 + /Kids [ + 3 0 R + 4 0 R + 5 0 R + 6 0 R + ] + /Type /Pages +>> +endobj + +%% Page 1 +%% Original object ID: 3 0 +3 0 obj +<< + /Contents 7 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 2 0 R + /Resources << + /Font << + /F1 9 0 R + >> + /ProcSet 10 0 R + /XObject << + /Im1 11 0 R + >> + >> + /Type /Page +>> +endobj + +%% Page 2 +%% Original object ID: 5 0 +4 0 obj +<< + /Contents 13 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 2 0 R + /Resources << + /Font << + /F1 9 0 R + >> + /ProcSet 10 0 R + /XObject << + /Im3 15 0 R + >> + >> + /Type /Page +>> +endobj + +%% Page 3 +%% Original object ID: 56 0 +5 0 obj +<< + /Contents 7 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 2 0 R + /Resources << + /Font << + /F1 9 0 R + >> + /ProcSet 10 0 R + /XObject << + /Im1 11 0 R + >> + >> + /Type /Page +>> +endobj + +%% Page 4 +%% Original object ID: 4 0 +6 0 obj +<< + /Contents 17 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 2 0 R + /Resources << + /Font << + /F1 9 0 R + >> + /ProcSet 10 0 R + /XObject << + /Im2 19 0 R + >> + >> + /Type /Page +>> +endobj + +%% Contents for page 3 +%% Original object ID: 13 0 +7 0 obj +<< + /Length 8 0 R +>> +stream +BT /F1 24 Tf 72 720 Td (page 1) Tj ET +q 468 0 0 468 72 72 cm /Im1 Do Q +endstream +endobj + +8 0 obj +71 +endobj + +%% Original object ID: 15 0 +9 0 obj +<< + /BaseFont /Helvetica + /Encoding /WinAnsiEncoding + /Name /F1 + /Subtype /Type1 + /Type /Font +>> +endobj + +%% Original object ID: 16 0 +10 0 obj +[ + /PDF + /Text + /ImageC +] +endobj + +%% Original object ID: 17 0 +11 0 obj +<< + /BitsPerComponent 8 + /ColorSpace /DeviceGray + /Height 50 + /Subtype /Image + /Type /XObject + /Width 50 + /Length 12 0 R +>> +stream +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀ +endstream +endobj + +%QDF: ignore_newline +12 0 obj +2500 +endobj + +%% Contents for page 2 +%% Original object ID: 23 0 +13 0 obj +<< + /Length 14 0 R +>> +stream +BT /F1 24 Tf 72 720 Td (page 3) Tj ET +q 468 0 0 468 72 72 cm /Im3 Do Q +endstream +endobj + +14 0 obj +71 +endobj + +%% Original object ID: 25 0 +15 0 obj +<< + /BitsPerComponent 8 + /ColorSpace /DeviceGray + /Height 50 + /Subtype /Image + /Type /XObject + /Width 50 + /Length 16 0 R +>> +stream +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀ +endstream +endobj + +%QDF: ignore_newline +16 0 obj +2500 +endobj + +%% Contents for page 4 +%% Original object ID: 19 0 +17 0 obj +<< + /Length 18 0 R +>> +stream +BT /F1 24 Tf 72 720 Td (page 2) Tj ET +q 468 0 0 468 72 72 cm /Im2 Do Q +endstream +endobj + +18 0 obj +71 +endobj + +%% Original object ID: 21 0 +19 0 obj +<< + /BitsPerComponent 8 + /ColorSpace /DeviceGray + /Height 50 + /Subtype /Image + /Type /XObject + /Width 50 + /Length 20 0 R +>> +stream +@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀ@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ +endstream +endobj + +%QDF: ignore_newline +20 0 obj +2500 +endobj + +xref +0 21 +0000000000 65535 f +0000000052 00000 n +0000000133 00000 n +0000000272 00000 n +0000000543 00000 n +0000000816 00000 n +0000001087 00000 n +0000001373 00000 n +0000001499 00000 n +0000001546 00000 n +0000001692 00000 n +0000001766 00000 n +0000004453 00000 n +0000004526 00000 n +0000004654 00000 n +0000004702 00000 n +0000007389 00000 n +0000007462 00000 n +0000007590 00000 n +0000007638 00000 n +0000010325 00000 n +trailer << + /Root 1 0 R + /Size 21 + /ID [<31415926535897932384626433832795><31415926535897932384626433832795>] +>> +startxref +10347 +%%EOF