Layout PDF documents in Java with iText

iText is a free Java library for generating PDF documents inside your own applications. The library is easy to use and can produce great results with only little programming. The basic usage is pretty simple. Let’s take a look at a small “Hello World” application:

Document document = new Document();
try {
    PdfWriter.getInstance(document, new FileOutputStream("output.pdf"));
    document.open();
    document.add(new Paragraph("Hello World"));
} catch (Exception e) {
}
document.close();

Creating a new document object will initialize a new PDF document with A4 dimensions. The PdfWriter will be used to write the resulting document to an OutputStream, which is in the above example a file. After opening the document you can just add new paragraphs to the document.

Using this document based approach allows quick results with limited control over the layout of the resulting PDF document. To have a better control of the document layout, you need to use the PdfContentByte object to modify the document. This object allows us to position text and graphics with absolute coordinates in the document. Please note that the PDF coordinate system has the origin in the lower left corner of the page. The x-axis is oriented to the right and the y-axis to the top. The coordinates are measured in points. 1 inch is divided into 72 points so that 1 Millimeter equals 2.8346 points. This means that you can position elements on the page with an accuracy of approximately 1/3 Millimeters.

Let’s create a new document and initialize the PdfContentByte object:

Document document = new Document();
try {
    PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream("output.pdf"));
    document.open();
    PdfContentByte cb = writer.getDirectContent();

   // now we can place content elements on the page
} catch (Exception e) {
}
document.close();

Once the PdfContentByte object is initialized, we can use the handle to that object to print text or draw directly on the page. All coordinates are relative to the lower left corner of the page. Let’s write a headline which is centered at the top of the page with a line below it which spawn from the left side to the right side of the page:

// we need to switch to text mode
cb.beginText();
// write text centered at 155 mm from left side and 270 mm from bottom
cb.showTextAligned(PdfContentByte.ALIGN_CENTER, "Our headline", 439, 765, 0);
// leave text mode
cb.endText();

// now draw a line below the headline
cb.setLineWidth(1f); 
cb.moveTo(0, 755);
cb.lineTo(595. 755);
cb.stroke();

It is already possible to create some complex documents with the above methods but when dealing with longer text passages the method showTextAligned has its drawbacks. When dealing with longer text passages, iText has the capability to work with so called columns. A simple column is a rectangular area on the page where a given text is rendered into. The text will be wrapped automatically and if it does not fit into a single column it can continue in another column. This concept of text columns is also widely used in desktop publishing applications. Let’s take a look at how we can use text columns to place text in the document:

// first define a standard font for our text
Font helvetica8BoldBlue = FontFactory.getFont(FontFactory.HELVETICA, 8, Font.BOLD, Color.blue);

// create a column object
ColumnText ct = new ColumnText(cb);

// define the text to print in the column
Phrase myText = new Phrase("Lorem ipsum dolor sit amet, ...", helvetica8BoldBlue);
ct.setSimpleColumn(myText, 72, 600, 355, 317, 10, Element.ALIGN_LEFT);
ct.go();

The above example will create a 10cm x 10cm text box with the sample text printed in a blue 8 point large Helvetica font left aligned.

Please note that when you define additional columns with the setSimpleColumn() method, text which does not fit into the first column will continue in the next column. Although this will be a desired behavior most of the time, sometimes you might want to avoid this. In that case you need to create a new ColumnText object before calling setSimpleColumn().

This should get you going with complex layouts in iText. Please consult the official iText documentation for further information about the iText API.

Leave a Reply