Skip to main content

Binary Fonts

This section describes how to use binary fonts in TouchGFX. The first section contains some in-depth information about the font and text system in TouchGFX that can be benificial to understand when working with binary fonts. The second section explains how to use binary fonts.

Binary fonts can be used as an alternative to the traditional way of compiling and linking font information in to your application (the .cpp files in generated/fonts/src). The main advantages of this approach is to get a smaller application binary and get a flexibility in providing different sets of fonts with your device. For example you can pack the Chinese font with devices going to China, and the Japanese font with devices going there. The drawback of this approach is that the whole binary font needs to be loaded to RAM (or memory-mapped flash) which can be a problem if the font is large.

The main advantage of the normal principle of linking fonts into the application is that the application will always automatically contain the updated texts and typographies used in the application. This is very easy and safe to use. The disadvantage is that fonts can make the application big.

The Font and Text system classes

In the default configuration TouchGFX generates .cpp-files for all texts and fonts used in the application. These files are compiled and linked into the application together with the generated UI and your application code.

When you show a text on the UI with e.g. a TextArea, you reference the text with a TextId. This TextId is used by the Widgets to find the actual letters in the text. The Widgets will access the texts through the touchgfx::Texts class framework/include/touchgfx/Texts.hpp.

The Text class contains a pointer array with a pointer to a translation table for each language in the application. A translation table is in principle a collection of all strings used in that language:

Mapping texts to specific languages

This table allows TouchGFX to find a given text in the selected language.

The tables are regenerated whenever you change a text in TouchGFX Designer and generate your application.

Before we can draw on the screen we need to know which font to use for the text. This mapping between texts and fonts is controlled by the TypedTextDatabase class (generated/texts/include/texts/TypedTextDatabase.hpp).

In the texts tab in TouchGFX Designer you can specify a typography, writing order (Left-to-right or Right-to-left), and an alignment for each text (Left, Right, Center). The typography, order, and alignment can be different for each translation of the text. This information is compiled into a table specific for each language. This makes it easy for TouchGFX to find out what font to use for a given text, how to align it, and how to write it.

typography information is specific to a language

In the above figure the TypedTextData table has pointers to three arrays. One for each language in the application. Each of the arrays has 3 elements, one for each text in the system. Each elements describes a font, a reading order, and the alignment. We see that in this example the texts use the same font in the three languages. The Fonts table has two pointers because there are two fonts in the application.

When TouchGFX is about to draw a text on the screen, it looks up the TypedTextData for the given text. This data contains the font index, letter order (LTR/RTL), and the horizontal alignment (Left, Right, Center) of the text as specified in the Excel sheet. TouchGFX uses the font index in the TypedTextData (F1 or F2) to lookup the correct font for the text.

All this happens automatically when the fonts are compiled into your application.

Using Binary Fonts

When an application is using many letters in many different fonts the size of the application can grow substantially.

To relieve this problem TouchGFX allows applications to use binary fonts. These fonts are not linked into the application but are stored separately from the application as files. These files are loaded and provided to TouchGFX by the application at runtime. The application can e.g. load the font from an external storage like an sd-card or maybe download the font from the internet.

When the application has loaded the font, it can ask TouchGFX to install the Binary Font in the font system:

Installing a binary font in the font table

Here the built-in Font2 is replaced by the Binaryfont loaded by the application. The linked-in Font2 is hereafter not used by TouchGFX.

Configuring the Font converter to generate Binary Fonts

The font converter must be configured to generate binary fonts. This is easily done in TouchGFXDesigner. Go to the Config tab, select "Text Configuration", and click "Binary font files":

Selecting Binary Fonts

When you regenerate the code, TouchGFX will generate binary fonts in the generated/fonts/bin/ folder, and empty fonts in the normal files in generated/fonts/src/

Manual Configuration

If you are not using TouchGFX Designer you can still generate binary fonts. Change the option "binary_fonts" to "yes" in the text_configuration section in the application.config file in your project.

application.config
  "text_configuration": {
"remap": "yes",
"a4": "yes",
"binary_translations": "no",
"binary_fonts": "yes",
"framebuffer_bpp": "16"
}

When you generate assets the next time, the binary fonts will be in the generated/fonts/bin folder.

Installing the binary font

Before TouchGFX can use a binary font it must be copied from the file or other storage. The font must be made available in addressable memory like RAM or QSPI flash (where it can be accessed through a pointer).

When the application has loaded the binary font to memory, it can install the font in TouchGFX. Hereafter TouchGFX will use that font and not the compiled font. The binary needs to be installed before the text is used, but it does not need to be done immediately after booting. The FrontendApplication::FrontendApplication(Model& m, FrontendHeap& heap) constructor in FrontApplication.cpp can be used to install fonts. This constructor is executed before anything is drawn.

Here is an example:

FrontendApplication.cpp
//read the file into this array in internal RAM
uint8_t fontdata[10000];

//binary font object using the data
BinaryFont bf;

FrontendApplication::FrontendApplication(Model& m, FrontendHeap& heap)
: FrontendApplicationBase(m, heap)
{
//read the binary font from a file
FILE* font = fopen("generated/fonts/bin/Font_verdana_20_4bpp.bin", "rb");
if (font)
{
//read data from the file
fread(fontdata, 1, 10000, font);
fclose(font);

//initialize BinaryFont object in bf using placement new
new (&bf) BinaryFont((const struct touchgfx::BinaryFontData*)fontdata);

//replace application font 'DEFAULT' with the binary font
TypedTextDatabase::setFont(DEFAULT, &bf); //verdana_20_4bpp
}
}

The exact code for opening a file and reading data will depend on your file system and operating system. The basic steps are to make the font data available in memory, initialize a BinaryFont object with a pointer to the data, and finally pass the BinaryFont object to TouchGFX.

After the call to setFont TouchGFX will use the binary font to draw text on the screen.

Resetting a font

Sometimes you want to go back to the original font compiled into your application after using a binary font. For example if you are changing language, and want to use the default font. The resetFont() function in TypedTextDatabase will reset the font pointer to the built in font:

//reset to original font
TypedTextDatabase::resetFont(DEFAULT);

After this call, the application can reuse the memory occupied by the binary font to allocate a new font or for other purposes.