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,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 |