Skip to content

Commit

Permalink
fix(label): do not break last line for LV_LABEL_LONG_DOT (lvgl#5606) (l…
Browse files Browse the repository at this point in the history
  • Loading branch information
niklasf authored Jul 15, 2024
1 parent bf1e6ab commit bac697f
Show file tree
Hide file tree
Showing 6 changed files with 35 additions and 11 deletions.
14 changes: 8 additions & 6 deletions src/misc/lv_text.c
Original file line number Diff line number Diff line change
Expand Up @@ -164,12 +164,11 @@ void lv_text_get_size(lv_point_t * size_res, const char * text, const lv_font_t
* @param max_width max width of the text (break the lines to fit this size). Set COORD_MAX to avoid line breaks
* @param flags settings for the text from 'txt_flag_type' enum
* @param[out] word_w_ptr width (in pixels) of the parsed word. May be NULL.
* @param force Force return the fraction of the word that can fit in the provided space.
* @return the index of the first char of the next word (in byte index not letter index. With UTF-8 they are different)
*/
static uint32_t lv_text_get_next_word(const char * txt, const lv_font_t * font,
int32_t letter_space, int32_t max_width,
lv_text_flag_t flag, uint32_t * word_w_ptr, bool force)
lv_text_flag_t flag, uint32_t * word_w_ptr)
{
if(txt == NULL || txt[0] == '\0') return 0;
if(font == NULL) return 0;
Expand Down Expand Up @@ -239,14 +238,14 @@ static uint32_t lv_text_get_next_word(const char * txt, const lv_font_t * font,
#if LV_TXT_LINE_BREAK_LONG_LEN > 0
/*Word doesn't fit in provided space, but isn't "long"*/
if(word_len < LV_TXT_LINE_BREAK_LONG_LEN) {
if(force) return break_index;
if(flag & LV_TEXT_FLAG_BREAK_ALL) return break_index;
if(word_w_ptr != NULL) *word_w_ptr = 0; /*Return no word*/
return 0;
}

/*Word is "long," but insufficient amounts can fit in provided space*/
if(break_letter_count < LV_TXT_LINE_BREAK_LONG_PRE_MIN_LEN) {
if(force) return break_index;
if(flag & LV_TEXT_FLAG_BREAK_ALL) return break_index;
if(word_w_ptr != NULL) *word_w_ptr = 0;
return 0;
}
Expand All @@ -266,7 +265,7 @@ static uint32_t lv_text_get_next_word(const char * txt, const lv_font_t * font,
}
return i;
#else
if(force) return break_index;
if(flag & LV_TEXT_FLAG_BREAK_ALL) return break_index;
if(word_w_ptr != NULL) *word_w_ptr = 0; /*Return no word*/
(void) break_letter_count;
return 0;
Expand Down Expand Up @@ -301,8 +300,11 @@ uint32_t lv_text_get_next_line(const char * txt, const lv_font_t * font,
uint32_t i = 0; /*Iterating index into txt*/

while(txt[i] != '\0' && max_width > 0) {
lv_text_flag_t word_flag = flag;
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, flag, &word_w, i == 0);
uint32_t advance = lv_text_get_next_word(&txt[i], font, letter_space, max_width, word_flag, &word_w);
max_width -= word_w;
line_w += word_w;

Expand Down
10 changes: 7 additions & 3 deletions src/misc/lv_text.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,13 @@ extern "C" {
*/

enum _lv_text_flag_t {
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_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.*/
};

#ifdef DOXYGEN
Expand Down
18 changes: 16 additions & 2 deletions src/widgets/label/lv_label.c
Original file line number Diff line number Diff line change
Expand Up @@ -291,11 +291,15 @@ void lv_label_get_letter_pos(const lv_obj_t * obj, uint32_t char_id, lv_point_t
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);

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_DOT) flag |= LV_TEXT_FLAG_BREAK_ALL;

new_line_start += lv_text_get_next_line(&txt[line_start], 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'*/
Expand Down Expand Up @@ -370,7 +374,8 @@ 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_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);
Expand All @@ -381,6 +386,11 @@ uint32_t lv_label_get_letter_on(const lv_obj_t * obj, lv_point_t * pos_in, bool

/*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_DOT) flag |= LV_TEXT_FLAG_BREAK_ALL;

new_line_start += lv_text_get_next_line(&txt[line_start], font, letter_space, max_w, NULL, flag);

if(pos.y <= y + letter_height) {
Expand Down Expand Up @@ -479,7 +489,8 @@ bool lv_label_is_char_under_pos(const lv_obj_t * obj, lv_point_t * pos)
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_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);
Expand All @@ -490,6 +501,9 @@ bool lv_label_is_char_under_pos(const lv_obj_t * obj, lv_point_t * pos)
/*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_DOT) flag |= LV_TEXT_FLAG_BREAK_ALL;

new_line_start += lv_text_get_next_line(&txt[line_start], font, letter_space, max_w, NULL, flag);

if(pos->y <= y + letter_height) break; /*The line is found (stored in 'line_start')*/
Expand Down
Binary file modified tests/ref_imgs/widgets/label_max_width.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/ref_imgs_vg_lite/widgets/label_max_width.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions tests/src/test_cases/widgets/test_label.c
Original file line number Diff line number Diff line change
Expand Up @@ -598,13 +598,17 @@ void test_label_max_width(void)
lv_label_set_text(test_label1, long_text);
lv_obj_set_width(test_label1, 600);
lv_obj_set_style_max_width(test_label1, 200, LV_PART_MAIN);
lv_obj_set_style_bg_color(test_label1, lv_palette_main(LV_PALETTE_GREY), LV_PART_MAIN);
lv_obj_set_style_bg_opa(test_label1, LV_OPA_100, LV_PART_MAIN);

lv_obj_t * test_label2 = lv_label_create(lv_screen_active());
lv_label_set_text(test_label2, long_text);
lv_obj_set_width(test_label2, 600);
lv_obj_set_height(test_label2, 50);
lv_obj_set_x(test_label2, 300);
lv_obj_set_style_max_width(test_label2, 200, LV_PART_MAIN);
lv_obj_set_style_bg_color(test_label2, lv_palette_main(LV_PALETTE_GREY), LV_PART_MAIN);
lv_obj_set_style_bg_opa(test_label2, LV_OPA_100, LV_PART_MAIN);
lv_label_set_long_mode(test_label2, LV_LABEL_LONG_DOT);

TEST_ASSERT_EQUAL_SCREENSHOT("widgets/label_max_width.png");
Expand Down

0 comments on commit bac697f

Please sign in to comment.