Skip to content

Commit

Permalink
PdfStructureTreeRoot update - fixing Page linking
Browse files Browse the repository at this point in the history
  • Loading branch information
luzhanov authored and asturio committed Apr 14, 2024
1 parent a980f72 commit c07947f
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 17 deletions.
5 changes: 4 additions & 1 deletion openpdf/src/main/java/com/lowagie/text/pdf/PdfDocument.java
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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) {
Expand All @@ -171,12 +180,12 @@ private void nodeProcess(PdfDictionary dictionary, PdfIndirectReference referenc
void buildTree() throws IOException {
Map<Integer, PdfIndirectReference> 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);
Expand Down
15 changes: 13 additions & 2 deletions openpdf/src/main/java/com/lowagie/text/pdf/PdfWriter.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ void buildTreeShouldGenerateParentTreeWithoutException() throws IOException {

PdfStructureTreeRoot treeRoot = new PdfStructureTreeRoot(mockWriter);

assertDoesNotThrow(() -> treeRoot.buildTree());
assertDoesNotThrow(treeRoot::buildTree);
}

@Test
Expand All @@ -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);
}
}

0 comments on commit c07947f

Please sign in to comment.