Font Manager

The font manager is a secondary encapsulation of the LVGL font engine, which facilitates the use and management of fonts for applications. The font management functions currently provided include:

  • Font resource reference counting (reduces repeated creation of font resources).

  • Font resource concatenation (font fallback).

  • Font resource recycling mechanism (buffers recently deleted font resources to reduce the time overhead of repeated creation).

Usage

Enable FreeType and Font Manager in lv_conf.h by setting the LV_USE_FONT_MANAGER macros to non-zero values, and configure LV_FONT_MANAGER_NAME_MAX_LEN to set the maximum length of the font name.

Initialize Font Manager

Use lv_font_manager_create() to create a font manager, where the recycle_cache_size() parameter is used to set the number of font recycling caches, which can improve font creation efficiency.

Use lv_font_manager_add_src_static() to add a mapping between font names and font resources to tell the font manager how to access the font resources. Note that if the font resource description structure is not statically allocated (for example, allocated from a local variable), use lv_font_manager_add_src() to add the resource. This function will copy the contents of the structure itself.

Use lv_font_manager_remove_src() to remove the font resource mapping.

It should be noted that the src parameter must strictly correspond to class_p. class_p will affect the way the font manager interprets src. If an incompatible parameter is passed, the program may fail. For currently supported font classes, please refer to the example code.

static lv_font_manager_t * g_font_manager = NULL;

void font_manager_init(void)
{
   /* Create font manager, with 8 fonts recycling buffers */
   g_font_manager = lv_font_manager_create(8);

   /* Add font path mapping to font manager */
   lv_font_manager_add_src_static(g_font_manager, "Lato-Regular", "./lvgl/examples/libs/freetype/Lato-Regular.ttf", &lv_freetype_font_class);

   char path[] = "/path/to/myfont.ttf";
   lv_font_manager_add_src(g_font_manager, "MyFont", path, &lv_freetype_font_class);
}

Create Font from Font Manager

The parameters will be passed to the font creation function of the font backend, such as lv_freetype_font_create() and lv_tiny_ttf_create_file(). The font backend will select the supported parameters by itself and ignore the unsupported parameters.

The font_family parameter can be filled with the names of multiple fonts (separated by ,) to achieve font concatenation (when the corresponding glyph is not found in a font file, it will automatically search from the next concatenated font).

static lv_font_t * g_font = NULL;

/* Create font from font manager */
lv_font_t * g_font = lv_font_manager_create_font(g_font_manager,
                                                 "Lato-Regular,MyFont",
                                                 LV_FREETYPE_FONT_RENDER_MODE_BITMAP,
                                                 24,
                                                 LV_FREETYPE_FONT_STYLE_NORMAL,
                                                 LV_FONT_KERNING_NONE);

/* Handle error case */
if(g_font == NULL) {
   g_font = (lv_font_t *)LV_FONT_DEFAULT;
}

/* Create label with the font */
lv_obj_t * label = lv_label_create(lv_screen_active());
lv_obj_set_style_text_font(label, g_font, 0);
lv_label_set_text(label, "Hello World!");

Delete Font

Use lv_font_manager_delete_font() to delete the font when it is no longer needed. The font manager will mark the font resource as a recyclable font so that it has the possibility of being more quickly created next time.

Note that you need to delete any Widgets that used the font first, and then delete the font to avoid accessing wild pointers.

/* Delete label and font */
lv_obj_delete(label);
lv_font_manager_delete_font(g_font_manager, g_font);
g_font = NULL;

Delete Font Manager

Use lv_font_manager_delete() to destroy the entire font manager. It should be noted that before destruction, it is necessary to ensure that the application has deleted all fonts using lv_font_manager_delete_font(). The font manager will check the reference status of all allocated fonts. If there are still fonts being referenced, the font manager will fail to be destroyed and the function will return false.

Example

Create FreeType Font

#include "../../lv_examples.h"
#if LV_USE_FONT_MANAGER && LV_USE_FREETYPE && LV_BUILD_EXAMPLES

#if LV_FREETYPE_USE_LVGL_PORT
    #define PATH_PREFIX "A:"
#else
    #define PATH_PREFIX "./"
#endif

static lv_font_manager_t * g_font_manager = NULL;

void lv_example_font_manager_1(void)
{
    /* Create font manager, with 8 fonts recycling buffers */
    g_font_manager = lv_font_manager_create(8);

    /* Add font path mapping to font manager */
    lv_font_manager_add_src_static(g_font_manager,
                                   "Lato-Regular",
                                   PATH_PREFIX "lvgl/examples/libs/freetype/Lato-Regular.ttf",
                                   &lv_freetype_font_class);

    /* Create font from font manager */
    lv_font_t * font = lv_font_manager_create_font(g_font_manager,
                                                   "Lato-Regular",
                                                   LV_FREETYPE_FONT_RENDER_MODE_BITMAP,
                                                   24,
                                                   LV_FREETYPE_FONT_STYLE_NORMAL,
                                                   LV_FONT_KERNING_NONE);

    if(!font) {
        LV_LOG_ERROR("Could not create font");
        return;
    }

    /* Create label with the font */
    lv_obj_t * label = lv_label_create(lv_screen_active());
    lv_obj_set_style_text_font(label, font, 0);
    lv_label_set_text(label, "Hello Font Manager!");
    lv_obj_center(label);
}

#else

void lv_example_font_manager_1(void)
{
    lv_obj_t * label = lv_label_create(lv_screen_active());
    lv_label_set_text(label, "Font Manager or FreeType is not enabled");
    lv_obj_center(label);
}

#endif

Create Font Family

#include "../../lv_examples.h"
#if LV_USE_FONT_MANAGER && LV_BUILD_EXAMPLES

#if defined(LV_FREETYPE_USE_LVGL_PORT) && LV_FREETYPE_USE_LVGL_PORT
    #define PATH_PREFIX "A:"
#else
    #define PATH_PREFIX "./"
#endif

static lv_font_manager_t * g_font_manager = NULL;

void lv_example_font_manager_2(void)
{
    /* Create font manager, with 8 fonts recycling buffers */
    g_font_manager = lv_font_manager_create(8);

#if LV_FONT_MONTSERRAT_14 && LV_FONT_MONTSERRAT_32

    /* Register built-in font sources */
    static lv_builtin_font_src_t builtin_font_src[3] = { 0 };
    builtin_font_src[0].font_p = &lv_font_montserrat_14;
    builtin_font_src[0].size = 14;
    builtin_font_src[1].font_p = &lv_font_montserrat_32;
    builtin_font_src[1].size = 32;

    /* IMPORTANT! Marking the end of the array */
    builtin_font_src[2].font_p = NULL;
    builtin_font_src[2].size = 0;

    lv_font_manager_add_src_static(g_font_manager,
                                   "Montserrat",
                                   builtin_font_src,
                                   &lv_builtin_font_class);
#endif

#if LV_USE_FREETYPE
    /* Register FreeType font source */
    lv_font_manager_add_src_static(g_font_manager,
                                   "NotoColorEmoji",
                                   PATH_PREFIX "lvgl/examples/libs/freetype/NotoColorEmoji-32.subset.ttf",
                                   &lv_freetype_font_class);
#endif

#if LV_USE_TINY_TTF && LV_TINY_TTF_FILE_SUPPORT
    /* Register TinyTTF font source */
    static const lv_tiny_ttf_font_src_t tiny_ttf_font_src = {
        .path = "A:lvgl/examples/libs/tiny_ttf/Ubuntu-Medium.ttf",
        .data = NULL,
        .data_size = 0,
        .cache_size = 0,
    };

    lv_font_manager_add_src_static(g_font_manager,
                                   "Ubuntu-Medium",
                                   &tiny_ttf_font_src,
                                   &lv_tiny_ttf_font_class);
#endif

    /* Create font from font manager */
    lv_font_t * font = lv_font_manager_create_font(g_font_manager,
                                                   "Ubuntu-Medium,NotoColorEmoji,Montserrat",
                                                   LV_FREETYPE_FONT_RENDER_MODE_BITMAP,
                                                   32,
                                                   LV_FREETYPE_FONT_STYLE_NORMAL,
                                                   LV_FONT_KERNING_NONE);

    if(!font) {
        LV_LOG_ERROR("Could not create font");
        return;
    }

    /* Create label with the font */
    lv_obj_t * label = lv_label_create(lv_screen_active());
    lv_obj_set_style_text_font(label, font, 0);
    lv_label_set_text(label, "Hello Font Manager! 😀 " LV_SYMBOL_OK);
    lv_obj_center(label);
}

#else

void lv_example_font_manager_2(void)
{
    lv_obj_t * label = lv_label_create(lv_screen_active());
    lv_label_set_text(label, "Font Manager is not enabled");
    lv_obj_center(label);
}

#endif

Create Custom Image Font

#include "../../lv_examples.h"
#if LV_USE_FONT_MANAGER && LV_USE_FREETYPE && LV_USE_IMGFONT && LV_BUILD_EXAMPLES

#if LV_FREETYPE_USE_LVGL_PORT
    #define PATH_PREFIX "A:"
#else
    #define PATH_PREFIX "./"
#endif

typedef struct {
    uint16_t match_size_min;
    uint16_t match_size_max;
    lv_imgfont_get_path_cb_t get_path_cb;
} imgfont_src_t;

static lv_font_manager_t * g_font_manager = NULL;

static const void * get_imgfont_path(const lv_font_t * font, uint32_t unicode, uint32_t unicode_next,
                                     int32_t * offset_y, void * user_data)
{
    LV_UNUSED(font);
    LV_UNUSED(unicode_next);
    LV_UNUSED(offset_y);
    LV_UNUSED(user_data);

    LV_IMAGE_DECLARE(emoji_F617);

    if(unicode == 0xF617) {
        return &emoji_F617;
    }

    return NULL;
}

static lv_font_t * imgfont_create_cb(const lv_font_info_t * info, const void * src)
{
    const imgfont_src_t * imgfont_src = src;

    if(info->size < imgfont_src->match_size_min
       || info->size > imgfont_src->match_size_max) {
        return NULL;
    }

    return lv_imgfont_create(info->size, imgfont_src->get_path_cb, NULL);
}

static void imgfont_delete_cb(lv_font_t * font)
{
    lv_imgfont_destroy(font);
}

static void * imgfont_dup_src_cb(const void * src)
{
    imgfont_src_t * imgfont_src = lv_malloc(sizeof(imgfont_src_t));
    LV_ASSERT_MALLOC(imgfont_src);
    lv_memcpy(imgfont_src, src, sizeof(imgfont_src_t));
    return imgfont_src;
}

static void imgfont_free_src_cb(void * src)
{
    lv_free(src);
}

static const lv_font_class_t imgfont_class = {
    .create_cb = imgfont_create_cb,
    .delete_cb = imgfont_delete_cb,
    .dup_src_cb = imgfont_dup_src_cb,
    .free_src_cb = imgfont_free_src_cb,
};

void lv_example_font_manager_3(void)
{
    /* Create font manager, with 8 fonts recycling buffers */
    g_font_manager = lv_font_manager_create(8);

    /* Add font path mapping to font manager */
    lv_font_manager_add_src_static(g_font_manager,
                                   "Lato-Regular",
                                   PATH_PREFIX "lvgl/examples/libs/freetype/Lato-Regular.ttf",
                                   &lv_freetype_font_class);

    /* Add custom imgfont source to font manager */
    static const imgfont_src_t imgfont_src = {
        .match_size_min = 70,
        .match_size_max = 80,
        .get_path_cb = get_imgfont_path,
    };
    lv_font_manager_add_src_static(g_font_manager,
                                   "Emoji",
                                   &imgfont_src,
                                   &imgfont_class);

    /* Create font from font manager */
    lv_font_t * font = lv_font_manager_create_font(g_font_manager,
                                                   "Lato-Regular,Emoji",
                                                   LV_FREETYPE_FONT_RENDER_MODE_BITMAP,
                                                   75,
                                                   LV_FREETYPE_FONT_STYLE_NORMAL,
                                                   LV_FONT_KERNING_NONE);

    if(!font) {
        LV_LOG_ERROR("Could not create font");
        return;
    }

    /* Create label with the font */
    lv_obj_t * label = lv_label_create(lv_screen_active());
    lv_obj_set_style_text_font(label, font, 0);
    lv_label_set_text(label, "Quiet\uF617~");
    lv_obj_center(label);
}

#else

void lv_example_font_manager_3(void)
{
    lv_obj_t * label = lv_label_create(lv_screen_active());
    lv_label_set_text(label, "Font Manager or Freetype or Imgfont is not enabled");
    lv_obj_center(label);
}

#endif

API

lv_font_manager.h

lv_font_manager_recycle.h