libgdx Fonts

One of the first things I did when I joined the libgdx project was add the BitmapFont class. (Hey, look at that, we now have javadocs we can link to! Source is here.) This class is based on the BitmapFont class from Matthias Mann‘s Themeable Widget Library. You can tell this because we haven’t removed his @author tag or BSD license header.  TWL’s class was used as a base because Matthias’ code is solid and this made it easier to support TWL in libgdx, which has specific requirements for the font implementation to support things like text wrapping. libgdx has a full TWL renderer, which allows for very rich OpenGL GUIs, but more on that in a later blog post.

A bitmap font consists of an image that contains all the glyphs, and a descriptor file that defines the bounds for each glyph. When you draw text in your game, the BitmapFont class plucks out the glyphs, arranges them for the string you requested, and hands the geometry off to SpriteBatch to be drawn. If you are going to be drawing the same text repeatedly, and you almost always are since you’ll need to give readers a chance to read it, you can use BitmapFontCache. This class stores all the geometry for a string, so when it is drawn it can just hand off the geometry to SpriteBatch and there is no need to compute glyph locations every frame.

This is all great, but creating the image that contains all the glyphs is very time consuming using Paintbrush, not to mention carefully noting their pixel bounds in the descriptor file. This is where our awesome tools come in! The tool is named Hiero v3. The first version of Hiero was written by Kevin Glass for his Slick library. Later on, I rewrote it so it could support Unicode fonts. I have since ported it to libgdx under the extensions directory. Kev has graciously allowed us to keep the Hiero name. Just tonight I set up a Java WebStart made a jar, you can find it on Google code or by clicking this image:

Hiero


First, choose a font on the top left. Note with Java 1.5 that you don’t get kerning unless you choose a font file and NOT a system font, due to an AWT limitation. Next choose your effects on the right. If you remove all effects, nothing is drawn, so you probably want at least the “color” or “gradient” effect. Remove and re-add an effect to change the order they are drawn.

Clicking the “Glyph cache” radio button will show you the backing texture that will be exported when you save the font. The glyphs that will be on the backing texture come from the sample text box. If you change the sample text, you probably want to press “Reset Cache” to regenerate the backing texture. This is because Hiero will do better packing of the glyphs on the backing texture when it knows all the glyphs up front.

Note that Hiero supports multiple pages of glyphs, however the libgdx BitmapFont class currently does not. So make sure all your glyphs fit on one image. You can change the image size, up to 1024×1024.

When you are satisfied with your backing texture, click File -> Save BMFont File to save the image and descriptor file. The BMFont format comes from AngelCode. You may also want to save the Hiero file, which will allow you to reload all your effects and other settings in case you need to make changes later and regenerate your BMFont files.

Instead of loading the backing image from a file, you can use the alternate BitmapFont constructor that takes a Sprite. This allows you to pack multiple font backing images into the same larger image, and draw text in different fonts with only a single texture bind. The packing is easy with SpriteSheetPacker.

TWL has a sophisticated theme editor that can also create BMFont text files that are usable by libgdx. In the theme editor, click Tools -> Create Font. This tool has the advantage over Hiero in that it can draw fonts using FreeType, which may produce cleaner font renderings than the AWT, vector based Java rendering or the simplistic native rendering that Hiero provides. I may add this to Hiero eventually. You might also notice that the entire theme editor is built using TWL. It serves as a great example of a very complex GUI, rendered completely in OpenGL. If you are bored, you can read my theme editor tutorial about how to make a new theme from scratch.

Another approach to rendering fonts is to draw glyphs at runtime to a backing texture. This is somewhat complex, adds to the loading time, and doesn’t (easily) allow for fancy effects like outlines and drop shadows. The upside to rendering glyphs at runtime is that you can support users typing in nearly any glyph, which can be useful for CJKV and other languages that have tons of glyphs. However, there are many complexities involved in doing this, and the Android font APIs really don’t provide everything necessary to do this well. The desktop’s AWT API does, and in fact the Hiero tool is based on a class I originally wrote for Slick called UnicodeFont, which generates glyphs at runtime and supports any left-to-right Unicode font. Unicode characters can still be used with a bitmap font, just don’t go crazy and try to add 40,000 glyphs, unless your font size is very, very small. Anyway, bitmap fonts are easy, fast, have nice looking effects, and are perfectly sufficient for most games.

-Nate

small edit by me, Mario we had a Font class before the BitmapFont class by Nate (Matthias) that did the glyph compositing on the fly. We’ll eventually add that back in once we figured out a clean way to make them co-exist with BitmapFont.

15 thoughts on “libgdx Fonts

  1. @aaa, file an issue detailing the problem. I use fonts from TWL just fine. Trying running Hiero from source.

  2. Hii,
    I am using libgdx for past 2 project.It was awesome.Now After changing the font tool to Jar.I can’t do font for my new Projects.Please Help me.I am stuck at font now.All Game Logic is done..:(

  3. Hiero v3.0 needs to be run with 32-bit java otherwise you will get a “Could not find the main class error”. Hiero v2.0 does not work for libgdx as the png files it generates are not consistent with the orientation that BitmapFont’s constructor expects.

  4. How can I run Heiro v3.0 under 64bit? (Mac OS Mountain Lion). It doesn’t work under 64 :(

    $ java -jar hiero2.jar
    Exception in thread “AWT-EventQueue-0″ java.lang.UnsatisfiedLinkError: Can’t load library: /var/folders/pc/bl49f45d1bz3c7048qk_8wj40000gn/T/libgdx/3892129738/liblwjgl.dylib
    at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1828)
    at java.lang.Runtime.load0(Runtime.java:792)
    at java.lang.System.load(System.java:1059)
    at org.lwjgl.Sys$1.run(Sys.java:70)
    at java.security.AccessController.doPrivileged(Native Method)
    at org.lwjgl.Sys.doLoadLibrary(Sys.java:66)
    at org.lwjgl.Sys.loadLibrary(Sys.java:95)
    at org.lwjgl.Sys.(Sys.java:112)
    at org.lwjgl.openal.AL.(AL.java:59)
    at com.badlogic.gdx.backends.openal.OpenALAudio.(OpenALAudio.java:80)
    at com.badlogic.gdx.backends.openal.OpenALAudio.(OpenALAudio.java:68)
    at com.badlogic.gdx.backends.lwjgl.LwjglCanvas.(LwjglCanvas.java:101)
    at com.badlogic.gdx.tools.hiero.Hiero.(Hiero.java:170)
    at com.badlogic.gdx.tools.hiero.Hiero$19.run(Hiero.java:1271)
    at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:251)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:705)
    at java.awt.EventQueue.access$000(EventQueue.java:101)
    at java.awt.EventQueue$3.run(EventQueue.java:666)
    at java.awt.EventQueue$3.run(EventQueue.java:664)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:675)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:240)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:157)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:146)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:142)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:134)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:91)

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>