Hi, Habr! I present to you the translation of the article
The Joy of Haxe. FontStruct's love affair with a neglected programming language .
A rather crude attempt to reproduce the Haxe logo in the FontStruct font editor.
Recently, we have opened the source code of the most important part of our module for creating fonts. This is the
fonthx library for creating TrueType fonts, and it is written in
Haxe .
This article is almost no code. If you are only interested in the code, then you can familiarize yourself with it on
github , and its work is shown
on the example of the simplest pixel font editor, built using the fonthx library.
Regardless of whether you are familiar with Haxe or not, the fonthx project may interest you, as it demonstrates some of the amazing features of the language, little-known outside the Haxe community - in particular, the ability to write code in one pleasant language with further compilation / translation not only in Javascript, but also in many other platforms, in the case of fonthx, such platforms are JVM (project code is translated to Java), native code (C ++ or C #), NodeJS or WASM.
')
I can be called a staunch polyglot. Like many other developers, I write code in different languages ​​and, respecting the serious intentions of those who prefer to specialize only in any one language, I also fear all those fans and evangelical fraudsters who say the same true language. But what prompted me to use such a niche language like Haxe to create key components of FontStruct, as well as write this article? And what is Haxe?
Haxe
Haxe is a modern, strictly typed programming language with some interesting features and a small standard library.
The most significant feature of a language is its ability to compile the same code for different target platforms.
Most developers are familiar with the concept of "isomorphic" development, when a programmer writes both server and client code in the same language. Most often, Javascript or TypeScript is used as such language, but any other language that can be compiled into Javascript can also be used. Haxe in this direction goes much further, opening a number of interesting additional features. It is possible to compile an executable file, a Java application, a WASM module, a NodeJS application, a browser-based application, a mobile application, and even libraries for languages ​​such as PHP, Lua, or Python from a single code base on Haxe.
At FontStruct, we take this opportunity to develop key components of our Haxe application. Server modules are compiled as Java servlets, and client modules are compiled as applications on JS. And although we are currently focusing mainly on these two target platforms (as well as NodeJS to run speed tests), we are also considering using the tools provided by the Haxe ecosystem to create mobile applications in C ++. In addition, the use of Haxe in the future may allow you to create a native (non-Electron-based) desktop application.
Due to the fact that Haxe supports such a multitude of target platforms, it best of all (at least for our tasks) implements the idea of ​​“write the code once - run it everywhere”, better than any tool I've met in the last twenty years. This gives the feeling that the same code can be compiled under any platform or runtime environment.
Haxe adoption process
FontStructor is a free font editor at FontStruct.com
More than 10 years ago, when FontStruct was launched, Adobe Flash was used for the FontStructor font editor, as well as for the widgets for viewing fonts. And to create TrueType-fonts on the server was used completely independent code written in Java.
Old Flash version of FontStructor. All controls in it were drawn in Flash. Notice the weird scroll bars in the panels on the left. Over time, the main menu at the top of the page gradually diverged visually and functionally from the html menu used in the rest of the site. There is neither DOM nor CSS
Although FontStruct was and remains a huge success, our initial technical solutions did not pass the test of time. The development of web standards and the lack of support for the plug-in on mobile platforms have made Flash unsuitable for use in web applications. We also had to deal with duplicating code between the server in Java and the client in Flash, as well as between Flash and the rest of the client written in HTML / JS / CSS. It was necessary to constantly synchronize among themselves the three code bases, both in terms of functionality and design.
In 2013, we began to consider the possibility of using Haxe, in particular, as a means for translating FontStructor from Flash to HTML5. In our initial research, we discovered that there are already available tools for automatically converting ActionScript code to Haxe (
as3hx ) and even the
Haxe port of the Robotlegs MVC framework, which we used in the Flash version. And so we began the experiment on porting the client.
Slow and full start problems
Our first year of relationship with Haxe was accompanied by indecision and doubt.
For several reasons, and not least because of the limited resources we could devote to it, the porting process was rather slow. As
noted by other authors , the tool for automatically converting ActionScript code to Haxe (as3hx) turned out to be very useful, but not without flaws - the code obtained with it had to be additionally viewed and edited. During this process, it came to the understanding that our code base was inflated and erroneous in its design; therefore, in parallel with porting, we decided to make improvements, thereby further slowing down further progress. In addition, Haxe was a new language for us, so we inevitably made mistakes when learning this language and its tools.
Of course, our biggest mistake was to additionally use a third-party UI framework on Haxe.
For Haxe, there are many such frameworks (perhaps even too many) that provide a unified API for drawing graphics on various platforms.
OpenFL and
NME are examples of such frameworks and provide tools to build Haxe applications for mobile platforms and even consoles. At the same time, they provide an implementation of the Flash API for drawing graphics. It all seemed very tempting - we could transfer our application to HTML5 using a familiar API and maybe even create applications for Android and iOS at the same time!
Therefore, we decided to use OpenFL to port our application to Haxe.
I do not want to show disrespect for OpenFL (I even want to say that: “The problem is not in OpenFL, but in us”). OpenFL is a fantastic project that has shown itself well in many projects, and we can return to it in the future, but after porting about 90% of our application on Haxe, we decided to abandon it.
OpenFL turned out to be a much more serious addiction than we expected. It was originally planned that it will be used only as an external library for our UI, but in the end it turned out that OpenFL was dragging its own tools for building projects, special file formats for describing projects, as well as additional external dependencies. Perhaps this is due to the fact that, like most of the Haxe ecosystem, OpenFL tries to meet the needs of indie game developers, while it develops rather quickly and its development focuses on adding new features rather than stability.
The most important thing for us was that the HTML5-code generated using OpenFL is ideal for games, but it is not suitable for an application like FontStruct. All we wanted to do in the end is to display in the browser a regular DOM tree, which we could style with CSS, rather than a set of canvas elements or sprites created by OpenFL.
We needed plain HTML5, and not an attempt to repeat Flash in the browser without using additional plug-ins.
Fun
As soon as we abandoned the use of OpenFL and realized that we could do everything we wanted, using only Haxe, everything went faster, easier and, ultimately, much more fun.
And working with Haxe is fun. It can be said, created by experts in fun - independent game developers. Game developers need fast compilation, as well as a single code base for creating applications for desktops, browsers, iOS, Android, and consoles. Game developers need productive and stable code. And Haxe provides all these great features, and not just for game developers.
I’m not afraid to express the idea that one of the biggest problems of Haxe - the relatively small size of its community and the associated sparseness of its ecosystem - is also its advantage in terms of experience for the developer. Working with Haxe, you are unlikely to spend hours on googling and searching for information on stack-overflow, or on parsing and comparing different lessons on a topic of interest, as well as while learning the API of some new framework or library — these answers, lessons and libraries may simply not be. And if there is, then, most likely, they will be the only materials on these topics. With Haxe, you will solve programming problems on your own (!), Write libraries yourself, without feeling any guilt, even reinvent or port the wheel yourself. This is fun and gives freedom, and this is something that many developers strive for after endless frameworks and modern development related to copying code from different sources. Using the principle “less is better”, Haxe is not unique, but this is its definite plus.
Haxe gives the programmer a unique opportunity. It gives a special feeling of amazing discovery and joy. Using Haxe, with its ability to compile code for a variety of target platforms, there is a feeling that the programmer is being freed from one of the most fundamental dependencies of all the existing ones - the execution environment itself.
Renderer FontStruct
The launch of our first component on Haxe for the FontStruct site in April 2015 was a strange and unexpected event.
Gallery is a central part of FontStruct: searchable, sortable lists of thousands of fonts created on our platform. From the very beginning in 2008, we had constant problems with download speed and font preview performance both in the gallery itself and on other pages of the site.
Part of the FontStruct gallery page, which shows a preview of the fonts created on the platform. Initially, each individual preview item was presented with a slow-loading Flash movie!
Since FontStruct fonts (“FontStructions”) are stored in proprietary format and are often edited, it is not possible to use them for rendering as regular TrueType fonts. This meant that it was impossible to create raster images on the server for previewing fonts (using the FreeType library).
To “solve” this problem, in the earliest days of FontStruct’s life, we used separate Flash movies for gallery elements. Each Flash movie loaded and parsed data in our proprietary format, and then showed a preview image on the client. When displaying on the page 20 or more such clips, each of which loaded data and tried to draw the font, the load time and resource consumption of the user's machine increased significantly, and the situation worsened with time as the fonts developed in our editor became and more complicated.
In the end, we used a fancy hybrid solution: the very first font preview used a Flash movie that generated the image for preview, then the image was captured and stored on the server as PNG files. And for previewing for the following users, PNGs stored on the server have already been used. - This strange hack has significantly improved the page load time, but it was dirty and, ultimately, wrong or something. The right decision would be to write a completely new server module — for example, in Java or PHP — to load and parse font data, and further create a bitmap on its basis, but we simply did not have the resources to do so.
In the meantime, the porting process of Fontstructor to Haxe proceeded very slowly, and we were far from the release. But we have advanced far enough to understand that the new Haxe code can solve our problems with previewing fonts in the gallery.
We already had the Haxe code for loading and parsing our font format. We had code for rendering glyphs (on Canvas in HTML5 or on sprites in Flash). We also had all the components needed to solve the problem on the client side. Could we adapt this code for use on the server?
Yes! After we realized this, the process went very quickly. At first we thought to use C ++ and the Cairo library to draw fonts (hoping that we could write an extension for PHP or some CGI module), but instead decided to use Java. “How wonderful it is to be able to make such a fundamental choice with a few lines of code and conditional compilation!” We could also use NodeJS and node-canvas for this, but we were already familiar with the process of creating and deploying Java servlets, and Java has all the functions we need to draw and manipulate raster images. Perhaps we didn’t like writing Java code, but with Haxe there is no need for that.
Such high-level drawing code can be compiled and run both on the client (JavaScript) and for the server (in the JVM)
As a result, it took us only a few days to make changes to our code base, and the new renderer was launched. Overnight, we significantly improved the performance of the FontStruct gallery, got rid of the use of dirty hacks, and, most importantly, launched our very first component on Haxe to the battle. We realized that Haxe is capable of surprising and has much greater capabilities than we expected from it.
Farewell to Flash (and vanilla Java c)
In November 2015, that is, after 7 months, we successfully launched the first client module on Haxe - an HTML5 version of the widget for previewing fonts. I think that our users almost did not notice the changes, which on the one hand somehow disappoints, but, ultimately, is an indicator of the success of this undertaking.
Now we only had one Flash module on the site - the FontStructor editor, and it took us another year to finally launch its HTML5 version in November 2016. So the time has come to finally abandon our AS3 code and declare FontStruct free from Flash.
New HTML5 version of FontStructor, launched in 2016
In August 2018, we ported the FontMortar font generation module to Haxe. This last port allowed us to completely abandon code written in Java.
I am not ready to use Haxe for everything. Yes, I know that there are projects where it is used as the main tool for all aspects of web development, but I am very satisfied with the excellent
Symfony framework as the basis of our web application. FontStruct continues to use many different programming languages, but the introduction of Haxe allowed us to reduce the size and complexity of the most important parts of our code. For our tiny organization, such a simplification has proved vital to the maintenance and development of the platform.
Plunging deeper into Hux
If this is the first time you've heard about Haxe and you are interested in my story, then I just have to list a few more facts about him.
- Language support from the IDE is quite decent and is constantly improving, modules for IntelliJ Idea and Visual Studio Code are being actively developed.
- Haxe provides tools for working with native code and libraries , so it does not limit your capabilities by imposing only a small subset of the available functions. If you are developing for JavaScript, then you have the opportunity to use any JavaScript library, for example, various binders are available for working with React. For the FontStructor, we use several npm modules, such as interactive.js and opentip. Writing binders for them took just a couple of minutes.
- Haxe has a robust advanced type system with features like type parameterization , generic classes and methods , abstract types, and type inference .
- Haxe has extremely powerful macros that provide access to AST at compile time, which allows developers to add their own language constructs and generate code dynamically.
- Despite the fact that Haxe doesn’t have many resources on the Internet, there is a library repository covering the general needs of developers outside the standard library (besides you can find even more repositories not represented on haxelib on Github). .
- Last but not least, Haxe has a very talented and responsive community .
Conclusion
Most experienced developers are ready to change, but they are careful in choosing the technologies used. It is likely that at some point most of you also felt a desire to change the programming language within the project, especially when new, trendy languages ​​appear, with many interesting possibilities. We were careful about choosing Haxe, thinking about how long our relationship will last. These were our thoughts about him:
It sounds great, but he has such a small community. What will happen to him in 5 years? The site seems to be normal, but for some reason it does not look modern. And it does not inspire confidence.
It seems that it is not so well documented.
Isn't it for indie game developers?
After five years of using Haxe, I am genuinely surprised that I do not regret our choice of this technology. Despite all the shortcomings and all the difficulties caused by them, despite the relatively small community and the absence of large corporate sponsors, Haxe completely copes with its tasks. With Haxe, I feel freedom and independence from any platform. Now we have a single code base for the main components of FontStruct, while earlier there were two of them. Over the past few months of work, new versions of servlets, which are responsible for generating fonts and preview images, have never failed. New HTML5 editor and preview widget now work in all browsers, including mobile, whereas earlier we had to work with outdated and dying technology.
And, if we ignore the practical benefits, working with Haxe brings joy and a sense of magic, the joy of
Haxe !