From ec7f5f73d9357cce3c866732653a7e3c66a81204 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Thu, 14 Aug 2025 19:23:38 +0200 Subject: [PATCH] refactor(text): use struct to pass params to lv_text_* and lv_font_* functions (#8500) Co-authored-by: Erik Tagirov Co-authored-by: liamHowatt --- demos/benchmark/lv_demo_benchmark.c | 7 +- demos/widgets/lv_demo_widgets.c | 2 - demos/widgets/lv_demo_widgets_analytics.c | 6 +- demos/widgets/lv_demo_widgets_profile.c | 6 +- examples/widgets/bar/lv_example_bar_6.c | 9 +- examples/widgets/scale/lv_example_scale_7.c | 9 +- examples/widgets/slider/lv_example_slider_3.c | 8 +- scripts/code-format.cfg | 3 + src/draw/lv_draw_label.c | 43 +++--- src/draw/lv_draw_rect.c | 10 +- src/draw/nema_gfx/lv_draw_nema_gfx_label.c | 30 ++--- src/draw/sw/lv_draw_sw.c | 9 +- src/drivers/uefi/lv_uefi_indev_keyboard.c | 4 +- src/drivers/uefi/lv_uefi_indev_pointer.c | 4 +- src/drivers/uefi/lv_uefi_indev_touch.c | 4 +- src/font/lv_font.c | 12 +- src/font/lv_font.h | 5 +- src/libs/svg/lv_svg_render.c | 6 +- src/misc/lv_text.c | 107 +++++++-------- src/misc/lv_text.h | 78 +++++------ src/misc/lv_text_private.h | 33 +++-- src/widgets/animimage/lv_animimage.c | 2 +- src/widgets/arclabel/lv_arclabel.c | 9 +- src/widgets/buttonmatrix/lv_buttonmatrix.c | 11 +- src/widgets/checkbox/lv_checkbox.c | 21 ++- src/widgets/dropdown/lv_dropdown.c | 18 ++- src/widgets/image/lv_image.c | 22 ++- src/widgets/label/lv_label.c | 127 ++++++++++-------- src/widgets/roller/lv_roller.c | 17 ++- src/widgets/scale/lv_scale.c | 14 +- src/widgets/span/lv_span.c | 19 ++- src/widgets/table/lv_table.c | 32 +++-- src/widgets/textarea/lv_textarea.c | 6 +- tests/src/test_cases/libs/test_freetype.c | 1 - tests/src/test_cases/test_txt.c | 9 +- tests/src/test_cases/widgets/test_chart.c | 9 +- tests/src/test_cases/widgets/test_scale.c | 8 +- tests/src/test_cases_perf/test_label.c | 20 +++ 38 files changed, 455 insertions(+), 285 deletions(-) create mode 100644 tests/src/test_cases_perf/test_label.c diff --git a/demos/benchmark/lv_demo_benchmark.c b/demos/benchmark/lv_demo_benchmark.c index 8f5297c15b..557a41eb1e 100644 --- a/demos/benchmark/lv_demo_benchmark.c +++ b/demos/benchmark/lv_demo_benchmark.c @@ -228,8 +228,11 @@ static void multiple_labels_cb(void) #endif lv_point_t s; - lv_text_get_size(&s, "Hello LVGL!", lv_obj_get_style_text_font(scr, LV_PART_MAIN), 0, 0, LV_COORD_MAX, - LV_TEXT_FLAG_NONE); + lv_text_attributes_t attributes; + lv_text_attributes_init(&attributes); + attributes.max_width = LV_COORD_MAX; + + lv_text_get_size(&s, "Hello LVGL!", lv_obj_get_style_text_font(scr, 0), &attributes); int32_t hor_cnt = ((int32_t)lv_obj_get_content_width(scr)) / (s.x * 3 / 2); int32_t ver_cnt = ((int32_t)lv_obj_get_content_height(scr)) / (s.y * 3); diff --git a/demos/widgets/lv_demo_widgets.c b/demos/widgets/lv_demo_widgets.c index 8185e218af..33265f7352 100644 --- a/demos/widgets/lv_demo_widgets.c +++ b/demos/widgets/lv_demo_widgets.c @@ -265,8 +265,6 @@ static void color_event_cb(lv_event_t * e) } } - - static void scroll_anim_y_cb(void * var, int32_t v) { lv_obj_scroll_to_y(var, v, LV_ANIM_OFF); diff --git a/demos/widgets/lv_demo_widgets_analytics.c b/demos/widgets/lv_demo_widgets_analytics.c index d8ba8147de..19a1aedc07 100644 --- a/demos/widgets/lv_demo_widgets_analytics.c +++ b/demos/widgets/lv_demo_widgets_analytics.c @@ -668,8 +668,12 @@ static void chart_event_cb(lv_event_t * e) char buf[8]; lv_snprintf(buf, sizeof(buf), "%"LV_PRId32, lv_chart_get_series_y_array(obj, (lv_chart_series_t *)ser)[base_dsc->id2]); + lv_text_attributes_t attributes; + lv_text_attributes_init(&attributes); + attributes.max_width = LV_COORD_MAX; + attributes.text_flags = LV_TEXT_FLAG_NONE; lv_point_t text_size; - lv_text_get_size(&text_size, buf, font_normal, 0, 0, LV_COORD_MAX, LV_TEXT_FLAG_NONE); + lv_text_get_size(&text_size, buf, font_normal, &attributes); lv_area_t txt_area; lv_area_t draw_task_area; diff --git a/demos/widgets/lv_demo_widgets_profile.c b/demos/widgets/lv_demo_widgets_profile.c index 54962313aa..aa4b224dd3 100644 --- a/demos/widgets/lv_demo_widgets_profile.c +++ b/demos/widgets/lv_demo_widgets_profile.c @@ -457,8 +457,12 @@ static void slider_event_cb(lv_event_t * e) char buf[8]; lv_snprintf(buf, sizeof(buf), "%"LV_PRId32, lv_slider_get_value(obj)); + lv_text_attributes_t attributes; + lv_text_attributes_init(&attributes); + attributes.max_width = LV_COORD_MAX; + attributes.text_flags = LV_TEXT_FLAG_NONE; lv_point_t text_size; - lv_text_get_size(&text_size, buf, font_normal, 0, 0, LV_COORD_MAX, LV_TEXT_FLAG_NONE); + lv_text_get_size(&text_size, buf, font_normal, &attributes); lv_area_t txt_area; lv_area_t draw_task_area; diff --git a/examples/widgets/bar/lv_example_bar_6.c b/examples/widgets/bar/lv_example_bar_6.c index be8bcf1cbb..a7cece1d3b 100644 --- a/examples/widgets/bar/lv_example_bar_6.c +++ b/examples/widgets/bar/lv_example_bar_6.c @@ -20,9 +20,14 @@ static void event_cb(lv_event_t * e) char buf[8]; lv_snprintf(buf, sizeof(buf), "%d", (int)lv_bar_get_value(obj)); + lv_text_attributes_t attributes = {0}; + attributes.letter_space = label_dsc.letter_space; + attributes.line_space = label_dsc.line_space; + attributes.max_width = LV_COORD_MAX; + attributes.text_flags = label_dsc.flag; + lv_point_t txt_size; - lv_text_get_size(&txt_size, buf, label_dsc.font, label_dsc.letter_space, label_dsc.line_space, LV_COORD_MAX, - label_dsc.flag); + lv_text_get_size(&txt_size, buf, label_dsc.font, &attributes); lv_area_t txt_area; txt_area.x1 = 0; diff --git a/examples/widgets/scale/lv_example_scale_7.c b/examples/widgets/scale/lv_example_scale_7.c index 8bf376ecaf..eb22749c62 100644 --- a/examples/widgets/scale/lv_example_scale_7.c +++ b/examples/widgets/scale/lv_example_scale_7.c @@ -33,8 +33,15 @@ static void draw_event_cb(lv_event_t * e) label_draw_dsc->text = lv_strdup(tmp_buffer); label_draw_dsc->text_local = 1; + lv_text_attributes_t attributes = {0}; lv_point_t size; - lv_text_get_size(&size, label_draw_dsc->text, label_draw_dsc->font, 0, 0, 1000, LV_TEXT_FLAG_NONE); + + attributes.text_flags = LV_TEXT_FLAG_NONE; + attributes.letter_space = 0; + attributes.line_space = 0; + attributes.max_width = 1000; + + lv_text_get_size(&size, label_draw_dsc->text, label_draw_dsc->font, &attributes); int32_t new_w = size.x; int32_t old_w = lv_area_get_width(&draw_task->area); diff --git a/examples/widgets/slider/lv_example_slider_3.c b/examples/widgets/slider/lv_example_slider_3.c index 198ce021a4..19495f5df0 100644 --- a/examples/widgets/slider/lv_example_slider_3.c +++ b/examples/widgets/slider/lv_example_slider_3.c @@ -46,8 +46,14 @@ static void slider_event_cb(lv_event_t * e) char buf[16]; lv_snprintf(buf, sizeof(buf), "%d - %d", (int)lv_slider_get_left_value(obj), (int)lv_slider_get_value(obj)); + lv_text_attributes_t attributes = {0}; + attributes.text_flags = LV_TEXT_FLAG_NONE; + attributes.max_width = LV_COORD_MAX; + attributes.letter_space = 0; + attributes.line_space = 0; + lv_point_t label_size; - lv_text_get_size(&label_size, buf, LV_FONT_DEFAULT, 0, 0, LV_COORD_MAX, LV_TEXT_FLAG_NONE); + lv_text_get_size(&label_size, buf, LV_FONT_DEFAULT, &attributes); lv_area_t label_area; label_area.x1 = 0; label_area.x2 = label_size.x - 1; diff --git a/scripts/code-format.cfg b/scripts/code-format.cfg index 3caae375bf..3ee0adcf3e 100644 --- a/scripts/code-format.cfg +++ b/scripts/code-format.cfg @@ -59,3 +59,6 @@ --exclude=../tests/test_images --exclude=../tests/build_test_defheap --exclude=../tests/build_test_sysheap +--exclude=../tests/build_test_vg_lite +--exclude=../tests/build_test_perf32b +--exclude=../tests/build_test_perf64b diff --git a/src/draw/lv_draw_label.c b/src/draw/lv_draw_label.c index 47e6386518..bcf4b2defe 100644 --- a/src/draw/lv_draw_label.c +++ b/src/draw/lv_draw_label.c @@ -137,6 +137,7 @@ void LV_ATTRIBUTE_FAST_MEM lv_draw_character(lv_layer_t * layer, lv_draw_label_d LV_PROFILER_DRAW_BEGIN; lv_font_glyph_dsc_t g; + lv_font_get_glyph_dsc(dsc->font, &g, unicode_letter, 0); lv_area_t a; @@ -175,6 +176,7 @@ void LV_ATTRIBUTE_FAST_MEM lv_draw_letter(lv_layer_t * layer, lv_draw_letter_dsc LV_PROFILER_DRAW_BEGIN; lv_font_glyph_dsc_t g; + lv_font_get_glyph_dsc(font, &g, dsc->unicode, 0); font = g.resolved_font ? g.resolved_font : dsc->font; @@ -223,9 +225,15 @@ void lv_draw_label_iterate_characters(lv_draw_task_t * t, const lv_draw_label_ds w = dsc->text_size.x; } else { + lv_text_attributes_t attributes = {0}; + + attributes.letter_space = dsc->letter_space; + attributes.line_space = dsc->line_space; + attributes.max_width = LV_COORD_MAX; + attributes.text_flags = dsc->flag; + lv_point_t p; - lv_text_get_size(&p, dsc->text, dsc->font, dsc->letter_space, dsc->line_space, LV_COORD_MAX, - dsc->flag); + lv_text_get_size(&p, dsc->text, dsc->font, &attributes); w = p.x; } } @@ -263,15 +271,18 @@ void lv_draw_label_iterate_characters(lv_draw_task_t * t, const lv_draw_label_ds } uint32_t remaining_len = dsc->text_length; + lv_text_attributes_t attributes = {0}; + attributes.letter_space = dsc->letter_space; + attributes.text_flags = dsc->flag; + attributes.max_width = w; - uint32_t line_end = line_start + lv_text_get_next_line(&dsc->text[line_start], remaining_len, font, dsc->letter_space, - w, NULL, dsc->flag); + uint32_t line_end = line_start + lv_text_get_next_line(&dsc->text[line_start], remaining_len, font, NULL, &attributes); /*Go the first visible line*/ while(pos.y + line_height_font < t->clip_area.y1) { /*Go to next line*/ line_start = line_end; - line_end += lv_text_get_next_line(&dsc->text[line_start], remaining_len, font, dsc->letter_space, w, NULL, dsc->flag); + line_end += lv_text_get_next_line(&dsc->text[line_start], remaining_len, font, NULL, &attributes); pos.y += line_height; /*Save at the threshold coordinate*/ @@ -286,16 +297,13 @@ void lv_draw_label_iterate_characters(lv_draw_task_t * t, const lv_draw_label_ds /*Align to middle*/ if(align == LV_TEXT_ALIGN_CENTER) { - line_width = lv_text_get_width_with_flags(&dsc->text[line_start], line_end - line_start, font, dsc->letter_space, - dsc->flag); - + line_width = lv_text_get_width(&dsc->text[line_start], line_end - line_start, font, &attributes); pos.x += (lv_area_get_width(coords) - line_width) / 2; } /*Align to the right*/ else if(align == LV_TEXT_ALIGN_RIGHT) { - line_width = lv_text_get_width_with_flags(&dsc->text[line_start], line_end - line_start, font, dsc->letter_space, - dsc->flag); + line_width = lv_text_get_width(&dsc->text[line_start], line_end - line_start, font, &attributes); pos.x += lv_area_get_width(coords) - line_width; } @@ -514,25 +522,31 @@ void lv_draw_label_iterate_characters(lv_draw_task_t * t, const lv_draw_label_ds lv_free(bidi_txt); bidi_txt = NULL; #endif + + lv_text_attributes_t text_attributes = {0}; + text_attributes.letter_space = dsc->letter_space; + text_attributes.text_flags = dsc->flag; + text_attributes.max_width = w; + /*Go to next line*/ remaining_len -= line_end - line_start; line_start = line_end; if(remaining_len) { - line_end += lv_text_get_next_line(&dsc->text[line_start], remaining_len, font, dsc->letter_space, w, NULL, dsc->flag); + line_end += lv_text_get_next_line(&dsc->text[line_start], remaining_len, font, NULL, &text_attributes); } pos.x = coords->x1; /*Align to middle*/ if(align == LV_TEXT_ALIGN_CENTER) { line_width = - lv_text_get_width_with_flags(&dsc->text[line_start], line_end - line_start, font, dsc->letter_space, dsc->flag); + lv_text_get_width(&dsc->text[line_start], line_end - line_start, font, &text_attributes); pos.x += (lv_area_get_width(coords) - line_width) / 2; } /*Align to the right*/ else if(align == LV_TEXT_ALIGN_RIGHT) { line_width = - lv_text_get_width_with_flags(&dsc->text[line_start], line_end - line_start, font, dsc->letter_space, dsc->flag); + lv_text_get_width(&dsc->text[line_start], line_end - line_start, font, &text_attributes); pos.x += lv_area_get_width(coords) - line_width; } @@ -575,7 +589,7 @@ void lv_draw_unit_draw_letter(lv_draw_task_t * t, lv_draw_glyph_dsc_t * dsc, co if(dsc->g == NULL) { dsc->g = &g; /*If the glyph dsc is not set then get it from the font*/ - bool g_ret = lv_font_get_glyph_dsc(font, &g, letter, '\0'); + bool g_ret = lv_font_get_glyph_dsc(font, &g, letter, 0); if(g_ret == false) { /*Add warning if the dsc is not found*/ LV_LOG_WARN("lv_draw_letter: glyph dsc. not found for U+%" LV_PRIX32, letter); @@ -626,7 +640,6 @@ void lv_draw_unit_draw_letter(lv_draw_task_t * t, lv_draw_glyph_dsc_t * dsc, co if(g.format == LV_FONT_GLYPH_FORMAT_VECTOR) { /*Load the outline of the glyph, even if the function says bitmap*/ - g.outline_stroke_width = dsc->outline_stroke_width; dsc->glyph_data = (void *) lv_font_get_glyph_bitmap(dsc->g, draw_buf); dsc->format = dsc->glyph_data ? g.format : LV_FONT_GLYPH_FORMAT_NONE; } diff --git a/src/draw/lv_draw_rect.c b/src/draw/lv_draw_rect.c index 3ee299ac56..6b73daaa9f 100644 --- a/src/draw/lv_draw_rect.c +++ b/src/draw/lv_draw_rect.c @@ -10,6 +10,7 @@ #include "lv_draw_private.h" #include "../core/lv_obj.h" #include "../misc/lv_assert.h" +#include "../misc/lv_text_private.h" #include "../core/lv_obj_event.h" #include "../stdlib/lv_string.h" @@ -273,7 +274,14 @@ void lv_draw_rect(lv_layer_t * layer, const lv_draw_rect_dsc_t * dsc, const lv_a } else { lv_point_t s; - lv_text_get_size(&s, dsc->bg_image_src, dsc->bg_image_symbol_font, 0, 0, LV_COORD_MAX, LV_TEXT_FLAG_NONE); + + lv_text_attributes_t attributes = {0}; + attributes.text_flags = LV_TEXT_FLAG_NONE; + attributes.max_width = LV_COORD_MAX; + attributes.line_space = 0; + attributes.letter_space = 0; + + lv_text_get_size(&s, dsc->bg_image_src, dsc->bg_image_symbol_font, &attributes); lv_area_t a = {0, 0, s.x - 1, s.y - 1}; lv_area_align(coords, &a, LV_ALIGN_CENTER, 0, 0); diff --git a/src/draw/nema_gfx/lv_draw_nema_gfx_label.c b/src/draw/nema_gfx/lv_draw_nema_gfx_label.c index a3920778de..7390ebacd1 100644 --- a/src/draw/nema_gfx/lv_draw_nema_gfx_label.c +++ b/src/draw/nema_gfx/lv_draw_nema_gfx_label.c @@ -414,7 +414,11 @@ static void _draw_label_iterate_characters(lv_draw_task_t * t, const lv_draw_lab const lv_area_t * coords) { const lv_font_t * font = dsc->font; - int32_t w; + lv_text_attributes_t attributes = {0}; + attributes.letter_space = dsc->letter_space; + attributes.line_space = dsc->line_space; + attributes.max_width = LV_COORD_MAX; + attributes.text_flags = dsc->flag; lv_area_t clipped_area; bool clip_ok = lv_area_intersect(&clipped_area, coords, &t->clip_area); @@ -427,14 +431,13 @@ static void _draw_label_iterate_characters(lv_draw_task_t * t, const lv_draw_lab if((dsc->flag & LV_TEXT_FLAG_EXPAND) == 0) { /*Normally use the label's width as width*/ - w = lv_area_get_width(coords); + attributes.max_width = lv_area_get_width(coords); } else { /*If EXPAND is enabled then not limit the text's width to the object's width*/ lv_point_t p; - lv_text_get_size(&p, dsc->text, dsc->font, dsc->letter_space, dsc->line_space, LV_COORD_MAX, - dsc->flag); - w = p.x; + lv_text_get_size(&p, dsc->text, dsc->font, &attributes); + attributes.max_width = p.x; } int32_t line_height_font = lv_font_get_line_height(font); @@ -471,14 +474,13 @@ static void _draw_label_iterate_characters(lv_draw_task_t * t, const lv_draw_lab uint32_t remaining_len = dsc->text_length; - uint32_t line_end = line_start + lv_text_get_next_line(&dsc->text[line_start], remaining_len, font, dsc->letter_space, - w, NULL, dsc->flag); + uint32_t line_end = line_start + lv_text_get_next_line(&dsc->text[line_start], remaining_len, font, NULL, &attributes); /*Go the first visible line*/ while(pos.y + line_height_font < t->clip_area.y1) { /*Go to next line*/ line_start = line_end; - line_end += lv_text_get_next_line(&dsc->text[line_start], remaining_len, font, dsc->letter_space, w, NULL, dsc->flag); + line_end += lv_text_get_next_line(&dsc->text[line_start], remaining_len, font, NULL, &attributes); pos.y += line_height; /*Save at the threshold coordinate*/ @@ -493,16 +495,14 @@ static void _draw_label_iterate_characters(lv_draw_task_t * t, const lv_draw_lab /*Align to middle*/ if(align == LV_TEXT_ALIGN_CENTER) { - line_width = lv_text_get_width_with_flags(&dsc->text[line_start], line_end - line_start, font, dsc->letter_space, - dsc->flag); + line_width = lv_text_get_width(&dsc->text[line_start], line_end - line_start, font, &attributes); pos.x += (lv_area_get_width(coords) - line_width) / 2; } /*Align to the right*/ else if(align == LV_TEXT_ALIGN_RIGHT) { - line_width = lv_text_get_width_with_flags(&dsc->text[line_start], line_end - line_start, font, dsc->letter_space, - dsc->flag); + line_width = lv_text_get_width(&dsc->text[line_start], line_end - line_start, font, &attributes); pos.x += lv_area_get_width(coords) - line_width; } @@ -731,21 +731,21 @@ static void _draw_label_iterate_characters(lv_draw_task_t * t, const lv_draw_lab remaining_len -= line_end - line_start; line_start = line_end; if(remaining_len) { - line_end += lv_text_get_next_line(&dsc->text[line_start], remaining_len, font, dsc->letter_space, w, NULL, dsc->flag); + line_end += lv_text_get_next_line(&dsc->text[line_start], remaining_len, font, NULL, &attributes); } pos.x = coords->x1; /*Align to middle*/ if(align == LV_TEXT_ALIGN_CENTER) { line_width = - lv_text_get_width_with_flags(&dsc->text[line_start], line_end - line_start, font, dsc->letter_space, dsc->flag); + lv_text_get_width(&dsc->text[line_start], line_end - line_start, font, &attributes); pos.x += (lv_area_get_width(coords) - line_width) / 2; } /*Align to the right*/ else if(align == LV_TEXT_ALIGN_RIGHT) { line_width = - lv_text_get_width_with_flags(&dsc->text[line_start], line_end - line_start, font, dsc->letter_space, dsc->flag); + lv_text_get_width(&dsc->text[line_start], line_end - line_start, font, &attributes); pos.x += lv_area_get_width(coords) - line_width; } diff --git a/src/draw/sw/lv_draw_sw.c b/src/draw/sw/lv_draw_sw.c index d1260919cb..7a2a7a23dd 100644 --- a/src/draw/sw/lv_draw_sw.c +++ b/src/draw/sw/lv_draw_sw.c @@ -437,6 +437,13 @@ static void parallel_debug_draw(lv_draw_task_t * t, uint32_t idx) /*Layers manage it for themselves*/ if(t->type != LV_DRAW_TASK_TYPE_LAYER) { lv_area_t draw_area; + lv_text_attributes_t attributes = {0}; + + attributes.text_flags = LV_TEXT_FLAG_NONE; + attributes.line_space = 0; + attributes.letter_space = 0; + attributes.max_width = 100; + if(!lv_area_intersect(&draw_area, &t->area, &t->clip_area)) return; lv_draw_fill_dsc_t fill_dsc; @@ -453,7 +460,7 @@ static void parallel_debug_draw(lv_draw_task_t * t, uint32_t idx) lv_draw_sw_border(t, &border_dsc, &draw_area); lv_point_t txt_size; - lv_text_get_size(&txt_size, "W", LV_FONT_DEFAULT, 0, 0, 100, LV_TEXT_FLAG_NONE); + lv_text_get_size(&txt_size, "W", LV_FONT_DEFAULT, &attributes); lv_area_t txt_area; txt_area.x1 = draw_area.x1; diff --git a/src/drivers/uefi/lv_uefi_indev_keyboard.c b/src/drivers/uefi/lv_uefi_indev_keyboard.c index 308057ccf1..4c8ad0b036 100644 --- a/src/drivers/uefi/lv_uefi_indev_keyboard.c +++ b/src/drivers/uefi/lv_uefi_indev_keyboard.c @@ -10,7 +10,7 @@ #include "../../lvgl.h" #include "../../stdlib/lv_mem.h" #include "../../misc/lv_types.h" -#include "../../misc/lv_text.h" +#include "../../misc/lv_text_private.h" #if LV_USE_UEFI @@ -343,4 +343,4 @@ static uint32_t _key_from_uefi_key(const EFI_KEY_DATA * key) } } -#endif \ No newline at end of file +#endif diff --git a/src/drivers/uefi/lv_uefi_indev_pointer.c b/src/drivers/uefi/lv_uefi_indev_pointer.c index 9e1c512158..4714a61ee9 100644 --- a/src/drivers/uefi/lv_uefi_indev_pointer.c +++ b/src/drivers/uefi/lv_uefi_indev_pointer.c @@ -10,7 +10,7 @@ #include "../../lvgl.h" #include "../../stdlib/lv_mem.h" #include "../../misc/lv_types.h" -#include "../../misc/lv_text.h" +#include "../../misc/lv_text_private.h" #if LV_USE_UEFI @@ -282,4 +282,4 @@ static void _simple_pointer_read(lv_uefi_simple_pointer_context_t * indev_ctx, *was_pressed = state.LeftButton; } -#endif \ No newline at end of file +#endif diff --git a/src/drivers/uefi/lv_uefi_indev_touch.c b/src/drivers/uefi/lv_uefi_indev_touch.c index f76ededdda..3ac227e50f 100644 --- a/src/drivers/uefi/lv_uefi_indev_touch.c +++ b/src/drivers/uefi/lv_uefi_indev_touch.c @@ -10,7 +10,7 @@ #include "../../lvgl.h" #include "../../stdlib/lv_mem.h" #include "../../misc/lv_types.h" -#include "../../misc/lv_text.h" +#include "../../misc/lv_text_private.h" #if LV_USE_UEFI @@ -287,4 +287,4 @@ static void _absolute_pointer_read(lv_uefi_absolute_pointer_context_t * indev_ct *was_pressed = (state.ActiveButtons & EFI_ABSP_TouchActive) != 0; } -#endif \ No newline at end of file +#endif diff --git a/src/font/lv_font.c b/src/font/lv_font.c index 26199fc73f..651998ec92 100644 --- a/src/font/lv_font.c +++ b/src/font/lv_font.c @@ -95,19 +95,20 @@ bool lv_font_get_glyph_dsc(const lv_font_t * font_p, lv_font_glyph_dsc_t * dsc_o uint32_t letter_next) { - LV_ASSERT_NULL(font_p); LV_ASSERT_NULL(dsc_out); + LV_ASSERT_NULL(font_p); #if LV_USE_FONT_PLACEHOLDER const lv_font_t * placeholder_font = NULL; #endif - const lv_font_t * f = font_p; + const bool has_kerning = f->kerning != LV_FONT_KERNING_NONE; lv_memzero(dsc_out, sizeof(lv_font_glyph_dsc_t)); while(f) { - bool found = f->get_glyph_dsc(f, dsc_out, letter, f->kerning == LV_FONT_KERNING_NONE ? 0 : letter_next); + bool found = f->get_glyph_dsc(f, dsc_out, letter, + has_kerning ? letter_next : 0); if(found) { if(!dsc_out->is_placeholder) { dsc_out->resolved_font = f; @@ -125,7 +126,7 @@ bool lv_font_get_glyph_dsc(const lv_font_t * font_p, lv_font_glyph_dsc_t * dsc_o #if LV_USE_FONT_PLACEHOLDER if(placeholder_font != NULL) { placeholder_font->get_glyph_dsc(placeholder_font, dsc_out, letter, - placeholder_font->kerning == LV_FONT_KERNING_NONE ? 0 : letter_next); + has_kerning ? letter_next : 0); dsc_out->resolved_font = placeholder_font; return true; } @@ -147,19 +148,18 @@ bool lv_font_get_glyph_dsc(const lv_font_t * font_p, lv_font_glyph_dsc_t * dsc_o dsc_out->format = LV_FONT_GLYPH_FORMAT_A1; dsc_out->is_placeholder = true; - return false; } uint16_t lv_font_get_glyph_width(const lv_font_t * font, uint32_t letter, uint32_t letter_next) { - LV_ASSERT_NULL(font); lv_font_glyph_dsc_t g; /*Return zero if letter is marker*/ if(lv_text_is_marker(letter)) return 0; lv_font_get_glyph_dsc(font, &g, letter, letter_next); + return g.adv_w; } diff --git a/src/font/lv_font.h b/src/font/lv_font.h index 3d66a93cc8..f12d565a40 100644 --- a/src/font/lv_font.h +++ b/src/font/lv_font.h @@ -68,7 +68,7 @@ typedef struct { * 1: return the bitmap as it is (Maybe A1/2/4 or any proprietary formats). */ uint8_t req_raw_bitmap: 1; - int32_t outline_stroke_width; /**< used with freetype vector fonts - width of the letter outline */ + int32_t outline_stroke_width; /**< used with freetype vector fonts - width of the letter border */ union { uint32_t index; /**< Unicode code point*/ @@ -113,7 +113,7 @@ struct _lv_font_t { int8_t underline_thickness; /**< Thickness of the underline*/ const void * dsc; /**< Store implementation specific or run_time data or caching here*/ - const lv_font_t * fallback; /**< Fallback font for missing glyph. Resolved recursively */ + const lv_font_t * fallback; /**< Fallback font for missing glyph. Resolved recursively */ void * user_data; /**< Custom user data for font.*/ }; @@ -172,7 +172,6 @@ const void * lv_font_get_glyph_static_bitmap(lv_font_glyph_dsc_t * g_dsc); */ bool lv_font_get_glyph_dsc(const lv_font_t * font, lv_font_glyph_dsc_t * dsc_out, uint32_t letter, uint32_t letter_next); - /** * Release the bitmap of a font. * @note You must call lv_font_get_glyph_dsc() to get `g_dsc` (lv_font_glyph_dsc_t) before you can call this function. diff --git a/src/libs/svg/lv_svg_render.c b/src/libs/svg/lv_svg_render.c index 0206a3b366..00a4973453 100644 --- a/src/libs/svg/lv_svg_render.c +++ b/src/libs/svg/lv_svg_render.c @@ -1629,12 +1629,13 @@ static void _render_text(const lv_svg_render_obj_t * obj, lv_vector_dsc_t * dsc, float scale = text->size / 128.0f; for(uint32_t j = 0; j < content->count; j++) { + uint32_t letter = content->letters[j]; if(_is_control_character(letter)) { continue; } lv_font_glyph_dsc_t g; - lv_font_get_glyph_dsc(text->font, &g, letter, '\0'); + lv_font_get_glyph_dsc(text->font, &g, content->letters[j], '\0'); lv_vector_path_t * p = (lv_vector_path_t *)lv_font_get_glyph_bitmap(&g, NULL); lv_vector_path_clear(glyph_path); lv_vector_path_copy(glyph_path, p); @@ -1697,12 +1698,13 @@ static void _render_span(const lv_svg_render_content_t * content, lv_vector_dsc_ float scale = span->size / 128.0f; for(uint32_t j = 0; j < content->count; j++) { + uint32_t letter = content->letters[j]; if(_is_control_character(letter)) { continue; } lv_font_glyph_dsc_t g; - lv_font_get_glyph_dsc(span->font, &g, letter, '\0'); + lv_font_get_glyph_dsc(span->font, &g, content->letters[j], '\0'); lv_vector_path_t * p = (lv_vector_path_t *)lv_font_get_glyph_bitmap(&g, NULL); lv_vector_path_clear(glyph_path); lv_vector_path_copy(glyph_path, p); diff --git a/src/misc/lv_text.c b/src/misc/lv_text.c index de182033b1..2f2f515911 100644 --- a/src/misc/lv_text.c +++ b/src/misc/lv_text.c @@ -88,38 +88,48 @@ /********************** * GLOBAL FUNCTIONS **********************/ - -void lv_text_get_size(lv_point_t * size_res, const char * text, const lv_font_t * font, int32_t letter_space, - int32_t line_space, int32_t max_width, lv_text_flag_t flag) +void lv_text_attributes_init(lv_text_attributes_t * attributes) { + lv_memzero(attributes, sizeof(lv_text_attributes_t)); +} + +void lv_text_get_size(lv_point_t * size_res, const char * text, const lv_font_t * font, + lv_text_attributes_t * attributes) +{ + uint32_t line_start = 0; + uint32_t new_line_start = 0; + uint16_t letter_height = 0; size_res->x = 0; size_res->y = 0; - if(text == NULL) return; - if(font == NULL) return; + LV_ASSERT_NULL(attributes); + LV_ASSERT_NULL(font); + LV_ASSERT_NULL(text); - if(flag & LV_TEXT_FLAG_EXPAND) max_width = LV_COORD_MAX; + letter_height = lv_font_get_line_height(font); - uint32_t line_start = 0; - uint32_t new_line_start = 0; - uint16_t letter_height = lv_font_get_line_height(font); + if(attributes->text_flags & LV_TEXT_FLAG_EXPAND) { + attributes->max_width = LV_COORD_MAX; + } /*Calc. the height and longest line*/ while(text[line_start] != '\0') { - new_line_start += lv_text_get_next_line(&text[line_start], LV_TEXT_LEN_MAX, font, letter_space, max_width, NULL, flag); + new_line_start += lv_text_get_next_line( + &text[line_start], LV_TEXT_LEN_MAX, font, NULL, attributes); - if((unsigned long)size_res->y + (unsigned long)letter_height + (unsigned long)line_space > LV_MAX_OF(int32_t)) { + if((unsigned long)size_res->y + + (unsigned long)letter_height + (unsigned long)attributes->line_space > LV_MAX_OF(int32_t)) { LV_LOG_WARN("integer overflow while calculating text height"); return; } else { size_res->y += letter_height; - size_res->y += line_space; + size_res->y += attributes->line_space; } /*Calculate the longest line*/ - int32_t act_line_length = lv_text_get_width_with_flags(&text[line_start], new_line_start - line_start, font, - letter_space, flag); + int32_t act_line_length = lv_text_get_width( + &text[line_start], new_line_start - line_start, font, attributes); size_res->x = LV_MAX(act_line_length, size_res->x); line_start = new_line_start; @@ -127,14 +137,14 @@ void lv_text_get_size(lv_point_t * size_res, const char * text, const lv_font_t /*Make the text one line taller if the last character is '\n' or '\r'*/ if((line_start != 0) && (text[line_start - 1] == '\n' || text[line_start - 1] == '\r')) { - size_res->y += letter_height + line_space; + size_res->y += letter_height + attributes->line_space; } /*Correction with the last line space or set the height manually if the text is empty*/ if(size_res->y == 0) size_res->y = letter_height; else - size_res->y -= line_space; + size_res->y -= attributes->line_space; } bool lv_text_is_cmd(lv_text_cmd_state_t * state, uint32_t c) @@ -320,9 +330,9 @@ static uint32_t lv_text_get_next_word(const char * txt, const lv_font_t * font, } uint32_t lv_text_get_next_line(const char * txt, uint32_t len, - const lv_font_t * font, int32_t letter_space, - int32_t max_width, int32_t * used_width, lv_text_flag_t flag) + const lv_font_t * font, int32_t * used_width, lv_text_attributes_t * attributes) { + if(used_width) *used_width = 0; if(txt == NULL) return 0; @@ -333,7 +343,9 @@ uint32_t lv_text_get_next_line(const char * txt, uint32_t len, /*If max_width doesn't matter simply find the new line character *without thinking about word wrapping*/ - if((flag & LV_TEXT_FLAG_EXPAND) || (flag & LV_TEXT_FLAG_FIT)) { + if((attributes->text_flags & LV_TEXT_FLAG_EXPAND) || + (attributes->text_flags & LV_TEXT_FLAG_FIT)) { + uint32_t i; for(i = 0; i < len && txt[i] != '\n' && txt[i] != '\r' && txt[i] != '\0'; i++) { /*Just find the new line chars or string ends by incrementing `i`*/ @@ -343,17 +355,22 @@ uint32_t lv_text_get_next_line(const char * txt, uint32_t len, return i; } - if(flag & LV_TEXT_FLAG_EXPAND) max_width = LV_COORD_MAX; + if(attributes->text_flags & LV_TEXT_FLAG_EXPAND) { + attributes->max_width = LV_COORD_MAX; + } lv_text_cmd_state_t cmd_state = LV_TEXT_CMD_STATE_WAIT; uint32_t i = 0; /*Iterating index into txt*/ + uint32_t max_width = attributes->max_width; while(i < len && txt[i] != '\0' && max_width > 0) { - lv_text_flag_t word_flag = flag; + lv_text_flag_t word_flag = attributes->text_flags; + if(i == 0) word_flag |= LV_TEXT_FLAG_BREAK_ALL; uint32_t word_w = 0; - uint32_t advance = lv_text_get_next_word(&txt[i], font, letter_space, max_width, word_flag, &word_w, &cmd_state); + uint32_t advance = lv_text_get_next_word(&txt[i], font, attributes->letter_space, + max_width, word_flag, &word_w, &cmd_state); max_width -= word_w; line_w += word_w; @@ -369,7 +386,6 @@ uint32_t lv_text_get_next_line(const char * txt, uint32_t len, i++; /*Include the following newline in the current line*/ break; } - } /*Always step at least one to avoid infinite loops*/ @@ -387,55 +403,26 @@ uint32_t lv_text_get_next_line(const char * txt, uint32_t len, return i; } -int32_t lv_text_get_width(const char * txt, uint32_t length, const lv_font_t * font, int32_t letter_space) +int32_t lv_text_get_width(const char * txt, uint32_t length, const lv_font_t * font, + const lv_text_attributes_t * attributes) { if(txt == NULL) return 0; if(font == NULL) return 0; if(txt[0] == '\0') return 0; - uint32_t i = 0; - int32_t width = 0; - - if(length != 0) { - while(i < length) { - uint32_t letter; - uint32_t letter_next; - lv_text_encoded_letter_next_2(txt, &letter, &letter_next, &i); - - int32_t char_width = lv_font_get_glyph_width(font, letter, letter_next); - if(char_width > 0) { - width += char_width; - width += letter_space; - } - } - - if(width > 0) { - width -= letter_space; /*Trim the last letter space. Important if the text is center - aligned*/ - } - } - - return width; -} - -int32_t lv_text_get_width_with_flags(const char * txt, uint32_t length, const lv_font_t * font, int32_t letter_space, - lv_text_flag_t flags) -{ - if(txt == NULL) return 0; - if(font == NULL) return 0; - if(txt[0] == '\0') return 0; - - uint32_t i = 0; + uint32_t i = 0; int32_t width = 0; lv_text_cmd_state_t cmd_state = LV_TEXT_CMD_STATE_WAIT; if(length != 0) { while(txt[i] != '\0' && i < length) { + uint32_t letter; uint32_t letter_next; + lv_text_encoded_letter_next_2(txt, &letter, &letter_next, &i); - if((flags & LV_TEXT_FLAG_RECOLOR) != 0) { + if((attributes->text_flags & LV_TEXT_FLAG_RECOLOR) != 0) { if(lv_text_is_cmd(&cmd_state, letter) != false) { continue; } @@ -444,12 +431,12 @@ int32_t lv_text_get_width_with_flags(const char * txt, uint32_t length, const lv int32_t char_width = lv_font_get_glyph_width(font, letter, letter_next); if(char_width > 0) { width += char_width; - width += letter_space; + width += attributes->letter_space; } } if(width > 0) { - width -= letter_space; /*Trim the last letter space. Important if the text is center + width -= attributes->letter_space; /*Trim the last letter space. Important if the text is center aligned*/ } } diff --git a/src/misc/lv_text.h b/src/misc/lv_text.h index 77b176d3e2..a63b00a6dd 100644 --- a/src/misc/lv_text.h +++ b/src/misc/lv_text.h @@ -42,13 +42,22 @@ extern "C" { typedef enum { LV_TEXT_FLAG_NONE = 0x00, - LV_TEXT_FLAG_EXPAND = 0x01, /**< Ignore max-width to avoid automatic word wrapping*/ - LV_TEXT_FLAG_FIT = 0x02, /**< Max-width is already equal to the longest line. (Used to skip some calculation)*/ - LV_TEXT_FLAG_BREAK_ALL = 0x04, /**< To prevent overflow, insert breaks between any two characters. - Otherwise breaks are inserted at word boundaries, as configured via LV_TXT_BREAK_CHARS - or according to LV_TXT_LINE_BREAK_LONG_LEN, LV_TXT_LINE_BREAK_LONG_PRE_MIN_LEN, - and LV_TXT_LINE_BREAK_LONG_POST_MIN_LEN.*/ - LV_TEXT_FLAG_RECOLOR = 0x08, /**< Enable parsing of recolor command*/ + + /*Ignore max-width to avoid automatic word wrapping*/ + LV_TEXT_FLAG_EXPAND = 0x01, + + /**Max-width is already equal to the longest line. (Used to skip some calculation)*/ + LV_TEXT_FLAG_FIT = 0x02, + + /**To prevent overflow, insert breaks between any two characters. + Otherwise breaks are inserted at word boundaries, as configured via LV_TXT_BREAK_CHARS + or according to LV_TXT_LINE_BREAK_LONG_LEN, LV_TXT_LINE_BREAK_LONG_PRE_MIN_LEN, + and LV_TXT_LINE_BREAK_LONG_POST_MIN_LEN.*/ + LV_TEXT_FLAG_BREAK_ALL = 0x04, + + /**Enable parsing of recolor command*/ + LV_TEXT_FLAG_RECOLOR = 0x08, + } lv_text_flag_t; /** Label align policy*/ @@ -66,56 +75,33 @@ typedef enum { LV_TEXT_CMD_STATE_IN, /**< Processing the command*/ } lv_text_cmd_state_t; +typedef struct { + int32_t letter_space; /**< Letter space between letters*/ + int32_t line_space; /**< Space between lines of text*/ + int32_t max_width; /**< Max width of the text (break the lines to fit this size). Set COORD_MAX to avoid*/ + lv_text_flag_t text_flags; +} lv_text_attributes_t; + /********************** * GLOBAL PROTOTYPES **********************/ +/** + * Initialize the text attributes descriptor + * @param attributes the text attributes descriptor to initialize + */ +void lv_text_attributes_init(lv_text_attributes_t * attributes); + /** * Get size of a text * @param size_res pointer to a 'point_t' variable to store the result * @param text pointer to a text * @param font pointer to font of the text - * @param letter_space letter space of the text - * @param line_space line space of the text - * @param max_width max width of the text (break the lines to fit this size). Set COORD_MAX to avoid - * @param flag settings for the text from ::lv_text_flag_t - - * line breaks + * @param attributes the text attributes, flags for line break behaviour, spacing etc */ -void lv_text_get_size(lv_point_t * size_res, const char * text, const lv_font_t * font, int32_t letter_space, - int32_t line_space, int32_t max_width, lv_text_flag_t flag); +void lv_text_get_size(lv_point_t * size_res, const char * text, const lv_font_t * font, + lv_text_attributes_t * attributes); -/** - * Give the length of a text with a given font - * @param txt a '\0' terminate string - * @param length length of 'txt' in byte count and not characters (Á is 1 character but 2 bytes in - * UTF-8) - * @param font pointer to a font - * @param letter_space letter space - * @return length of a char_num long text - */ -int32_t lv_text_get_width(const char * txt, uint32_t length, const lv_font_t * font, int32_t letter_space); - -/** - * Give the length of a text with a given font with text flags - * @param txt a '\0' terminate string - * @param length length of 'txt' in byte count and not characters (Á is 1 character but 2 bytes in - * UTF-8) - * @param font pointer to a font - * @param letter_space letter space - * @param flags settings for the text from ::lv_text_flag_t - * @return length of a char_num long text - */ -int32_t lv_text_get_width_with_flags(const char * txt, uint32_t length, const lv_font_t * font, int32_t letter_space, - lv_text_flag_t flags); - -/** - * Check if c is command state - * @param state - * @param c - * @return True if c is state - */ -bool lv_text_is_cmd(lv_text_cmd_state_t * state, uint32_t c); /********************** * MACROS **********************/ diff --git a/src/misc/lv_text_private.h b/src/misc/lv_text_private.h index 3814d8a14d..1088c85eef 100644 --- a/src/misc/lv_text_private.h +++ b/src/misc/lv_text_private.h @@ -28,22 +28,39 @@ extern "C" { * GLOBAL PROTOTYPES **********************/ +/** + * Give the length of a text with a given font with text flags + * @param txt a '\0' terminate string + * @param length length of 'txt' in byte count and not characters (Á is 1 character but 2 bytes in + * UTF-8) + * @param font pointer to font of the text + * @param attributes the text attributes, flags for line break behaviour, spacing etc + * @return length of a char_num long text + */ +int32_t lv_text_get_width(const char * txt, uint32_t length, const lv_font_t * font, + const lv_text_attributes_t * attributes); + +/** + * Check if c is command state + * @param state + * @param c + * @return True if c is state + */ +bool lv_text_is_cmd(lv_text_cmd_state_t * state, uint32_t c); + /** * Get the next line of text. Check line length and break chars too. * @param txt a '\0' terminated string * @param len length of 'txt' in bytes * @param font pointer to a font - * @param letter_space letter space - * @param max_width max width of the text (break the lines to fit this size). Set COORD_MAX to avoid - * line breaks * @param used_width When used_width != NULL, save the width of this line if * flag == LV_TEXT_FLAG_NONE, otherwise save -1. - * @param flag settings for the text from 'txt_flag_type' enum - * @return the index of the first char of the new line (in byte index not letter index. With UTF-8 - * they are different) + * @param attributes text attributes, flags to control line break behaviour, spacing etc + * @return the index of the first char of the new line + * (in byte index not letter index. With UTF-8 they are different) */ -uint32_t lv_text_get_next_line(const char * txt, uint32_t len, const lv_font_t * font, int32_t letter_space, - int32_t max_width, int32_t * used_width, lv_text_flag_t flag); +uint32_t lv_text_get_next_line(const char * txt, uint32_t len, const lv_font_t * font, int32_t * used_width, + lv_text_attributes_t * attributes); /** * Insert a string into another diff --git a/src/widgets/animimage/lv_animimage.c b/src/widgets/animimage/lv_animimage.c index 5ddb88fd39..ed91e78b43 100644 --- a/src/widgets/animimage/lv_animimage.c +++ b/src/widgets/animimage/lv_animimage.c @@ -22,7 +22,7 @@ #include "../../draw/lv_image_decoder.h" #include "../../misc/lv_assert.h" #include "../../misc/lv_fs.h" -#include "../../misc/lv_text.h" +#include "../../misc/lv_text_private.h" #include "../../misc/lv_math.h" #include "../../misc/lv_log.h" #include "../../misc/lv_anim.h" diff --git a/src/widgets/arclabel/lv_arclabel.c b/src/widgets/arclabel/lv_arclabel.c index 812d38c29b..a5a1aa4559 100644 --- a/src/widgets/arclabel/lv_arclabel.c +++ b/src/widgets/arclabel/lv_arclabel.c @@ -437,6 +437,9 @@ static void arclabel_draw_main(lv_event_t * e) lv_value_precise_t prev_letter_w = 0; lv_value_precise_t total_arc_length = deg_to_rad(arclabel->angle_size, arc_r); lv_value_precise_t curr_total_arc_length = deg_to_rad(angle_start, arc_r); + uint32_t letter; + uint32_t letter_next; + while(text) { uint32_t word_i = 0; @@ -446,8 +449,6 @@ static void arclabel_draw_main(lv_event_t * e) else text = NULL; while(word_i < text_len && curr_total_arc_length <= total_arc_length) { - uint32_t letter; - uint32_t letter_next; lv_text_encoded_letter_next_2(text_start, &letter, &letter_next, &word_i); const lv_value_precise_t letter_w = lv_font_get_glyph_width(font, letter, letter_next); @@ -524,6 +525,8 @@ static lv_value_precise_t calc_arc_text_total_angle(const char * text, const lv_ lv_value_precise_t prev_letter_w = 0; const lv_value_precise_t angle_size_in_arc_length = deg_to_rad(angle_size, radius); lv_value_precise_t total_arc_length = 0; + uint32_t letter; + uint32_t letter_next; while(text) { uint32_t word_i = 0; @@ -536,8 +539,6 @@ static lv_value_precise_t calc_arc_text_total_angle(const char * text, const lv_ break; } - uint32_t letter; - uint32_t letter_next; lv_text_encoded_letter_next_2(text_start, &letter, &letter_next, &word_i); const lv_value_precise_t letter_w = lv_font_get_glyph_width(font, letter, letter_next); diff --git a/src/widgets/buttonmatrix/lv_buttonmatrix.c b/src/widgets/buttonmatrix/lv_buttonmatrix.c index 5d1bcd3870..1ac30a711b 100644 --- a/src/widgets/buttonmatrix/lv_buttonmatrix.c +++ b/src/widgets/buttonmatrix/lv_buttonmatrix.c @@ -17,7 +17,7 @@ #include "../../core/lv_group.h" #include "../../draw/lv_draw.h" #include "../../core/lv_refr.h" -#include "../../misc/lv_text.h" +#include "../../misc/lv_text_private.h" #include "../../misc/lv_text_ap.h" #include "../../stdlib/lv_string.h" @@ -727,9 +727,14 @@ static void draw_main(lv_event_t * e) txt = txt_ap; } #endif + lv_text_attributes_t attributes = {0}; + attributes.letter_space = letter_space; + attributes.line_space = line_space; + attributes.text_flags = draw_label_dsc_act.flag; + attributes.max_width = lv_area_get_width(&area_obj); + lv_point_t txt_size; - lv_text_get_size(&txt_size, txt, font, letter_space, - line_space, lv_area_get_width(&area_obj), draw_label_dsc_act.flag); + lv_text_get_size(&txt_size, txt, font, &attributes); btn_area.x1 += (lv_area_get_width(&btn_area) - txt_size.x) / 2; btn_area.y1 += (lv_area_get_height(&btn_area) - txt_size.y) / 2; diff --git a/src/widgets/checkbox/lv_checkbox.c b/src/widgets/checkbox/lv_checkbox.c index ea581b5e88..ea8facffe4 100644 --- a/src/widgets/checkbox/lv_checkbox.c +++ b/src/widgets/checkbox/lv_checkbox.c @@ -12,6 +12,7 @@ #if LV_USE_CHECKBOX != 0 #include "../../misc/lv_assert.h" +#include "../../misc/lv_text_private.h" #include "../../misc/lv_text_ap.h" #include "../../core/lv_group.h" #include "../../draw/lv_draw.h" @@ -182,11 +183,16 @@ static void lv_checkbox_event(const lv_obj_class_t * class_p, lv_event_t * e) const lv_font_t * font = lv_obj_get_style_text_font(obj, LV_PART_MAIN); int32_t font_h = lv_font_get_line_height(font); - int32_t line_space = lv_obj_get_style_text_line_space(obj, LV_PART_MAIN); - int32_t letter_space = lv_obj_get_style_text_letter_space(obj, LV_PART_MAIN); + lv_text_attributes_t attributes = {0}; + + attributes.line_space = lv_obj_get_style_text_line_space(obj, LV_PART_MAIN); + attributes.letter_space = lv_obj_get_style_text_letter_space(obj, LV_PART_MAIN); + attributes.max_width = LV_COORD_MAX; + attributes.text_flags = LV_TEXT_FLAG_NONE; lv_point_t txt_size; - lv_text_get_size(&txt_size, cb->txt, font, letter_space, line_space, LV_COORD_MAX, LV_TEXT_FLAG_NONE); + + lv_text_get_size(&txt_size, cb->txt, font, &attributes); int32_t bg_colp = lv_obj_get_style_pad_column(obj, LV_PART_MAIN); int32_t marker_leftp = lv_obj_get_style_pad_left(obj, LV_PART_INDICATOR); @@ -257,11 +263,14 @@ static void lv_checkbox_draw(lv_event_t * e) lv_draw_rect(layer, &indic_dsc, &marker_area_transf); - int32_t line_space = lv_obj_get_style_text_line_space(obj, LV_PART_MAIN); - int32_t letter_space = lv_obj_get_style_text_letter_space(obj, LV_PART_MAIN); + lv_text_attributes_t attributes = {0}; + attributes.line_space = lv_obj_get_style_text_line_space(obj, LV_PART_MAIN); + attributes.letter_space = lv_obj_get_style_text_letter_space(obj, LV_PART_MAIN); + attributes.text_flags = LV_TEXT_FLAG_NONE; + attributes.max_width = LV_COORD_MAX; lv_point_t txt_size; - lv_text_get_size(&txt_size, cb->txt, font, letter_space, line_space, LV_COORD_MAX, LV_TEXT_FLAG_NONE); + lv_text_get_size(&txt_size, cb->txt, font, &attributes); lv_draw_label_dsc_t txt_dsc; lv_draw_label_dsc_init(&txt_dsc); diff --git a/src/widgets/dropdown/lv_dropdown.c b/src/widgets/dropdown/lv_dropdown.c index ba7867c94b..b16ec89b93 100644 --- a/src/widgets/dropdown/lv_dropdown.c +++ b/src/widgets/dropdown/lv_dropdown.c @@ -868,6 +868,7 @@ static void draw_main(lv_event_t * e) int32_t left = lv_obj_get_style_pad_left(obj, LV_PART_MAIN) + border_width; int32_t right = lv_obj_get_style_pad_right(obj, LV_PART_MAIN) + border_width; + lv_text_attributes_t attributes = {0}; lv_draw_label_dsc_t symbol_dsc; lv_draw_label_dsc_init(&symbol_dsc); symbol_dsc.base.layer = layer; @@ -892,8 +893,13 @@ static void draw_main(lv_event_t * e) int32_t symbol_h; if(symbol_type == LV_IMAGE_SRC_SYMBOL) { lv_point_t size; - lv_text_get_size(&size, dropdown->symbol, symbol_dsc.font, symbol_dsc.letter_space, symbol_dsc.line_space, LV_COORD_MAX, - symbol_dsc.flag); + + attributes.letter_space = symbol_dsc.letter_space; + attributes.line_space = symbol_dsc.line_space; + attributes.max_width = LV_COORD_MAX; + attributes.text_flags = symbol_dsc.flag; + + lv_text_get_size(&size, dropdown->symbol, symbol_dsc.font, &attributes); symbol_w = size.x; symbol_h = size.y; } @@ -944,9 +950,13 @@ static void draw_main(lv_event_t * e) lv_obj_init_draw_label_dsc(obj, LV_PART_MAIN, &label_dsc); label_dsc.flag |= LV_TEXT_FLAG_EXPAND; + attributes.letter_space = label_dsc.letter_space; + attributes.max_width = LV_COORD_MAX; + attributes.line_space = label_dsc.line_space; + attributes.text_flags = label_dsc.flag; + lv_point_t size; - lv_text_get_size(&size, opt_txt, label_dsc.font, label_dsc.letter_space, label_dsc.line_space, LV_COORD_MAX, - label_dsc.flag); + lv_text_get_size(&size, opt_txt, label_dsc.font, &attributes); lv_area_t txt_area; txt_area.x1 = obj->coords.x1 + left; diff --git a/src/widgets/image/lv_image.c b/src/widgets/image/lv_image.c index b64bafddad..0506b71101 100644 --- a/src/widgets/image/lv_image.c +++ b/src/widgets/image/lv_image.c @@ -8,6 +8,7 @@ *********************/ #include "lv_image_private.h" #include "../../misc/lv_area_private.h" +#include "../../misc/lv_text_private.h" #include "../../draw/lv_draw_image_private.h" #include "../../draw/lv_draw_private.h" #include "../../core/lv_obj_event_private.h" @@ -234,10 +235,15 @@ void lv_image_set_src(lv_obj_t * obj, const void * src) if(src_type == LV_IMAGE_SRC_SYMBOL) { /*`lv_image_dsc_get_info` couldn't set the width and height of a font so set it here*/ const lv_font_t * font = lv_obj_get_style_text_font(obj, LV_PART_MAIN); - int32_t letter_space = lv_obj_get_style_text_letter_space(obj, LV_PART_MAIN); - int32_t line_space = lv_obj_get_style_text_line_space(obj, LV_PART_MAIN); + lv_text_attributes_t attributes = {0}; + + attributes.letter_space = lv_obj_get_style_text_letter_space(obj, LV_PART_MAIN); + attributes.line_space = lv_obj_get_style_text_line_space(obj, LV_PART_MAIN); + attributes.max_width = LV_COORD_MAX; + attributes.text_flags = LV_TEXT_FLAG_NONE; + lv_point_t size; - lv_text_get_size(&size, src, font, letter_space, line_space, LV_COORD_MAX, LV_TEXT_FLAG_NONE); + lv_text_get_size(&size, src, font, &attributes); header.w = size.x; header.h = size.y; } @@ -915,8 +921,14 @@ static void draw_image(lv_event_t * e) const bool inner_alignment_is_transforming = img->align >= LV_IMAGE_ALIGN_AUTO_TRANSFORM; if((needs_inner_alignment || has_offset) && !inner_alignment_is_transforming) { lv_point_t text_size; - lv_text_get_size(&text_size, label_dsc.text, label_dsc.font, label_dsc.letter_space, - label_dsc.line_space, LV_COORD_MAX, LV_TEXT_FLAG_NONE); + + lv_text_attributes_t attributes; + attributes.letter_space = label_dsc.letter_space; + attributes.line_space = label_dsc.line_space; + attributes.max_width = LV_COORD_MAX; + attributes.text_flags = LV_TEXT_FLAG_NONE; + + lv_text_get_size(&text_size, label_dsc.text, label_dsc.font, &attributes); lv_area_set(&aligned_coords, 0, 0, text_size.x, text_size.y); lv_area_align(&obj->coords, &aligned_coords, img->align, img->offset.x, img->offset.y); coords = &aligned_coords; diff --git a/src/widgets/label/lv_label.c b/src/widgets/label/lv_label.c index af7bbcf06b..0ca8b99f10 100644 --- a/src/widgets/label/lv_label.c +++ b/src/widgets/label/lv_label.c @@ -57,7 +57,7 @@ static size_t get_text_length(const char * text); static void copy_text_to_label(lv_label_t * label, const char * text); static lv_text_flag_t get_label_flags(lv_label_t * label); static void calculate_x_coordinate(int32_t * x, const lv_text_align_t align, const char * txt, - uint32_t length, const lv_font_t * font, int32_t letter_space, lv_area_t * txt_coords, lv_text_flag_t flags); + uint32_t length, const lv_font_t * font, lv_area_t * txt_coords, lv_text_attributes_t * attributes); /********************** * STATIC VARIABLES @@ -331,40 +331,43 @@ void lv_label_get_letter_pos(const lv_obj_t * obj, uint32_t char_id, lv_point_t return; } - lv_text_flag_t flag = get_label_flags(label); const uint32_t byte_id = lv_text_encoded_get_byte_id(txt, char_id); /*Search the line of the index letter*/ - const int32_t line_space = lv_obj_get_style_text_line_space(obj, LV_PART_MAIN); - const int32_t letter_space = lv_obj_get_style_text_letter_space(obj, LV_PART_MAIN); + lv_text_attributes_t attributes = {0}; + attributes.text_flags = get_label_flags(label); + attributes.line_space = lv_obj_get_style_text_line_space(obj, LV_PART_MAIN); + attributes.letter_space = lv_obj_get_style_text_letter_space(obj, LV_PART_MAIN); const lv_font_t * font = lv_obj_get_style_text_font(obj, LV_PART_MAIN); const int32_t letter_height = lv_font_get_line_height(font); lv_area_t txt_coords; lv_obj_get_content_coords(obj, &txt_coords); - const int32_t max_w = lv_area_get_width(&txt_coords); const int32_t max_h = lv_area_get_height(&txt_coords); + attributes.max_width = lv_area_get_width(&txt_coords); + int32_t y = 0; uint32_t line_start = 0; uint32_t new_line_start = 0; while(txt[new_line_start] != '\0') { - bool last_line = y + letter_height + line_space + letter_height > max_h; - if(last_line && label->long_mode == LV_LABEL_LONG_MODE_DOTS) flag |= LV_TEXT_FLAG_BREAK_ALL; + bool last_line = y + letter_height + attributes.line_space + letter_height > max_h; + if(last_line && label->long_mode == LV_LABEL_LONG_MODE_DOTS) attributes.text_flags |= LV_TEXT_FLAG_BREAK_ALL; + + new_line_start += lv_text_get_next_line(&txt[line_start], LV_TEXT_LEN_MAX, font, NULL, &attributes); - new_line_start += lv_text_get_next_line(&txt[line_start], LV_TEXT_LEN_MAX, font, letter_space, max_w, NULL, flag); if(byte_id < new_line_start || txt[new_line_start] == '\0') break; /*The line of 'index' letter begins at 'line_start'*/ - y += letter_height + line_space; + y += letter_height + attributes.line_space; line_start = new_line_start; } /*If the last character is line break then go to the next line*/ if(byte_id > 0) { if((txt[byte_id - 1] == '\n' || txt[byte_id - 1] == '\r') && txt[byte_id] == '\0') { - y += letter_height + line_space; + y += letter_height + attributes.line_space; line_start = byte_id; } } @@ -398,11 +401,11 @@ void lv_label_get_letter_pos(const lv_obj_t * obj, uint32_t char_id, lv_point_t #endif /*Calculate the x coordinate*/ - int32_t x = lv_text_get_width_with_flags(bidi_txt, visual_byte_pos, font, letter_space, flag); - if(char_id != line_start) x += letter_space; + int32_t x = lv_text_get_width(bidi_txt, visual_byte_pos, font, &attributes); + if(char_id != line_start) x += attributes.letter_space; uint32_t length = new_line_start - line_start; - calculate_x_coordinate(&x, align, bidi_txt, length, font, letter_space, &txt_coords, flag); + calculate_x_coordinate(&x, align, bidi_txt, length, font, &txt_coords, &attributes); pos->x = x; pos->y = y; @@ -427,25 +430,25 @@ uint32_t lv_label_get_letter_on(const lv_obj_t * obj, lv_point_t * pos_in, bool const char * txt = lv_label_get_text(obj); uint32_t line_start = 0; uint32_t new_line_start = 0; - int32_t max_w = lv_area_get_width(&txt_coords); int32_t max_h = lv_area_get_height(&txt_coords); const lv_font_t * font = lv_obj_get_style_text_font(obj, LV_PART_MAIN); - const int32_t line_space = lv_obj_get_style_text_line_space(obj, LV_PART_MAIN); - const int32_t letter_space = lv_obj_get_style_text_letter_space(obj, LV_PART_MAIN); const int32_t letter_height = lv_font_get_line_height(font); int32_t y = 0; - - lv_text_flag_t flag = get_label_flags(label); + lv_text_attributes_t attributes = {0}; + attributes.letter_space = lv_obj_get_style_text_letter_space(obj, LV_PART_MAIN); + attributes.line_space = lv_obj_get_style_text_line_space(obj, LV_PART_MAIN); + attributes.text_flags = get_label_flags(label); + attributes.max_width = lv_area_get_width(&txt_coords); /*Search the line of the index letter*/; while(txt[line_start] != '\0') { /*If dots will be shown, break the last visible line anywhere, *not only at word boundaries.*/ - bool last_line = y + letter_height + line_space + letter_height > max_h; - if(last_line && label->long_mode == LV_LABEL_LONG_MODE_DOTS) flag |= LV_TEXT_FLAG_BREAK_ALL; + bool last_line = y + letter_height + attributes.line_space + letter_height > max_h; + if(last_line && label->long_mode == LV_LABEL_LONG_MODE_DOTS) attributes.text_flags |= LV_TEXT_FLAG_BREAK_ALL; - new_line_start += lv_text_get_next_line(&txt[line_start], LV_TEXT_LEN_MAX, font, letter_space, max_w, NULL, flag); + new_line_start += lv_text_get_next_line(&txt[line_start], LV_TEXT_LEN_MAX, font, NULL, &attributes); if(pos.y <= y + letter_height) { /*The line is found (stored in 'line_start')*/ @@ -456,7 +459,7 @@ uint32_t lv_label_get_letter_on(const lv_obj_t * obj, lv_point_t * pos_in, bool if(letter != '\n' && txt[new_line_start] == '\0') new_line_start++; break; } - y += letter_height + line_space; + y += letter_height + attributes.line_space; line_start = new_line_start; } @@ -481,7 +484,7 @@ uint32_t lv_label_get_letter_on(const lv_obj_t * obj, lv_point_t * pos_in, bool int32_t x = 0; const lv_text_align_t align = lv_obj_calculate_style_text_align(obj, LV_PART_MAIN, label->text); uint32_t length = new_line_start - line_start; - calculate_x_coordinate(&x, align, bidi_txt, length, font, letter_space, &txt_coords, flag); + calculate_x_coordinate(&x, align, bidi_txt, length, font, &txt_coords, &attributes); lv_text_cmd_state_t cmd_state = LV_TEXT_CMD_STATE_WAIT; @@ -490,13 +493,13 @@ uint32_t lv_label_get_letter_on(const lv_obj_t * obj, lv_point_t * pos_in, bool if(new_line_start > 0) { while(i + line_start < new_line_start) { - /*Get the current letter and the next letter for kerning*/ - /*Be careful 'i' already points to the next character*/ uint32_t letter; uint32_t letter_next; + /*Get the current letter and the next letter for kerning*/ + /*Be careful 'i' already points to the next character*/ lv_text_encoded_letter_next_2(bidi_txt, &letter, &letter_next, &i); - if((flag & LV_TEXT_FLAG_RECOLOR) != 0) { + if((attributes.text_flags & LV_TEXT_FLAG_RECOLOR) != 0) { if(lv_text_is_cmd(&cmd_state, bidi_txt[i]) != false) { continue; /*Skip the letter if it is part of a command*/ } @@ -510,7 +513,7 @@ uint32_t lv_label_get_letter_on(const lv_obj_t * obj, lv_point_t * pos_in, bool break; } x += gw; - x += letter_space; + x += attributes.letter_space; i_act = i; } } @@ -547,29 +550,30 @@ bool lv_label_is_char_under_pos(const lv_obj_t * obj, lv_point_t * pos) lv_area_t txt_coords; lv_obj_get_content_coords(obj, &txt_coords); + lv_text_attributes_t attributes = {0}; const char * txt = lv_label_get_text(obj); lv_label_t * label = (lv_label_t *)obj; uint32_t line_start = 0; uint32_t new_line_start = 0; - const int32_t max_w = lv_area_get_width(&txt_coords); - const int32_t max_h = lv_area_get_height(&txt_coords); const lv_font_t * font = lv_obj_get_style_text_font(obj, LV_PART_MAIN); - const int32_t line_space = lv_obj_get_style_text_line_space(obj, LV_PART_MAIN); - const int32_t letter_space = lv_obj_get_style_text_letter_space(obj, LV_PART_MAIN); const int32_t letter_height = lv_font_get_line_height(font); + const int32_t max_h = lv_area_get_height(&txt_coords); - lv_text_flag_t flag = get_label_flags(label); + attributes.max_width = lv_area_get_width(&txt_coords); + attributes.line_space = lv_obj_get_style_text_line_space(obj, LV_PART_MAIN); + attributes.letter_space = lv_obj_get_style_text_letter_space(obj, LV_PART_MAIN); + attributes.text_flags = get_label_flags(label); /*Search the line of the index letter*/ int32_t y = 0; while(txt[line_start] != '\0') { - bool last_line = y + letter_height + line_space + letter_height > max_h; - if(last_line && label->long_mode == LV_LABEL_LONG_MODE_DOTS) flag |= LV_TEXT_FLAG_BREAK_ALL; + bool last_line = y + letter_height + attributes.line_space + letter_height > max_h; + if(last_line && label->long_mode == LV_LABEL_LONG_MODE_DOTS) attributes.text_flags |= LV_TEXT_FLAG_BREAK_ALL; - new_line_start += lv_text_get_next_line(&txt[line_start], LV_TEXT_LEN_MAX, font, letter_space, max_w, NULL, flag); + new_line_start += lv_text_get_next_line(&txt[line_start], LV_TEXT_LEN_MAX, font, NULL, &attributes); if(pos->y <= y + letter_height) break; /*The line is found (stored in 'line_start')*/ - y += letter_height + line_space; + y += letter_height + attributes.line_space; line_start = new_line_start; } @@ -579,13 +583,11 @@ bool lv_label_is_char_under_pos(const lv_obj_t * obj, lv_point_t * pos) int32_t x = 0; if(align == LV_TEXT_ALIGN_CENTER) { - const int32_t line_w = lv_text_get_width_with_flags(&txt[line_start], new_line_start - line_start, font, letter_space, - flag); + const int32_t line_w = lv_text_get_width(&txt[line_start], new_line_start - line_start, font, &attributes); x += lv_area_get_width(&txt_coords) / 2 - line_w / 2; } else if(align == LV_TEXT_ALIGN_RIGHT) { - const int32_t line_w = lv_text_get_width_with_flags(&txt[line_start], new_line_start - line_start, font, letter_space, - flag); + const int32_t line_w = lv_text_get_width(&txt[line_start], new_line_start - line_start, font, &attributes); x += lv_area_get_width(&txt_coords) - line_w; } @@ -594,7 +596,7 @@ bool lv_label_is_char_under_pos(const lv_obj_t * obj, lv_point_t * pos) int32_t last_x = 0; uint32_t i = line_start; uint32_t i_current = i; - uint32_t letter = '\0'; + uint32_t letter = '\0'; uint32_t letter_next = '\0'; if(new_line_start > 0) { @@ -603,7 +605,7 @@ bool lv_label_is_char_under_pos(const lv_obj_t * obj, lv_point_t * pos) /*Be careful 'i' already points to the next character*/ lv_text_encoded_letter_next_2(txt, &letter, &letter_next, &i); - if((flag & LV_TEXT_FLAG_RECOLOR) != 0) { + if((attributes.text_flags & LV_TEXT_FLAG_RECOLOR) != 0) { if(lv_text_is_cmd(&cmd_state, txt[i]) != false) { continue; /*Skip the letter if it is part of a command*/ } @@ -615,13 +617,13 @@ bool lv_label_is_char_under_pos(const lv_obj_t * obj, lv_point_t * pos) i = i_current; break; } - x += letter_space; + x += attributes.letter_space; i_current = i; } } - const int32_t max_diff = lv_font_get_glyph_width(font, letter, letter_next) + letter_space + 1; - return (pos->x >= (last_x - letter_space) && pos->x <= (last_x + max_diff)); + const int32_t max_diff = lv_font_get_glyph_width(font, letter, letter_next) + attributes.letter_space + 1; + return (pos->x >= (last_x - attributes.letter_space) && pos->x <= (last_x + max_diff)); } uint32_t lv_label_get_text_selection_start(const lv_obj_t * obj) @@ -794,7 +796,15 @@ static void lv_label_event(const lv_obj_class_t * class_p, lv_event_t * e) uint32_t dot_begin = label->dot_begin; lv_label_revert_dots(obj); - lv_text_get_size(&label->size_cache, label->text, font, letter_space, line_space, w, flag); + + lv_text_attributes_t attributes = {0}; + + attributes.letter_space = letter_space; + attributes.line_space = line_space; + attributes.text_flags = flag; + attributes.max_width = w; + + lv_text_get_size(&label->size_cache, label->text, font, &attributes); lv_label_set_dots(obj, dot_begin); label->size_cache.y = LV_MIN(label->size_cache.y, lv_obj_get_style_max_height(obj, LV_PART_MAIN)); @@ -964,18 +974,19 @@ static void lv_label_refr_text(lv_obj_t * obj) label->invalid_size_cache = true; lv_area_t txt_coords; + lv_text_attributes_t attributes = {0}; lv_obj_get_content_coords(obj, &txt_coords); - int32_t max_w = lv_area_get_width(&txt_coords); const lv_font_t * font = lv_obj_get_style_text_font(obj, LV_PART_MAIN); - int32_t line_space = lv_obj_get_style_text_line_space(obj, LV_PART_MAIN); - int32_t letter_space = lv_obj_get_style_text_letter_space(obj, LV_PART_MAIN); + attributes.line_space = lv_obj_get_style_text_line_space(obj, LV_PART_MAIN); + attributes.letter_space = lv_obj_get_style_text_letter_space(obj, LV_PART_MAIN); + attributes.text_flags = get_label_flags(label); + attributes.max_width = lv_area_get_width(&txt_coords); /*Calc. the height and longest line*/ lv_point_t size; - lv_text_flag_t flag = get_label_flags(label); lv_label_revert_dots(obj); - lv_text_get_size(&size, label->text, font, letter_space, line_space, max_w, flag); + lv_text_get_size(&size, label->text, font, &attributes); label->text_size = size; lv_obj_refresh_self_size(obj); @@ -1106,6 +1117,7 @@ static void lv_label_refr_text(lv_obj_t * obj) lv_anim_set_repeat_count(&a, LV_ANIM_REPEAT_INFINITE); bool hor_anim = false; + if(size.x > lv_area_get_width(&txt_coords)) { #if LV_USE_BIDI int32_t start, end; @@ -1179,24 +1191,25 @@ static void lv_label_refr_text(lv_obj_t * obj) } } else if(label->long_mode == LV_LABEL_LONG_MODE_DOTS) { + if(size.y > lv_area_get_height(&txt_coords) && /*Text overflows available area*/ size.y > lv_font_get_line_height(font) && /*No break requested, so no dots required*/ lv_text_get_encoded_length(label->text) > LV_LABEL_DOT_NUM) { /*Do not turn all characters into dots*/ lv_point_t p; int32_t y_overed; p.x = lv_area_get_width(&txt_coords) - - (lv_font_get_glyph_width(font, '.', '.') + letter_space) * + (lv_font_get_glyph_width(font, '.', '.') + attributes.letter_space) * LV_LABEL_DOT_NUM; /*Shrink with dots*/ p.y = lv_area_get_height(&txt_coords); y_overed = p.y % - (lv_font_get_line_height(font) + line_space); /*Round down to the last line*/ + (lv_font_get_line_height(font) + attributes.line_space); /*Round down to the last line*/ if(y_overed >= lv_font_get_line_height(font)) { p.y -= y_overed; p.y += lv_font_get_line_height(font); } else { p.y -= y_overed; - p.y -= line_space; + p.y -= attributes.line_space; } uint32_t letter_id = lv_label_get_letter_on(obj, &p, false); @@ -1303,14 +1316,14 @@ static lv_text_flag_t get_label_flags(lv_label_t * label) /* Function created because of this pattern be used in multiple functions */ static void calculate_x_coordinate(int32_t * x, const lv_text_align_t align, const char * txt, uint32_t length, - const lv_font_t * font, int32_t letter_space, lv_area_t * txt_coords, lv_text_flag_t flags) + const lv_font_t * font, lv_area_t * txt_coords, lv_text_attributes_t * attributes) { if(align == LV_TEXT_ALIGN_CENTER) { - const int32_t line_w = lv_text_get_width_with_flags(txt, length, font, letter_space, flags); + const int32_t line_w = lv_text_get_width(txt, length, font, attributes); *x += lv_area_get_width(txt_coords) / 2 - line_w / 2; } else if(align == LV_TEXT_ALIGN_RIGHT) { - const int32_t line_w = lv_text_get_width_with_flags(txt, length, font, letter_space, flags); + const int32_t line_w = lv_text_get_width(txt, length, font, attributes); *x += lv_area_get_width(txt_coords) - line_w; } else { diff --git a/src/widgets/roller/lv_roller.c b/src/widgets/roller/lv_roller.c index 3700ccb955..3966024bd3 100644 --- a/src/widgets/roller/lv_roller.c +++ b/src/widgets/roller/lv_roller.c @@ -538,6 +538,12 @@ static void draw_main(lv_event_t * e) label_dsc.base.layer = layer; lv_obj_init_draw_label_dsc(obj, LV_PART_SELECTED, &label_dsc); + lv_text_attributes_t attributes = {0}; + attributes.letter_space = label_dsc.letter_space; + attributes.line_space = label_dsc.line_space; + attributes.max_width = lv_obj_get_width(obj); + attributes.text_flags = LV_TEXT_FLAG_EXPAND; + /*Redraw the text on the selected area*/ lv_area_t sel_area; get_sel_area(obj, &sel_area); @@ -550,8 +556,7 @@ static void draw_main(lv_event_t * e) /*Get the size of the "selected text"*/ lv_point_t label_sel_size; - lv_text_get_size(&label_sel_size, lv_label_get_text(label), label_dsc.font, label_dsc.letter_space, - label_dsc.line_space, lv_obj_get_width(obj), LV_TEXT_FLAG_EXPAND); + lv_text_get_size(&label_sel_size, lv_label_get_text(label), label_dsc.font, &attributes); /*Move the selected label proportionally with the background label*/ int32_t roller_h = lv_obj_get_height(obj); @@ -858,11 +863,15 @@ static int32_t get_selected_label_width(const lv_obj_t * obj) lv_obj_t * label = get_label(obj); if(label == NULL) return 0; + lv_text_attributes_t attributes = {0}; const lv_font_t * font = lv_obj_get_style_text_font(obj, LV_PART_SELECTED); - int32_t letter_space = lv_obj_get_style_text_letter_space(obj, LV_PART_SELECTED); + attributes.letter_space = lv_obj_get_style_text_letter_space(obj, LV_PART_SELECTED); + attributes.max_width = LV_COORD_MAX; + attributes.text_flags = LV_TEXT_FLAG_NONE; + const char * txt = lv_label_get_text(label); lv_point_t size; - lv_text_get_size(&size, txt, font, letter_space, 0, LV_COORD_MAX, LV_TEXT_FLAG_NONE); + lv_text_get_size(&size, txt, font, &attributes); return size.x; } diff --git a/src/widgets/scale/lv_scale.c b/src/widgets/scale/lv_scale.c index 6a45fb72ae..8513474955 100644 --- a/src/widgets/scale/lv_scale.c +++ b/src/widgets/scale/lv_scale.c @@ -14,6 +14,7 @@ #include "../../core/lv_group.h" #include "../../misc/lv_assert.h" #include "../../misc/lv_math.h" +#include "../../misc/lv_text_private.h" #include "../../draw/lv_draw_arc.h" /********************* @@ -631,6 +632,7 @@ static void scale_draw_indicator(lv_obj_t * obj, lv_event_t * event) /* Formatting the labels with the configured style for LV_PART_INDICATOR */ lv_obj_init_draw_label_dsc(obj, LV_PART_INDICATOR, &label_dsc); + /* Major tick style */ lv_draw_line_dsc_t major_tick_dsc; lv_draw_line_dsc_init(&major_tick_dsc); @@ -1272,10 +1274,18 @@ static void scale_get_label_coords(lv_obj_t * obj, lv_draw_label_dsc_t * label_d { lv_scale_t * scale = (lv_scale_t *)obj; + lv_text_attributes_t attributes = {0}; + attributes.letter_space = label_dsc->letter_space; + attributes.line_space = label_dsc->line_space; + attributes.max_width = LV_COORD_MAX; + attributes.text_flags = LV_TEXT_FLAG_NONE; + /* Reserve appropriate size for the tick label */ lv_point_t label_size; - lv_text_get_size(&label_size, label_dsc->text, - label_dsc->font, label_dsc->letter_space, label_dsc->line_space, LV_COORD_MAX, LV_TEXT_FLAG_NONE); + + if(label_dsc->text != NULL) { + lv_text_get_size(&label_size, label_dsc->text, label_dsc->font, &attributes); + } /* Set the label draw area at some distance of the major tick */ if((LV_SCALE_MODE_HORIZONTAL_BOTTOM == scale->mode) || (LV_SCALE_MODE_HORIZONTAL_TOP == scale->mode)) { diff --git a/src/widgets/span/lv_span.c b/src/widgets/span/lv_span.c index 1fe8e297f7..4231c71f11 100644 --- a/src/widgets/span/lv_span.c +++ b/src/widgets/span/lv_span.c @@ -449,10 +449,13 @@ uint32_t lv_spangroup_get_expand_width(lv_obj_t * obj, uint32_t max_width) } uint32_t width = LV_COORD_IS_PCT(spans->indent) ? 0 : spans->indent; - lv_span_t * cur_span; int32_t letter_space = 0; + lv_span_t * cur_span; LV_LL_READ(&spans->child_ll, cur_span) { + uint32_t letter; + uint32_t letter_next; const lv_font_t * font = lv_span_get_style_text_font(obj, cur_span); + letter_space = lv_span_get_style_text_letter_space(obj, cur_span); uint32_t j = 0; const char * cur_txt = cur_span->txt; @@ -461,8 +464,8 @@ uint32_t lv_spangroup_get_expand_width(lv_obj_t * obj, uint32_t max_width) if(max_width > 0 && width >= max_width) { return max_width; } - uint32_t letter = lv_text_encoded_next(cur_txt, &j); - uint32_t letter_next = lv_text_encoded_next(&cur_txt[j], NULL); + letter = lv_text_encoded_next(cur_txt, &j); + letter_next = lv_text_encoded_next(&cur_txt[j], NULL); uint32_t letter_w = lv_font_get_glyph_width(font, letter, letter_next); width = width + letter_w + letter_space; } @@ -793,10 +796,15 @@ static bool lv_text_get_snippet(const char * txt, const lv_font_t * font, real_max_width++; #endif - uint32_t ofs = lv_text_get_next_line(txt, LV_TEXT_LEN_MAX, font, letter_space, real_max_width, use_width, flag); + lv_text_attributes_t attributes = {0}; + attributes.letter_space = letter_space; + attributes.max_width = real_max_width; + attributes.text_flags = flag; + + uint32_t ofs = lv_text_get_next_line(txt, LV_TEXT_LEN_MAX, font, use_width, &attributes); *end_ofs = ofs; - if(txt[ofs] == '\0' && *use_width < max_width && !(ofs && (txt[ofs - 1] == '\n' || txt[ofs - 1] == '\r'))) { + if(txt[ofs] == '\0' && *use_width < attributes.max_width && !(ofs && (txt[ofs - 1] == '\n' || txt[ofs - 1] == '\r'))) { return false; } else { @@ -1201,6 +1209,7 @@ static void lv_draw_span(lv_obj_t * obj, lv_layer_t * layer) bool need_draw_ellipsis = false; uint32_t dot_width = 0; + /* deal overflow */ if(ellipsis_valid) { uint32_t dot_letter_w = lv_font_get_glyph_width(pinfo->font, '.', '.'); diff --git a/src/widgets/table/lv_table.c b/src/widgets/table/lv_table.c index 062e12e62f..8f8555d934 100644 --- a/src/widgets/table/lv_table.c +++ b/src/widgets/table/lv_table.c @@ -14,7 +14,7 @@ #include "../../indev/lv_indev.h" #include "../../misc/lv_assert.h" -#include "../../misc/lv_text.h" +#include "../../misc/lv_text_private.h" #include "../../misc/lv_text_ap.h" #include "../../misc/lv_math.h" #include "../../stdlib/lv_sprintf.h" @@ -823,24 +823,28 @@ static void draw_main(lv_event_t * e) const int32_t cell_right = lv_obj_get_style_pad_right(obj, LV_PART_ITEMS); const int32_t cell_top = lv_obj_get_style_pad_top(obj, LV_PART_ITEMS); const int32_t cell_bottom = lv_obj_get_style_pad_bottom(obj, LV_PART_ITEMS); - lv_text_flag_t txt_flags = LV_TEXT_FLAG_NONE; - lv_area_t txt_area; + lv_text_attributes_t attributes = {0}; + attributes.text_flags = LV_TEXT_FLAG_NONE; + attributes.letter_space = label_dsc_act.letter_space; + attributes.line_space = label_dsc_act.line_space; + + lv_area_t txt_area; txt_area.x1 = cell_area.x1 + cell_left; txt_area.x2 = cell_area.x2 - cell_right; txt_area.y1 = cell_area.y1 + cell_top; txt_area.y2 = cell_area.y2 - cell_bottom; + attributes.max_width = lv_area_get_width(&txt_area); + /*Align the content to the middle if not cropped*/ bool crop = ctrl & LV_TABLE_CELL_CTRL_TEXT_CROP; if(crop) { - txt_flags = LV_TEXT_FLAG_EXPAND; + attributes.text_flags = LV_TEXT_FLAG_EXPAND; label_dsc_act.flag |= LV_TEXT_FLAG_EXPAND; } - lv_text_get_size(&txt_size, table->cell_data[cell]->txt, label_dsc_def.font, - label_dsc_act.letter_space, label_dsc_act.line_space, - lv_area_get_width(&txt_area), txt_flags); + lv_text_get_size(&txt_size, table->cell_data[cell]->txt, label_dsc_def.font, &attributes); /*Align the content to the middle if not cropped*/ if(!crop) { @@ -938,6 +942,11 @@ static int32_t get_row_height(lv_obj_t * obj, uint32_t row_id, const lv_font_t * /* Calculate the cell_data index where to start */ uint32_t row_start = row_id * table->col_cnt; + lv_text_attributes_t attributes = {0}; + attributes.letter_space = letter_space; + attributes.line_space = line_space; + attributes.text_flags = LV_TEXT_FLAG_NONE; + /* Traverse the cells in the row_id row */ uint32_t cell; uint32_t col; @@ -948,7 +957,7 @@ static int32_t get_row_height(lv_obj_t * obj, uint32_t row_id, const lv_font_t * continue; } - int32_t txt_w = table->col_w[col]; + attributes.max_width = table->col_w[col]; /* Traverse the current row from the first until the penultimate column. * Increment the text width if the cell has the LV_TABLE_CELL_CTRL_MERGE_RIGHT control, @@ -961,7 +970,7 @@ static int32_t get_row_height(lv_obj_t * obj, uint32_t row_id, const lv_font_t * lv_table_cell_ctrl_t ctrl = (lv_table_cell_ctrl_t) next_cell_data->ctrl; if(ctrl & LV_TABLE_CELL_CTRL_MERGE_RIGHT) { - txt_w += table->col_w[col + col_merge + 1]; + attributes.max_width += table->col_w[col + col_merge + 1]; } else { break; @@ -978,10 +987,9 @@ static int32_t get_row_height(lv_obj_t * obj, uint32_t row_id, const lv_font_t * /*Else we have to calculate the height of the cell text*/ else { lv_point_t txt_size; - txt_w -= cell_left + cell_right; + attributes.max_width -= cell_left + cell_right; - lv_text_get_size(&txt_size, table->cell_data[cell]->txt, font, - letter_space, line_space, txt_w, LV_TEXT_FLAG_NONE); + lv_text_get_size(&txt_size, table->cell_data[cell]->txt, font, &attributes); h_max = LV_MAX(txt_size.y + cell_top + cell_bottom, h_max); /*Skip until one element after the last merged column*/ diff --git a/src/widgets/textarea/lv_textarea.c b/src/widgets/textarea/lv_textarea.c index 7399ad5c50..dc12b55148 100644 --- a/src/widgets/textarea/lv_textarea.c +++ b/src/widgets/textarea/lv_textarea.c @@ -704,11 +704,12 @@ const char * lv_textarea_get_password_bullet(lv_obj_t * obj) if(ta->pwd_bullet) return ta->pwd_bullet; lv_font_glyph_dsc_t g; - const lv_font_t * font = lv_obj_get_style_text_font(obj, LV_PART_MAIN); /*If the textarea's font has the bullet character use it else fallback to "*"*/ - if(lv_font_get_glyph_dsc(font, &g, LV_TEXTAREA_PWD_BULLET_UNICODE, 0)) + const lv_font_t * bullet_font = lv_obj_get_style_text_font(obj, LV_PART_MAIN); + if(lv_font_get_glyph_dsc(bullet_font, &g, LV_TEXTAREA_PWD_BULLET_UNICODE, '\0')) return LV_SYMBOL_BULLET; + return "*"; } @@ -1184,6 +1185,7 @@ static void refr_cursor_area(lv_obj_t * obj) uint32_t tmp = letter; if(is_valid_but_non_printable_char(letter)) { + /*If non printable get the letter_w of the space char*/ tmp = ' '; } letter_w = lv_font_get_glyph_width(font, tmp, IGNORE_KERNING); diff --git a/tests/src/test_cases/libs/test_freetype.c b/tests/src/test_cases/libs/test_freetype.c index efbbbcf5e4..63c9950352 100644 --- a/tests/src/test_cases/libs/test_freetype.c +++ b/tests/src/test_cases/libs/test_freetype.c @@ -531,7 +531,6 @@ void test_freetype_render_outline(void) lv_freetype_outline_add_event(freetype_outline_event_cb, LV_EVENT_ALL, NULL); lv_font_glyph_dsc_t g; - lv_font_get_glyph_dsc(font_italic, &g, 0x9F98, '\0'); const lv_ll_t * outline_data; diff --git a/tests/src/test_cases/test_txt.c b/tests/src/test_cases/test_txt.c index e2fb2a53f8..0866edcab5 100644 --- a/tests/src/test_cases/test_txt.c +++ b/tests/src/test_cases/test_txt.c @@ -130,11 +130,12 @@ void test_txt_get_encoded_next_detect_invalid_4_byte_input(void) void test_txt_next_line_should_handle_empty_string(void) { const lv_font_t * font_ptr = NULL; - int32_t letter_space = 0; - int32_t max_width = 0; - lv_text_flag_t flag = LV_TEXT_FLAG_NONE; + lv_text_attributes_t attributes = {0}; + attributes.letter_space = 0; + attributes.max_width = 0; + attributes.text_flags = LV_TEXT_FLAG_NONE; - uint32_t next_line = lv_text_get_next_line("", 0, font_ptr, letter_space, max_width, NULL, flag); + uint32_t next_line = lv_text_get_next_line("", 0, font_ptr, NULL, &attributes); TEST_ASSERT_EQUAL_UINT32(0, next_line); } diff --git a/tests/src/test_cases/widgets/test_chart.c b/tests/src/test_cases/widgets/test_chart.c index 22adb5191b..d82d08ae2d 100644 --- a/tests/src/test_cases/widgets/test_chart.c +++ b/tests/src/test_cases/widgets/test_chart.c @@ -128,7 +128,14 @@ static void chart_event_cb(lv_event_t * e) lv_snprintf(buf, sizeof(buf), "%"LV_PRIu32, ser->y_points[base_dsc->id2]); lv_point_t text_size; - lv_text_get_size(&text_size, buf, LV_FONT_DEFAULT, 0, 0, LV_COORD_MAX, LV_TEXT_FLAG_NONE); + lv_text_attributes_t attributes = {0}; + + attributes.letter_space = 0; + attributes.line_space = 0; + attributes.max_width = LV_COORD_MAX; + attributes.text_flags = LV_TEXT_FLAG_NONE; + + lv_text_get_size(&text_size, buf, LV_FONT_DEFAULT, &attributes); lv_area_t txt_area; txt_area.x1 = draw_task->area.x1 + lv_area_get_width(&draw_task->area) / 2 - text_size.x / 2; diff --git a/tests/src/test_cases/widgets/test_scale.c b/tests/src/test_cases/widgets/test_scale.c index 3515b6381b..81a21493b1 100644 --- a/tests/src/test_cases/widgets/test_scale.c +++ b/tests/src/test_cases/widgets/test_scale.c @@ -278,7 +278,13 @@ static void draw_event_cb(lv_event_t * e) label_draw_dsc->text_local = 1; lv_point_t size; - lv_text_get_size(&size, label_draw_dsc->text, label_draw_dsc->font, 0, 0, 1000, LV_TEXT_FLAG_NONE); + lv_text_attributes_t attributes = {0}; + attributes.letter_space = 0; + attributes.line_space = 0; + attributes.max_width = 1000; + attributes.text_flags = LV_TEXT_FLAG_NONE; + + lv_text_get_size(&size, label_draw_dsc->text, label_draw_dsc->font, &attributes); int32_t new_w = size.x; int32_t old_w = lv_area_get_width(&draw_task->area); diff --git a/tests/src/test_cases_perf/test_label.c b/tests/src/test_cases_perf/test_label.c new file mode 100644 index 0000000000..9116509bfd --- /dev/null +++ b/tests/src/test_cases_perf/test_label.c @@ -0,0 +1,20 @@ +/* Performance test for the lv_text and lv_font_* functions */ +#if LV_BUILD_TEST_PERF +#include "unity/unity.h" + +static lv_obj_t * active_screen = NULL; +static lv_obj_t * label = NULL; + +void setUp(void) +{ + active_screen = lv_screen_active(); + label = lv_label_create(active_screen); +} + +void test_label(void) +{ + TEST_ASSERT_MAX_TIME(lv_label_set_text, 0.5, label, + "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Ut auctor sed dui interdum convallis. Proin in ante magna. Pellentesque placerat condimentum erat ac laoreet. Cras mi eros, convallis vitae massa ac, blandit sodales urna. Proin tincidunt fermentum leo a volutpat. Donec ut blandit tortor. Duis elementum nibh nec consequat sagittis. Lutrae sunt praeclarae"); + +} +#endif