Creating an iText pdf with embedded JFreeChart

Charts are simple to make with JFreeChart and there are tons of examples on the web about how to generate them and save them as .jpg or .gif files. I ran into an issue however, where I needed to embed a chart into a pdf file. My first thoughts were to generate the charts as a .jpg file and embed them, but the pdfs looked a little choppy and didn’t print well.

To solve the problem you need to have the chart rendered as vector graphics and inserted into the pdf. The code required to do this ended up being simple, but I wasn’t able to find any good complete examples on the web. This is a simple working example I made for anyone else who finds themselves in this position.

Downloads:

To do an ant build, all you need to do is set j2ee.lib.dir in the build.properties file to a directory that contains the j2ee.jar (in your jdk or app server) and you are good to go. The war file should easily deploy on any app server.

Here is the meat of the code required:

docWriter = PdfWriter.getInstance(doc, baosPDF);
 
doc.addProducer();
doc.addCreator(this.getClass().getName());
doc.addTitle("jfreechart pdf");
doc.setPageSize(PageSize.LETTER);
 
doc.open();
 
// add some text to the document
doc.add(new Phrase("Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."));
 
// build up the dataset for the char
XYSeriesCollection dataset = new XYSeriesCollection();
 
XYSeries series = new XYSeries("XYGraph");
series.add(1, 1);
series.add(2, 3);
series.add(3, 9);
series.add(4, 11);
 
dataset.addSeries(series);
 
// set up the chart
JFreeChart chart = ChartFactory.createXYLineChart("XY Chart Sample, non default font", // chart title
        "x-axis",   // domain axis label
        "y-axis",   // range axis label
        dataset,    // data
        PlotOrientation.VERTICAL,   // orientation
        true,   // include legend
        true,   // tooltips
        false   // urls
    );
 
// trick to change the default font of the chart
chart.setTitle(new TextTitle("XY Chart Sample, non default font", new java.awt.Font("Serif", Font.BOLD, 12)));
chart.setBackgroundPaint(Color.white);
chart.setBorderPaint(Color.black);
chart.setBorderStroke(new BasicStroke(1));
chart.setBorderVisible(true);
 
int width = 260;
int height = 250;
 
// get the direct pdf content
PdfContentByte dc = docWriter.getDirectContent();
 
// get a pdf template from the direct content
PdfTemplate tp = dc.createTemplate(width, height);
 
// create an AWT renderer from the pdf template
Graphics2D g2 = tp.createGraphics(width, height, new DefaultFontMapper() );
Rectangle2D r2D = new Rectangle2D.Double(0,0, width,height);
chart.draw(g2,r2D,null);
g2.dispose();
 
// add the rendered pdf template to the direct content
// you will have to play around with this because the chart is absolutely positioned.
// 38 is just a typical left margin
// docWriter.getVerticalPosition(true) will approximate the position that the content above the chart ended
dc.addTemplate(tp, 38, docWriter.getVerticalPosition(true)-height);

  • Eduard

    nice article!!!
    it just saved my day!
    thanks :D

  • Mak

    Thanks …It saved my day…ta

  • jack

    thank you very much .

  • Kev

    Hey, still helped a lot, even over 5 years later ;)
    But i still got one question: the legend on my pieChart is to big in the PDF, so that the names of the pie parts are above each other and dont scale down, although this doesnt happen when i paint them with jPanel. Maybe you got a tip?
    **Excuse my english ;)