Commit 68754ee81d0f007502fb6c41ed2e77a847ad5d93
1 parent
4f23d70b
Refactor annotation flattening: move `flattenAnnotationsForPage` to `Pages` from…
… `QPDFPageDocumentHelper`, consolidate redundant logic, and streamline method calls.
Showing
4 changed files
with
18 additions
and
26 deletions
include/qpdf/QPDFPageDocumentHelper.hh
| ... | ... | @@ -120,13 +120,6 @@ class QPDFPageDocumentHelper: public QPDFDocumentHelper |
| 120 | 120 | void flattenAnnotations(int required_flags = 0, int forbidden_flags = an_invisible | an_hidden); |
| 121 | 121 | |
| 122 | 122 | private: |
| 123 | - void flattenAnnotationsForPage( | |
| 124 | - QPDFPageObjectHelper& page, | |
| 125 | - QPDFObjectHandle& resources, | |
| 126 | - QPDFAcroFormDocumentHelper& afdh, | |
| 127 | - int required_flags, | |
| 128 | - int forbidden_flags); | |
| 129 | - | |
| 130 | 123 | class Members; |
| 131 | 124 | |
| 132 | 125 | std::shared_ptr<Members> m; | ... | ... |
libqpdf/QPDF_pages.cc
| ... | ... | @@ -631,6 +631,12 @@ QPDFPageDocumentHelper::removePage(QPDFPageObjectHelper page) |
| 631 | 631 | void |
| 632 | 632 | QPDFPageDocumentHelper::flattenAnnotations(int required_flags, int forbidden_flags) |
| 633 | 633 | { |
| 634 | + qpdf.doc().pages().flatten_annotations(required_flags, forbidden_flags); | |
| 635 | +} | |
| 636 | + | |
| 637 | +void | |
| 638 | +Pages::flatten_annotations(int required_flags, int forbidden_flags) | |
| 639 | +{ | |
| 634 | 640 | auto& afdh = qpdf.doc().acroform(); |
| 635 | 641 | if (afdh.getNeedAppearances()) { |
| 636 | 642 | qpdf.getRoot() |
| ... | ... | @@ -639,14 +645,13 @@ QPDFPageDocumentHelper::flattenAnnotations(int required_flags, int forbidden_fla |
| 639 | 645 | "document does not have updated appearance streams, so form fields " |
| 640 | 646 | "will not be flattened"); |
| 641 | 647 | } |
| 642 | - for (auto& ph: getAllPages()) { | |
| 648 | + for (QPDFPageObjectHelper ph: all()) { | |
| 643 | 649 | QPDFObjectHandle resources = ph.getAttribute("/Resources", true); |
| 644 | 650 | if (!resources.isDictionary()) { |
| 645 | 651 | // As of #1521, this should be impossible unless a user inserted an invalid page. |
| 646 | - resources = ph.getObjectHandle().replaceKeyAndGetNew( | |
| 647 | - "/Resources", QPDFObjectHandle::newDictionary()); | |
| 652 | + resources = ph.getObjectHandle().replaceKeyAndGetNew("/Resources", Dictionary::empty()); | |
| 648 | 653 | } |
| 649 | - flattenAnnotationsForPage(ph, resources, afdh, required_flags, forbidden_flags); | |
| 654 | + flatten_annotations_for_page(ph, resources, afdh, required_flags, forbidden_flags); | |
| 650 | 655 | } |
| 651 | 656 | if (!afdh.getNeedAppearances()) { |
| 652 | 657 | qpdf.getRoot().removeKey("/AcroForm"); |
| ... | ... | @@ -654,7 +659,7 @@ QPDFPageDocumentHelper::flattenAnnotations(int required_flags, int forbidden_fla |
| 654 | 659 | } |
| 655 | 660 | |
| 656 | 661 | void |
| 657 | -QPDFPageDocumentHelper::flattenAnnotationsForPage( | |
| 662 | +Pages::flatten_annotations_for_page( | |
| 658 | 663 | QPDFPageObjectHelper& page, |
| 659 | 664 | QPDFObjectHandle& resources, |
| 660 | 665 | QPDFAcroFormDocumentHelper& afdh, |
| ... | ... | @@ -676,16 +681,14 @@ QPDFPageDocumentHelper::flattenAnnotationsForPage( |
| 676 | 681 | bool is_widget = (aoh.getSubtype() == "/Widget"); |
| 677 | 682 | bool process = true; |
| 678 | 683 | if (need_appearances && is_widget) { |
| 679 | - QTC::TC("qpdf", "QPDFPageDocumentHelper skip widget need appearances"); | |
| 680 | 684 | process = false; |
| 681 | 685 | } |
| 682 | 686 | if (process && as.isStream()) { |
| 683 | 687 | if (is_widget) { |
| 684 | - QTC::TC("qpdf", "QPDFPageDocumentHelper merge DR"); | |
| 685 | 688 | QPDFFormFieldObjectHelper ff = afdh.getFieldForAnnotation(aoh); |
| 686 | 689 | QPDFObjectHandle as_resources = as.getDict().getKey("/Resources"); |
| 687 | 690 | if (as_resources.isIndirect()) { |
| 688 | - QTC::TC("qpdf", "QPDFPageDocumentHelper indirect as resources"); | |
| 691 | + ; | |
| 689 | 692 | as.getDict().replaceKey("/Resources", as_resources.shallowCopy()); |
| 690 | 693 | as_resources = as.getDict().getKey("/Resources"); |
| 691 | 694 | } |
| ... | ... | @@ -708,7 +711,6 @@ QPDFPageDocumentHelper::flattenAnnotationsForPage( |
| 708 | 711 | // associated with comments that aren't visible, and other types of annotations that |
| 709 | 712 | // aren't visible. Annotations that have no appearance streams at all, such as Link, |
| 710 | 713 | // Popup, and Projection, should be preserved. |
| 711 | - QTC::TC("qpdf", "QPDFPageDocumentHelper ignore annotation with no appearance"); | |
| 712 | 714 | } else { |
| 713 | 715 | new_annots.push_back(aoh.getObjectHandle()); |
| 714 | 716 | } |
| ... | ... | @@ -716,16 +718,13 @@ QPDFPageDocumentHelper::flattenAnnotationsForPage( |
| 716 | 718 | if (new_annots.size() != annots.size()) { |
| 717 | 719 | QPDFObjectHandle page_oh = page.getObjectHandle(); |
| 718 | 720 | if (new_annots.empty()) { |
| 719 | - QTC::TC("qpdf", "QPDFPageDocumentHelper remove annots"); | |
| 720 | 721 | page_oh.removeKey("/Annots"); |
| 721 | 722 | } else { |
| 722 | 723 | QPDFObjectHandle old_annots = page_oh.getKey("/Annots"); |
| 723 | 724 | QPDFObjectHandle new_annots_oh = QPDFObjectHandle::newArray(new_annots); |
| 724 | 725 | if (old_annots.isIndirect()) { |
| 725 | - QTC::TC("qpdf", "QPDFPageDocumentHelper replace indirect annots"); | |
| 726 | 726 | qpdf.replaceObject(old_annots.getObjGen(), new_annots_oh); |
| 727 | 727 | } else { |
| 728 | - QTC::TC("qpdf", "QPDFPageDocumentHelper replace direct annots"); | |
| 729 | 728 | page_oh.replaceKey("/Annots", new_annots_oh); |
| 730 | 729 | } |
| 731 | 730 | } | ... | ... |
libqpdf/qpdf/QPDF_private.hh
| ... | ... | @@ -900,6 +900,7 @@ class QPDF::Doc::Pages: Common |
| 900 | 900 | int find(QPDFObjGen og); |
| 901 | 901 | void erase(QPDFObjectHandle& page); |
| 902 | 902 | void update_cache(); |
| 903 | + void flatten_annotations(int required_flags, int forbidden_flags); | |
| 903 | 904 | |
| 904 | 905 | bool |
| 905 | 906 | ever_pushed_inherited_attributes_to_pages() const |
| ... | ... | @@ -931,6 +932,12 @@ class QPDF::Doc::Pages: Common |
| 931 | 932 | QPDFObjGen::set& seen, |
| 932 | 933 | bool media_box, |
| 933 | 934 | bool resources); |
| 935 | + void flatten_annotations_for_page( | |
| 936 | + QPDFPageObjectHelper& page, | |
| 937 | + QPDFObjectHandle& resources, | |
| 938 | + QPDFAcroFormDocumentHelper& afdh, | |
| 939 | + int required_flags, | |
| 940 | + int forbidden_flags); | |
| 934 | 941 | |
| 935 | 942 | std::vector<QPDFObjectHandle> all_pages; |
| 936 | 943 | std::map<QPDFObjGen, int> pageobj_to_pages_pos; | ... | ... |
qpdf/qpdf.testcov
| ... | ... | @@ -224,14 +224,8 @@ QPDFAnnotationObjectHelper default matrix 0 |
| 224 | 224 | QPDFAnnotationObjectHelper rotate 90 0 |
| 225 | 225 | QPDFAnnotationObjectHelper rotate 180 0 |
| 226 | 226 | QPDFAnnotationObjectHelper rotate 270 0 |
| 227 | -QPDFPageDocumentHelper skip widget need appearances 0 | |
| 228 | -QPDFPageDocumentHelper merge DR 0 | |
| 229 | 227 | QPDFPageDocumentHelper non-widget annotation 0 |
| 230 | -QPDFPageDocumentHelper remove annots 0 | |
| 231 | -QPDFPageDocumentHelper replace indirect annots 0 | |
| 232 | -QPDFPageDocumentHelper replace direct annots 0 | |
| 233 | 228 | QPDFObjectHandle replace with copy 0 |
| 234 | -QPDFPageDocumentHelper indirect as resources 0 | |
| 235 | 229 | QPDFAnnotationObjectHelper forbidden flags 0 |
| 236 | 230 | QPDFAnnotationObjectHelper missing required flags 0 |
| 237 | 231 | QPDFFormFieldObjectHelper checkbox kid widget 0 |
| ... | ... | @@ -255,7 +249,6 @@ QPDFJob auto-encode password 0 |
| 255 | 249 | QPDFJob bytes fallback warning 0 |
| 256 | 250 | QPDFJob invalid utf-8 in auto 0 |
| 257 | 251 | QPDFJob input password hex-bytes 0 |
| 258 | -QPDFPageDocumentHelper ignore annotation with no appearance 0 | |
| 259 | 252 | QPDFFormFieldObjectHelper replaced BMC at EOF 0 |
| 260 | 253 | QPDFFormFieldObjectHelper fallback Tf 0 |
| 261 | 254 | QPDFPageObjectHelper copy shared attribute 1 | ... | ... |