Skip to content

Commit dd3251a

Browse files
SnipxiText-CI
authored andcommitted
Add tests demonstrating problems with annotation relationship incorrectly transferred during copying
If annotations refer to other annotations with Popup or IRT keys, this relationship is not correctly transferred at the moment and the result is annotation on one page referring to an annotation on another page, which for IRT key for example is forbidden by the specification DEVSIX-3585 Autoported commit. Original commit hash: [c3e97d52a]
1 parent 6a96743 commit dd3251a

File tree

5 files changed

+132
-2
lines changed

5 files changed

+132
-2
lines changed
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
/*
2+
This file is part of the iText (R) project.
3+
Copyright (c) 1998-2019 iText Group NV
4+
Authors: iText Software.
5+
6+
This program is offered under a commercial and under the AGPL license.
7+
For commercial licensing, contact us at https://itextpdf.com/sales. For AGPL licensing, see below.
8+
9+
AGPL licensing:
10+
This program is free software: you can redistribute it and/or modify
11+
it under the terms of the GNU Affero General Public License as published by
12+
the Free Software Foundation, either version 3 of the License, or
13+
(at your option) any later version.
14+
15+
This program is distributed in the hope that it will be useful,
16+
but WITHOUT ANY WARRANTY; without even the implied warranty of
17+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18+
GNU Affero General Public License for more details.
19+
20+
You should have received a copy of the GNU Affero General Public License
21+
along with this program. If not, see <https://www.gnu.org/licenses/>.
22+
*/
23+
using System;
24+
using NUnit.Framework;
25+
using iText.IO.Util;
26+
using iText.Kernel.Pdf;
27+
using iText.Kernel.Pdf.Annot;
28+
using iText.Test;
29+
30+
namespace iText.Kernel.Pdf.Copy {
31+
public class PdfAnnotationCopyingTest : ExtendedITextTest {
32+
public static readonly String destinationFolder = NUnit.Framework.TestContext.CurrentContext.TestDirectory
33+
+ "/test/itext/kernel/pdf/PdfAnnotationCopyingTest/";
34+
35+
public static readonly String sourceFolder = iText.Test.TestUtil.GetParentProjectDirectory(NUnit.Framework.TestContext
36+
.CurrentContext.TestDirectory) + "/resources/itext/kernel/pdf/PdfAnnotationCopyingTest/";
37+
38+
[NUnit.Framework.OneTimeSetUp]
39+
public static void BeforeClass() {
40+
CreateOrClearDestinationFolder(destinationFolder);
41+
}
42+
43+
[NUnit.Framework.Test]
44+
public virtual void TestCopyingPageWithAnnotationContainingPopupKey() {
45+
NUnit.Framework.Assert.That(() => {
46+
// TODO remove expected exception and thus enable assertions when DEVSIX-3585 is implemented
47+
String inFilePath = sourceFolder + "annotation-with-popup.pdf";
48+
String outFilePath = destinationFolder + "copy-annotation-with-popup.pdf";
49+
PdfDocument originalDocument = new PdfDocument(new PdfReader(inFilePath));
50+
PdfDocument outDocument = new PdfDocument(new PdfWriter(outFilePath));
51+
originalDocument.CopyPagesTo(1, 1, outDocument);
52+
// During the second copy call we have to rebuild/preserve all the annotation relationship (Popup in this case),
53+
// so that we don't end up with annotation on one page referring to an annotation on another page as its popup
54+
// or as its parent
55+
originalDocument.CopyPagesTo(1, 1, outDocument);
56+
originalDocument.Close();
57+
outDocument.Close();
58+
outDocument = new PdfDocument(new PdfReader(outFilePath));
59+
for (int pageNum = 1; pageNum <= outDocument.GetNumberOfPages(); pageNum++) {
60+
PdfPage page = outDocument.GetPage(pageNum);
61+
NUnit.Framework.Assert.AreEqual(2, page.GetAnnotsSize());
62+
NUnit.Framework.Assert.AreEqual(2, page.GetAnnotations().Count);
63+
bool foundMarkupAnnotation = false;
64+
foreach (PdfAnnotation annotation in page.GetAnnotations()) {
65+
PdfDictionary annotationPageDict = annotation.GetPageObject();
66+
if (annotationPageDict != null) {
67+
NUnit.Framework.Assert.AreSame(page.GetPdfObject(), annotationPageDict);
68+
}
69+
if (annotation is PdfMarkupAnnotation) {
70+
foundMarkupAnnotation = true;
71+
PdfPopupAnnotation popup = ((PdfMarkupAnnotation)annotation).GetPopup();
72+
NUnit.Framework.Assert.IsTrue(page.ContainsAnnotation(popup), MessageFormatUtil.Format("Popup reference must point to annotation present on the same page (# {0})"
73+
, pageNum));
74+
PdfDictionary parentAnnotation = popup.GetParentObject();
75+
NUnit.Framework.Assert.AreSame(annotation.GetPdfObject(), parentAnnotation, "Popup annotation parent must point to the annotation that specified it as Popup"
76+
);
77+
}
78+
}
79+
NUnit.Framework.Assert.IsTrue(foundMarkupAnnotation, "Markup annotation expected to be present but not found"
80+
);
81+
}
82+
outDocument.Close();
83+
}
84+
, NUnit.Framework.Throws.InstanceOf<AssertionException>())
85+
;
86+
}
87+
88+
[NUnit.Framework.Test]
89+
public virtual void TestCopyingPageWithAnnotationContainingIrtKey() {
90+
NUnit.Framework.Assert.That(() => {
91+
// TODO remove expected exception and thus enable assertions when DEVSIX-3585 is implemented
92+
String inFilePath = sourceFolder + "annotation-with-irt.pdf";
93+
String outFilePath = destinationFolder + "copy-annotation-with-irt.pdf";
94+
PdfDocument originalDocument = new PdfDocument(new PdfReader(inFilePath));
95+
PdfDocument outDocument = new PdfDocument(new PdfWriter(outFilePath));
96+
originalDocument.CopyPagesTo(1, 1, outDocument);
97+
// During the second copy call we have to rebuild/preserve all the annotation relationship (IRT in this case),
98+
// so that we don't end up with annotation on one page referring to an annotation on another page as its IRT
99+
// or as its parent
100+
originalDocument.CopyPagesTo(1, 1, outDocument);
101+
originalDocument.Close();
102+
outDocument.Close();
103+
outDocument = new PdfDocument(new PdfReader(outFilePath));
104+
for (int pageNum = 1; pageNum <= outDocument.GetNumberOfPages(); pageNum++) {
105+
PdfPage page = outDocument.GetPage(pageNum);
106+
NUnit.Framework.Assert.AreEqual(4, page.GetAnnotsSize());
107+
NUnit.Framework.Assert.AreEqual(4, page.GetAnnotations().Count);
108+
bool foundMarkupAnnotation = false;
109+
foreach (PdfAnnotation annotation in page.GetAnnotations()) {
110+
PdfDictionary annotationPageDict = annotation.GetPageObject();
111+
if (annotationPageDict != null) {
112+
NUnit.Framework.Assert.AreSame(page.GetPdfObject(), annotationPageDict);
113+
}
114+
if (annotation is PdfMarkupAnnotation) {
115+
foundMarkupAnnotation = true;
116+
PdfDictionary inReplyTo = ((PdfMarkupAnnotation)annotation).GetInReplyToObject();
117+
NUnit.Framework.Assert.IsTrue(page.ContainsAnnotation(PdfAnnotation.MakeAnnotation(inReplyTo)), "IRT reference must point to annotation present on the same page"
118+
);
119+
}
120+
}
121+
NUnit.Framework.Assert.IsTrue(foundMarkupAnnotation, "Markup annotation expected to be present but not found"
122+
);
123+
}
124+
outDocument.Close();
125+
}
126+
, NUnit.Framework.Throws.InstanceOf<AssertionException>())
127+
;
128+
}
129+
}
130+
}

itext/itext.kernel/itext/kernel/pdf/annot/PdfAnnotation.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1363,7 +1363,7 @@ public virtual iText.Kernel.Pdf.Annot.PdfAnnotation SetTitle(PdfString title) {
13631363
/// <returns>
13641364
///
13651365
/// <see cref="iText.Kernel.Pdf.PdfString"/>
1366-
/// which value is an annotation title or null if it isn't specifed.
1366+
/// which value is an annotation title or null if it isn't specified.
13671367
/// </returns>
13681368
public virtual PdfString GetTitle() {
13691369
return GetPdfObject().GetAsString(PdfName.T);

port-hash

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
eb43d782a1bda5142eee6cc0ab1c5237b864d98d
1+
c3e97d52af4a38b3c447deb4aced473eea0fb56a

0 commit comments

Comments
 (0)