Commit 73752683c936af0f5a556982c2c59516d2914ee3
1 parent
a3a3203f
Fix overlay/underlay on page with no resources (fixes #527)
Showing
7 changed files
with
54 additions
and
2 deletions
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 "\n"; | @@ -5080,6 +5080,12 @@ print "\n"; | ||
| 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->runtest("compare files", | @@ -477,7 +477,7 @@ $td->runtest("compare files", | ||
| 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->runtest("page operations on form xobject", | @@ -550,6 +550,15 @@ $td->runtest("page operations on form xobject", | ||
| 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 |