mirror of
https://github.com/lvgl/lvgl.git
synced 2025-01-28 07:03:00 +08:00
feat(libs): add freetype font manager (#6482)
Signed-off-by: FASTSHIFT <vifextech@foxmail.com>
This commit is contained in:
parent
3db31e44e5
commit
dbb5905260
9
Kconfig
9
Kconfig
@ -1464,6 +1464,15 @@ menu "LVGL configuration"
|
||||
default y
|
||||
help
|
||||
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
|
||||
default n
|
||||
config LV_FONT_MANAGER_NAME_MAX_LEN
|
||||
int "Font manager name max length"
|
||||
depends on LV_USE_FONT_MANAGER
|
||||
default 32
|
||||
endmenu
|
||||
|
||||
menu "Devices"
|
||||
|
@ -970,6 +970,16 @@
|
||||
#define LV_FILE_EXPLORER_QUICK_ACCESS 1
|
||||
#endif
|
||||
|
||||
/*1: Enable freetype font manager*/
|
||||
/*Requires: LV_USE_FREETYPE*/
|
||||
#define LV_USE_FONT_MANAGER 0
|
||||
#if LV_USE_FONT_MANAGER
|
||||
|
||||
/*Font manager name max length*/
|
||||
#define LV_FONT_MANAGER_NAME_MAX_LEN 32
|
||||
|
||||
#endif
|
||||
|
||||
/*==================
|
||||
* DEVICES
|
||||
*==================*/
|
||||
|
@ -3083,6 +3083,28 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*1: Enable freetype font manager*/
|
||||
/*Requires: LV_USE_FREETYPE*/
|
||||
#ifndef LV_USE_FONT_MANAGER
|
||||
#ifdef CONFIG_LV_USE_FONT_MANAGER
|
||||
#define LV_USE_FONT_MANAGER CONFIG_LV_USE_FONT_MANAGER
|
||||
#else
|
||||
#define LV_USE_FONT_MANAGER 0
|
||||
#endif
|
||||
#endif
|
||||
#if LV_USE_FONT_MANAGER
|
||||
|
||||
/*Font manager name max length*/
|
||||
#ifndef LV_FONT_MANAGER_NAME_MAX_LEN
|
||||
#ifdef CONFIG_LV_FONT_MANAGER_NAME_MAX_LEN
|
||||
#define LV_FONT_MANAGER_NAME_MAX_LEN CONFIG_LV_FONT_MANAGER_NAME_MAX_LEN
|
||||
#else
|
||||
#define LV_FONT_MANAGER_NAME_MAX_LEN 32
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/*==================
|
||||
* DEVICES
|
||||
*==================*/
|
||||
|
601
src/others/font_manager/lv_font_manager.c
Executable file
601
src/others/font_manager/lv_font_manager.c
Executable file
@ -0,0 +1,601 @@
|
||||
/**
|
||||
* @file lv_font_manager.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_font_manager.h"
|
||||
|
||||
#if LV_USE_FONT_MANAGER
|
||||
|
||||
#include "lv_font_manager_recycle.h"
|
||||
#include "lv_font_manager_utils.h"
|
||||
#include "../../lvgl.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
#define IS_FONT_FAMILY_NAME(name) (lv_strchr((name), ',') != NULL)
|
||||
#define IS_FONT_HAS_FALLBACK(font) ((font)->fallback != NULL)
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/* font manager object */
|
||||
struct _lv_font_manager_t {
|
||||
lv_ll_t refer_ll; /* freetype font record list */
|
||||
lv_ll_t rec_ll; /* lvgl font record list */
|
||||
lv_ll_t path_ll; /* font path record list */
|
||||
lv_font_manager_recycle_t * recycle_manager;
|
||||
};
|
||||
|
||||
/* freetype 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 */
|
||||
char name[LV_FONT_MANAGER_NAME_MAX_LEN]; /* name buffer */
|
||||
int ref_cnt; /* reference count */
|
||||
} 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 */
|
||||
} lv_font_rec_node_t;
|
||||
|
||||
typedef struct _lv_font_path_t {
|
||||
char * name;
|
||||
char * path;
|
||||
bool is_static;
|
||||
} lv_font_path_t;
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
static const char * lv_font_manager_get_path(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 lv_font_t * lv_font_manager_create_font_single(lv_font_manager_t * manager, const lv_freetype_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 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 VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
lv_font_manager_t * lv_font_manager_create(uint32_t recycle_cache_size)
|
||||
{
|
||||
LV_ASSERT_MSG(recycle_cache_size > 0, "recycle_cache_size should be greater than 0");
|
||||
lv_font_manager_t * manager = lv_malloc_zeroed(sizeof(lv_font_manager_t));
|
||||
LV_ASSERT_MALLOC(manager);
|
||||
if(!manager) {
|
||||
LV_LOG_ERROR("malloc failed for lv_font_manager_t");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
_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));
|
||||
|
||||
manager->recycle_manager = lv_font_manager_recycle_create(recycle_cache_size);
|
||||
|
||||
LV_LOG_INFO("success");
|
||||
return manager;
|
||||
}
|
||||
|
||||
bool lv_font_manager_delete(lv_font_manager_t * manager)
|
||||
{
|
||||
LV_ASSERT_NULL(manager);
|
||||
|
||||
/* Resource leak check */
|
||||
if(lv_font_manager_check_resource(manager)) {
|
||||
LV_LOG_ERROR("unfreed resource detected, delete failed!");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* clean recycle_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);
|
||||
}
|
||||
|
||||
font_path->name = NULL;
|
||||
font_path->path = NULL;
|
||||
}
|
||||
_lv_ll_clear(&manager->path_ll);
|
||||
|
||||
lv_free(manager);
|
||||
|
||||
LV_LOG_INFO("success");
|
||||
return true;
|
||||
}
|
||||
|
||||
void lv_font_manager_add_path(lv_font_manager_t * manager, const char * name, const char * path)
|
||||
{
|
||||
lv_font_manager_add_path_core(manager, name, path, false);
|
||||
}
|
||||
|
||||
void lv_font_manager_add_path_static(lv_font_manager_t * manager, const char * name, const char * path)
|
||||
{
|
||||
lv_font_manager_add_path_core(manager, name, path, true);
|
||||
}
|
||||
|
||||
bool lv_font_manager_remove_path(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;
|
||||
}
|
||||
}
|
||||
|
||||
if(!font_path) {
|
||||
LV_LOG_WARN("name: %s not found", name);
|
||||
return false;
|
||||
}
|
||||
|
||||
_lv_ll_remove(&manager->path_ll, font_path);
|
||||
|
||||
if(!font_path->is_static) {
|
||||
lv_free(font_path->name);
|
||||
lv_free(font_path->path);
|
||||
}
|
||||
|
||||
font_path->name = NULL;
|
||||
font_path->path = NULL;
|
||||
|
||||
lv_free(font_path);
|
||||
|
||||
LV_LOG_WARN("name: %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_ASSERT_NULL(manager);
|
||||
LV_ASSERT_NULL(font_family);
|
||||
|
||||
lv_freetype_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;
|
||||
|
||||
lv_font_t * ret_font;
|
||||
|
||||
if(IS_FONT_FAMILY_NAME(ft_info.name)) {
|
||||
ret_font = lv_font_manager_create_font_family(manager, &ft_info);
|
||||
}
|
||||
else {
|
||||
ret_font = lv_font_manager_create_font_single(manager, &ft_info);
|
||||
}
|
||||
|
||||
/* make LV_SYMBOL displayable */
|
||||
if(ret_font) {
|
||||
ret_font->fallback = LV_FONT_DEFAULT;
|
||||
}
|
||||
|
||||
return ret_font;
|
||||
}
|
||||
|
||||
void lv_font_manager_delete_font(lv_font_manager_t * manager, lv_font_t * font)
|
||||
{
|
||||
LV_ASSERT_NULL(manager);
|
||||
LV_ASSERT_NULL(font);
|
||||
|
||||
if(IS_FONT_HAS_FALLBACK(font)) {
|
||||
lv_font_manager_delete_font_family(manager, font);
|
||||
return;
|
||||
}
|
||||
|
||||
lv_font_manager_delete_font_single(manager, 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)
|
||||
{
|
||||
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);
|
||||
if(!refer_node) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* add font record node */
|
||||
lv_font_rec_node_t * rec_node = _lv_ll_ins_head(&manager->rec_ll);
|
||||
LV_ASSERT_MALLOC(rec_node);
|
||||
lv_memzero(rec_node, sizeof(lv_font_rec_node_t));
|
||||
|
||||
/* copy freetype_font data */
|
||||
rec_node->font = *refer_node->font_p;
|
||||
|
||||
/* record reference freetype_font */
|
||||
rec_node->refer_node_p = refer_node;
|
||||
|
||||
LV_LOG_INFO("success");
|
||||
return &rec_node->font;
|
||||
}
|
||||
|
||||
static bool lv_font_manager_delete_font_single(lv_font_manager_t * manager, lv_font_t * font)
|
||||
{
|
||||
LV_ASSERT_NULL(manager);
|
||||
LV_ASSERT_NULL(font);
|
||||
|
||||
if(font == LV_FONT_DEFAULT) {
|
||||
LV_LOG_INFO("LV_FONT_DEFAULT can not be deleted");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* check font is created by font manager */
|
||||
lv_font_rec_node_t * rec_node = lv_font_manager_search_rec_node(manager, font);
|
||||
if(!rec_node) {
|
||||
LV_LOG_WARN("NO record found for font: %p(%d),"
|
||||
" it was not created by font manager",
|
||||
font, (int)font->line_height);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* reset freetype font resource */
|
||||
bool retval = lv_font_manager_reset_freetype_font(manager, rec_node->refer_node_p);
|
||||
LV_ASSERT(retval);
|
||||
|
||||
/* free rec_node */
|
||||
_lv_ll_remove(&manager->rec_ll, rec_node);
|
||||
lv_free(rec_node);
|
||||
|
||||
LV_LOG_INFO("success");
|
||||
return retval;
|
||||
}
|
||||
|
||||
static const char * strncpy_until(char * dest, const char * src, size_t n, char c)
|
||||
{
|
||||
LV_ASSERT_NULL(dest);
|
||||
LV_ASSERT_NULL(src);
|
||||
|
||||
size_t i = 0;
|
||||
while(i < n && *src != '\0' && *src != c) {
|
||||
*dest++ = *src++;
|
||||
i++;
|
||||
}
|
||||
|
||||
if(i < n) {
|
||||
*dest = '\0';
|
||||
}
|
||||
|
||||
return src;
|
||||
}
|
||||
|
||||
static lv_font_t * lv_font_manager_create_font_family(lv_font_manager_t * manager, const lv_freetype_info_t * ft_info)
|
||||
{
|
||||
LV_ASSERT_NULL(manager);
|
||||
LV_ASSERT_NULL(ft_info);
|
||||
|
||||
lv_font_t * first_font = NULL;
|
||||
lv_font_t * pre_font = NULL;
|
||||
|
||||
const char * family_str = ft_info->name;
|
||||
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;
|
||||
tmp_ft_info.name = tmp_name;
|
||||
|
||||
while(1) {
|
||||
family_str = strncpy_until(tmp_name, family_str, sizeof(tmp_name) - 1, ',');
|
||||
|
||||
lv_font_t * cur_font = lv_font_manager_create_font_single(manager, &tmp_ft_info);
|
||||
|
||||
if(cur_font) {
|
||||
/* save first font pointer */
|
||||
if(!first_font) {
|
||||
first_font = cur_font;
|
||||
}
|
||||
|
||||
/* append font fallback */
|
||||
if(pre_font) {
|
||||
pre_font->fallback = cur_font;
|
||||
}
|
||||
|
||||
pre_font = cur_font;
|
||||
}
|
||||
|
||||
/* stop */
|
||||
if(*family_str == '\0') {
|
||||
break;
|
||||
}
|
||||
|
||||
if(*family_str != ',') {
|
||||
LV_LOG_ERROR("font name buffer is too small, please increase FONT_NAME_MAX");
|
||||
break;
|
||||
}
|
||||
|
||||
/* skip ',' */
|
||||
family_str++;
|
||||
}
|
||||
|
||||
return first_font;
|
||||
}
|
||||
|
||||
static void lv_font_manager_delete_font_family(lv_font_manager_t * manager, lv_font_t * font)
|
||||
{
|
||||
LV_ASSERT_NULL(manager);
|
||||
LV_ASSERT_NULL(font);
|
||||
|
||||
lv_font_t * f = font;
|
||||
while(f) {
|
||||
lv_font_t * fallback = (lv_font_t *)f->fallback;
|
||||
lv_font_manager_delete_font_single(manager, f);
|
||||
f = fallback;
|
||||
}
|
||||
}
|
||||
|
||||
static void lv_font_manager_add_path_core(lv_font_manager_t * manager, const char * name, const char * path,
|
||||
bool is_static)
|
||||
{
|
||||
LV_ASSERT_NULL(manager);
|
||||
LV_ASSERT_NULL(name);
|
||||
LV_ASSERT_NULL(path);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
lv_font_path_t * font_path = _lv_ll_ins_tail(&manager->path_ll);
|
||||
LV_ASSERT_MALLOC(font_path);
|
||||
font_path->is_static = is_static;
|
||||
|
||||
if(is_static) {
|
||||
font_path->name = (char *)name;
|
||||
font_path->path = (char *)path;
|
||||
}
|
||||
else {
|
||||
uint32_t name_len = lv_strlen(name) + 1;
|
||||
font_path->name = lv_malloc(name_len);
|
||||
LV_ASSERT_MALLOC(font_path->name);
|
||||
lv_memcpy(font_path->name, name, name_len);
|
||||
|
||||
uint32_t path_len = lv_strlen(path) + 1;
|
||||
font_path->path = lv_malloc(path_len);
|
||||
LV_ASSERT_MALLOC(font_path->path);
|
||||
lv_memcpy(font_path->path, path, path_len);
|
||||
}
|
||||
|
||||
LV_LOG_INFO("name: %s, path: %s add success", name, path);
|
||||
}
|
||||
|
||||
static const char * lv_font_manager_get_path(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;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool lv_font_manager_check_resource(lv_font_manager_t * manager)
|
||||
{
|
||||
LV_ASSERT_NULL(manager);
|
||||
|
||||
/* Check the recorded font */
|
||||
lv_ll_t * rec_ll = &manager->rec_ll;
|
||||
uint32_t rec_ll_len = _lv_ll_get_len(rec_ll);
|
||||
if(rec_ll_len) {
|
||||
LV_LOG_WARN("lvgl font resource[%" LV_PRIu32 "]:", rec_ll_len);
|
||||
|
||||
lv_font_rec_node_t * node;
|
||||
_LV_LL_READ(rec_ll, node) {
|
||||
LV_LOG_WARN("font: %p(%d) -> ref: %s(%d)",
|
||||
node,
|
||||
(int)node->font.line_height,
|
||||
node->refer_node_p->ft_info.name,
|
||||
node->refer_node_p->ft_info.size);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check the recorded font resources created by freetype */
|
||||
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_font_refer_node_t * node;
|
||||
_LV_LL_READ(refer_ll, node) {
|
||||
LV_LOG_WARN("font: %s(%d), ref_cnt = %d",
|
||||
node->ft_info.name,
|
||||
node->ft_info.size,
|
||||
node->ref_cnt);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check resource leak */
|
||||
bool has_resource = (rec_ll_len || refer_ll_len);
|
||||
|
||||
return has_resource;
|
||||
}
|
||||
|
||||
static lv_font_rec_node_t * lv_font_manager_search_rec_node(lv_font_manager_t * manager, lv_font_t * font)
|
||||
{
|
||||
LV_ASSERT_NULL(manager);
|
||||
LV_ASSERT_NULL(font);
|
||||
|
||||
lv_font_rec_node_t * rec_node;
|
||||
_LV_LL_READ(&manager->rec_ll, rec_node) {
|
||||
if(font == &rec_node->font) {
|
||||
LV_LOG_INFO("font: %p(%d) matched", font, (int)font->line_height);
|
||||
return rec_node;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static lv_font_refer_node_t * lv_font_manager_search_refer_node(lv_font_manager_t * manager,
|
||||
const lv_freetype_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)) {
|
||||
LV_LOG_INFO("font: %s(%d) matched", ft_info->name, ft_info->size);
|
||||
return refer_node;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static lv_font_t * lv_font_manager_create_font_warpper(lv_font_manager_t * manager, const lv_freetype_info_t * ft_info)
|
||||
{
|
||||
LV_ASSERT_NULL(manager);
|
||||
LV_ASSERT_NULL(ft_info);
|
||||
|
||||
lv_font_t * font;
|
||||
|
||||
/* create freetype font */
|
||||
font = lv_font_manager_recycle_get_reuse(manager->recycle_manager, ft_info);
|
||||
|
||||
/* get reuse font from recycle */
|
||||
if(font) {
|
||||
return font;
|
||||
}
|
||||
|
||||
/* 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);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
font = lv_freetype_font_create(path, ft_info->render_mode, ft_info->size, ft_info->style);
|
||||
if(!font) {
|
||||
LV_LOG_ERROR("Freetype font init 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;
|
||||
}
|
||||
|
||||
return font;
|
||||
}
|
||||
|
||||
static void lv_font_manager_delete_font_warpper(lv_font_manager_t * manager, lv_font_refer_node_t * refer_node)
|
||||
{
|
||||
LV_ASSERT_NULL(manager);
|
||||
LV_ASSERT_NULL(refer_node);
|
||||
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)
|
||||
{
|
||||
LV_ASSERT_NULL(manager);
|
||||
LV_ASSERT_NULL(ft_info);
|
||||
|
||||
/* check refer_node is existed */
|
||||
lv_font_refer_node_t * refer_node = lv_font_manager_search_refer_node(manager, ft_info);
|
||||
if(refer_node) {
|
||||
refer_node->ref_cnt++;
|
||||
LV_LOG_INFO("refer_node existed, ref_cnt++ = %d", refer_node->ref_cnt);
|
||||
return refer_node;
|
||||
}
|
||||
|
||||
/* not fount refer_node, start to create font */
|
||||
|
||||
lv_font_t * font = lv_font_manager_create_font_warpper(manager, ft_info);
|
||||
|
||||
if(!font) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* add refer_node to refer_ll */
|
||||
refer_node = _lv_ll_ins_head(&manager->refer_ll);
|
||||
LV_ASSERT_MALLOC(refer_node);
|
||||
lv_memzero(refer_node, sizeof(lv_font_refer_node_t));
|
||||
|
||||
lv_strncpy(refer_node->name, ft_info->name, sizeof(refer_node->name) - 1);
|
||||
|
||||
/* copy font data */
|
||||
refer_node->font_p = font;
|
||||
refer_node->ft_info = *ft_info;
|
||||
refer_node->ft_info.name = refer_node->name;
|
||||
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)
|
||||
{
|
||||
LV_ASSERT_NULL(manager);
|
||||
LV_ASSERT_NULL(node);
|
||||
|
||||
/* Check refer_node is existed */
|
||||
lv_font_refer_node_t * refer_node = lv_font_manager_search_refer_node(manager, &node->ft_info);
|
||||
if(!refer_node) {
|
||||
LV_LOG_WARN("NO record found for font: %s(%d),"
|
||||
" it was not created by font manager",
|
||||
node->ft_info.name, node->ft_info.size);
|
||||
return false;
|
||||
}
|
||||
|
||||
refer_node->ref_cnt--;
|
||||
|
||||
/* If ref_cnt is > 0, no need to delete font */
|
||||
if(refer_node->ref_cnt > 0) {
|
||||
LV_LOG_INFO("refer_node existed, ref_cnt-- = %d", refer_node->ref_cnt);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* if if ref_cnt is about to be 0, free font resource */
|
||||
lv_font_manager_delete_font_warpper(manager, refer_node);
|
||||
|
||||
/* free refer_node */
|
||||
_lv_ll_remove(&manager->refer_ll, refer_node);
|
||||
lv_free(refer_node);
|
||||
|
||||
LV_LOG_INFO("success");
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif /* LV_USE_FONT_MANAGER */
|
106
src/others/font_manager/lv_font_manager.h
Executable file
106
src/others/font_manager/lv_font_manager.h
Executable file
@ -0,0 +1,106 @@
|
||||
/**
|
||||
* @file lv_font_manager.h
|
||||
*
|
||||
*/
|
||||
#ifndef LV_FONT_MANAGER_H
|
||||
#define LV_FONT_MANAGER_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "../../misc/lv_types.h"
|
||||
|
||||
#if LV_USE_FONT_MANAGER
|
||||
|
||||
#if !LV_USE_FREETYPE
|
||||
#error "LV_USE_FONT_MANAGER requires LV_USE_FREETYPE"
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef struct _lv_font_manager_t lv_font_manager_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create main font manager.
|
||||
* @param recycle_cache_size number of fonts that were recently deleted from the cache.
|
||||
* @return pointer to main font manager.
|
||||
*/
|
||||
lv_font_manager_t * lv_font_manager_create(uint32_t recycle_cache_size);
|
||||
|
||||
/**
|
||||
* Delete main font manager.
|
||||
* @param manager pointer to main font manager.
|
||||
* @return return true if the deletion was successful.
|
||||
*/
|
||||
bool lv_font_manager_delete(lv_font_manager_t * manager);
|
||||
|
||||
/**
|
||||
* Add the font file path.
|
||||
* @param manager pointer to main font manager.
|
||||
* @param name font name.
|
||||
* @param path font file path.
|
||||
*/
|
||||
void lv_font_manager_add_path(lv_font_manager_t * manager, const char * name, const char * path);
|
||||
|
||||
/**
|
||||
* Add the font file path with static memory.
|
||||
* @param manager pointer to main font manager.
|
||||
* @param name font name.
|
||||
* @param path font file path.
|
||||
*/
|
||||
void lv_font_manager_add_path_static(lv_font_manager_t * manager, const char * name, const char * path);
|
||||
|
||||
/**
|
||||
* Remove the font file path.
|
||||
* @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);
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
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);
|
||||
|
||||
/**
|
||||
* Delete font.
|
||||
* @param manager pointer to main font manager.
|
||||
* @param font point to the font.
|
||||
* @return return true if the deletion was successful.
|
||||
*/
|
||||
void lv_font_manager_delete_font(lv_font_manager_t * manager, lv_font_t * font);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /* LV_USE_FONT_MANAGER */
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* FONT_MANAGER_MANAGER_H */
|
170
src/others/font_manager/lv_font_manager_recycle.c
Executable file
170
src/others/font_manager/lv_font_manager_recycle.c
Executable file
@ -0,0 +1,170 @@
|
||||
/**
|
||||
* @file lv_font_manager_recycle.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_font_manager_recycle.h"
|
||||
|
||||
#if LV_USE_FONT_MANAGER
|
||||
|
||||
#include "../../lvgl.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
struct _lv_font_manager_recycle_t {
|
||||
lv_ll_t recycle_ll;
|
||||
uint32_t max_size;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
lv_freetype_info_t ft_info;
|
||||
char name[LV_FONT_MANAGER_NAME_MAX_LEN];
|
||||
lv_font_t * font;
|
||||
} lv_font_recycle_t;
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
static void lv_font_recycle_close(lv_font_manager_recycle_t * manager, lv_font_recycle_t * recycle);
|
||||
static void lv_font_manager_recycle_remove_tail(lv_font_manager_recycle_t * manager);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* GLOBAL FUNCTIONS
|
||||
**********************/
|
||||
|
||||
lv_font_manager_recycle_t * lv_font_manager_recycle_create(uint32_t max_size)
|
||||
{
|
||||
lv_font_manager_recycle_t * manager = lv_malloc_zeroed(sizeof(lv_font_manager_recycle_t));
|
||||
LV_ASSERT_MALLOC(manager);
|
||||
if(!manager) {
|
||||
LV_LOG_ERROR("malloc failed for lv_font_manager_recycle_t");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
_lv_ll_init(&manager->recycle_ll, sizeof(lv_font_recycle_t));
|
||||
manager->max_size = max_size;
|
||||
|
||||
LV_LOG_INFO("success");
|
||||
return manager;
|
||||
}
|
||||
|
||||
void lv_font_manager_recycle_delete(lv_font_manager_recycle_t * manager)
|
||||
{
|
||||
LV_ASSERT_NULL(manager);
|
||||
|
||||
lv_ll_t * recycle_ll = &manager->recycle_ll;
|
||||
|
||||
lv_font_recycle_t * recycle = _lv_ll_get_head(recycle_ll);
|
||||
|
||||
/* clear all recycle */
|
||||
while(recycle != NULL) {
|
||||
lv_font_recycle_t * recycle_next = _lv_ll_get_next(recycle_ll, recycle);
|
||||
lv_font_recycle_close(manager, recycle);
|
||||
recycle = recycle_next;
|
||||
}
|
||||
|
||||
lv_free(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_ASSERT_NULL(manager);
|
||||
LV_ASSERT_NULL(ft_info);
|
||||
|
||||
lv_ll_t * recycle_ll = &manager->recycle_ll;
|
||||
|
||||
LV_LOG_INFO("font: %s(%d) searching...", ft_info->name, ft_info->size);
|
||||
|
||||
lv_font_recycle_t * recycle;
|
||||
_LV_LL_READ(recycle_ll, recycle) {
|
||||
/* match font */
|
||||
if(lv_freetype_info_is_equal(ft_info, &recycle->ft_info)) {
|
||||
lv_font_t * font = recycle->font;
|
||||
LV_LOG_INFO("found font: %p", font);
|
||||
|
||||
/* remove reused font */
|
||||
_lv_ll_remove(recycle_ll, recycle);
|
||||
lv_free(recycle);
|
||||
return font;
|
||||
}
|
||||
}
|
||||
|
||||
LV_LOG_INFO("NOT found");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void lv_font_manager_recycle_set_reuse(lv_font_manager_recycle_t * manager, lv_font_t * font,
|
||||
const lv_freetype_info_t * ft_info)
|
||||
{
|
||||
LV_ASSERT_NULL(manager);
|
||||
LV_ASSERT_NULL(ft_info);
|
||||
|
||||
lv_ll_t * recycle_ll = &manager->recycle_ll;
|
||||
|
||||
/* check recycled 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);
|
||||
}
|
||||
|
||||
/* record reuse font */
|
||||
lv_font_recycle_t * recycle = _lv_ll_ins_head(recycle_ll);
|
||||
LV_ASSERT_MALLOC(recycle);
|
||||
lv_memzero(recycle, sizeof(lv_font_recycle_t));
|
||||
|
||||
lv_strncpy(recycle->name, ft_info->name, sizeof(recycle->name));
|
||||
recycle->name[sizeof(recycle->name) - 1] = '\0';
|
||||
|
||||
recycle->font = font;
|
||||
recycle->ft_info = *ft_info;
|
||||
recycle->ft_info.name = recycle->name;
|
||||
|
||||
LV_LOG_INFO("insert font: %s(%d) to reuse list", ft_info->name, ft_info->size);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static void lv_font_recycle_close(lv_font_manager_recycle_t * manager, lv_font_recycle_t * recycle)
|
||||
{
|
||||
LV_ASSERT_NULL(manager);
|
||||
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);
|
||||
|
||||
_lv_ll_remove(&manager->recycle_ll, recycle);
|
||||
lv_free(recycle);
|
||||
}
|
||||
|
||||
static void lv_font_manager_recycle_remove_tail(lv_font_manager_recycle_t * manager)
|
||||
{
|
||||
lv_font_recycle_t * tail = _lv_ll_get_tail(&manager->recycle_ll);
|
||||
LV_ASSERT_NULL(tail);
|
||||
lv_font_recycle_close(manager, tail);
|
||||
}
|
||||
|
||||
#endif /* LV_USE_FONT_MANAGER */
|
78
src/others/font_manager/lv_font_manager_recycle.h
Executable file
78
src/others/font_manager/lv_font_manager_recycle.h
Executable file
@ -0,0 +1,78 @@
|
||||
/**
|
||||
* @file lv_font_manager_recycle.h
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LV_FONT_MANAGER_RECYCLE_H
|
||||
#define LV_FONT_MANAGER_RECYCLE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_font_manager_utils.h"
|
||||
|
||||
#if LV_USE_FONT_MANAGER
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
typedef struct _lv_font_manager_recycle_t lv_font_manager_recycle_t;
|
||||
|
||||
/**********************
|
||||
* GLOBAL PROTOTYPES
|
||||
**********************/
|
||||
|
||||
/**
|
||||
* Create font recycle manager.
|
||||
* @param max_size recycle size.
|
||||
* @return pointer to font recycle manager.
|
||||
*/
|
||||
lv_font_manager_recycle_t * lv_font_manager_recycle_create(uint32_t max_size);
|
||||
|
||||
/**
|
||||
* Delete font recycle manager.
|
||||
* @param manager pointer to font recycle manager.
|
||||
*/
|
||||
void lv_font_manager_recycle_delete(lv_font_manager_recycle_t * manager);
|
||||
|
||||
/**
|
||||
* Get a reusable font.
|
||||
* @param manager pointer to font recycle 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);
|
||||
|
||||
/**
|
||||
* Set fonts to be reused.
|
||||
* @param manager pointer to font recycle manager.
|
||||
* @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);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /* LV_USE_FONT_MANAGER */
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /* LV_FONT_MANAGER_RECYCLE_H */
|
56
src/others/font_manager/lv_font_manager_utils.c
Executable file
56
src/others/font_manager/lv_font_manager_utils.c
Executable file
@ -0,0 +1,56 @@
|
||||
/**
|
||||
* @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 */
|
59
src/others/font_manager/lv_font_manager_utils.h
Executable file
59
src/others/font_manager/lv_font_manager_utils.h
Executable file
@ -0,0 +1,59 @@
|
||||
/**
|
||||
* @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 */
|
@ -262,6 +262,21 @@ char * lv_strncat(char * dst, const char * src, size_t src_len)
|
||||
return tmp;
|
||||
}
|
||||
|
||||
char * lv_strchr(const char * s, int c)
|
||||
{
|
||||
for(; ; s++) {
|
||||
if(*s == c) {
|
||||
return (char *)s;
|
||||
}
|
||||
|
||||
if(*s == '\0') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
@ -107,6 +107,11 @@ char * lv_strncat(char * dst, const char * src, size_t src_len)
|
||||
return strncat(dst, src, src_len);
|
||||
}
|
||||
|
||||
char * lv_strchr(const char * str, int c)
|
||||
{
|
||||
return strchr(str, c);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
@ -147,6 +147,14 @@ char * lv_strcat(char * dst, const char * src);
|
||||
*/
|
||||
char * lv_strncat(char * dst, const char * src, size_t src_len);
|
||||
|
||||
/**
|
||||
* @brief Searches for the first occurrence of character c in the string str.
|
||||
* @param str Pointer to the null-terminated byte string to be searched.
|
||||
* @param c The character to be searched for.
|
||||
* @return A pointer to the first occurrence of character c in the string str, or a null pointer if c is not found.
|
||||
*/
|
||||
char * lv_strchr(const char * str, int c);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
@ -116,6 +116,21 @@ char * lv_strncat(char * dst, const char * src, size_t src_len)
|
||||
return tmp;
|
||||
}
|
||||
|
||||
char * lv_strchr(const char * s, int c)
|
||||
{
|
||||
for(; ; s++) {
|
||||
if(*s == c) {
|
||||
return (char *)s;
|
||||
}
|
||||
|
||||
if(*s == '\0') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
Loading…
x
Reference in New Issue
Block a user