Add QPDFWriter::setExtraHeaderText

This commit is contained in:
Jay Berkenbilt 2012-09-06 15:30:13 -04:00
parent fc4c82a950
commit c1627d0438
11 changed files with 102 additions and 2 deletions

View File

@ -1,5 +1,11 @@
2012-09-06 Jay Berkenbilt <ejb@ql.org>
* Add new method QPDFWriter::setExtraHeaderText to add extra text,
such as application-specific comments, to near the beginning of a
PDF file. For linearized files, this appears after the
linearization parameter dictionary. For non-linearized files, it
appears right after the PDF header and non-ASCII comment.
* Make it possible to write the same QPDF object with two
different QPDFWriter objects that have both called
setLinearization(true) by making private method

View File

@ -163,6 +163,18 @@ class QPDFWriter
QPDF_DLL
void forcePDFVersion(std::string const&);
// Provide additional text to insert in the PDF file somewhere
// near the beginning of the file. This can be used to add
// comments to the beginning of a PDF file, for example, if those
// comments are to be consumed by some other application. No
// checks are performed to ensure that the text inserted here is
// valid PDF. If you want to insert multiline comments, you will
// need to include \n in the string yourself and start each line
// with %. An extra newline will be appended if one is not
// already present at the end of your text.
QPDF_DLL
void setExtraHeaderText(std::string const&);
// Cause a static /ID value to be generated. Use only in test
// suites.
QPDF_DLL
@ -354,6 +366,7 @@ class QPDFWriter
std::string id2; // trailer dictionary
std::string min_pdf_version;
std::string forced_pdf_version;
std::string extra_header_text;
int encryption_dict_objid;
std::string cur_data_key;
std::list<PointerHolder<Pipeline> > to_delete;

View File

@ -195,6 +195,22 @@ QPDFWriter::forcePDFVersion(std::string const& version)
this->forced_pdf_version = version;
}
void
QPDFWriter::setExtraHeaderText(std::string const& text)
{
this->extra_header_text = text;
if ((this->extra_header_text.length() > 0) &&
(*(this->extra_header_text.rbegin()) != '\n'))
{
QTC::TC("qpdf", "QPDFWriter extra header text add newline");
this->extra_header_text += "\n";
}
else
{
QTC::TC("qpdf", "QPDFWriter extra header text no newline");
}
}
void
QPDFWriter::setStaticID(bool val)
{
@ -1832,6 +1848,12 @@ QPDFWriter::writeHeader()
// it really should be treated as binary.
writeString("\n%\xbf\xf7\xa2\xfe\n");
writeStringQDF("%QDF-1.0\n\n");
// Note: do not write extra header text here. Linearized PDFs
// must include the entire linearization parameter dictionary
// within the first 1024 characters of the PDF file, so for
// linearized files, we have to write extra header text after the
// linearization parameter dictionary.
}
void
@ -2189,7 +2211,9 @@ QPDFWriter::writeLinearized()
// space to write real dictionary. 200 characters is enough
// space if all numerical values in the parameter dictionary
// that contain offsets are 20 digits long plus a few extra
// characters for safety.
// characters for safety. The entire linearization parameter
// dictionary must appear within the first 1024 characters of
// the file.
qpdf_offset_t pos = this->pipeline->getCount();
openObject(lindict_id);
@ -2225,6 +2249,10 @@ QPDFWriter::writeLinearized()
writePad(spaces);
writeString("\n");
// If the user supplied any additional header text, write it
// here after the linearization parameter dictionary.
writeString(this->extra_header_text);
// Part 3: first page cross reference table and trailer.
qpdf_offset_t first_xref_offset = this->pipeline->getCount();
@ -2396,6 +2424,7 @@ QPDFWriter::writeStandard()
// Start writing
writeHeader();
writeString(this->extra_header_text);
// Put root first on queue.
QPDFObjectHandle trailer = pdf.getTrailer();

View File

@ -240,3 +240,5 @@ QPDFObjectHandle trailing data in parse 0
qpdf pages encryption password 0
QPDF_Tokenizer EOF reading token 0
QPDF_Tokenizer EOF reading appendable token 0
QPDFWriter extra header text no newline 0
QPDFWriter extra header text add newline 0

View File

@ -149,7 +149,7 @@ $td->runtest("remove page we don't have",
$td->NORMALIZE_NEWLINES);
# ----------
$td->notify("--- Miscellaneous Tests ---");
$n_tests += 48;
$n_tests += 53;
$td->runtest("qpdf version",
{$td->COMMAND => "qpdf --version"},
@ -387,6 +387,22 @@ $td->runtest("EOF reading token",
{$td->COMMAND => "qpdf --check eof-reading-token.pdf"},
{$td->FILE => "eof-reading-token.out", $td->EXIT_STATUS => 0},
$td->NORMALIZE_NEWLINES);
$td->runtest("extra header text",
{$td->COMMAND => "test_driver 32 minimal.pdf"},
{$td->FILE => "test-32.out", $td->EXIT_STATUS => 0},
$td->NORMALIZE_NEWLINES);
$td->runtest("check output",
{$td->FILE => "a.pdf"},
{$td->FILE => "extra-header-no-newline.pdf"});
$td->runtest("check output",
{$td->FILE => "b.pdf"},
{$td->FILE => "extra-header-lin-no-newline.pdf"});
$td->runtest("check output",
{$td->FILE => "c.pdf"},
{$td->FILE => "extra-header-newline.pdf"});
$td->runtest("check output",
{$td->FILE => "d.pdf"},
{$td->FILE => "extra-header-lin-newline.pdf"});
show_ntests();
# ----------

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,13 @@
file: a.pdf
linearized: no
newline: no
file: b.pdf
linearized: yes
newline: no
file: c.pdf
linearized: no
newline: yes
file: d.pdf
linearized: yes
newline: yes
test 32 done

View File

@ -1091,6 +1091,27 @@ void runtest(int n, char const* filename1, char const* filename2)
<< std::endl;
}
}
else if (n == 32)
{
// Extra header text
char const* filenames[] = {"a.pdf", "b.pdf", "c.pdf", "d.pdf"};
for (int i = 0; i < 4; ++i)
{
bool linearized = ((i & 1) != 0);
bool newline = ((i & 2) != 0);
QPDFWriter w(pdf, filenames[i]);
w.setStaticID(true);
std::cout
<< "file: " << filenames[i] << std::endl
<< "linearized: " << (linearized ? "yes" : "no") << std::endl
<< "newline: " << (newline ? "yes" : "no") << std::endl;
w.setLinearization(linearized);
w.setExtraHeaderText(newline
? "%% Comment with newline\n"
: "%% Comment\n% No newline");
w.write();
}
}
else
{
throw std::runtime_error(std::string("invalid test ") +