aboutsummaryrefslogtreecommitdiffstats
path: root/libqpdf/QPDFJob.cc
diff options
context:
space:
mode:
authorJay Berkenbilt <ejb@ql.org>2023-02-25 18:55:47 +0100
committerJay Berkenbilt <ejb@ql.org>2023-02-25 18:58:51 +0100
commit78f7dc9fe81d6d10edaa620a0319ab9d0dce84ff (patch)
tree2adeba185a6c287f40ad9234011b77076c2cbe91 /libqpdf/QPDFJob.cc
parent48bacbf2e66b08c9f738416044d5797554ffa203 (diff)
downloadqpdf-78f7dc9fe81d6d10edaa620a0319ab9d0dce84ff.tar.zst
Overlay/underlay: capture origial page as form XObject (fixes #904)
Diffstat (limited to 'libqpdf/QPDFJob.cc')
-rw-r--r--libqpdf/QPDFJob.cc39
1 files changed, 26 insertions, 13 deletions
diff --git a/libqpdf/QPDFJob.cc b/libqpdf/QPDFJob.cc
index 06d93fd7..dabbf2ea 100644
--- a/libqpdf/QPDFJob.cc
+++ b/libqpdf/QPDFJob.cc
@@ -2082,11 +2082,6 @@ QPDFJob::doUnderOverlayForPage(
std::string content;
int min_suffix = 1;
QPDFObjectHandle resources = dest_page.getAttribute("/Resources", true);
- if (!resources.isDictionary()) {
- QTC::TC("qpdf", "QPDFJob overlay page with no resources");
- resources = dest_page.getObjectHandle().replaceKeyAndGetNew(
- "/Resources", QPDFObjectHandle::newDictionary());
- }
for (int from_pageno: pagenos[pageno]) {
doIfVerbose([&](Pipeline& v, std::string const& prefix) {
v << " " << uo.which << " " << from_pageno << "\n";
@@ -2179,7 +2174,24 @@ QPDFJob::handleUnderOverlay(QPDF& pdf)
overlay_pagenos.count(pageno))) {
continue;
}
+ // This code converts the original page, any underlays, and
+ // any overlays to form XObjects. Then it concatenates display
+ // of all underlays, the original page, and all overlays.
+ // Prior to 11.3.0, the original page contents were wrapped in
+ // q/Q, but this didin't work if the original page had
+ // unbalanced q/Q operators. See github issue #904.
auto& dest_page = main_pages.at(i);
+ auto dest_page_oh = dest_page.getObjectHandle();
+ auto this_page_fo = dest_page.getFormXObjectForPage();
+ // The resulting form xobject lazily reads the content from
+ // the original page, which we are going to replace. Therefore
+ // we have to explicitly copy it.
+ auto content_data = this_page_fo.getRawStreamData();
+ this_page_fo.replaceStreamData(
+ content_data, QPDFObjectHandle(), QPDFObjectHandle());
+ auto resources = dest_page_oh.replaceKeyAndGetNew(
+ "/Resources", "<< /XObject << >> >>"_qpdf);
+ resources.getKey("/XObject").replaceKeyAndGetNew("/Fx0", this_page_fo);
auto content = doUnderOverlayForPage(
pdf,
m->underlay,
@@ -2188,15 +2200,16 @@ QPDFJob::handleUnderOverlay(QPDF& pdf)
underlay_fo,
upages,
dest_page);
- if (!content.empty()) {
- dest_page.addPageContents(pdf.newStream(content), true);
- }
- content = doUnderOverlayForPage(
+ content += dest_page.placeFormXObject(
+ this_page_fo,
+ "/Fx0",
+ dest_page.getMediaBox().getArrayAsRectangle(),
+ true,
+ false,
+ false);
+ content += doUnderOverlayForPage(
pdf, m->overlay, overlay_pagenos, i, overlay_fo, opages, dest_page);
- if (!content.empty()) {
- dest_page.addPageContents(pdf.newStream("q\n"), true);
- dest_page.addPageContents(pdf.newStream("\nQ\n" + content), false);
- }
+ dest_page_oh.replaceKey("/Contents", pdf.newStream(content));
}
}