LVGL 库提交
This commit is contained in:
@@ -0,0 +1,619 @@
|
||||
/**
|
||||
* @file lv_font_manager.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_font_manager.h"
|
||||
|
||||
#if LV_USE_FONT_MANAGER
|
||||
|
||||
#include "lv_font_manager_recycle.h"
|
||||
#include "../../misc/lv_ll.h"
|
||||
#include "../../stdlib/lv_sprintf.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; /* font reference list */
|
||||
lv_ll_t rec_ll; /* lvgl font record list */
|
||||
lv_ll_t src_ll; /* font src record list */
|
||||
lv_font_manager_recycle_t * recycle_manager;
|
||||
};
|
||||
|
||||
/* font reference node */
|
||||
typedef struct _lv_font_refer_node_t {
|
||||
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;
|
||||
|
||||
/* 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 font resource */
|
||||
} lv_font_rec_node_t;
|
||||
|
||||
typedef struct _lv_font_src_t {
|
||||
char * name;
|
||||
void * src;
|
||||
bool is_static;
|
||||
const lv_font_class_t * class_p;
|
||||
} lv_font_src_t;
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
|
||||
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_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_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_font_info_t * ft_info);
|
||||
static void lv_font_manager_delete_font_family(lv_font_manager_t * manager, lv_font_t * font);
|
||||
|
||||
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
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* 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->src_ll, sizeof(lv_font_src_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_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_src->name = NULL;
|
||||
font_src->src = NULL;
|
||||
}
|
||||
lv_ll_clear(&manager->src_ll);
|
||||
|
||||
lv_free(manager);
|
||||
|
||||
LV_LOG_INFO("success");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool lv_font_manager_add_src(lv_font_manager_t * manager,
|
||||
const char * name,
|
||||
const void * src,
|
||||
const lv_font_class_t * class_p)
|
||||
{
|
||||
return lv_font_manager_add_src_core(manager, name, src, class_p, false);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
return lv_font_manager_add_src_core(manager, name, src, class_p, true);
|
||||
}
|
||||
|
||||
bool lv_font_manager_remove_src(lv_font_manager_t * manager, const char * name)
|
||||
{
|
||||
LV_ASSERT_NULL(manager);
|
||||
LV_ASSERT_NULL(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->src_ll, font_src);
|
||||
|
||||
if(!font_src->is_static) {
|
||||
lv_free(font_src->name);
|
||||
font_src->class_p->free_src_cb(font_src->src);
|
||||
}
|
||||
|
||||
font_src->name = NULL;
|
||||
font_src->src = NULL;
|
||||
|
||||
lv_free(font_src);
|
||||
|
||||
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,
|
||||
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_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;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/* Append fallback font to make LV_SYMBOL displayable */
|
||||
lv_font_t * cur_font = ret_font;
|
||||
while(cur_font) {
|
||||
if(cur_font->fallback == NULL) {
|
||||
cur_font->fallback = LV_FONT_DEFAULT;
|
||||
break;
|
||||
}
|
||||
cur_font = (lv_font_t *)cur_font->fallback;
|
||||
}
|
||||
|
||||
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_font_info_t * ft_info)
|
||||
{
|
||||
LV_ASSERT_NULL(manager);
|
||||
LV_ASSERT_NULL(ft_info);
|
||||
|
||||
const lv_font_refer_node_t * refer_node = lv_font_manager_get_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 font data */
|
||||
rec_node->font = *refer_node->font_p;
|
||||
|
||||
/* record reference 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",
|
||||
(void *)font, (int)font->line_height);
|
||||
return false;
|
||||
}
|
||||
|
||||
bool retval = lv_font_manager_drop_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_font_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_font_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 LV_FONT_MANAGER_NAME_MAX_LEN");
|
||||
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 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(src);
|
||||
LV_ASSERT_NULL(class_p);
|
||||
|
||||
if(lv_font_manager_get_src(manager, name)) {
|
||||
LV_LOG_WARN("name: %s already exists", name);
|
||||
return false;
|
||||
}
|
||||
|
||||
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_src->name = (char *)name;
|
||||
font_src->src = (void *)src;
|
||||
}
|
||||
else {
|
||||
font_src->name = lv_strdup(name);
|
||||
LV_ASSERT_MALLOC(font_src->name);
|
||||
|
||||
font_src->src = font_src->class_p->dup_src_cb(src);
|
||||
LV_ASSERT_NULL(font_src->src);
|
||||
}
|
||||
|
||||
LV_LOG_INFO("name: %s, src: %p add success", name, src);
|
||||
return true;
|
||||
}
|
||||
|
||||
static lv_font_src_t * lv_font_manager_get_src(lv_font_manager_t * manager, const char * name)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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)",
|
||||
(void *)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 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("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", (void *)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_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_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;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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 font */
|
||||
font = lv_font_manager_recycle_get_reuse(manager->recycle_manager, ft_info);
|
||||
|
||||
/* get reuse font from recycle */
|
||||
if(font) {
|
||||
return font;
|
||||
}
|
||||
|
||||
/* cache miss */
|
||||
|
||||
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 = font_src->class_p->create_cb(ft_info, font_src->src);
|
||||
if(!font) {
|
||||
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;
|
||||
}
|
||||
|
||||
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_font(lv_font_manager_t * manager,
|
||||
const lv_font_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 found refer_node, start to create font */
|
||||
|
||||
lv_font_t * font = lv_font_manager_create_font_wrapper(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);
|
||||
|
||||
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_drop_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 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 */
|
||||
@@ -0,0 +1,115 @@
|
||||
/**
|
||||
* @file lv_font_manager.h
|
||||
*
|
||||
*/
|
||||
#ifndef LV_FONT_MANAGER_H
|
||||
#define LV_FONT_MANAGER_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "../../font/lv_font.h"
|
||||
|
||||
#if LV_USE_FONT_MANAGER
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
/**********************
|
||||
* 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 font resource.
|
||||
* @param manager pointer to main font manager.
|
||||
* @param name font name.
|
||||
* @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.
|
||||
*/
|
||||
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 font resource with static memory.
|
||||
* @param manager pointer to main font manager.
|
||||
* @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.
|
||||
*/
|
||||
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 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_src(lv_font_manager_t * manager, const char * name);
|
||||
|
||||
/**
|
||||
* Create font.
|
||||
* @param manager pointer to main font manager.
|
||||
* @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,
|
||||
uint32_t render_mode,
|
||||
uint32_t size,
|
||||
uint32_t style,
|
||||
lv_font_kerning_t kerning);
|
||||
|
||||
/**
|
||||
* 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 */
|
||||
@@ -0,0 +1,172 @@
|
||||
/**
|
||||
* @file lv_font_manager_recycle.c
|
||||
*
|
||||
*/
|
||||
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
|
||||
#include "lv_font_manager_recycle.h"
|
||||
|
||||
#if LV_USE_FONT_MANAGER
|
||||
|
||||
#include "../../font/lv_font.h"
|
||||
#include "../../misc/lv_ll.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
|
||||
struct _lv_font_manager_recycle_t {
|
||||
lv_ll_t recycle_ll;
|
||||
uint32_t max_size;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
lv_font_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_font_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_font_info_is_equal(ft_info, &recycle->ft_info)) {
|
||||
lv_font_t * font = recycle->font;
|
||||
LV_LOG_INFO("found font: %p", (void *)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_font_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);
|
||||
recycle->ft_info.class_p->delete_cb(recycle->font);
|
||||
recycle->font = NULL;
|
||||
|
||||
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 */
|
||||
@@ -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 "../../misc/lv_types.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_font_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_font_info_t * ft_info);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#endif /* LV_USE_FONT_MANAGER */
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /*extern "C"*/
|
||||
#endif
|
||||
|
||||
#endif /* LV_FONT_MANAGER_RECYCLE_H */
|
||||
Reference in New Issue
Block a user