Search code examples
javaitextautofillform-fieldsformfield

Remove page reference from annotation


I added a textfield with several kids similar as described here. Did that to use the autofill functionality of PDF... Now my question is how am I able to remove the page reference from the parent element? The data field should not contain a parent reference since it is not related to any page. The widgets should contain those (which I added there however I can't remove the parent /P page reference)

I tried

PdfFormField parent = PdfFormField.createTextField(stamper.getWriter(), false, false, 0);
parent.setFieldName(fieldName);

for (int page = 1; page <= pages; page++) {
    TextField textField = new TextField(stamper.getWriter(), new Rectangle(560, 600, 590, 800), null);

    PdfFormField pff = textField.getTextField();
    parent.addKid(pff);
    // add widget to each page
    pff.setPlaceInPage(page);
    //iText workarounds
    field.put(PdfName.P, stamper.getWriter().getPageReference(page));
    field.remove(PdfName.FF);
    field.remove(PdfName.FT);
}
//in addAnnotation() the page reference is written
stamper.addAnnotation(parent, 1);
//does not work
parent.remove(PdfName.P);

however it didn't work since I guess the page reference is already written. Is there a way to remove it afterwards?


Solution

  • Fact 1:

    The PdfFormField class extends the PdfAnnotation class, because most of the times, it is possible to merge a field dictionary with an annotation dictionary.

    In your case, you have a PdfFormField that is used as a hierarchical element and although that element is also an instance of PdfAnnotation, it isn't. You can check this by using the isAnnotation() method. It will return false.

    Fact 2:

    When you add an annotation to an existing PDF, you have to use PdfStamper's addAnnotation() method that not only accepts an annotation object, but also a page number. If you didn't add a page number, PdfStamper wouldn't know where to add the annotation.

    When you add a real annotation, PdfStamper will add a /P key that refers to the page where the annotations is visualized.

    Fact 3:

    There is no other way than using addAnnotation() with an annotation and a page number when working with PdfStamper. When you add a PdfFormField object that is not a real annotation, it won't be treated differently, hence a /P entry will be added, although that doesn't really make sense (as you rightly point out in your question).

    Fact 4:

    The /P entry is optional. For the widget annotations to be displayed correctly, it is sufficient that they appear in the /Annots of a page.

    Conclusion:

    iText shouldn't add a /P entry in case you add a PdfFormField that is not a real annotation. Hence I have committed the following change: revision 6756

         void addAnnotation(PdfAnnotation annot, int page) {
    -     annot.setPage(page);
    +        if (annot.isAnnotation())
    +            annot.setPage(page);
             addAnnotation(annot, reader.getPageN(page));
         }
    

    I have tested this with the AddFieldAndKids example and it seems to work: the /P entry is no longer added.

    This solves your problem in a more robust way. You shouldn't try to remove something that shouldn't have been added in the first place.