- HubPages»
- Technology»
- Computers & Software»
- Computer Science & Programming»
- Programming Languages
How to Create a Basic iText PDF Document with Graphics Using itextpdf Java Library
Overview
This article is meant as an introductory high level overview of iText Java library for creating PDF documents, as well as a showcase of some of the features I found to be really cool and useful. I will intertwine theoretical knowledge with the practical examples and let you see what was driving my decisions.
In the more technical part of this article I show you how to add text, links, images and generated graphics to your PDF document. So the end result will hopefully be that you get a good grasp of the iText API and will be able to start thinking about your future projects of generating PDFs as a part of your web service.
Although I will try to make my code as clear as poossible you would probably help your self greatly by knowing at least a little bit about Java.
Software You Need for This Exercice
- Java Runtime Environment - http://www.oracle.com/technetwork/java/javase/downloads/index.html (or just try http://www.oracle.com if the link above gets outdated)
- Integrated Development Environment - Eclipse - http://eclipse.org/downloads/
- iText library - http://itextpdf.com/download.php (click on the "Download iText" when you get there)
Why use iText?
The short answer is because you want to automate your PDF generation. A slightly longer answer is that you want to be able to produce high quality PDF documents
generated from an XML or a database. Plus "Google is using iText in the Google Calendar, Google Spreadsheets, Google Analytics...". Many other companies in the Business Intelligence & Reporting Tools world are using iText.
The most basic reason though is to produce documents that would look the same on all computers that can open a PDF document, which is not possible even today if you're using HTML. Also iText is very fast, has an unprecedented free support, (that some say is even better than paid support) with very active mailing list.
And in general the creation of iText is in my opinion an epic story in itself which deserves a separate reading session. Luckily Bruno Lowagie, the creator of iText, has been very active with creation, support and marketing of his great tool, so you'll be able to find a lot of information ranging from his biography, interviews, funny support related answers and of course much more.
Bruno Lowagie is one of those rare people that can be an open source pogrammer,
entrepreneur, marketer and all the while remain true to himself. I'm greatly
inspired by his story.
High Level Overview of the Sample Code
- Set up a document
- Add a Title
- Add a Subtitle
- Add a Paragraph of Text
- Add a Hyper Link
- Add a Click-able Image with a URL
- Add a Very Simple Pie-chart
- Helper Functions
If You Don't Understand Something or Want to Have More Examples Please Consider Buying One of the Books from Bruno Lowagie (iText in Action: Creating and Manipu
Static Finals or Constants at the Top of iTextIntroduction Class
There is a bunch of static final variables defined at the top of my iTextIntroduction class. I have created them for myself and for you for easy tinkering. So feel free to change things up and generate different PDFs. I actually recommend doing this before getting your hands dirty with the code.
1 Set Up a Document
Calling setUpDocument(Document doc) from createPdf() method
The first six lines add meta data to the PDF document which can be seen from the File > Properties from inside the Acrobat Reader. The last three lines are related to the size and margins of the document. It is worth noting that the A4 standard of sheet size is equivalent to 210 millimeters by 297 millimeters which translates to about 605 by 855 points. This information will be important later on in this application and is generally good to know if you often word with PDF documents.
1 Set Up a Document Code Snippet
doc.addTitle( "Introduction to iText - " + "Create a PDF Document with Text, Hyperlinks and Graphics" ); doc.addSubject( "Introduction to iText" ); doc.addKeywords( "Java, PDF, iText" ); doc.addAuthor( "kievan" ); doc.addCreator( "kievan" ); // A4 = 210mm x 297mm ~ 605points x 855points doc.setPageSize( PageSize.A4 ); doc.setMargins( 72f, 72f, 72f, 72f );
2 Add a Title
Calling addText( titleS, document, TITLE_FONT, 2 ) from createPdf() method
Here is a pretty simple function that adds a string of text to a document. The first line creates a paragraph using a string and a previously defined TITLE_FONT object. The second line calls a helper function that will add two new lines to the title object. And finally third line will add the title object to a doc object.
2 Add a Title Code Snippet
Paragraph paragraph = new Paragraph( text, font ); addEmptyLine( paragraph, newLines ); doc.add( paragraph );
3 Add a Subtitle
Calling addText( titleS, document, TITLE_FONT, 2 ) from createPdf() method
A very similar scenario to the step above with the exception of the font object. By passing a different font object I changed the appearance of the subtitle string.
3 Add a Subtitle Code Snippet
Paragraph paragraph = new Paragraph( text, font ); addEmptyLine( paragraph, newLines ); doc.add( paragraph );
4 Add a Paragraph of Text
Calling addText( String paragraphS, Document doc, Font font, int newLines ) from createPdf() method
Again the code reuse in action shows that we only change parameters to the same function. Again the only thing that changes is the font.
4 Add a Paragraph of Text Code Snippet
Paragraph paragraph = new Paragraph( text, font ); addEmptyLine( paragraph, newLines ); doc.add( paragraph );
If You Don't Understand Something or Want to Have More Examples Please Consider Buying One of the Books from Bruno Lowagie (iText in Action: Creating and Manipu
5 Add a Hyper Link
Calling addURL( urlS, PARAGRAPH_URL, document, URL_FONT ) from createPdf() method
In this function we are faced with a slightly different situation. We are essentially adding a text that is hyperlinked to a URL. First I create an instance of Chunk object using its constructor. Then the Chunk c is assigned an action on line 2 (this is where the url is "built into" the text), and gets a decoration attribute added to it on line 3. And finally the Chunk c is added to the Document doc. The setUnderline takes two parameters of type float: line width and line y position.
5 Add a Hyper Link Code Snippet
Chunk c = new Chunk( text, font ); c.setAction( new PdfAction( new URL( url ) ) ); c.setUnderline(0.8f, -0.8f); doc.add( c );
6 Add a Click-able Image with a URL
Calling addTextAtXY() and addImageAtXY( urlS, PARAGRAPH_URL, document, URL_FONT ) from createPdf() method
I will take a closer look at addTextAtXY() in the last step titled Helper Functions, as for right now the function does what the name suggests, it adds a string of text at the specified absolute location inside a document. addImageAtXY() has couple of extra wrinkles to make the image fit in nicely with the rest of the PDF document. iText PDF Library allows to scale and manipulate an image in different ways, which is very handy. On line 1 I am creating an Image instance called img, then I resize the image to 150 by 150 pixels or points (Note that I know the dimensions of the imported image before hand so I knew this would look ok, but if your image is not a square it might look malformed). Then I position the image on line 4 (Note that in iText the coordinate system's [0,0] coordinate is at the lower left corner of the page and, in case of A4 sized document, [605,855] is at the upper right corner!). I create an annotation on line 5 and on line 6 is where I add a link to an image by setting an annotation. Line 7 is where image is added to the document.
6 Add a Click-able Image with a URL Code Snippet
Image img = com.itextpdf.text.Image.getInstance( imageSource ); img.scaleToFit( 150f, 150f ); img.setAbsolutePosition( x, y ); Annotation anno = new Annotation( 0f, 0f, 0f, 0f, url ); img.setAnnotation( anno ); doc.add( img );
7 Add a Very Simple Pie-chart
Calling addTextAtXY( "Very simple pie chart.", writer.getDirectContent(), 260f, 305f ) and addPieChart( writer.getDirectContent() ) from createPdf() method
Again we'll take a closer at addTextAtXY in the next step, as for the addPieChart() this function is shamelessly simple. Basic idea is to use arcs to create equally sized pie segments.
First you'll see that I plan to update this function so it does all the things I've outlined in the TODO list.
Then on line 9 I set the width of line to be 3.2 points, right after on line 10 I set the color of the line to white. Line 12 is where the fill color is defined to a bright green. Then on line 13 there is a hint I've left for myself, which reads like this: lower left x, lower left y, upper right x, upper right y, starting angle in degrees, the extent of the arc segment in degrees. With that knowledge it is easier to understand line 14: we're drawing an arc bounded by the rectangle (I've made it a square) with lower left coordinates at 200,100 and upper right coordinates at 400,300 and that begins at angle 0 and extends for 120 degrees. Next line, 15, I'm drawing a line from where the arc method stopped drawing to the center of the future pie chart. At line 16, a method closePathFillStroke does two things at once: a line is drawn from the center of the pie chart to the beginning of the arc and then the pie piece is filled with predefined (line 12) color.
The rest of this function is just a repetition of lines 12 to 16. It most definitely not a way to create a pie, but for the purposes of understanding how iText draws simple shapes it is simpler to grasp.
7 Add a Very Simple Pie-chart Code Snippet
/** TODO: Automate and improve pie chart creation. * 1. Add support for adding pie pieces dynamically * from an ArrayList. * 2. Calculate pie chart location based on single set * of coordinates. * 3. Assign each pie piece a random color. */ directcontent.setLineWidth(3.2f); directcontent.setRGBColorStroke(255, 255, 255); directcontent.setRGBColorFill(16, 205, 55); // llx, lly, urx, ury, begin, extent directcontent.arc(200, 100, 400, 300, 0, 120); directcontent.lineTo(300,200); directcontent.closePathFillStroke(); directcontent.setRGBColorFill(254, 205, 16); directcontent.arc(200, 100, 400, 300, 120, 120); directcontent.lineTo(300,200); directcontent.closePathFillStroke(); directcontent.setRGBColorFill(155, 25, 16); directcontent.arc(200, 100, 400, 300, 240, 120); directcontent.lineTo(300,200); directcontent.closePathFillStroke();
8 Helper Functions addTextAtXY()
Calling addTextAtXY( String text, PdfContentByte cb, float x, float y ) from various places in createPdf() method
On line 1 the Basefont object is created. Line 2, signaling a beginning of text generatoin on the current canvas (PdfContentByte cb). Line 3, setting the fill color, which sets the text color using of the predefined constants. Line 4, setting the font (font name [it is possible to use a font that you've downloaded to your system], encoding -> http://en.wikipedia.org/wiki/Windows-1252, and if its embedded or not, which means that if you use a font you've downloaded from somewhere iText can embed it in a PDF document; than the font looks the same on other machines even if they don't have it installed) and its size. Line 5 is where the absolute position of the text is set. Line 6 makes the text visible on the canvas, and line 7 indicates the end of text operations on canvas.
8 Helper Functions addTextAtXY() Code Snippet
BaseFont labelFont = BaseFont.createFont( BaseFont.TIMES_ROMAN, "Cp1252", true ); cb.beginText(); cb.setColorFill( TITLE_COLOR ); cb.setFontAndSize( labelFont, 10 ); cb.setTextMatrix( x, y ); cb.showText( text ); cb.endText();
8 Helper Functions addEmptyLine()
Calling addEmptyLine(Paragraph par, int howMany) from various places in createPdf() method
Line 1 is the start of a for loop which runs for as many times as specified by the howMany parameter. Line 2, adding an empty Paragraph to a Paragraph par.
8 Helper Functions addEmptyLine() Code Snippet
for( int i=0; i < howMany; i++ ) par.add( new Paragraph(" ") );
If You Don't Understand Something or Want to Have More Examples Please Consider Buying One of the Books from Bruno Lowagie (iText in Action: Creating and Manipu
Screenshot of the PDF generated by iTextIntroduction class
iTextIntroduction.java
import java.io.FileOutputStream; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import com.itextpdf.text.Annotation; import com.itextpdf.text.BaseColor; import com.itextpdf.text.Chunk; import com.itextpdf.text.Document; import com.itextpdf.text.DocumentException; import com.itextpdf.text.Font; import com.itextpdf.text.FontFactory; import com.itextpdf.text.Image; import com.itextpdf.text.PageSize; import com.itextpdf.text.Paragraph; import com.itextpdf.text.pdf.BaseFont; import com.itextpdf.text.pdf.PdfAction; import com.itextpdf.text.pdf.PdfContentByte; import com.itextpdf.text.pdf.PdfWriter; public class iTextIntroduction { /** Path of the PDF document. */ public static final String OUTPUT = "c:\\temp\\iTextIntorduction.pdf"; /** Title color using rgb */ public static final BaseColor TITLE_COLOR = new BaseColor(25, 50, 75); /** Title font name, size, style and color */ public static final Font TITLE_FONT = FontFactory.getFont( FontFactory.TIMES, 18, Font.BOLD, TITLE_COLOR ); /** Subtitle font name, size, style and color */ public static final Font SUBTITLE_FONT = FontFactory.getFont( FontFactory.TIMES, 16, Font.BOLD, TITLE_COLOR ); /** Paragraph color using rgb */ public static final BaseColor PARAGRAPH_COLOR = new BaseColor(75, 50, 75); /** Paragraph font name, size, style and color */ public static final Font PARAGRAPH_FONT = FontFactory.getFont( FontFactory.TIMES, 12, Font.BOLD, PARAGRAPH_COLOR ); /** URL color using rgb */ public static final BaseColor URL_COLOR = new BaseColor( 5, 5, 75); /** Paragraph font name, size, style and color */ public static final Font URL_FONT = FontFactory.getFont( FontFactory.TIMES, 12, Font.BOLD, URL_COLOR ); /** Url string to be added to a paragraph */ public static final String PARAGRAPH_URL = "http://hubpages.com/profile/kievan"; /** Url string of an image */ public static final String IMAGE_SRC_URL = "http://s2.hubimg.com/u/3954873_177.jpg"; /** Url string to be added to an image */ public static final String IMAGE_URL = "http://hubpages.com/profile/kievan"; public void createPdf(String output) throws IOException, DocumentException { // Create a document object Document document = new Document(); // Create a writer that puts a document into a file FileOutputStream fos = new FileOutputStream( output ); PdfWriter writer = PdfWriter.getInstance( document, fos ); document.open(); // Set document size, margins and meta data setUpDocument( document ); // Add a title String titleS = "Introduction to iText - Create a PDF Document with " + "Text, Hyperlinks and Graphics"; addText( titleS, document, TITLE_FONT, 2 ); // Add a subtitle String subtitleS = "iText rules!"; addText( subtitleS, document, SUBTITLE_FONT, 2 ); // Add a paragraph String paragraphS = "A Sample text from me. Anything that comes to mind " + "is simply written here. Where the mighty wind blows,"+ " there you shall find me."; addText( paragraphS, document, PARAGRAPH_FONT, 2 ); // Add a URL String urlS = "- kievan"; addURL( urlS, PARAGRAPH_URL, document, URL_FONT ); // Add image with a label addTextAtXY( "Clickable HubPages profile picture.", writer.getDirectContent(), 225f, 530f ); addImageAtXY( document, new URL( IMAGE_SRC_URL ), new URL( IMAGE_URL ), 225f, 370f ); // Add pie chart addTextAtXY( "Very simple pie chart.", writer.getDirectContent(), 260f, 305f ); addPieChart( writer.getDirectContent() ); // Close a document document.close(); System.out.println("Created PDF document!"); } /** * Sets up document size, margins and metadata. * iText allows to add metadata to the PDF which can be * viewed in your Adobe Reader under File -> Properties * @param doc a document that is going to be set up. */ public static void setUpDocument( Document doc ) { doc.addTitle( "Introduction to iText - " + "Create a PDF Document with Text, Hyperlinks and Graphics" ); doc.addSubject( "Introduction to iText" ); doc.addKeywords( "Java, PDF, iText" ); doc.addAuthor( "kievan" ); doc.addCreator( "kievan" ); // A4 = 210mm x 297mm ~ 605points x 855points doc.setPageSize( PageSize.A4 ); doc.setMargins( 72f, 72f, 72f, 72f ); } public static void addText( String text, Document doc, Font font, int newLines ) throws DocumentException { Paragraph paragraph = new Paragraph( text, font ); addEmptyLine( paragraph, newLines ); doc.add( paragraph ); } public static void addURL( String text, String url, Document doc, Font font ) throws DocumentException, MalformedURLException { Chunk c = new Chunk( text, font ); c.setAction( new PdfAction( new URL( url ) ) ); c.setUnderline(0.8f, -0.8f); doc.add( c ); } public static void addImageAtXY( Document doc, URL imageSource, URL url, float x, float y ) throws DocumentException, IOException { Image img = com.itextpdf.text.Image.getInstance( imageSource ); img.scaleToFit( 150f, 150f ); img.setAbsolutePosition( x, y ); Annotation anno = new Annotation( 0f, 0f, 0f, 0f, url ); img.setAnnotation( anno ); doc.add( img ); } /** * Draws the pie chart. * @param directcontent a canvas to which the pie chart has to be drawn. * @throws IOException */ public static void addPieChart(PdfContentByte directcontent) throws DocumentException { /** TODO: Automate and improve pie chart creation. * 1. Add support for adding pie pieces dynamically * from an Array or ArrayList. * 2. Calculate pie chart location based on single set * of coordinates. * 3. Assign each pie piece a random color. */ directcontent.setLineWidth(3.2f); directcontent.setRGBColorStroke(255, 255, 255); directcontent.setRGBColorFill(16, 205, 55); // llx, lly, urx, ury, begin, extent directcontent.arc(200, 100, 400, 300, 0, 120); directcontent.lineTo(300,200); directcontent.closePathFillStroke(); directcontent.setRGBColorFill(254, 205, 16); directcontent.arc(200, 100, 400, 300, 120, 120); directcontent.lineTo(300,200); directcontent.closePathFillStroke(); directcontent.setRGBColorFill(155, 25, 16); directcontent.arc(200, 100, 400, 300, 240, 120); directcontent.lineTo(300,200); directcontent.closePathFillStroke(); } /** * Adds text at an absolute position. * @param text a string of text to be added. * @param cb a canvas to which the text will be added. * @param x a position of the text along x axis. * @param y a position of the text along y axis. */ public static void addTextAtXY( String text, PdfContentByte cb, float x, float y ) throws IOException, DocumentException { BaseFont labelFont = BaseFont.createFont( BaseFont.TIMES_ROMAN, "Cp1252", true ); cb.beginText(); cb.setColorFill( TITLE_COLOR ); cb.setFontAndSize( labelFont, 10 ); cb.setTextMatrix( x, y ); cb.showText( text ); cb.endText(); } /** * Adds empty line to a paragraph. * @param par a paragraph object to which line will be added. * @param howMany a number of empty lines to be added. */ public static void addEmptyLine( Paragraph par, int howMany ) throws DocumentException { for( int i=0; i < howMany; i++ ) par.add( new Paragraph(" ") ); } public static void main(String...args) throws IOException, DocumentException { new iTextIntroduction().createPdf( OUTPUT ); } }