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 beneficial 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 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:
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.
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:
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 TouchGFX Designer. Go to the Config tab, select "Text Configuration", and click "Binary font files":
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. Now 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.