Mark Stephens

Mark Stephens has been working with Java and PDF since 1999 and has diversified into HTML5, SVG and JavaFX.

He also enjoys speaking at conferences and has been a Speaker at user groups, Business of Software, Seybold and JavaOne conferences. He has a very dry sense of humor and an MA in Medieval History for which he has not yet found a practical use.

Manipulating signatures and links in PDF files

1 min read

We get quite a few questions asking about accessing Form objects on the page especially Link or signature objects.

This is actually fairly easy to do. The PDF file normally contains both of these objects as Annotations. A list of Annotations are stored on each page and the Annotations objects contain their type and location. If you read them using their Object reference you can then use that to manipulate them using tools such as IText. The important thing to remember with such objects is that all the co-ordinates are specified using PDF co-ordinates, so you may need to alter them if you are using another language such as Java.

And lastly, here is some code so you can visualise this or see how it would work in JPedal

int pageCount=decodePdf.getPageCount(); //page count
for(int ii=1;ii<pageCount+1;ii++){
    
    //get the list of Annotations for each page
    PdfArrayIterator annotListForPage = decodePdf.
                           getFormRenderer().getAnnotsOnPage(ii);

    //if values present scan through
    if(annotListForPage!=null){
while (annotListForPage.hasMoreTokens()) {

    //get PDF ref ID of annot
    String annotKey = annotListForPage.
                                       getNextValueAsString(true);

    //could get more than one item back for radio buttons 
            //but with PFD ref should be only 1
    Object[] rawObj = decodePdf.getFormRenderer().
                               getCompData().getRawForm(annotKey);

    //if we have scan through and show some useful info
    for (int i = 0; i < rawObj.length; i++) {

                if (rawObj[i] == null)
                    continue;

//each PDF annot object - extract data from it
FormObject annotObj = (FormObject) rawObj[i];

int subtype = annotObj.
                  getParameterConstant(PdfDictionary.Subtype);

                //ignore other PDF object types
if (subtype != PdfDictionary.Sig || 
                     subtype != PdfDictionary.Link)
                     continue;

if(subtype== PdfDictionary.Link)
   System.out.println("link object");
else
   System.out.println("Sig object");
    
                //PDF co-ords

float[] coords = annotObj.
                           getFloatArray(PdfDictionary.Rect);

System.out.println("PDF Rect= " + coords[0] + " " + 
                coords[1] + 
                  " " + coords[2] + " " + coords[3]);

//convert to Javaspace rectangle by subtracting 
                //page Crop Height
int pageH = decodePdf.getPdfPageData().
                                  getCropBoxHeight(ii);

float x = coords[0];

float w = coords[2] - coords[0];
float h = coords[3] - coords[1];
                //note we remove h from y
float y = pageH - coords[1] - h; 
System.out.println("Javaspace Rect x=" + x + 
                " y=" + y +" w=" + w + " h=" + h);

//text in A subobject
PdfObject aData = annotObj.
                               getDictionary(PdfDictionary.A);

if (aData != null && 
                  aData.getNameAsConstant(PdfDictionary.S) == 
                   PdfDictionary.URI) {

  String text = aData.
                           getTextStreamValue(PdfDictionary.URI);

          System.out.println("text=" + text);
   
                }
    }
}
    }
}
Mark Stephens

Mark Stephens has been working with Java and PDF since 1999 and has diversified into HTML5, SVG and JavaFX.

He also enjoys speaking at conferences and has been a Speaker at user groups, Business of Software, Seybold and JavaOne conferences. He has a very dry sense of humor and an MA in Medieval History for which he has not yet found a practical use.

Leave a Reply

Your email address will not be published. Required fields are marked *