fix(label): preserve recolor state across line wrapping (#8755)

Co-authored-by: jacobpanov <jacobpanov@gmail.com>
This commit is contained in:
André Costa
2025-09-05 04:18:50 +02:00
committed by GitHub
parent 91c1e38104
commit b83c104b37
5 changed files with 46 additions and 2 deletions
+1 -1
View File
@@ -339,6 +339,7 @@ void lv_draw_label_iterate_characters(lv_draw_task_t * t, const lv_draw_label_ds
uint32_t next_char_offset;
uint32_t recolor_command_start_index = 0;
int32_t letter_w;
cmd_state_t recolor_cmd_state = RECOLOR_CMD_STATE_WAIT_FOR_PARAMETER;
lv_color_t recolor = lv_color_black(); /* Holds the selected color inside the recolor command */
uint8_t is_first_space_after_cmd = 0;
@@ -349,7 +350,6 @@ void lv_draw_label_iterate_characters(lv_draw_task_t * t, const lv_draw_label_ds
line_start_x = pos.x;
/*Write all letter of a line*/
recolor_cmd_state = RECOLOR_CMD_STATE_WAIT_FOR_PARAMETER;
next_char_offset = 0;
#if LV_USE_BIDI
size_t bidi_size = line_end - line_start;
+1 -1
View File
@@ -530,6 +530,7 @@ static void _draw_label_iterate_characters(lv_draw_task_t * t, const lv_draw_lab
uint32_t next_char_offset;
uint32_t recolor_command_start_index = 0;
int32_t letter_w;
cmd_state_t recolor_cmd_state = RECOLOR_CMD_STATE_WAIT_FOR_PARAMETER;
lv_color_t recolor = lv_color_black(); /* Holds the selected color inside the recolor command */
uint8_t is_first_space_after_cmd = 0;
@@ -553,7 +554,6 @@ static void _draw_label_iterate_characters(lv_draw_task_t * t, const lv_draw_lab
line_start_x = pos.x;
/*Write all letter of a line*/
recolor_cmd_state = RECOLOR_CMD_STATE_WAIT_FOR_PARAMETER;
next_char_offset = 0;
#if LV_USE_BIDI
char * bidi_txt = lv_malloc(line_end - line_start + 1);
Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

+44
View File
@@ -626,6 +626,50 @@ void test_label_with_recolor_cmd(void)
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/label_recolor.png");
}
void test_label_recolor_with_text_wrap(void)
{
lv_obj_clean(lv_screen_active());
/* Create a label with recolor enabled and text wrapping */
lv_obj_t * label_recolor_wrap = lv_label_create(lv_screen_active());
/* Configure the label similar to the bug report */
lv_obj_set_style_text_font(label_recolor_wrap, &lv_font_montserrat_22, 0);
lv_obj_set_style_text_color(label_recolor_wrap, lv_color_hex(0x8199f7), 0);
lv_obj_set_width(label_recolor_wrap, 300); /* Fixed width to force wrapping */
lv_obj_set_style_text_align(label_recolor_wrap, LV_TEXT_ALIGN_CENTER, 0);
lv_label_set_long_mode(label_recolor_wrap, LV_LABEL_LONG_MODE_WRAP);
lv_label_set_recolor(label_recolor_wrap, true);
/* Test text with recolor commands that should wrap across multiple lines */
const char * test_text_with_recolor =
"Before color. #ff0000 This is a very long red colored text that should maintain its red color even when it wraps across multiple lines due to the label width being too narrow to contain the entire text on a single line# After color.";
lv_label_set_text(label_recolor_wrap, test_text_with_recolor);
lv_obj_align(label_recolor_wrap, LV_ALIGN_TOP_MID, 0, 20);
/* Create a reference label without recolor for comparison */
lv_obj_t * label_no_recolor = lv_label_create(lv_screen_active());
lv_obj_set_style_text_font(label_no_recolor, &lv_font_montserrat_22, 0);
lv_obj_set_style_text_color(label_no_recolor, lv_color_hex(0x8199f7), 0);
lv_obj_set_width(label_no_recolor, 300);
lv_obj_set_style_text_align(label_no_recolor, LV_TEXT_ALIGN_CENTER, 0);
lv_label_set_long_mode(label_no_recolor, LV_LABEL_LONG_MODE_WRAP);
lv_label_set_recolor(label_no_recolor, false); /* Disabled for comparison */
/* Same text but without recolor commands */
const char * test_text_without_recolor =
"Before color. This is a very long red colored text that should maintain its red color even when it wraps across multiple lines due to the label width being too narrow to contain the entire text on a single line After color.";
lv_label_set_text(label_no_recolor, test_text_without_recolor);
lv_obj_align(label_no_recolor, LV_ALIGN_BOTTOM_MID, 0, -20);
/* The bug would manifest as improper recolor handling when text wraps */
/* This test verifies that recolor commands work correctly with text wrapping */
/* No assertion needed - the test passes if no crashes occur during rendering */
TEST_ASSERT_EQUAL_SCREENSHOT("widgets/label_recolor_2.png");
}
static void scroll_next_step(lv_obj_t * label1, lv_obj_t * label2, const char * text1, const char * text2, uint32_t idx)
{
lv_label_set_text(label1, (idx % 2) == 0 ? text1 : text2);