diff --git a/Kconfig b/Kconfig index 964b269d9b..3f999c6cf1 100644 --- a/Kconfig +++ b/Kconfig @@ -1656,8 +1656,7 @@ menu "LVGL configuration" This can save some memory, but not much. After the quick access bar is created, it can be hidden by clicking the button at the top left corner of the browsing area, which is very useful for small screen devices. config LV_USE_FONT_MANAGER - bool "Enable freetype font manager" - depends on LV_USE_FREETYPE + bool "Enable Font manager" default n config LV_FONT_MANAGER_NAME_MAX_LEN int "Font manager name max length" diff --git a/docs/src/details/auxiliary-modules/font_manager.rst b/docs/src/details/auxiliary-modules/font_manager.rst index 9d5698c327..4720debd16 100644 --- a/docs/src/details/auxiliary-modules/font_manager.rst +++ b/docs/src/details/auxiliary-modules/font_manager.rst @@ -4,9 +4,9 @@ Font Manager ============ -Font Manager is a secondary encapsulation of :ref:`freetype`, which provides -facilities for high-level applications to manage and use vector fonts. Currently -provided font-management functions includes: +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). @@ -21,7 +21,7 @@ Usage ***** Enable FreeType and Font Manager in ``lv_conf.h`` by setting the -:c:macro:`LV_USE_FREETYPE` and :c:macro:`LV_USE_FONT_MANAGER` macros to non-zero +:c:macro:`LV_USE_FONT_MANAGER` macros to non-zero values, and configure :c:macro:`LV_FONT_MANAGER_NAME_MAX_LEN` to set the maximum length of the font name. @@ -32,13 +32,17 @@ Use :cpp:func:`lv_font_manager_create` to create a font manager, where the :cpp:func:`recycle_cache_size` parameter is used to set the number of font recycling caches, which can improve font creation efficiency. -Use :cpp:func:`lv_font_manager_add_path_static` to add a mapping between the font -file path and the custom font name, so that the application can access the font -resources more conveniently. It should be noted that if the file path is not static -(assigned from a local variable), use :cpp:func:`lv_font_manager_add_path` to -add the path. This function will make its own copy of the string. +Use :cpp:func:`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 :cpp:func:`lv_font_manager_add_src` to add the resource. +This function will copy the contents of the structure itself. -Use :cpp:func:`lv_font_manager_remove_path` to remove the font path mapping. +Use :cpp:func:`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. .. code-block:: c @@ -50,15 +54,18 @@ Use :cpp:func:`lv_font_manager_remove_path` to remove the font path mapping. g_font_manager = lv_font_manager_create(8); /* Add font path mapping to font manager */ - lv_font_manager_add_path_static(g_font_manager, "Lato-Regular", "./lvgl/examples/libs/freetype/Lato-Regular.ttf"); - lv_font_manager_add_path_static(g_font_manager, "MyFont", "./path/to/myfont.ttf"); + 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 ----------------------------- -Use :cpp:func:`lv_font_manager_create_font` to create a font. The parameters are -basically the same as :cpp:func:`lv_freetype_font_create`. +The parameters will be passed to the font creation function of the font backend, +such as :cpp:func:`lv_freetype_font_create` and :cpp:func:`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 @@ -74,7 +81,13 @@ font). "Lato-Regular,MyFont", LV_FREETYPE_FONT_RENDER_MODE_BITMAP, 24, - LV_FREETYPE_FONT_STYLE_NORMAL); + 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()); diff --git a/env_support/cmsis-pack/LVGL.lvgl.pdsc b/env_support/cmsis-pack/LVGL.lvgl.pdsc index 94849c2a8a..6e77e90365 100644 --- a/env_support/cmsis-pack/LVGL.lvgl.pdsc +++ b/env_support/cmsis-pack/LVGL.lvgl.pdsc @@ -1766,7 +1766,7 @@ -/*! \brief Enable freetype font manager */ +/*! \brief Enable Font manager */ #define LV_USE_FONT_MANAGER 1 diff --git a/env_support/cmsis-pack/lv_conf_cmsis.h b/env_support/cmsis-pack/lv_conf_cmsis.h index e8929d4d1b..e10c53157a 100644 --- a/env_support/cmsis-pack/lv_conf_cmsis.h +++ b/env_support/cmsis-pack/lv_conf_cmsis.h @@ -1004,7 +1004,7 @@ #define LV_FILE_EXPLORER_QUICK_ACCESS 1 #endif -/** 1: Enable freetype font manager +/** 1: Enable Font manager * - Requires: LV_USE_FREETYPE */ #if LV_USE_FONT_MANAGER diff --git a/examples/others/font_manager/index.rst b/examples/others/font_manager/index.rst index da2f6a45ba..dc90443140 100644 --- a/examples/others/font_manager/index.rst +++ b/examples/others/font_manager/index.rst @@ -1,6 +1,18 @@ -Font manager example +Create FreeType Font -------------------- .. lv_example:: others/font_manager/lv_example_font_manager_1 :language: c + +Create Font Family +------------------ + +.. lv_example:: others/font_manager/lv_example_font_manager_2 + :language: c + +Create Custom Image Font +------------------------ + +.. lv_example:: others/font_manager/lv_example_font_manager_3 + :language: c diff --git a/examples/others/font_manager/lv_example_font_manager.h b/examples/others/font_manager/lv_example_font_manager.h index 44b4e6bea6..93b64db150 100644 --- a/examples/others/font_manager/lv_example_font_manager.h +++ b/examples/others/font_manager/lv_example_font_manager.h @@ -26,6 +26,8 @@ extern "C" { * GLOBAL PROTOTYPES **********************/ void lv_example_font_manager_1(void); +void lv_example_font_manager_2(void); +void lv_example_font_manager_3(void); /********************** * MACROS diff --git a/examples/others/font_manager/lv_example_font_manager_1.c b/examples/others/font_manager/lv_example_font_manager_1.c index 0b2985fc4e..c64777a500 100644 --- a/examples/others/font_manager/lv_example_font_manager_1.c +++ b/examples/others/font_manager/lv_example_font_manager_1.c @@ -1,5 +1,5 @@ #include "../../lv_examples.h" -#if LV_USE_FREETYPE && LV_USE_FONT_MANAGER && LV_BUILD_EXAMPLES +#if LV_USE_FONT_MANAGER && LV_USE_FREETYPE && LV_BUILD_EXAMPLES #if LV_FREETYPE_USE_LVGL_PORT #define PATH_PREFIX "A:" @@ -15,16 +15,18 @@ void lv_example_font_manager_1(void) g_font_manager = lv_font_manager_create(8); /* Add font path mapping to font manager */ - lv_font_manager_add_path_static(g_font_manager, - "Lato-Regular", - PATH_PREFIX "lvgl/examples/libs/freetype/Lato-Regular.ttf"); + 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_FREETYPE_FONT_STYLE_NORMAL, + LV_FONT_KERNING_NONE); if(!font) { LV_LOG_ERROR("Could not create font"); @@ -43,7 +45,7 @@ void lv_example_font_manager_1(void) void lv_example_font_manager_1(void) { lv_obj_t * label = lv_label_create(lv_screen_active()); - lv_label_set_text(label, "FreeType or font_manager is not enabled"); + lv_label_set_text(label, "Font Manager or FreeType is not enabled"); lv_obj_center(label); } diff --git a/examples/others/font_manager/lv_example_font_manager_2.c b/examples/others/font_manager/lv_example_font_manager_2.c new file mode 100644 index 0000000000..4a5f36f880 --- /dev/null +++ b/examples/others/font_manager/lv_example_font_manager_2.c @@ -0,0 +1,88 @@ +#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 diff --git a/examples/others/font_manager/lv_example_font_manager_3.c b/examples/others/font_manager/lv_example_font_manager_3.c new file mode 100644 index 0000000000..af7a6d9ec4 --- /dev/null +++ b/examples/others/font_manager/lv_example_font_manager_3.c @@ -0,0 +1,123 @@ +#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 diff --git a/lv_conf_template.h b/lv_conf_template.h index 6f5b82ced5..b2742d1154 100644 --- a/lv_conf_template.h +++ b/lv_conf_template.h @@ -1117,8 +1117,7 @@ #define LV_FILE_EXPLORER_QUICK_ACCESS 1 #endif -/** 1: Enable freetype font manager - * - Requires: LV_USE_FREETYPE */ +/** 1: Enable Font manager */ #define LV_USE_FONT_MANAGER 0 #if LV_USE_FONT_MANAGER diff --git a/src/font/lv_binfont_loader.c b/src/font/lv_binfont_loader.c index 4746026f52..a39e2bc642 100644 --- a/src/font/lv_binfont_loader.c +++ b/src/font/lv_binfont_loader.c @@ -69,10 +69,26 @@ int32_t load_kern(lv_fs_file_t * fp, lv_font_fmt_txt_dsc_t * font_dsc, uint8_t f static int read_bits_signed(bit_iterator_t * it, int n_bits, lv_fs_res_t * res); static unsigned int read_bits(bit_iterator_t * it, int n_bits, lv_fs_res_t * res); +static lv_font_t * binfont_font_create_cb(const lv_font_info_t * info, const void * src); +static void binfont_font_delete_cb(lv_font_t * font); +static void * binfont_font_dup_src_cb(const void * src); +static void binfont_font_free_src_cb(void * src); + /********************** * MACROS **********************/ +/********************** + * GLOBAL VARIABLES + **********************/ + +const lv_font_class_t lv_binfont_font_class = { + .create_cb = binfont_font_create_cb, + .delete_cb = binfont_font_delete_cb, + .dup_src_cb = binfont_font_dup_src_cb, + .free_src_cb = binfont_font_free_src_cb, +}; + /********************** * GLOBAL FUNCTIONS **********************/ @@ -656,3 +672,53 @@ int32_t load_kern(lv_fs_file_t * fp, lv_font_fmt_txt_dsc_t * font_dsc, uint8_t f return kern_length; } + +static lv_font_t * binfont_font_create_cb(const lv_font_info_t * info, const void * src) +{ + const lv_binfont_font_src_t * font_src = src; + + if(info->size == font_src->font_size) { + if(font_src->path) { + return lv_binfont_create(font_src->path); + } +#if LV_USE_FS_MEMFS + return lv_binfont_create_from_buffer((void *)font_src->buffer, font_src->buffer_size); +#else + LV_LOG_WARN("LV_USE_FS_MEMFS not enabled"); + return NULL; +#endif + } + + return NULL; +} + +static void binfont_font_delete_cb(lv_font_t * font) +{ + lv_binfont_destroy(font); +} + +static void * binfont_font_dup_src_cb(const void * src) +{ + const lv_binfont_font_src_t * font_src = src; + + lv_binfont_font_src_t * new_src = lv_malloc_zeroed(sizeof(lv_binfont_font_src_t)); + LV_ASSERT_MALLOC(new_src); + *new_src = *font_src; + + if(font_src->path) { + new_src->path = lv_strdup(font_src->path); + } + + return new_src; +} + +static void binfont_font_free_src_cb(void * src) +{ + lv_binfont_font_src_t * font_src = src; + if(font_src->path) { + lv_free((char *)font_src->path); + font_src->path = NULL; + } + + lv_free(font_src); +} diff --git a/src/font/lv_binfont_loader.h b/src/font/lv_binfont_loader.h index 25e7b83747..a8b447dd2b 100644 --- a/src/font/lv_binfont_loader.h +++ b/src/font/lv_binfont_loader.h @@ -22,6 +22,16 @@ extern "C" { * TYPEDEFS **********************/ + +typedef struct { + uint32_t font_size; /**< Size of the font in pixels*/ + const char * path; /**< Path to font file*/ + const void * buffer; /**< Address of the font file in the memory*/ + uint32_t buffer_size; /**< Size of the font file buffer*/ +} lv_binfont_font_src_t; + +LV_ATTRIBUTE_EXTERN_DATA extern const lv_font_class_t lv_binfont_font_class; + /********************** * GLOBAL PROTOTYPES **********************/ diff --git a/src/font/lv_font.c b/src/font/lv_font.c index a509621cc0..28e7ea2160 100644 --- a/src/font/lv_font.c +++ b/src/font/lv_font.c @@ -154,6 +154,20 @@ const lv_font_t * lv_font_get_default(void) return LV_FONT_DEFAULT; } +bool lv_font_info_is_equal(const lv_font_info_t * ft_info_1, const lv_font_info_t * ft_info_2) +{ + LV_ASSERT_NULL(ft_info_1); + LV_ASSERT_NULL(ft_info_2); + + bool is_equal = (ft_info_1->size == ft_info_2->size + && ft_info_1->style == ft_info_2->style + && ft_info_1->render_mode == ft_info_2->render_mode + && ft_info_1->kerning == ft_info_2->kerning + && lv_strcmp(ft_info_1->name, ft_info_2->name) == 0); + + return is_equal; +} + /********************** * STATIC FUNCTIONS **********************/ diff --git a/src/font/lv_font.h b/src/font/lv_font.h index fa2d9311c2..1c8f17d4fd 100644 --- a/src/font/lv_font.h +++ b/src/font/lv_font.h @@ -120,6 +120,22 @@ struct _lv_font_t { void * user_data; /**< Custom user data for font.*/ }; +struct _lv_font_class_t { + lv_font_t * (*create_cb)(const lv_font_info_t * info, const void * src); /**< Font creation callback function*/ + void (*delete_cb)(lv_font_t * font); /**< Font deletion callback function*/ + void * (*dup_src_cb)(const void * src); /**< Font source duplication callback function*/ + void (*free_src_cb)(void * src); /**< Font source free callback function*/ +}; + +struct _lv_font_info_t { + const char * name; /**< Font name, used to distinguish different font resources*/ + const lv_font_class_t * class_p; /**< Font backend implementation*/ + uint32_t size; /**< Font size in pixel*/ + uint32_t render_mode; /**< Font rendering mode, see `lv_freetype_font_render_mode_t`*/ + uint32_t style; /**< Font style, see `lv_freetype_font_style_t`*/ + lv_font_kerning_t kerning; /**< Font kerning, see `lv_font_kerning_t`*/ +}; + /********************** * GLOBAL PROTOTYPES **********************/ @@ -181,6 +197,14 @@ void lv_font_set_kerning(lv_font_t * font, lv_font_kerning_t kerning); */ const lv_font_t * lv_font_get_default(void); +/** + * Compare font information. + * @param ft_info_1 font information 1. + * @param ft_info_2 font information 2. + * @return return true if the fonts are equal. + */ +bool lv_font_info_is_equal(const lv_font_info_t * ft_info_1, const lv_font_info_t * ft_info_2); + /********************** * MACROS **********************/ diff --git a/src/font/lv_font_fmt_txt.c b/src/font/lv_font_fmt_txt.c index 53a927439f..100da39843 100644 --- a/src/font/lv_font_fmt_txt.c +++ b/src/font/lv_font_fmt_txt.c @@ -47,6 +47,11 @@ static int kern_pair_16_compare(const void * ref, const void * element); static inline uint8_t rle_next(void); #endif /*LV_USE_FONT_COMPRESSED*/ +static lv_font_t * builtin_font_create_cb(const lv_font_info_t * info, const void * src); +static void builtin_font_delete_cb(lv_font_t * font); +static void * builtin_font_dup_src_cb(const void * src); +static void builtin_font_free_src_cb(void * src); + /********************** * STATIC VARIABLES **********************/ @@ -63,6 +68,13 @@ static const uint8_t opa3_table[8] = {0, 36, 73, 109, 146, 182, 218, 255}; static const uint8_t opa2_table[4] = {0, 85, 170, 255}; +const lv_font_class_t lv_builtin_font_class = { + .create_cb = builtin_font_create_cb, + .delete_cb = builtin_font_delete_cb, + .dup_src_cb = builtin_font_dup_src_cb, + .free_src_cb = builtin_font_free_src_cb, +}; + /********************** * GLOBAL PROTOTYPES **********************/ @@ -598,3 +610,61 @@ static int unicode_list_compare(const void * ref, const void * element) { return (*(uint16_t *)ref) - (*(uint16_t *)element); } + +static lv_font_t * builtin_font_create_cb(const lv_font_info_t * info, const void * src) +{ + const lv_builtin_font_src_t * font_src = src; + + /** + * If a crash occurs here, please check whether the last font in + * the lv_builtin_font_src array is set to NULL as required to mark the end of the array. + */ + while(font_src->font_p) { + if(info->size == font_src->size) { + return (lv_font_t *)font_src->font_p; + } + font_src++; + } + + LV_LOG_WARN("No built-in font found with size: %" LV_PRIu32, info->size); + return NULL; +} + +static void builtin_font_delete_cb(lv_font_t * font) +{ + /*Nothing to delete*/ + LV_UNUSED(font); +} + +static void * builtin_font_dup_src_cb(const void * src) +{ + const lv_builtin_font_src_t * font_src = src; + uint32_t len = 0; + + /*Measure the size of the source data*/ + + /** + * If a crash occurs here, please check whether the last font in + * the lv_builtin_font_src array is set to NULL as required to mark the end of the array. + */ + while(font_src->font_p) { + len++; + font_src++; + } + + if(len == 0) { + LV_LOG_WARN("No source data found"); + return NULL; + } + + lv_builtin_font_src_t * new_src = lv_malloc_zeroed(sizeof(lv_builtin_font_src_t) * (len + 1)); + LV_ASSERT_MALLOC(new_src); + lv_memcpy(new_src, src, sizeof(lv_builtin_font_src_t) * len); + + return new_src; +} + +static void builtin_font_free_src_cb(void * src) +{ + lv_free(src); +} diff --git a/src/font/lv_font_fmt_txt.h b/src/font/lv_font_fmt_txt.h index f534b8abe5..41ad164590 100644 --- a/src/font/lv_font_fmt_txt.h +++ b/src/font/lv_font_fmt_txt.h @@ -186,6 +186,13 @@ typedef struct { uint16_t bitmap_format : 2; } lv_font_fmt_txt_dsc_t; +typedef struct { + const lv_font_t * font_p; /**< Pointer to built-in font*/ + uint32_t size; /** < Size of the built-in font*/ +} lv_builtin_font_src_t; + +LV_ATTRIBUTE_EXTERN_DATA extern const lv_font_class_t lv_builtin_font_class; + /********************** * GLOBAL PROTOTYPES **********************/ diff --git a/src/libs/freetype/lv_freetype.c b/src/libs/freetype/lv_freetype.c index c6edfb8079..9a33823048 100755 --- a/src/libs/freetype/lv_freetype.c +++ b/src/libs/freetype/lv_freetype.c @@ -50,10 +50,23 @@ static bool cache_node_cache_create_cb(lv_freetype_cache_node_t * node, void * u static void cache_node_cache_free_cb(lv_freetype_cache_node_t * node, void * user_data); static lv_cache_compare_res_t cache_node_cache_compare_cb(const lv_freetype_cache_node_t * lhs, const lv_freetype_cache_node_t * rhs); + +static lv_font_t * freetype_font_create_cb(const lv_font_info_t * info, const void * src); +static void freetype_font_delete_cb(lv_font_t * font); +static void * freetype_font_dup_src_cb(const void * src); +static void freetype_font_free_src_cb(void * src); + /********************** * STATIC VARIABLES **********************/ +const lv_font_class_t lv_freetype_font_class = { + .create_cb = freetype_font_create_cb, + .delete_cb = freetype_font_delete_cb, + .dup_src_cb = freetype_font_dup_src_cb, + .free_src_cb = freetype_font_free_src_cb, +}; + /********************** * MACROS **********************/ @@ -415,4 +428,24 @@ static lv_cache_compare_res_t cache_node_cache_compare_cb(const lv_freetype_cach return 0; } +static lv_font_t * freetype_font_create_cb(const lv_font_info_t * info, const void * src) +{ + return lv_freetype_font_create(src, info->render_mode, info->size, info->style); +} + +static void freetype_font_delete_cb(lv_font_t * font) +{ + lv_freetype_font_delete(font); +} + +static void * freetype_font_dup_src_cb(const void * src) +{ + return lv_strdup(src); +} + +static void freetype_font_free_src_cb(void * src) +{ + lv_free(src); +} + #endif /*LV_USE_FREETYPE*/ diff --git a/src/libs/freetype/lv_freetype.h b/src/libs/freetype/lv_freetype.h index 3bade7dbd6..48b071d502 100755 --- a/src/libs/freetype/lv_freetype.h +++ b/src/libs/freetype/lv_freetype.h @@ -61,6 +61,11 @@ typedef enum { LV_FREETYPE_OUTLINE_BORDER_START, /* When line width > 0 the border glyph is drawn after the regular glyph */ } lv_freetype_outline_type_t; +/* Only path string is required */ +typedef const char lv_freetype_font_src_t; + +LV_ATTRIBUTE_EXTERN_DATA extern const lv_font_class_t lv_freetype_font_class; + /********************** * GLOBAL PROTOTYPES **********************/ diff --git a/src/libs/tiny_ttf/lv_tiny_ttf.c b/src/libs/tiny_ttf/lv_tiny_ttf.c index e19e95606a..434584ea9c 100644 --- a/src/libs/tiny_ttf/lv_tiny_ttf.c +++ b/src/libs/tiny_ttf/lv_tiny_ttf.c @@ -104,10 +104,23 @@ static lv_cache_compare_res_t tiny_ttf_draw_data_cache_compare_cb(const tiny_ttf const tiny_ttf_cache_data_t * rhs); static void lv_tiny_ttf_cache_create(ttf_font_desc_t * dsc); + +static lv_font_t * tiny_ttf_font_create_cb(const lv_font_info_t * info, const void * src); +static void tiny_ttf_font_delete_cb(lv_font_t * font); +static void * tiny_ttf_font_dup_src_cb(const void * src); +static void tiny_ttf_font_free_src_cb(void * src); + /********************** * GLOBAL VARIABLES **********************/ +const lv_font_class_t lv_tiny_ttf_font_class = { + .create_cb = tiny_ttf_font_create_cb, + .delete_cb = tiny_ttf_font_delete_cb, + .dup_src_cb = tiny_ttf_font_dup_src_cb, + .free_src_cb = tiny_ttf_font_free_src_cb, +}; + /********************** * STATIC VARIABLES **********************/ @@ -556,4 +569,59 @@ static lv_cache_compare_res_t tiny_ttf_draw_data_cache_compare_cb(const tiny_ttf return 0; } +static lv_font_t * tiny_ttf_font_create_cb(const lv_font_info_t * info, const void * src) +{ + const lv_tiny_ttf_font_src_t * font_src = src; + + if(font_src->path) { +#if LV_TINY_TTF_FILE_SUPPORT + if(font_src->cache_size) { + return lv_tiny_ttf_create_file_ex(font_src->path, info->size, info->kerning, font_src->cache_size); + } + + return lv_tiny_ttf_create_file(font_src->path, info->size); +#else + LV_LOG_WARN("LV_TINY_TTF_FILE_SUPPORT not enabled"); + return NULL; +#endif + } + + if(font_src->cache_size) { + return lv_tiny_ttf_create_data_ex(font_src->data, font_src->data_size, info->size, info->kerning, font_src->cache_size); + } + + return lv_tiny_ttf_create_data(font_src->data, font_src->data_size, info->size); +} + +static void tiny_ttf_font_delete_cb(lv_font_t * font) +{ + lv_tiny_ttf_destroy(font); +} + +static void * tiny_ttf_font_dup_src_cb(const void * src) +{ + const lv_tiny_ttf_font_src_t * font_src = src; + + lv_tiny_ttf_font_src_t * new_src = lv_malloc_zeroed(sizeof(lv_tiny_ttf_font_src_t)); + LV_ASSERT_MALLOC(new_src); + *new_src = *font_src; + + if(font_src->path) { + new_src->path = lv_strdup(font_src->path); + } + + return new_src; +} + +static void tiny_ttf_font_free_src_cb(void * src) +{ + lv_tiny_ttf_font_src_t * font_src = src; + if(font_src->path) { + lv_free((char *)font_src->path); + font_src->path = NULL; + } + + lv_free(font_src); +} + #endif diff --git a/src/libs/tiny_ttf/lv_tiny_ttf.h b/src/libs/tiny_ttf/lv_tiny_ttf.h index b6e7dc0a8e..09910bca97 100644 --- a/src/libs/tiny_ttf/lv_tiny_ttf.h +++ b/src/libs/tiny_ttf/lv_tiny_ttf.h @@ -25,6 +25,15 @@ extern "C" { * TYPEDEFS **********************/ +typedef struct { + const char * path; /**< Path to the font file*/ + const void * data; /**< Pointer to the font data*/ + size_t data_size; /**< Size of the font data*/ + size_t cache_size; /**< Size of the font cache*/ +} lv_tiny_ttf_font_src_t; + +LV_ATTRIBUTE_EXTERN_DATA extern const lv_font_class_t lv_tiny_ttf_font_class; + /********************** * GLOBAL PROTOTYPES **********************/ diff --git a/src/lv_conf_internal.h b/src/lv_conf_internal.h index 5f2738b64f..671f17b551 100644 --- a/src/lv_conf_internal.h +++ b/src/lv_conf_internal.h @@ -3550,8 +3550,7 @@ #endif #endif -/** 1: Enable freetype font manager - * - Requires: LV_USE_FREETYPE */ +/** 1: Enable Font manager */ #ifndef LV_USE_FONT_MANAGER #ifdef CONFIG_LV_USE_FONT_MANAGER #define LV_USE_FONT_MANAGER CONFIG_LV_USE_FONT_MANAGER diff --git a/src/misc/lv_types.h b/src/misc/lv_types.h index 03a7c19c61..88656c73b6 100644 --- a/src/misc/lv_types.h +++ b/src/misc/lv_types.h @@ -116,6 +116,10 @@ typedef struct _lv_theme_t lv_theme_t; typedef struct _lv_anim_t lv_anim_t; typedef struct _lv_font_t lv_font_t; +typedef struct _lv_font_class_t lv_font_class_t; +typedef struct _lv_font_info_t lv_font_info_t; + +typedef struct _lv_font_manager_t lv_font_manager_t; typedef struct _lv_image_decoder_t lv_image_decoder_t; diff --git a/src/others/font_manager/lv_font_manager.c b/src/others/font_manager/lv_font_manager.c index 4fd0318d31..525b5a09be 100755 --- a/src/others/font_manager/lv_font_manager.c +++ b/src/others/font_manager/lv_font_manager.c @@ -12,8 +12,8 @@ #if LV_USE_FONT_MANAGER #include "lv_font_manager_recycle.h" -#include "lv_font_manager_utils.h" -#include "../../lvgl.h" +#include "../../misc/lv_ll.h" +#include "../../stdlib/lv_sprintf.h" /********************* * DEFINES @@ -28,16 +28,16 @@ /* font manager object */ struct _lv_font_manager_t { - lv_ll_t refer_ll; /* freetype font record list */ + lv_ll_t refer_ll; /* font reference list */ lv_ll_t rec_ll; /* lvgl font record list */ - lv_ll_t path_ll; /* font path record list */ + lv_ll_t src_ll; /* font src record list */ lv_font_manager_recycle_t * recycle_manager; }; -/* freetype font reference node */ +/* font reference node */ typedef struct _lv_font_refer_node_t { - lv_font_t * font_p; /* lv_freetype gen font */ - lv_freetype_info_t ft_info; /* freetype font info */ + lv_font_t * font_p; + lv_font_info_t ft_info; char name[LV_FONT_MANAGER_NAME_MAX_LEN]; /* name buffer */ int ref_cnt; /* reference count */ } lv_font_refer_node_t; @@ -45,36 +45,37 @@ typedef struct _lv_font_refer_node_t { /* lvgl font record node */ typedef struct _lv_font_rec_node_t { lv_font_t font; /* lvgl font info */ - const lv_font_refer_node_t * refer_node_p; /* referenced freetype resource */ + const lv_font_refer_node_t * refer_node_p; /* referenced font resource */ } lv_font_rec_node_t; -typedef struct _lv_font_path_t { +typedef struct _lv_font_src_t { char * name; - char * path; + void * src; bool is_static; -} lv_font_path_t; + const lv_font_class_t * class_p; +} lv_font_src_t; /********************** * STATIC PROTOTYPES **********************/ -static const char * lv_font_manager_get_path(lv_font_manager_t * manager, const char * name); +static lv_font_src_t * lv_font_manager_get_src(lv_font_manager_t * manager, const char * name); static bool lv_font_manager_check_resource(lv_font_manager_t * manager); static lv_font_rec_node_t * lv_font_manager_search_rec_node(lv_font_manager_t * manager, lv_font_t * font); -static const lv_font_refer_node_t * lv_font_manager_get_freetype_font(lv_font_manager_t * manager, - const lv_freetype_info_t * ft_info); -static bool lv_font_manager_reset_freetype_font(lv_font_manager_t * manager, const lv_font_refer_node_t * node); +static const lv_font_refer_node_t * lv_font_manager_get_font(lv_font_manager_t * manager, + const lv_font_info_t * ft_info); +static bool lv_font_manager_drop_font(lv_font_manager_t * manager, const lv_font_refer_node_t * node); -static lv_font_t * lv_font_manager_create_font_single(lv_font_manager_t * manager, const lv_freetype_info_t * ft_info); +static lv_font_t * lv_font_manager_create_font_single(lv_font_manager_t * manager, const lv_font_info_t * ft_info); static bool lv_font_manager_delete_font_single(lv_font_manager_t * manager, lv_font_t * font); -static lv_font_t * lv_font_manager_create_font_family(lv_font_manager_t * manager, const lv_freetype_info_t * ft_info); +static lv_font_t * lv_font_manager_create_font_family(lv_font_manager_t * manager, const lv_font_info_t * ft_info); static void lv_font_manager_delete_font_family(lv_font_manager_t * manager, lv_font_t * font); -static void lv_font_manager_add_path_core(lv_font_manager_t * manager, const char * name, const char * path, - bool is_static); +static bool lv_font_manager_add_src_core(lv_font_manager_t * manager, const char * name, const char * path, + const lv_font_class_t * class_p, bool is_static); /********************** * STATIC VARIABLES @@ -96,7 +97,7 @@ lv_font_manager_t * lv_font_manager_create(uint32_t recycle_cache_size) lv_ll_init(&manager->refer_ll, sizeof(lv_font_refer_node_t)); lv_ll_init(&manager->rec_ll, sizeof(lv_font_rec_node_t)); - lv_ll_init(&manager->path_ll, sizeof(lv_font_path_t)); + lv_ll_init(&manager->src_ll, sizeof(lv_font_src_t)); manager->recycle_manager = lv_font_manager_recycle_create(recycle_cache_size); @@ -118,17 +119,18 @@ bool lv_font_manager_delete(lv_font_manager_t * manager) lv_font_manager_recycle_delete(manager->recycle_manager); /* clean path map */ - lv_font_path_t * font_path; - LV_LL_READ(&manager->path_ll, font_path) { - if(!font_path->is_static) { - lv_free(font_path->name); - lv_free(font_path->path); + lv_font_src_t * font_src; + LV_LL_READ(&manager->src_ll, font_src) { + LV_LOG_INFO("remove src: %s", font_src->name); + if(!font_src->is_static) { + lv_free(font_src->name); + font_src->class_p->free_src_cb(font_src->src); } - font_path->name = NULL; - font_path->path = NULL; + font_src->name = NULL; + font_src->src = NULL; } - lv_ll_clear(&manager->path_ll); + lv_ll_clear(&manager->src_ll); lv_free(manager); @@ -136,59 +138,67 @@ bool lv_font_manager_delete(lv_font_manager_t * manager) return true; } -void lv_font_manager_add_path(lv_font_manager_t * manager, const char * name, const char * path) +bool lv_font_manager_add_src(lv_font_manager_t * manager, + const char * name, + const void * src, + const lv_font_class_t * class_p) { - lv_font_manager_add_path_core(manager, name, path, false); + return lv_font_manager_add_src_core(manager, name, src, class_p, false); } -void lv_font_manager_add_path_static(lv_font_manager_t * manager, const char * name, const char * path) +bool lv_font_manager_add_src_static(lv_font_manager_t * manager, + const char * name, + const void * src, + const lv_font_class_t * class_p) { - lv_font_manager_add_path_core(manager, name, path, true); + return lv_font_manager_add_src_core(manager, name, src, class_p, true); } -bool lv_font_manager_remove_path(lv_font_manager_t * manager, const char * name) +bool lv_font_manager_remove_src(lv_font_manager_t * manager, const char * name) { - lv_font_path_t * font_path; - LV_LL_READ(&manager->path_ll, font_path) { - if(lv_strcmp(name, font_path->name) == 0) { - break; - } - } + LV_ASSERT_NULL(manager); + LV_ASSERT_NULL(name); - if(!font_path) { - LV_LOG_WARN("name: %s not found", name); + lv_font_src_t * font_src = lv_font_manager_get_src(manager, name); + if(!font_src) { + LV_LOG_WARN("src: %s not found", name); return false; } - lv_ll_remove(&manager->path_ll, font_path); + lv_ll_remove(&manager->src_ll, font_src); - if(!font_path->is_static) { - lv_free(font_path->name); - lv_free(font_path->path); + if(!font_src->is_static) { + lv_free(font_src->name); + font_src->class_p->free_src_cb(font_src->src); } - font_path->name = NULL; - font_path->path = NULL; + font_src->name = NULL; + font_src->src = NULL; - lv_free(font_path); + lv_free(font_src); - LV_LOG_WARN("name: %s remove success", name); + LV_LOG_WARN("src: %s remove success", name); return true; } -lv_font_t * lv_font_manager_create_font(lv_font_manager_t * manager, const char * font_family, uint16_t render_mode, - uint32_t size, uint16_t style) +lv_font_t * lv_font_manager_create_font(lv_font_manager_t * manager, + const char * font_family, + uint32_t render_mode, + uint32_t size, + uint32_t style, + lv_font_kerning_t kerning) { LV_ASSERT_NULL(manager); LV_ASSERT_NULL(font_family); - lv_freetype_info_t ft_info; + lv_font_info_t ft_info; lv_memzero(&ft_info, sizeof(ft_info)); ft_info.name = font_family; ft_info.render_mode = render_mode; ft_info.size = size; ft_info.style = style; + ft_info.kerning = kerning; lv_font_t * ret_font; @@ -229,13 +239,12 @@ void lv_font_manager_delete_font(lv_font_manager_t * manager, lv_font_t * font) * STATIC FUNCTIONS **********************/ -static lv_font_t * lv_font_manager_create_font_single(lv_font_manager_t * manager, const lv_freetype_info_t * ft_info) +static lv_font_t * lv_font_manager_create_font_single(lv_font_manager_t * manager, const lv_font_info_t * ft_info) { LV_ASSERT_NULL(manager); LV_ASSERT_NULL(ft_info); - /* get freetype font */ - const lv_font_refer_node_t * refer_node = lv_font_manager_get_freetype_font(manager, ft_info); + const lv_font_refer_node_t * refer_node = lv_font_manager_get_font(manager, ft_info); if(!refer_node) { return NULL; } @@ -245,10 +254,10 @@ static lv_font_t * lv_font_manager_create_font_single(lv_font_manager_t * manage LV_ASSERT_MALLOC(rec_node); lv_memzero(rec_node, sizeof(lv_font_rec_node_t)); - /* copy freetype_font data */ + /* copy font data */ rec_node->font = *refer_node->font_p; - /* record reference freetype_font */ + /* record reference font */ rec_node->refer_node_p = refer_node; LV_LOG_INFO("success"); @@ -274,8 +283,7 @@ static bool lv_font_manager_delete_font_single(lv_font_manager_t * manager, lv_f return false; } - /* reset freetype font resource */ - bool retval = lv_font_manager_reset_freetype_font(manager, rec_node->refer_node_p); + bool retval = lv_font_manager_drop_font(manager, rec_node->refer_node_p); LV_ASSERT(retval); /* free rec_node */ @@ -304,7 +312,7 @@ static const char * strncpy_until(char * dest, const char * src, size_t n, char return src; } -static lv_font_t * lv_font_manager_create_font_family(lv_font_manager_t * manager, const lv_freetype_info_t * ft_info) +static lv_font_t * lv_font_manager_create_font_family(lv_font_manager_t * manager, const lv_font_info_t * ft_info) { LV_ASSERT_NULL(manager); LV_ASSERT_NULL(ft_info); @@ -316,7 +324,7 @@ static lv_font_t * lv_font_manager_create_font_family(lv_font_manager_t * manage LV_LOG_INFO("font-family: %s", family_str); char tmp_name[LV_FONT_MANAGER_NAME_MAX_LEN] = { 0 }; - lv_freetype_info_t tmp_ft_info = *ft_info; + lv_font_info_t tmp_ft_info = *ft_info; tmp_ft_info.name = tmp_name; while(1) { @@ -344,7 +352,7 @@ static lv_font_t * lv_font_manager_create_font_family(lv_font_manager_t * manage } if(*family_str != ',') { - LV_LOG_ERROR("font name buffer is too small, please increase FONT_NAME_MAX"); + LV_LOG_ERROR("font name buffer is too small, please increase LV_FONT_MANAGER_NAME_MAX_LEN"); break; } @@ -368,44 +376,50 @@ static void lv_font_manager_delete_font_family(lv_font_manager_t * manager, lv_f } } -static void lv_font_manager_add_path_core(lv_font_manager_t * manager, const char * name, const char * path, - bool is_static) +static bool lv_font_manager_add_src_core(lv_font_manager_t * manager, + const char * name, + const char * src, + const lv_font_class_t * class_p, + bool is_static) { LV_ASSERT_NULL(manager); LV_ASSERT_NULL(name); - LV_ASSERT_NULL(path); + LV_ASSERT_NULL(src); + LV_ASSERT_NULL(class_p); - const char * old_path = lv_font_manager_get_path(manager, name); - if(old_path) { - LV_LOG_WARN("name: %s, path: %s already exists", name, old_path); - return; + if(lv_font_manager_get_src(manager, name)) { + LV_LOG_WARN("name: %s already exists", name); + return false; } - lv_font_path_t * font_path = lv_ll_ins_tail(&manager->path_ll); - LV_ASSERT_MALLOC(font_path); - font_path->is_static = is_static; + lv_font_src_t * font_src = lv_ll_ins_tail(&manager->src_ll); + LV_ASSERT_MALLOC(font_src); + lv_memzero(font_src, sizeof(lv_font_src_t)); + font_src->is_static = is_static; + font_src->class_p = class_p; if(is_static) { - font_path->name = (char *)name; - font_path->path = (char *)path; + font_src->name = (char *)name; + font_src->src = (void *)src; } else { - font_path->name = lv_strdup(name); - LV_ASSERT_MALLOC(font_path->name); + font_src->name = lv_strdup(name); + LV_ASSERT_MALLOC(font_src->name); - font_path->path = lv_strdup(path); - LV_ASSERT_MALLOC(font_path->path); + font_src->src = font_src->class_p->dup_src_cb(src); + LV_ASSERT_NULL(font_src->src); } - LV_LOG_INFO("name: %s, path: %s add success", name, path); + LV_LOG_INFO("name: %s, src: %p add success", name, src); + return true; } -static const char * lv_font_manager_get_path(lv_font_manager_t * manager, const char * name) +static lv_font_src_t * lv_font_manager_get_src(lv_font_manager_t * manager, const char * name) { - lv_font_path_t * font_path; - LV_LL_READ(&manager->path_ll, font_path) { - if(lv_strcmp(name, font_path->name) == 0) { - return font_path->path; + lv_font_src_t * font_src; + LV_LL_READ(&manager->src_ll, font_src) { + if(lv_strcmp(name, font_src->name) == 0) { + return font_src; } } @@ -432,11 +446,11 @@ static bool lv_font_manager_check_resource(lv_font_manager_t * manager) } } - /* Check the recorded font resources created by freetype */ + /* Check the recorded font resources created by font creater */ lv_ll_t * refer_ll = &manager->refer_ll; uint32_t refer_ll_len = lv_ll_get_len(refer_ll); if(refer_ll_len) { - LV_LOG_WARN("freetype font resource[%" LV_PRIu32 "]:", refer_ll_len); + LV_LOG_WARN("font resource[%" LV_PRIu32 "]:", refer_ll_len); lv_font_refer_node_t * node; LV_LL_READ(refer_ll, node) { @@ -470,14 +484,14 @@ static lv_font_rec_node_t * lv_font_manager_search_rec_node(lv_font_manager_t * } static lv_font_refer_node_t * lv_font_manager_search_refer_node(lv_font_manager_t * manager, - const lv_freetype_info_t * ft_info) + const lv_font_info_t * ft_info) { LV_ASSERT_NULL(manager); LV_ASSERT_NULL(ft_info); lv_font_refer_node_t * refer_node; LV_LL_READ(&manager->refer_ll, refer_node) { - if(lv_freetype_info_is_equal(ft_info, &refer_node->ft_info)) { + if(lv_font_info_is_equal(ft_info, &refer_node->ft_info)) { LV_LOG_INFO("font: %s(%d) matched", ft_info->name, ft_info->size); return refer_node; } @@ -486,14 +500,14 @@ static lv_font_refer_node_t * lv_font_manager_search_refer_node(lv_font_manager_ return NULL; } -static lv_font_t * lv_font_manager_create_font_warpper(lv_font_manager_t * manager, const lv_freetype_info_t * ft_info) +static lv_font_t * lv_font_manager_create_font_wrapper(lv_font_manager_t * manager, const lv_font_info_t * ft_info) { LV_ASSERT_NULL(manager); LV_ASSERT_NULL(ft_info); lv_font_t * font; - /* create freetype font */ + /* create font */ font = lv_font_manager_recycle_get_reuse(manager->recycle_manager, ft_info); /* get reuse font from recycle */ @@ -503,16 +517,15 @@ static lv_font_t * lv_font_manager_create_font_warpper(lv_font_manager_t * manag /* cache miss */ - /* generate full file path */ - const char * path = lv_font_manager_get_path(manager, ft_info->name); - if(!path) { - LV_LOG_ERROR("name: %s not found path", ft_info->name); + const lv_font_src_t * font_src = lv_font_manager_get_src(manager, ft_info->name); + if(!font_src) { + LV_LOG_ERROR("name: %s not found src", ft_info->name); return NULL; } - font = lv_freetype_font_create(path, ft_info->render_mode, ft_info->size, ft_info->style); + font = font_src->class_p->create_cb(ft_info, font_src->src); if(!font) { - LV_LOG_ERROR("Freetype font init failed, name: %s, render_mode: %d, size: %d, style: %d", + LV_LOG_ERROR("font create failed, name: %s, render_mode: %d, size: %d, style: %d", ft_info->name, ft_info->render_mode, ft_info->size, ft_info->style); return NULL; } @@ -527,8 +540,8 @@ static void lv_font_manager_delete_font_warpper(lv_font_manager_t * manager, lv_ lv_font_manager_recycle_set_reuse(manager->recycle_manager, refer_node->font_p, &refer_node->ft_info); } -static const lv_font_refer_node_t * lv_font_manager_get_freetype_font(lv_font_manager_t * manager, - const lv_freetype_info_t * ft_info) +static const lv_font_refer_node_t * lv_font_manager_get_font(lv_font_manager_t * manager, + const lv_font_info_t * ft_info) { LV_ASSERT_NULL(manager); LV_ASSERT_NULL(ft_info); @@ -543,7 +556,7 @@ static const lv_font_refer_node_t * lv_font_manager_get_freetype_font(lv_font_ma /* not found refer_node, start to create font */ - lv_font_t * font = lv_font_manager_create_font_warpper(manager, ft_info); + lv_font_t * font = lv_font_manager_create_font_wrapper(manager, ft_info); if(!font) { return NULL; @@ -556,17 +569,21 @@ static const lv_font_refer_node_t * lv_font_manager_get_freetype_font(lv_font_ma lv_strncpy(refer_node->name, ft_info->name, sizeof(refer_node->name) - 1); + const lv_font_src_t * font_src = lv_font_manager_get_src(manager, ft_info->name); + LV_ASSERT_NULL(font_src); + /* copy font data */ refer_node->font_p = font; refer_node->ft_info = *ft_info; refer_node->ft_info.name = refer_node->name; + refer_node->ft_info.class_p = font_src->class_p; refer_node->ref_cnt = 1; LV_LOG_INFO("success"); return refer_node; } -static bool lv_font_manager_reset_freetype_font(lv_font_manager_t * manager, const lv_font_refer_node_t * node) +static bool lv_font_manager_drop_font(lv_font_manager_t * manager, const lv_font_refer_node_t * node) { LV_ASSERT_NULL(manager); LV_ASSERT_NULL(node); diff --git a/src/others/font_manager/lv_font_manager.h b/src/others/font_manager/lv_font_manager.h index b5e33b9fa0..5ba4ccc3e3 100755 --- a/src/others/font_manager/lv_font_manager.h +++ b/src/others/font_manager/lv_font_manager.h @@ -13,14 +13,10 @@ extern "C" { * INCLUDES *********************/ -#include "../../misc/lv_types.h" +#include "../../font/lv_font.h" #if LV_USE_FONT_MANAGER -#if !LV_USE_FREETYPE -#error "LV_USE_FONT_MANAGER requires LV_USE_FREETYPE" -#endif - /********************* * DEFINES *********************/ @@ -29,8 +25,6 @@ extern "C" { * TYPEDEFS **********************/ -typedef struct _lv_font_manager_t lv_font_manager_t; - /********************** * GLOBAL PROTOTYPES **********************/ @@ -50,40 +44,55 @@ lv_font_manager_t * lv_font_manager_create(uint32_t recycle_cache_size); bool lv_font_manager_delete(lv_font_manager_t * manager); /** - * Add the font file path. + * Add font resource. * @param manager pointer to main font manager. * @param name font name. - * @param path font file path. + * @param src font source. Need to strictly correspond to the font class. + * @param class_p font class. eg. lv_freetype_font_class, lv_builtin_font_class. + * @return return true if the add was successful. */ -void lv_font_manager_add_path(lv_font_manager_t * manager, const char * name, const char * path); +bool lv_font_manager_add_src(lv_font_manager_t * manager, + const char * name, + const void * src, + const lv_font_class_t * class_p); /** - * Add the font file path with static memory. + * Add font resource with static memory. * @param manager pointer to main font manager. - * @param name font name. - * @param path font file path. + * @param name font name. It cannot be a local variable. + * @param src font source. Need to strictly correspond to the font class. And it cannot be a local variable. + * @param class_p font class. E.g. lv_freetype_font_class, lv_builtin_font_class. + * @return return true if the add was successful. */ -void lv_font_manager_add_path_static(lv_font_manager_t * manager, const char * name, const char * path); +bool lv_font_manager_add_src_static(lv_font_manager_t * manager, + const char * name, + const void * src, + const lv_font_class_t * class_p); /** - * Remove the font file path. + * Remove font resource. * @param manager pointer to main font manager. * @param name font name. * @return return true if the remove was successful. */ -bool lv_font_manager_remove_path(lv_font_manager_t * manager, const char * name); +bool lv_font_manager_remove_src(lv_font_manager_t * manager, const char * name); /** * Create font. * @param manager pointer to main font manager. - * @param font_family font family name. - * @param render_mode font render mode, see lv_freetype_font_render_mode_t. - * @param size font size. - * @param style font style, see lv_freetype_font_style_t. - * @return point to the created font + * @param font_family font family name. Matches the font resource name, using commas to separate different names. E.g. "my_font_1,my_font_2". + * @param render_mode font render mode. see `lv_freetype_font_render_mode_t`. + * @param size font size in pixel. + * @param style font style. see `lv_freetype_font_style_t`. + * @param kerning kerning mode. see `lv_font_kerning_t`. + * @return point to the created font. */ -lv_font_t * lv_font_manager_create_font(lv_font_manager_t * manager, const char * font_family, uint16_t render_mode, - uint32_t size, uint16_t style); +lv_font_t * lv_font_manager_create_font(lv_font_manager_t * manager, + const char * font_family, + uint32_t render_mode, + uint32_t size, + uint32_t style, + lv_font_kerning_t kerning); /** * Delete font. diff --git a/src/others/font_manager/lv_font_manager_recycle.c b/src/others/font_manager/lv_font_manager_recycle.c index 38271f3211..87bafd90d6 100755 --- a/src/others/font_manager/lv_font_manager_recycle.c +++ b/src/others/font_manager/lv_font_manager_recycle.c @@ -11,7 +11,8 @@ #if LV_USE_FONT_MANAGER -#include "../../lvgl.h" +#include "../../font/lv_font.h" +#include "../../misc/lv_ll.h" /********************* * DEFINES @@ -27,7 +28,7 @@ struct _lv_font_manager_recycle_t { }; typedef struct { - lv_freetype_info_t ft_info; + lv_font_info_t ft_info; char name[LV_FONT_MANAGER_NAME_MAX_LEN]; lv_font_t * font; } lv_font_recycle_t; @@ -87,7 +88,7 @@ void lv_font_manager_recycle_delete(lv_font_manager_recycle_t * manager) LV_LOG_INFO("success"); } -lv_font_t * lv_font_manager_recycle_get_reuse(lv_font_manager_recycle_t * manager, const lv_freetype_info_t * ft_info) +lv_font_t * lv_font_manager_recycle_get_reuse(lv_font_manager_recycle_t * manager, const lv_font_info_t * ft_info) { LV_ASSERT_NULL(manager); LV_ASSERT_NULL(ft_info); @@ -99,7 +100,7 @@ lv_font_t * lv_font_manager_recycle_get_reuse(lv_font_manager_recycle_t * manage lv_font_recycle_t * recycle; LV_LL_READ(recycle_ll, recycle) { /* match font */ - if(lv_freetype_info_is_equal(ft_info, &recycle->ft_info)) { + if(lv_font_info_is_equal(ft_info, &recycle->ft_info)) { lv_font_t * font = recycle->font; LV_LOG_INFO("found font: %p", (void *)font); @@ -116,7 +117,7 @@ lv_font_t * lv_font_manager_recycle_get_reuse(lv_font_manager_recycle_t * manage } void lv_font_manager_recycle_set_reuse(lv_font_manager_recycle_t * manager, lv_font_t * font, - const lv_freetype_info_t * ft_info) + const lv_font_info_t * ft_info) { LV_ASSERT_NULL(manager); LV_ASSERT_NULL(ft_info); @@ -124,7 +125,7 @@ void lv_font_manager_recycle_set_reuse(lv_font_manager_recycle_t * manager, lv_f lv_ll_t * recycle_ll = &manager->recycle_ll; /* check recycled size */ - if(_lv_ll_get_len(recycle_ll) >= manager->max_size) { + if(lv_ll_get_len(recycle_ll) >= manager->max_size) { LV_LOG_INFO("recycle full, remove tail font..."); lv_font_manager_recycle_remove_tail(manager); } @@ -154,7 +155,8 @@ static void lv_font_recycle_close(lv_font_manager_recycle_t * manager, lv_font_r LV_ASSERT_NULL(recycle); LV_LOG_INFO("font: %s(%d) close", recycle->ft_info.name, recycle->ft_info.size); - lv_freetype_font_delete(recycle->font); + recycle->ft_info.class_p->delete_cb(recycle->font); + recycle->font = NULL; lv_ll_remove(&manager->recycle_ll, recycle); lv_free(recycle); diff --git a/src/others/font_manager/lv_font_manager_recycle.h b/src/others/font_manager/lv_font_manager_recycle.h index 57d41ec437..58eb89474c 100755 --- a/src/others/font_manager/lv_font_manager_recycle.h +++ b/src/others/font_manager/lv_font_manager_recycle.h @@ -14,7 +14,7 @@ extern "C" { * INCLUDES *********************/ -#include "lv_font_manager_utils.h" +#include "../../misc/lv_types.h" #if LV_USE_FONT_MANAGER @@ -55,7 +55,7 @@ void lv_font_manager_recycle_delete(lv_font_manager_recycle_t * manager); * @param ft_info font info. * @return returns true on success. */ -lv_font_t * lv_font_manager_recycle_get_reuse(lv_font_manager_recycle_t * manager, const lv_freetype_info_t * ft_info); +lv_font_t * lv_font_manager_recycle_get_reuse(lv_font_manager_recycle_t * manager, const lv_font_info_t * ft_info); /** * Set fonts to be reused. @@ -63,7 +63,7 @@ lv_font_t * lv_font_manager_recycle_get_reuse(lv_font_manager_recycle_t * manage * @param ft_info font info. */ void lv_font_manager_recycle_set_reuse(lv_font_manager_recycle_t * manager, lv_font_t * font, - const lv_freetype_info_t * ft_info); + const lv_font_info_t * ft_info); /********************** * MACROS diff --git a/src/others/font_manager/lv_font_manager_utils.c b/src/others/font_manager/lv_font_manager_utils.c deleted file mode 100755 index efbeb89b8a..0000000000 --- a/src/others/font_manager/lv_font_manager_utils.c +++ /dev/null @@ -1,56 +0,0 @@ -/** - * @file lv_font_manager_utils.c - * - */ - -/********************* - * INCLUDES - *********************/ - -#include "lv_font_manager_utils.h" - -#if LV_USE_FONT_MANAGER -#include "../../misc/lv_assert.h" - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ - -/********************** - * STATIC PROTOTYPES - **********************/ - -/********************** - * STATIC VARIABLES - **********************/ - -/********************** - * MACROS - **********************/ - -/********************** - * GLOBAL FUNCTIONS - **********************/ - -bool lv_freetype_info_is_equal(const lv_freetype_info_t * ft_info_1, const lv_freetype_info_t * ft_info_2) -{ - LV_ASSERT_NULL(ft_info_1); - LV_ASSERT_NULL(ft_info_2); - - bool is_equal = (ft_info_1->size == ft_info_2->size - && ft_info_1->style == ft_info_2->style - && ft_info_1->render_mode == ft_info_2->render_mode - && lv_strcmp(ft_info_1->name, ft_info_2->name) == 0); - - return is_equal; -} - -/********************** - * STATIC FUNCTIONS - **********************/ - -#endif /* LV_USE_FONT_MANAGER */ diff --git a/src/others/font_manager/lv_font_manager_utils.h b/src/others/font_manager/lv_font_manager_utils.h deleted file mode 100755 index a04b287e07..0000000000 --- a/src/others/font_manager/lv_font_manager_utils.h +++ /dev/null @@ -1,59 +0,0 @@ -/** - * @file lv_font_manager_utils.h - * - */ -#ifndef LV_FONT_MANAGER_UTILS_H -#define LV_FONT_MANAGER_UTILS_H - -#ifdef __cplusplus -extern "C" { -#endif - -/********************* - * INCLUDES - *********************/ - -#include "../../misc/lv_types.h" - -#if LV_USE_FONT_MANAGER - -#include "../../libs/freetype/lv_freetype.h" - -/********************* - * DEFINES - *********************/ - -/********************** - * TYPEDEFS - **********************/ - -typedef struct { - const char * name; - lv_freetype_font_render_mode_t render_mode; - lv_freetype_font_style_t style; - uint32_t size; -} lv_freetype_info_t; - -/********************** - * GLOBAL PROTOTYPES - **********************/ - -/** - * Compare font information. - * @param ft_info_1 font information 1. - * @param ft_info_2 font information 2. - * @return return true if the fonts are equal. - */ -bool lv_freetype_info_is_equal(const lv_freetype_info_t * ft_info_1, const lv_freetype_info_t * ft_info_2); - -/********************** - * MACROS - **********************/ - -#endif /*LV_USE_FONT_MANAGER*/ - -#ifdef __cplusplus -} /*extern "C"*/ -#endif - -#endif /* LV_FONT_MANAGER_UTILS_H */ diff --git a/tests/ref_imgs/libs/font_manager_1.lp32.png b/tests/ref_imgs/libs/font_manager_1.lp32.png new file mode 100755 index 0000000000..aab6e84a60 Binary files /dev/null and b/tests/ref_imgs/libs/font_manager_1.lp32.png differ diff --git a/tests/ref_imgs/libs/font_manager_1.lp64.png b/tests/ref_imgs/libs/font_manager_1.lp64.png new file mode 100644 index 0000000000..aab6e84a60 Binary files /dev/null and b/tests/ref_imgs/libs/font_manager_1.lp64.png differ diff --git a/tests/ref_imgs/libs/font_manager_2.lp32.png b/tests/ref_imgs/libs/font_manager_2.lp32.png new file mode 100755 index 0000000000..8f9cfbb3de Binary files /dev/null and b/tests/ref_imgs/libs/font_manager_2.lp32.png differ diff --git a/tests/ref_imgs/libs/font_manager_2.lp64.png b/tests/ref_imgs/libs/font_manager_2.lp64.png new file mode 100644 index 0000000000..8f9cfbb3de Binary files /dev/null and b/tests/ref_imgs/libs/font_manager_2.lp64.png differ diff --git a/tests/ref_imgs/libs/font_manager_3.lp32.png b/tests/ref_imgs/libs/font_manager_3.lp32.png new file mode 100755 index 0000000000..11b65a11bb Binary files /dev/null and b/tests/ref_imgs/libs/font_manager_3.lp32.png differ diff --git a/tests/ref_imgs/libs/font_manager_3.lp64.png b/tests/ref_imgs/libs/font_manager_3.lp64.png new file mode 100644 index 0000000000..589e38dd52 Binary files /dev/null and b/tests/ref_imgs/libs/font_manager_3.lp64.png differ diff --git a/tests/ref_imgs/libs/font_manager_4.png b/tests/ref_imgs/libs/font_manager_4.png new file mode 100644 index 0000000000..6faec6d6a3 Binary files /dev/null and b/tests/ref_imgs/libs/font_manager_4.png differ diff --git a/tests/ref_imgs_vg_lite/libs/font_manager_1.lp32.png b/tests/ref_imgs_vg_lite/libs/font_manager_1.lp32.png new file mode 100755 index 0000000000..1a3932703a Binary files /dev/null and b/tests/ref_imgs_vg_lite/libs/font_manager_1.lp32.png differ diff --git a/tests/ref_imgs_vg_lite/libs/font_manager_1.lp64.png b/tests/ref_imgs_vg_lite/libs/font_manager_1.lp64.png new file mode 100644 index 0000000000..1a3932703a Binary files /dev/null and b/tests/ref_imgs_vg_lite/libs/font_manager_1.lp64.png differ diff --git a/tests/ref_imgs_vg_lite/libs/font_manager_2.lp32.png b/tests/ref_imgs_vg_lite/libs/font_manager_2.lp32.png new file mode 100755 index 0000000000..fe7f6e47c8 Binary files /dev/null and b/tests/ref_imgs_vg_lite/libs/font_manager_2.lp32.png differ diff --git a/tests/ref_imgs_vg_lite/libs/font_manager_2.lp64.png b/tests/ref_imgs_vg_lite/libs/font_manager_2.lp64.png new file mode 100644 index 0000000000..fe7f6e47c8 Binary files /dev/null and b/tests/ref_imgs_vg_lite/libs/font_manager_2.lp64.png differ diff --git a/tests/ref_imgs_vg_lite/libs/font_manager_3.lp32.png b/tests/ref_imgs_vg_lite/libs/font_manager_3.lp32.png new file mode 100755 index 0000000000..8b7a9d32b4 Binary files /dev/null and b/tests/ref_imgs_vg_lite/libs/font_manager_3.lp32.png differ diff --git a/tests/ref_imgs_vg_lite/libs/font_manager_3.lp64.png b/tests/ref_imgs_vg_lite/libs/font_manager_3.lp64.png new file mode 100644 index 0000000000..fae114d65a Binary files /dev/null and b/tests/ref_imgs_vg_lite/libs/font_manager_3.lp64.png differ diff --git a/tests/ref_imgs_vg_lite/libs/font_manager_4.png b/tests/ref_imgs_vg_lite/libs/font_manager_4.png new file mode 100644 index 0000000000..2a762b135d Binary files /dev/null and b/tests/ref_imgs_vg_lite/libs/font_manager_4.png differ diff --git a/tests/src/test_cases/libs/test_font_stress.c b/tests/src/test_cases/libs/test_font_stress.c index b96edd74c4..43568d782e 100644 --- a/tests/src/test_cases/libs/test_font_stress.c +++ b/tests/src/test_cases/libs/test_font_stress.c @@ -183,7 +183,7 @@ static lv_font_t * font_manager_font_create_cb(font_stress_ctx_t * ctx, lv_freetype_font_style_t style) { TEST_ASSERT_NOT_NULL(ctx->font_manager); - return lv_font_manager_create_font(ctx->font_manager, name, render_mode, size, style); + return lv_font_manager_create_font(ctx->font_manager, name, render_mode, size, style, LV_FONT_KERNING_NONE); } static void font_manager_font_delete_cb(font_stress_ctx_t * ctx, lv_font_t * font) @@ -248,11 +248,13 @@ void test_font_manager_stress(void) g_ctx.font_manager = lv_font_manager_create(2); TEST_ASSERT_NOT_NULL(g_ctx.font_manager); - lv_font_manager_add_path_static(g_ctx.font_manager, "NotoSansSC-Regular", - "./src/test_files/fonts/noto/NotoSansSC-Regular.ttf"); - lv_font_manager_add_path_static(g_ctx.font_manager, "Arial", "../src/libs/freetype/arial.ttf"); - lv_font_manager_add_path(g_ctx.font_manager, "Montserrat-Bold", "./src/test_files/fonts/Montserrat-Bold.ttf"); - lv_font_manager_add_path(g_ctx.font_manager, "UNKNOWN", "UNKNOWN_FONT_PATH"); + lv_font_manager_add_src_static(g_ctx.font_manager, "NotoSansSC-Regular", + "./src/test_files/fonts/noto/NotoSansSC-Regular.ttf", + &lv_freetype_font_class); + lv_font_manager_add_src_static(g_ctx.font_manager, "Arial", "../src/libs/freetype/arial.ttf", &lv_freetype_font_class); + lv_font_manager_add_src(g_ctx.font_manager, "Montserrat-Bold", "./src/test_files/fonts/Montserrat-Bold.ttf", + &lv_freetype_font_class); + lv_font_manager_add_src(g_ctx.font_manager, "UNKNOWN", "UNKNOWN_FONT_PATH", &lv_freetype_font_class); static const char * font_name_arr[] = { "NotoSansSC-Regular,Arial", @@ -280,10 +282,10 @@ void test_font_manager_stress(void) font_stress_label_delete_all(&g_ctx); - bool remove_ok = lv_font_manager_remove_path(g_ctx.font_manager, "Arial"); + bool remove_ok = lv_font_manager_remove_src(g_ctx.font_manager, "Arial"); TEST_ASSERT_TRUE(remove_ok); - remove_ok = lv_font_manager_remove_path(g_ctx.font_manager, "UNKNOWN"); + remove_ok = lv_font_manager_remove_src(g_ctx.font_manager, "UNKNOWN"); TEST_ASSERT_TRUE(remove_ok); bool success = lv_font_manager_delete(g_ctx.font_manager); diff --git a/tests/src/test_cases/test_font_manager.c b/tests/src/test_cases/test_font_manager.c new file mode 100644 index 0000000000..4d047180bb --- /dev/null +++ b/tests/src/test_cases/test_font_manager.c @@ -0,0 +1,247 @@ +#if LV_BUILD_TEST +#include "../lvgl.h" + +#include "unity/unity.h" + +#if LV_USE_FONT_MANAGER \ + && LV_FONT_MONTSERRAT_14 && LV_FONT_MONTSERRAT_32 \ + && LV_USE_FREETYPE \ + && LV_USE_TINY_TTF && LV_TINY_TTF_FILE_SUPPORT + +/** + * There are some differences between the rendering of FreeType in 64-bit and 32-bit, + * so we compare them separately here. + */ +#ifndef NON_AMD64_BUILD + #define EXT_NAME ".lp64.png" +#else + #define EXT_NAME ".lp32.png" +#endif + +static lv_font_manager_t * g_font_manager = NULL; + +typedef bool (*add_src_cb_t)(lv_font_manager_t * manager, + const char * name, + const void * src, + const lv_font_class_t * class_p); + +void setUp(void) +{ +} + +void tearDown(void) +{ + lv_obj_clean(lv_screen_active()); +} + +static void test_font_manager_src(add_src_cb_t add_src_cb) +{ + g_font_manager = lv_font_manager_create(2); + TEST_ASSERT_NOT_NULL(g_font_manager); + + /* 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; + + bool add_src_result = add_src_cb(g_font_manager, + "Montserrat", + builtin_font_src, + &lv_builtin_font_class); + TEST_ASSERT_TRUE(add_src_result); + + /* Try to add the same source again, should fail */ + add_src_result = add_src_cb(g_font_manager, + "Montserrat", + builtin_font_src, + &lv_builtin_font_class); + TEST_ASSERT_FALSE(add_src_result); + + /* Register FreeType font source */ + add_src_result = add_src_cb(g_font_manager, + "NotoSansSC-Regular", + "./src/test_files/fonts/noto/NotoSansSC-Regular.ttf", + &lv_freetype_font_class); + TEST_ASSERT_TRUE(add_src_result); + + /* Register TinyTTF font source */ + extern const uint8_t test_ubuntu_font[]; + extern size_t test_ubuntu_font_size; + static lv_tiny_ttf_font_src_t tiny_ttf_font_data_src = { 0 }; + tiny_ttf_font_data_src.data = test_ubuntu_font; + tiny_ttf_font_data_src.data_size = test_ubuntu_font_size; + + add_src_result = add_src_cb(g_font_manager, + "Ubuntu-Medium", + &tiny_ttf_font_data_src, + &lv_tiny_ttf_font_class); + TEST_ASSERT_TRUE(add_src_result); + + static lv_tiny_ttf_font_src_t tiny_ttf_font_file_src = { 0 }; + tiny_ttf_font_file_src.path = "A:src/test_files/fonts/noto/NotoSansSC-Regular.ttf"; + + add_src_result = add_src_cb(g_font_manager, + "NotoSansSC-Regular-2", + &tiny_ttf_font_file_src, + &lv_tiny_ttf_font_class); + TEST_ASSERT_TRUE(add_src_result); + + /* Register binary font source */ + static const lv_binfont_font_src_t binfont_font_file_src = { + .font_size = 20, + .path = "A:src/test_assets/test_font_3.fnt", + .buffer = NULL, + .buffer_size = 0, + }; + + add_src_result = add_src_cb(g_font_manager, + "RobotoMono-Regular-file", + &binfont_font_file_src, + &lv_binfont_font_class); + TEST_ASSERT_TRUE(add_src_result); + + extern uint8_t const test_font_3_buf[4892]; + static lv_binfont_font_src_t binfont_font_buffer_src = { 0 }; + binfont_font_buffer_src.font_size = 20; + binfont_font_buffer_src.buffer = test_font_3_buf; + binfont_font_buffer_src.buffer_size = sizeof(test_font_3_buf); + + add_src_result = add_src_cb(g_font_manager, + "RobotoMono-Regular-buffer", + &binfont_font_buffer_src, + &lv_binfont_font_class); + TEST_ASSERT_TRUE(add_src_result); + + /* Create font from font manager */ + + /* Try to create font with unknown name, should fail */ + lv_font_t * font_unknown = lv_font_manager_create_font(g_font_manager, + "UNKNOWN_FONT_NAME", + 0, + 10, + 0, + LV_FONT_KERNING_NONE); + TEST_ASSERT_NULL(font_unknown); + + lv_font_t * font_14 = lv_font_manager_create_font(g_font_manager, + "NotoSansSC-Regular,Ubuntu-Medium,Montserrat,UNKNOWN_FONT_NAME", + LV_FREETYPE_FONT_RENDER_MODE_BITMAP, + 14, + LV_FREETYPE_FONT_STYLE_NORMAL, + LV_FONT_KERNING_NONE); + TEST_ASSERT_NOT_NULL(font_14); + + lv_font_t * font_32 = lv_font_manager_create_font(g_font_manager, + "Ubuntu-Medium,NotoSansSC-Regular,Montserrat", + LV_FREETYPE_FONT_RENDER_MODE_BITMAP, + 32, + LV_FREETYPE_FONT_STYLE_NORMAL, + LV_FONT_KERNING_NONE); + TEST_ASSERT_NOT_NULL(font_32); + + lv_font_t * font_40 = lv_font_manager_create_font(g_font_manager, + "Ubuntu-Medium,NotoSansSC-Regular-2,Montserrat", + 0, + 40, + 0, + LV_FONT_KERNING_NONE); + TEST_ASSERT_NOT_NULL(font_40); + + lv_font_t * font_file_20 = lv_font_manager_create_font(g_font_manager, + "RobotoMono-Regular-file,NotoSansSC-Regular-2", + 0, + 20, + 0, + LV_FONT_KERNING_NONE); + TEST_ASSERT_NOT_NULL(font_file_20); + + lv_font_t * font_buffer_20 = lv_font_manager_create_font(g_font_manager, + "RobotoMono-Regular-buffer,NotoSansSC-Regular-2", + 0, + 20, + 0, + LV_FONT_KERNING_NONE); + TEST_ASSERT_NOT_NULL(font_file_20); + + /* Create label with the font */ + lv_obj_t * label = lv_label_create(lv_screen_active()); + lv_label_set_text(label, + "这是一段中文。\n" + "This is a English text.\n" + "Symbols: " LV_SYMBOL_OK LV_SYMBOL_CLOSE); + lv_obj_center(label); + + lv_obj_set_style_text_font(label, font_14, 0); + TEST_ASSERT_EQUAL_SCREENSHOT("libs/font_manager_1" EXT_NAME); + + lv_obj_set_style_text_font(label, font_32, 0); + TEST_ASSERT_EQUAL_SCREENSHOT("libs/font_manager_2" EXT_NAME); + + lv_obj_set_style_text_font(label, font_40, 0); + TEST_ASSERT_EQUAL_SCREENSHOT("libs/font_manager_3" EXT_NAME); + + /* Freetype fonts have not been tested, so there is no need to distinguish and process images */ + lv_obj_set_style_text_font(label, font_file_20, 0); + TEST_ASSERT_EQUAL_SCREENSHOT("libs/font_manager_4.png"); + + /* Rendered images should be the same */ + lv_obj_set_style_text_font(label, font_buffer_20, 0); + TEST_ASSERT_EQUAL_SCREENSHOT("libs/font_manager_4.png"); + + /* Should not be deleted successfully, because it is used by the label */ + bool delete_result = lv_font_manager_delete(g_font_manager); + TEST_ASSERT_FALSE(delete_result); + + lv_obj_delete(label); + lv_font_manager_delete_font(g_font_manager, font_14); + lv_font_manager_delete_font(g_font_manager, font_32); + lv_font_manager_delete_font(g_font_manager, font_40); + lv_font_manager_delete_font(g_font_manager, font_file_20); + lv_font_manager_delete_font(g_font_manager, font_buffer_20); + + /* Trying to delete a font that was not created by the font manager, it needs to handle this situation */ + lv_font_manager_delete_font(g_font_manager, (lv_font_t *)LV_FONT_DEFAULT); + lv_font_manager_delete_font(g_font_manager, (lv_font_t *)&lv_font_montserrat_32); + + delete_result = lv_font_manager_delete(g_font_manager); + TEST_ASSERT_TRUE(delete_result); + g_font_manager = NULL; +} + +void test_font_manager_src_normal(void) +{ + test_font_manager_src(lv_font_manager_add_src); +} + +void test_font_manager_src_static(void) +{ + test_font_manager_src(lv_font_manager_add_src_static); +} + +#else + +void setUp(void) +{ +} + +void tearDown(void) +{ +} + +void test_font_manager_src_normal(void) +{ +} + +void test_font_manager_src_static(void) +{ +} + +#endif + +#endif /* LV_BUILD_TEST */