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 843 from_afdh = &QPDFAcroFormDocumentHelper::get(*from_qpdf);
844 844 }
845 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 856 void
... ... @@ -854,7 +861,8 @@ AcroForm::transformAnnotations(
854 861 std::set<QPDFObjGen>& old_fields,
855 862 QPDFMatrix const& cm,
856 863 QPDF* from_qpdf,
857   - AcroForm* from_afdh)
  864 + AcroForm* from_afdh,
  865 + QPDFObjectHandle* new_page)
858 866 {
859 867 qpdf_expect(from_qpdf);
860 868 qpdf_expect(from_afdh);
... ... @@ -1149,6 +1157,9 @@ AcroForm::transformAnnotations(
1149 1157 }
1150 1158 auto rect = cm.transformRectangle(annot["/Rect"].getArrayAsRectangle());
1151 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 1180 AcroForm& from_afdh,
1170 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 1184 if (old_annots.empty() || !old_annots.isArray()) {
1174 1185 return;
1175 1186 }
... ... @@ -1184,7 +1195,8 @@ AcroForm::fixCopiedAnnotations(
1184 1195 old_fields,
1185 1196 QPDFMatrix(),
1186 1197 &(from_afdh.qpdf),
1187   - &from_afdh);
  1198 + &from_afdh,
  1199 + &to_page);
1188 1200  
1189 1201 to_page.replaceKey("/Annots", QPDFObjectHandle::newArray(new_annots));
1190 1202 addAndRenameFormFields(new_fields);
... ...
libqpdf/qpdf/AcroForm.hh
... ... @@ -166,7 +166,8 @@ namespace qpdf::impl
166 166 std::set<QPDFObjGen>& old_fields,
167 167 QPDFMatrix const& cm,
168 168 QPDF* from_qpdf,
169   - AcroForm* from_afdh);
  169 + AcroForm* from_afdh,
  170 + QPDFObjectHandle* new_page);
170 171  
171 172 // Copy form fields and annotations from one page to another, allowing the from page to be
172 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 324 {
325 325 }
326 326  
  327 + explicit
  328 + operator bool() const
  329 + {
  330 + return obj != nullptr;
  331 + }
  332 +
327 333 // Return the integer value. If the object is not a valid Integer, throw a
328 334 // std::invalid_argument exception. If the object is out of range for the target type,
329 335 // throw a std::overflow_error or std::underflow_error exception.
... ...
manual/release-notes.rst
... ... @@ -43,6 +43,9 @@ more detail.
43 43 - When parsing qpdf JSON input files allow empty name objects. These are
44 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 49 - Library Enhancements
47 50  
48 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 71  
72 72 $td->runtest("check output",
73 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 76 $td->runtest("copy annotations no acroform from foreign file",
78 77 {$td->COMMAND =>
... ... @@ -167,7 +166,7 @@ $td-&gt;runtest(&quot;check output&quot;,
167 166 # field-resource-conflict.pdf was crafted so that an appearance stream
168 167 # had an existing resource that it actually referenced in the
169 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 170 # ever happened, it would be really hard to track down, and it could
172 171 # arise through multiple passes through qpdf with intervening edits.
173 172 $td->runtest("appearance stream resource conflict",
... ...
qpdf/qtest/qpdf/resolved-appearance-conflicts.pdf
... ... @@ -119,7 +119,7 @@ endobj
119 119 /MK <<
120 120 /CA (8)
121 121 >>
122   - /P 17 0 R
  122 + /P 26 0 R
123 123 /Rect [
124 124 174.5
125 125 719.7
... ... @@ -136,7 +136,7 @@ endobj
136 136 6 0 obj
137 137 <<
138 138 /AP <<
139   - /N 26 0 R
  139 + /N 27 0 R
140 140 >>
141 141 /DA (0.29803 0.29803 0.29803 rg /F1 12 Tf)
142 142 /DR <<
... ... @@ -145,7 +145,7 @@ endobj
145 145 /DV <feff>
146 146 /F 4
147 147 /FT /Tx
148   - /P 17 0 R
  148 + /P 26 0 R
149 149 /Rect [
150 150 59.6
151 151 715
... ... @@ -163,8 +163,8 @@ endobj
163 163 <<
164 164 /AP <<
165 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 170 /AS /Off
... ... @@ -176,7 +176,7 @@ endobj
176 176 /MK <<
177 177 /CA (8)
178 178 >>
179   - /P 32 0 R
  179 + /P 33 0 R
180 180 /Rect [
181 181 174.5
182 182 719.7
... ... @@ -193,14 +193,14 @@ endobj
193 193 8 0 obj
194 194 <<
195 195 /AP <<
196   - /N 33 0 R
  196 + /N 34 0 R
197 197 >>
198 198 /DA (0.29803 0.29803 0.29803 rg /F1_1 12 Tf)
199 199 /DR 2 0 R
200 200 /DV <feff>
201 201 /F 4
202 202 /FT /Tx
203   - /P 32 0 R
  203 + /P 33 0 R
204 204 /Rect [
205 205 59.6
206 206 715
... ... @@ -219,8 +219,8 @@ endobj
219 219 /Count 3
220 220 /Kids [
221 221 17 0 R
222   - 35 0 R
223   - 32 0 R
  222 + 26 0 R
  223 + 33 0 R
224 224 ]
225 225 /Type /Pages
226 226 >>
... ... @@ -431,8 +431,41 @@ endobj
431 431 81
432 432 endobj
433 433  
  434 +%% Page 2
434 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 469 /BBox [
437 470 0
438 471 0
... ... @@ -447,7 +480,7 @@ endobj
447 480 >>
448 481 /Subtype /Form
449 482 /Type /XObject
450   - /Length 27 0 R
  483 + /Length 28 0 R
451 484 >>
452 485 stream
453 486 BT /F1_1 12 Tf ET
... ... @@ -456,11 +489,11 @@ EMC
456 489 endstream
457 490 endobj
458 491  
459   -27 0 obj
  492 +28 0 obj
460 493 30
461 494 endobj
462 495  
463   -28 0 obj
  496 +29 0 obj
464 497 <<
465 498 /BBox [
466 499 0
... ... @@ -471,7 +504,7 @@ endobj
471 504 /Resources 39 0 R
472 505 /Subtype /Form
473 506 /Type /XObject
474   - /Length 29 0 R
  507 + /Length 30 0 R
475 508 >>
476 509 stream
477 510 /Tx BMC
... ... @@ -479,11 +512,11 @@ EMC
479 512 endstream
480 513 endobj
481 514  
482   -29 0 obj
  515 +30 0 obj
483 516 12
484 517 endobj
485 518  
486   -30 0 obj
  519 +31 0 obj
487 520 <<
488 521 /BBox [
489 522 0
... ... @@ -494,7 +527,7 @@ endobj
494 527 /Resources 40 0 R
495 528 /Subtype /Form
496 529 /Type /XObject
497   - /Length 31 0 R
  530 + /Length 32 0 R
498 531 >>
499 532 stream
500 533 /Tx BMC
... ... @@ -507,12 +540,12 @@ EMC
507 540 endstream
508 541 endobj
509 542  
510   -31 0 obj
  543 +32 0 obj
511 544 83
512 545 endobj
513 546  
514 547 %% Page 3
515   -32 0 obj
  548 +33 0 obj
516 549 <<
517 550 /Annots [
518 551 7 0 R
... ... @@ -544,7 +577,7 @@ endobj
544 577 >>
545 578 endobj
546 579  
547   -33 0 obj
  580 +34 0 obj
548 581 <<
549 582 /BBox [
550 583 0
... ... @@ -560,7 +593,7 @@ endobj
560 593 >>
561 594 /Subtype /Form
562 595 /Type /XObject
563   - /Length 34 0 R
  596 + /Length 35 0 R
564 597 >>
565 598 stream
566 599 BT /F1_1_1 12 Tf ET
... ... @@ -569,41 +602,8 @@ EMC
569 602 endstream
570 603 endobj
571 604  
572   -34 0 obj
573   -32
574   -endobj
575   -
576   -%% Page 2
577 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 607 endobj
608 608  
609 609 36 0 obj
... ... @@ -742,16 +742,16 @@ xref
742 742 0000004092 00000 n
743 743 0000004112 00000 n
744 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 755 0000006066 00000 n
756 756 0000006194 00000 n
757 757 0000006531 00000 n
... ...