diff --git a/src/draw/lv_draw_label.c b/src/draw/lv_draw_label.c index a8c0b1ff6c..38d22a469b 100644 --- a/src/draw/lv_draw_label.c +++ b/src/draw/lv_draw_label.c @@ -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; 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 7390ebacd1..04495fa6ee 100644 --- a/src/draw/nema_gfx/lv_draw_nema_gfx_label.c +++ b/src/draw/nema_gfx/lv_draw_nema_gfx_label.c @@ -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); diff --git a/tests/ref_imgs/widgets/label_recolor_2.png b/tests/ref_imgs/widgets/label_recolor_2.png new file mode 100644 index 0000000000..1b52d5a81a Binary files /dev/null and b/tests/ref_imgs/widgets/label_recolor_2.png differ diff --git a/tests/ref_imgs_vg_lite/widgets/label_recolor_2.png b/tests/ref_imgs_vg_lite/widgets/label_recolor_2.png new file mode 100644 index 0000000000..d4e37857a6 Binary files /dev/null and b/tests/ref_imgs_vg_lite/widgets/label_recolor_2.png differ diff --git a/tests/src/test_cases/widgets/test_label.c b/tests/src/test_cases/widgets/test_label.c index e17c35cb10..399307cbd0 100644 --- a/tests/src/test_cases/widgets/test_label.c +++ b/tests/src/test_cases/widgets/test_label.c @@ -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);