Skip to content

Commit 085d05f

Browse files
committed
Finalize anntotation flattening API
DEVSIX-2440
1 parent 2914ea8 commit 085d05f

20 files changed

+278
-142
lines changed

kernel/src/main/java/com/itextpdf/kernel/logs/KernelLogMessageConstant.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@ public final class KernelLogMessageConstant {
8787
+ "fail";
8888
public static final String FLATTENING_IS_NOT_YET_SUPPORTED =
8989
"Flattening annotation type {0} is not yet supported, it will not be removed from the page";
90+
public static final String FORMFIELD_ANNOTATION_WILL_NOT_BE_FLATTENED = "Form field annotation flattening is not "
91+
+ "supported. Use the PdfAcroForm#flattenFields() method instead.";
9092

9193
private KernelLogMessageConstant() {
9294
//Private constructor will prevent the instantiation of this class directly

kernel/src/main/java/com/itextpdf/kernel/utils/PdfAnnotationFlattener.java

Lines changed: 35 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,13 @@ This file is part of the iText (R) project.
2525
import com.itextpdf.commons.utils.MessageFormatUtil;
2626
import com.itextpdf.kernel.exceptions.KernelExceptionMessageConstant;
2727
import com.itextpdf.kernel.exceptions.PdfException;
28+
import com.itextpdf.kernel.pdf.PdfDocument;
2829
import com.itextpdf.kernel.pdf.PdfPage;
2930
import com.itextpdf.kernel.pdf.annot.PdfAnnotation;
3031
import com.itextpdf.kernel.utils.annotationsflattening.IAnnotationFlattener;
3132
import com.itextpdf.kernel.utils.annotationsflattening.PdfAnnotationFlattenFactory;
3233

34+
import java.util.ArrayList;
3335
import java.util.List;
3436

3537
/**
@@ -63,36 +65,56 @@ public PdfAnnotationFlattener() {
6365
* {@link IAnnotationFlattener}.
6466
*
6567
* @param annotationsToFlatten the annotations that should be flattened.
66-
* @param page the page where the annotations are located.
68+
*
69+
* @return the list of annotations that were not flattened successfully
6770
*/
68-
public void flatten(List<PdfAnnotation> annotationsToFlatten, PdfPage page) {
69-
if (page == null) {
70-
throw new PdfException(
71-
MessageFormatUtil.format(KernelExceptionMessageConstant.ARG_SHOULD_NOT_BE_NULL, "page"));
72-
}
71+
public List<PdfAnnotation> flatten(List<PdfAnnotation> annotationsToFlatten) {
7372
if (annotationsToFlatten == null) {
7473
throw new PdfException(
7574
MessageFormatUtil.format(KernelExceptionMessageConstant.ARG_SHOULD_NOT_BE_NULL,
7675
"annotationsToFlatten"));
7776
}
77+
final List<PdfAnnotation> unFlattenedAnnotations = new ArrayList<>();
7878
for (final PdfAnnotation pdfAnnotation : annotationsToFlatten) {
79+
if (pdfAnnotation == null) {
80+
continue;
81+
}
82+
PdfPage page = pdfAnnotation.getPage();
83+
if (page == null) {
84+
continue;
85+
}
7986
final IAnnotationFlattener worker = pdfAnnotationFlattenFactory.getAnnotationFlattenWorker(
8087
pdfAnnotation.getSubtype());
81-
worker.flatten(pdfAnnotation, page);
88+
final boolean flattenedSuccessfully = worker.flatten(pdfAnnotation, page);
89+
if (!flattenedSuccessfully) {
90+
unFlattenedAnnotations.add(pdfAnnotation);
91+
}
92+
8293
}
94+
return unFlattenedAnnotations;
8395
}
8496

8597
/**
86-
* Flattens all annotations on the page according to the defined implementation of
98+
* Flattens the annotations on the page according to the defined implementation of
8799
* {@link IAnnotationFlattener}.
88100
*
89-
* @param page the page where the annotations are located.
101+
* @param document the document that contains the annotations that should be flattened.
102+
*
103+
* @return the list of annotations that were not flattened successfully
90104
*/
91-
public void flatten(PdfPage page) {
92-
if (page == null) {
105+
public List<PdfAnnotation> flatten(PdfDocument document) {
106+
if (document == null) {
93107
throw new PdfException(
94-
MessageFormatUtil.format(KernelExceptionMessageConstant.ARG_SHOULD_NOT_BE_NULL, "page"));
108+
MessageFormatUtil.format(KernelExceptionMessageConstant.ARG_SHOULD_NOT_BE_NULL, "document"));
109+
}
110+
final List<PdfAnnotation> annotations = new ArrayList<>();
111+
// Process page by page to avoid loading a bunch of annotations into memory
112+
final int documentNumberOfPages = document.getNumberOfPages();
113+
for (int i = 1; i <= documentNumberOfPages; i++) {
114+
final PdfPage page = document.getPage(i);
115+
final List<PdfAnnotation> failedFlatteningAnnotations = flatten(page.getAnnotations());
116+
annotations.addAll(failedFlatteningAnnotations);
95117
}
96-
flatten(page.getAnnotations(), page);
118+
return annotations;
97119
}
98120
}

kernel/src/main/java/com/itextpdf/kernel/utils/annotationsflattening/PdfAnnotationFlattenFactory.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ public class PdfAnnotationFlattenFactory {
3434
static {
3535
map = new HashMap<>();
3636
map.put(PdfName.Link, () -> new DefaultAnnotationFlattener());
37-
map.put(PdfName.Popup, () -> new NotSupportedFlattener());
38-
map.put(PdfName.Widget, () -> new NotSupportedFlattener());
37+
map.put(PdfName.Popup, () -> new RemoveWithoutDrawingFlattener());
38+
map.put(PdfName.Widget, () -> new WarnFormfieldFlattener());
3939
map.put(PdfName.Screen, () -> new DefaultAnnotationFlattener());
4040
map.put(PdfName._3D, () -> new DefaultAnnotationFlattener());
4141
map.put(PdfName.Highlight, () -> new HighLightTextMarkupAnnotationFlattener());
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
package com.itextpdf.kernel.utils.annotationsflattening;
2+
3+
import com.itextpdf.commons.utils.MessageFormatUtil;
4+
import com.itextpdf.kernel.exceptions.KernelExceptionMessageConstant;
5+
import com.itextpdf.kernel.exceptions.PdfException;
6+
import com.itextpdf.kernel.pdf.PdfPage;
7+
import com.itextpdf.kernel.pdf.annot.PdfAnnotation;
8+
9+
/**
10+
* This class is used to Remove annotations without drawing them on the page content stream.
11+
*/
12+
public class RemoveWithoutDrawingFlattener implements IAnnotationFlattener {
13+
14+
15+
/**
16+
* Creates a new {@link RemoveWithoutDrawingFlattener} instance.
17+
*/
18+
public RemoveWithoutDrawingFlattener() {
19+
//empty constructor
20+
}
21+
22+
/**
23+
* {@inheritDoc}
24+
*/
25+
@Override
26+
public boolean flatten(PdfAnnotation annotation, PdfPage page) {
27+
if (annotation == null) {
28+
throw new PdfException(
29+
MessageFormatUtil.format(KernelExceptionMessageConstant.ARG_SHOULD_NOT_BE_NULL, "annotation"));
30+
}
31+
if (page == null) {
32+
throw new PdfException(
33+
MessageFormatUtil.format(KernelExceptionMessageConstant.ARG_SHOULD_NOT_BE_NULL, "page"));
34+
}
35+
page.removeAnnotation(annotation);
36+
return true;
37+
}
38+
}
39+
40+
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package com.itextpdf.kernel.utils.annotationsflattening;
2+
3+
import com.itextpdf.commons.utils.MessageFormatUtil;
4+
import com.itextpdf.kernel.exceptions.KernelExceptionMessageConstant;
5+
import com.itextpdf.kernel.exceptions.PdfException;
6+
import com.itextpdf.kernel.logs.KernelLogMessageConstant;
7+
import com.itextpdf.kernel.pdf.PdfPage;
8+
import com.itextpdf.kernel.pdf.annot.PdfAnnotation;
9+
10+
import org.slf4j.Logger;
11+
import org.slf4j.LoggerFactory;
12+
13+
/**
14+
* This class is used to warn user that annotation will not be flattened.
15+
*/
16+
public class WarnFormfieldFlattener implements IAnnotationFlattener {
17+
18+
private static final Logger LOGGER = LoggerFactory.getLogger(WarnFormfieldFlattener.class);
19+
20+
/**
21+
* Creates a new {@link WarnFormfieldFlattener} instance.
22+
*/
23+
public WarnFormfieldFlattener() {
24+
//empty constructor
25+
}
26+
27+
/**
28+
* {@inheritDoc}
29+
*/
30+
@Override
31+
public boolean flatten(PdfAnnotation annotation, PdfPage page) {
32+
if (annotation == null) {
33+
throw new PdfException(
34+
MessageFormatUtil.format(KernelExceptionMessageConstant.ARG_SHOULD_NOT_BE_NULL, "annotation"));
35+
}
36+
if (page == null) {
37+
throw new PdfException(
38+
MessageFormatUtil.format(KernelExceptionMessageConstant.ARG_SHOULD_NOT_BE_NULL, "page"));
39+
}
40+
LOGGER.warn(KernelLogMessageConstant.FORMFIELD_ANNOTATION_WILL_NOT_BE_FLATTENED);
41+
return false;
42+
}
43+
}

0 commit comments

Comments
 (0)