Unlike a PC or a tablet, most embedded devices have limited memory space to store graphics content. These hardware constraints make designing a high-quality graphical user interface (GUI) a challenging task for designers. In this Altia Developer Blog Series article, we’ll provide some design techniques and sample designs created with Altia Design, our GUI editor, to demonstrate how to build efficient font usage into your embedded device GUIs.
Methods of handling fonts
Altia handles fonts in two different ways. With the first method, font glyphs can be generated and saved in a reflash file at the time of code generation. With the second method, you can generate code with runtime fonts which will generate font glyphs as they are needed during runtime.
First, we will talk about the simpler option of generating all font glyphs needed in the design at code generation. These generated font characters are also called pre-rendered glyphs. Every font used in your design requires that its full catalog of characters is added to reflash assets. Additionally, every size of every font requires that this data be added to the reflash data. It’s the same for every bold in every size in every font, for every italic in every size in every font…you get the picture.
By looking at your reflash/fonts folder, you will be able to see the number, sizes and variations of fonts that you are using in your design. In the image below, you can see that this design uses Arial Bold Italic 18, Arial Bold 17, Arial Italic 16, Arial Italic 17 and Arial Normal 17.
Our second font-handling method, using runtime fonts, the source code for the font engine used in the design is generated and loaded to your hardware. Then when a character is needed, the font glyph is generated from this code. This can be especially beneficial if you are using languages like Chinese where tens of thousands of characters are required. Instead of loading every single one of the characters you might need in your production GUI, each one is generated as needed.
So which method do you choose? Honestly, it depends. Runtime fonts are generally recommended if the size of the font engine and shaper code is less than the size of the generated glyphs font files. If these are equal, we recommend using the pre-rendered glyphs (the first method), because pre-rendered glyphs do not have the same CPU and RAM requirements of a runtime font engine. Also, in some special cases when the right rendering pipeline is used, pre-rendered glyphs will have smaller encoding and compression formats than the runtime option.
Another great way to save space on your hardware is to modify your .gen file for code generation to load only certain font ranges. If you have a design that uses a single font size or type only once in a splash screen, you can program your software to load only the ASCII English letters section with a Unicode font. This can save a lot of space on hardware!
In the example above, you can see how simple it is to manipulate a font range. In the first line, we’re loading only the character range [\32-\127]. In the second line, the character range is applied to a specific denoted font in the project. -Arial-medium-r-normal–_-170. This is the only font impacted so this font will have only the predetermined printable characters loaded to hardware. The third line applies the limit to all fonts of a certain family, the font above included. The %FONTRANGEFLAG% support ups to 1024 selections (1024 different bracketed ranges from the example), and those selections can be characters or character codes. These lines would not be used together in the same .gen file; it is just three single line examples.
Font optimization results
Please note that the following reflash file sizes apply to the very simple test designs for this article. The only way to know how they will affect your designs is to use these tests on your own GUI projects.
In Example A, you will see 13 different fonts. The second design, Example B, uses a single font. Example A has a reflash .bin file size of 73 kB. Example B utilizes only one font and does not include any bold or italics, has a .bin size of 24kB. When we generate code for Example B and use the %FONTRANGEFLAG% * [\32-~] in the .gen file, we get the .bin size down to 2kB!
It’s important to note that optimizations of this magnitude can impact the overall user experience of your GUI. Striking the right balance of design and memory usage is essential, so be sure to test early and often. Part of that testing may include understanding whether every font used in your design is necessary. Altia makes it easy to user test during development so that you can find that balance before you even get to hardware. Implementing any feedback is fast too!
Using font ranging can also make a huge difference in the .bin file size. This, too, must be done carefully. If you use a character in your GUI that isn’t included in the specified font range, you will get an error. Yet another reason to make testing part of your development process!
Finally, reducing your GUI design to a minimal number of fonts can provide incredible RAM savings. While it might not make sense to reduce your font usage to just one like we did in our example, this is an area where your design team can really make an impact on your memory usage.
There are many ways to help prevent designers from running into RAM space and CPU usage issues while designing high-quality GUIs for embedded devices. These font design techniques for embedded GUIs are just a few to consider.
Altia specializes in getting high-impact graphics onto the lowest possible hardware. Our GUI experts have powerful techniques for creating and implementing high-quality graphics with less time and effort. Feel free to request a demo with our team to discuss how you can create exciting, rich GUIs for your memory-constrained hardware.