Replacing a Font using iText

This article is based on iText in Action, Second Edition, published on October, 2010. It is being reproduced here by permission from Manning Publications. Manning publishes MEAP (Manning Early Access Program,) eBooks and pBooks. MEAPs are sold exclusively through Manning.com. All pBook purchases include free PDF, mobi and epub. When mobile formats become available all customers will be contacted and upgraded. Visit Manning.com for more information. [ Use promotional code 'java40beat' and get 40% discount on eBooks and pBooks ]

also read:

Replacing a Font

Introduction

Figure 1 shows two PDF files that were created in exactly the same way, except for one difference: in the top PDF, the font (Walt Disney Script v4.1) wasn’t embedded. It’s a font I’ve downloaded from a site with plenty of free fonts. The font isn’t installed on my operating system. As a result, Adobe Reader doesn’t find it, and the words “iText in Action” are shown in Adobe Sans MM, which is quite different from the font shown in the PDF that has the font embedded.

If we had the top PDF as well as the font file for the Walt Disney Script font, we could use listing 1 to embed that font after the fact.

Listing 1 EmbedFontPostFacto.java

RandomAccessFile raf = new RandomAccessFile(FONT, "r"); 		A
	byte fontfile[] = new byte[(int)raf.length()]; 		A
	raf.readFully(fontfile); 		A
	raf.close(); A
	PdfStream stream = new PdfStream(fontfile); B
	stream.flateCompress(); B
	stream.put(PdfName.LENGTH1, new PdfNumber(fontfile.length)); B
	PdfReader reader = new PdfReader(RESULT1);
	int n = reader.getXrefSize();
	PdfObject object;
	PdfDictionary font;
	PdfStamper stamper
		= new PdfStamper(reader, new FileOutputStream(RESULT2));
	PdfName fontname = new PdfName(FONTNAME);
	for (int i = 0; i < n; i++) { C
		object = reader.getPdfObject(i); C
		if (object == null || !object.isDictionary()) C
		continue; C
		font = (PdfDictionary)object; C
		if (PdfName.FONTDESCRIPTOR.equals(font.get(PdfName.TYPE)) C
			&& fontname.equals(font.get(PdfName.FONTNAME))) { C
			PdfIndirectObject objref = stamper.getWriter().addToBody(stream); D
			font.put(PdfName.FONTFILE2, objref.getIndirectReference()); E
		}
	}
	stamper.close();

	A Reads the font file into a byte array
	B Creates a PDF stream
	C Finds the unembedded font
	D Adds the stream to the writer
	E Adds the reference to the stream

Note that we’re adding the complete font file in this example. We add the reference to the stream using the key FONTFILE2 because we know in advance that the font has True Type outlines. That’s not the only assumption we make. We also assume that the metrics of the font that is used in the PDF correspond with the metrics of the new font we’re embedding.

As for parsing PDF, we could only do a fair attempt, but the functionality could fail for PDFs using exotic encodings. In real world examples, replacing one font with another can be very difficult.

Summary

In this article, I showed you how to replace a font in a PDF document using the embed feature in iText.

Comments

comments

About Krishna Srinivasan

He is Founder and Chief Editor of JavaBeat. He has more than 8+ years of experience on developing Web applications. He writes about Spring, DOJO, JSF, Hibernate and many other emerging technologies in this blog.

Speak Your Mind

*