From 397b097c469db89a49e5a6c2035a0beee2e4d117 Mon Sep 17 00:00:00 2001 From: Jay Berkenbilt Date: Thu, 21 Jun 2018 15:00:00 -0400 Subject: [PATCH] Allow setting a form field's value --- ChangeLog | 5 +++ include/qpdf/QPDFAcroFormDocumentHelper.hh | 17 +++++++ include/qpdf/QPDFFormFieldObjectHelper.hh | 23 ++++++++++ libqpdf/QPDFAcroFormDocumentHelper.cc | 35 +++++++++++++++ libqpdf/QPDFFormFieldObjectHelper.cc | 42 ++++++++++++++++++ qpdf/qtest/qpdf.test | 11 ++++- .../qpdf/form-no-need-appearances-filled.pdf | Bin 0 -> 12686 bytes qpdf/qtest/qpdf/form-no-need-appearances.out | 3 ++ qpdf/qtest/qpdf/form-no-need-appearances.pdf | Bin 0 -> 12572 bytes qpdf/test_driver.cc | 28 ++++++++++++ 10 files changed, 163 insertions(+), 1 deletion(-) create mode 100644 qpdf/qtest/qpdf/form-no-need-appearances-filled.pdf create mode 100644 qpdf/qtest/qpdf/form-no-need-appearances.out create mode 100644 qpdf/qtest/qpdf/form-no-need-appearances.pdf diff --git a/ChangeLog b/ChangeLog index e27b680d..3d593dff 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,10 @@ 2018-06-21 Jay Berkenbilt + * Added methods QPDFAcroFormDocumentHelper::setNeedAppearances and + added methods to QPDFFormFieldObjectHelper to set a field's value, + optionally updating the document to indicate that appearance + streams need to be regenerated. + * Added QPDFObject::newUnicodeString and QPDFObject::unparseBinary to allow for more convenient creation of strings that are explicitly encoded in UTF-16 BE. This is useful for creating diff --git a/include/qpdf/QPDFAcroFormDocumentHelper.hh b/include/qpdf/QPDFAcroFormDocumentHelper.hh index d786fff4..2aa0d377 100644 --- a/include/qpdf/QPDFAcroFormDocumentHelper.hh +++ b/include/qpdf/QPDFAcroFormDocumentHelper.hh @@ -135,6 +135,23 @@ class QPDFAcroFormDocumentHelper: public QPDFDocumentHelper QPDFFormFieldObjectHelper getFieldForAnnotation(QPDFAnnotationObjectHelper); + // Return the current value of /NeedAppearances. If + // /NeedAppearances is missing, return false as that is how PDF + // viewers are supposed to interpret it. + QPDF_DLL + bool getNeedAppearances(); + + // Indicate whether appearance streams must be regenerated. If you + // modify a field value, you should call setNeedAppearances(true) + // unless you also generate an appearance stream for the + // corresponding annotation at the same time. If you generate + // appearance streams for all fields, you can call + // setNeedAppearances(false). If you use + // QPDFFormFieldObjectHelper::setV, it will automatically call + // this method unless you tell it not to. + QPDF_DLL + void setNeedAppearances(bool); + private: void analyze(); void traverseField(QPDFObjectHandle field, diff --git a/include/qpdf/QPDFFormFieldObjectHelper.hh b/include/qpdf/QPDFFormFieldObjectHelper.hh index b45955a3..c22703aa 100644 --- a/include/qpdf/QPDFFormFieldObjectHelper.hh +++ b/include/qpdf/QPDFFormFieldObjectHelper.hh @@ -114,6 +114,29 @@ class QPDFFormFieldObjectHelper: public QPDFObjectHelper QPDF_DLL int getQuadding(); + // Set an attribute to the given value + QPDF_DLL + void setFieldAttribute(std::string const& key, QPDFObjectHandle value); + + // Set an attribute to the given value as a Unicode string (UTF-16 + // BE encoded). The input string should be UTF-8 encoded. + QPDF_DLL + void setFieldAttribute(std::string const& key, + std::string const& utf8_value); + + // Set /V (field value) to the given value. Optionally set + // /NeedAppearances to true. You can explicitly tell this method + // not to set /NeedAppearances if you are going to explicitly + // generate an appearance stream yourself. + QPDF_DLL + void setV(QPDFObjectHandle value, bool need_appearances = true); + + // Set /V (field value) to the given string value encoded as a + // Unicode string. The input value should be UTF-8 encoded. See + // comments above about /NeedAppearances. + QPDF_DLL + void setV(std::string const& utf8_value, bool need_appearances = true); + private: class Members { diff --git a/libqpdf/QPDFAcroFormDocumentHelper.cc b/libqpdf/QPDFAcroFormDocumentHelper.cc index 7e70fd92..46648ed9 100644 --- a/libqpdf/QPDFAcroFormDocumentHelper.cc +++ b/libqpdf/QPDFAcroFormDocumentHelper.cc @@ -250,3 +250,38 @@ QPDFAcroFormDocumentHelper::traverseField( QPDFFormFieldObjectHelper(our_field); } } + +bool +QPDFAcroFormDocumentHelper::getNeedAppearances() +{ + bool result = false; + QPDFObjectHandle acroform = this->qpdf.getRoot().getKey("/AcroForm"); + if (acroform.isDictionary() && + acroform.getKey("/NeedAppearances").isBool()) + { + result = acroform.getKey("/NeedAppearances").getBoolValue(); + } + return result; +} + +void +QPDFAcroFormDocumentHelper::setNeedAppearances(bool val) +{ + QPDFObjectHandle acroform = this->qpdf.getRoot().getKey("/AcroForm"); + if (! acroform.isDictionary()) + { + this->qpdf.getRoot().warnIfPossible( + "ignoring call to QPDFAcroFormDocumentHelper::setNeedAppearances" + " on a file that lacks an /AcroForm dictionary"); + return; + } + if (val) + { + acroform.replaceKey("/NeedAppearances", + QPDFObjectHandle::newBool(true)); + } + else + { + acroform.removeKey("/NeedAppearances"); + } +} diff --git a/libqpdf/QPDFFormFieldObjectHelper.cc b/libqpdf/QPDFFormFieldObjectHelper.cc index e6445af3..283b632d 100644 --- a/libqpdf/QPDFFormFieldObjectHelper.cc +++ b/libqpdf/QPDFFormFieldObjectHelper.cc @@ -1,5 +1,6 @@ #include #include +#include QPDFFormFieldObjectHelper::Members::~Members() { @@ -188,3 +189,44 @@ QPDFFormFieldObjectHelper::getQuadding() } return result; } + +void +QPDFFormFieldObjectHelper::setFieldAttribute( + std::string const& key, QPDFObjectHandle value) +{ + this->oh.replaceKey(key, value); +} + +void +QPDFFormFieldObjectHelper::setFieldAttribute( + std::string const& key, std::string const& utf8_value) +{ + this->oh.replaceKey(key, QPDFObjectHandle::newUnicodeString(utf8_value)); +} + +void +QPDFFormFieldObjectHelper::setV( + QPDFObjectHandle value, bool need_appearances) +{ + setFieldAttribute("/V", value); + if (need_appearances) + { + QPDF* qpdf = this->oh.getOwningQPDF(); + if (! qpdf) + { + throw std::logic_error( + "QPDFFormFieldObjectHelper::setV called with" + " need_appearances = true on an object that is" + " not associated with an owning QPDF"); + } + QPDFAcroFormDocumentHelper(*qpdf).setNeedAppearances(true); + } +} + +void +QPDFFormFieldObjectHelper::setV( + std::string const& utf8_value, bool need_appearances) +{ + setV(QPDFObjectHandle::newUnicodeString(utf8_value), + need_appearances); +} diff --git a/qpdf/qtest/qpdf.test b/qpdf/qtest/qpdf.test index f80da1c9..5f5b9612 100644 --- a/qpdf/qtest/qpdf.test +++ b/qpdf/qtest/qpdf.test @@ -115,7 +115,7 @@ my @form_tests = ( 'form-errors', ); -$n_tests += scalar(@form_tests); +$n_tests += scalar(@form_tests) + 2; # Many of the form*.pdf files were created by converting the # LibreOffice document storage/form.odt to PDF and then manually @@ -132,6 +132,15 @@ foreach my $f (@form_tests) $td->NORMALIZE_NEWLINES); } +$td->runtest("fill fields", + {$td->COMMAND => "test_driver 44 form-no-need-appearances.pdf"}, + {$td->FILE => "form-no-need-appearances.out", + $td->EXIT_STATUS => 0}, + $td->NORMALIZE_NEWLINES); +$td->runtest("compare files", + {$td->FILE => "a.pdf"}, + {$td->FILE => "form-no-need-appearances-filled.pdf"}); + show_ntests(); # ---------- $td->notify("--- Stream Replacement Tests ---"); diff --git a/qpdf/qtest/qpdf/form-no-need-appearances-filled.pdf b/qpdf/qtest/qpdf/form-no-need-appearances-filled.pdf new file mode 100644 index 0000000000000000000000000000000000000000..790281798d1c7d9985a62cf226e8dd1d34d77baf GIT binary patch literal 12686 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 3.14 ÷ 0 +Set field value: Text Box 2 -> 3.14 ÷ 0 +test 44 done diff --git a/qpdf/qtest/qpdf/form-no-need-appearances.pdf b/qpdf/qtest/qpdf/form-no-need-appearances.pdf new file mode 100644 index 0000000000000000000000000000000000000000..298955b0af93ee9498b31b6d09b91378ac858185 GIT binary patch literal 12572 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 AVE_OC literal 0 HcmV?d00001 diff --git a/qpdf/test_driver.cc b/qpdf/test_driver.cc index 9f4f18fe..c167b643 100644 --- a/qpdf/test_driver.cc +++ b/qpdf/test_driver.cc @@ -1584,6 +1584,34 @@ void runtest(int n, char const* filename1, char const* arg2) } } } + else if (n == 44) + { + // Set form fields. + QPDFAcroFormDocumentHelper afdh(pdf); + std::vector fields = afdh.getFormFields(); + for (std::vector::iterator iter = + fields.begin(); + iter != fields.end(); ++iter) + { + QPDFFormFieldObjectHelper& field(*iter); + QPDFObjectHandle ft = field.getInheritableFieldValue("/FT"); + if (ft.isName() && (ft.getName() == "/Tx")) + { + // \xc3\xb7 is utf-8 for U+00F7 (divided by) + field.setV("3.14 \xc3\xb7 0"); + std::cout << "Set field value: " + << field.getFullyQualifiedName() + << " -> " + << field.getValueAsString() + << std::endl; + } + } + QPDFWriter w(pdf, "a.pdf"); + w.setQDFMode(true); + w.setStaticID(true); + w.setSuppressOriginalObjectIDs(true); + w.write(); + } else { throw std::runtime_error(std::string("invalid test ") +