Commit 3e39e0dcc02fca4e7bb437444044531cb7ce0bad

Authored by m-holger
1 parent dcd53ffc

Refactor `QPDFJob::handlePageSpecs`: streamline page handling by removing `QPDFP…

…ageDocumentHelper` dependency, simplifying page and form field operations, and updating test coverage.
libqpdf/QPDFJob.cc
@@ -2486,10 +2486,9 @@ QPDFJob::handlePageSpecs(QPDF& pdf) @@ -2486,10 +2486,9 @@ QPDFJob::handlePageSpecs(QPDF& pdf)
2486 doIfVerbose([&](Pipeline& v, std::string const& prefix) { 2486 doIfVerbose([&](Pipeline& v, std::string const& prefix) {
2487 v << prefix << ": removing unreferenced pages from primary input\n"; 2487 v << prefix << ": removing unreferenced pages from primary input\n";
2488 }); 2488 });
2489 - QPDFPageDocumentHelper dh(pdf);  
2490 - std::vector<QPDFPageObjectHelper> orig_pages = dh.getAllPages(); 2489 + auto orig_pages = pdf.getAllPages();
2491 for (auto const& page: orig_pages) { 2490 for (auto const& page: orig_pages) {
2492 - dh.removePage(page); 2491 + pdf.removePage(page);
2493 } 2492 }
2494 2493
2495 auto n_collate = m->collate.size(); 2494 auto n_collate = m->collate.size();
@@ -2568,7 +2567,7 @@ QPDFJob::handlePageSpecs(QPDF&amp; pdf) @@ -2568,7 +2567,7 @@ QPDFJob::handlePageSpecs(QPDF&amp; pdf)
2568 to_copy.removeUnreferencedResources(); 2567 to_copy.removeUnreferencedResources();
2569 } 2568 }
2570 } 2569 }
2571 - dh.addPage(to_copy, false); 2570 + pdf.addPage(to_copy, false);
2572 bool first_copy_from_orig = false; 2571 bool first_copy_from_orig = false;
2573 bool this_file = (page_data.qpdf == &pdf); 2572 bool this_file = (page_data.qpdf == &pdf);
2574 if (this_file) { 2573 if (this_file) {
@@ -2609,43 +2608,41 @@ QPDFJob::handlePageSpecs(QPDF&amp; pdf) @@ -2609,43 +2608,41 @@ QPDFJob::handlePageSpecs(QPDF&amp; pdf)
2609 } 2608 }
2610 } 2609 }
2611 if (any_page_labels) { 2610 if (any_page_labels) {
2612 - QPDFObjectHandle page_labels = QPDFObjectHandle::newDictionary();  
2613 - page_labels.replaceKey("/Nums", QPDFObjectHandle::newArray(new_labels));  
2614 - pdf.getRoot().replaceKey("/PageLabels", page_labels); 2611 + pdf.getRoot().replaceKey("/PageLabels", Dictionary({{"/Nums", Array(new_labels)}}));
2615 } 2612 }
2616 2613
2617 // Delete page objects for unused page in primary. This prevents those objects from being 2614 // Delete page objects for unused page in primary. This prevents those objects from being
2618 // preserved by being referred to from other places, such as the outlines dictionary. Also make 2615 // preserved by being referred to from other places, such as the outlines dictionary. Also make
2619 // sure we keep form fields from pages we preserved. 2616 // sure we keep form fields from pages we preserved.
2620 - for (size_t pageno = 0; pageno < orig_pages.size(); ++pageno) {  
2621 - auto page = orig_pages.at(pageno);  
2622 - if (selected_from_orig.contains(QIntC::to_int(pageno))) { 2617 + int page_idx = 0;
  2618 + for (auto const& page: orig_pages) {
  2619 + if (selected_from_orig.contains(page_idx)) {
2623 for (auto field: this_afdh.getFormFieldsForPage(page)) { 2620 for (auto field: this_afdh.getFormFieldsForPage(page)) {
2624 - QTC::TC("qpdf", "QPDFJob pages keeping field from original");  
2625 - referenced_fields.insert(field.getObjectHandle().getObjGen()); 2621 + referenced_fields.insert(field);
2626 } 2622 }
2627 } else { 2623 } else {
2628 - pdf.replaceObject(page.getObjectHandle().getObjGen(), QPDFObjectHandle::newNull()); 2624 + pdf.replaceObject(page, QPDFObjectHandle::newNull());
2629 } 2625 }
  2626 + ++page_idx;
2630 } 2627 }
2631 // Remove unreferenced form fields 2628 // Remove unreferenced form fields
2632 if (this_afdh.hasAcroForm()) { 2629 if (this_afdh.hasAcroForm()) {
2633 - auto acroform = pdf.getRoot().getKey("/AcroForm");  
2634 - auto fields = acroform.getKey("/Fields");  
2635 - if (fields.isArray()) {  
2636 - auto new_fields = QPDFObjectHandle::newArray();  
2637 - if (fields.isIndirect()) {  
2638 - new_fields = pdf.makeIndirectObject(new_fields);  
2639 - }  
2640 - for (auto const& field: fields.aitems()) { 2630 + auto acroform = pdf.getRoot()["/AcroForm"];
  2631 + if (Array fields = acroform["/Fields"]) {
  2632 + std::vector<QPDFObjectHandle> new_fields;
  2633 + new_fields.reserve(referenced_fields.size());
  2634 + for (auto const& field: fields) {
2641 if (referenced_fields.contains(field.getObjGen())) { 2635 if (referenced_fields.contains(field.getObjGen())) {
2642 - new_fields.appendItem(field); 2636 + new_fields.emplace_back(field);
2643 } 2637 }
2644 } 2638 }
2645 if (new_fields.empty()) { 2639 if (new_fields.empty()) {
2646 - pdf.getRoot().removeKey("/AcroForm"); 2640 + pdf.getRoot().erase("/AcroForm");
2647 } else { 2641 } else {
2648 - acroform.replaceKey("/Fields", new_fields); 2642 + acroform.replaceKey(
  2643 + "/Fields",
  2644 + fields.indirect() ? pdf.makeIndirectObject(Array(new_fields))
  2645 + : QPDFObjectHandle(Array(new_fields)));
2649 } 2646 }
2650 } 2647 }
2651 } 2648 }
qpdf/qpdf.testcov
@@ -452,7 +452,6 @@ QPDFFileSpecObjectHelper empty compat_name 0 @@ -452,7 +452,6 @@ QPDFFileSpecObjectHelper empty compat_name 0
452 QPDFFileSpecObjectHelper non-empty compat_name 0 452 QPDFFileSpecObjectHelper non-empty compat_name 0
453 QPDFAcroFormDocumentHelper copy annotation 3 453 QPDFAcroFormDocumentHelper copy annotation 3
454 QPDFAcroFormDocumentHelper field with parent 3 454 QPDFAcroFormDocumentHelper field with parent 3
455 -QPDFJob pages keeping field from original 0  
456 QPDFObjectHandle merge reuse 0 455 QPDFObjectHandle merge reuse 0
457 QPDFObjectHandle merge generate 0 456 QPDFObjectHandle merge generate 0
458 QPDFAcroFormDocumentHelper replaced DA token 0 457 QPDFAcroFormDocumentHelper replaced DA token 0