The Joy of Haxe
FontStruct’s love affair with a neglected programming language
Recently, we quietly open-sourced a key part of FontStruct’s font-generation module. It’s a very basic TrueType font-generation library called fonthx and it’s written in Haxe. This is FontStruct’s first open-source contribution.
There’s almost no code in this post, so if that’s your primary interest, I suggest you have a look at the code on github or try a live browser demo of a primitive pixel-font editor built using the library.
I’m an ardent polyglot. Like many developers I write in various different languages and while respecting the serious intent of those who choose to specialise in just one, I’m also wary of all fanboys and blinkered evangelists — all heralds of the one true new dawn. In fact I’m suspicious of articles exactly like this one. So what led me not only to use a niche language like Haxe for key components of FontStruct, but to attempt to sing its praises in a blog post? And what is Haxe anyway?
Haxe is a modern, strongly-typed, programming language with some interesting but not outlandish features and a small, solid standard library.
Its most notable feature however is its ability to compile or transpile to multiple “targets”.
You can, and we do. At FontStruct we currently develop four key components of our application in Haxe. Two performance-critical server-side modules are compiled as Java servlets. Two client-side modules are compiled as JS browser apps. While our current focus is primarily on these two targets (as well as the nodejs target for running tests at speed) in the future we hope to explore the C++ based mobile toolchains which the Haxe ecosystem also offers. A genuine (non-Electron) desktop app is a further avenue to explore, also opened up by Haxe.
With its multiplicity of transpilation targets, Haxe fulfils the write-once-run-anywhere promise more usefully — at least for FontStruct’s purposes — than any tool I’ve encountered in the last twenty years. It gives developers the feeling that they can, at any time, choose to compile to virtually any environment, runtime or platform.
FontStruct’s adoption of Haxe
When FontStruct was launched over 10 years ago, we used Adobe Flash for the “FontStructor” —our font editor— and for font preview widgets all over the website. On the server, for TrueType font generation, we used a completely separate codebase written in Java.
While FontStruct was, and remains a huge success, our original technical choices proved problematic with the passing of the years. The push for web standards, and the lack of mobile support for the plugin made Flash a less and less viable option for a web application. We also had to manage large-scale code duplication, both between our server-side Java and our client-side Flash, and between Flash and the rest of the HTML/JS/CSS web app. It was a struggle to keep everything in-sync across three codebases, both in terms of functionality and design.
In 2013 we started exploring Haxe, specifically as a way to transition the FontStructor editor from Flash to HTML5. In our initial researches, we discovered that there were automated conversion tools available (as3hx) and even a Haxe port of Robotlegs, the MVC framework we’d been using in Flash, so we tentatively started the porting process.
A Slow and Rocky Start
Our first year of courting Haxe was hesitant and not free from doubt.
For several reasons, not least the limited number of person-hours we could devote to it, the port turned out to be a relatively slow process. As others have discussed, the automated conversion tool from Actionscript to Haxe is very useful but inevitably imperfect, so to get the details right we had to manually review and tweak every file. During the process we realised that our codebase was bloated and flawed in its design, so we took the opportunity of the port to improve this, thus slowing progress further. In addition, Haxe was simply new to us, and inevitably we made mistakes as we learned the new language and its tooling.
By far the biggest mistake we made was in deciding to use an additional UI-framework on top of Haxe from the very start.
There are a number of such frameworks for Haxe (arguably too many) which offer a single drawing API across the various targets. OpenFL and NME, for example, are exciting frameworks which provide mobile and even console-targeting toolchains built on top of Haxe, promising a simple, unified view layer. They also offer a very straightforward, direct translation of all the Flash drawing APIs. This all seemed extremely tempting — We could port our application to HTML5, using familiar APIs, and maybe even create Android and iOS apps at the same time!
So we proceeded to port our application not simply to Haxe but also to OpenFL.
I intend no disrespect to OpenFL. (I’m tempted to write, “it wasn’t OpenFL it was us”) OpenFL is a fantastic project which serves many projects well, and we may well return to it in the future, but after porting about 90% of our application to Haxe and OpenFL we decided to drop the latter.
OpenFL turned out to be much more of a global dependency than we had hoped. While we expected it only to be referenced as a library in our UI code, it seemed to creep in everywhere, and brought with it its own build tools, project file formats and dependencies. Perhaps because it is, like much of the Haxe-ecosystem, driven by the needs of indie game developers, OpenFL seems to be a very fast-moving project, with a focus on new features and cutting-edge development rather than consolidation and stability.
Most importantly for us, it became clear that the HTML5 code generated by OpenFL, while perhaps perfect for games and those wedded to the Flash API, was less suited to an application like FontStruct. Ultimately we wanted to render a traditional DOM tree in the browser, which we could style with CSS, and not the collection of canvases or sprite-like nodes generated by OpenFL.
We wanted vanilla HTML5 and not a plugin-less recreation of Flash within the browser.
As soon as we took the decision to stop using the OpenFL framework, and realised that we could do everything we wanted with Haxe alone, everything became faster, easier and ultimately much more fun.
And Haxe is fun. It’s created in large part by experts on fun — those independent game developers. Game developers are looking for fast compilation times and a single codebase generating desktop, browser, iOS, Android and console outcomes. Game developers want performant, stable production code. Haxe delivers these things and they are wonderful things, not just for game devs.
I would even go so far as to suggest that one of Haxe’s biggest problems — the relatively small size of its community and the consequent sparseness of the ecosystem — is also an advantage in terms of developer experience. When working with Haxe you are unlikely to lose yourself in hours of stupefying googling or stack-overflowing for answers, or in parsing and comparing multiple code tutorials, or in learning the APIs of some new framework or library — for those answers, tutorials and libraries may well simply not be out there. If they are, most likely they are singular. With Haxe, you may actually find yourself having to solve programming problems yourself(!), writing libraries yourself or, without a moment’s guilt, inventing or porting the wheel yourself. This is fun and it’s liberating and it’s what many developers find themselves longing-for amid the endless framework-grokking and boilerplating of contemporary development work. Haxe is not unique in this “small is beautiful” quality but it’s a definite plus point.
Haxe empowers the programmer in unique ways. It provides a special kind of surprise and joy. Using Haxe with its multiplicity of compilation targets, one has the feeling that one is liberated from one of the most fundamental dependencies of all — the runtime environment itself.
The FontStruct Renderer
When FontStruct launched its first Haxe component on FontStruct in April 2015 it was a strangely sudden and spontaneous event.
Gallery pages are a central part of FontStruct: searchable, sortable listings of the thousands of fonts which have been created on the platform. From the very beginning in 2008 we had constant problems with load times and the performant provision of preview images for fonts on gallery pages and elsewhere on the site.
Since FontStruct fonts (“FontStructions”) are stored in a proprietary format and are frequently being edited, they are not readily available as TrueType fonts for rendering. This means that we couldn’t easily use traditional FreeType-based rendering to create bitmap image previews on the server.
To “solve” this problem, in the very early days of FontStruct we would load a separate Flash movie in the client browser for each gallery item. These flash movies would load and parse the proprietary data and then render a preview on the client. With 20+ movies on the page at a time –all loading data and attempting to draw it simultaneously– this made for very slow load times, and a hot, fan-whirring waste of client resources, especially as the fonts designed with our editor became more and more ambitious and complex.
Eventually we adopted a bizarre, hybrid solution whereby we farmed out rendering to the client: The Flash movies on gallery pages would capture their contents as a bitmap once they had displayed a preview, and then save that bitmap back to the server as a PNG. This PNG could, in turn, be used in place of the Flash movie for future visitors. — This strange hack improved page load times significantly, but it was messy and ultimately it felt kind of wrong. The right solution would have been to write a completely new server-side module — in Java or PHP for example — to load and parse our font data and then draw it on a bitmap, but we just didn’t have the resources to do that.
Meanwhile we were crawling along with the port of the Fontstructor to Haxe and were not yet close to releasing anything. But we were just far enough along to have our first Haxe-induced epiphany as we realised one day that our new Haxe code might be able to solve our gallery preview rendering problem.
In Haxe, we already had all the code to load and parse our font format. We also already had all the code to draw our glyphs onto something (at this point that something was a HTML5 canvas or a Flash Sprite). We already had all the ingredients required for a solution on the client-side. With Haxe’s magical assistance, could these be repurposed for use on the server?
Yes! After the initial realisation everything went very quickly. There were some brief hours of flirtation with the C++ target and some Cairo wrappers (thinking we could make a PHP extension or some kind of CGI module) we decided instead to use the Java target for our renderer. — How wonderful to be able to make such a fundamental choice with just a few lines of code and the flick of some compilation switches! We could also have used Node and node-canvas, but we were already familiar with building and deploying Java servlets, and Java provided all the drawing and bitmap-manipulation features we needed. We might not love writing vanilla Java code, but with Haxe, we didn’t need to in order to enjoy the performant stability of the JVM.
Ultimately it only took a few days and some minor adjustments to our existing codebase to put the renderer together and launch it. Overnight we massively improved the performance of the FontStruct gallery pages, obviated a really nasty hack, and, perhaps most importantly, we launched our very first Haxe component in production. We realised that Haxe could surprise us and do much more than we had originally expected.
Farewell to Flash (and vanilla Java)
Spurred on by the success of the renderer, 7 months later in November 2015, we successfully and quite seamlessly launched our first, client-side, Haxe-based module: a HTML5 replacement for our font preview widget. This widget is used for dynamic previews of font designs on single font pages. I think our users barely registered the change, which is somehow disappointing, but ultimately an indicator of success.
Now we were left with just one Flash-based module on the site — the FontStructor editor itself — and it took us a further year to finally launch that in November 2016. Although I once loved the unique technology that was Flash, it felt like the right time to finally abandon our AS3 codebase and declare FontStruct Flash-free.
Most recently, we ported our font generation module (the “FontMortar”) to Haxe, pushing it live as a Java servlet in August 2018. This last port allowed us to amicably divorce ourselves from the last of our pure Java source code.
I’m not quite ready to use Haxe for everything. People do use it for general web development, but I’m very happy with using the excellent Symfony as the core of our web application. FontStruct continues to use a number of different programming languages, but adopting Haxe has allowed us to reduce the size and complexity of the most important, domain-specific parts of our codebase. For a tiny organisation, this reduction in complexity is essential in allowing us to maintain and develop our platform.
Falling deeper into Haxe
Here are a few more wonderful things about the Haxe language which I haven’t mentioned in this post but really should, just in case this is your first encounter with the language and your interest has been piqued.
- Editor support is good and improving, with IntelliJ and Visual Studio Code plugins under active development.
- Haxe has a robust, sophisticated type system with features such as type parameters, generic classes and methods, abstract types and type inference.
- Haxe has an immensely powerful macro facility, providing access to the AST at compile time thereby allowing developers to add their own language features and generate code dynamically.
- Despite Haxe’s relatively small online footprint, there is a solid collection of well-designed libraries available, covering common developer needs beyond the standard library.
- Last but not least, Haxe has a very talented and helpful community.
Most mature developers are open to change but also cautious in their technological choices. Most will probably also experience, if not regret or jealousy, at least the urge to switch languages at some point within a project, especially when newer, hipper, shinier things come along. We were certainly cautious regarding Haxe, wondering how long our love would last. To faux-quote our thoughts:
It sounds great but it’s such a small community. Where’s it going to be in 5 years?
Their website’s ok, but somehow it doesn’t look contemporary. It doesn’t inspire confidence.
The documentation looks a little thin.
Isn’t it just for indie game devs?
Five years on from starting with Haxe at FontStruct, I’m genuinely surprised to find that I feel no regret whatsoever regarding our decision to go with the technology. Despite its imperfections and struggles, despite its relatively small-scale community and its lack of a big corporate backer, Haxe has delivered completely on its promise. With Haxe I feel the freedom of platform-agnostic independence rather than the burden of a dependency. For its core components, FontStruct now has a single codebase in a single language, whereas before it had two. We have stable servlets, reliably pumping out font files and font image previews for months on end, without a single crash. We have an HTML5 editor and an HTML5 preview widget which will work across all browsers including mobile, whereas before we were stuck with a deprecated and dying technology.
And setting aside all the practical benefits, there’s all the fun and the magic, the joy of Haxe!