diff --git a/openpdf/src/main/java/com/lowagie/text/pdf/PdfDocument.java b/openpdf/src/main/java/com/lowagie/text/pdf/PdfDocument.java index 5ae234122..9dec58b04 100644 --- a/openpdf/src/main/java/com/lowagie/text/pdf/PdfDocument.java +++ b/openpdf/src/main/java/com/lowagie/text/pdf/PdfDocument.java @@ -977,7 +977,10 @@ public boolean newPage() { // [F12] we add tag info if (writer.isTagged()) { - page.put(PdfName.STRUCTPARENTS, new PdfNumber(writer.getCurrentPageNumber() - 1)); + //connecting /NUMS array entry (pageIdValue) with Page via /STRUCTPARENTS value + int pageIdValue = writer.getStructureTreeRoot() + .getOrCreatePageKey(writer.getCurrentPageNumber() - 1); + page.put(PdfName.STRUCTPARENTS, new PdfNumber(pageIdValue)); } if (text.size() > textEmptySize) { diff --git a/openpdf/src/main/java/com/lowagie/text/pdf/PdfStructureTreeRoot.java b/openpdf/src/main/java/com/lowagie/text/pdf/PdfStructureTreeRoot.java index f743c08dd..ef629d554 100644 --- a/openpdf/src/main/java/com/lowagie/text/pdf/PdfStructureTreeRoot.java +++ b/openpdf/src/main/java/com/lowagie/text/pdf/PdfStructureTreeRoot.java @@ -130,19 +130,29 @@ public int addExistingObject(PdfIndirectReference reference) { return key; } - void setPageMark(int page, PdfIndirectReference reference) { - Integer entryForPageArray = pageKeysMap.get(page); + void setPageMark(int pageNumber, PdfIndirectReference reference) { + PdfArray pageArray = (PdfArray) parentTree.get(getOrCreatePageKey(pageNumber)); + pageArray.add(reference); + } + + /** + * Returns array ID for a page-related entry or creates a new one if not exists. + * Can be used for STRUCTPARENTS tag value + * + * @param pageNumber number of page for which the ID is required + * @return Optional with array ID, empty Optional otherwise + */ + int getOrCreatePageKey(int pageNumber) { + Integer entryForPageArray = pageKeysMap.get(pageNumber); if (entryForPageArray == null) { //putting page array PdfArray ar = new PdfArray(); entryForPageArray = parentTreeNextKey; parentTree.put(entryForPageArray, ar); parentTreeNextKey++; - pageKeysMap.put(page, entryForPageArray); + pageKeysMap.put(pageNumber, entryForPageArray); } - - PdfArray pageArray = (PdfArray) parentTree.get(entryForPageArray); - pageArray.add(reference); + return entryForPageArray; } private void nodeProcess(PdfDictionary dictionary, PdfIndirectReference reference) @@ -154,8 +164,7 @@ private void nodeProcess(PdfDictionary dictionary, PdfIndirectReference referenc for (int k = 0; k < ar.size(); ++k) { PdfObject pdfObj = ar.getDirectObject(k); - if (pdfObj instanceof PdfStructureElement) { - PdfStructureElement e = (PdfStructureElement) pdfObj; + if (pdfObj instanceof PdfStructureElement e) { ar.set(k, e.getReference()); nodeProcess(e, e.getReference()); } else if (pdfObj instanceof PdfIndirectReference) { @@ -171,12 +180,12 @@ private void nodeProcess(PdfDictionary dictionary, PdfIndirectReference referenc void buildTree() throws IOException { Map numTree = new HashMap<>(); for (Integer i : parentTree.keySet()) { - PdfObject ar = parentTree.get(i); - if (ar instanceof PdfIndirectReference) { + PdfObject pdfObj = parentTree.get(i); + if (pdfObj instanceof PdfIndirectReference pdfRef) { //saving the reference to the object which was already added to the body - numTree.put(i, (PdfIndirectReference) ar); + numTree.put(i, pdfRef); } else { - numTree.put(i, writer.addToBody(ar).getIndirectReference()); + numTree.put(i, writer.addToBody(pdfObj).getIndirectReference()); } } PdfDictionary dicTree = PdfNumberTree.writeTree(numTree, writer); diff --git a/openpdf/src/main/java/com/lowagie/text/pdf/PdfWriter.java b/openpdf/src/main/java/com/lowagie/text/pdf/PdfWriter.java index 4d857dee2..b2a77d62e 100644 --- a/openpdf/src/main/java/com/lowagie/text/pdf/PdfWriter.java +++ b/openpdf/src/main/java/com/lowagie/text/pdf/PdfWriter.java @@ -1093,15 +1093,26 @@ public PdfIndirectReference getPageReference(int page) { * * @return a page number */ - public int getPageNumber() { return pdf.getPageNumber(); } - PdfIndirectReference getCurrentPage() { + /** + * Retrieves a reference to the current page of the document. + * The current page is typically the last page that was modified or accessed. + * + * @return a {@link PdfIndirectReference} object pointing to the current page in the PDF document. + */ + public PdfIndirectReference getCurrentPage() { return getPageReference(currentPageNumber); } + /** + * Returns the number of the current page in the document. + * The current page is typically the last page that was modified or accessed. + * + * @return the current page number. + */ public int getCurrentPageNumber() { return currentPageNumber; } diff --git a/openpdf/src/test/java/com/lowagie/text/pdf/PdfStructureTreeRootTest.java b/openpdf/src/test/java/com/lowagie/text/pdf/PdfStructureTreeRootTest.java index 43a67fed8..0a33dc2ac 100644 --- a/openpdf/src/test/java/com/lowagie/text/pdf/PdfStructureTreeRootTest.java +++ b/openpdf/src/test/java/com/lowagie/text/pdf/PdfStructureTreeRootTest.java @@ -75,7 +75,7 @@ void buildTreeShouldGenerateParentTreeWithoutException() throws IOException { PdfStructureTreeRoot treeRoot = new PdfStructureTreeRoot(mockWriter); - assertDoesNotThrow(() -> treeRoot.buildTree()); + assertDoesNotThrow(treeRoot::buildTree); } @Test @@ -86,6 +86,38 @@ void buildTreeShouldHandleIOException() throws IOException { PdfStructureTreeRoot treeRoot = new PdfStructureTreeRoot(mockWriter); treeRoot.setPageMark(1, mock(PdfIndirectReference.class)); - assertThrows(IOException.class, () -> treeRoot.buildTree()); + assertThrows(IOException.class, treeRoot::buildTree); + } + + @Test + void getOrCreatePageKeyShouldCreateNewPageArrayWhenNotExists() { + PdfWriter mockWriter = mock(PdfWriter.class); + PdfStructureTreeRoot treeRoot = new PdfStructureTreeRoot(mockWriter); + + PdfIndirectReference mockRef = mock(PdfIndirectReference.class); + + int firstKey = treeRoot.addExistingObject(mockRef); + assertEquals(0, firstKey); + + int pageKey = treeRoot.getOrCreatePageKey(1); + assertEquals(1, pageKey); + } + + @Test + void getOrCreatePageKeyShouldReturnExistingPageKey() { + PdfWriter mockWriter = mock(PdfWriter.class); + PdfStructureTreeRoot treeRoot = new PdfStructureTreeRoot(mockWriter); + + PdfIndirectReference mockRef = mock(PdfIndirectReference.class); + + int firstKey = treeRoot.addExistingObject(mockRef); + assertEquals(0, firstKey); + + //key should be created when setting page mark + treeRoot.setPageMark(1, mock(PdfIndirectReference.class)); + + //existing key should be returned + int pageKey = treeRoot.getOrCreatePageKey(1); + assertEquals(1, pageKey); } } \ No newline at end of file