Create BitmapsFonts on the fly with gdx-freetype

Hiero or BMFont are nice tools when it comes to generating bitmap fonts offline, adding fancy effects like dropshadows and similar things. However, this also means that you have to generate various versions of your fonts, for different screen sizes and resolutions, a tedious process, that is not exact.

For the Reddit app i’m working on i needed something more flexibel. Thus i wrapped FreeType, the goto FOSS solution when it comes to font rendering. The code can be found in the gdx-freetype project in SVN. It allows you to generate BitmapFontData and BitmapFont instances on the fly from TrueType font files. Here’s how you use it:

FreeTypeFontGenerator generator = new FreeTypeFontGenerator(fontFile);
BitmapFont font15 = generator.generateFont(15);
BitmapFont font22 = generator.generateFont(22);
generator.dispose();

Remember to dispose the generator once you are done generating fonts for a specific TrueType file. The generateData method has overloads that allow you to specify more things, such as the characters you want the BitmapFont to contain and so on.

To use gdx-freetype, grab the latest nightlies, link gdx-freetype.jar and gdx-freetype-natives.jar to your desktop project, link gdx-freetype.jar to your Android project, and copy the armeabi/libgdx-freetype.so and armeabi-v7a/libgdx-freetype.so files to your Android project’s libs/ folder, just like with the libgdx.so files.

Caveats:

  • If you use to big of a size, things might explode. BitmapFonts still only support a single atlas page at the moment, something i’ll try to fix in the next couple of weeks.
  • Asian scripts “might” work, see caveat above though. They contain just to many glyphs. I’m thinking about ways to fix this.
  • Right-to-left scripts like arabic are a no-go. The layouting “algorithms” in BitmapFont and BitmapFontCache have no idea how to handle that.
  • Throwing just any font at FreeType is not a super awesome idea. Some fonts in the wild are just terrible, with bad or no hinting information and will look like poopoo.

That being said, i’ll try to improve support of more complex scripts, arabic would be nice :) But i guess there’s a reason for this bug on the Android tracker.

  • biobob

    This is great extension of the libgdx. I’m sure that it will be included in majority of future projects.

    I hope you didn’t summon demon of bug tracker spamming by mentioning arabic support. 7000+ comments to one issue just scares the shit out of me :D.

  • adeluiz

    Great, but I’ve had some problems. If I use it on my project, I get an error when running on the android device:

    03-06 22:59:03.617: E/AndroidRuntime(4324): java.lang.RuntimeException: Key with name ‘�’ is already in map

    Maybe, you see another thing on your system, but inside “name ‘�’” my system sees a diamond with a question mark inside. And that is because of that line:

    public static final java.lang.String DEFAULT_CHARS = “ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890″!`?’.,;:()[]{}|/@\^$-%+=#_&~*����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������”;

    After the * (asterisk) I only see lots of diamonds with question marks inside (unknown characters, I guess). This could be because I’m using a Mac or because I’m using a spanish computer (or both).

    I’ve used a special string without those characters and all works great. Thanks again for your framework.

  • http://badlogicgames.com Mario

    Make sure you set the Character encoding of your Eclipse workspace to UTF-8, that will fix the issue. I have no clue why Eclipse does not default to that on all operating systems.

  • Andrew

    I’m getting this error only on my galaxy nexus:

    E/AndroidRuntime(11874): com.badlogic.gdx.utils.GdxRuntimeException: No x-height character found in font

    Works on PC, Desire HD, and Evo 3D. Any ideas?

    Thanks.

  • http://badlogicgames.com Mario

    What font file are you using? Can you provide that? What characters are you creating glyphs for?

  • Andrew

    Font file: http://dl.dropbox.com/u/17175030/consolab.ttf

    Characters:

    “abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789][_!$%#@|\\/?-+=()*&.;,{}\”´`’”

    Thanks

  • http://badlogicgames.com Mario

    Andrew, i can kinda reproduce your issue. Investigating it.

  • http://2dmx.com Andrew

    Thanks a lot.

  • http://badlogicgames.com Mario

    fixed, fetch latest nightlies.

  • Andrew

    Works great. Thanks a lot.

  • biobob

    If DEFAULT_CHARS value is only one class in LibGDX using UTF-8 characters directly in sources, I would suggest to use Unicode escape sequences instead.

  • Chen

    Chinese Characters unavailable:(
    expecting an easy way to use ttf. stb not good enough

  • Aare

    There is a problem on android backend, log details in this post: http://www.badlogicgames.com/forum/viewtopic.php?f=11&t=3633

  • http://blog.csdn.net/achellies achellies

    Chinese Characters now available….
    just use the freetype and the Chinese font file

  • Cypher

    im getting this error on desktop windows x86

    #
    # A fatal error has been detected by the Java Runtime Environment:
    #
    # EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x0000000c, pid=148, tid=2404
    #
    # JRE version: 7.0-b147
    # Java VM: Java HotSpot(TM) Client VM (21.0-b17 mixed mode, sharing windows-x86 )
    # Problematic frame:
    # C 0x0000000c
    #
    # Failed to write core dump. Minidumps are not enabled by default on client versions of Windows
    #
    # An error report file with more information is saved as:
    # E:\Android SDK\Android SDK\Workspace\gdx-helloworld\hs_err_pid148.log
    #
    # If you would like to submit a bug report, please visit:
    # http://bugreport.sun.com/bugreport/crash.jsp
    # The crash happened outside the Java Virtual Machine in native code.
    # See problematic frame for where to report the bug.
    #
    AL lib: ReleaseALC: 1 device not closed

  • Owen

    Cypher – a number of people, myself included, seem to still be getting that EXCEPTION_ACCESS_VIOLATION error when running on Windows desktop. There was an error report, 768 (http://is.gd/enCrPk), dealing with it, but that has been prematurely marked as fixed, and the issue has been closed.

  • passover

    @Owen I have the same problem on Windows desktop, and I still wait for the solution of this issue.

  • M_M

    Is there an update which fix that problem?

  • M_M

    Is there an update which fixes this bug?

  • Oakshiro

    I am getting a UnsatisfiedLinkError when trying to create the generator

    FileHandle font = Gdx.files.internal(“myfont.ttf”);
    FreeTypeFontGenerator generator = new FreeTypeFontGenerator(font); //boom!
    enumeradosFont = generator.generateFont(12);
    generator.dispose();

    I placed the jar and the two .so in the android project, the two jars in the desktop project and added the libraries in the build path for both projects. When I try to launch the desktop project that exception occurs… any clue?

  • Sridhar

    Mario,
    thanks for building a great platform.

    I did not know where or whom to ask, hence posting this comment here.
    For Indic languages, I needed complex script layout.
    I have integrated harfbuzz-ng, freetype using Android NDP into libgdx.
    This code can be generalized and made a part of libgdx if it is useful to others.

  • http://badlogicgames.com Mario

    Very cool! Drop me a mail at contact@badlogicgames.com!

  • http://www.peter.poliwoda.info KMT

    Hey guys,
    First of all thanks for making this happen. I’m using your engine to build a Final Year Project in college – details on the provided website :).
    Now, while this just helped enormously with my fonts, here’s a couple of questions:
    Can this be referenced by the skin JSon file so that I would use an auto-generated font in the skins?
    Is there a chance to put some kind of an outline stroke on the font?

    Thanks a trillion,
    Peter

  • http://badlogicgames.com Mario

    At the moment you have to programmatically add a freetype bitmap font to a skin. outlines are currentl not planned i’m afraid.

  • Nick Stirushnik

    1. Which class do I place the code into? Do I run it in the terminal?
    2. When I placed it in any one of my classes after copying/linking the necessary Jars to the correct locations, it says FreeTypeFontGenerator(String) is undefined in the console. How do I import the Required things to make it recognize FreeTypeFontGenerator?
    I’m a newbie at programming and I seriously can’t find any better BitmapFont Generating Program because I’m on a Mac and I have no money.

  • Edd

    Russian strings are not displayed. Also if you specify characters the font should contain in generateFont (For example “абвгд” <- abvgd in russian) you will get "Exception in thread "LWJGL Application" java.lang.RuntimeException: Key with name 'а' is already in map". Tested with:

    DroidSerif-Regular.ttf and impact.ttf fonts.

  • Edd

    Sorry, false alarm. All mentioned above works ^^

  • Marek Halmo

    Hi.. any possibility to save the generated font to a file?

    It would help to generate the font just on the first start (having the proper resolution e.t.c) and save it to local storage (to save aprox 1.5sec’s of loading time)

    I was tryiing to use:

    font.getData().getFontFile()

    but it is null.

    Also i’m not shure how to save the TextureAtlas.

    Has anybody tried this?

  • Ashraf Sayied-Ahmad

    So when can see a support in Arabic fonts?
    If you need help in the implementation please leave a hint from where to start?

  • Richard

    I would strongly recommend, to anyone that is looking for a way to SPEED UP this process (takes me about 500ms per font at run time to generate) that you just use this in development, and before you go live, you actually generate out the fonts using the Hiero program here: http://www.badlogicgames.com/wordpress/?p=1247

    Those files can then be loaded using

    font = new BitmapFont(Gdx.files.internal(“data/myfont.fnt”),Gdx.files.internal(“data/myfont.png”),false);

    It’s WAYYY faster than generating it on the fly.

    Richard

  • Marius Duna

    Hiero issue:

    This application will be blocked in a future Java security update because
    the JAR file manifest does not contain the Permissions attribute. Please
    contact the Publisher for more information.

  • Hejaaa

    Chars like “ÁČĎÉĚÍŇÓŘŠŤÚŮÝŽáčďéěíňóřšťúůýž” not work with FreeTypeFontGenerator :( Please can you help me?

    http://www.badlogicgames.com/forum/viewtopic.php?f=11&t=14167

  • Hejaaa

    Unicode escape sequences not working