diff --git a/docs/src/details/auxiliary-modules/xml/component_library.rst b/docs/src/details/auxiliary-modules/xml/component_library.rst
index d91a5b52af..b51df1d1fa 100644
--- a/docs/src/details/auxiliary-modules/xml/component_library.rst
+++ b/docs/src/details/auxiliary-modules/xml/component_library.rst
@@ -163,6 +163,6 @@ A ``globals.xml`` file of a component library can look like this:
-
+
diff --git a/docs/src/details/auxiliary-modules/xml/fonts.rst b/docs/src/details/auxiliary-modules/xml/fonts.rst
index e3b6eec775..41f190e1d9 100644
--- a/docs/src/details/auxiliary-modules/xml/fonts.rst
+++ b/docs/src/details/auxiliary-modules/xml/fonts.rst
@@ -29,7 +29,7 @@ In ```` and ````, fonts can be referenced by their name, e.g.,
-The tag name determines how the font is loaded. Currently, only ``tinyttf as_file="true"`` is supported.
+The tag name determines how the font is loaded. Currently, only ``tiny_ttf as_file="true"`` is supported.
- ``bin``:
@@ -38,7 +38,7 @@ The tag name determines how the font is loaded. Currently, only ``tinyttf as_fil
- If ``as_file="false"`` (default): On export, the font file will be converted to a C array LVGL font
that can be used directly by LVGL.
-- ``tinyttf``:
+- ``tiny_ttf``:
- If ``as_file="true"``: Can be loaded directly by ``lv_tiny_ttf_create_file()``.
- If ``as_file="false"`` (default): The font file will be converted to a raw C array on export
diff --git a/examples/others/xml/lv_example_xml_2.c b/examples/others/xml/lv_example_xml_2.c
index 65fb37e38f..eac2fd2e81 100644
--- a/examples/others/xml/lv_example_xml_2.c
+++ b/examples/others/xml/lv_example_xml_2.c
@@ -15,7 +15,7 @@ void lv_example_xml_2(void)
lv_xml_component_register_from_file("A:lvgl/examples/others/xml/my_button.xml");
lv_xml_component_register_from_file("A:lvgl/examples/others/xml/view.xml");
- lv_xml_register_font("lv_montserrat_18", &lv_font_montserrat_18);
+ lv_xml_register_font(NULL, "lv_montserrat_18", &lv_font_montserrat_18);
lv_obj_t * obj = lv_xml_create(lv_screen_active(), "view", NULL);
lv_obj_set_pos(obj, 10, 10);
diff --git a/src/others/xml/lv_xml.c b/src/others/xml/lv_xml.c
index 092670e352..b8174cf5cf 100644
--- a/src/others/xml/lv_xml.c
+++ b/src/others/xml/lv_xml.c
@@ -195,7 +195,7 @@ const lv_font_t * lv_xml_get_font(lv_xml_component_ctx_t * ctx, const char * nam
}
/*If not found in the component check the global space*/
- if(!lv_streq(ctx->name, "globals")) {
+ if(ctx == NULL || !lv_streq(ctx->name, "globals")) {
ctx = lv_xml_component_get_ctx("globals");
if(ctx) {
LV_LL_READ(&ctx->font_ll, f) {
@@ -233,7 +233,7 @@ lv_subject_t * lv_xml_get_subject(lv_xml_component_ctx_t * ctx, const char * nam
}
/*If not found in the component check the global space*/
- if(!lv_streq(ctx->name, "globals")) {
+ if(ctx == NULL || !lv_streq(ctx->name, "globals")) {
ctx = lv_xml_component_get_ctx("globals");
if(ctx) {
LV_LL_READ(&ctx->subjects_ll, s) {
@@ -277,7 +277,7 @@ const char * lv_xml_get_const(lv_xml_component_ctx_t * ctx, const char * name)
}
/*If not found in the component check the global space*/
- if(!lv_streq(ctx->name, "globals")) {
+ if(ctx == NULL || !lv_streq(ctx->name, "globals")) {
ctx = lv_xml_component_get_ctx("globals");
if(ctx) {
LV_LL_READ(&ctx->const_ll, cnst) {
@@ -325,7 +325,7 @@ const void * lv_xml_get_image(lv_xml_component_ctx_t * ctx, const char * name)
}
/*If not found in the component check the global space*/
- if(!lv_streq(ctx->name, "globals")) {
+ if(ctx == NULL || !lv_streq(ctx->name, "globals")) {
ctx = lv_xml_component_get_ctx("globals");
if(ctx) {
LV_LL_READ(&ctx->image_ll, img) {
@@ -367,7 +367,7 @@ lv_event_cb_t lv_xml_get_event_cb(lv_xml_component_ctx_t * ctx, const char * nam
}
/*If not found in the component check the global space*/
- if(!lv_streq(ctx->name, "globals")) {
+ if(ctx == NULL || !lv_streq(ctx->name, "globals")) {
ctx = lv_xml_component_get_ctx("globals");
if(ctx) {
LV_LL_READ(&ctx->event_ll, e) {
diff --git a/src/others/xml/lv_xml_component.c b/src/others/xml/lv_xml_component.c
index fa55aa6c07..6996532357 100644
--- a/src/others/xml/lv_xml_component.c
+++ b/src/others/xml/lv_xml_component.c
@@ -9,6 +9,7 @@
#include "lv_xml_component.h"
#if LV_USE_XML
+#include "../../lvgl.h"
#include "lv_xml_component_private.h"
#include "lv_xml_private.h"
#include "lv_xml_parser.h"
@@ -34,6 +35,8 @@
static void start_metadata_handler(void * user_data, const char * name, const char ** attrs);
static void end_metadata_handler(void * user_data, const char * name);
static void process_const_element(lv_xml_parser_state_t * state, const char ** attrs);
+static void process_font_element(lv_xml_parser_state_t * state, const char * type, const char ** attrs);
+static void process_image_element(lv_xml_parser_state_t * state, const char * type, const char ** attrs);
static void process_prop_element(lv_xml_parser_state_t * state, const char ** attrs);
static char * extract_view_content(const char * xml_definition);
@@ -242,6 +245,19 @@ lv_result_t lv_xml_component_unregister(const char * name)
lv_ll_clear(&ctx->param_ll);
+ lv_xml_font_t * font;
+ LV_LL_READ(&ctx->font_ll, font) {
+ lv_free((char *)font->name);
+ }
+ lv_ll_clear(&ctx->image_ll);
+
+ lv_xml_image_t * image;
+ LV_LL_READ(&ctx->image_ll, image) {
+ lv_free((char *)image->name);
+ lv_free((char *)image->src);
+ }
+ lv_ll_clear(&ctx->image_ll);
+
lv_xml_style_t * style;
LV_LL_READ(&ctx->style_ll, style) {
lv_free((char *)style->name);
@@ -294,6 +310,97 @@ static void process_const_element(lv_xml_parser_state_t * state, const char ** a
lv_xml_register_const(&state->ctx, name, value);
}
+static void process_font_element(lv_xml_parser_state_t * state, const char * type, const char ** attrs)
+{
+ const char * name = lv_xml_get_value_of(attrs, "name");
+ if(name == NULL) {
+ LV_LOG_WARN("'name' is missing from a font");
+ return;
+ }
+
+ const char * src_path = lv_xml_get_value_of(attrs, "src_path");
+ if(src_path == NULL) {
+ LV_LOG_WARN("'src_path' is missing from a `%s` font", name);
+ return;
+ }
+
+ const char * as_file = lv_xml_get_value_of(attrs, "as_file");
+ if(as_file == NULL || as_file == false) {
+ LV_LOG_INFO("Ignore non-file based font `%s`", name);
+ return;
+ }
+
+ /*E.g. */
+ if(lv_streq(type, "tiny_ttf")) {
+ const char * size = lv_xml_get_value_of(attrs, "size");
+ if(size == NULL) {
+ LV_LOG_WARN("'size' is missing from a `%s` tiny_ttf font", name);
+ return;
+ }
+#if LV_TINY_TTF_FILE_SUPPORT
+ lv_font_t * font = lv_tiny_ttf_create_file(src_path, lv_xml_atoi(size));
+ if(font == NULL) {
+ LV_LOG_WARN("Couldn't load `%s` tiny_ttf font", name);
+ return;
+ }
+ lv_result_t res = lv_xml_register_font(&state->ctx, name, font);
+ if(res == LV_RESULT_INVALID) {
+ LV_LOG_WARN("Failed to register `%s` tiny_ttf font", name);
+ return;
+ }
+
+ lv_xml_font_t * f = lv_ll_get_head(&state->ctx.font_ll);
+ f->font_destroy_cb = lv_tiny_ttf_destroy;
+
+#else
+ LV_LOG_WARN("LV_TINY_TTF_FILE_SUPPORT is not enabled for `%s` font", name);
+
+#endif
+ }
+ else if(lv_streq(type, "bin")) {
+ lv_font_t * font = lv_binfont_create(src_path);
+ if(font == NULL) {
+ LV_LOG_WARN("Couldn't load `%s` bin font", name);
+ return;
+ }
+
+ lv_result_t res = lv_xml_register_font(&state->ctx, name, font);
+ if(res == LV_RESULT_INVALID) {
+ LV_LOG_WARN("Failed to register `%s` bin font", name);
+ return;
+ }
+
+ lv_xml_font_t * f = lv_ll_get_head(&state->ctx.font_ll);
+ f->font_destroy_cb = lv_binfont_destroy;
+ }
+ else {
+ LV_LOG_WARN("`%s` is a not supported font type", type);
+ }
+}
+
+static void process_image_element(lv_xml_parser_state_t * state, const char * type, const char ** attrs)
+{
+ const char * name = lv_xml_get_value_of(attrs, "name");
+ if(name == NULL) {
+ LV_LOG_WARN("'name' is missing from a font");
+ return;
+ }
+
+ const char * src_path = lv_xml_get_value_of(attrs, "src_path");
+ if(src_path == NULL) {
+ LV_LOG_WARN("'src_path' is missing from a `%s` font", name);
+ return;
+ }
+
+ /* E.g. */
+ if(lv_streq(type, "file")) {
+ lv_xml_register_image(&state->ctx, name, src_path);
+ }
+ else {
+ LV_LOG_INFO("Ignore non-file image `%s`", name);
+ }
+}
+
static void process_subject_element(lv_xml_parser_state_t * state, const char * type, const char ** attrs)
{
const char * name = lv_xml_get_value_of(attrs, "name");
@@ -310,7 +417,6 @@ static void process_subject_element(lv_xml_parser_state_t * state, const char *
lv_subject_t * subject = lv_malloc(sizeof(lv_subject_t));
-
if(lv_streq(type, "int")) lv_subject_init_int(subject, lv_xml_atoi(value));
else if(lv_streq(type, "color")) lv_subject_init_color(subject, lv_xml_to_color(value));
else if(lv_streq(type, "string")) {
@@ -540,6 +646,14 @@ static void start_metadata_handler(void * user_data, const char * name, const ch
if(old_section != state->section) return; /*Ignore the section opening, e.g. */
lv_xml_style_register(&state->ctx, attrs);
break;
+ case LV_XML_PARSER_SECTION_FONTS:
+ if(old_section != state->section) return; /*Ignore the section opening, e.g. */
+ process_font_element(state, name, attrs);
+ break;
+ case LV_XML_PARSER_SECTION_IMAGES:
+ if(old_section != state->section) return; /*Ignore the section opening, e.g. */
+ process_image_element(state, name, attrs);
+ break;
case LV_XML_PARSER_SECTION_SUBJECTS:
if(old_section != state->section) return; /*Ignore the section opening, e.g. */
diff --git a/src/others/xml/lv_xml_parser.c b/src/others/xml/lv_xml_parser.c
index bb2e425c45..d140bbb58e 100644
--- a/src/others/xml/lv_xml_parser.c
+++ b/src/others/xml/lv_xml_parser.c
@@ -69,6 +69,14 @@ void lv_xml_parser_start_section(lv_xml_parser_state_t * state, const char * nam
state->section = LV_XML_PARSER_SECTION_STYLES;
return;
}
+ else if(lv_streq(name, "images")) {
+ state->section = LV_XML_PARSER_SECTION_IMAGES;
+ return;
+ }
+ else if(lv_streq(name, "fonts")) {
+ state->section = LV_XML_PARSER_SECTION_FONTS;
+ return;
+ }
else if(lv_streq(name, "subjects")) {
state->section = LV_XML_PARSER_SECTION_SUBJECTS;
return;
diff --git a/src/others/xml/lv_xml_parser.h b/src/others/xml/lv_xml_parser.h
index a7956cd36d..bf56579f34 100644
--- a/src/others/xml/lv_xml_parser.h
+++ b/src/others/xml/lv_xml_parser.h
@@ -35,6 +35,8 @@ typedef enum {
LV_XML_PARSER_SECTION_GRAD,
LV_XML_PARSER_SECTION_GRAD_STOP,
LV_XML_PARSER_SECTION_STYLES,
+ LV_XML_PARSER_SECTION_FONTS,
+ LV_XML_PARSER_SECTION_IMAGES,
LV_XML_PARSER_SECTION_SUBJECTS,
LV_XML_PARSER_SECTION_VIEW
} lv_xml_parser_section_t;
diff --git a/src/others/xml/lv_xml_private.h b/src/others/xml/lv_xml_private.h
index 6c6a26b88c..71abee3da5 100644
--- a/src/others/xml/lv_xml_private.h
+++ b/src/others/xml/lv_xml_private.h
@@ -33,6 +33,7 @@ extern "C" {
typedef struct {
const char * name;
const lv_font_t * font;
+ void (*font_destroy_cb)(lv_font_t *);
} lv_xml_font_t;
typedef struct {
diff --git a/tests/src/lv_test_conf_full.h b/tests/src/lv_test_conf_full.h
index 6646b5498a..68e93bff27 100644
--- a/tests/src/lv_test_conf_full.h
+++ b/tests/src/lv_test_conf_full.h
@@ -90,6 +90,7 @@
#define LV_USE_OBSERVER 1
#define LV_USE_FILE_EXPLORER 1
#define LV_USE_TINY_TTF 1
+#define LV_TINY_TTF_FILE_SUPPORT 1
#define LV_USE_SYSMON 1
#define LV_USE_MEM_MONITOR 1
#define LV_USE_PERF_MONITOR 1
diff --git a/tests/src/test_assets/xml/globals.xml b/tests/src/test_assets/xml/globals.xml
index 9b6782b620..98bbe29ba5 100644
--- a/tests/src/test_assets/xml/globals.xml
+++ b/tests/src/test_assets/xml/globals.xml
@@ -1,15 +1,29 @@
-
-
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/src/test_cases/xml/test_xml_view3.c b/tests/src/test_cases/xml/test_xml_view3.c
index 00ae4b8b99..7f0e5ac30c 100644
--- a/tests/src/test_cases/xml/test_xml_view3.c
+++ b/tests/src/test_cases/xml/test_xml_view3.c
@@ -22,6 +22,11 @@ void test_xml_view3_scoping(void)
lv_xml_create(lv_screen_active(), "view3", NULL);
TEST_ASSERT_EQUAL_SCREENSHOT("xml/view3.png");
+
+ /*Fonts and image defined in globals.xml*/
+ TEST_ASSERT_NOT_EQUAL(lv_font_get_default(), lv_xml_get_font(NULL, "my_bin_font"));
+ TEST_ASSERT_NOT_EQUAL(lv_font_get_default(), lv_xml_get_font(NULL, "noto_32"));
+ TEST_ASSERT_EQUAL_STRING("A:src/test_assets/test_img_lvgl_logo.png", lv_xml_get_image(NULL, "logo"));
}
#endif