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.

39 thoughts on “Create BitmapsFonts on the fly with gdx-freetype

  1. 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.

  2. 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.

  3. 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.

  4. 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.

  5. 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.

  6. 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

  7. 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.

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

  9. 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?

  10. 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.

  11. 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

  12. 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.

  13. 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.

  14. 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?

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

  16. 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

  17. 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.

  18. Have no money and still own a Macintosh? Thinking that Java code runs in terminal already says you’re a Mac/Apple user. You probably over-stressed your pricey Apple keyboard typing the second part..

  19. Got this working, I’m pretty impressed with the results, it does the alpha blending/antialiasing too by the looks of it. :D

    This post is a bit out of date now though, since you are now meant to pass a FreeTypeFontParameter object into generateFont().

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>