Commit 68754ee81d0f007502fb6c41ed2e77a847ad5d93

Authored by m-holger
1 parent 4f23d70b

Refactor annotation flattening: move `flattenAnnotationsForPage` to `Pages` from…

… `QPDFPageDocumentHelper`, consolidate redundant logic, and streamline method calls.
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
... ...