Search code examples
pdfitextbirtpdf-manipulation

Co-ordinates of a element in a pdf file using iText


I'm creating a pdf file using BIRT reporting library. Later I need to digitally sign these files. I'm using iText to digitally sign the document.

The issue I'm facing is, I need to place the signature in different places in different reports. I already have the code to digitally sign the document, now I'm always placing the signature at the bottom of last page in every report.

Eventually I need each report to say where I need to place the signature. Then I've to read the location using iText and then place the signature at that location.

Is this possible to achieve using BIRT and iText

Thanks


Solution

  • If you're willing to cheat a bit, you can use a link... which BIRT supports according to my little dive into their docs just now.

    A link is an annotation. Sadly, iText doesn't support examining annotations at a high level, only generating them, so you'll have to use the low-level object calls.

    The code to extract it might look something like this:

    // getPageN is looking for a page number, not a page index
    PdfDictionary lastPageDict = myReader.getPageN(myReader.getNumberOfPages());
    
    PdfArray annotations = lastPageDict.getAsArray( PdfName.ANNOTS );
    PdfArray linkRect = null;
    if (annotations != null) {
      int numAnnots = annotations.size();
      for (int i = 0; i < numAnnots; ++i) {
        PdfDictionary annotDict = annotations.getAsDict( i );
        if (annotDict == null) 
          continue; // it'll never happen, unless you're dealing with a Really Messed Up PDF.
    
        if (PdfName.LINK.equals( annotDict.getAsName( PdfName.SUBTYPE ) )) {
          // if this isn't the only link on the last page, you'll have to check the URL, which
          // is a tad more work.
          linkRect = annotDict.getAsArray( PdfName.RECT );
    
          // a little sanity check here wouldn't hurt, but I have yet to come across a PDF
          // that was THAT screwed up, and I've seen some Really Messed Up PDFs over the years.
    
          // and kill the link, it's just there for a placeholder anyway.
          // iText doesn't maintain any extra info on links, so no need for other calls.
          annotations.remove( i ); 
          break;
        }
      }
    }
    
    if (linkRect != null) {
      // linkRect is an array, thusly: [ llx, lly, urx, ury ].
      // you could use floats instead, but I wouldn't go with integers.  
      double llx = linkRect.getAsNumber( 0 ).getDoubleValue(); 
      double lly = linkRect.getAsNumber( 1 ).getDoubleValue();
      double urx = linkRect.getAsNumber( 2 ).getDoubleValue();
      double ury = linkRect.getAsNumber( 3 ).getDoubleValue();
    
      // make your signature
      magic();
    }
    

    If BIRT generates some text in the page contents under the link for its visual representation, that's only a minor issue. Your signature should cover it completely.

    You're definitely better of if you can generate the signature directly from BIRT in the first place, but my little inspection of their docs didn't exactly fill me with confidence in their PDF customization abilities... despite sitting on top of iText themselves. It's a report generator that happens to be able to produce PDFs... I shouldn't expect too much. `

    Edit: If you need to look for the specific URL, you'll want to look at section "12.5.6.5 Link Annotations" of the PDF Reference, which can be found here: http://www.adobe.com/content/dam/Adobe/en/devnet/pdf/pdfs/PDF32000_2008.pdf