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