C

Qt Quick Ultralite font_quality Example

Demonstrates how to control font quality in an application.

Overview

This example demonstrates how to use the CMake and QML APIs to control font quality in an application. It shows how these APIs affect text rendering with optimal memory footprint.

The example's UI has multiple Text items rendered with different font quality settings.

Target platforms

Project structure

CMake project file

The example contains two executable targets that share the same QML code. These targets use different settings for the MCU.Config.autoGenerateGlyphs target property:

This setting affects the set of glyphs that are generated for each font.

Both are using MCU.Config.defaultFontQuality target property set to "VeryLow". This results in using low quality fonts by default, when not explicitly set using QML API. autoGenerateGlyphs enabled:

...
    MCU.Config {
        autoGenerateGlyphs: false
        defaultFontQuality: "VeryLow"
    }
...

autoGenerateGlyphs disabled:

...
        MCU.Config {
                autoGenerateGlyphs: true
                defaultFontQuality: "VeryLow"
        }
...
Application UI

The application UI is defined in font_quality.qml file. It uses two fonts, a lowQualityLatinFont font with default quality (which is set to "VeryLow"), and a highQualityDigits font with higher quality.

The low quality font has the font.unicodeCoverage set to BasicLatin unicode block.

readonly property font lowQualityLatinFont: Qt.font({
    pixelSize: 30,
    unicodeCoverage: [Font.UnicodeBlock_BasicLatin]
    // quality set Font.QualityVeryLow by defualy
    // using \l MCU.Config.defaultFontQuality QmlProject property
})

Whereas, the high quality font has the font.unicodeCoverage set to contain digits from 0 to 9 and the : colon character.

readonly property font highQualityDigits: Qt.font({
    pixelSize: 60,
    unicodeCoverage: [[0x30,0x3A]], // 0-9:
    quality: Font.QualityVeryHigh
})

Next, text items are created, one for rendering arbitrary low quality Latin text:

Text {
    anchors.horizontalCenter: parent.horizontalCenter
    id: lowQualityText
    font: lowQualityLatinFont
    text: "VeryLow 123"
}

Another for rendering the high quality digits:

Text {
    anchors.centerIn: parent
    font: highQualityDigits
    text: "13:59"
}

At the very end, a text that shows result of binding the text properties of these two Text items with different font qualities:

Text {
    anchors.horizontalCenter: parent.horizontalCenter
    anchors.bottom: parent.bottom
    font: highQualityDigits
    // Glyps may be missing if \l MCU.Config.autoGenerateGlyphs is set to \c false
    text: lowQualityText.text
}

Notice that the glyphs may be missing in this text item, depending on the MCU.Config.autoGenerateGlyphs property value. See Missing glyphs for more information.

Memory footprint

Font family combined with other font properties such as: weight, size, italics, and quality uniquely defines so called "font configuration".

Using font.unicodeCoverage affects the memory footprint and rendering output when used with the MCU.Config.autoGenerateGlyphs property.

By default, this property is set to ON and glyphs for all used characters in qml file are generated for every font configuration that is used by the application. This is convenient, as you don't need to check if all the glyphs are present, before creating bindings between the properties of Text items with different font configurations. This convinience comes at a cost, as it increases the binary size and the runtime memory footprint.

To optimize binary size and the footprint, you can set MCU.Config.autoGenerateGlyphs to OFF. This disables automatic generation of all the glyphs and relies on the font.unicodeCoverage setting to generate only the glyphs that are needed. This enusres that each font configuration gets glyphs based on the font.unicodeCoverage property, resulting in optimal memory footprint. Although it sounds simple, it requires careful application design to ensure that all font configurations contains all glyphs that are needed.

Note: The text items are rendered with place holder boxes for the missing glyphs, if the font.unicodeCoverage is not set to an appropriate value when MCU.Config.autoGenerateGlyphs is set to OFF.

Missing glyphs

Although setting MCU.Config.autoGenerateGlyphs to OFF and specifying font.unicodeCoverage for each font configuration results in an optimal binary size and lower memory footprint, you must carefully design your application.

Let's take a look at the QML code where low quality text is assigned to the high quality one:

Text {
    anchors.horizontalCenter: parent.horizontalCenter
    anchors.bottom: parent.bottom
    font: highQualityDigits
    // Glyps may be missing if \l MCU.Config.autoGenerateGlyphs is set to \c false
    text: lowQualityText.text
}

Although this is completely fine with MCU.Config.autoGenerateGlyphs set to ON, it will result in missing glyphs while rendering the texts with the auto-generation set to OFF.

You can see in the earlier image that highQualityDigits font contains only glyphs for characters with the font.unicodeCoverage specified (which are 0-9 and :). The glyphs needed for rending lowQualityText are not generated for this font configuration.

Files:

See also font.quality, MCU.Config.autoGenerateGlyphs, and MCU.config.defaultFontQuality.

Available under certain Qt licenses.
Find out more.