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.

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());
		}
	}
}

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

Regards,
Alex