Commit f37d399d825fc70155a3634c26463a24a2e17035
1 parent
6a7d53ad
Add newline-before-endstream option (fixes #103)
Showing
6 changed files
with
41 additions
and
2 deletions
ChangeLog
| 1 | 1 | 2017-07-29 Jay Berkenbilt <ejb@ql.org> |
| 2 | 2 | |
| 3 | + * Add --newline-before-endstream command-line option and | |
| 4 | + setNewlineBeforeEndstream method to QPDFWriter. This forces qpdf | |
| 5 | + to always add a newline before the endstream keyword. It is a | |
| 6 | + necessary but not sufficient condition for PDF/A compliance. Fixes | |
| 7 | + #103. | |
| 8 | + | |
| 3 | 9 | * Handle zlib data errors when decoding streams. Fixes #106. |
| 4 | 10 | |
| 5 | 11 | * Improve handling of files where the "stream" keyword is not | ... | ... |
include/qpdf/QPDFWriter.hh
| ... | ... | @@ -161,6 +161,11 @@ class QPDFWriter |
| 161 | 161 | QPDF_DLL |
| 162 | 162 | void setPreserveUnreferencedObjects(bool); |
| 163 | 163 | |
| 164 | + // Always write a newline before the endstream keyword. This helps | |
| 165 | + // with PDF/A compliance, though it is not sufficient for it. | |
| 166 | + QPDF_DLL | |
| 167 | + void setNewlineBeforeEndstream(bool); | |
| 168 | + | |
| 164 | 169 | // Set the minimum PDF version. If the PDF version of the input |
| 165 | 170 | // file (or previously set minimum version) is less than the |
| 166 | 171 | // version passed to this method, the PDF version of the output |
| ... | ... | @@ -434,6 +439,7 @@ class QPDFWriter |
| 434 | 439 | bool qdf_mode; |
| 435 | 440 | bool precheck_streams; |
| 436 | 441 | bool preserve_unreferenced_objects; |
| 442 | + bool newline_before_endstream; | |
| 437 | 443 | bool static_id; |
| 438 | 444 | bool suppress_original_object_ids; |
| 439 | 445 | bool direct_stream_lengths; | ... | ... |
libqpdf/QPDFWriter.cc
| ... | ... | @@ -59,6 +59,7 @@ QPDFWriter::init() |
| 59 | 59 | qdf_mode = false; |
| 60 | 60 | precheck_streams = false; |
| 61 | 61 | preserve_unreferenced_objects = false; |
| 62 | + newline_before_endstream = false; | |
| 62 | 63 | static_id = false; |
| 63 | 64 | suppress_original_object_ids = false; |
| 64 | 65 | direct_stream_lengths = true; |
| ... | ... | @@ -191,6 +192,12 @@ QPDFWriter::setPreserveUnreferencedObjects(bool val) |
| 191 | 192 | } |
| 192 | 193 | |
| 193 | 194 | void |
| 195 | +QPDFWriter::setNewlineBeforeEndstream(bool val) | |
| 196 | +{ | |
| 197 | + this->newline_before_endstream = val; | |
| 198 | +} | |
| 199 | + | |
| 200 | +void | |
| 194 | 201 | QPDFWriter::setMinimumPDFVersion(std::string const& version) |
| 195 | 202 | { |
| 196 | 203 | setMinimumPDFVersion(version, 0); |
| ... | ... | @@ -1580,7 +1587,7 @@ QPDFWriter::unparseObject(QPDFObjectHandle object, int level, |
| 1580 | 1587 | char last_char = this->pipeline->getLastChar(); |
| 1581 | 1588 | popPipelineStack(); |
| 1582 | 1589 | |
| 1583 | - if (this->qdf_mode) | |
| 1590 | + if (this->qdf_mode || this->newline_before_endstream) | |
| 1584 | 1591 | { |
| 1585 | 1592 | if (last_char != '\n') |
| 1586 | 1593 | { | ... | ... |
qpdf/qpdf.cc
| ... | ... | @@ -204,6 +204,7 @@ familiar with the PDF file format or who are PDF developers.\n\ |
| 204 | 204 | --ignore-xref-streams tells qpdf to ignore any cross-reference streams\n\ |
| 205 | 205 | --precheck-streams precheck ability to decode streams\n\ |
| 206 | 206 | --preserve-unreferenced preserve unreferenced objects\n\ |
| 207 | +--newline-before-endstream always put a newline before endstream\n\ | |
| 207 | 208 | --qdf turns on \"QDF mode\" (below)\n\ |
| 208 | 209 | --min-version=version sets the minimum PDF version of the output file\n\ |
| 209 | 210 | --force-version=version forces this to be the PDF version of the output file\n\ |
| ... | ... | @@ -1032,6 +1033,7 @@ int main(int argc, char* argv[]) |
| 1032 | 1033 | bool qdf_mode = false; |
| 1033 | 1034 | bool precheck_streams = false; |
| 1034 | 1035 | bool preserve_unreferenced_objects = false; |
| 1036 | + bool newline_before_endstream = false; | |
| 1035 | 1037 | std::string min_version; |
| 1036 | 1038 | std::string force_version; |
| 1037 | 1039 | |
| ... | ... | @@ -1225,6 +1227,10 @@ int main(int argc, char* argv[]) |
| 1225 | 1227 | { |
| 1226 | 1228 | preserve_unreferenced_objects = true; |
| 1227 | 1229 | } |
| 1230 | + else if (strcmp(arg, "newline-before-endstream") == 0) | |
| 1231 | + { | |
| 1232 | + newline_before_endstream = true; | |
| 1233 | + } | |
| 1228 | 1234 | else if (strcmp(arg, "min-version") == 0) |
| 1229 | 1235 | { |
| 1230 | 1236 | if (parameter == 0) |
| ... | ... | @@ -1724,6 +1730,10 @@ int main(int argc, char* argv[]) |
| 1724 | 1730 | { |
| 1725 | 1731 | w.setPreserveUnreferencedObjects(true); |
| 1726 | 1732 | } |
| 1733 | + if (newline_before_endstream) | |
| 1734 | + { | |
| 1735 | + w.setNewlineBeforeEndstream(true); | |
| 1736 | + } | |
| 1727 | 1737 | if (normalize_set) |
| 1728 | 1738 | { |
| 1729 | 1739 | w.setContentNormalization(normalize); | ... | ... |
qpdf/qtest/qpdf.test
| ... | ... | @@ -206,7 +206,7 @@ $td->runtest("remove page we don't have", |
| 206 | 206 | show_ntests(); |
| 207 | 207 | # ---------- |
| 208 | 208 | $td->notify("--- Miscellaneous Tests ---"); |
| 209 | -$n_tests += 89; | |
| 209 | +$n_tests += 91; | |
| 210 | 210 | |
| 211 | 211 | $td->runtest("qpdf version", |
| 212 | 212 | {$td->COMMAND => "qpdf --version"}, |
| ... | ... | @@ -618,6 +618,16 @@ $td->runtest("split content stream errors", |
| 618 | 618 | $td->EXIT_STATUS => 3}, |
| 619 | 619 | $td->NORMALIZE_NEWLINES); |
| 620 | 620 | |
| 621 | +$td->runtest("newline before endstream", | |
| 622 | + {$td->COMMAND => | |
| 623 | + "qpdf --static-id --newline-before-endstream" . | |
| 624 | + " minimal.pdf a.pdf"}, | |
| 625 | + {$td->STRING => "", $td->EXIT_STATUS => 0}, | |
| 626 | + $td->NORMALIZE_NEWLINES); | |
| 627 | +$td->runtest("check output", | |
| 628 | + {$td->FILE => "a.pdf"}, | |
| 629 | + {$td->FILE => "newline-before-endstream.pdf"}); | |
| 630 | + | |
| 621 | 631 | |
| 622 | 632 | show_ntests(); |
| 623 | 633 | # ---------- | ... | ... |
qpdf/qtest/qpdf/newline-before-endstream.pdf
0 → 100644
No preview for this file type