Skip to content

Commit 9109947

Browse files
author
Alexander Pliushchou
committed
Allow PdfStreams as a referenced object for MCR
DEVSIX-8283
1 parent deb13da commit 9109947

29 files changed

+145
-19
lines changed

kernel/src/main/java/com/itextpdf/kernel/exceptions/KernelExceptionMessageConstant.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,8 @@ public final class KernelExceptionMessageConstant {
251251
"Invalid PDF Type 3 Function object, \"Functions\" array should exist and can't be empty.";
252252
public static final String INVALID_RANGE_ARRAY = "Invalid range array.";
253253
public static final String INVALID_OFFSET_FOR_THIS_OBJECT = "Invalid offset for object {0}.";
254+
public static final String INVALID_OBJECT_REFERENCE_TYPE = "Object reference has unsupported type, " +
255+
"supported types are dictionaries and streams";
254256
public static final String INVALID_XREF_STREAM = "Invalid xref stream.";
255257
public static final String INVALID_XREF_TABLE = "Invalid xref table.";
256258
public static final String IO_EXCEPTION = "I/O exception.";

kernel/src/main/java/com/itextpdf/kernel/pdf/tagging/ParentTreeHandler.java

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -197,8 +197,13 @@ private void registerMcr(PdfMcr mcr, boolean registeringOnInit) {
197197
}
198198
pageMcrs.putXObjectMcr(stmIndRef, mcr);
199199
} else if (mcr instanceof PdfObjRef) {
200-
PdfDictionary obj = ((PdfDictionary) mcr.getPdfObject()).getAsDictionary(PdfName.Obj);
201-
if (obj == null || obj.isFlushed()) {
200+
PdfObject mcrObj = ((PdfDictionary) mcr.getPdfObject()).get(PdfName.Obj);
201+
if (!(mcrObj instanceof PdfDictionary)) {
202+
throw new PdfException(KernelExceptionMessageConstant.INVALID_OBJECT_REFERENCE_TYPE);
203+
}
204+
205+
PdfDictionary obj = (PdfDictionary) mcrObj;
206+
if (obj.isFlushed()) {
202207
throw new PdfException(
203208
KernelExceptionMessageConstant.WHEN_ADDING_OBJECT_REFERENCE_TO_THE_TAG_TREE_IT_MUST_BE_CONNECTED_TO_NOT_FLUSHED_OBJECT);
204209
}
@@ -247,15 +252,6 @@ public void unregisterMcr(PdfMcr mcrToUnregister) {
247252
}
248253
structTreeRoot.setModified();
249254
} else if (mcrToUnregister instanceof PdfObjRef) {
250-
PdfDictionary obj = ((PdfDictionary) mcrToUnregister.getPdfObject()).getAsDictionary(PdfName.Obj);
251-
if (obj != null && !obj.isFlushed()) {
252-
PdfNumber n = obj.getAsNumber(PdfName.StructParent);
253-
if (n != null) {
254-
pageMcrs.getObjRefs().remove(n.intValue());
255-
structTreeRoot.setModified();
256-
return;
257-
}
258-
}
259255
for (Map.Entry<Integer, PdfMcr> entry : pageMcrs.getObjRefs().entrySet()) {
260256
if (entry.getValue().getPdfObject() == mcrToUnregister.getPdfObject()) {
261257
pageMcrs.getObjRefs().remove(entry.getKey());

kernel/src/main/java/com/itextpdf/kernel/pdf/tagging/PdfObjRef.java

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ This file is part of the iText (R) project.
2525
import com.itextpdf.kernel.pdf.PdfDictionary;
2626
import com.itextpdf.kernel.pdf.PdfName;
2727
import com.itextpdf.kernel.pdf.PdfNumber;
28+
import com.itextpdf.kernel.pdf.PdfObject;
2829
import com.itextpdf.kernel.pdf.annot.PdfAnnotation;
2930

3031
public class PdfObjRef extends PdfMcr {
@@ -55,6 +56,11 @@ public PdfDictionary getPageObject() {
5556
}
5657

5758
public PdfDictionary getReferencedObject() {
58-
return ((PdfDictionary) getPdfObject()).getAsDictionary(PdfName.Obj);
59+
PdfObject obj = ((PdfDictionary) getPdfObject()).get(PdfName.Obj);
60+
if(obj instanceof PdfDictionary){
61+
return (PdfDictionary) obj;
62+
} else {
63+
return null;
64+
}
5965
}
6066
}

kernel/src/main/java/com/itextpdf/kernel/pdf/tagging/StructureTreeCopier.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -354,13 +354,14 @@ private static PdfDictionary copyObject(PdfDictionary source, PdfDictionary dest
354354
} else {
355355
copied = source.copyTo(copyingParams.getToDocument(), ignoreKeysForCopy, true);
356356

357-
PdfDictionary obj = source.getAsDictionary(PdfName.Obj);
358-
if (obj != null) {
357+
PdfObject obj = source.get(PdfName.Obj);
358+
if (obj instanceof PdfDictionary) {
359+
PdfDictionary objDic = (PdfDictionary) obj;
359360
// Link annotations could be not added to the toDocument, so we need to identify this case.
360361
// When obj.copyTo is called, and annotation was already copied, we would get this already created copy.
361362
// If it was already copied and added, /P key would be set. Otherwise /P won't be set.
362-
obj = obj.copyTo(copyingParams.getToDocument(), Arrays.asList(PdfName.P), false);
363-
copied.put(PdfName.Obj, obj);
363+
objDic = objDic.copyTo(copyingParams.getToDocument(), Arrays.asList(PdfName.P), false);
364+
copied.put(PdfName.Obj, objDic);
364365
}
365366

366367
PdfDictionary nsDict = source.getAsDictionary(PdfName.NS);
@@ -456,7 +457,7 @@ private static PdfObject copyObjectKid(PdfObject kid, PdfDictionary copiedParent
456457
PdfMcr mcr;
457458
if (copiedKid.containsKey(PdfName.Obj)) {
458459
mcr = new PdfObjRef(copiedKid, new PdfStructElem(copiedParent));
459-
PdfDictionary contentItemObject = copiedKid.getAsDictionary(PdfName.Obj);
460+
PdfDictionary contentItemObject = (PdfDictionary) copiedKid.get(PdfName.Obj);
460461
if (PdfName.Link.equals(contentItemObject.getAsName(PdfName.Subtype))
461462
&& !contentItemObject.containsKey(PdfName.P)) {
462463
// Some link annotations may be not copied, because their destination page is not copied.

kernel/src/test/java/com/itextpdf/kernel/pdf/ParentTreeTest.java

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,44 @@ public void test06() throws IOException {
358358
assertTrue(checkParentTree(outFile, cmpFile));
359359
}
360360

361+
@Test
362+
public void objRefAsStreamTest() throws IOException, InterruptedException {
363+
String pdf = sourceFolder + "objRefAsStream.pdf";
364+
String outPdf = destinationFolder + "objRefAsStream.pdf";
365+
String cmpPdf = sourceFolder + "cmp_objRefAsStream.pdf";
366+
367+
PdfDocument taggedPdf = new PdfDocument(new PdfReader(pdf), CompareTool.createTestPdfWriter(outPdf));
368+
taggedPdf.close();
369+
370+
Assert.assertNull(new CompareTool().compareByContent(outPdf, cmpPdf, destinationFolder, "diff"));
371+
}
372+
373+
@Test
374+
@LogMessages(messages = {
375+
@LogMessage(messageTemplate = IoLogMessageConstant.TAG_STRUCTURE_INIT_FAILED)
376+
})
377+
public void objRefAsInvalidType() throws IOException {
378+
String pdf = sourceFolder + "objRefAsInvalidType.pdf";
379+
PdfDocument doc = new PdfDocument(new PdfReader(pdf));
380+
Assert.assertNull(doc.getStructTreeRoot());
381+
}
382+
383+
@Test
384+
public void unregisterObjRefAsStreamTest() throws IOException, InterruptedException {
385+
String pdf = sourceFolder + "objRefAsStream.pdf";
386+
String outPdf = destinationFolder + "objRefAsStreamUnregisterMcr.pdf";
387+
String cmpPdf = sourceFolder + "cmp_objRefAsStreamUnregisterMcr.pdf";
388+
389+
PdfDocument taggedPdf = new PdfDocument(new PdfReader(pdf), CompareTool.createTestPdfWriter(outPdf));
390+
391+
PdfStructElem elem = (PdfStructElem) taggedPdf.getStructTreeRoot().getKids().get(0).getKids().get(0);
392+
elem.removeKid(0);
393+
taggedPdf.close();
394+
395+
Assert.assertNull(new CompareTool().compareByContent(outPdf, cmpPdf, destinationFolder, "diff"));
396+
}
397+
398+
361399
@Test
362400
@LogMessages(messages = {
363401
@LogMessage(messageTemplate = KernelLogMessageConstant.STRUCT_PARENT_INDEX_MISSED_AND_RECREATED, count = 4)

kernel/src/test/java/com/itextpdf/kernel/pdf/PdfCopyTest.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,23 @@ public void copyPagesLinkAnnotationTest() throws IOException, InterruptedExcepti
383383
Assert.assertNull(new CompareTool().compareByContent(outFileName, cmpFileName, destinationFolder));
384384
}
385385

386+
@Test
387+
public void objRefAsStreamCopyTest() throws IOException, InterruptedException {
388+
String pdf = sourceFolder + "objRefAsStream.pdf";
389+
String outPdf = destinationFolder + "objRefAsStreamCopy.pdf";
390+
String cmpPdf = sourceFolder + "cmp_objRefAsStreamCopy.pdf";
391+
392+
PdfDocument pdfFile = new PdfDocument(new PdfReader(pdf));
393+
PdfDocument copiedFile = new PdfDocument(CompareTool.createTestPdfWriter(outPdf));
394+
copiedFile.setTagged();
395+
pdfFile.copyPagesTo(1, 1, copiedFile);
396+
397+
pdfFile.close();
398+
copiedFile.close();
399+
400+
Assert.assertNull(new CompareTool().compareByContent(outPdf, cmpPdf, destinationFolder, "diff"));
401+
}
402+
386403
@Test
387404
public void copyDocWithFullDDictionary() throws IOException, InterruptedException {
388405
String outFileName = destinationFolder + "copyDocWithDDictionary.pdf";
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package com.itextpdf.kernel.pdf.tagging;
2+
3+
import com.itextpdf.kernel.pdf.*;
4+
import com.itextpdf.test.ExtendedITextTest;
5+
import com.itextpdf.test.annotations.type.UnitTest;
6+
import org.junit.Assert;
7+
import org.junit.Test;
8+
import org.junit.experimental.categories.Category;
9+
10+
@Category(UnitTest.class)
11+
public class PdfObjRefUnitTest extends ExtendedITextTest {
12+
13+
@Test
14+
public void refObjAsStreamTest() {
15+
PdfDictionary ref = new PdfStream();
16+
ref.put(PdfName.Name, new PdfString("reference"));
17+
18+
PdfDictionary obj = new PdfDictionary();
19+
obj.put(PdfName.Obj, ref);
20+
21+
PdfObjRef objRef = new PdfObjRef(obj, new PdfStructElem(new PdfDictionary()));
22+
23+
Assert.assertTrue(objRef.getReferencedObject() instanceof PdfStream);
24+
Assert.assertTrue(objRef.getReferencedObject().containsKey(PdfName.Name));
25+
}
26+
27+
@Test
28+
public void refObjAsInvalidTypeTest() {
29+
PdfDictionary obj = new PdfDictionary();
30+
obj.put(PdfName.Obj, new PdfString("incorrect type"));
31+
32+
PdfObjRef objRef = new PdfObjRef(obj, new PdfStructElem(new PdfDictionary()));
33+
34+
Assert.assertNull(objRef.getReferencedObject());
35+
}
36+
}

0 commit comments

Comments
 (0)