diff --git a/src/draw/lv_draw_label.c b/src/draw/lv_draw_label.c index ba5308dca..a7cb4ef8e 100644 --- a/src/draw/lv_draw_label.c +++ b/src/draw/lv_draw_label.c @@ -141,13 +141,13 @@ LV_ATTRIBUTE_FAST_MEM void lv_draw_label(const lv_area_t * coords, const lv_area pos.y += hint->y; } - uint32_t line_end = line_start + _lv_txt_get_next_line(&txt[line_start], font, dsc->letter_space, w, dsc->flag); + uint32_t line_end = line_start + _lv_txt_get_next_line(&txt[line_start], font, dsc->letter_space, w, NULL, dsc->flag); /*Go the first visible line*/ while(pos.y + line_height_font < mask->y1) { /*Go to next line*/ line_start = line_end; - line_end += _lv_txt_get_next_line(&txt[line_start], font, dsc->letter_space, w, dsc->flag); + line_end += _lv_txt_get_next_line(&txt[line_start], font, dsc->letter_space, w, NULL, dsc->flag); pos.y += line_height; /*Save at the threshold coordinate*/ @@ -323,7 +323,7 @@ LV_ATTRIBUTE_FAST_MEM void lv_draw_label(const lv_area_t * coords, const lv_area #endif /*Go to next line*/ line_start = line_end; - line_end += _lv_txt_get_next_line(&txt[line_start], font, dsc->letter_space, w, dsc->flag); + line_end += _lv_txt_get_next_line(&txt[line_start], font, dsc->letter_space, w, NULL, dsc->flag); pos.x = coords->x1; /*Align to middle*/ diff --git a/src/extra/widgets/span/lv_span.c b/src/extra/widgets/span/lv_span.c index d242fe26f..9282ae989 100644 --- a/src/extra/widgets/span/lv_span.c +++ b/src/extra/widgets/span/lv_span.c @@ -684,12 +684,10 @@ static bool lv_txt_get_snippet(const char * txt, const lv_font_t * font, return false; } - uint32_t ofs = _lv_txt_get_next_line(txt, font, letter_space, max_width, flag); - lv_coord_t width = lv_txt_get_width(txt, ofs, font, letter_space, flag); + uint32_t ofs = _lv_txt_get_next_line(txt, font, letter_space, max_width, use_width, flag); *end_ofs = ofs; - *use_width = width; - if(txt[ofs] == '\0' && width < max_width) { + if(txt[ofs] == '\0' && *use_width < max_width) { return false; } else { diff --git a/src/misc/lv_txt.c b/src/misc/lv_txt.c index fab48af18..02224fb54 100644 --- a/src/misc/lv_txt.c +++ b/src/misc/lv_txt.c @@ -105,7 +105,7 @@ void lv_txt_get_size(lv_point_t * size_res, const char * text, const lv_font_t * /*Calc. the height and longest line*/ while(text[line_start] != '\0') { - new_line_start += _lv_txt_get_next_line(&text[line_start], font, letter_space, max_width, flag); + new_line_start += _lv_txt_get_next_line(&text[line_start], font, letter_space, max_width, NULL, flag); if((unsigned long)size_res->y + (unsigned long)letter_height + (unsigned long)line_space > LV_MAX_OF(lv_coord_t)) { LV_LOG_WARN("lv_txt_get_size: integer overflow while calculating text height"); @@ -276,12 +276,17 @@ static uint32_t lv_txt_get_next_word(const char * txt, const lv_font_t * font, } uint32_t _lv_txt_get_next_line(const char * txt, const lv_font_t * font, - lv_coord_t letter_space, lv_coord_t max_width, lv_text_flag_t flag) + lv_coord_t letter_space, lv_coord_t max_width, + lv_coord_t * used_width, lv_text_flag_t flag) { + if(used_width) *used_width = 0; + if(txt == NULL) return 0; if(txt[0] == '\0') return 0; if(font == NULL) return 0; + lv_coord_t line_w = 0; + /*If max_width doesn't mater simply find the new line character *without thinking about word wrapping*/ if((flag & LV_TEXT_FLAG_EXPAND) || (flag & LV_TEXT_FLAG_FIT)) { @@ -290,6 +295,7 @@ uint32_t _lv_txt_get_next_line(const char * txt, const lv_font_t * font, /*Just find the new line chars or string ends by incrementing `i`*/ } if(txt[i] != '\0') i++; /*To go beyond `\n`*/ + if(used_width) *used_width = -1; return i; } @@ -301,9 +307,9 @@ uint32_t _lv_txt_get_next_line(const char * txt, const lv_font_t * font, uint32_t word_w = 0; uint32_t advance = lv_txt_get_next_word(&txt[i], font, letter_space, max_width, flag, &word_w, &cmd_state, i == 0); max_width -= word_w; + line_w += word_w; if(advance == 0) { - if(i == 0) _lv_txt_encoded_next(txt, &i); // prevent inf loops break; } @@ -320,7 +326,14 @@ uint32_t _lv_txt_get_next_line(const char * txt, const lv_font_t * font, /*Always step at least one to avoid infinite loops*/ if(i == 0) { - _lv_txt_encoded_next(txt, &i); + uint32_t letter = _lv_txt_encoded_next(txt, &i); + if(used_width != NULL) { + line_w = lv_font_get_glyph_width(font, letter, '\0'); + } + } + + if(used_width != NULL) { + *used_width = line_w; } return i; diff --git a/src/misc/lv_txt.h b/src/misc/lv_txt.h index 2775c862d..4f134ab6d 100644 --- a/src/misc/lv_txt.h +++ b/src/misc/lv_txt.h @@ -90,12 +90,14 @@ void lv_txt_get_size(lv_point_t * size_res, const char * text, const lv_font_t * * @param letter_space letter space * @param max_width max with of the text (break the lines to fit this size) Set CORD_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 flags 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) */ -uint32_t _lv_txt_get_next_line(const char * txt, const lv_font_t * font, lv_coord_t letter_space, lv_coord_t max_width, - lv_text_flag_t flag); +uint32_t _lv_txt_get_next_line(const char * txt, const lv_font_t * font, lv_coord_t letter_space, + lv_coord_t max_width, lv_coord_t * used_width, lv_text_flag_t flag); /** * Give the length of a text with a given font diff --git a/src/widgets/lv_label.c b/src/widgets/lv_label.c index 57c933257..8505382b4 100644 --- a/src/widgets/lv_label.c +++ b/src/widgets/lv_label.c @@ -329,7 +329,7 @@ void lv_label_get_letter_pos(const lv_obj_t * obj, uint32_t char_id, lv_point_t /*Search the line of the index letter*/; while(txt[new_line_start] != '\0') { - new_line_start += _lv_txt_get_next_line(&txt[line_start], font, letter_space, max_w, flag); + new_line_start += _lv_txt_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'*/ @@ -430,7 +430,7 @@ uint32_t lv_label_get_letter_on(const lv_obj_t * obj, lv_point_t * pos_in) /*Search the line of the index letter*/; while(txt[line_start] != '\0') { - new_line_start += _lv_txt_get_next_line(&txt[line_start], font, letter_space, max_w, flag); + new_line_start += _lv_txt_get_next_line(&txt[line_start], font, letter_space, max_w, NULL, flag); if(pos.y <= y + letter_height) { /*The line is found (stored in 'line_start')*/ @@ -548,7 +548,7 @@ bool lv_label_is_char_under_pos(const lv_obj_t * obj, lv_point_t * pos) /*Search the line of the index letter*/; while(txt[line_start] != '\0') { - new_line_start += _lv_txt_get_next_line(&txt[line_start], font, letter_space, max_w, flag); + new_line_start += _lv_txt_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')*/ y += letter_height + line_space; diff --git a/tests/src/test_cases/test_txt.c b/tests/src/test_cases/test_txt.c index 9487d2eda..6dbad90f0 100644 --- a/tests/src/test_cases/test_txt.c +++ b/tests/src/test_cases/test_txt.c @@ -199,7 +199,7 @@ void test_txt_next_line_should_handle_empty_string(void) lv_coord_t max_width = 0; lv_text_flag_t flag = LV_TEXT_FLAG_NONE; - uint32_t next_line = _lv_txt_get_next_line("", font_ptr, letter_space, max_width, flag); + uint32_t next_line = _lv_txt_get_next_line("", font_ptr, letter_space, max_width, NULL, flag); TEST_ASSERT_EQUAL_UINT32(0, next_line); }