mirror of
https://github.com/lvgl/lvgl.git
synced 2025-01-14 06:42:58 +08:00
Merge pull request #1120 from littlevgl/revert-1115-long_txt
Revert "Long txt wrapping refactor"
This commit is contained in:
commit
d823194378
@ -297,16 +297,6 @@ typedef void * lv_font_user_data_t;
|
|||||||
/*Can break (wrap) texts on these chars*/
|
/*Can break (wrap) texts on these chars*/
|
||||||
#define LV_TXT_BREAK_CHARS " ,.;:-_"
|
#define LV_TXT_BREAK_CHARS " ,.;:-_"
|
||||||
|
|
||||||
/* If a character is at least this long, will break wherever "prettiest" */
|
|
||||||
#define LV_TXT_LINE_BREAK_LONG_LEN 12
|
|
||||||
|
|
||||||
/* Minimum number of characters of a word to put on a line before a break */
|
|
||||||
#define LV_TXT_LINE_BREAK_LONG_PRE_MIN_LEN 3
|
|
||||||
|
|
||||||
/* Minimum number of characters of a word to put on a line after a break */
|
|
||||||
#define LV_TXT_LINE_BREAK_LONG_POST_MIN_LEN 3
|
|
||||||
|
|
||||||
|
|
||||||
/*===================
|
/*===================
|
||||||
* LV_OBJ SETTINGS
|
* LV_OBJ SETTINGS
|
||||||
*==================*/
|
*==================*/
|
||||||
|
@ -405,21 +405,6 @@
|
|||||||
#define LV_TXT_BREAK_CHARS " ,.;:-_"
|
#define LV_TXT_BREAK_CHARS " ,.;:-_"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* If a character is at least this long, will break wherever "prettiest" */
|
|
||||||
#ifndef LV_TXT_LINE_BREAK_LONG_LEN
|
|
||||||
#define LV_TXT_LINE_BREAK_LONG_LEN 12
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Minimum number of characters of a word to put on a line before a break */
|
|
||||||
#ifndef LV_TXT_LINE_BREAK_LONG_PRE_MIN_LEN
|
|
||||||
#define LV_TXT_LINE_BREAK_LONG_PRE_MIN_LEN 3
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Minimum number of characters of a word to put on a line after a break */
|
|
||||||
#ifndef LV_TXT_LINE_BREAK_LONG_POST_MIN_LEN
|
|
||||||
#define LV_TXT_LINE_BREAK_LONG_POST_MIN_LEN 3
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*===================
|
/*===================
|
||||||
* LV_OBJ SETTINGS
|
* LV_OBJ SETTINGS
|
||||||
*==================*/
|
*==================*/
|
||||||
|
@ -13,7 +13,6 @@
|
|||||||
#include "lv_disp.h"
|
#include "lv_disp.h"
|
||||||
#include "../lv_themes/lv_theme.h"
|
#include "../lv_themes/lv_theme.h"
|
||||||
#include "../lv_draw/lv_draw.h"
|
#include "../lv_draw/lv_draw.h"
|
||||||
#include "../lv_draw/lv_img_cache.h"
|
|
||||||
#include "../lv_misc/lv_anim.h"
|
#include "../lv_misc/lv_anim.h"
|
||||||
#include "../lv_misc/lv_task.h"
|
#include "../lv_misc/lv_task.h"
|
||||||
#include "../lv_misc/lv_fs.h"
|
#include "../lv_misc/lv_fs.h"
|
||||||
|
@ -130,133 +130,6 @@ void lv_txt_get_size(lv_point_t * size_res, const char * text, const lv_font_t *
|
|||||||
size_res->y -= line_space;
|
size_res->y -= line_space;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the next word of text. A word is delimited by break characters.
|
|
||||||
*
|
|
||||||
* If the word cannot fit in the max_width space, obey LV_TXT_LINE_BREAK_LONG_* rules.
|
|
||||||
*
|
|
||||||
* If the next word cannot fit anything, return 0.
|
|
||||||
*
|
|
||||||
* If the first character is a break character, returns the next index.
|
|
||||||
*
|
|
||||||
* Example calls from lv_txt_get_next_line() assuming sufficent max_width and
|
|
||||||
* txt = "Test text\n"
|
|
||||||
* 0123456789
|
|
||||||
*
|
|
||||||
* Calls would be as follows:
|
|
||||||
* 1. Return i=4, pointing at breakchar ' ', for the string "Test"
|
|
||||||
* 2. Return i=5, since i=4 was a breakchar.
|
|
||||||
* 3. Return i=9, pointing at breakchar '\n'
|
|
||||||
* 4. Parenting lv_txt_get_next_line() would detect subsequent '\0'
|
|
||||||
*
|
|
||||||
* @param txt a '\0' terminated string
|
|
||||||
* @param font pointer to a font
|
|
||||||
* @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 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.
|
|
||||||
* @return the index of the first char of the next word (in byte index not letter index. With UTF-8 they are different)
|
|
||||||
*/
|
|
||||||
static uint16_t lv_txt_get_next_word(const char * txt, const lv_font_t * font,
|
|
||||||
lv_coord_t letter_space, lv_coord_t max_width,
|
|
||||||
lv_txt_flag_t flag, uint32_t *word_w_ptr)
|
|
||||||
{
|
|
||||||
if(txt == NULL || txt[0] == '\0') return 0;
|
|
||||||
if(font == NULL) return 0;
|
|
||||||
|
|
||||||
if(flag & LV_TXT_FLAG_EXPAND) max_width = LV_COORD_MAX;
|
|
||||||
|
|
||||||
uint32_t i = 0, i_next = 0, i_next_next = 0; /* Iterating index into txt */
|
|
||||||
lv_txt_cmd_state_t cmd_state = LV_TXT_CMD_STATE_WAIT;
|
|
||||||
uint32_t letter = 0; /* Letter at i */
|
|
||||||
uint32_t letter_next = 0; /* Letter at i_next */
|
|
||||||
lv_coord_t letter_w;
|
|
||||||
lv_coord_t cur_w = 0; /* Pixel Width of transversed string */
|
|
||||||
uint32_t word_len = 0; /* Number of characters in the transversed word */
|
|
||||||
uint32_t break_index = NO_BREAK_FOUND; /* only used for "long" words */
|
|
||||||
uint32_t break_letter_count = 0; /* Number of characters up to the long word break point */
|
|
||||||
|
|
||||||
letter = lv_txt_encoded_next(txt, &i_next);
|
|
||||||
i_next_next = i_next;
|
|
||||||
|
|
||||||
while(txt[i] != '\0') {
|
|
||||||
letter_next = lv_txt_encoded_next(txt, &i_next_next);
|
|
||||||
word_len++;
|
|
||||||
|
|
||||||
/*Handle the recolor command*/
|
|
||||||
if((flag & LV_TXT_FLAG_RECOLOR) != 0) {
|
|
||||||
if(lv_txt_is_cmd(&cmd_state, letter) != false) {
|
|
||||||
continue; /*Skip the letter is it is part of a command*/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
letter_w = lv_font_get_glyph_width(font, letter, letter_next);
|
|
||||||
cur_w += letter_w;
|
|
||||||
|
|
||||||
|
|
||||||
/* Test if this character fits within max_width */
|
|
||||||
if( break_index == NO_BREAK_FOUND && cur_w > max_width) {
|
|
||||||
break_index = i;
|
|
||||||
if(break_index > 0) { /* zero is possible if first character doesn't fit in width */
|
|
||||||
lv_txt_encoded_prev(txt, &break_index);
|
|
||||||
}
|
|
||||||
/* break_index is now pointing at the character that doesn't fit */
|
|
||||||
break_letter_count = word_len - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*Check for new line chars and breakchars*/
|
|
||||||
if(letter == '\n' || letter == '\r' || is_break_char(letter)) {
|
|
||||||
/* Update the output width on the first character if it fits.
|
|
||||||
* Must do this here incase first letter is a break character. */
|
|
||||||
if(i == 0 && break_index == NO_BREAK_FOUND && word_w_ptr != NULL) *word_w_ptr = cur_w;
|
|
||||||
word_len--;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Update the output width */
|
|
||||||
if( word_w_ptr != NULL && break_index == NO_BREAK_FOUND ) *word_w_ptr = cur_w;
|
|
||||||
|
|
||||||
if(letter_w > 0) {
|
|
||||||
cur_w += letter_space;
|
|
||||||
}
|
|
||||||
|
|
||||||
i = i_next;
|
|
||||||
i_next = i_next_next;
|
|
||||||
letter = letter_next;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Entire Word fits in the provided space */
|
|
||||||
if( break_index == NO_BREAK_FOUND ) {
|
|
||||||
if( word_len == 0 || (letter == '\r' && letter_next == '\n') ) i = i_next;
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Word doesn't fit in provided space, but isn't "long" */
|
|
||||||
if(word_len < LV_TXT_LINE_BREAK_LONG_LEN) {
|
|
||||||
if(word_w_ptr != NULL) *word_w_ptr = 0;
|
|
||||||
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(word_w_ptr != NULL) *word_w_ptr = 0;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Word is a "long", but letters may need to be better distributed */
|
|
||||||
{
|
|
||||||
i = break_index;
|
|
||||||
int32_t n_move = LV_TXT_LINE_BREAK_LONG_POST_MIN_LEN - (word_len - break_letter_count);
|
|
||||||
/* Move pointer "i" backwards */
|
|
||||||
for(;n_move>0; n_move--){
|
|
||||||
lv_txt_encoded_prev(txt, &i);
|
|
||||||
// todo: it would be appropriate to update the returned word width here
|
|
||||||
// However, in current usage, this doesn't impact anything.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the next line of text. Check line length and break chars too.
|
* Get the next line of text. Check line length and break chars too.
|
||||||
@ -275,32 +148,65 @@ uint16_t lv_txt_get_next_line(const char * txt, const lv_font_t * font,
|
|||||||
|
|
||||||
if(flag & LV_TXT_FLAG_EXPAND) max_width = LV_COORD_MAX;
|
if(flag & LV_TXT_FLAG_EXPAND) max_width = LV_COORD_MAX;
|
||||||
|
|
||||||
uint32_t i = 0; /* Iterating index into txt */
|
uint32_t i = 0;
|
||||||
|
uint32_t i_next = 0;
|
||||||
|
lv_coord_t cur_w = 0;
|
||||||
|
uint32_t last_break = NO_BREAK_FOUND;
|
||||||
|
lv_txt_cmd_state_t cmd_state = LV_TXT_CMD_STATE_WAIT;
|
||||||
|
uint32_t letter_w;
|
||||||
|
uint32_t letter = 0;
|
||||||
|
uint32_t letter_next = 0;
|
||||||
|
|
||||||
while(txt[i] != '\0' && max_width > 0) {
|
letter_next = lv_txt_encoded_next(txt, &i_next);
|
||||||
uint32_t word_w = 0;
|
|
||||||
uint32_t advance = lv_txt_get_next_word(&txt[i], font, letter_space, max_width, flag, &word_w);
|
|
||||||
max_width -= word_w;
|
|
||||||
|
|
||||||
if( advance == 0 ){
|
while(txt[i] != '\0') {
|
||||||
if(i == 0) lv_txt_encoded_next(txt, &i); // prevent inf loops
|
letter = letter_next;
|
||||||
break;
|
i = i_next;
|
||||||
|
letter_next = lv_txt_encoded_next(txt, &i_next);
|
||||||
|
|
||||||
|
/*Handle the recolor command*/
|
||||||
|
if((flag & LV_TXT_FLAG_RECOLOR) != 0) {
|
||||||
|
if(lv_txt_is_cmd(&cmd_state, letter) != false) {
|
||||||
|
continue; /*Skip the letter is it is part of a command*/
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
i += advance;
|
/*Check for new line chars*/
|
||||||
|
if(letter == '\n' || letter == '\r') {
|
||||||
|
/*Return with the first letter of the next line*/
|
||||||
|
if(letter == '\r' && letter_next == '\n') return i_next;
|
||||||
|
else return i;
|
||||||
|
} else { /*Check the actual length*/
|
||||||
|
letter_w = lv_font_get_glyph_width(font, letter, letter_next);
|
||||||
|
cur_w += letter_w;
|
||||||
|
|
||||||
if(txt[i] == '\n') break;
|
/*If the txt is too long then finish, this is the line end*/
|
||||||
}
|
if(cur_w > max_width) {
|
||||||
|
/*If a break character was already found break there*/
|
||||||
|
if(last_break != NO_BREAK_FOUND) {
|
||||||
|
i = last_break;
|
||||||
|
} else {
|
||||||
|
/* Now this character is out of the area so it will be first character of the next line*/
|
||||||
|
/* But 'i' already points to the next character (because of lv_txt_utf8_next) step beck one*/
|
||||||
|
lv_txt_encoded_prev(txt, &i);
|
||||||
|
}
|
||||||
|
|
||||||
/* If this is the last of the string, make sure pointer is at NULL-terminator.
|
/* Do not let to return without doing nothing.
|
||||||
* This catches the case, for example of a string ending in "\n" */
|
* Find at least one character (Avoid infinite loop )*/
|
||||||
if(txt[i] != '\0'){
|
if(i == 0) lv_txt_encoded_next(txt, &i);
|
||||||
uint32_t i_next = i;
|
|
||||||
int tmp;
|
return i;
|
||||||
uint32_t letter_next = lv_txt_encoded_next(txt, &i_next); /*Gets current character*/
|
}
|
||||||
tmp = i_next;
|
/*If this char still can fit to this line then check if
|
||||||
letter_next = lv_txt_encoded_next(txt, &i_next); /*Gets subsequent character*/
|
* txt can be broken here later */
|
||||||
if(letter_next == '\0') i = tmp;
|
else if(is_break_char(letter)) {
|
||||||
|
last_break = i; /*Save the first char index after break*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(letter_w > 0) {
|
||||||
|
cur_w += letter_space;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return i;
|
return i;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user