diff --git a/include/qpdf/QPDFJob.hh b/include/qpdf/QPDFJob.hh index 247a80a9..a89d1503 100644 --- a/include/qpdf/QPDFJob.hh +++ b/include/qpdf/QPDFJob.hh @@ -514,16 +514,15 @@ class QPDFJob void handlePageSpecs(QPDF& pdf, std::vector>& page_heap); bool shouldRemoveUnreferencedResources(QPDF& pdf); void handleRotations(QPDF& pdf); - void getUOPagenos( - std::vector& uo, std::map>>& pagenos); + std::map, std::vector> + getUOPagenos(std::vector const& uo); void handleUnderOverlay(QPDF& pdf); std::string doUnderOverlayForPage( QPDF& pdf, std::map>& afdh, UnderOverlay& uo, - std::map>>& pagenos, - size_t page_idx, - size_t uo_idx, + std::map, std::vector> const& pagenos, + std::pair pageno_uo_idx, std::map>& fo, std::vector&& pages, QPDFPageObjectHelper& dest_page); diff --git a/libqpdf/QPDFJob.cc b/libqpdf/QPDFJob.cc index 6201ca1a..64de4b68 100644 --- a/libqpdf/QPDFJob.cc +++ b/libqpdf/QPDFJob.cc @@ -1886,15 +1886,14 @@ QPDFJob::doUnderOverlayForPage( QPDF& pdf, std::map>& afdh, UnderOverlay& uo, - std::map>>& pagenos, - size_t page_idx, - size_t uo_idx, + std::map, std::vector> const& pagenos, + std::pair pageno_uo_idx, std::map>& fo, std::vector&& pages, QPDFPageObjectHelper& dest_page) { - int pageno = 1 + QIntC::to_int(page_idx); - if (!(pagenos.count(pageno) && pagenos[pageno].count(uo_idx))) { + auto pagenos_it = pagenos.find(pageno_uo_idx); + if (pagenos_it == pagenos.end()) { return ""; } @@ -1906,13 +1905,14 @@ QPDFJob::doUnderOverlayForPage( std::string content; int min_suffix = 1; QPDFObjectHandle resources = dest_page.getAttribute("/Resources", true); - for (Page from_page: pagenos[pageno][uo_idx]) { + for (Page from_page: pagenos_it->second) { doIfVerbose([&](Pipeline& v, std::string const& prefix) { v << " " << uo.filename << " " << uo.which << " " << from_page.no << "\n"; }); auto from_page_ph = pages.at(from_page.idx); - if (fo[from_page.no].count(uo_idx) == 0) { - fo[from_page.no][uo_idx] = pdf.copyForeignObject(from_page_ph.getFormXObjectForPage()); + if (fo[from_page.no].count(pageno_uo_idx.second) == 0) { + fo[from_page.no][pageno_uo_idx.second] = + pdf.copyForeignObject(from_page_ph.getFormXObjectForPage()); } // If the same page is overlaid or underlaid multiple times, we'll generate multiple names @@ -1920,13 +1920,16 @@ QPDFJob::doUnderOverlayForPage( std::string name = resources.getUniqueResourceName("/Fx", min_suffix); QPDFMatrix cm; std::string new_content = dest_page.placeFormXObject( - fo[from_page.no][uo_idx], name, dest_page.getTrimBox().getArrayAsRectangle(), cm); + fo[from_page.no][pageno_uo_idx.second], + name, + dest_page.getTrimBox().getArrayAsRectangle(), + cm); dest_page.copyAnnotations(from_page_ph, cm, dest_afdh, make_afdh(from_page_ph)); if (!new_content.empty()) { resources.mergeResources("<< /XObject << >> >>"_qpdf); auto xobject = resources.getKey("/XObject"); if (xobject.isDictionary()) { - xobject.replaceKey(name, fo[from_page.no][uo_idx]); + xobject.replaceKey(name, fo[from_page.no][pageno_uo_idx.second]); } ++min_suffix; content += new_content; @@ -1935,27 +1938,29 @@ QPDFJob::doUnderOverlayForPage( return content; } -void -QPDFJob::getUOPagenos( - std::vector& uos, - std::map>>& pagenos) +std::map, std::vector> +QPDFJob::getUOPagenos(std::vector const& uos) { + std::map, std::vector> pagenos; size_t uo_idx = 0; for (auto const& uo: uos) { size_t page_idx = 0; - size_t from_size = uo.from_pagenos.size(); + auto from_it = uo.from_pagenos.cbegin(); + auto from_end = uo.from_pagenos.cend(); + auto from_size = uo.from_pagenos.size(); size_t repeat_size = uo.repeat_pagenos.size(); for (int to_pageno: uo.to_pagenos) { - if (page_idx < from_size) { - pagenos[to_pageno][uo_idx].push_back(uo.from_pagenos.at(page_idx)); + if (from_it != from_end) { + pagenos[{to_pageno, uo_idx}].emplace_back(*from_it++); } else if (repeat_size) { - pagenos[to_pageno][uo_idx].push_back( + pagenos[{to_pageno, uo_idx}].push_back( uo.repeat_pagenos.at((page_idx - from_size) % repeat_size)); } ++page_idx; } ++uo_idx; } + return pagenos; } void @@ -1973,10 +1978,8 @@ QPDFJob::handleUnderOverlay(QPDF& pdf) // First map key is 1-based page number. Second is index into the overlay/underlay vector. Watch // out to not reverse the keys or be off by one. - std::map>> underlay_pagenos; - std::map>> overlay_pagenos; - getUOPagenos(m->underlay, underlay_pagenos); - getUOPagenos(m->overlay, overlay_pagenos); + auto underlay_pagenos = getUOPagenos(m->underlay); + auto overlay_pagenos = getUOPagenos(m->overlay); doIfVerbose([&](Pipeline& v, std::string const& prefix) { v << prefix << ": processing underlay/overlay\n"; }); @@ -1997,7 +2000,10 @@ QPDFJob::handleUnderOverlay(QPDF& pdf) for (Page page; page.idx < main_npages; ++page) { doIfVerbose( [&](Pipeline& v, std::string const& prefix) { v << " page " << page.no << "\n"; }); - if (underlay_pagenos[page.no].empty() && overlay_pagenos[page.no].empty()) { + if (underlay_pagenos.lower_bound({page.no, 0}) == + underlay_pagenos.lower_bound({page.no + 1, 0}) && + overlay_pagenos.lower_bound({page.no, 0}) == + overlay_pagenos.lower_bound({page.no + 1, 0})) { continue; } // This code converts the original page, any underlays, and any overlays to form XObjects. @@ -2022,8 +2028,7 @@ QPDFJob::handleUnderOverlay(QPDF& pdf) afdh, underlay, underlay_pagenos, - page.idx, - uo_idx, + {page.no, uo_idx}, underlay_fo, get_pages(underlay, uo_idx), dest_page); @@ -2043,8 +2048,7 @@ QPDFJob::handleUnderOverlay(QPDF& pdf) afdh, overlay, overlay_pagenos, - page.idx, - uo_idx, + {page.no, uo_idx}, overlay_fo, get_pages(overlay, uo_idx), dest_page);