From 0dadf17ab705fa2f96f0513278672978d73601ed Mon Sep 17 00:00:00 2001 From: Jay Berkenbilt Date: Mon, 18 Jun 2018 16:38:15 -0400 Subject: [PATCH] Convert command-line and test suite to use page helper classes This provides better test coverage and more useful code for people to read and copy. --- qpdf/pdf_from_scratch.cc | 3 +- qpdf/qpdf.cc | 47 ++++++++++++++++++------------ qpdf/test_driver.cc | 63 ++++++++++++++++++++++++---------------- qpdf/test_large_file.cc | 4 ++- qpdf/test_tokenizer.cc | 7 +++-- 5 files changed, 76 insertions(+), 48 deletions(-) diff --git a/qpdf/pdf_from_scratch.cc b/qpdf/pdf_from_scratch.cc index 967025df..cc57428c 100644 --- a/qpdf/pdf_from_scratch.cc +++ b/qpdf/pdf_from_scratch.cc @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -67,7 +68,7 @@ void runtest(int n) page.replaceKey("/Contents", contents); page.replaceKey("/Resources", resources); - pdf.addPage(page, true); + QPDFPageDocumentHelper(pdf).addPage(page, true); QPDFWriter w(pdf, "a.pdf"); w.setStaticID(true); diff --git a/qpdf/qpdf.cc b/qpdf/qpdf.cc index 2b18400d..bcc5927c 100644 --- a/qpdf/qpdf.cc +++ b/qpdf/qpdf.cc @@ -12,6 +12,8 @@ #include #include +#include +#include #include #include @@ -1810,17 +1812,19 @@ static void do_check(QPDF& pdf, Options& o, int& exit_code) w.write(); // Parse all content streams - std::vector pages = pdf.getAllPages(); + QPDFPageDocumentHelper dh(pdf); + std::vector pages = dh.getAllPages(); DiscardContents discard_contents; int pageno = 0; - for (std::vector::iterator iter = + for (std::vector::iterator iter = pages.begin(); iter != pages.end(); ++iter) { + QPDFPageObjectHelper& page(*iter); ++pageno; try { - (*iter).parsePageContents(&discard_contents); + page.parsePageContents(&discard_contents); } catch (QPDFExc& e) { @@ -1897,17 +1901,18 @@ static void do_show_obj(QPDF& pdf, Options& o, int& exit_code) static void do_show_pages(QPDF& pdf, Options& o) { + QPDFPageDocumentHelper dh(pdf); if (o.show_page_images) { - pdf.pushInheritedAttributesToPage(); + dh.pushInheritedAttributesToPage(); } - std::vector pages = pdf.getAllPages(); + std::vector pages = dh.getAllPages(); int pageno = 0; - for (std::vector::iterator iter = - pages.begin(); + for (std::vector::iterator iter = pages.begin(); iter != pages.end(); ++iter) { - QPDFObjectHandle& page = *iter; + QPDFPageObjectHelper& ph(*iter); + QPDFObjectHandle page = ph.getObjectHandle(); ++pageno; std::cout << "page " << pageno << ": " @@ -1916,7 +1921,7 @@ static void do_show_pages(QPDF& pdf, Options& o) if (o.show_page_images) { std::map images = - page.getPageImages(); + ph.getPageImages(); if (! images.empty()) { std::cout << " images:" << std::endl; @@ -1942,7 +1947,7 @@ static void do_show_pages(QPDF& pdf, Options& o) std::cout << " content:" << std::endl; std::vector content = - page.getPageContents(); + ph.getPageContents(); for (std::vector::iterator iter = content.begin(); iter != content.end(); ++iter) @@ -2013,10 +2018,11 @@ static void do_inspection(QPDF& pdf, Options& o) static void handle_transformations(QPDF& pdf, Options& o) { + QPDFPageDocumentHelper dh(pdf); if (o.coalesce_contents) { - std::vector pages = pdf.getAllPages(); - for (std::vector::iterator iter = pages.begin(); + std::vector pages = dh.getAllPages(); + for (std::vector::iterator iter = pages.begin(); iter != pages.end(); ++iter) { (*iter).coalesceContentStreams(); @@ -2077,12 +2083,13 @@ static void handle_page_specs(QPDF& pdf, Options& o, // without changing their object numbers. This enables other // things in the original file, such as outlines, to continue to // work. - std::vector orig_pages = pdf.getAllPages(); - for (std::vector::iterator iter = + QPDFPageDocumentHelper dh(pdf); + std::vector orig_pages = dh.getAllPages(); + for (std::vector::iterator iter = orig_pages.begin(); iter != orig_pages.end(); ++iter) { - pdf.removePage(*iter); + dh.removePage(*iter); } // Add all the pages from all the files in the order specified. @@ -2102,7 +2109,7 @@ static void handle_page_specs(QPDF& pdf, Options& o, // Pages are specified from 1 but numbered from 0 in the // vector int pageno = *pageno_iter - 1; - pdf.addPage(page_data.orig_pages.at(pageno), false); + dh.addPage(page_data.orig_pages.at(pageno), false); if (page_data.qpdf == &pdf) { // This is a page from the original file. Keep track @@ -2119,15 +2126,17 @@ static void handle_page_specs(QPDF& pdf, Options& o, { if (selected_from_orig.count(pageno) == 0) { - pdf.replaceObject(orig_pages.at(pageno).getObjGen(), - QPDFObjectHandle::newNull()); + pdf.replaceObject( + orig_pages.at(pageno).getObjectHandle().getObjGen(), + QPDFObjectHandle::newNull()); } } } static void handle_rotations(QPDF& pdf, Options& o) { - std::vector pages = pdf.getAllPages(); + QPDFPageDocumentHelper dh(pdf); + std::vector pages = dh.getAllPages(); int npages = static_cast(pages.size()); for (std::map::iterator iter = o.rotations.begin(); diff --git a/qpdf/test_driver.cc b/qpdf/test_driver.cc index 7dd6c595..10958657 100644 --- a/qpdf/test_driver.cc +++ b/qpdf/test_driver.cc @@ -3,6 +3,8 @@ #include +#include +#include #include #include #include @@ -455,12 +457,13 @@ void runtest(int n, char const* filename1, char const* arg2) } else if (n == 5) { - std::vector pages = pdf.getAllPages(); + QPDFPageDocumentHelper dh(pdf); + std::vector pages = dh.getAllPages(); int pageno = 0; - for (std::vector::iterator iter = pages.begin(); + for (std::vector::iterator iter = pages.begin(); iter != pages.end(); ++iter) { - QPDFObjectHandle& page = *iter; + QPDFPageObjectHelper& page(*iter); ++pageno; std::cout << "page " << pageno << ":" << std::endl; @@ -633,11 +636,13 @@ void runtest(int n, char const* filename1, char const* arg2) } else if (n == 10) { - std::vector pages = pdf.getAllPages(); - pages.at(0).addPageContents( + std::vector pages = + QPDFPageDocumentHelper(pdf).getAllPages(); + QPDFPageObjectHelper& ph(pages.at(0)); + ph.addPageContents( QPDFObjectHandle::newStream( &pdf, "BT /F1 12 Tf 72 620 Td (Baked) Tj ET\n"), true); - pages.at(0).addPageContents( + ph.addPageContents( QPDFObjectHandle::newStream( &pdf, "BT /F1 18 Tf 72 520 Td (Mashed) Tj ET\n"), false); @@ -887,6 +892,7 @@ void runtest(int n, char const* filename1, char const* arg2) assert(pages.size() == 10); QPDFObjectHandle page5 = pages.at(5); pdf.removePage(page5); + assert(pages.size() == 9); pdf.addPage(page5, false); assert(pages.size() == 10); assert(pages.back().getObjGen() == page5.getObjGen()); @@ -899,10 +905,11 @@ void runtest(int n, char const* filename1, char const* arg2) else if (n == 19) { // Remove a page and re-insert it in the same file. - std::vector const& pages = pdf.getAllPages(); + QPDFPageDocumentHelper dh(pdf); + std::vector pages = dh.getAllPages(); // Try to insert a page that's already there. - pdf.addPage(pages.at(5), false); + dh.addPage(pages.at(5), false); std::cout << "you can't see this" << std::endl; } else if (n == 20) @@ -932,16 +939,18 @@ void runtest(int n, char const* filename1, char const* arg2) else if (n == 22) { // Try to remove a page we don't have - std::vector const& pages = pdf.getAllPages(); - QPDFObjectHandle page = pages.at(0); - pdf.removePage(page); - pdf.removePage(page); + QPDFPageDocumentHelper dh(pdf); + std::vector pages = dh.getAllPages(); + QPDFPageObjectHelper& page = pages.at(0); + dh.removePage(page); + dh.removePage(page); std::cout << "you can't see this" << std::endl; } else if (n == 23) { - std::vector const& pages = pdf.getAllPages(); - pdf.removePage(pages.back()); + QPDFPageDocumentHelper dh(pdf); + std::vector pages = dh.getAllPages(); + dh.removePage(pages.back()); } else if (n == 24) { @@ -1053,7 +1062,7 @@ void runtest(int n, char const* filename1, char const* arg2) newpdf.processFile(arg2); QPDFObjectHandle qtest = pdf.getTrailer().getKey("/QTest"); QPDFObjectHandle O3 = qtest.getKey("/O3"); - newpdf.addPage(O3, false); + QPDFPageDocumentHelper(newpdf).addPage(O3, false); newpdf.getTrailer().replaceKey( "/QTest", newpdf.copyForeignObject(qtest)); @@ -1073,8 +1082,9 @@ void runtest(int n, char const* filename1, char const* arg2) newpdf.processFile(arg2); QPDFObjectHandle qtest = pdf.getTrailer().getKey("/QTest"); QPDFObjectHandle O3 = qtest.getKey("/O3"); - newpdf.addPage(O3.getKey("/OtherPage"), false); - newpdf.addPage(O3, false); + QPDFPageDocumentHelper dh(newpdf); + dh.addPage(O3.getKey("/OtherPage"), false); + dh.addPage(O3, false); newpdf.getTrailer().replaceKey( "/QTest", newpdf.copyForeignObject(qtest)); @@ -1320,11 +1330,12 @@ void runtest(int n, char const* filename1, char const* arg2) else if (n == 37) { // Parse content streams of all pages - std::vector pages = pdf.getAllPages(); - for (std::vector::iterator iter = pages.begin(); + std::vector pages = + QPDFPageDocumentHelper(pdf).getAllPages(); + for (std::vector::iterator iter = pages.begin(); iter != pages.end(); ++iter) { - QPDFObjectHandle page = *iter; + QPDFPageObjectHelper& page(*iter); ParserCallbacks cb; page.parsePageContents(&cb); } @@ -1341,9 +1352,10 @@ void runtest(int n, char const* filename1, char const* arg2) else if (n == 39) { // Display image filter and color set for each image on each page - std::vector pages = pdf.getAllPages(); + std::vector pages = + QPDFPageDocumentHelper(pdf).getAllPages(); int pageno = 0; - for (std::vector::iterator p_iter = + for (std::vector::iterator p_iter = pages.begin(); p_iter != pages.end(); ++p_iter) { @@ -1378,8 +1390,9 @@ void runtest(int n, char const* filename1, char const* arg2) { // Apply a token filter. This test case is crafted to work // with coalesce.pdf. - std::vector pages = pdf.getAllPages(); - for (std::vector::iterator iter = + std::vector pages = + QPDFPageDocumentHelper(pdf).getAllPages(); + for (std::vector::iterator iter = pages.begin(); iter != pages.end(); ++iter) { @@ -1446,7 +1459,7 @@ void runtest(int n, char const* filename1, char const* arg2) std::cerr << "One error\n"; array.getArrayItem(1).getKey("/K").getArrayItem(0).getStringValue(); // Stream dictionary - QPDFObjectHandle page = pdf.getAllPages()[0]; + QPDFObjectHandle page = pdf.getAllPages().at(0); assert("/QPDFFakeName" == page.getKey("/Contents").getDict().getKey("/Potato").getName()); // Rectangles diff --git a/qpdf/test_large_file.cc b/qpdf/test_large_file.cc index 5e4557c8..ab56bb8a 100644 --- a/qpdf/test_large_file.cc +++ b/qpdf/test_large_file.cc @@ -5,6 +5,7 @@ // I/O. #include +#include #include #include #include @@ -208,6 +209,7 @@ static void create_pdf(char const* filename) mediabox.appendItem(newInteger(612)); mediabox.appendItem(newInteger(792)); + QPDFPageDocumentHelper dh(pdf); for (int pageno = 1; pageno <= npages; ++pageno) { QPDFObjectHandle image = QPDFObjectHandle::newStream(&pdf); @@ -241,7 +243,7 @@ static void create_pdf(char const* filename) page.replaceKey("/Contents", contents); page.replaceKey("/Resources", resources); - pdf.addPage(page, false); + dh.addPage(page, false); } QPDFWriter w(pdf, filename); diff --git a/qpdf/test_tokenizer.cc b/qpdf/test_tokenizer.cc index 955af1ec..9f65281b 100644 --- a/qpdf/test_tokenizer.cc +++ b/qpdf/test_tokenizer.cc @@ -1,4 +1,6 @@ #include +#include +#include #include #include #include @@ -206,9 +208,10 @@ static void process(char const* filename, bool include_ignorable, // Tokenize content streams, skipping inline images QPDF qpdf; qpdf.processFile(filename); - std::vector pages = qpdf.getAllPages(); + std::vector pages = + QPDFPageDocumentHelper(qpdf).getAllPages(); int pageno = 0; - for (std::vector::iterator iter = pages.begin(); + for (std::vector::iterator iter = pages.begin(); iter != pages.end(); ++iter) { ++pageno;