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 form of providing different sets of
fonts with your devices. 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 TypedTextId. This TypedTextId is used by the Widgets to
find the actual letters in the text. The Widgets will access the texts
through the touchgfx::Texts class in
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 or directly in the texts.xml
file and generate your
application.
Before we can draw the text 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 found in (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 in what order to write the letters.
In the above figure the TypedTextData table has pointers to three arrays. One for each language in the application. Each of the arrays have 3 elements, one for each text in the system. Each element 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, but the texts use different fonts (F1 or F2). The Fonts table has two pointers because two fonts are used 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 TouchGFX Designer or the xml document. 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 can be 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 binary font loaded by the application. The linked-in Font2 is hereafter not used by TouchGFX.
Note that nothing changed in the text tables. These still refer to the same fonts (F1 and F2) by index.
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/
.
The generated code will configure TouchGFX to use the empty font. The application is required to install the binary font at runtime.
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 the font data must be made available in addressable memory like RAM or QSPI flash (where it can be directly accessed through a pointer). Typically this involves copying the data from a file or block storage like emmc flash. This can also happen during production where the binary font is flashed to a predefined address in a memory-mapped flash.
When the application has loaded the binary font to memory (if not
available already), the application must create and install a
BinaryFont
object referring the data in TouchGFX. After this,
TouchGFX will use that font and not the compiled in font.
The binary font needs to be installed before it is used to draw the
text that refers to the font, but it does not need to be installed
immediately after booting. The
FrontendApplication::FrontendApplication(Model& m, FrontendHeap&
heap) constructor in FrontApplication.cpp
can be used to
install fonts. This constructor is executed once before anything is
drawn.
Fonts can also be installed in the setupScreen()
methods. This is
useful if you have a font that is only used in a specific screen. The
font can then be un-installed in tearDownScreen()
Here is an example of loading a binary font from a file-system to internal RAM:
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 the TypedTextDatabase
of TouchGFX.
After the call to setFont TouchGFX will use the binary font to draw text on the screen instead of the compiled in font (DEFAULT).
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.
Generating binary fonts in another project
In some cases you want to have both normal fonts and binary fonts in a project. For example you want to have English letters in a normal compiled-in font, but Chinese and Japanese characters in binary fonts for optional inclusion in the device. This setup is not configurable in TouchGFX Designer.
In this case it is advised to create two TouchGFX projects. In the first project (your normal application) you have all your application code and UI with normal fonts. In the second project you have only enough texts (or wildcard characters) to generate the binary fonts.
In the first project, you deselect "Binary font files". In the second project you select "Binary font files".
When you generate code in the second TouchGFX project the binary fonts are generated. The binary fonts can then be copied to the first project (in a folder of your convenience), and be used in the code as shown above.