Commit ca5fafb0f8779507c95a75e5d9eb712613e43702

Authored by m-holger
Committed by GitHub
2 parents fd71c95e 4069df97

Merge pull request #1637 from m-holger/ca

Enhance `AcroForm::transformAnnotations` to update '/P' field
libqpdf/QPDFAcroFormDocumentHelper.cc
@@ -843,7 +843,14 @@ QPDFAcroFormDocumentHelper::transformAnnotations( @@ -843,7 +843,14 @@ QPDFAcroFormDocumentHelper::transformAnnotations(
843 from_afdh = &QPDFAcroFormDocumentHelper::get(*from_qpdf); 843 from_afdh = &QPDFAcroFormDocumentHelper::get(*from_qpdf);
844 } 844 }
845 m->transformAnnotations( 845 m->transformAnnotations(
846 - a_old_annots, new_annots, new_fields, old_fields, cm, from_qpdf, from_afdh->m.get()); 846 + a_old_annots,
  847 + new_annots,
  848 + new_fields,
  849 + old_fields,
  850 + cm,
  851 + from_qpdf,
  852 + from_afdh->m.get(),
  853 + nullptr);
847 } 854 }
848 855
849 void 856 void
@@ -854,7 +861,8 @@ AcroForm::transformAnnotations( @@ -854,7 +861,8 @@ AcroForm::transformAnnotations(
854 std::set<QPDFObjGen>& old_fields, 861 std::set<QPDFObjGen>& old_fields,
855 QPDFMatrix const& cm, 862 QPDFMatrix const& cm,
856 QPDF* from_qpdf, 863 QPDF* from_qpdf,
857 - AcroForm* from_afdh) 864 + AcroForm* from_afdh,
  865 + QPDFObjectHandle* new_page)
858 { 866 {
859 qpdf_expect(from_qpdf); 867 qpdf_expect(from_qpdf);
860 qpdf_expect(from_afdh); 868 qpdf_expect(from_afdh);
@@ -1149,6 +1157,9 @@ AcroForm::transformAnnotations( @@ -1149,6 +1157,9 @@ AcroForm::transformAnnotations(
1149 } 1157 }
1150 auto rect = cm.transformRectangle(annot["/Rect"].getArrayAsRectangle()); 1158 auto rect = cm.transformRectangle(annot["/Rect"].getArrayAsRectangle());
1151 annot.replaceKey("/Rect", QPDFObjectHandle::newFromRectangle(rect)); 1159 annot.replaceKey("/Rect", QPDFObjectHandle::newFromRectangle(rect));
  1160 + if (new_page && annot.contains("/P")) {
  1161 + annot.replace("/P", *new_page);
  1162 + }
1152 } 1163 }
1153 } 1164 }
1154 1165
@@ -1169,7 +1180,7 @@ AcroForm::fixCopiedAnnotations( @@ -1169,7 +1180,7 @@ AcroForm::fixCopiedAnnotations(
1169 AcroForm& from_afdh, 1180 AcroForm& from_afdh,
1170 std::set<QPDFObjGen>* added_fields) 1181 std::set<QPDFObjGen>* added_fields)
1171 { 1182 {
1172 - auto old_annots = from_page.getKey("/Annots"); 1183 + auto const& old_annots = from_page.getKey("/Annots");
1173 if (old_annots.empty() || !old_annots.isArray()) { 1184 if (old_annots.empty() || !old_annots.isArray()) {
1174 return; 1185 return;
1175 } 1186 }
@@ -1184,7 +1195,8 @@ AcroForm::fixCopiedAnnotations( @@ -1184,7 +1195,8 @@ AcroForm::fixCopiedAnnotations(
1184 old_fields, 1195 old_fields,
1185 QPDFMatrix(), 1196 QPDFMatrix(),
1186 &(from_afdh.qpdf), 1197 &(from_afdh.qpdf),
1187 - &from_afdh); 1198 + &from_afdh,
  1199 + &to_page);
1188 1200
1189 to_page.replaceKey("/Annots", QPDFObjectHandle::newArray(new_annots)); 1201 to_page.replaceKey("/Annots", QPDFObjectHandle::newArray(new_annots));
1190 addAndRenameFormFields(new_fields); 1202 addAndRenameFormFields(new_fields);
libqpdf/qpdf/AcroForm.hh
@@ -166,7 +166,8 @@ namespace qpdf::impl @@ -166,7 +166,8 @@ namespace qpdf::impl
166 std::set<QPDFObjGen>& old_fields, 166 std::set<QPDFObjGen>& old_fields,
167 QPDFMatrix const& cm, 167 QPDFMatrix const& cm,
168 QPDF* from_qpdf, 168 QPDF* from_qpdf,
169 - AcroForm* from_afdh); 169 + AcroForm* from_afdh,
  170 + QPDFObjectHandle* new_page);
170 171
171 // Copy form fields and annotations from one page to another, allowing the from page to be 172 // Copy form fields and annotations from one page to another, allowing the from page to be
172 // in a different QPDF or in the same QPDF. This would typically be called after calling 173 // in a different QPDF or in the same QPDF. This would typically be called after calling
libqpdf/qpdf/QPDFObjectHandle_private.hh
@@ -324,6 +324,12 @@ namespace qpdf @@ -324,6 +324,12 @@ namespace qpdf
324 { 324 {
325 } 325 }
326 326
  327 + explicit
  328 + operator bool() const
  329 + {
  330 + return obj != nullptr;
  331 + }
  332 +
327 // Return the integer value. If the object is not a valid Integer, throw a 333 // Return the integer value. If the object is not a valid Integer, throw a
328 // std::invalid_argument exception. If the object is out of range for the target type, 334 // std::invalid_argument exception. If the object is out of range for the target type,
329 // throw a std::overflow_error or std::underflow_error exception. 335 // throw a std::overflow_error or std::underflow_error exception.
manual/release-notes.rst
@@ -43,6 +43,9 @@ more detail. @@ -43,6 +43,9 @@ more detail.
43 - When parsing qpdf JSON input files allow empty name objects. These are 43 - When parsing qpdf JSON input files allow empty name objects. These are
44 allowed by the PDF specification but were previously rejected. 44 allowed by the PDF specification but were previously rejected.
45 45
  46 + - ``QPDFAcroFormDocumentHelper::fixCopiedAnnotations`` now correctly
  47 + updates any annotation's ``/P`` entries to point to the owning page.
  48 +
46 - Library Enhancements 49 - Library Enhancements
47 50
48 - Add ``QPDFNameTreeObjectHelper`` and ``QPDFNumberTreeObjectHelper`` 51 - Add ``QPDFNameTreeObjectHelper`` and ``QPDFNumberTreeObjectHelper``
qpdf/qtest/copy-annotations.test
@@ -71,8 +71,7 @@ $td-&gt;runtest(&quot;copy annotations with /P entry&quot;, @@ -71,8 +71,7 @@ $td-&gt;runtest(&quot;copy annotations with /P entry&quot;,
71 71
72 $td->runtest("check output", 72 $td->runtest("check output",
73 {$td->FILE => "a.pdf"}, 73 {$td->FILE => "a.pdf"},
74 - {$td->FILE => "annotations-no-acroform-with-p.out.pdf"},  
75 - $td->EXPECT_FAILURE); 74 + {$td->FILE => "annotations-no-acroform-with-p.out.pdf"});
76 75
77 $td->runtest("copy annotations no acroform from foreign file", 76 $td->runtest("copy annotations no acroform from foreign file",
78 {$td->COMMAND => 77 {$td->COMMAND =>
@@ -167,7 +166,7 @@ $td-&gt;runtest(&quot;check output&quot;, @@ -167,7 +166,7 @@ $td-&gt;runtest(&quot;check output&quot;,
167 # field-resource-conflict.pdf was crafted so that an appearance stream 166 # field-resource-conflict.pdf was crafted so that an appearance stream
168 # had an existing resource that it actually referenced in the 167 # had an existing resource that it actually referenced in the
169 # appearance stream whose name, /F1_1, clashed with the result of 168 # appearance stream whose name, /F1_1, clashed with the result of
170 -# resolving conflicts in /DR. It's a crazy corner case, but it if it 169 +# resolving conflicts in /DR. It's a crazy corner case, but if it
171 # ever happened, it would be really hard to track down, and it could 170 # ever happened, it would be really hard to track down, and it could
172 # arise through multiple passes through qpdf with intervening edits. 171 # arise through multiple passes through qpdf with intervening edits.
173 $td->runtest("appearance stream resource conflict", 172 $td->runtest("appearance stream resource conflict",
qpdf/qtest/qpdf/resolved-appearance-conflicts.pdf
@@ -119,7 +119,7 @@ endobj @@ -119,7 +119,7 @@ endobj
119 /MK << 119 /MK <<
120 /CA (8) 120 /CA (8)
121 >> 121 >>
122 - /P 17 0 R 122 + /P 26 0 R
123 /Rect [ 123 /Rect [
124 174.5 124 174.5
125 719.7 125 719.7
@@ -136,7 +136,7 @@ endobj @@ -136,7 +136,7 @@ endobj
136 6 0 obj 136 6 0 obj
137 << 137 <<
138 /AP << 138 /AP <<
139 - /N 26 0 R 139 + /N 27 0 R
140 >> 140 >>
141 /DA (0.29803 0.29803 0.29803 rg /F1 12 Tf) 141 /DA (0.29803 0.29803 0.29803 rg /F1 12 Tf)
142 /DR << 142 /DR <<
@@ -145,7 +145,7 @@ endobj @@ -145,7 +145,7 @@ endobj
145 /DV <feff> 145 /DV <feff>
146 /F 4 146 /F 4
147 /FT /Tx 147 /FT /Tx
148 - /P 17 0 R 148 + /P 26 0 R
149 /Rect [ 149 /Rect [
150 59.6 150 59.6
151 715 151 715
@@ -163,8 +163,8 @@ endobj @@ -163,8 +163,8 @@ endobj
163 << 163 <<
164 /AP << 164 /AP <<
165 /N << 165 /N <<
166 - /Off 28 0 R  
167 - /Yes 30 0 R 166 + /Off 29 0 R
  167 + /Yes 31 0 R
168 >> 168 >>
169 >> 169 >>
170 /AS /Off 170 /AS /Off
@@ -176,7 +176,7 @@ endobj @@ -176,7 +176,7 @@ endobj
176 /MK << 176 /MK <<
177 /CA (8) 177 /CA (8)
178 >> 178 >>
179 - /P 32 0 R 179 + /P 33 0 R
180 /Rect [ 180 /Rect [
181 174.5 181 174.5
182 719.7 182 719.7
@@ -193,14 +193,14 @@ endobj @@ -193,14 +193,14 @@ endobj
193 8 0 obj 193 8 0 obj
194 << 194 <<
195 /AP << 195 /AP <<
196 - /N 33 0 R 196 + /N 34 0 R
197 >> 197 >>
198 /DA (0.29803 0.29803 0.29803 rg /F1_1 12 Tf) 198 /DA (0.29803 0.29803 0.29803 rg /F1_1 12 Tf)
199 /DR 2 0 R 199 /DR 2 0 R
200 /DV <feff> 200 /DV <feff>
201 /F 4 201 /F 4
202 /FT /Tx 202 /FT /Tx
203 - /P 32 0 R 203 + /P 33 0 R
204 /Rect [ 204 /Rect [
205 59.6 205 59.6
206 715 206 715
@@ -219,8 +219,8 @@ endobj @@ -219,8 +219,8 @@ endobj
219 /Count 3 219 /Count 3
220 /Kids [ 220 /Kids [
221 17 0 R 221 17 0 R
222 - 35 0 R  
223 - 32 0 R 222 + 26 0 R
  223 + 33 0 R
224 ] 224 ]
225 /Type /Pages 225 /Type /Pages
226 >> 226 >>
@@ -431,8 +431,41 @@ endobj @@ -431,8 +431,41 @@ endobj
431 81 431 81
432 endobj 432 endobj
433 433
  434 +%% Page 2
434 26 0 obj 435 26 0 obj
435 << 436 <<
  437 + /Annots [
  438 + 5 0 R
  439 + 6 0 R
  440 + ]
  441 + /Contents 37 0 R
  442 + /Group <<
  443 + /CS /DeviceRGB
  444 + /I true
  445 + /S /Transparency
  446 + >>
  447 + /MediaBox [
  448 + 0
  449 + 0
  450 + 611.971653543307
  451 + 791.971653543307
  452 + ]
  453 + /Parent 9 0 R
  454 + /Resources <<
  455 + /Font <<
  456 + /F1 10 0 R
  457 + >>
  458 + /ProcSet [
  459 + /PDF
  460 + /Text
  461 + ]
  462 + >>
  463 + /Type /Page
  464 +>>
  465 +endobj
  466 +
  467 +27 0 obj
  468 +<<
436 /BBox [ 469 /BBox [
437 0 470 0
438 0 471 0
@@ -447,7 +480,7 @@ endobj @@ -447,7 +480,7 @@ endobj
447 >> 480 >>
448 /Subtype /Form 481 /Subtype /Form
449 /Type /XObject 482 /Type /XObject
450 - /Length 27 0 R 483 + /Length 28 0 R
451 >> 484 >>
452 stream 485 stream
453 BT /F1_1 12 Tf ET 486 BT /F1_1 12 Tf ET
@@ -456,11 +489,11 @@ EMC @@ -456,11 +489,11 @@ EMC
456 endstream 489 endstream
457 endobj 490 endobj
458 491
459 -27 0 obj 492 +28 0 obj
460 30 493 30
461 endobj 494 endobj
462 495
463 -28 0 obj 496 +29 0 obj
464 << 497 <<
465 /BBox [ 498 /BBox [
466 0 499 0
@@ -471,7 +504,7 @@ endobj @@ -471,7 +504,7 @@ endobj
471 /Resources 39 0 R 504 /Resources 39 0 R
472 /Subtype /Form 505 /Subtype /Form
473 /Type /XObject 506 /Type /XObject
474 - /Length 29 0 R 507 + /Length 30 0 R
475 >> 508 >>
476 stream 509 stream
477 /Tx BMC 510 /Tx BMC
@@ -479,11 +512,11 @@ EMC @@ -479,11 +512,11 @@ EMC
479 endstream 512 endstream
480 endobj 513 endobj
481 514
482 -29 0 obj 515 +30 0 obj
483 12 516 12
484 endobj 517 endobj
485 518
486 -30 0 obj 519 +31 0 obj
487 << 520 <<
488 /BBox [ 521 /BBox [
489 0 522 0
@@ -494,7 +527,7 @@ endobj @@ -494,7 +527,7 @@ endobj
494 /Resources 40 0 R 527 /Resources 40 0 R
495 /Subtype /Form 528 /Subtype /Form
496 /Type /XObject 529 /Type /XObject
497 - /Length 31 0 R 530 + /Length 32 0 R
498 >> 531 >>
499 stream 532 stream
500 /Tx BMC 533 /Tx BMC
@@ -507,12 +540,12 @@ EMC @@ -507,12 +540,12 @@ EMC
507 endstream 540 endstream
508 endobj 541 endobj
509 542
510 -31 0 obj 543 +32 0 obj
511 83 544 83
512 endobj 545 endobj
513 546
514 %% Page 3 547 %% Page 3
515 -32 0 obj 548 +33 0 obj
516 << 549 <<
517 /Annots [ 550 /Annots [
518 7 0 R 551 7 0 R
@@ -544,7 +577,7 @@ endobj @@ -544,7 +577,7 @@ endobj
544 >> 577 >>
545 endobj 578 endobj
546 579
547 -33 0 obj 580 +34 0 obj
548 << 581 <<
549 /BBox [ 582 /BBox [
550 0 583 0
@@ -560,7 +593,7 @@ endobj @@ -560,7 +593,7 @@ endobj
560 >> 593 >>
561 /Subtype /Form 594 /Subtype /Form
562 /Type /XObject 595 /Type /XObject
563 - /Length 34 0 R 596 + /Length 35 0 R
564 >> 597 >>
565 stream 598 stream
566 BT /F1_1_1 12 Tf ET 599 BT /F1_1_1 12 Tf ET
@@ -569,41 +602,8 @@ EMC @@ -569,41 +602,8 @@ EMC
569 endstream 602 endstream
570 endobj 603 endobj
571 604
572 -34 0 obj  
573 -32  
574 -endobj  
575 -  
576 -%% Page 2  
577 35 0 obj 605 35 0 obj
578 -<<  
579 - /Annots [  
580 - 5 0 R  
581 - 6 0 R  
582 - ]  
583 - /Contents 37 0 R  
584 - /Group <<  
585 - /CS /DeviceRGB  
586 - /I true  
587 - /S /Transparency  
588 - >>  
589 - /MediaBox [  
590 - 0  
591 - 0  
592 - 611.971653543307  
593 - 791.971653543307  
594 - ]  
595 - /Parent 9 0 R  
596 - /Resources <<  
597 - /Font <<  
598 - /F1 10 0 R  
599 - >>  
600 - /ProcSet [  
601 - /PDF  
602 - /Text  
603 - ]  
604 - >>  
605 - /Type /Page  
606 ->> 606 +32
607 endobj 607 endobj
608 608
609 36 0 obj 609 36 0 obj
@@ -742,16 +742,16 @@ xref @@ -742,16 +742,16 @@ xref
742 0000004092 00000 n 742 0000004092 00000 n
743 0000004112 00000 n 743 0000004112 00000 n
744 0000004347 00000 n 744 0000004347 00000 n
745 -0000004367 00000 n  
746 -0000004610 00000 n  
747 -0000004630 00000 n  
748 -0000004797 00000 n  
749 -0000004817 00000 n  
750 -0000005055 00000 n  
751 -0000005085 00000 n  
752 -0000005436 00000 n  
753 -0000005685 00000 n  
754 -0000005715 00000 n 745 +0000004377 00000 n
  746 +0000004728 00000 n
  747 +0000004971 00000 n
  748 +0000004991 00000 n
  749 +0000005158 00000 n
  750 +0000005178 00000 n
  751 +0000005416 00000 n
  752 +0000005446 00000 n
  753 +0000005797 00000 n
  754 +0000006046 00000 n
755 0000006066 00000 n 755 0000006066 00000 n
756 0000006194 00000 n 756 0000006194 00000 n
757 0000006531 00000 n 757 0000006531 00000 n