2
1
mirror of https://github.com/qpdf/qpdf.git synced 2025-02-09 15:18:29 +00:00

In QPDFJob::handleUnderOverlay flatten nested under/overlay_pagenos maps

Also, in QPDFJob::getUOPagenos tweak vector access and change signature to
return result and make parameter const. In doUnderOverlayForPage make
pagenos parameter a const&.
This commit is contained in:
m-holger 2024-01-15 01:03:41 +00:00
parent b84a08f447
commit 09ddce19e8
2 changed files with 35 additions and 32 deletions

View File

@ -514,16 +514,15 @@ class QPDFJob
void handlePageSpecs(QPDF& pdf, std::vector<std::unique_ptr<QPDF>>& page_heap); void handlePageSpecs(QPDF& pdf, std::vector<std::unique_ptr<QPDF>>& page_heap);
bool shouldRemoveUnreferencedResources(QPDF& pdf); bool shouldRemoveUnreferencedResources(QPDF& pdf);
void handleRotations(QPDF& pdf); void handleRotations(QPDF& pdf);
void getUOPagenos( std::map<std::pair<int, size_t>, std::vector<int>>
std::vector<UnderOverlay>& uo, std::map<int, std::map<size_t, std::vector<int>>>& pagenos); getUOPagenos(std::vector<UnderOverlay> const& uo);
void handleUnderOverlay(QPDF& pdf); void handleUnderOverlay(QPDF& pdf);
std::string doUnderOverlayForPage( std::string doUnderOverlayForPage(
QPDF& pdf, QPDF& pdf,
std::map<unsigned long long int, std::unique_ptr<QPDFAcroFormDocumentHelper>>& afdh, std::map<unsigned long long int, std::unique_ptr<QPDFAcroFormDocumentHelper>>& afdh,
UnderOverlay& uo, UnderOverlay& uo,
std::map<int, std::map<size_t, std::vector<int>>>& pagenos, std::map<std::pair<int, size_t>, std::vector<int>> const& pagenos,
size_t page_idx, std::pair<int, size_t> pageno_uo_idx,
size_t uo_idx,
std::map<int, std::map<size_t, QPDFObjectHandle>>& fo, std::map<int, std::map<size_t, QPDFObjectHandle>>& fo,
std::vector<QPDFPageObjectHelper>&& pages, std::vector<QPDFPageObjectHelper>&& pages,
QPDFPageObjectHelper& dest_page); QPDFPageObjectHelper& dest_page);

View File

@ -1886,15 +1886,14 @@ QPDFJob::doUnderOverlayForPage(
QPDF& pdf, QPDF& pdf,
std::map<unsigned long long int, std::unique_ptr<QPDFAcroFormDocumentHelper>>& afdh, std::map<unsigned long long int, std::unique_ptr<QPDFAcroFormDocumentHelper>>& afdh,
UnderOverlay& uo, UnderOverlay& uo,
std::map<int, std::map<size_t, std::vector<int>>>& pagenos, std::map<std::pair<int, size_t>, std::vector<int>> const& pagenos,
size_t page_idx, std::pair<int, size_t> pageno_uo_idx,
size_t uo_idx,
std::map<int, std::map<size_t, QPDFObjectHandle>>& fo, std::map<int, std::map<size_t, QPDFObjectHandle>>& fo,
std::vector<QPDFPageObjectHelper>&& pages, std::vector<QPDFPageObjectHelper>&& pages,
QPDFPageObjectHelper& dest_page) QPDFPageObjectHelper& dest_page)
{ {
int pageno = 1 + QIntC::to_int(page_idx); auto pagenos_it = pagenos.find(pageno_uo_idx);
if (!(pagenos.count(pageno) && pagenos[pageno].count(uo_idx))) { if (pagenos_it == pagenos.end()) {
return ""; return "";
} }
@ -1906,13 +1905,14 @@ QPDFJob::doUnderOverlayForPage(
std::string content; std::string content;
int min_suffix = 1; int min_suffix = 1;
QPDFObjectHandle resources = dest_page.getAttribute("/Resources", true); 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) { doIfVerbose([&](Pipeline& v, std::string const& prefix) {
v << " " << uo.filename << " " << uo.which << " " << from_page.no << "\n"; v << " " << uo.filename << " " << uo.which << " " << from_page.no << "\n";
}); });
auto from_page_ph = pages.at(from_page.idx); auto from_page_ph = pages.at(from_page.idx);
if (fo[from_page.no].count(uo_idx) == 0) { if (fo[from_page.no].count(pageno_uo_idx.second) == 0) {
fo[from_page.no][uo_idx] = pdf.copyForeignObject(from_page_ph.getFormXObjectForPage()); 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 // 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); std::string name = resources.getUniqueResourceName("/Fx", min_suffix);
QPDFMatrix cm; QPDFMatrix cm;
std::string new_content = dest_page.placeFormXObject( 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)); dest_page.copyAnnotations(from_page_ph, cm, dest_afdh, make_afdh(from_page_ph));
if (!new_content.empty()) { if (!new_content.empty()) {
resources.mergeResources("<< /XObject << >> >>"_qpdf); resources.mergeResources("<< /XObject << >> >>"_qpdf);
auto xobject = resources.getKey("/XObject"); auto xobject = resources.getKey("/XObject");
if (xobject.isDictionary()) { 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; ++min_suffix;
content += new_content; content += new_content;
@ -1935,27 +1938,29 @@ QPDFJob::doUnderOverlayForPage(
return content; return content;
} }
void std::map<std::pair<int, size_t>, std::vector<int>>
QPDFJob::getUOPagenos( QPDFJob::getUOPagenos(std::vector<QPDFJob::UnderOverlay> const& uos)
std::vector<QPDFJob::UnderOverlay>& uos,
std::map<int, std::map<size_t, std::vector<int>>>& pagenos)
{ {
std::map<std::pair<int, size_t>, std::vector<int>> pagenos;
size_t uo_idx = 0; size_t uo_idx = 0;
for (auto const& uo: uos) { for (auto const& uo: uos) {
size_t page_idx = 0; 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(); size_t repeat_size = uo.repeat_pagenos.size();
for (int to_pageno: uo.to_pagenos) { for (int to_pageno: uo.to_pagenos) {
if (page_idx < from_size) { if (from_it != from_end) {
pagenos[to_pageno][uo_idx].push_back(uo.from_pagenos.at(page_idx)); pagenos[{to_pageno, uo_idx}].emplace_back(*from_it++);
} else if (repeat_size) { } 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)); uo.repeat_pagenos.at((page_idx - from_size) % repeat_size));
} }
++page_idx; ++page_idx;
} }
++uo_idx; ++uo_idx;
} }
return pagenos;
} }
void 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 // 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. // out to not reverse the keys or be off by one.
std::map<int, std::map<size_t, std::vector<int>>> underlay_pagenos; auto underlay_pagenos = getUOPagenos(m->underlay);
std::map<int, std::map<size_t, std::vector<int>>> overlay_pagenos; auto overlay_pagenos = getUOPagenos(m->overlay);
getUOPagenos(m->underlay, underlay_pagenos);
getUOPagenos(m->overlay, overlay_pagenos);
doIfVerbose([&](Pipeline& v, std::string const& prefix) { doIfVerbose([&](Pipeline& v, std::string const& prefix) {
v << prefix << ": processing underlay/overlay\n"; v << prefix << ": processing underlay/overlay\n";
}); });
@ -1997,7 +2000,10 @@ QPDFJob::handleUnderOverlay(QPDF& pdf)
for (Page page; page.idx < main_npages; ++page) { for (Page page; page.idx < main_npages; ++page) {
doIfVerbose( doIfVerbose(
[&](Pipeline& v, std::string const& prefix) { v << " page " << page.no << "\n"; }); [&](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; continue;
} }
// This code converts the original page, any underlays, and any overlays to form XObjects. // This code converts the original page, any underlays, and any overlays to form XObjects.
@ -2022,8 +2028,7 @@ QPDFJob::handleUnderOverlay(QPDF& pdf)
afdh, afdh,
underlay, underlay,
underlay_pagenos, underlay_pagenos,
page.idx, {page.no, uo_idx},
uo_idx,
underlay_fo, underlay_fo,
get_pages(underlay, uo_idx), get_pages(underlay, uo_idx),
dest_page); dest_page);
@ -2043,8 +2048,7 @@ QPDFJob::handleUnderOverlay(QPDF& pdf)
afdh, afdh,
overlay, overlay,
overlay_pagenos, overlay_pagenos,
page.idx, {page.no, uo_idx},
uo_idx,
overlay_fo, overlay_fo,
get_pages(overlay, uo_idx), get_pages(overlay, uo_idx),
dest_page); dest_page);