You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@pdfbox.apache.org by ms...@apache.org on 2020/10/31 19:18:23 UTC
svn commit: r1883025 - in /pdfbox/trunk/pdfbox/src:
main/java/org/apache/pdfbox/pdmodel/fixup/processor/AcroFormOrphanWidgetsProcessor.java
test/java/org/apache/pdfbox/pdmodel/interactive/form/PDAcroFormFromAnnotsTest.java
Author: msahyoun
Date: Sat Oct 31 19:18:22 2020
New Revision: 1883025
URL: http://svn.apache.org/viewvc?rev=1883025&view=rev
Log:
PDFBOX-3891: handle adding nested fields; enable test
Modified:
pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fixup/processor/AcroFormOrphanWidgetsProcessor.java
pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/interactive/form/PDAcroFormFromAnnotsTest.java
Modified: pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fixup/processor/AcroFormOrphanWidgetsProcessor.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fixup/processor/AcroFormOrphanWidgetsProcessor.java?rev=1883025&r1=1883024&r2=1883025&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fixup/processor/AcroFormOrphanWidgetsProcessor.java (original)
+++ pdfbox/trunk/pdfbox/src/main/java/org/apache/pdfbox/pdmodel/fixup/processor/AcroFormOrphanWidgetsProcessor.java Sat Oct 31 19:18:22 2020
@@ -17,11 +17,14 @@
package org.apache.pdfbox.pdmodel.fixup.processor;
import java.io.IOException;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.fontbox.ttf.TrueTypeFont;
+import org.apache.pdfbox.cos.COSDictionary;
import org.apache.pdfbox.cos.COSName;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
@@ -71,34 +74,83 @@ public class AcroFormOrphanWidgetsProces
private void resolveFieldsFromWidgets(PDAcroForm acroForm)
{
+ Map<String, PDField> nonTerminalFieldsMap = new HashMap<>();
+
LOG.debug("rebuilding fields from widgets");
+
List<PDField> fields = acroForm.getFields();
+
for (PDPage page : document.getPages())
{
try
{
- List<PDAnnotation> annots = page.getAnnotations();
- for (PDAnnotation annot : annots)
- {
- if (annot instanceof PDAnnotationWidget)
- {
- PDField field = PDFieldFactory.createField(acroForm, annot.getCOSObject(), null);
- if (field instanceof PDVariableText)
- {
- ensureFontResources(acroForm.getDefaultResources(), (PDVariableText) field);
- }
- fields.add(field);
- }
- }
+ handleAnnotations(acroForm, fields, page.getAnnotations(), nonTerminalFieldsMap);
}
catch (IOException ioe)
{
LOG.debug("couldn't read annotations for page " + ioe.getMessage());
}
}
+
acroForm.setFields(fields);
+
+ // ensure that PDVariableText fields have the neccesary resources
+ for (PDField field : acroForm.getFieldTree())
+ {
+ if (field instanceof PDVariableText)
+ {
+ ensureFontResources(acroForm.getDefaultResources(), (PDVariableText) field);
+ }
+ }
}
+ private void handleAnnotations(PDAcroForm acroForm, List<PDField> fields, List<PDAnnotation> annotations, Map<String, PDField> nonTerminalFieldsMap)
+ {
+ for (PDAnnotation annot : annotations)
+ {
+ if (annot instanceof PDAnnotationWidget)
+ {
+ if (annot.getCOSObject().containsKey(COSName.PARENT))
+ {
+ PDField resolvedField = resolveNonRootField(acroForm, (PDAnnotationWidget) annot, nonTerminalFieldsMap);
+ if (resolvedField != null)
+ {
+ fields.add(resolvedField);
+ }
+ }
+ else
+ {
+ fields.add(PDFieldFactory.createField(acroForm, annot.getCOSObject(), null));
+ }
+ }
+ }
+ }
+
+ /*
+ * Widgets having a /Parent entry are non root fields. Go up until the root node is found
+ * and handle from there.
+ */
+ private PDField resolveNonRootField(PDAcroForm acroForm, PDAnnotationWidget widget, Map<String, PDField> nonTerminalFieldsMap)
+ {
+ COSDictionary parent = widget.getCOSObject().getCOSDictionary(COSName.PARENT);
+ while (parent.containsKey(COSName.PARENT))
+ {
+ parent = parent.getCOSDictionary(COSName.PARENT);
+ }
+
+ if (nonTerminalFieldsMap.get(parent.getString(COSName.T)) == null)
+ {
+ PDField field = PDFieldFactory.createField(acroForm, parent, null);
+ nonTerminalFieldsMap.put(field.getFullyQualifiedName(),field);
+
+ return field;
+ }
+
+ // this should not happen
+ return null;
+ }
+
+
/*
* Lookup the font used in the default appearance and if this is
* not available try to find a suitable font and use that.
Modified: pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/interactive/form/PDAcroFormFromAnnotsTest.java
URL: http://svn.apache.org/viewvc/pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/interactive/form/PDAcroFormFromAnnotsTest.java?rev=1883025&r1=1883024&r2=1883025&view=diff
==============================================================================
--- pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/interactive/form/PDAcroFormFromAnnotsTest.java (original)
+++ pdfbox/trunk/pdfbox/src/test/java/org/apache/pdfbox/pdmodel/interactive/form/PDAcroFormFromAnnotsTest.java Sat Oct 31 19:18:22 2020
@@ -17,9 +17,12 @@
package org.apache.pdfbox.pdmodel.interactive.form;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
import java.io.IOException;
import java.net.URL;
+import java.util.HashMap;
+import java.util.Map;
import org.apache.pdfbox.Loader;
import org.apache.pdfbox.cos.COSArray;
@@ -168,7 +171,7 @@ public class PDAcroFormFromAnnotsTest
*
* @throws IOException
*/
- // @Test
+ @Test
public void testFromAnnots3891CreateFields() throws IOException
{
@@ -177,11 +180,18 @@ public class PDAcroFormFromAnnotsTest
int numFormFieldsByAcrobat = 0;
+ // will build the expected fields using the acrobat source document
+ Map<String, PDField> fieldsByName = new HashMap<>();
+
try (PDDocument testPdf = Loader.loadPDF(new URL(acrobatSourceUrl).openStream()))
{
PDDocumentCatalog catalog = testPdf.getDocumentCatalog();
PDAcroForm acroForm = catalog.getAcroForm(null);
numFormFieldsByAcrobat = acroForm.getFields().size();
+ for (PDField field : acroForm.getFieldTree())
+ {
+ fieldsByName.put(field.getFullyQualifiedName(), field);
+ }
}
try (PDDocument testPdf = Loader.loadPDF(new URL(sourceUrl).openStream()))
@@ -193,6 +203,19 @@ public class PDAcroFormFromAnnotsTest
assertEquals("Initially there shall be 0 fields", 0, cosFields.size());
PDAcroForm acroForm = catalog.getAcroForm(new CreateFieldsFixup(testPdf));
assertEquals("After rebuild there shall be " + numFormFieldsByAcrobat + " fields", numFormFieldsByAcrobat, acroForm.getFields().size());
+ testPdf.save("/home/msahyoun/Dokumente/Projekte/pdfbox-tests/PDFBOX-3891/merge-tests-fields-pdfbox.pdf");
+
+ // the the fields found are contained in the map
+ for (PDField field : acroForm.getFieldTree())
+ {
+ assertNotNull(fieldsByName.get(field.getFullyQualifiedName()));
+ }
+
+ // test all fields in the map are also found in the AcroForm
+ for (String fieldName : fieldsByName.keySet())
+ {
+ assertNotNull(acroForm.getField(fieldName));
+ }
}
}