Tuesday, August 21, 2007

Creating weblinks in PDF with iText

Mr. LennyJPG pinged me this morning asking about creating hyperlinks in PDFs generated with Processing. After some digging through the iText javadocs and reading various tutorials it became obvious that Processing's PGraphicsPDF class had to be modified to give us access to the wrapped PdfContentByte instance so that the hyperlink magic can happen. My modified version of Processing's PDF library can be downloaded from here (jar) and there (source). The .jar has to be placed in the /libraries/pdf/library folder inside the Processing root, but please make sure to keep a backup of the original.

The demo below is briefly showing how to create weblinks (here: to various users) and how to position these on the page. All should be pretty self-explanatory. Finally, here's an example PDF generated with this demo.

* iText/Processing PDF weblink demo
* Builds a number of links on the fly and
* positions them randomly on the page.
* CAUTION: This demo requires a modified version of
* Processing's PGraphicsPDF class
* @author: info at toxi dot co dot uk
import processing.pdf.*;
import com.lowagie.text.*;
import com.lowagie.text.pdf.*;

void setup() {
PGraphicsPDF pdf=(PGraphicsPDF)beginRecord(PDF,"test"+(System.currentTimeMillis()/1000)+".pdf");

// draw something in the background
for(int i=0; i < height; i+=10) {

try {
// build hyperlinks for these users
String[] users=new String[] {

for(int i=0; i < users.length; i++) {
// java colours are normalized 0.0 .. 1.0
Color linkCol = new Color(random(1), random(1), random(1));
Chunk c=new Chunk(users[i],FontFactory.getFont(FontFactory.HELVETICA, 14, com.lowagie.text.Font.UNDERLINE, linkCol));
c.setBackground(new Color(0,0,0),5,5,5,5);
// this is using a hacked version of PGraphicsPDF to get access to the PDF content
PdfContentByte cb=pdf.getContent();
ColumnText ct = new ColumnText(cb);
float x=random(width-100);
float y=random(height-100);
ct.setSimpleColumn(new Phrase(c), x,y, x+100, y+50, 16, Element.ALIGN_CENTER);
catch(Exception e) {

// see link below for more info about this method:
void pageSize(com.lowagie.text.Rectangle r, boolean isLandscape, String renderer) {
if (isLandscape) {
else {