BitmapFont refactoring

My friends! Let’s talk about font rendering. So far we’ve been using a relatively naive way of rendering in libgdx: for each character in the string, find the glyph, draw the glyph. This works fine for English and others, but not all. Some languages use different glyphs for the same character depending on where it appears in the word or sentence. As soon as we don’t have a one-to-one relationship between characters and glyphs, we can’t do proper rendering.

The solution for this is to transform the list of characters into a list of glyphs, then render the glyphs. The BitmapFontData, BitmapFont, and BitmapFontCache classes have been refactored to support doing that. Here’s how it works:

  1. GlyphLayout, a new class, is given a string of characters. It first breaks the strings into “runs”. A run is a string of characters all the same color and without newlines. The reason to break the text into runs is that each run can be “shaped” individually, which means to convert the characters into glyphs for display. When breaking the string into runs, GlyphLayout parses color markup tags (eg “thisIsWhite[red]thisIsRed”) and stores the color for each run.
  2. Next, the runs are shaped using a new BitmapFontData method, getGlyphs. This takes the characters for the run and generates both a list of glyphs and a list of positions for each glyph. The default implementation just looks up the glyph for the character as has always been done. A more complex implementation could use HarfBuzz or another lib to do the shaping.
  3. Next, the shaped runs are laid out. If wrapping is enabled and a run’s glyphs exceed the wrap width, then glyphs are split for line wrapping using another new BitmapFontData method, getWrapIndex. The run is ended, the remaining glyphs are moved to a new run on the next line, and the layout process repeats. Because BitmapFontData controls line wrapping, it can be customized for a particular langauge.
  4. At this point GlyphLayout is done. It stores the Array<GlyphRun> and provides a width and height which is the bounds of all the runs. Previously getting text bounds required all the work of laying out the glyphs, which then had to be repeated for drawing. With GlyphLayout, the work is only done once. Each GlyphRun has Array<Glyph> and a FloatArray for the positions.
  5. Next comes BitmapFontCache. This class now has an Array<GlyphLayout> and its job is to store the vertex data for rendering the glyphs in those GlyphLayouts.

Introducing GlyphLayout and the new way of rendering glyphs required some relatively small API changes. Sorry! Since breaking the API was unavoidable, we also made a few other breaking changes. It’s better to fix up a few API changes in one go than to have to do it every time you update libgdx.

Here are the changes that may affect you:

  • The BitmapFontCache setText, setMultilineText, setWrappedText, and similar addXxx methods are replaced by setText and addText. The same happened to the BitmapFont draw methods, which delegates to BitmapFontCache. There are fewer methods now and they have more features. These methods all return GlyphLayout instead of TextBounds.
  • BitmapFont.TextBounds and getBounds are done. Instead, give the string to GlyphLayout and get the bounds using its width and height fields. You can then draw the text by passing the same GlyphLayout to BitmapFont, which means the glyphs don’t have to be laid out twice like they used to.
  • BitmapFont.HAlignment is gone. Align is used instead.
  • Align has been moved to the utils package.
  • markupEnabled and setScale have been moved to BitmapFontData. These are really BitmapFontData settings, not per BitmapFont settings.
  • BitmapFont computeGlyphAdvancesAndPositions and computeVisibleGlyphs are gone. GlyphLayout can be used instead, which provides each glyph position.
  • BitmapFont has an Array<TextureRegion> rather than a TextureRegion[]. This makes it easier to add regions as needed.

Here’s a quick guide for moving to the new API:

Sorry for the trouble if you end up needing to change your code slightly, but this enables us to have proper font rendering in the future. HarfBuzz and FreeType can allow us to render text in any language, which is a big deal!

But wait, there’s more! Many languages don’t need glyph shaping – they can use a one-to-one mapping of characters to glyphs – but they have a different problem: they have way too many glyphs than we can hope to fit on a texture. There are only a few solutions for this, you need to render on the fly.

Rendering entire sentences to the atlas instead of individual glyphs is one approach, but this isn’t great for text input or text that changes a lot. Rendering glyphs on the fly, as they are encountered, is probably the best we can do. If the glyph atlas becomes filled, we can either add atlas pages (bad for draw calls) or empty the atlas texture and start over (fails if the screen contains more glyphs than can fit in a single page).

Rendering glyphs on the fly means using FreeType. We already have FreeTypeFontGenerator to generate a BitmapFont using FreeType, but now you can tell it to generate an “incremental” font. When the font is queried for a glyph that hasn’t been rendered yet, it renders it to the glyph atlas.

The red boxes at the top are the glyph atlas pages (purposefully made tiny for testing) and the text below is rendered using those glyphs. We can implement better packing (eg, a skyline variant) in the future, for now it uses PixmapPacker as it used to.

It will be interesting to see if this helps libgdx have better adoption in China, where currently cocos2d-x is widely used. Interestingly, cocos2d-x appears to use a “label” approach to font rendering where an entire sentence is rendered to the backing texture rather than individual glyphs.

If you’re interested in the changes for these features, you can check out PRs #2955 and #2973.

libGDX 1.5.5 released

libGDX 1.5.5

New month, new release! This release brings changes and additions to the 3D API, and 64-bit support for Bullet Physics on iOS!


Note: Make sure to update your RoboVM Eclipse plugin to 1.0.0! You can now also sign up for a trial to use the RoboVM debugger, or get a license. No worries, you can still develop all your apps for free as before. Head over to

Let us know if you run into any issues. See this wiki article on how to update your libGDX project to the latest version. The current libGDX version is “1.5.5”, the current nightly version is “1.5.6-SNAPSHOT”, OR you can just check our versions page which details all the versions of dependencies as well.

RoboVM 1.0 Released! A Look Under the Hood

Reddit, you killed our server at You can still give RoboVM a whirl over here. This is a mirror of our blog post, we’ll be back.

After months of hard work we are proud to announce our first stable release, RoboVM 1.0! This would not have been possible without the help from our fantastic community who provided feedback, filed issue reports and worked with us to track down bugs. A big THANK YOU to all of the over 2000 beta subscribers!

With the 1.0 release, we hope to grow our community even further. For this reason, we’ll also take a look under the hood of RoboVM today, giving newcomers a bit of insight what RoboVM is, how it works, and what our motivation behind it is. If you want to know more, jump to “What’s RoboVM?”

What’s new?

Many new features and bug fixes went into 1.0:

  • The debugger has received another round of updates. All JDWP functionality is now implemented.
  • Support for RAM disk caches. This can help speed up the compilation and linking process on slow HDDs.
  • Support for HFS+ file compression. All files put into the cache are now compressed, further speeding up the compilation process and reducing the amount of space used for the RoboVM cache.
  • Initial project template and Maven archetype support.
  • A new Eclipse project wizard, using the templates project
  • Support for invoking tools via robovm.xml. We currently support the TextureAtlas tool, with more to come.
  • Cleanup and simplification of Objective-C bindings, see the binding status page

Announcing Commercial Licenses

First off: nothing will change for users of our OSS core! You will continue to be able to create apps without any artificial limitations, free of charge. With our new commercial licenses we add convenience features and support services on top of the OSS core. This will allow us to support our work on the free OSS core and ensure the longevity of the project as a whole.

Our commercial license scale with the size of your business, covering solo developers, startups, SMEs and big enterprises. Depending on your plan, you’ll get access to the following features and services:

  • JDWP compliant debugger for both simulator and on-device debugging
  • Improved crash reporting
  • Private e-mail support, with and without SLA
  • JavaFX support
  • Hotfix support
  • Alpha channel access to new commercial features

Our full pricing information is available at

Over 2000 developers have subscribed to our beta program over the last few months. You have provided invaluable feedback for which we’d like to thank you with more than just words.

All beta users are eligible for a discount of 50% for the solo and startup license tiers (one year subscriptions)! Please sign up for a trial with the e-mail address you used for the beta. We’ll get back to you with a discounted license in the next 14 days!

What’s next?

The 1.0 release marks an important milestone for us. But we are far from being done. We’ll continue with our fast paced releases, with the following features scheduled for the near term future:

  • Improved documentation, users guides and screencasts
  • Intellij IDEA & Android Studio integration, a preliminary Gradle-based plugin is available
  • Interface Builder integration (commercial feature)
  • Support for extensions (dynamic libraries) to enable peripherals like Apple Watch
  • Support for statically linking RoboVM into Objective-C apps

Exciting times ahead! With all of this out of the way, let’s take a look at what’s under the hood of RoboVM.

What’s RoboVM?

At Trillian Mobile, we really love the JVM ecosystem. With an abundance of great IDEs, build systems, languages for every taste and a huge amount of 3rd party libraries, we think it’s one of the most productive environments around. Over the years, the JVM ecosystem has been slowly fading from the client-side, for better or worse (anyone remember applets?). With Android, client-side Java is a thing again, but that’s only one of the two big mobile platforms.

Our goal with RoboVM is to bridge the gap between backend, Android and iOS. We want to unify the workflow of millions of Java, Scala, Kotlin, Groovy and Clojure developers, so they can use their tools and skills while creating truly native apps for every platform.

To achieve this goal, RoboVM is setup as a platform with multiple components:

All of these components allow you to write native iOS apps, share code with Android and the backend, have a sane build and test environment and make you a happier developer overall. Apart from the debugger, everything is OSS and available to be torn apart and remixed on Github!

The AOT Compiler

At the heart of RoboVM lies its AOT compiler. JVMs usually employ just-in-time (JIT) compilation: JVM bytecode is loaded at runtime and transformed to native code. Apple does not allow JIT compilers on iOS, memory pages can not be set as executable. For this reason, RoboVM takes your Java 8 bytecode and transforms it to a native executable before your app is deployed to a device. As a result, RoboVM can not load bytecode at runtime, which is pretty much the only limitation of RoboVM.

By taking bytecode as input, RoboVM does not need to care about what produced this bytecode. You can feed RoboVM’s compiler bytecode generated by Java, Scala, Groovy, Kotlin, Clojure or any other alternative JVM language compiler, and it will happily compile it to native code. This is in contrast to approaches such as J2ObjC, which takes Java source code instead of bytecode and transforms it to mostly equivalent Objective-C code. Not having to rely on the original source makes it possible to integrate any 3rd party JAR easily.

As a first step in the compilation process, RoboVM parses the bytecode of a class file via Soot. Soot allows us to transform the stack-machine based JVM bytecode to more manageable 3-address code representation called Jimple. We then apply many optimization and simplification passes on this Jimple code, such as dead code elimination.

Once we are done jimpling up all the things, we apply custom transformations that allow us to support Java 8 language features such as lambdas and our custom binding bridge called Bro, responsible for easily interfacing with C and Objective-C code from Java.

After all these transformations we translate our heavily modified Jimple to LLVM IR. LLVM is the compiler infrastructure used by Clang to compile C, C++, Objective-C and Swift, among other languages. By employing LLVM, we reap the same benefits as those “native” languages: highly optimized emitters for a broad range of architectures such as x86, x86_64, ARM thumbv7 and ARM 64-bit. With the LLVM IR in hand, we generate an architecture specific assembly file that we then assemble to a final object file.

The compiler is modular, so we can add any amount of plugins that interfer with this compilation process. One such plugin allows us to add DWARF metadata to the LLVM IR, which we later use to know where local variables are located on the stack or where to insert instrumentation for debugging.

Every class file is hence compiled to a corresponding object file. Doing this for every compilation would be rather time-consuming, which is why RoboVM employs incremental compilation: only the set of class files that changed since the last compilation is recompiled, along with their dependent classes. The resulting object files are cached for re-use.

Just blindly compiling all classes specified in the classpath of a project would also not be the smartest thing to do. Given a main class as the main entry point, RoboVM will figure out the set of classes that are actually required. We can bring down the number of classes, methods and fields being compiled even further by tree-shaking, an area we are currently investigating.

With all the object files for a project in hand, we can link the final executable. RoboVM allows you to easily specify any additional native frameworks or libraries you want to link in, either via annotations in code or the project’s configuration file for non-system frameworks and libraries. We also need to link in RoboVM’s runtime, consisting of things like the GC, debugging support, native code for the class library and so on.

An executable alone is not enough, so RoboVM will also take any resources you have, optionally run them through tools such as TextureAtlas, and compile the final application bundle, ready for submission to the app store!

The Runtime

A virtual machine requires a runtime to provide low-level services to the user code. Such services include garbage collection, threading, reflection and so on. Let’s look at a few pieces of RoboVM’s runtime.

One central part of RoboVM’s runtime is the garbage collector GC. RoboVM uses the Boehm-Demers-Weisser GC, a conservative GC originally designed for languages like C or C++. A conservative GC has to scan the heap and registers under the assumption that anything can be a pointer to managed data. This sounds suboptimal, and it is, but with some tuning and optimizations, the Boehm GC can be a rather capable GC.

RoboVM tunes the Boehm GC in such a way, that it’s working in mostly-precise mode. The GC does not have to blindly scan large portions of the heap, but can instead rely on some additional information we give to it. This way, the GC only has to scan registers and the stack conservatively, greatly improving performance. On top of this, we also enable thread local allocation, meaning we do not have to take a global lock when allocating memory for an object. Finally, we also enable parallel mark & sweep, distributing the GC load to multiple threads, reducing GC latency.

The runtime is also responsible for supporting reflection. A RoboVM executable stores all information required to support the full reflection capabilities found in standard JVMs, including method invocation and proxies. We use a few assembler tricks for the latter two features, which makes RoboVM a very capable runtime for Java bytecode.

The Class Library

Java is known for its extensive standard class library. Any 3rd party library your app depends on expects certain classes of that standard library to be in place. RoboVM takes its class library from Android, which itself is a fork based on the now defunct Apache Harmony. This means that any 3rd party library that works on Android will also work on RoboVM, with the exclusion of Android specific APIs, such as Android’s UI layer.

Just taking Android’s class library and hoping for the best when using it on iOS is of course not going to work. The class library does not only consist of Java code. To interface with system services such as the file system, there’s also a considerable amount of native C/C++ code which is exposed to Java via JNI.

We therefore have to massage those native bits a little bit to make them work on iOS. Both Android and iOS are supposed to implement the Posix standard. In reality, they both have a slightly different interpretation of this standard when it comes to things like networking or threading.

A standard class library has to be rock solid, especially if you port it to a new operating system. We run tests against 3 huge test suites that guarantee the proper behaviour of both the class library and the VM features the class library relies upon. These test suites come from the original Apache Harmony project and the Android Dalivk/ART runtime.

The Bindings

With RoboVM, we want to enable you to write native applications instead of pushing your UI to a webview. This means that you need full access to the iOS frameworks required to implement your UIs, interface with the hardware or use services such as in-app purchasing or notifications. Historically, JVMs interface with native code through the Java Native Interface, a rather cumbersome way of talking to C/C++/Objective-C code.

We wanted something simpler, with better performance. Which is why we came up with Bro, our custom Java-to-native bridge. Bro is inspired by JNA and other similar JVM solutions, as well as .NET’s p/invoke.

With Bro, you can wrap any native C or Objective-C API in pure Java code via annotations. Here’s a basic example that gives you access to the native implementations of abs():

The @Library annotation tells the compiler which library or framework to link. The @Bridge annotation tells the compiler that the abs method should be bound to the C function of the same name.

This is of course only the tip of the ice-berg. RoboVM will automatically marshal more complex data types between the Java and native side. You can also bind C structs, Objective-C classes, which is what we do to give you full access to all of iOS’ frameworks and APIs. You can even subclass Objective-C classes!

Bro allows you to use iOS frameworks and APIs in a very natural way. We already did all the heavy lifting and created bindings for all of iOS frameworks and APIs. Here’s an example of a custom view controller:

The MyViewController class actually extends an Objective-C class called UIViewController! The rest of the code also flows quite naturally, especially with Java 8 lambdas.

RoboVM will also take care of the interaction with Objective-C’s Automatic Reference Counting (ARC) mechamism. RoboVM will do the “right thing”, so you do not have to think about it too hard. Should you still require to interact with ARC, RoboVM lets you do it.

The bindings to iOS frameworks & APIs are generated semi-automatically. If you want to create a binding for an existing iOS library, you can employ our binding generator and modify things to suite your needs. To date, we’ve bound 98% of all iOS 8.1 framworks and APIs.

Now, not every scenario lends itself well to writing two separate UI layers. Especially in the enterprise, there’s a need to get things going quickly, with minor compromises regarding the UIs native look and feel. For this use-case, we support JavaFX on both iOS and Android. This approach allows you to share 100% of your code between both platforms. We partner with LogdON to ensure JavaFX works smoothly across iOS and Android.

The Debugger

A RoboVM commercial license give you access to a Java Debug Wire Protocol (JDWP) compatible debugger. JDWP is what allows you to debug a Java process from within your IDE. RoboVM supports JDWP as well, so you can debug apps an both the simulator and the device, using the tools you are used to.

RoboVM’s implements a soft-debugger: the runtime cooperates with the debugger at specific safe-points in the user code to implement thread suspension, stepping, breakpoints and memory inspection. In debugging mode, the app will spin up an additional thread that listens for commands over TCP. On the other side of the TCP channel sits our JDWP server, implementing the protocol on-top of our custom, minimal debugging protocol.

Alternative approaches such as GDB and LLDB use OS services to control the process. We actually investigated the use of LLDB in the beginning but ultimately decided against it. First, LLDB is process-centric: if one thread stops, all other threads have to stop as well. This is ultimately incompatible with JDWP’s thread-centric model: you can stop one or more threads, while the remaining threads continue to run. The second reason for deciding against LLDB is that our JDWP server would have to take over the process via LLDB. This would prevent you from debugging the native side of your app while also debugging the Java-side. As it stands, you can simultaneously debug your app from your Java IDE as well as XCode!

The RoboVM debugger allows you to do anything you are able to do with a normal JVM debugger: suspend/resume threads, set (conditional) breakpoints, step in/out/over source lines, modify variables at runtime and invoke methods, e.g. via Eclipse’ display view or Intellij IDEA’s “Watch Expressions” dialog. All of this works both on the simulator and on the device.

IDE Integration

One of the biggest reason we are working on RoboVM is to bring the tooling around the JVM to iOS. For the past year we have focused on Eclipse, which is our current default development environment. Our Eclipse plugin (update url: supports the easy creation of both console and iOS projects. It integrates the debugger and JUnit support for a smooth development experience. You can also pair Eclipse with either Gradle or Maven for saner builds and continuous integration.

Android has since shifted fully to Android Studio, which is based on JetBrain’s Intellij IDEA. We have an initial version of the RoboVM Intellij IDEA plugin ready and are working hard on bringing it up to the quality of the Eclipse plugin. We realize the importance of support for both IDEA and Android Studio, especially if you do cross-platform development. Expect more in this area in the upcoming weeks!

Finally, there’s also some community work on NetBeans integration.

For a full featured experience, we also have to play nice with the tools provided by Apple. We are currently working on full interface builder integration, which should make creating basic UIs even simpler. Interface builder integration will be a commercial feature and is planned to be released in Q2 2015.

Build System Integration

RoboVM supports a wide range of build systems. For the die-hard, we provide a distribution of RoboVM that you can invoke from your command line like any other compiler system. That way you can integrate RoboVM with shell scripts should the need arise.

However, we’d strongly suggest to use more established build systems! We created a dedicated Maven plugin as well as a Gradle plugin, which should make your life considerably easier.

Going forward, we’ll provide project templates both via the Maven archetype as well as the IDE integration so setup not only iOS RoboVM projects, but also cross-platform iOS and Android projects.

Where to go from here?

By now, you should have a pretty good idea of what RoboVM is and how it can help you. If we peeked your interest, head over to our documentation page, and get started today!

If you just want to check out some code, we recommend looking through our ports of Apple’s iOS sample apps.

Finally, if you are very adventurous, you can also check out the RoboVM internals, right on Github!

About RoboVM

The goal of the RoboVM open-source project is to bring Java and other JVM languages to iOS. RoboVM’s ahead-of-time compiler translates Java bytecode into native ARM or x86 machine code that runs directly on the target CPU without being interpreted. The runtime is based on Android’s runtime classes and includes a Java to Objective-C bridge which makes it easy to use the native iOS Cocoa Touch APIs from Java or your JVM language of choice.


Web site:
Google Groups: