Generate PDF with Flying Saucer and iText by Adding Font Files

In this post, I would like to show how to load font files and format specific sections of the document at run time, when generating PDF document using Flying Saucer and iText libraries.

I will create a String that has a structure of valid XHTML file. The content of String is what going to be generated as a PDF document. Flying Saucer knows how to render XHTML. Before generating the PDF, I will load a font file for future formatting. Once the font file is loaded, I will retrieve the font family and will apply it as a formatting style to the selected paragraph of my future PDF document.

[java]
import java.io.*;
import com.lowagie.text.pdf.*;
import org.xhtmlrenderer.pdf.*;

public class TestFont {

public static void main(String[] args) {
try {
ITextRenderer renderer = new ITextRenderer();
File fontDir = new File(SOME_ABSOLUTE_PATH_TO_YOUR_FONT_DIR);

//Build valid XHTML source for parsing
StringBuffer buf = new StringBuffer();
buf.append("<html>");
buf.append("<head>");
buf.append("</head>");
buf.append("<body>");

String body = "This is formatted paragraph";

//Gets TTF or OTF font file from
//the font directory
if (fontDir.isDirectory()) {

//Only add fonts with specific extensions
File[] files = fontDir.listFiles( new FilenameFilter() {
public boolean accept(File dir, String name) {
String lower = name.toLowerCase();
//Load TTF or OTF files
return lower.endsWith(".otf") || lower.endsWith(".ttf");
}
});

if (files.length > 0) {
String fontFamilyName = "";
//You should always embed TrueType fonts.
renderer.getFontResolver().addFont(files[0].getAbsolutePath(),
BaseFont.IDENTITY_H, BaseFont.EMBEDDED);

//Get font family name from the BaseFont object.
//All this work just to get font family name
BaseFont font = BaseFont.createFont(files[0].getAbsolutePath(),
BaseFont.IDENTITY_H , BaseFont.NOT_EMBEDDED);
fontFamilyName = TrueTypeUtil.
getFamilyName(font);

if (!fontFamilyName.equals("")) {
//Wrap DIV with font family name around the content
body = "<div style="font-family: " + fontFamilyName + ";">" + body + "</div>";
}
}
}

buf.append("<p>This paragraph is unformatted</p>");
buf.append("<p>" + body + "</p>");
buf.append("</body>");
buf.append("</html>");

byte[] bytes = buf.toString().getBytes("UTF-8");

ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
InputSource is = new InputSource(bais);
Document doc = builder.parse(is);

renderer.setDocument(doc, null);
renderer.layout();

String filename = "document.pdf";
BufferedOutputStream bufferedOutput = new BufferedOutputStream(new
FileOutputStream(filename));

renderer.createPDF(bufferedOutput);
bufferedOutput.flush();
bufferedOutput.close();
}
catch (Exception e)
{
System.out.println(e.getMessage());
}
}
}
[/java]

I hope by looking at the source code, the concept of how to add fonts and retrieve font family was clear.

Regards,
Alex

Export to PDF using iText and Flying Saucer

In my previous post I attempted to generate PDF on the fly using iText library. My goal was to parse HTML snippet into PDF. Unfortunately, as I discovered iText alone is not powerful enough as HTML parser. iText is not flexible enough to manipulate the CSS. Its understandable, since iText‘s main functionality is PDF generation and not HTML parsing.

While trying to find workaround iText limitations, I came across Flying Saucer Java library. Flying Saucer is XML/XHTML/CSS 2.1 renderer, that uses iText and allows to render CSS stylesheets and XHTML, either static or generated, directly to PDFs.

I want to say that Flying Saucer does a beautiful job. You can check this out by trying to export current post to PDF :)

Joshua Marinacci, the Flying Saucer project lead wrote a nice tutorial that explains how to generate PDF using Flying Saucer.