Skip to content

Commit c25d43c

Browse files
committed
Fix PdfAcroform flattening bug with circular references when xObject's resources and page resources are a same object and we later want to add xObject to the page resources
1 parent 5a595a8 commit c25d43c

File tree

3 files changed

+24
-1
lines changed

3 files changed

+24
-1
lines changed

core/src/main/java/com/itextpdf/core/pdf/PdfObject.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ public PdfDocument getDocument() {
215215
* @return cloned object.
216216
*/
217217
@Override
218-
public Object clone() {
218+
public PdfObject clone() {
219219
PdfObject newObject = newInstance();
220220
if (indirectReference != null || checkState(MustBeIndirect)) {
221221
newObject.setState(MustBeIndirect);

forms/src/main/java/com/itextpdf/forms/PdfAcroForm.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -565,6 +565,17 @@ public void flattenFields() {
565565
}
566566
}
567567

568+
// In case of appearance resources and page resources are the same object, it would not be possible to add
569+
// the xObject to the page resources. So in that case we would copy page resources and use the copy for
570+
// xObject, so that circular reference is avoided.
571+
// We copy beforehand firstly not to produce a copy every time, and secondly not to copy all the
572+
// xObjects that have already been added to the page resources.
573+
Map<Integer, PdfObject> initialPageResourceClones = new LinkedHashMap<>();
574+
for (int i = 1; i <= document.getNumberOfPages(); i++) {
575+
PdfObject resources = document.getPage(i).getPdfObject().getAsDictionary(PdfName.Resources);
576+
initialPageResourceClones.put(i, resources == null ? null : resources.clone());
577+
}
578+
568579
PdfPage page;
569580
for (PdfFormField field : fields) {
570581
page = getFieldPage(field.getPdfObject());
@@ -604,6 +615,16 @@ public void flattenFields() {
604615
throw new PdfException(PdfException.PageWasAlreadyFlushedUseAddFieldAppearanceToPageMethodInstead);
605616
}
606617
PdfCanvas canvas = new PdfCanvas(page);
618+
619+
// Here we avoid circular reference which might occur when page resources and the appearance xObject's
620+
// resources are the same object
621+
PdfObject xObjectResources = xObject.getPdfObject().get(PdfName.Resources);
622+
PdfObject pageResources = page.getResources().getPdfObject();
623+
if (xObjectResources != null && pageResources != null &&
624+
xObjectResources == pageResources) {
625+
xObject.getPdfObject().put(PdfName.Resources, initialPageResourceClones.get(document.getPageNumber(page)));
626+
}
627+
607628
canvas.addXObject(xObject, box.getX(), box.getY());
608629
}
609630
}

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,8 @@ public static PdfChoiceFormField createChoice(PdfDocument doc, Rectangle rect, S
409409
public static PdfChoiceFormField createChoice(PdfDocument doc, Rectangle rect, String name, String value, PdfFont font, int fontSize, PdfArray options, int flags) {
410410
PdfWidgetAnnotation annot = new PdfWidgetAnnotation(rect);
411411
PdfChoiceFormField field = new PdfChoiceFormField(annot, doc);
412+
field.font = font;
413+
field.fontSize = fontSize;
412414
field.put(PdfName.Opt, options);
413415
field.setFieldFlags(flags);
414416
field.setFieldName(name);

0 commit comments

Comments
 (0)