Skip to content

Commit 56486c3

Browse files
Remove outlines and annotations along with removing the page
DEVSIX-485
1 parent e8c4b7f commit 56486c3

File tree

7 files changed

+96
-19
lines changed

7 files changed

+96
-19
lines changed

forms/src/main/java/com/itextpdf/forms/fields/PdfFormField.java

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1467,10 +1467,8 @@ public boolean regenerateField() {
14671467
if (PdfName.Tx.equals(type)) {
14681468
if (!isMultiline()) {
14691469
drawTextAppearance(bBox.toRectangle(), localFont, fontSz, value, appearance);
1470-
// drawnAppearance = drawTextAppearance(bBox.toRectangle(), localFont, fontSz, value, appearance1);
14711470
} else {
14721471
drawMultiLineTextAppearance(bBox.toRectangle(), localFont, fontSz, value, appearance);
1473-
// drawnAppearance = drawMultiLineTextAppearance(bBox.toRectangle(), localFont, fontSz, value, apResources);
14741472
}
14751473

14761474
} else {
@@ -1485,14 +1483,9 @@ public boolean regenerateField() {
14851483
value = optionsArrayToString(options);
14861484
}
14871485
drawMultiLineTextAppearance(bBox.toRectangle(), localFont, fontSz, value, appearance);
1488-
// drawnAppearance = drawMultiLineTextAppearance(bBox.toRectangle(), localFont, fontSz, value, apResources);
14891486
}
14901487

1491-
//appearance1.getPdfObject().setData(drawnAppearance);
1492-
//appearance1.getPdfObject().getOutputStream().writeBytes();
14931488
appearance.getResources().addFont(getDocument(), localFont);
1494-
1495-
//appearance.getResources().addFont(getDocument(), localFont);
14961489
PdfDictionary ap = new PdfDictionary();
14971490
ap.put(PdfName.N, appearance.getPdfObject());
14981491
put(PdfName.AP, ap);

kernel/src/main/java/com/itextpdf/kernel/pdf/PdfCatalog.java

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,15 @@
22

33
import com.itextpdf.kernel.PdfException;
44
import com.itextpdf.kernel.pdf.action.PdfAction;
5+
import com.itextpdf.kernel.pdf.annot.PdfAnnotation;
6+
import com.itextpdf.kernel.pdf.annot.PdfWidgetAnnotation;
57
import com.itextpdf.kernel.pdf.collection.PdfCollection;
68
import com.itextpdf.kernel.pdf.layer.PdfOCProperties;
79
import com.itextpdf.kernel.pdf.navigation.PdfDestination;
810
import com.itextpdf.kernel.pdf.navigation.PdfExplicitDestination;
911
import com.itextpdf.kernel.pdf.navigation.PdfStringDestination;
1012

11-
import java.util.ArrayList;
12-
import java.util.HashMap;
13-
import java.util.List;
14-
import java.util.Map;
13+
import java.util.*;
1514

1615
public class PdfCatalog extends PdfObjectWrapper<PdfDictionary> {
1716

@@ -80,15 +79,16 @@ public int getPageNumber(PdfDictionary pageDictionary) {
8079

8180
public boolean removePage(PdfPage page) {
8281
//TODO log removing flushed page
83-
if (outlineMode)
84-
removeOutlines(page);
82+
removeOutlines(page);
83+
removeUnusedWidgetsFromFields(page);
8584
return pageTree.removePage(page);
8685
}
8786

8887
public PdfPage removePage(int pageNum) {
8988
//TODO log removing flushed page
90-
if (outlineMode)
91-
removeOutlines(getPage(pageNum));
89+
PdfPage page = getPage(pageNum);
90+
removeOutlines(page);
91+
removeUnusedWidgetsFromFields(page);
9292
return pageTree.removePage(pageNum);
9393
}
9494

@@ -419,15 +419,37 @@ PdfDestination copyDestination(PdfObject dest, Map<PdfPage, PdfPage> page2page,
419419
return d;
420420
}
421421

422+
/**
423+
* This method removes all annotation entries from form fields associated with a given page.
424+
* @param page
425+
*/
426+
private void removeUnusedWidgetsFromFields(PdfPage page){
427+
if (page.isFlushed()) {
428+
return;
429+
}
430+
List<PdfAnnotation> annots = page.getAnnotations();
431+
for (PdfAnnotation annot : annots) {
432+
if (annot.getSubtype().equals(PdfName.Widget)) {
433+
((PdfWidgetAnnotation)annot).releaseFormFieldFromWidgetAnnotation();
434+
}
435+
}
436+
}
437+
422438
/**
423439
* This method removes all outlines associated with a given page
424440
*
425441
* @param page
426442
* @throws PdfException
427443
*/
428444
private void removeOutlines(PdfPage page) {
429-
for (PdfOutline outline : pagesWithOutlines.get(page.getPdfObject().getIndirectReference())) {
430-
outline.removeOutline();
445+
if (getDocument().getWriter() == null) {
446+
return;
447+
}
448+
getOutlines(false);
449+
if (!pagesWithOutlines.isEmpty()) {
450+
for (PdfOutline outline : pagesWithOutlines.get(page.getPdfObject().getIndirectReference())) {
451+
outline.removeOutline();
452+
}
431453
}
432454
}
433455

kernel/src/main/java/com/itextpdf/kernel/pdf/PdfOutline.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,13 +166,21 @@ void setDestination(PdfDestination destination){
166166
* @throws PdfException
167167
*/
168168
void removeOutline() {
169+
PdfName type = content.getAsName(PdfName.Type);
170+
if (type != null && type.equals(PdfName.Outlines)) {
171+
pdfDoc.getCatalog().remove(PdfName.Outlines);
172+
return;
173+
}
169174
PdfOutline parent = this.parent;
170175
List<PdfOutline> children = parent.children;
171176
children.remove(this);
172177
PdfDictionary parentContent = parent.content;
173178
if (!children.isEmpty()){
174179
parentContent.put(PdfName.First, children.get(0).content);
175180
parentContent.put(PdfName.Last, children.get(children.size()-1).content);
181+
} else {
182+
parent.removeOutline();
183+
return;
176184
}
177185

178186
PdfDictionary next = content.getAsDictionary(PdfName.Next);

kernel/src/main/java/com/itextpdf/kernel/pdf/annot/PdfWidgetAnnotation.java

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
package com.itextpdf.kernel.pdf.annot;
22

33
import com.itextpdf.kernel.geom.Rectangle;
4+
import com.itextpdf.kernel.pdf.PdfArray;
45
import com.itextpdf.kernel.pdf.PdfDictionary;
56
import com.itextpdf.kernel.pdf.PdfName;
67
import com.itextpdf.kernel.pdf.PdfObject;
78

9+
import java.util.HashSet;
10+
811
public class PdfWidgetAnnotation extends PdfAnnotation {
912

1013
public PdfWidgetAnnotation(Rectangle rect) {
@@ -15,6 +18,28 @@ public PdfWidgetAnnotation(PdfDictionary pdfObject) {
1518
super(pdfObject);
1619
}
1720

21+
private HashSet<PdfName> widgetEntries = new HashSet<PdfName>() {{
22+
add(PdfName.Subtype);
23+
add(PdfName.Type);
24+
add(PdfName.Rect);
25+
add(PdfName.Contents);
26+
add(PdfName.P);
27+
add(PdfName.NM);
28+
add(PdfName.M);
29+
add(PdfName.F);
30+
add(PdfName.AP);
31+
add(PdfName.AS);
32+
add(PdfName.Border);
33+
add(PdfName.C);
34+
add(PdfName.StructParent);
35+
add(PdfName.OC);
36+
add(PdfName.H);
37+
add(PdfName.MK);
38+
add(PdfName.A);
39+
add(PdfName.AA);
40+
add(PdfName.BS);
41+
}};
42+
1843
@Override
1944
public PdfName getSubtype() {
2045
return PdfName.Widget;
@@ -47,4 +72,20 @@ public PdfWidgetAnnotation setHighlightMode(PdfName mode) {
4772
public PdfName getHighlightMode() {
4873
return getPdfObject().getAsName(PdfName.H);
4974
}
75+
76+
/**
77+
* This method removes all widget annotation entries from the form field the given annotation merged with.
78+
*/
79+
public void releaseFormFieldFromWidgetAnnotation(){
80+
PdfDictionary annotDict = getPdfObject();
81+
getPdfObject().keySet().removeAll(widgetEntries);
82+
PdfDictionary parent = annotDict.getAsDictionary(PdfName.Parent);
83+
if (parent != null && annotDict.keySet().size() == 1) {
84+
PdfArray kids = parent.getAsArray(PdfName.Kids);
85+
kids.remove(annotDict.getIndirectReference());
86+
if (kids.isEmpty()) {
87+
parent.remove(PdfName.Kids);
88+
}
89+
}
90+
}
5091
}

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

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,6 @@ public void setupRemovePageWithOutlinesTest() throws IOException {
105105
FileOutputStream fos = new FileOutputStream(destinationFolder+"removePagesWithOutlinesResult.pdf");
106106
PdfWriter writer = new PdfWriter(fos);
107107
PdfDocument pdfDoc = new PdfDocument(reader, writer);
108-
109-
PdfOutline outlines = pdfDoc.getOutlines(false);
110108
pdfDoc.removePage(102);
111109

112110
pdfDoc.close();

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

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import com.itextpdf.test.ExtendedITextTest;
66

77
import java.io.ByteArrayOutputStream;
8+
import java.io.FileNotFoundException;
89
import java.io.FileOutputStream;
910
import java.io.IOException;
1011
import java.util.List;
@@ -329,5 +330,19 @@ public void getPageByDictionary() throws IOException {
329330
pdfDoc.close();
330331
}
331332

333+
@Test
334+
public void removePageWithFormFieldsTest() throws IOException {
335+
String filename = sourceFolder + "docWithFields.pdf";
336+
337+
PdfDocument pdfDoc = new PdfDocument(new PdfReader(filename));
338+
pdfDoc.removePage(1);
339+
340+
PdfArray fields = pdfDoc.getCatalog().getPdfObject().getAsDictionary(PdfName.AcroForm).getAsArray(PdfName.Fields);
341+
PdfDictionary field = (PdfDictionary) fields.get(0);
342+
PdfDictionary kid = (PdfDictionary) field.getAsArray(PdfName.Kids).get(0);
343+
Assert.assertEquals(6, kid.keySet().size());
344+
Assert.assertEquals(3, fields.size());
345+
}
346+
332347

333348
}
Binary file not shown.

0 commit comments

Comments
 (0)