Skip to content

Commit

Permalink
refact(binfont): unified font creation API (lvgl#5333)
Browse files Browse the repository at this point in the history
Co-authored-by: pengyiqiang <pengyiqiang@xiaomi.com>
  • Loading branch information
FASTSHIFT and pengyiqiang authored Jan 15, 2024
1 parent c7bece7 commit 106519b
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 81 deletions.
19 changes: 9 additions & 10 deletions docs/overview/font.rst
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ The built-in symbols are created from the `FontAwesome <https://fontawesome.com/
Load a font at run-time
***********************

:cpp:func:`lv_binfont_load` can be used to load a font from a file. The font needs
:cpp:func:`lv_binfont_create` can be used to load a font from a file. The font needs
to have a special binary format. (Not TTF or WOFF). Use
`lv_font_conv <https://github.com/lvgl/lv_font_conv/>`__ with the
``--format bin`` option to generate an LVGL compatible font file.
Expand All @@ -302,19 +302,18 @@ Example

.. code:: c
static lv_font_t my_font;
lv_result_t res = lv_binfont_load(&my_font, "X:/path/to/my_font.bin");
if(res != LV_RESULT_OK) return;
lv_font_t *my_font = lv_binfont_create("X:/path/to/my_font.bin");
if(my_font == NULL) return;
/*Use the font*/
/*Free the font if not required anymore*/
lv_font_free(&my_font);
lv_binfont_destroy(my_font);
Load a font from a memory buffer at run-time
******************************************

:cpp:func:`lv_binfont_load_from_buffer` can be used to load a font from a memory buffer.
:cpp:func:`lv_binfont_create_from_buffer` can be used to load a font from a memory buffer.
This function may be useful to load a font from an external file system, which is not
supported by LVGL. The font needs to be in the same format as if it were loaded from a file.

Expand All @@ -325,20 +324,20 @@ Example

.. code:: c
static lv_font_t my_font;
lv_font_t *my_font;
uint8_t *buf;
uint32_t bufsize;
/*Read font file into the buffer from the external file system*/
...
/*Load font from the buffer*/
lv_result_t res = lv_binfont_load_from_buffer(&my_font, (void *)buf, buf));
if(res != LV_RESULT_OK) return;
my_font = lv_binfont_create_from_buffer((void *)buf, buf));
if(my_font == NULL) return;
/*Use the font*/
/*Free the font if not required anymore*/
lv_font_free(&my_font);
lv_binfont_destroy(my_font);
Add a new font engine
*********************
Expand Down
36 changes: 17 additions & 19 deletions src/font/lv_binfont_loader.c
Original file line number Diff line number Diff line change
Expand Up @@ -78,47 +78,44 @@ static unsigned int read_bits(bit_iterator_t * it, int n_bits, lv_fs_res_t * res
* GLOBAL FUNCTIONS
**********************/

lv_result_t lv_binfont_load(lv_font_t * font, const char * path)
lv_font_t * lv_binfont_create(const char * path)
{
LV_ASSERT_NULL(font);
LV_ASSERT_NULL(path);

lv_result_t result = LV_RESULT_INVALID;

lv_fs_file_t file;
lv_fs_res_t fs_res = lv_fs_open(&file, path, LV_FS_MODE_RD);
if(fs_res != LV_FS_RES_OK) return result;
if(fs_res != LV_FS_RES_OK) return NULL;

lv_memzero(font, sizeof(lv_font_t));
if(lvgl_load_font(&file, font)) {
result = LV_RESULT_OK;
}
else {
LV_LOG_WARN("Error loading font file: %s\n", path);
lv_font_t * font = lv_malloc_zeroed(sizeof(lv_font_t));
LV_ASSERT_MALLOC(font);

if(!lvgl_load_font(&file, font)) {
LV_LOG_WARN("Error loading font file: %s", path);
/*
* When `lvgl_load_font` fails it can leak some pointers.
* All non-null pointers can be assumed as allocated and
* `lv_font_free` should free them correctly.
* `lv_binfont_destroy` should free them correctly.
*/
lv_font_free(font);
lv_binfont_destroy(font);
font = NULL;
}

lv_fs_close(&file);

return result;
return font;
}

#if LV_USE_FS_MEMFS
lv_result_t lv_binfont_load_from_buffer(lv_font_t * font, void * buffer, uint32_t size)
lv_font_t * lv_binfont_create_from_buffer(void * buffer, uint32_t size)
{
lv_fs_path_ex_t mempath;

lv_fs_make_path_from_buffer(&mempath, LV_FS_MEMFS_LETTER, buffer, size);
return lv_binfont_load(font, (const char *)&mempath);
return lv_binfont_create((const char *)&mempath);
}
#endif

void lv_font_free(lv_font_t * font)
void lv_binfont_destroy(lv_font_t * font)
{
if(font == NULL) return;

Expand Down Expand Up @@ -155,6 +152,7 @@ void lv_font_free(lv_font_t * font)
lv_free((void *)dsc->glyph_bitmap);
lv_free((void *)dsc->glyph_dsc);
lv_free((void *)dsc);
lv_free(font);
}

/**********************
Expand Down Expand Up @@ -454,9 +452,9 @@ static int32_t load_glyph(lv_fs_file_t * fp, lv_font_fmt_txt_dsc_t * font_dsc,
* the pointer should be set on the `lv_font_t` data before any possible return.
*
* When something fails, it returns `false` and the memory on the `lv_font_t`
* still needs to be freed using `lv_font_free`.
* still needs to be freed using `lv_binfont_destroy`.
*
* `lv_font_free` will assume that all non-null pointers are allocated and
* `lv_binfont_destroy` will assume that all non-null pointers are allocated and
* should be freed.
*/
static bool lvgl_load_font(lv_fs_file_t * fp, lv_font_t * font)
Expand Down
16 changes: 7 additions & 9 deletions src/font/lv_binfont_loader.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,29 +28,27 @@ extern "C" {

/**
* Loads a `lv_font_t` object from a binary font file
* @param font pointer to font where to load
* @param path path where the font file is located
* @return LV_RESULT_OK on success; LV_RESULT_INVALID on error
* @return pointer to font where to load
*/
lv_result_t lv_binfont_load(lv_font_t * font, const char * font_name);
lv_font_t * lv_binfont_create(const char * font_name);

#if LV_USE_FS_MEMFS
/**
* Loads a `lv_font_t` object from a memory buffer containing the binary font file.
* Requires LV_USE_FS_MEMFS
* @param font pointer to font where to load
* @param buffer address of the font file in the memory
* @param size size of the font file buffer
* @return LV_RESULT_OK on success; LV_RESULT_INVALID on error
* @return pointer to font where to load
*/
lv_result_t lv_binfont_load_from_buffer(lv_font_t * font, void * buffer, uint32_t size);
lv_font_t * lv_binfont_create_from_buffer(void * buffer, uint32_t size);
#endif

/**
* Frees the memory allocated by the `lv_binfont_load()` function
* @param font lv_font_t object created by the lv_binfont_load function
* Frees the memory allocated by the `lv_binfont_create()` function
* @param font lv_font_t object created by the lv_binfont_create function
*/
void lv_font_free(lv_font_t * font);
void lv_binfont_destroy(lv_font_t * font);

/**********************
* MACROS
Expand Down
2 changes: 1 addition & 1 deletion src/libs/fsdrv/lv_fs_memfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
*
* The path object can be used at any place where a file path is required, e.g.:
*
* lv_font_t* my_font = lv_binfont_load((const char *) & mempath);
* lv_font_t* my_font = lv_binfont_create((const char *) & mempath);
*
*/

Expand Down
83 changes: 41 additions & 42 deletions tests/src/test_cases/test_font_loader.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,9 @@ extern uint8_t const font_1_buf[6876];
extern uint8_t const font_2_buf[7252];
extern uint8_t const font_3_buf[4892];

static lv_font_t font_1_bin;
static lv_font_t font_2_bin;
static lv_font_t font_3_bin;
static lv_font_t * font_1_bin = NULL;
static lv_font_t * font_2_bin = NULL;
static lv_font_t * font_3_bin = NULL;

void setUp(void)
{
Expand All @@ -68,9 +68,9 @@ void tearDown(void)

static void common(void)
{
compare_fonts(&font_1, &font_1_bin);
compare_fonts(&font_2, &font_2_bin);
compare_fonts(&font_3, &font_3_bin);
compare_fonts(&font_1, font_1_bin);
compare_fonts(&font_2, font_2_bin);
compare_fonts(&font_3, font_3_bin);

/* create labels for testing */
lv_obj_t * scr = lv_screen_active();
Expand All @@ -82,68 +82,65 @@ static void common(void)
lv_obj_set_flex_align(scr, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER, LV_FLEX_ALIGN_CENTER);

lv_label_set_text(label1, "The quick brown fox jumped over the lazy dog");
lv_obj_set_style_text_font(label1, &font_1_bin, 0);
lv_obj_set_style_text_font(label1, font_1_bin, 0);
lv_label_set_text(label2, "The quick brown fox jumped over the lazy dog");
lv_obj_set_style_text_font(label2, &font_2_bin, 0);
lv_obj_set_style_text_font(label2, font_2_bin, 0);
lv_label_set_text(label3, "The quick brown fox jumped over the lazy dog");
lv_obj_set_style_text_font(label3, &font_3_bin, 0);
lv_obj_set_style_text_font(label3, font_3_bin, 0);

TEST_ASSERT_EQUAL_SCREENSHOT("font_loader_1.png");

lv_obj_clean(lv_screen_active());

lv_font_free(&font_1_bin);
lv_font_free(&font_2_bin);
lv_font_free(&font_3_bin);
lv_binfont_destroy(font_1_bin);
lv_binfont_destroy(font_2_bin);
lv_binfont_destroy(font_3_bin);
}

void test_font_loader_with_cache(void)
{
/*Test with cache ('A' has cache)*/
lv_result_t res;

res = lv_binfont_load(&font_1_bin, "A:src/test_assets/font_1.fnt");
TEST_ASSERT_EQUAL(LV_RESULT_OK, res);
font_1_bin = lv_binfont_create("A:src/test_assets/font_1.fnt");
TEST_ASSERT_NOT_NULL(font_1_bin);

res = lv_binfont_load(&font_2_bin, "A:src/test_assets/font_2.fnt");
TEST_ASSERT_EQUAL(LV_RESULT_OK, res);
font_2_bin = lv_binfont_create("A:src/test_assets/font_2.fnt");
TEST_ASSERT_NOT_NULL(font_2_bin);

res = lv_binfont_load(&font_3_bin, "A:src/test_assets/font_3.fnt");
TEST_ASSERT_EQUAL(LV_RESULT_OK, res);
font_3_bin = lv_binfont_create("A:src/test_assets/font_3.fnt");
TEST_ASSERT_NOT_NULL(font_3_bin);

common();
}

void test_font_loader_no_cache(void)
{
/*Test without cache ('B' has NO cache)*/
lv_result_t res;

res = lv_binfont_load(&font_1_bin, "B:src/test_assets/font_1.fnt");
TEST_ASSERT_EQUAL(LV_RESULT_OK, res);
font_1_bin = lv_binfont_create("B:src/test_assets/font_1.fnt");
TEST_ASSERT_NOT_NULL(font_1_bin);

res = lv_binfont_load(&font_2_bin, "B:src/test_assets/font_2.fnt");
TEST_ASSERT_EQUAL(LV_RESULT_OK, res);
font_2_bin = lv_binfont_create("B:src/test_assets/font_2.fnt");
TEST_ASSERT_NOT_NULL(font_2_bin);

res = lv_binfont_load(&font_3_bin, "B:src/test_assets/font_3.fnt");
TEST_ASSERT_EQUAL(LV_RESULT_OK, res);
font_3_bin = lv_binfont_create("B:src/test_assets/font_3.fnt");
TEST_ASSERT_NOT_NULL(font_3_bin);

common();
}

void test_font_loader_from_buffer(void)
{
/*Test with memfs*/
lv_result_t res;

res = lv_binfont_load_from_buffer(&font_1_bin, (void *)&font_1_buf, sizeof(font_1_buf));
TEST_ASSERT_EQUAL(LV_RESULT_OK, res);
font_1_bin = lv_binfont_create_from_buffer((void *)&font_1_buf, sizeof(font_1_buf));
TEST_ASSERT_NOT_NULL(font_1_bin);

res = lv_binfont_load_from_buffer(&font_2_bin, (void *)&font_2_buf, sizeof(font_2_buf));
TEST_ASSERT_EQUAL(LV_RESULT_OK, res);
font_2_bin = lv_binfont_create_from_buffer((void *)&font_2_buf, sizeof(font_2_buf));
TEST_ASSERT_NOT_NULL(font_2_bin);

res = lv_binfont_load_from_buffer(&font_3_bin, (void *)&font_3_buf, sizeof(font_3_buf));
TEST_ASSERT_EQUAL(LV_RESULT_OK, res);
font_3_bin = lv_binfont_create_from_buffer((void *)&font_3_buf, sizeof(font_3_buf));
TEST_ASSERT_NOT_NULL(font_3_bin);

common();
}
Expand All @@ -156,27 +153,29 @@ void test_font_loader_reload(void)
lv_obj_center(label);
lv_label_set_text(label, "The quick brown fox jumped over the lazy dog");

lv_font_t font;
lv_result_t res;
res = lv_binfont_load(&font, "A:src/test_assets/font_2.fnt");
TEST_ASSERT_EQUAL(LV_RESULT_OK, res);
lv_font_t style_font;
lv_font_t * font;
font = lv_binfont_create("A:src/test_assets/font_2.fnt");
TEST_ASSERT_NOT_NULL(font);
lv_memcpy(&style_font, font, sizeof(lv_font_t));

lv_obj_set_style_text_font(label, &font, 0);
lv_obj_set_style_text_font(label, &style_font, 0);

TEST_ASSERT_EQUAL_SCREENSHOT("font_loader_2.png");

lv_font_free(&font);
lv_binfont_destroy(font);

res = lv_binfont_load(&font, "A:src/test_assets/font_3.fnt");
TEST_ASSERT_EQUAL(LV_RESULT_OK, res);
font = lv_binfont_create("A:src/test_assets/font_3.fnt");
TEST_ASSERT_NOT_NULL(font);
lv_memcpy(&style_font, font, sizeof(lv_font_t));

lv_obj_report_style_change(NULL);

TEST_ASSERT_EQUAL_SCREENSHOT("font_loader_3.png");

lv_obj_delete(label);

lv_font_free(&font);
lv_binfont_destroy(font);
}

static int compare_fonts(lv_font_t * f1, lv_font_t * f2)
Expand Down

0 comments on commit 106519b

Please sign in to comment.