Thursday, August 16, 2012

Embedding Fonts In Java PDF-Creating Agents | Blog

Embedding Fonts In Java PDF-Creating Agents | Blog:
Yesterday I talked about using Web Fonts to overcome the limitations of being restricted to the limited set of fonts available to web developers. Today I'll talk about over-coming the even more limited set of fonts available when creating PDF documents.
When you create a PDF with the likes of iText you're normally limited to the choice of Courier, Helvetica and Times New Roman. Helvetica is probably the default choice, but it's borrrrrring.
Let's use Source Sans Pro instead! Here's an example of a PDF using Source Sans Pro.
image
So, so, so much nicer than Helvetica.
If you want to try it out, you can create a Domino-driven PDF with the above font embedded in it by using this demo form.


How To Embed Fonts


How do you go about embedded the font for use with a Domino Java agent? Well, first thing you do is download the font. It doesn't have to be Source Sans Pro, but assuming you want it then download the "fonts only" ZIP from Sourceforge and extract to your PC.
Now, open the Java Agent you use for creating PDFs and click the Import dropdown button and choose to import a Resource. Browse to the folder of fonts and select the ones you want to use in your PDF.
image
When you're done the Agent will list the font files in the "Res" section, as below:
image
With the font files stored in the Agent you can load them at runtime and create a BaseFont based on them.
Here's the code that load the fonts as two BaseFonts (one for regular fonts and one for bold). The code then uses the BaseFonts to create some useable Fonts.
//Regular base font
BaseFont bf = BaseFont.createFont("SourceSansPro-Regular.otf",
BaseFont.WINANSI,
BaseFont.EMBEDDED,
false,
getResourceAsByteArray("SourceSansPro-Regular.otf"),
null);

//Bold base font
BaseFont bfb = BaseFont.createFont("SourceSansPro-Bold.otf",
BaseFont.WINANSI,
BaseFont.EMBEDDED,
false,
getResourceAsByteArray("SourceSansPro-Semibold.otf"),
null);

//A collection of fonts (based upon our base fonts) for re-use throughout the code!
Font defaultFont = new Font(bf, 12);
Font headerFont = new Font(bfb, 18);
Font tinyFont = new Font(bf, 9);
Font tinyFontBoldAndWhite = new Font(bfb, 9, Font.NORMAL, Color.WHITE);

It's those last four Font objects that we'll use in our code to specify the font for any PDF objects we add to our iText PDF Document.


Loading Resources


Notice in the above code that there was a call to a method call getResourceAsByteArray(). This simply gets a stream on the font file we stored in the Agent and converts it to a byte[] array that the BaseFont class can use.
Here's what that method looks like.
public static byte[] getResourceAsByteArray(String resourceName) throws Exception{
InputStream is = this.getClass().getResourceAsStream("/" + resourceName);
ByteArrayOutputStream buffer = new ByteArrayOutputStream();

int nRead;
byte[] data = new byte[16384];

while ((nRead = is.read(data, 0, data.length)) != -1) {
buffer.write(data, 0, nRead);
}
buffer.flush();

return buffer.toByteArray();
}

The key to the above code is the getClass().getResourceAsStream() call which is what actually loads the file from the Resources section of the Agent.


Using The Fonts


Now that we've defined our Font objects we can use them in the code when added iText objects such as Paragraph to the document.



Paragraph myParagraph = new Paragraph( doc.getItemValueString("Title") , headerFont);
myParagraph.setAlignment(Element.ALIGN_CENTER);
document.add( myParagraph );

Anchor anchor = new Anchor(
new Chunk( "This is a link back to the document which created this PDF!",
new Font(bf, 10, Font.UNDERLINE, new Color(0, 0, 255) )
)
);

It's as simple as that. And the results are worth it.


Trade-Off


As with using Web Fonts there's a file size trade-off to consider. Embedding fonts in a PDF can easily add 50KB to its size. And that's per font-style. So, if you want Regular, Bold and Italic, it's three times that size.
You could of course just embed the Regular font and force it to act like bold or italic, but, as with the web, you don't get the same results.
Click here to post a response

DIGITAL JUICE

No comments:

Post a Comment

Thank's!