1
0
mirror of https://github.com/lvgl/lvgl.git synced 2025-01-14 06:42:58 +08:00

fix(label): do not break last line for LV_LABEL_LONG_DOT (#5606) (#6362)

This commit is contained in:
Niklas Fiekas 2024-07-15 16:13:31 +02:00 committed by GitHub
parent bf1e6ab39c
commit bac697ff9c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 35 additions and 11 deletions

View File

@ -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;
@ -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;
}
@ -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;
@ -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;

View File

@ -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

View File

@ -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'*/
@ -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);
@ -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) {
@ -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);
@ -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')*/

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.7 KiB

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.7 KiB

After

Width:  |  Height:  |  Size: 8.0 KiB

View File

@ -598,6 +598,8 @@ 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);
@ -605,6 +607,8 @@ void test_label_max_width(void)
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");