Commit d35c34d89c06ff3d00a3678660bf4586f6ff1b4a
1 parent
8d36ca4d
Refactor `AcroForm` to replace pointer-based method arguments with references fo…
…r improved clarity and safety. Update related methods and references accordingly.
Showing
7 changed files
with
72 additions
and
26 deletions
include/qpdf/QPDFAcroFormDocumentHelper.hh
| @@ -225,6 +225,7 @@ class QPDFAcroFormDocumentHelper: public QPDFDocumentHelper | @@ -225,6 +225,7 @@ class QPDFAcroFormDocumentHelper: public QPDFDocumentHelper | ||
| 225 | std::set<QPDFObjGen>* new_fields = nullptr); | 225 | std::set<QPDFObjGen>* new_fields = nullptr); |
| 226 | 226 | ||
| 227 | private: | 227 | private: |
| 228 | + friend class QPDF::Doc; | ||
| 228 | class Members; | 229 | class Members; |
| 229 | 230 | ||
| 230 | std::shared_ptr<Members> m; | 231 | std::shared_ptr<Members> m; |
libqpdf/QPDF.cc
| @@ -11,6 +11,7 @@ | @@ -11,6 +11,7 @@ | ||
| 11 | #include <sstream> | 11 | #include <sstream> |
| 12 | #include <vector> | 12 | #include <vector> |
| 13 | 13 | ||
| 14 | +#include <qpdf/AcroForm.hh> | ||
| 14 | #include <qpdf/FileInputSource.hh> | 15 | #include <qpdf/FileInputSource.hh> |
| 15 | #include <qpdf/InputSource_private.hh> | 16 | #include <qpdf/InputSource_private.hh> |
| 16 | #include <qpdf/OffsetInputSource.hh> | 17 | #include <qpdf/OffsetInputSource.hh> |
| @@ -147,6 +148,21 @@ QPDF::QPDF() : | @@ -147,6 +148,21 @@ QPDF::QPDF() : | ||
| 147 | m->unique_id = unique_id.fetch_add(1ULL); | 148 | m->unique_id = unique_id.fetch_add(1ULL); |
| 148 | } | 149 | } |
| 149 | 150 | ||
| 151 | +/// @brief Initializes the AcroForm functionality for the document. | ||
| 152 | +/// @par | ||
| 153 | +/// This method creates a unique instance of QPDFAcroFormDocumentHelper and associates it | ||
| 154 | +/// with the document. It also updates the `acroform_` pointer to reference the AcroForm | ||
| 155 | +/// instance managed by the helper. | ||
| 156 | +/// | ||
| 157 | +/// The method has been separated out from `acroform` to avoid it being inlined | ||
| 158 | +/// unnecessarily. | ||
| 159 | +void | ||
| 160 | +QPDF::Doc::init_acroform() | ||
| 161 | +{ | ||
| 162 | + acroform_dh_ = std::make_unique<QPDFAcroFormDocumentHelper>(qpdf); | ||
| 163 | + acroform_ = acroform_dh_->m.get(); | ||
| 164 | +} | ||
| 165 | + | ||
| 150 | // Provide access to disconnect(). Disconnect will in due course be merged into the current ObjCache | 166 | // Provide access to disconnect(). Disconnect will in due course be merged into the current ObjCache |
| 151 | // (future Objects::Entry) to centralize all QPDF access to QPDFObject. | 167 | // (future Objects::Entry) to centralize all QPDF access to QPDFObject. |
| 152 | class Disconnect: BaseHandle | 168 | class Disconnect: BaseHandle |
libqpdf/QPDFAcroFormDocumentHelper.cc
| @@ -18,14 +18,7 @@ using namespace qpdf; | @@ -18,14 +18,7 @@ using namespace qpdf; | ||
| 18 | using namespace qpdf::impl; | 18 | using namespace qpdf::impl; |
| 19 | using namespace std::literals; | 19 | using namespace std::literals; |
| 20 | 20 | ||
| 21 | -class QPDFAcroFormDocumentHelper::Members: public AcroForm | ||
| 22 | -{ | ||
| 23 | - public: | ||
| 24 | - Members(QPDF& qpdf) : | ||
| 25 | - AcroForm(qpdf.doc()) | ||
| 26 | - { | ||
| 27 | - } | ||
| 28 | -}; | 21 | +using AcroForm = impl::AcroForm; |
| 29 | 22 | ||
| 30 | QPDFAcroFormDocumentHelper::QPDFAcroFormDocumentHelper(QPDF& qpdf) : | 23 | QPDFAcroFormDocumentHelper::QPDFAcroFormDocumentHelper(QPDF& qpdf) : |
| 31 | QPDFDocumentHelper(qpdf), | 24 | QPDFDocumentHelper(qpdf), |
| @@ -36,7 +29,7 @@ QPDFAcroFormDocumentHelper::QPDFAcroFormDocumentHelper(QPDF& qpdf) : | @@ -36,7 +29,7 @@ QPDFAcroFormDocumentHelper::QPDFAcroFormDocumentHelper(QPDF& qpdf) : | ||
| 36 | QPDFAcroFormDocumentHelper& | 29 | QPDFAcroFormDocumentHelper& |
| 37 | QPDFAcroFormDocumentHelper::get(QPDF& qpdf) | 30 | QPDFAcroFormDocumentHelper::get(QPDF& qpdf) |
| 38 | { | 31 | { |
| 39 | - return qpdf.doc().acroform(); | 32 | + return qpdf.doc().acroform_dh(); |
| 40 | } | 33 | } |
| 41 | 34 | ||
| 42 | void | 35 | void |
libqpdf/QPDFJob.cc
| @@ -4,6 +4,7 @@ | @@ -4,6 +4,7 @@ | ||
| 4 | #include <iostream> | 4 | #include <iostream> |
| 5 | #include <memory> | 5 | #include <memory> |
| 6 | 6 | ||
| 7 | +#include <qpdf/AcroForm.hh> | ||
| 7 | #include <qpdf/ClosedFileInputSource.hh> | 8 | #include <qpdf/ClosedFileInputSource.hh> |
| 8 | #include <qpdf/FileInputSource.hh> | 9 | #include <qpdf/FileInputSource.hh> |
| 9 | #include <qpdf/Pipeline_private.hh> | 10 | #include <qpdf/Pipeline_private.hh> |
| @@ -1866,7 +1867,7 @@ QPDFJob::doUnderOverlayForPage( | @@ -1866,7 +1867,7 @@ QPDFJob::doUnderOverlayForPage( | ||
| 1866 | if (!(uo.pdf && pagenos[pageno.idx].contains(uo_idx))) { | 1867 | if (!(uo.pdf && pagenos[pageno.idx].contains(uo_idx))) { |
| 1867 | return ""; | 1868 | return ""; |
| 1868 | } | 1869 | } |
| 1869 | - auto& dest_afdh = dest_page.qpdf()->doc().acroform(); | 1870 | + auto& dest_afdh = dest_page.qpdf()->doc().acroform_dh(); |
| 1870 | 1871 | ||
| 1871 | auto const& pages = uo.pdf->doc().pages().all(); | 1872 | auto const& pages = uo.pdf->doc().pages().all(); |
| 1872 | std::string content; | 1873 | std::string content; |
| @@ -1887,7 +1888,8 @@ QPDFJob::doUnderOverlayForPage( | @@ -1887,7 +1888,8 @@ QPDFJob::doUnderOverlayForPage( | ||
| 1887 | QPDFMatrix cm; | 1888 | QPDFMatrix cm; |
| 1888 | std::string new_content = dest_page.placeFormXObject( | 1889 | std::string new_content = dest_page.placeFormXObject( |
| 1889 | fo[from_no.no][uo_idx], name, dest_page.getTrimBox().getArrayAsRectangle(), cm); | 1890 | fo[from_no.no][uo_idx], name, dest_page.getTrimBox().getArrayAsRectangle(), cm); |
| 1890 | - dest_page.copyAnnotations(from_page, cm, &dest_afdh, &from_page.qpdf()->doc().acroform()); | 1891 | + dest_page.copyAnnotations( |
| 1892 | + from_page, cm, &dest_afdh, &from_page.qpdf()->doc().acroform_dh()); | ||
| 1891 | if (!new_content.empty()) { | 1893 | if (!new_content.empty()) { |
| 1892 | resources.mergeResources(Dictionary({{"/XObject", Dictionary::empty()}})); | 1894 | resources.mergeResources(Dictionary({{"/XObject", Dictionary::empty()}})); |
| 1893 | auto xobject = resources.getKey("/XObject"); | 1895 | auto xobject = resources.getKey("/XObject"); |
| @@ -2107,7 +2109,7 @@ QPDFJob::handleTransformations(QPDF& pdf) | @@ -2107,7 +2109,7 @@ QPDFJob::handleTransformations(QPDF& pdf) | ||
| 2107 | QPDFAcroFormDocumentHelper* afdh_ptr = nullptr; | 2109 | QPDFAcroFormDocumentHelper* afdh_ptr = nullptr; |
| 2108 | auto afdh = [&]() -> QPDFAcroFormDocumentHelper& { | 2110 | auto afdh = [&]() -> QPDFAcroFormDocumentHelper& { |
| 2109 | if (!afdh_ptr) { | 2111 | if (!afdh_ptr) { |
| 2110 | - afdh_ptr = &pdf.doc().acroform(); | 2112 | + afdh_ptr = &pdf.doc().acroform_dh(); |
| 2111 | } | 2113 | } |
| 2112 | return *afdh_ptr; | 2114 | return *afdh_ptr; |
| 2113 | }; | 2115 | }; |
| @@ -2978,8 +2980,7 @@ QPDFJob::doSplitPages(QPDF& pdf) | @@ -2978,8 +2980,7 @@ QPDFJob::doSplitPages(QPDF& pdf) | ||
| 2978 | QPDF outpdf; | 2980 | QPDF outpdf; |
| 2979 | outpdf.doc().config(m->d_cfg); | 2981 | outpdf.doc().config(m->d_cfg); |
| 2980 | outpdf.emptyPDF(); | 2982 | outpdf.emptyPDF(); |
| 2981 | - QPDFAcroFormDocumentHelper* out_afdh = | ||
| 2982 | - afdh.hasAcroForm() ? &outpdf.doc().acroform() : nullptr; | 2983 | + impl::AcroForm* out_afdh = afdh.hasAcroForm() ? &outpdf.doc().acroform() : nullptr; |
| 2983 | for (size_t pageno = first; pageno <= last; ++pageno) { | 2984 | for (size_t pageno = first; pageno <= last; ++pageno) { |
| 2984 | QPDFObjectHandle page = pages.at(pageno - 1); | 2985 | QPDFObjectHandle page = pages.at(pageno - 1); |
| 2985 | outpdf.addPage(page, false); | 2986 | outpdf.addPage(page, false); |
libqpdf/QPDF_pages.cc
| 1 | #include <qpdf/QPDFPageDocumentHelper.hh> | 1 | #include <qpdf/QPDFPageDocumentHelper.hh> |
| 2 | #include <qpdf/QPDF_private.hh> | 2 | #include <qpdf/QPDF_private.hh> |
| 3 | 3 | ||
| 4 | -#include <qpdf/QPDFAcroFormDocumentHelper.hh> | 4 | +#include <qpdf/AcroForm.hh> |
| 5 | #include <qpdf/QPDFExc.hh> | 5 | #include <qpdf/QPDFExc.hh> |
| 6 | #include <qpdf/QPDFObjectHandle_private.hh> | 6 | #include <qpdf/QPDFObjectHandle_private.hh> |
| 7 | #include <qpdf/QTC.hh> | 7 | #include <qpdf/QTC.hh> |
| @@ -660,7 +660,7 @@ void | @@ -660,7 +660,7 @@ void | ||
| 660 | Pages::flatten_annotations_for_page( | 660 | Pages::flatten_annotations_for_page( |
| 661 | QPDFPageObjectHelper& page, | 661 | QPDFPageObjectHelper& page, |
| 662 | QPDFObjectHandle& resources, | 662 | QPDFObjectHandle& resources, |
| 663 | - QPDFAcroFormDocumentHelper& afdh, | 663 | + impl::AcroForm& afdh, |
| 664 | int required_flags, | 664 | int required_flags, |
| 665 | int forbidden_flags) | 665 | int forbidden_flags) |
| 666 | { | 666 | { |
libqpdf/qpdf/AcroForm.hh
| @@ -546,7 +546,7 @@ namespace qpdf::impl | @@ -546,7 +546,7 @@ namespace qpdf::impl | ||
| 546 | /// @param inherit If set to `true`, the function will attempt to retrieve `/V` by | 546 | /// @param inherit If set to `true`, the function will attempt to retrieve `/V` by |
| 547 | /// inheritance from the parent hierarchy of the form field. Defaults to `true`. | 547 | /// inheritance from the parent hierarchy of the form field. Defaults to `true`. |
| 548 | /// @return Returns the field's value if found; otherwise, returns a default-constructed | 548 | /// @return Returns the field's value if found; otherwise, returns a default-constructed |
| 549 | - /// object handle. | 549 | + /// object handle. |
| 550 | QPDFObjectHandle const& | 550 | QPDFObjectHandle const& |
| 551 | V(bool inherit = true) const | 551 | V(bool inherit = true) const |
| 552 | { | 552 | { |
| @@ -557,7 +557,7 @@ namespace qpdf::impl | @@ -557,7 +557,7 @@ namespace qpdf::impl | ||
| 557 | } | 557 | } |
| 558 | 558 | ||
| 559 | /// @brief Retrieves the field value `/V` attribute of the form field, considering | 559 | /// @brief Retrieves the field value `/V` attribute of the form field, considering |
| 560 | - /// inheritance, if the value is a String. | 560 | + /// inheritance, if the value is a String. |
| 561 | /// | 561 | /// |
| 562 | /// This function extracts the value of the form field, accounting for potential inheritance | 562 | /// This function extracts the value of the form field, accounting for potential inheritance |
| 563 | /// through the form hierarchy. It returns the value if it is a String, and an empty string | 563 | /// through the form hierarchy. It returns the value if it is a String, and an empty string |
| @@ -567,7 +567,7 @@ namespace qpdf::impl | @@ -567,7 +567,7 @@ namespace qpdf::impl | ||
| 567 | /// an empty string if the value is not present or not a String. | 567 | /// an empty string if the value is not present or not a String. |
| 568 | std::string value() const; | 568 | std::string value() const; |
| 569 | 569 | ||
| 570 | - /// @brief Retrieves the field default value (`/DV` attribute) of a specified field, | 570 | + /// @brief Retrieves the field default value (`/DV` attribute) of a specified field, |
| 571 | /// accounting for inheritance through the hierarchy of ancestor nodes in the form | 571 | /// accounting for inheritance through the hierarchy of ancestor nodes in the form |
| 572 | /// field tree. | 572 | /// field tree. |
| 573 | /// | 573 | /// |
| @@ -592,14 +592,14 @@ namespace qpdf::impl | @@ -592,14 +592,14 @@ namespace qpdf::impl | ||
| 592 | } | 592 | } |
| 593 | 593 | ||
| 594 | /// @brief Retrieves the default value `/DV` attribute of the form field, considering | 594 | /// @brief Retrieves the default value `/DV` attribute of the form field, considering |
| 595 | - /// inheritance, if the default value is a String. | 595 | + /// inheritance, if the default value is a String. |
| 596 | /// | 596 | /// |
| 597 | /// This function extracts the default value of the form field, accounting for potential | 597 | /// This function extracts the default value of the form field, accounting for potential |
| 598 | /// inheritance through the form hierarchy. It returns the value if it is a String, and an | 598 | /// inheritance through the form hierarchy. It returns the value if it is a String, and an |
| 599 | /// empty string otherwise. | 599 | /// empty string otherwise. |
| 600 | /// | 600 | /// |
| 601 | - /// @return A string containing the actual or inherited `/V` attribute of the form field, or | ||
| 602 | - /// an empty string if the value is not present or not a String. | 601 | + /// @return A string containing the actual or inherited `/DV` attribute of the form field, |
| 602 | + /// or an empty string if the value is not present or not a String. | ||
| 603 | std::string default_value() const; | 603 | std::string default_value() const; |
| 604 | 604 | ||
| 605 | /// @brief Returns the default appearance string for the form field, considering inheritance | 605 | /// @brief Returns the default appearance string for the form field, considering inheritance |
| @@ -711,4 +711,13 @@ namespace qpdf::impl | @@ -711,4 +711,13 @@ namespace qpdf::impl | ||
| 711 | }; // class FormNode | 711 | }; // class FormNode |
| 712 | } // namespace qpdf::impl | 712 | } // namespace qpdf::impl |
| 713 | 713 | ||
| 714 | +class QPDFAcroFormDocumentHelper::Members: public qpdf::impl::AcroForm | ||
| 715 | +{ | ||
| 716 | + public: | ||
| 717 | + Members(QPDF& qpdf) : | ||
| 718 | + AcroForm(qpdf.doc()) | ||
| 719 | + { | ||
| 720 | + } | ||
| 721 | +}; | ||
| 722 | + | ||
| 714 | #endif // ACRO_FORM_HH | 723 | #endif // ACRO_FORM_HH |
libqpdf/qpdf/QPDF_private.hh
| @@ -28,8 +28,9 @@ namespace qpdf | @@ -28,8 +28,9 @@ namespace qpdf | ||
| 28 | 28 | ||
| 29 | namespace impl | 29 | namespace impl |
| 30 | { | 30 | { |
| 31 | + class AcroForm; | ||
| 31 | using Doc = QPDF::Doc; | 32 | using Doc = QPDF::Doc; |
| 32 | - } | 33 | + } // namespace impl |
| 33 | 34 | ||
| 34 | class Doc: public QPDF | 35 | class Doc: public QPDF |
| 35 | { | 36 | { |
| @@ -374,11 +375,33 @@ class QPDF::Doc | @@ -374,11 +375,33 @@ class QPDF::Doc | ||
| 374 | bool reconstructed_xref() const; | 375 | bool reconstructed_xref() const; |
| 375 | 376 | ||
| 376 | QPDFAcroFormDocumentHelper& | 377 | QPDFAcroFormDocumentHelper& |
| 378 | + acroform_dh() | ||
| 379 | + { | ||
| 380 | + if (!acroform_) { | ||
| 381 | + no_inspection(); | ||
| 382 | + init_acroform(); | ||
| 383 | + } | ||
| 384 | + return *acroform_dh_; | ||
| 385 | + } | ||
| 386 | + | ||
| 387 | + /// @brief Retrieves the shared impl::AcroForm instance associated with the document. | ||
| 388 | + /// | ||
| 389 | + /// @note The AcroForm class caches the form field structure for efficiency. If any part | ||
| 390 | + /// of the form field structure is modified directly the `validate` method MUST be | ||
| 391 | + /// called before calling any other AcroForm methods in order to refresh the cache. | ||
| 392 | + /// | ||
| 393 | + /// If the AcroForm instance has not already been initialized, the `init_acroform()` | ||
| 394 | + /// function is called to initialize it. | ||
| 395 | + /// | ||
| 396 | + /// @return A reference to the shared AcroForm object of the document. | ||
| 397 | + /// | ||
| 398 | + /// @since 12.3 | ||
| 399 | + impl::AcroForm& | ||
| 377 | acroform() | 400 | acroform() |
| 378 | { | 401 | { |
| 379 | if (!acroform_) { | 402 | if (!acroform_) { |
| 380 | no_inspection(); | 403 | no_inspection(); |
| 381 | - acroform_ = std::make_unique<QPDFAcroFormDocumentHelper>(qpdf); | 404 | + init_acroform(); |
| 382 | } | 405 | } |
| 383 | return *acroform_; | 406 | return *acroform_; |
| 384 | } | 407 | } |
| @@ -438,8 +461,11 @@ class QPDF::Doc | @@ -438,8 +461,11 @@ class QPDF::Doc | ||
| 438 | qpdf::Doc::Config cf; | 461 | qpdf::Doc::Config cf; |
| 439 | 462 | ||
| 440 | private: | 463 | private: |
| 464 | + void init_acroform(); | ||
| 465 | + | ||
| 441 | // Document Helpers; | 466 | // Document Helpers; |
| 442 | - std::unique_ptr<QPDFAcroFormDocumentHelper> acroform_; | 467 | + std::unique_ptr<QPDFAcroFormDocumentHelper> acroform_dh_; |
| 468 | + impl::AcroForm* acroform_{nullptr}; | ||
| 443 | std::unique_ptr<QPDFEmbeddedFileDocumentHelper> embedded_files_; | 469 | std::unique_ptr<QPDFEmbeddedFileDocumentHelper> embedded_files_; |
| 444 | std::unique_ptr<QPDFOutlineDocumentHelper> outlines_; | 470 | std::unique_ptr<QPDFOutlineDocumentHelper> outlines_; |
| 445 | std::unique_ptr<QPDFPageDocumentHelper> page_dh_; | 471 | std::unique_ptr<QPDFPageDocumentHelper> page_dh_; |
| @@ -1173,7 +1199,7 @@ class QPDF::Doc::Pages: Common | @@ -1173,7 +1199,7 @@ class QPDF::Doc::Pages: Common | ||
| 1173 | void flatten_annotations_for_page( | 1199 | void flatten_annotations_for_page( |
| 1174 | QPDFPageObjectHelper& page, | 1200 | QPDFPageObjectHelper& page, |
| 1175 | QPDFObjectHandle& resources, | 1201 | QPDFObjectHandle& resources, |
| 1176 | - QPDFAcroFormDocumentHelper& afdh, | 1202 | + impl::AcroForm& afdh, |
| 1177 | int required_flags, | 1203 | int required_flags, |
| 1178 | int forbidden_flags); | 1204 | int forbidden_flags); |
| 1179 | 1205 |