From 569edb76857c458636b7d23e1b80c3b13ba53bf3 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Fri, 22 Sep 2017 09:52:53 +0200 Subject: [PATCH] utf-8: lv_label full support, lv_ta in pwd_mode still not working --- lv_draw/lv_draw.c | 20 +++++----- lv_draw/lv_draw_vbasic.c | 2 +- lv_draw/lv_draw_vbasic.h | 2 +- lv_objx/lv_label.c | 63 +++++++---------------------- lv_objx/lv_label.h | 5 ++- lv_objx/lv_list.c | 19 --------- lv_objx/lv_list.h | 7 ---- lv_objx/lv_ta.c | 85 ++++++++++++++++++++++++++++------------ 8 files changed, 91 insertions(+), 112 deletions(-) diff --git a/lv_draw/lv_draw.c b/lv_draw/lv_draw.c index b8f02483d..6e027d2c0 100644 --- a/lv_draw/lv_draw.c +++ b/lv_draw/lv_draw.c @@ -64,14 +64,14 @@ static void point_swap(point_t * p1, point_t * p2); #if LV_VDB_SIZE != 0 static void (*px_fp)(cord_t x, cord_t y, const area_t * mask_p, color_t color, opa_t opa) = lv_vpx; static void (*fill_fp)(const area_t * cords_p, const area_t * mask_p, color_t color, opa_t opa) = lv_vfill; -static void (*letter_fp)(const point_t * pos_p, const area_t * mask_p, const font_t * font_p, uint8_t letter, color_t color, opa_t opa) = lv_vletter; +static void (*letter_fp)(const point_t * pos_p, const area_t * mask_p, const font_t * font_p, uint32_t letter, color_t color, opa_t opa) = lv_vletter; #if USE_FSINT != 0 static void (*map_fp)(const area_t * cords_p, const area_t * mask_p, const color_t * map_p, opa_t opa, bool transp, bool upscale, color_t recolor, opa_t recolor_opa) = lv_vmap; #endif #else static void (*px_fp)(cord_t x, cord_t y, const area_t * mask_p, color_t color, opa_t opa) = lv_rpx; static void (*fill_fp)(const area_t * cords_p, const area_t * mask_p, color_t color, opa_t opa) = lv_rfill; -static void (*letter_fp)(const point_t * pos_p, const area_t * mask_p, const font_t * font_p, uint8_t letter, color_t color, opa_t opa) = lv_rletter; +static void (*letter_fp)(const point_t * pos_p, const area_t * mask_p, const font_t * font_p, uint32_t letter, color_t color, opa_t opa) = lv_rletter; #if USE_LV_IMG != 0 && USE_FSINT != 0 static void (*map_fp)(const area_t * cords_p, const area_t * mask_p, const color_t * map_p, opa_t opa, bool transp, bool upscale, color_t recolor, opa_t recolor_opa) = lv_rmap; #endif @@ -280,13 +280,15 @@ void lv_draw_label(const area_t * cords_p,const area_t * mask_p, const lv_style_ } /*Write all letter of a line*/ cmd_state = CMD_STATE_WAIT; - - for(i = line_start; i < line_end; i++) { + i = line_start; + uint32_t letter; + while(i < line_end) { + letter = txt_utf8_next(txt, &i); /*Handle the re-color command*/ if((flag & TXT_FLAG_RECOLOR) != 0) { - if(txt[i] == TXT_RECOLOR_CMD) { + if(letter == TXT_RECOLOR_CMD) { if(cmd_state == CMD_STATE_WAIT) { /*Start char*/ - par_start = i + 1; + par_start = i + txt_utf8_size(&txt[i]); cmd_state = CMD_STATE_PAR; continue; } else if(cmd_state == CMD_STATE_PAR) { /*Other start char in parameter escaped cmd. char */ @@ -299,7 +301,7 @@ void lv_draw_label(const area_t * cords_p,const area_t * mask_p, const lv_style_ /*Skip the color parameter and wait the space after it*/ if(cmd_state == CMD_STATE_PAR) { - if(txt[i] == ' ') { + if(letter == ' ') { /*Get the parameter*/ if(i - par_start == LABEL_RECOLOR_PAR_LENGTH) { char buf[LABEL_RECOLOR_PAR_LENGTH + 1]; @@ -320,9 +322,9 @@ void lv_draw_label(const area_t * cords_p,const area_t * mask_p, const lv_style_ color_t color = style->ccolor; if(cmd_state == CMD_STATE_IN) color = recolor; - letter_fp(&pos, mask_p, font, txt[i], color, style->opa); + letter_fp(&pos, mask_p, font, letter, color, style->opa); - pos.x += (font_get_width(font, txt[i]) >> FONT_ANTIALIAS) + style->letter_space; + pos.x += (font_get_width(font, letter) >> FONT_ANTIALIAS) + style->letter_space; } /*Go to next line*/ diff --git a/lv_draw/lv_draw_vbasic.c b/lv_draw/lv_draw_vbasic.c index d3f543c6e..90fd052f6 100644 --- a/lv_draw/lv_draw_vbasic.c +++ b/lv_draw/lv_draw_vbasic.c @@ -148,7 +148,7 @@ void lv_vfill(const area_t * cords_p, const area_t * mask_p, * @param opa opacity of letter (0..255) */ void lv_vletter(const point_t * pos_p, const area_t * mask_p, - const font_t * font_p, uint8_t letter, + const font_t * font_p, uint32_t letter, color_t color, opa_t opa) { if(font_p == NULL) return; diff --git a/lv_draw/lv_draw_vbasic.h b/lv_draw/lv_draw_vbasic.h index c347d18be..4e39117f5 100644 --- a/lv_draw/lv_draw_vbasic.h +++ b/lv_draw/lv_draw_vbasic.h @@ -54,7 +54,7 @@ void lv_vfill(const area_t * cords_p, const area_t * mask_p, * @param opa opacity of letter (0..255) */ void lv_vletter(const point_t * pos_p, const area_t * mask_p, - const font_t * font_p, uint8_t letter, + const font_t * font_p, uint32_t letter, color_t color, opa_t opa); /** diff --git a/lv_objx/lv_label.c b/lv_objx/lv_label.c index 03b898f80..c68c5eb73 100644 --- a/lv_objx/lv_label.c +++ b/lv_objx/lv_label.c @@ -271,15 +271,6 @@ void lv_label_set_long_mode(lv_obj_t * label, lv_label_long_mode_t long_mode) { lv_label_ext_t * ext = lv_obj_get_ext(label); - /*When changing from dot mode reload the characters replaced by dots*/ - if(ext->long_mode == LV_LABEL_LONG_DOTS && - ext->dot_end != LV_LABEL_DOT_END_INV) { - uint8_t i; - for(i = 0; i < LV_LABEL_DOT_NUM + 1; i++) { - ext->txt[ext->dot_end - LV_LABEL_DOT_NUM + i] = ext->dot_tmp[i]; - } - } - /*Delete the old animation (if exists)*/ anim_del(label, (anim_fp_t) lv_obj_set_x); anim_del(label, (anim_fp_t) lv_obj_set_y); @@ -397,6 +388,7 @@ void lv_label_get_letter_pos(lv_obj_t * label, uint16_t index, point_t * pos) line_start = new_line_start; } + /*If the last character is lie break then go to the next line*/ if((txt[index - 1] == '\n' || txt[index - 1] == '\r') && txt[index] == '\0') { y += letter_height + style->line_space; line_start = index; @@ -404,16 +396,20 @@ void lv_label_get_letter_pos(lv_obj_t * label, uint16_t index, point_t * pos) /*Calculate the x coordinate*/ cord_t x = 0; - uint32_t i; + uint32_t i = line_start; + uint32_t cnt = line_start; /*Count the letter (in UTF-8 1 letter not 1 byte)*/ txt_cmd_state_t cmd_state = TXT_CMD_STATE_WAIT; - for(i = line_start; i < index; i++) { + uint32_t letter; + while(cnt < index) { + letter = txt_utf8_next(txt, &i); + cnt++; /*Handle the recolor command*/ if((flag & TXT_FLAG_RECOLOR) != 0) { if(txt_is_cmd(&cmd_state, txt[i]) != false) { continue; /*Skip the letter is it is part of a command*/ } } - x += (font_get_width(font, txt[i]) >> FONT_ANTIALIAS) + style->letter_space; + x += (font_get_width(font, letter) >> FONT_ANTIALIAS) + style->letter_space; } if(style->txt_align == LV_TXT_ALIGN_MID) { @@ -474,8 +470,10 @@ uint16_t lv_label_get_letter_on(lv_obj_t * label, point_t * pos) } txt_cmd_state_t cmd_state = TXT_CMD_STATE_WAIT; - uint16_t i; - for(i = line_start; i < new_line_start - 1; i++) { + uint32_t i = line_start; + uint32_t letter; + while(i < new_line_start - 1) { + letter = txt_utf8_next(txt, &i); /*Handle the recolor command*/ if((flag & TXT_FLAG_RECOLOR) != 0) { if(txt_is_cmd(&cmd_state, txt[i]) != false) { @@ -483,8 +481,8 @@ uint16_t lv_label_get_letter_on(lv_obj_t * label, point_t * pos) } } - x += (font_get_width(font, txt[i]) >> FONT_ANTIALIAS) + style->letter_space; - if(pos->x < x) break; + x += (font_get_width(font, letter) >> FONT_ANTIALIAS) + style->letter_space; + if(pos->x < x) break; /*Get the position*/ } return i; @@ -660,40 +658,7 @@ static void lv_label_refr_text(lv_obj_t * label) else if (ext->long_mode == LV_LABEL_LONG_BREAK) { lv_obj_set_height(label, size.y); } - /*Replace the last 'LV_LABEL_DOT_NUM' characters with dots - * and save these characters*/ - else if(ext->long_mode == LV_LABEL_LONG_DOTS) { - point_t point; - point.x = lv_obj_get_width(label) - 1; - point.y = lv_obj_get_height(label) - 1; - uint16_t index = lv_label_get_letter_on(label, &point); - if(index < strlen(ext->txt) - 1) { - - /* Change the last 'LV_LABEL_DOT_NUM' to dots - * (if there are at least 'LV_LABEL_DOT_NUM' characters*/ - if(index > LV_LABEL_DOT_NUM) { - uint8_t i; - for(i = 0; i < LV_LABEL_DOT_NUM; i++) { - ext->dot_tmp[i] = ext->txt[index - LV_LABEL_DOT_NUM + i]; - ext->txt[index - LV_LABEL_DOT_NUM + i] = '.'; - } - /*The last character is '\0'. Save this character from the text too.*/ - ext->dot_tmp[i] = ext->txt[index]; - ext->txt[index] = '\0'; - } - /*Else with short text change all characters to dots*/ - else { - uint8_t i; - for(i = 0; i < LV_LABEL_DOT_NUM; i++) { - ext->txt[i] = '.'; - } - ext->txt[i] = '\0'; - } - /*Save the dot end index*/ - ext->dot_end = index; - } - } lv_obj_inv(label); } diff --git a/lv_objx/lv_label.h b/lv_objx/lv_label.h index f5e84758d..516eb2687 100644 --- a/lv_objx/lv_label.h +++ b/lv_objx/lv_label.h @@ -34,7 +34,6 @@ typedef enum { LV_LABEL_LONG_EXPAND, /*Expand the object size to the text size*/ LV_LABEL_LONG_BREAK, /*Keep the object width, break the too long lines and expand the object height*/ - LV_LABEL_LONG_DOTS, /*Keep the object size, break the text and write dots in the last line*/ LV_LABEL_LONG_SCROLL, /*Expand the object size and scroll the text on the parent (move the label object)*/ LV_LABEL_LONG_ROLL, /*Keep the size and roll the text infinitely*/ }lv_label_long_mode_t; @@ -46,7 +45,11 @@ typedef struct /*New data for this type */ char * txt; /*Text of the label*/ lv_label_long_mode_t long_mode; /*Determinate what to do with the long texts*/ +#if TXT_UTF8 == 0 char dot_tmp[LV_LABEL_DOT_NUM + 1]; /*Store the character which are replaced by dots (Handled by the library)*/ +#else + uint32_t dot_tmp[LV_LABEL_DOT_NUM + 1]; /*Store the character which are replaced by dots (Handled by the library)*/ +#endif uint16_t dot_end; /*The text end position in dot mode (Handled by the library)*/ point_t offset; /*Text draw position offset*/ uint8_t static_txt :1; /*Flag to indicate the text is static*/ diff --git a/lv_objx/lv_list.c b/lv_objx/lv_list.c index efcbe4fd6..644f8219c 100644 --- a/lv_objx/lv_list.c +++ b/lv_objx/lv_list.c @@ -349,25 +349,6 @@ void lv_list_set_sb_out(lv_obj_t * list, bool out) ext->sb_out = out == false ? 0 : 1; } -/** - * Enable or disable the text rolling on a list element - * @param liste pinter to list element - * @param en true: enable text scrolling, false: disable text scrolling - */ -void lv_list_set_element_text_roll(lv_obj_t * liste, bool en) -{ - lv_obj_t * label = lv_list_get_element_label(liste); - if(label == NULL) return; - - if(en == false) { - lv_label_set_long_mode(label, LV_LABEL_LONG_DOTS); - } else { - lv_obj_set_width(label, liste->cords.x2 - label->cords.x1); - lv_label_set_long_mode(label, LV_LABEL_LONG_ROLL); - } - -} - /** * Set styles of the list elements of a list in each state diff --git a/lv_objx/lv_list.h b/lv_objx/lv_list.h index 9ef8f8809..08255843f 100644 --- a/lv_objx/lv_list.h +++ b/lv_objx/lv_list.h @@ -103,13 +103,6 @@ void lv_list_down(lv_obj_t * list); */ void lv_list_set_sb_out(lv_obj_t * list, bool out); -/** - * Enable or disable the text rolling on a list element - * @param liste pinter to list element - * @param en true: enable text scrolling, false: disable text scrolling - */ -void lv_list_set_element_text_roll(lv_obj_t * liste, bool en); - /** * Set styles of the list elements of a list in each state * @param list pointer to list object diff --git a/lv_objx/lv_ta.c b/lv_objx/lv_ta.c index ac865234b..15131dc90 100644 --- a/lv_objx/lv_ta.c +++ b/lv_objx/lv_ta.c @@ -14,6 +14,7 @@ #include "../lv_obj/lv_group.h" #include "../lv_draw/lv_draw.h" #include "misc/gfx/anim.h" +#include "misc/gfx/text.h" /********************* * DEFINES @@ -103,7 +104,7 @@ lv_obj_t * lv_ta_create(lv_obj_t * par, lv_obj_t * copy) lv_obj_set_design_f(ext->page.scrl, lv_ta_scrling_design); lv_label_set_long_mode(ext->label, LV_LABEL_LONG_BREAK); - lv_label_set_text(ext->label, "Text area"); + lv_label_set_text(ext->label, "Text.area"); lv_page_glue_obj(ext->label, true); lv_obj_set_click(ext->label, false); lv_obj_set_style(new_ta, lv_style_get(LV_STYLE_PRETTY, NULL)); @@ -221,22 +222,32 @@ void lv_ta_add_char(lv_obj_t * ta, char c) if(ext->pwd_mode != 0) pwd_char_hider(ta); /*Make sure all the current text contains only '*'*/ - char buf[LV_TA_MAX_LENGTH]; + uint32_t cur_pos; +#if TXT_UTF8 == 0 + cur_pos = ext->cursor_pos; +#else + cur_pos = txt_utf8_get_id(label_txt, ext->cursor_pos); +#endif + + char buf[LV_TA_MAX_LENGTH]; /*Insert the character*/ - memcpy(buf, label_txt, ext->cursor_pos); - buf[ext->cursor_pos] = c; - memcpy(buf+ext->cursor_pos+1, label_txt+ext->cursor_pos, strlen(label_txt) - ext->cursor_pos + 1); + memcpy(buf, label_txt, cur_pos); + buf[cur_pos] = c; + memcpy(buf + cur_pos + 1, label_txt + cur_pos, strlen(label_txt) - cur_pos + 1); /*Refresh the label*/ lv_label_set_text(ext->label, buf); if(ext->pwd_mode != 0) { +#if TXT_UTF8 != 0 + cur_pos = txt_utf8_get_id(ext->pwd_tmp, ext->cursor_pos); /*Noral text contains '*', pwd_tmp normal UTF-8 letter, so the cursor points to a different byte*/ +#endif ext->pwd_tmp = dm_realloc(ext->pwd_tmp, strlen(ext->pwd_tmp) + 2); /*+2: the new char + \0 */ dm_assert(ext->pwd_tmp); - memcpy(buf, ext->pwd_tmp, ext->cursor_pos); - buf[ext->cursor_pos] = c; - memcpy(buf + ext->cursor_pos + 1, ext->pwd_tmp + ext->cursor_pos, strlen(ext->pwd_tmp) - ext->cursor_pos + 1); + memcpy(buf, ext->pwd_tmp, cur_pos); + buf[cur_pos] = c; + memcpy(buf + cur_pos + 1, ext->pwd_tmp + cur_pos, strlen(ext->pwd_tmp) - cur_pos + 1); strcpy(ext->pwd_tmp, buf); anim_t a; @@ -283,12 +294,18 @@ void lv_ta_add_text(lv_obj_t * ta, const char * txt) /*Insert the text*/ char buf[LV_TA_MAX_LENGTH]; - memcpy(buf, label_txt, ext->cursor_pos); - memcpy(buf + ext->cursor_pos, txt, txt_len); - memcpy(buf + ext->cursor_pos + txt_len, label_txt+ext->cursor_pos, label_len - ext->cursor_pos + 1); + uint32_t cur_pos; +#if TXT_UTF8 == 0 + cur_pos = ext->cursor_pos; +#else + cur_pos = txt_utf8_get_id(label_txt, ext->cursor_pos); +#endif + + memcpy(buf, label_txt, cur_pos); + memcpy(buf + cur_pos, txt, txt_len); + memcpy(buf + cur_pos + txt_len, label_txt+cur_pos, label_len - cur_pos + 1); /*Refresh the label*/ - lv_label_set_text(ext->label, buf); @@ -296,8 +313,8 @@ void lv_ta_add_text(lv_obj_t * ta, const char * txt) ext->pwd_tmp = dm_realloc(ext->pwd_tmp, strlen(ext->pwd_tmp) + txt_len + 1); dm_assert(ext->pwd_tmp); memcpy(buf, ext->pwd_tmp, ext->cursor_pos); - memcpy(buf + ext->cursor_pos, txt, txt_len); - memcpy(buf + ext->cursor_pos + txt_len, ext->pwd_tmp+ext->cursor_pos, label_len - ext->cursor_pos + 1); + memcpy(buf + cur_pos, txt, txt_len); + memcpy(buf + cur_pos + txt_len, ext->pwd_tmp+ext->cursor_pos, label_len - ext->cursor_pos + 1); strcpy(ext->pwd_tmp, buf); anim_t a; @@ -416,11 +433,11 @@ void lv_ta_set_cursor_pos(lv_obj_t * ta, int16_t pos) lv_ta_ext_t * ext = lv_obj_get_ext(ta); lv_obj_t * scrl = lv_page_get_scrl(ta); lv_style_t * style_scrl = lv_obj_get_style(scrl); - uint16_t txt_len = strlen(lv_label_get_text(ext->label)); + uint16_t len = txt_len(lv_label_get_text(ext->label)); - if(pos < 0) pos = txt_len + pos; + if(pos < 0) pos = len + pos; - if(pos > txt_len || pos == LV_TA_CUR_LAST) pos = txt_len; + if(pos > len || pos == LV_TA_CUR_LAST) pos = len; ext->cursor_pos = pos; @@ -457,6 +474,7 @@ void lv_ta_set_cursor_pos(lv_obj_t * ta, int16_t pos) font_h + 2 * style_scrl->hpad)); } + /*Reset cursor blink animation*/ anim_t a; a.var = ta; a.fp = (anim_fp_t)cursor_blink_anim; @@ -607,14 +625,15 @@ void lv_ta_set_pwd_mode(lv_obj_t * ta, bool en) /*Pwd mode is now enabled*/ if(ext->pwd_mode == 0 && en != false) { char * txt = lv_label_get_text(ext->label); - uint16_t txt_len = strlen(txt); - ext->pwd_tmp = dm_alloc(txt_len + 1); + uint16_t len = strlen(txt); + ext->pwd_tmp = dm_alloc(len + 1); strcpy(ext->pwd_tmp, txt); uint16_t i; - for(i = 0; i < txt_len; i++) { + for(i = 0; i < len; i++) { txt[i] = '*'; /*All char to '*'*/ } + txt[i] = '\0'; lv_label_set_text(ext->label, NULL); } @@ -828,7 +847,17 @@ static bool lv_ta_scrling_design(lv_obj_t * scrling, const area_t * mask, lv_des uint16_t cur_pos = lv_ta_get_cursor_pos(ta); const char * txt = lv_label_get_text(ta_ext->label); - cord_t letter_w = font_get_width(label_style->font, txt[cur_pos] != '\0' ? txt[cur_pos] : ' '); + + uint32_t byte_pos; +#if TXT_UTF8 != 0 + byte_pos = txt_utf8_get_id(txt, cur_pos); +#else + byte_pos = cur_pos; +#endif + + uint32_t letter = txt_utf8_next(&txt[byte_pos], NULL); + printf("letter %d\n", letter); + cord_t letter_w = font_get_width(label_style->font, letter != '\0' ? letter : ' '); cord_t letter_h = font_get_height(label_style->font) >> FONT_ANTIALIAS; point_t letter_pos; lv_label_get_letter_pos(ta_ext->label, cur_pos, &letter_pos); @@ -847,9 +876,15 @@ static bool lv_ta_scrling_design(lv_obj_t * scrling, const area_t * mask, lv_des cur_area.y2 = letter_pos.y + ta_ext->label->cords.y1 + letter_h; lv_draw_rect(&cur_area, mask, &cur_style); + /*Get the current letter*/ +#if TXT_UTF8 == 0 char letter_buf[2]; - letter_buf[0] = txt[cur_pos]; - letter_buf[1] = '\0'; + letter_buf[0] = txt[byte_pos]; + letter_buf[1] = '\0'; +#else + char letter_buf[8] = {0}; + memcpy(letter_buf, &txt[byte_pos], txt_utf8_size(txt[byte_pos])); +#endif lv_draw_label(&cur_area, mask, &cur_style, letter_buf, TXT_FLAG_NONE, 0); } else if(ta_ext->cursor_type == LV_TA_CURSOR_OUTLINE) { @@ -911,10 +946,10 @@ static void pwd_char_hider(lv_obj_t * ta) lv_ta_ext_t * ext = lv_obj_get_ext(ta); if(ext->pwd_mode != 0) { char * txt = lv_label_get_text(ext->label); - int16_t txt_len = strlen(txt); + int16_t len = txt_len(txt); bool refr = false; uint16_t i; - for(i = 0; i < txt_len; i++) { + for(i = 0; i < len; i++) { if(txt[i] != '*') { txt[i] = '*'; refr = true;