Commit 73752683c936af0f5a556982c2c59516d2914ee3

Authored by Jay Berkenbilt
1 parent a3a3203f

Fix overlay/underlay on page with no resources (fixes #527)

ChangeLog
  1 +2021-11-03 Jay Berkenbilt <ejb@ql.org>
  2 +
  3 + * Bug fix: make overlay/underlay work on a page with no resource
  4 + dictionary. Fixes #527.
  5 +
1 2021-11-02 Jay Berkenbilt <ejb@ql.org> 6 2021-11-02 Jay Berkenbilt <ejb@ql.org>
2 7
3 * Add QPDF::findPage to the public API. This is primarily to help 8 * Add QPDF::findPage to the public API. This is primarily to help
manual/qpdf-manual.xml
@@ -5080,6 +5080,12 @@ print &quot;\n&quot;; @@ -5080,6 +5080,12 @@ print &quot;\n&quot;;
5080 that could occur when given bogus input. 5080 that could occur when given bogus input.
5081 </para> 5081 </para>
5082 </listitem> 5082 </listitem>
  5083 + <listitem>
  5084 + <para>
  5085 + Properly handle overlay/underlay on completely empty pages
  5086 + (with no resource dictionary).
  5087 + </para>
  5088 + </listitem>
5083 </itemizedlist> 5089 </itemizedlist>
5084 </listitem> 5090 </listitem>
5085 <listitem> 5091 <listitem>
qpdf/qpdf.cc
@@ -5226,6 +5226,12 @@ static void do_under_overlay_for_page( @@ -5226,6 +5226,12 @@ static void do_under_overlay_for_page(
5226 std::string content; 5226 std::string content;
5227 int min_suffix = 1; 5227 int min_suffix = 1;
5228 QPDFObjectHandle resources = dest_page.getAttribute("/Resources", true); 5228 QPDFObjectHandle resources = dest_page.getAttribute("/Resources", true);
  5229 + if (! resources.isDictionary())
  5230 + {
  5231 + QTC::TC("qpdf", "qpdf overlay page with no resources");
  5232 + resources = QPDFObjectHandle::newDictionary();
  5233 + dest_page.getObjectHandle().replaceKey("/Resources", resources);
  5234 + }
5229 for (std::vector<int>::iterator iter = pagenos[pageno].begin(); 5235 for (std::vector<int>::iterator iter = pagenos[pageno].begin();
5230 iter != pagenos[pageno].end(); ++iter) 5236 iter != pagenos[pageno].end(); ++iter)
5231 { 5237 {
@@ -5257,7 +5263,11 @@ static void do_under_overlay_for_page( @@ -5257,7 +5263,11 @@ static void do_under_overlay_for_page(
5257 { 5263 {
5258 resources.mergeResources( 5264 resources.mergeResources(
5259 QPDFObjectHandle::parse("<< /XObject << >> >>")); 5265 QPDFObjectHandle::parse("<< /XObject << >> >>"));
5260 - resources.getKey("/XObject").replaceKey(name, fo[from_pageno]); 5266 + auto xobject = resources.getKey("/XObject");
  5267 + if (xobject.isDictionary())
  5268 + {
  5269 + xobject.replaceKey(name, fo[from_pageno]);
  5270 + }
5261 ++min_suffix; 5271 ++min_suffix;
5262 content += new_content; 5272 content += new_content;
5263 } 5273 }
qpdf/qpdf.testcov
@@ -596,3 +596,4 @@ QPDFWriter preserve object streams 1 @@ -596,3 +596,4 @@ QPDFWriter preserve object streams 1
596 QPDFWriter exclude from object stream 0 596 QPDFWriter exclude from object stream 0
597 check unclosed --pages 1 597 check unclosed --pages 1
598 QPDF_pages findPage not found 0 598 QPDF_pages findPage not found 0
  599 +qpdf overlay page with no resources 0
qpdf/qtest/qpdf.test
@@ -477,7 +477,7 @@ $td-&gt;runtest(&quot;compare files&quot;, @@ -477,7 +477,7 @@ $td-&gt;runtest(&quot;compare files&quot;,
477 show_ntests(); 477 show_ntests();
478 # ---------- 478 # ----------
479 $td->notify("--- Form XObject, underlay, overlay ---"); 479 $td->notify("--- Form XObject, underlay, overlay ---");
480 -$n_tests += 20; 480 +$n_tests += 22;
481 481
482 $td->runtest("form xobject creation", 482 $td->runtest("form xobject creation",
483 {$td->COMMAND => "test_driver 55 fxo-red.pdf"}, 483 {$td->COMMAND => "test_driver 55 fxo-red.pdf"},
@@ -550,6 +550,15 @@ $td-&gt;runtest(&quot;page operations on form xobject&quot;, @@ -550,6 +550,15 @@ $td-&gt;runtest(&quot;page operations on form xobject&quot;,
550 {$td->FILE => "page-ops-on-form-xobject.out", 550 {$td->FILE => "page-ops-on-form-xobject.out",
551 $td->EXIT_STATUS => 0}, 551 $td->EXIT_STATUS => 0},
552 $td->NORMALIZE_NEWLINES); 552 $td->NORMALIZE_NEWLINES);
  553 +$td->runtest("overlay on page with no resources",
  554 + {$td->COMMAND =>
  555 + "qpdf --deterministic-id page-with-no-resources.pdf" .
  556 + " --overlay minimal.pdf -- a.pdf"},
  557 + {$td->STRING => "", $td->EXIT_STATUS => 0},
  558 + $td->NORMALIZE_NEWLINES);
  559 +$td->runtest("check overlay with no resources output",
  560 + {$td->FILE => "a.pdf"},
  561 + {$td->FILE => "overlay-no-resources.pdf"});
553 562
554 show_ntests(); 563 show_ntests();
555 # ---------- 564 # ----------
qpdf/qtest/qpdf/overlay-no-resources.pdf 0 → 100644
No preview for this file type
qpdf/qtest/qpdf/page-with-no-resources.pdf 0 → 100644
  1 +%PDF-1.3
  2 +%¿÷¢þ
  3 +1 0 obj
  4 +<< /Pages 2 0 R /Type /Catalog >>
  5 +endobj
  6 +2 0 obj
  7 +<< /Count 1 /Kids [ 3 0 R ] /Type /Pages >>
  8 +endobj
  9 +3 0 obj
  10 +<< /MediaBox [ 0.0 0.0 612 792 ] /Parent 2 0 R /Type /Page >>
  11 +endobj
  12 +xref
  13 +0 4
  14 +0000000000 65535 f
  15 +0000000015 00000 n
  16 +0000000064 00000 n
  17 +0000000123 00000 n
  18 +trailer << /Root 1 0 R /Size 4 /ID [<f47f51552a4f2e020e12a656e72ed64c><0c18b42478a35cdccff23c62f4c7b946>] >>
  19 +startxref
  20 +200
  21 +%%EOF