ParentTreeTest.java
/*
This file is part of the iText (R) project.
Copyright (c) 1998-2025 Apryse Group NV
Authors: Apryse Software.
This program is offered under a commercial and under the AGPL license.
For commercial licensing, contact us at https://itextpdf.com/sales. For AGPL licensing, see below.
AGPL licensing:
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.itextpdf.kernel.pdf;
import com.itextpdf.commons.utils.MessageFormatUtil;
import com.itextpdf.io.font.constants.StandardFonts;
import com.itextpdf.io.logs.IoLogMessageConstant;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.kernel.geom.Rectangle;
import com.itextpdf.kernel.logs.KernelLogMessageConstant;
import com.itextpdf.kernel.pdf.action.PdfAction;
import com.itextpdf.kernel.pdf.annot.PdfFileAttachmentAnnotation;
import com.itextpdf.kernel.pdf.annot.PdfLinkAnnotation;
import com.itextpdf.kernel.pdf.annot.PdfScreenAnnotation;
import com.itextpdf.kernel.pdf.canvas.CanvasTag;
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
import com.itextpdf.kernel.pdf.filespec.PdfFileSpec;
import com.itextpdf.kernel.pdf.tagging.PdfMcr;
import com.itextpdf.kernel.pdf.tagging.PdfMcrDictionary;
import com.itextpdf.kernel.pdf.tagging.PdfMcrNumber;
import com.itextpdf.kernel.pdf.tagging.PdfStructElem;
import com.itextpdf.kernel.pdf.tagging.PdfObjRef;
import com.itextpdf.kernel.utils.CompareTool;
import com.itextpdf.kernel.utils.CompareTool.CompareResult;
import com.itextpdf.test.AssertUtil;
import com.itextpdf.test.ExtendedITextTest;
import com.itextpdf.test.TestUtil;
import com.itextpdf.test.annotations.LogMessage;
import com.itextpdf.test.annotations.LogMessages;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.Tag;
import static org.junit.jupiter.api.Assertions.*;
@Tag("IntegrationTest")
public class ParentTreeTest extends ExtendedITextTest {
public static final String sourceFolder = "./src/test/resources/com/itextpdf/kernel/pdf/ParentTreeTest/";
public static final String destinationFolder = TestUtil.getOutputPath() + "/kernel/pdf/ParentTreeTest/";
@BeforeAll
public static void beforeClass() {
createDestinationFolder(destinationFolder);
}
@AfterAll
public static void afterClass() {
CompareTool.cleanup(destinationFolder);
}
@Test
public void test01() throws IOException {
String outFile = destinationFolder + "parentTreeTest01.pdf";
String cmpFile = sourceFolder + "cmp_parentTreeTest01.pdf";
PdfDocument document = new PdfDocument(CompareTool.createTestPdfWriter(outFile));
document.setTagged();
PdfStructElem doc = document.getStructTreeRoot().addKid(new PdfStructElem(document, PdfName.Document));
PdfPage firstPage = document.addNewPage();
PdfCanvas canvas = new PdfCanvas(firstPage);
canvas.beginText();
canvas.setFontAndSize(PdfFontFactory.createFont(StandardFonts.COURIER), 24);
canvas.setTextMatrix(1, 0, 0, 1, 32, 512);
PdfStructElem paragraph = doc.addKid(new PdfStructElem(document, PdfName.P));
PdfStructElem span1 = paragraph.addKid(new PdfStructElem(document, PdfName.Span, firstPage));
canvas.openTag(new CanvasTag(span1.addKid(new PdfMcrNumber(firstPage, span1))));
canvas.showText("Hello ");
canvas.closeTag();
canvas.openTag(new CanvasTag(span1.addKid(new PdfMcrDictionary(firstPage, span1))));
canvas.showText("World");
canvas.closeTag();
canvas.endText();
canvas.release();
PdfPage secondPage = document.addNewPage();
document.close();
assertTrue(checkParentTree(outFile, cmpFile));
}
@Test
public void stampingFormXObjectInnerContentTaggedTest() throws IOException, InterruptedException {
String pdf = sourceFolder + "alreadyTaggedFormXObjectInnerContent.pdf";
String outPdf = destinationFolder + "stampingFormXObjectInnerContentTaggedTest.pdf";
String cmpPdf = sourceFolder + "cmp_stampingFormXObjectInnerContentTaggedTest.pdf";
PdfDocument taggedPdf = new PdfDocument(new PdfReader(pdf), CompareTool.createTestPdfWriter(outPdf));
taggedPdf.setTagged();
taggedPdf.close();
Assertions.assertNull(new CompareTool().compareByContent(outPdf, cmpPdf, destinationFolder, "diff"));
}
@Test
public void severalXObjectsOnOnePageTest() throws IOException, InterruptedException {
String pdf = sourceFolder + "severalXObjectsOnOnePageTest.pdf";
String outPdf = destinationFolder + "severalXObjectsOnOnePageTest.pdf";
String cmpPdf = sourceFolder + "cmp_severalXObjectsOnOnePageTest.pdf";
PdfDocument taggedPdf = new PdfDocument(new PdfReader(pdf), CompareTool.createTestPdfWriter(outPdf));
taggedPdf.setTagged();
taggedPdf.close();
Assertions.assertNull(new CompareTool().compareByContent(outPdf, cmpPdf, destinationFolder, "diff"));
}
@Test
public void earlyFlushXObjectTaggedTest() throws IOException, InterruptedException {
String pdf = sourceFolder + "earlyFlushXObjectTaggedTest.pdf";
String outPdf = destinationFolder + "earlyFlushXObjectTaggedTest.pdf";
String cmpPdf = sourceFolder + "cmp_earlyFlushXObjectTaggedTest.pdf";
PdfDocument taggedPdf = new PdfDocument(new PdfReader(pdf), CompareTool.createTestPdfWriter(outPdf));
PdfDictionary resource = taggedPdf.getFirstPage().getResources().getResource(PdfName.XObject);
resource.get(new PdfName("Fm1")).flush();
taggedPdf.close();
Assertions.assertNull(new CompareTool().compareByContent(outPdf, cmpPdf, destinationFolder, "diff"));
}
@Test
public void identicalMcidIdInOneStreamTest() throws IOException, InterruptedException {
String pdf = sourceFolder + "identicalMcidIdInOneStreamTest.pdf";
String outPdf = destinationFolder + "identicalMcidIdInOneStreamTest.pdf";
String cmpPdf = sourceFolder + "cmp_identicalMcidIdInOneStreamTest.pdf";
PdfDocument taggedPdf = new PdfDocument(new PdfReader(pdf), CompareTool.createTestPdfWriter(outPdf));
taggedPdf.setTagged();
taggedPdf.close();
Assertions.assertNull(new CompareTool().compareByContent(outPdf, cmpPdf, destinationFolder, "diff"));
}
@Test
public void copyPageWithFormXObjectTaggedTest() throws IOException, InterruptedException {
String cmpPdf = sourceFolder + "cmp_copyPageWithFormXobjectTaggedTest.pdf";
String outDoc = destinationFolder + "copyPageWithFormXobjectTaggedTest.pdf";
PdfDocument srcPdf = new PdfDocument(new PdfReader(sourceFolder + "copyFromFile.pdf"));
PdfDocument outPdf = new PdfDocument(new PdfReader(sourceFolder + "copyToFile.pdf"), CompareTool.createTestPdfWriter(outDoc));
outPdf.setTagged();
srcPdf.copyPagesTo(1, 1, outPdf);
srcPdf.close();
outPdf.close();
Assertions.assertNull(new CompareTool().compareByContent(outDoc, cmpPdf, destinationFolder));
}
@Test
public void removePageWithFormXObjectTaggedTest() throws IOException, InterruptedException {
String cmpPdf = sourceFolder + "cmp_removePageWithFormXobjectTaggedTest.pdf";
String outDoc = destinationFolder + "removePageWithFormXobjectTaggedTest.pdf";
PdfDocument outPdf = new PdfDocument(new PdfReader(sourceFolder + "forRemovePage.pdf"), CompareTool.createTestPdfWriter(outDoc));
outPdf.setTagged();
outPdf.removePage(1);
outPdf.close();
Assertions.assertNull(new CompareTool().compareByContent(outDoc, cmpPdf, destinationFolder));
}
@Test
public void test02() throws IOException {
String outFile = destinationFolder + "parentTreeTest02.pdf";
String cmpFile = sourceFolder + "cmp_parentTreeTest02.pdf";
PdfDocument document = new PdfDocument(CompareTool.createTestPdfWriter(outFile));
document.setTagged();
PdfStructElem doc = document.getStructTreeRoot().addKid(new PdfStructElem(document, PdfName.Document));
PdfPage firstPage = document.addNewPage();
PdfPage secondPage = document.addNewPage();
PdfCanvas canvas = new PdfCanvas(secondPage);
canvas.beginText();
canvas.setFontAndSize(PdfFontFactory.createFont(StandardFonts.COURIER), 24);
canvas.setTextMatrix(1, 0, 0, 1, 32, 512);
PdfStructElem paragraph = doc.addKid(new PdfStructElem(document, PdfName.P));
PdfStructElem span1 = paragraph.addKid(new PdfStructElem(document, PdfName.Span, secondPage));
canvas.openTag(new CanvasTag(span1.addKid(new PdfMcrNumber(secondPage, span1))));
canvas.showText("Hello ");
canvas.closeTag();
canvas.openTag(new CanvasTag(span1.addKid(new PdfMcrDictionary(secondPage, span1))));
canvas.showText("World");
canvas.closeTag();
canvas.endText();
canvas.release();
document.close();
assertTrue(checkParentTree(outFile, cmpFile));
}
@Test
public void test03() throws IOException {
String outFile = destinationFolder + "parentTreeTest03.pdf";
String cmpFile = sourceFolder + "cmp_parentTreeTest03.pdf";
PdfDocument document = new PdfDocument(CompareTool.createTestPdfWriter(outFile));
document.setTagged();
PdfStructElem doc = document.getStructTreeRoot().addKid(new PdfStructElem(document, PdfName.Document));
PdfPage firstPage = document.addNewPage();
for (int i = 0; i < 51; i++) {
PdfPage anotherPage = document.addNewPage();
PdfCanvas canvas = new PdfCanvas(anotherPage);
canvas.beginText();
canvas.setFontAndSize(PdfFontFactory.createFont(StandardFonts.COURIER), 24);
canvas.setTextMatrix(1, 0, 0, 1, 32, 512);
PdfStructElem paragraph = doc.addKid(new PdfStructElem(document, PdfName.P));
PdfStructElem span1 = paragraph.addKid(new PdfStructElem(document, PdfName.Span, anotherPage));
canvas.openTag(new CanvasTag(span1.addKid(new PdfMcrNumber(anotherPage, span1))));
canvas.showText("Hello ");
canvas.closeTag();
canvas.openTag(new CanvasTag(span1.addKid(new PdfMcrDictionary(anotherPage, span1))));
canvas.showText("World");
canvas.closeTag();
canvas.endText();
canvas.release();
}
document.close();
assertTrue(checkParentTree(outFile, cmpFile));
}
@Test
public void test04() throws IOException {
String outFile = destinationFolder + "parentTreeTest04.pdf";
String cmpFile = sourceFolder + "cmp_parentTreeTest04.pdf";
PdfDocument document = new PdfDocument(CompareTool.createTestPdfWriter(outFile));
document.setTagged();
PdfStructElem doc = document.getStructTreeRoot().addKid(new PdfStructElem(document, PdfName.Document));
for (int i = 0; i < 51; i++) {
PdfPage anotherPage = document.addNewPage();
PdfCanvas canvas = new PdfCanvas(anotherPage);
canvas.beginText();
canvas.setFontAndSize(PdfFontFactory.createFont(StandardFonts.COURIER), 24);
canvas.setTextMatrix(1, 0, 0, 1, 32, 512);
PdfStructElem paragraph = doc.addKid(new PdfStructElem(document, PdfName.P));
PdfStructElem span1 = paragraph.addKid(new PdfStructElem(document, PdfName.Span, anotherPage));
canvas.openTag(new CanvasTag(span1.addKid(new PdfMcrNumber(anotherPage, span1))));
canvas.showText("Hello ");
canvas.closeTag();
canvas.openTag(new CanvasTag(span1.addKid(new PdfMcrDictionary(anotherPage, span1))));
canvas.showText("World");
canvas.closeTag();
canvas.endText();
canvas.release();
}
document.close();
assertTrue(checkParentTree(outFile, cmpFile));
}
@Test
public void test05() throws IOException {
String outFile = destinationFolder + "parentTreeTest05.pdf";
String cmpFile = sourceFolder + "cmp_parentTreeTest05.pdf";
PdfDocument document = new PdfDocument(CompareTool.createTestPdfWriter(outFile));
document.setTagged();
PdfStructElem doc = document.getStructTreeRoot().addKid(new PdfStructElem(document, PdfName.Document));
PdfPage page1 = document.addNewPage();
PdfCanvas canvas = new PdfCanvas(page1);
canvas.beginText();
canvas.setFontAndSize(PdfFontFactory.createFont(StandardFonts.COURIER), 24);
canvas.setTextMatrix(1, 0, 0, 1, 32, 512);
PdfStructElem paragraph = doc.addKid(new PdfStructElem(document, PdfName.P));
PdfStructElem span1 = paragraph.addKid(new PdfStructElem(document, PdfName.Span, page1));
canvas.openTag(new CanvasTag(span1.addKid(new PdfMcrNumber(page1, span1))));
canvas.showText("Hello ");
canvas.closeTag();
canvas.openTag(new CanvasTag(span1.addKid(new PdfMcrDictionary(page1, span1))));
canvas.showText("World");
canvas.closeTag();
canvas.endText();
canvas.release();
PdfPage page2 = document.addNewPage();
canvas = new PdfCanvas(page2);
canvas.beginText();
canvas.setFontAndSize(PdfFontFactory.createFont(StandardFonts.HELVETICA), 24);
canvas.setTextMatrix(1, 0, 0, 1, 32, 512);
paragraph = doc.addKid(new PdfStructElem(document, PdfName.P));
span1 = paragraph.addKid(new PdfStructElem(document, PdfName.Span, page2));
canvas.openTag(new CanvasTag(span1.addKid(new PdfMcrNumber(page2, span1))));
canvas.showText("Hello ");
canvas.closeTag();
PdfStructElem span2 = paragraph.addKid(new PdfStructElem(document, PdfName.Span, page2));
canvas.openTag(new CanvasTag(span2.addKid(new PdfMcrNumber(page2, span2))));
canvas.showText("World");
canvas.closeTag();
canvas.endText();
canvas.release();
document.close();
assertTrue(checkParentTree(outFile, cmpFile));
}
@Test
public void test06() throws IOException {
String outFile = destinationFolder + "parentTreeTest06.pdf";
String cmpFile = sourceFolder + "cmp_parentTreeTest06.pdf";
PdfDocument document = new PdfDocument(CompareTool.createTestPdfWriter(outFile));
document.setTagged();
PdfStructElem doc = document.getStructTreeRoot().addKid(new PdfStructElem(document, PdfName.Document));
PdfPage firstPage = document.addNewPage();
PdfCanvas canvas = new PdfCanvas(firstPage);
canvas.beginText();
canvas.setFontAndSize(PdfFontFactory.createFont(StandardFonts.COURIER), 24);
canvas.setTextMatrix(1, 0, 0, 1, 32, 512);
PdfStructElem paragraph = doc.addKid(new PdfStructElem(document, PdfName.P));
PdfStructElem span1 = paragraph.addKid(new PdfStructElem(document, PdfName.Span, firstPage));
canvas.openTag(new CanvasTag(span1.addKid(new PdfMcrNumber(firstPage, span1))));
canvas.showText("Hello ");
canvas.closeTag();
canvas.openTag(new CanvasTag(span1.addKid(new PdfMcrDictionary(firstPage, span1))));
canvas.showText("World");
canvas.closeTag();
canvas.endText();
canvas.release();
PdfPage secondPage = document.addNewPage();
PdfLinkAnnotation linkExplicitDest = new PdfLinkAnnotation(new Rectangle(35, 785, 160, 15));
secondPage.addAnnotation(linkExplicitDest);
document.close();
assertTrue(checkParentTree(outFile, cmpFile));
}
@Test
public void objRefAsStreamTest() throws IOException, InterruptedException {
String pdf = sourceFolder + "objRefAsStream.pdf";
String outPdf = destinationFolder + "objRefAsStream.pdf";
String cmpPdf = sourceFolder + "cmp_objRefAsStream.pdf";
PdfDocument taggedPdf = new PdfDocument(new PdfReader(pdf), CompareTool.createTestPdfWriter(outPdf));
taggedPdf.close();
Assertions.assertNull(new CompareTool().compareByContent(outPdf, cmpPdf, destinationFolder, "diff"));
}
@Test
@LogMessages(messages = {
@LogMessage(messageTemplate = IoLogMessageConstant.TAG_STRUCTURE_INIT_FAILED)
})
public void objRefAsInvalidType() throws IOException {
String pdf = sourceFolder + "objRefAsInvalidType.pdf";
PdfDocument doc = new PdfDocument(new PdfReader(pdf));
Assertions.assertNull(doc.getStructTreeRoot());
}
@Test
public void unregisterObjRefAsStreamTest() throws IOException, InterruptedException {
String pdf = sourceFolder + "objRefAsStream.pdf";
String outPdf = destinationFolder + "objRefAsStreamUnregisterMcr.pdf";
String cmpPdf = sourceFolder + "cmp_objRefAsStreamUnregisterMcr.pdf";
PdfDocument taggedPdf = new PdfDocument(new PdfReader(pdf), CompareTool.createTestPdfWriter(outPdf));
PdfStructElem elem = (PdfStructElem) taggedPdf.getStructTreeRoot().getKids().get(0).getKids().get(0);
elem.removeKid(0);
taggedPdf.close();
Assertions.assertNull(new CompareTool().compareByContent(outPdf, cmpPdf, destinationFolder, "diff"));
}
@Test
@LogMessages(messages = {
@LogMessage(messageTemplate = KernelLogMessageConstant.STRUCT_PARENT_INDEX_MISSED_AND_RECREATED, count = 4)
})
public void allObjRefDontHaveStructParentTest() throws IOException, InterruptedException {
String pdf = sourceFolder + "allObjRefDontHaveStructParent.pdf";
String outPdf = destinationFolder + "allObjRefDontHaveStructParent.pdf";
String cmpPdf = sourceFolder + "cmp_allObjRefDontHaveStructParent.pdf";
PdfDocument taggedPdf = new PdfDocument(new PdfReader(pdf), new PdfWriter(outPdf));
taggedPdf.close();
Assertions.assertNull(new CompareTool().compareByContent(outPdf, cmpPdf, destinationFolder, "diff"));
}
@Test
@LogMessages(messages = {
@LogMessage(messageTemplate = KernelLogMessageConstant.XOBJECT_STRUCT_PARENT_INDEX_MISSED_AND_RECREATED)
})
public void xObjDoesntHaveStructParentTest() throws IOException, InterruptedException {
String pdf = sourceFolder + "xObjDoesntHaveStructParentTest.pdf";
String outPdf = destinationFolder + "xObjDoesntHaveStructParentTest.pdf";
String cmpPdf = sourceFolder + "cmp_xObjDoesntHaveStructParentTest.pdf";
PdfDocument taggedPdf = new PdfDocument(new PdfReader(pdf), new PdfWriter(outPdf));
taggedPdf.close();
Assertions.assertNull(new CompareTool().compareByContent(outPdf, cmpPdf, destinationFolder, "diff"));
}
@Test
@LogMessages(messages = {
@LogMessage(messageTemplate = IoLogMessageConstant.TAG_STRUCTURE_INIT_FAILED)
})
public void objRefNoStructParentNoModificationTest() throws IOException {
String pdf = sourceFolder + "objRefNoStructParent.pdf";
String outPdf = destinationFolder + "objRefNoStructParentNoModification.pdf";
PdfReader reader = new PdfReader(pdf).setStrictnessLevel(PdfReader.StrictnessLevel.CONSERVATIVE);
PdfDocument doc = new PdfDocument(reader, CompareTool.createTestPdfWriter(outPdf));
PdfArray nums = doc.getCatalog().getPdfObject().getAsDictionary(PdfName.StructTreeRoot)
.getAsDictionary(PdfName.ParentTree).getAsArray(PdfName.Nums);
assertNull(getStructParentEntry(nums.get(3)));
assertNull(getStructParentEntry(nums.get(5)));
assertNull(getStructParentEntry(nums.get(7)));
assertNull(getStructParentEntry(nums.get(9)));
doc.close();
}
@Test
@LogMessages(messages = {
@LogMessage(messageTemplate = KernelLogMessageConstant.STRUCT_PARENT_INDEX_MISSED_AND_RECREATED, count = 4)
})
public void objRefNoStructParentModificationTest() throws IOException, InterruptedException {
String pdf = sourceFolder + "objRefNoStructParent.pdf";
String outPdf = destinationFolder + "objRefNoStructParentModification.pdf";
String cmpPdf = sourceFolder + "cmp_objRefNoStructParentModification.pdf";
PdfDocument doc = new PdfDocument(new PdfReader(pdf), CompareTool.createTestPdfWriter(outPdf));
doc.close();
Assertions.assertNull(new CompareTool().compareByContent(outPdf, cmpPdf, destinationFolder, "diff"));
}
@Test
@LogMessages(messages = {
@LogMessage(messageTemplate = IoLogMessageConstant.TAG_STRUCTURE_INIT_FAILED)
})
public void xObjNoStructParentNoModificationTest() throws IOException {
String pdf = sourceFolder + "xObjNoStructParent.pdf";
String outPdf = destinationFolder + "xObjNoStructParentNoModification.pdf";
PdfReader reader = new PdfReader(pdf).setStrictnessLevel(PdfReader.StrictnessLevel.CONSERVATIVE);
PdfDocument doc = new PdfDocument(reader, new PdfWriter(outPdf));
PdfObject obj = doc.getCatalog().getPdfObject().getAsDictionary(PdfName.StructTreeRoot)
.getAsDictionary(PdfName.ParentTree).getAsArray(PdfName.Nums).get(1);
PdfStream xObj = ((PdfDictionary) ((PdfArray) obj).get(0)).getAsDictionary(PdfName.K).getAsStream(PdfName.Stm);
assertNull(xObj.get(PdfName.StructParent));
doc.close();
}
@Test
@LogMessages(messages = {
@LogMessage(messageTemplate = KernelLogMessageConstant.XOBJECT_STRUCT_PARENT_INDEX_MISSED_AND_RECREATED)
})
public void xObjNoStructParentModificationTest() throws IOException, InterruptedException {
String pdf = sourceFolder + "xObjNoStructParent.pdf";
String outPdf = destinationFolder + "xObjNoStructParentModification.pdf";
String cmpPdf = sourceFolder + "cmp_xObjNoStructParentModification.pdf";
PdfDocument doc = new PdfDocument(new PdfReader(pdf), CompareTool.createTestPdfWriter(outPdf));
doc.close();
Assertions.assertNull(new CompareTool().compareByContent(outPdf, cmpPdf, destinationFolder, "diff"));
}
@Test
@LogMessages(messages = {
@LogMessage(messageTemplate = KernelLogMessageConstant.STRUCT_PARENT_INDEX_MISSED_AND_RECREATED)
})
public void objRefNoStructParentNoReaderTest() throws IOException, InterruptedException {
String outPdf = destinationFolder + "objRefNoStructParentNoReader.pdf";
String cmpPdf = sourceFolder + "cmp_objRefNoStructParentNoReader.pdf";
PdfDocument pdfDoc = new PdfDocument(CompareTool.createTestPdfWriter(outPdf));
pdfDoc.setTagged();
PdfPage page = pdfDoc.addNewPage();
PdfDictionary mcrDic = new PdfDictionary();
mcrDic.put(PdfName.Pg, page.getPdfObject());
mcrDic.put(PdfName.MCID, new PdfNumber(0));
mcrDic.put(PdfName.Obj, new PdfDictionary());
PdfDictionary elemDic = new PdfDictionary();
elemDic.put(PdfName.P,pdfDoc.getStructTreeRoot().getPdfObject());
PdfStructElem elem = new PdfStructElem(elemDic);
elem.makeIndirect(pdfDoc);
PdfMcr mcr = new PdfObjRef(mcrDic, elem);
elem.addKid(0,mcr);
pdfDoc.getStructTreeRoot().addKid(elem);
pdfDoc.close();
Assertions.assertNull(new CompareTool().compareByContent(outPdf, cmpPdf, destinationFolder, "diff"));
}
@Test
@LogMessages(messages = {
@LogMessage(messageTemplate = IoLogMessageConstant.CREATED_ROOT_TAG_HAS_MAPPING)
})
public void copyPageWithMultipleDocumentTagsTest() throws IOException {
PdfDocument pdfDoc = new PdfDocument(
new PdfReader(sourceFolder + "pdfWithMultipleDocumentTags.pdf"),
new PdfWriter(new ByteArrayOutputStream()));
AssertUtil.doesNotThrow(() -> pdfDoc.getTagStructureContext().normalizeDocumentRootTag());
}
@Test
public void addSeveralAnnotationsWithDifferentTagsTest() throws IOException, InterruptedException {
String outName = destinationFolder + "addSeveralAnnotationsWithDifferentTagsTest.pdf";
String cmpName = sourceFolder + "cmp_addSeveralAnnotationsWithDifferentTagsTest.pdf";
try (PdfDocument document = new PdfDocument(CompareTool.createTestPdfWriter(outName))) {
document.setTagged();
Rectangle rect = new Rectangle(100, 650, 400, 100);
document.addNewPage();
PdfPage pdfPage = document.getPage(1);
PdfScreenAnnotation screen = new PdfScreenAnnotation(new Rectangle(100, 100));
screen.setContents("screen annotation");
pdfPage.addAnnotation(screen);
PdfLinkAnnotation linkAnnotation =
new PdfLinkAnnotation(rect.moveDown(200)).setAction(PdfAction.createURI("https://itextpdf.com/"));
linkAnnotation.setContents("link annot");
pdfPage.addAnnotation(linkAnnotation);
}
Assertions.assertNull(new CompareTool().compareByContent(outName, cmpName, destinationFolder, "diff"));
}
private PdfObject getStructParentEntry(PdfObject obj){
return ((PdfDictionary) obj).getAsDictionary(PdfName.K).getAsDictionary(PdfName.Obj).get(PdfName.StructParent);
}
private boolean checkParentTree(String outFileName, String cmpFileName) throws IOException {
PdfReader outReader = CompareTool.createOutputReader(outFileName);
PdfDocument outDocument = new PdfDocument(outReader);
PdfReader cmpReader = CompareTool.createOutputReader(cmpFileName);
PdfDocument cmpDocument = new PdfDocument(cmpReader);
CompareResult result = new CompareTool().compareByCatalog(outDocument, cmpDocument);
if (!result.isOk()) {
System.out.println(result.getReport());
}
return result.isOk();
}
}