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 Pebble Blog Entry to PDF Plugin

In one of my previous posts, I described how I implemented a plug in for Pebble blogging software that allows export of blog entries to PDF.

Today, I have made modifications to enable plug in to load font files at run time during PDF generation to provide support for additional non-Latin languages. So now, it is possible to export non-Lain characters from blog entries to PDF.

Below, I’ve added some content using different languages. To allow support for non-Latin languages, I am using font file cyberbit.ttf by Bitstream. You can test the plugin’s multilingual support by generating PDF from the current post.

I think its comes out quite nicely. The only hitch at this moment is that Flying Saucer does not have support for right-to-left text in PDF yet.

Japanese Kanji:
五輪代表

Japanese Hiragana
こんにちは、これは真実を決定するためにはテストテキストです。

Japanese Katakana
ラドクリフ、マラソン

Japanese Kokuji
和製漢字

Chinese Simplified:
您好,这是一个测试文本,以确定事实真相

Chinese Traditional:
您好,這是一個測試文本,以確定事實真相

Korean:
안녕하세요,이 사실을 확인하는 테스트 텍스트입니다

Arabic:
مرحبا ، هذا هو اختبار لتحديد نص الحقيقة

Hebrew:
שלום, זוהי בדיקה טקסט כדי לקבוע את האמת

Russian:
Привет, это тест текста, чтобы определить истину

Greek:
Γεια σας, αυτό το κείμενο είναι μια δοκιμασία για τον προσδιορισμό της αλήθειας

Thai:
สวัสดีนี่คือการทดสอบข้อความเพื่อตรวจสอบความจริง

Vietnamese:
Xin chào, đây là một bài kiểm tra văn bản để xác định sự thật

Turkish:
Merhaba, bu gerçeği belirlemek için bir test metin