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
libqpdf/QPDF.cc
| ... | ... | @@ -11,6 +11,7 @@ |
| 11 | 11 | #include <sstream> |
| 12 | 12 | #include <vector> |
| 13 | 13 | |
| 14 | +#include <qpdf/AcroForm.hh> | |
| 14 | 15 | #include <qpdf/FileInputSource.hh> |
| 15 | 16 | #include <qpdf/InputSource_private.hh> |
| 16 | 17 | #include <qpdf/OffsetInputSource.hh> |
| ... | ... | @@ -147,6 +148,21 @@ QPDF::QPDF() : |
| 147 | 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 | 166 | // Provide access to disconnect(). Disconnect will in due course be merged into the current ObjCache |
| 151 | 167 | // (future Objects::Entry) to centralize all QPDF access to QPDFObject. |
| 152 | 168 | class Disconnect: BaseHandle | ... | ... |
libqpdf/QPDFAcroFormDocumentHelper.cc
| ... | ... | @@ -18,14 +18,7 @@ using namespace qpdf; |
| 18 | 18 | using namespace qpdf::impl; |
| 19 | 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 | 23 | QPDFAcroFormDocumentHelper::QPDFAcroFormDocumentHelper(QPDF& qpdf) : |
| 31 | 24 | QPDFDocumentHelper(qpdf), |
| ... | ... | @@ -36,7 +29,7 @@ QPDFAcroFormDocumentHelper::QPDFAcroFormDocumentHelper(QPDF& qpdf) : |
| 36 | 29 | QPDFAcroFormDocumentHelper& |
| 37 | 30 | QPDFAcroFormDocumentHelper::get(QPDF& qpdf) |
| 38 | 31 | { |
| 39 | - return qpdf.doc().acroform(); | |
| 32 | + return qpdf.doc().acroform_dh(); | |
| 40 | 33 | } |
| 41 | 34 | |
| 42 | 35 | void | ... | ... |
libqpdf/QPDFJob.cc
| ... | ... | @@ -4,6 +4,7 @@ |
| 4 | 4 | #include <iostream> |
| 5 | 5 | #include <memory> |
| 6 | 6 | |
| 7 | +#include <qpdf/AcroForm.hh> | |
| 7 | 8 | #include <qpdf/ClosedFileInputSource.hh> |
| 8 | 9 | #include <qpdf/FileInputSource.hh> |
| 9 | 10 | #include <qpdf/Pipeline_private.hh> |
| ... | ... | @@ -1866,7 +1867,7 @@ QPDFJob::doUnderOverlayForPage( |
| 1866 | 1867 | if (!(uo.pdf && pagenos[pageno.idx].contains(uo_idx))) { |
| 1867 | 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 | 1872 | auto const& pages = uo.pdf->doc().pages().all(); |
| 1872 | 1873 | std::string content; |
| ... | ... | @@ -1887,7 +1888,8 @@ QPDFJob::doUnderOverlayForPage( |
| 1887 | 1888 | QPDFMatrix cm; |
| 1888 | 1889 | std::string new_content = dest_page.placeFormXObject( |
| 1889 | 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 | 1893 | if (!new_content.empty()) { |
| 1892 | 1894 | resources.mergeResources(Dictionary({{"/XObject", Dictionary::empty()}})); |
| 1893 | 1895 | auto xobject = resources.getKey("/XObject"); |
| ... | ... | @@ -2107,7 +2109,7 @@ QPDFJob::handleTransformations(QPDF& pdf) |
| 2107 | 2109 | QPDFAcroFormDocumentHelper* afdh_ptr = nullptr; |
| 2108 | 2110 | auto afdh = [&]() -> QPDFAcroFormDocumentHelper& { |
| 2109 | 2111 | if (!afdh_ptr) { |
| 2110 | - afdh_ptr = &pdf.doc().acroform(); | |
| 2112 | + afdh_ptr = &pdf.doc().acroform_dh(); | |
| 2111 | 2113 | } |
| 2112 | 2114 | return *afdh_ptr; |
| 2113 | 2115 | }; |
| ... | ... | @@ -2978,8 +2980,7 @@ QPDFJob::doSplitPages(QPDF& pdf) |
| 2978 | 2980 | QPDF outpdf; |
| 2979 | 2981 | outpdf.doc().config(m->d_cfg); |
| 2980 | 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 | 2984 | for (size_t pageno = first; pageno <= last; ++pageno) { |
| 2984 | 2985 | QPDFObjectHandle page = pages.at(pageno - 1); |
| 2985 | 2986 | outpdf.addPage(page, false); | ... | ... |
libqpdf/QPDF_pages.cc
| 1 | 1 | #include <qpdf/QPDFPageDocumentHelper.hh> |
| 2 | 2 | #include <qpdf/QPDF_private.hh> |
| 3 | 3 | |
| 4 | -#include <qpdf/QPDFAcroFormDocumentHelper.hh> | |
| 4 | +#include <qpdf/AcroForm.hh> | |
| 5 | 5 | #include <qpdf/QPDFExc.hh> |
| 6 | 6 | #include <qpdf/QPDFObjectHandle_private.hh> |
| 7 | 7 | #include <qpdf/QTC.hh> |
| ... | ... | @@ -660,7 +660,7 @@ void |
| 660 | 660 | Pages::flatten_annotations_for_page( |
| 661 | 661 | QPDFPageObjectHelper& page, |
| 662 | 662 | QPDFObjectHandle& resources, |
| 663 | - QPDFAcroFormDocumentHelper& afdh, | |
| 663 | + impl::AcroForm& afdh, | |
| 664 | 664 | int required_flags, |
| 665 | 665 | int forbidden_flags) |
| 666 | 666 | { | ... | ... |
libqpdf/qpdf/AcroForm.hh
| ... | ... | @@ -546,7 +546,7 @@ namespace qpdf::impl |
| 546 | 546 | /// @param inherit If set to `true`, the function will attempt to retrieve `/V` by |
| 547 | 547 | /// inheritance from the parent hierarchy of the form field. Defaults to `true`. |
| 548 | 548 | /// @return Returns the field's value if found; otherwise, returns a default-constructed |
| 549 | - /// object handle. | |
| 549 | + /// object handle. | |
| 550 | 550 | QPDFObjectHandle const& |
| 551 | 551 | V(bool inherit = true) const |
| 552 | 552 | { |
| ... | ... | @@ -557,7 +557,7 @@ namespace qpdf::impl |
| 557 | 557 | } |
| 558 | 558 | |
| 559 | 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 | 562 | /// This function extracts the value of the form field, accounting for potential inheritance |
| 563 | 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 | 567 | /// an empty string if the value is not present or not a String. |
| 568 | 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 | 571 | /// accounting for inheritance through the hierarchy of ancestor nodes in the form |
| 572 | 572 | /// field tree. |
| 573 | 573 | /// |
| ... | ... | @@ -592,14 +592,14 @@ namespace qpdf::impl |
| 592 | 592 | } |
| 593 | 593 | |
| 594 | 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 | 597 | /// This function extracts the default value of the form field, accounting for potential |
| 598 | 598 | /// inheritance through the form hierarchy. It returns the value if it is a String, and an |
| 599 | 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 | 603 | std::string default_value() const; |
| 604 | 604 | |
| 605 | 605 | /// @brief Returns the default appearance string for the form field, considering inheritance |
| ... | ... | @@ -711,4 +711,13 @@ namespace qpdf::impl |
| 711 | 711 | }; // class FormNode |
| 712 | 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 | 723 | #endif // ACRO_FORM_HH | ... | ... |
libqpdf/qpdf/QPDF_private.hh
| ... | ... | @@ -28,8 +28,9 @@ namespace qpdf |
| 28 | 28 | |
| 29 | 29 | namespace impl |
| 30 | 30 | { |
| 31 | + class AcroForm; | |
| 31 | 32 | using Doc = QPDF::Doc; |
| 32 | - } | |
| 33 | + } // namespace impl | |
| 33 | 34 | |
| 34 | 35 | class Doc: public QPDF |
| 35 | 36 | { |
| ... | ... | @@ -374,11 +375,33 @@ class QPDF::Doc |
| 374 | 375 | bool reconstructed_xref() const; |
| 375 | 376 | |
| 376 | 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 | 400 | acroform() |
| 378 | 401 | { |
| 379 | 402 | if (!acroform_) { |
| 380 | 403 | no_inspection(); |
| 381 | - acroform_ = std::make_unique<QPDFAcroFormDocumentHelper>(qpdf); | |
| 404 | + init_acroform(); | |
| 382 | 405 | } |
| 383 | 406 | return *acroform_; |
| 384 | 407 | } |
| ... | ... | @@ -438,8 +461,11 @@ class QPDF::Doc |
| 438 | 461 | qpdf::Doc::Config cf; |
| 439 | 462 | |
| 440 | 463 | private: |
| 464 | + void init_acroform(); | |
| 465 | + | |
| 441 | 466 | // Document Helpers; |
| 442 | - std::unique_ptr<QPDFAcroFormDocumentHelper> acroform_; | |
| 467 | + std::unique_ptr<QPDFAcroFormDocumentHelper> acroform_dh_; | |
| 468 | + impl::AcroForm* acroform_{nullptr}; | |
| 443 | 469 | std::unique_ptr<QPDFEmbeddedFileDocumentHelper> embedded_files_; |
| 444 | 470 | std::unique_ptr<QPDFOutlineDocumentHelper> outlines_; |
| 445 | 471 | std::unique_ptr<QPDFPageDocumentHelper> page_dh_; |
| ... | ... | @@ -1173,7 +1199,7 @@ class QPDF::Doc::Pages: Common |
| 1173 | 1199 | void flatten_annotations_for_page( |
| 1174 | 1200 | QPDFPageObjectHelper& page, |
| 1175 | 1201 | QPDFObjectHandle& resources, |
| 1176 | - QPDFAcroFormDocumentHelper& afdh, | |
| 1202 | + impl::AcroForm& afdh, | |
| 1177 | 1203 | int required_flags, |
| 1178 | 1204 | int forbidden_flags); |
| 1179 | 1205 | ... | ... |