A while back I did a write-up on my FontBuilder project, which made mention of a tool I created for extracting font kerning data from font files. Although I’ve since moved from XNA to Unity, and this tool is no longer required, I still wanted to record all of my notes, and document what I’ve created, just in case it ever has some use in the future.
In addition, I wanted to note that if you’re ever wanting to do something fancy with fonts in a game, I recommend using a tool like Freetype. Freetype is an open source software font engine for producing glyph images. In other words, it does roughly what I was trying to accomplish with my FontBuilder project in the first place, and automatically takes care of things like kerning. There are several reasons why I didn’t use it in the first place, although I wish I would have:
- Documentation on using it within xna was very poor. I could barely find any information, and being a game development noob, I tried to follow the better documented solutions.
- As stated on their webpage, “FreeType is a font service and doesn’t provide APIs to perform higher-level features like text layout or graphics processing (e.g., colored text rendering, ‘hollowing’, etc.)”. My font builder already allowed me to do this, so I wanted to stick with that tool, rather than dumping it and starting over.
- I didn’t need any complicated font data. Just horizontal kerning info. I thought it would be much simpler than it was to extract this data.
As mentioned above, the basic goal of my font kerning project, aptly named the “FontKernalizer”, was to extract horizontal kerning data from font files of various formats, and save it in an organized, easily usable format. Basically, I wanted to be able to do this:
- float horizontalOffset = GetKerningPair(char firstChar, char secondChar).xadvance;
As I quickly discovered, fonts are complex. Really complex. Before we really get into my FontKernalizer and how it works, I should give you a brief overview of the various font formats, and how they work (or don’t work) in XNA.
TrueType vs PostScript Type 1 vs OpenType
- PostScript Type 1 came first in the late 1980’s or early 1990’s. It was created by Adobe, and is an open standard for font creation and how to render fonts.
- TrueType was created by Apple when they saw how important font information was, and realized that it needed to be information built in to operating systems. It was later traded/shared with Microsoft. It uses a .tt file extension.
- The main difference between Postscript and TrueType was the outline data, or the mathematical method behind how the curves and borders of fonts are handled.
- OpenType came much later, and is an amalgamation of the two. Adobe and Microsoft both worked together to make this happen. OpenType format supports both Postscript and TrueType outlines in .otf files.
.AFM and .INF Files
- AFM files (Adobe Font Metrics) and INF files were used by adobe back in the day of Postscript Type 1. They are files that describe the font, but don’t actually store any glyphs. The .afm file holds all kerning information for the font.
- Because there are various types of font files (.tt, .otf, etc), data is stored differently in each font file. Kerning information is retrieved differently from a .tt file than it is from a .otf file.
- Sometimes, the font file is associated with an additional file that contains various glyph metrics, including kerning, but no glyph images. A good example is the Type 1 format where glyph images are stored in a file with extension .pfa or .pfb, and where kerning metrics can be found in a file with extension .afm or.pfm.
Conversion between .AFM, .TT, .OTF, etc
- Various online website tools, downloadable font creators, and graphical libraries can convert files between the various different formats.
- These various tools, especially the cheap or free ones do a poor job of it however. Many tools are confused about how to find more complex data, like kerning information. Some tools are built to specifically work with TrueType files, and won’t pick up kerning data for .OTF files. Some tools understand .AFM files, and some don’t.
- Even if the tool used is of good quality, you’ll still lose some image quality translating between various font types. For example, translating a .OTF file with postscript outlines to a TrueType file is lossy. The quality of the font drops significantly and it looks terrible.
- By far the best tool I found for manipulating fonts and retrieving font data is Font Lab Studio 5. It’s free version allows you to export metrics information (kerning, etc) as an easily readable .AFM file. Font Lab Studio is also regarded as the king of font creation tools.
Fonts in XNA
- Sadly, XNA only supports TrueTypeFonts. You can load a .OTF font, but the font has to have been created with TrueTypeOutlines (remember .OTF files can store TrueType or PostScript Type1 fonts).
- Lithos Pro, for example, is an OpenType font, but was created using Postscript. Thus, the font is not usable in XNA.
- A way around this is to manually create a font bitmap. Basically, you create a bitmap file that has a separate glyph for each image. The images must appear left to right, and must be positioned in standard unicode order.
- I’ve created a C# program which executes a photoshop script to create these bitmaps, with proper vertical positioning. However, horizontal positioning does not take kerning into account. My photoshop script also allows bitmaps to be created with layer styles, colors, drop shadows, etc.
- Kerning in XNA isn’t real kerning. It’s more like pseudo-kerning. Read more about how kerning “sort of” works in xna.
- As of 1-17-2012, kerning in xna can only really be handled by reading in kerning data somehow, and drawing strings one letter at a time. If you know the kerning information for the font you’re using, you can slightly bump the characters as you draw them.
- Kerning information cannot easily be retrieved from within C#. I’ve seen a few things that come close (System.Windows.Media.GlyphTypeface, PInvoke GetKerningPairs), but it seems the only way to reliably do it for all font formats is to pass in the kerning data myself.
Whew, that’s a lot of information. In part 2, I show you my actual solution, and show you the tools I used to get the job done.
Part 1 | Part 2