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.
This commit is contained in:
Jay Berkenbilt 2018-06-18 16:38:15 -04:00
parent 2e6e1204a5
commit 0dadf17ab7
5 changed files with 76 additions and 48 deletions

View File

@ -4,6 +4,7 @@
#include <qpdf/QTC.hh>
#include <qpdf/QPDFWriter.hh>
#include <qpdf/QPDFObjectHandle.hh>
#include <qpdf/QPDFPageDocumentHelper.hh>
#include <iostream>
#include <stdio.h>
#include <string.h>
@ -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);

View File

@ -12,6 +12,8 @@
#include <qpdf/PointerHolder.hh>
#include <qpdf/QPDF.hh>
#include <qpdf/QPDFPageDocumentHelper.hh>
#include <qpdf/QPDFPageObjectHelper.hh>
#include <qpdf/QPDFExc.hh>
#include <qpdf/QPDFWriter.hh>
@ -1810,17 +1812,19 @@ static void do_check(QPDF& pdf, Options& o, int& exit_code)
w.write();
// Parse all content streams
std::vector<QPDFObjectHandle> pages = pdf.getAllPages();
QPDFPageDocumentHelper dh(pdf);
std::vector<QPDFPageObjectHelper> pages = dh.getAllPages();
DiscardContents discard_contents;
int pageno = 0;
for (std::vector<QPDFObjectHandle>::iterator iter =
for (std::vector<QPDFPageObjectHelper>::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<QPDFObjectHandle> pages = pdf.getAllPages();
std::vector<QPDFPageObjectHelper> pages = dh.getAllPages();
int pageno = 0;
for (std::vector<QPDFObjectHandle>::iterator iter =
pages.begin();
for (std::vector<QPDFPageObjectHelper>::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<std::string, QPDFObjectHandle> 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<QPDFObjectHandle> content =
page.getPageContents();
ph.getPageContents();
for (std::vector<QPDFObjectHandle>::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<QPDFObjectHandle> pages = pdf.getAllPages();
for (std::vector<QPDFObjectHandle>::iterator iter = pages.begin();
std::vector<QPDFPageObjectHelper> pages = dh.getAllPages();
for (std::vector<QPDFPageObjectHelper>::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<QPDFObjectHandle> orig_pages = pdf.getAllPages();
for (std::vector<QPDFObjectHandle>::iterator iter =
QPDFPageDocumentHelper dh(pdf);
std::vector<QPDFPageObjectHelper> orig_pages = dh.getAllPages();
for (std::vector<QPDFPageObjectHelper>::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<QPDFObjectHandle> pages = pdf.getAllPages();
QPDFPageDocumentHelper dh(pdf);
std::vector<QPDFPageObjectHelper> pages = dh.getAllPages();
int npages = static_cast<int>(pages.size());
for (std::map<std::string, RotationSpec>::iterator iter =
o.rotations.begin();

View File

@ -3,6 +3,8 @@
#include <qpdf/QPDF.hh>
#include <qpdf/QPDFPageDocumentHelper.hh>
#include <qpdf/QPDFPageObjectHelper.hh>
#include <qpdf/QUtil.hh>
#include <qpdf/QTC.hh>
#include <qpdf/Pl_StdioFile.hh>
@ -455,12 +457,13 @@ void runtest(int n, char const* filename1, char const* arg2)
}
else if (n == 5)
{
std::vector<QPDFObjectHandle> pages = pdf.getAllPages();
QPDFPageDocumentHelper dh(pdf);
std::vector<QPDFPageObjectHelper> pages = dh.getAllPages();
int pageno = 0;
for (std::vector<QPDFObjectHandle>::iterator iter = pages.begin();
for (std::vector<QPDFPageObjectHelper>::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<QPDFObjectHandle> pages = pdf.getAllPages();
pages.at(0).addPageContents(
std::vector<QPDFPageObjectHelper> 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<QPDFObjectHandle> const& pages = pdf.getAllPages();
QPDFPageDocumentHelper dh(pdf);
std::vector<QPDFPageObjectHelper> 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<QPDFObjectHandle> const& pages = pdf.getAllPages();
QPDFObjectHandle page = pages.at(0);
pdf.removePage(page);
pdf.removePage(page);
QPDFPageDocumentHelper dh(pdf);
std::vector<QPDFPageObjectHelper> 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<QPDFObjectHandle> const& pages = pdf.getAllPages();
pdf.removePage(pages.back());
QPDFPageDocumentHelper dh(pdf);
std::vector<QPDFPageObjectHelper> 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<QPDFObjectHandle> pages = pdf.getAllPages();
for (std::vector<QPDFObjectHandle>::iterator iter = pages.begin();
std::vector<QPDFPageObjectHelper> pages =
QPDFPageDocumentHelper(pdf).getAllPages();
for (std::vector<QPDFPageObjectHelper>::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<QPDFObjectHandle> pages = pdf.getAllPages();
std::vector<QPDFPageObjectHelper> pages =
QPDFPageDocumentHelper(pdf).getAllPages();
int pageno = 0;
for (std::vector<QPDFObjectHandle>::iterator p_iter =
for (std::vector<QPDFPageObjectHelper>::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<QPDFObjectHandle> pages = pdf.getAllPages();
for (std::vector<QPDFObjectHandle>::iterator iter =
std::vector<QPDFPageObjectHelper> pages =
QPDFPageDocumentHelper(pdf).getAllPages();
for (std::vector<QPDFPageObjectHelper>::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

View File

@ -5,6 +5,7 @@
// I/O.
#include <qpdf/QPDF.hh>
#include <qpdf/QPDFPageDocumentHelper.hh>
#include <qpdf/QPDFWriter.hh>
#include <qpdf/QPDFObjectHandle.hh>
#include <qpdf/QUtil.hh>
@ -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);

View File

@ -1,4 +1,6 @@
#include <qpdf/QPDFTokenizer.hh>
#include <qpdf/QPDFPageDocumentHelper.hh>
#include <qpdf/QPDFPageObjectHelper.hh>
#include <qpdf/QUtil.hh>
#include <qpdf/FileInputSource.hh>
#include <qpdf/BufferInputSource.hh>
@ -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<QPDFObjectHandle> pages = qpdf.getAllPages();
std::vector<QPDFPageObjectHelper> pages =
QPDFPageDocumentHelper(qpdf).getAllPages();
int pageno = 0;
for (std::vector<QPDFObjectHandle>::iterator iter = pages.begin();
for (std::vector<QPDFPageObjectHelper>::iterator iter = pages.begin();
iter != pages.end(); ++iter)
{
++pageno;