From 5574bac486d267fc85174bfcf88467006db36f09 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Fri, 15 Nov 2019 07:28:42 +0100 Subject: [PATCH] minor fixes --- src/lv_draw/lv_draw_label.c | 15 +++++-- src/lv_misc/lv_bidi.c | 88 ++++++++++++++++++++++++++++++++++--- src/lv_misc/lv_bidi.h | 84 ++++++++++++++++++++++++++++++++++- src/lv_objx/lv_label.c | 31 +++++-------- src/lv_objx/lv_table.c | 1 - 5 files changed, 187 insertions(+), 32 deletions(-) diff --git a/src/lv_draw/lv_draw_label.c b/src/lv_draw/lv_draw_label.c index a957a44e0..e4b712971 100644 --- a/src/lv_draw/lv_draw_label.c +++ b/src/lv_draw/lv_draw_label.c @@ -183,16 +183,15 @@ void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_st /*Write out all lines*/ while(txt[line_start] != '\0') { - if(offset != NULL) { - pos.x += x_ofs; - } + if(offset != NULL) pos.x += x_ofs; + /*Write all letter of a line*/ cmd_state = CMD_STATE_WAIT; i = 0; uint32_t letter; uint32_t letter_next; #if LV_USE_BIDI - char *bidi_txt = lv_draw_get_buf(line_end - line_start + 1); + char *bidi_txt = lv_draw_buf_get(line_end - line_start + 1); lv_bidi_process_paragraph(txt + line_start, bidi_txt, line_end - line_start, bidi_dir, NULL, 0); #else const char *bidi_txt = txt + line_start; @@ -274,6 +273,11 @@ void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_st pos.x += letter_w + style->text.letter_space; } } + +#if LV_USE_BIDI + lv_draw_buf_release(bidi_txt); + bidi_txt = NULL; +#endif /*Go to next line*/ line_start = line_end; line_end += lv_txt_get_next_line(&txt[line_start], font, style->text.letter_space, w, flag); @@ -294,6 +298,9 @@ void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_st pos.x += lv_area_get_width(coords) - line_width; } + + + /*Go the next line position*/ pos.y += line_height; diff --git a/src/lv_misc/lv_bidi.c b/src/lv_misc/lv_bidi.c index bde752071..9896d03c5 100644 --- a/src/lv_misc/lv_bidi.c +++ b/src/lv_misc/lv_bidi.c @@ -58,6 +58,13 @@ static uint8_t br_stack_p; * GLOBAL FUNCTIONS **********************/ +/** + * Convert a text to get the characters in the correct visual order according to + * Unicode Bidirectional Algorithm + * @param str_in the text to process + * @param str_out store the result here. Has the be `strlen(str_in)` length + * @param base_dir `LV_BIDI_DIR_LTR` or `LV_BIDI_DIR_RTL` + */ void lv_bidi_process(const char * str_in, char * str_out, lv_bidi_dir_t base_dir) { if(base_dir == LV_BIDI_DIR_AUTO) base_dir = lv_bidi_detect_base_dir(str_in); @@ -84,6 +91,11 @@ void lv_bidi_process(const char * str_in, char * str_out, lv_bidi_dir_t base_dir str_out[par_start] = '\0'; } +/** + * Auto-detect the direction of a text based on the first strong character + * @param txt the text to process + * @return `LV_BIDI_DIR_LTR` or `LV_BIDI_DIR_RTL` + */ lv_bidi_dir_t lv_bidi_detect_base_dir(const char * txt) { uint32_t i = 0; @@ -100,7 +112,11 @@ lv_bidi_dir_t lv_bidi_detect_base_dir(const char * txt) if(LV_BIDI_BASE_DIR_DEF == LV_BIDI_DIR_AUTO) return LV_BIDI_DIR_LTR; else return LV_BIDI_BASE_DIR_DEF; } - +/** + * Get the direction of a character + * @param letter an Unicode character + * @return `LV_BIDI_DIR_RTL/LTR/WEAK/NEUTRAL` + */ lv_bidi_dir_t lv_bidi_get_letter_dir(uint32_t letter) { if(lv_bidi_letter_is_rtl(letter)) return LV_BIDI_DIR_RTL; @@ -109,7 +125,11 @@ lv_bidi_dir_t lv_bidi_get_letter_dir(uint32_t letter) return LV_BIDI_DIR_LTR; } - +/** + * Tell whether a character is weak or not + * @param letter an Unicode character + * @return true/false + */ bool lv_bidi_letter_is_weak(uint32_t letter) { uint32_t i = 0; @@ -124,16 +144,24 @@ bool lv_bidi_letter_is_weak(uint32_t letter) return false; } - +/** + * Tell whether a character is RTL or not + * @param letter an Unicode character + * @return true/false + */ bool lv_bidi_letter_is_rtl(uint32_t letter) { if(letter >= 0x5d0 && letter <= 0x5ea) return true; if(letter == 0x202E) return true; /*Unicode of LV_BIDI_RLO*/ -// if(letter >= 'a' && letter <= 'z') return true; return false; } +/** + * Tell whether a character is neutral or not + * @param letter an Unicode character + * @return true/false + */ bool lv_bidi_letter_is_neutral(uint32_t letter) { uint16_t i; @@ -145,33 +173,76 @@ bool lv_bidi_letter_is_neutral(uint32_t letter) return false; } +/** + * Get the logical position of a character in a line + * @param str_in the input string. Can be only one line. + * @param bidi_txt internally the text is bidi processed which buffer can be get here. + * If not required anymore has to freed with `lv_mem_free()` + * Can be `NULL` is unused + * @param len length of the line in character count + * @param base_dir base direction of the text: `LV_BIDI_DIR_LTR` or `LV_BIDI_DIR_RTL` + * @param vicual_pos the visual character position which logical position should be get + * @param is_rtl tell the the char at `viasual_pos` is RTL or LTR context + * @return the logical character position + */ uint16_t lv_bidi_get_logical_pos(const char * str_in, char **bidi_txt, uint32_t len, lv_bidi_dir_t base_dir, uint32_t visual_pos, bool *is_rtl) { uint32_t pos_conv_len = get_txt_len(str_in, len); - void *buf = lv_draw_get_buf(len + pos_conv_len * sizeof(uint16_t)); + void *buf = lv_mem_alloc(len + pos_conv_len * sizeof(uint16_t)); + if(buf == NULL) return (uint16_t) -1; if (bidi_txt) *bidi_txt = buf; + uint16_t *pos_conv_buf = (uint16_t*) ((char*)buf + len); lv_bidi_process_paragraph(str_in, bidi_txt? *bidi_txt: NULL, len, base_dir, pos_conv_buf, pos_conv_len); + if (is_rtl) *is_rtl = IS_RTL_POS(pos_conv_buf[visual_pos]); + + if(bidi_txt == NULL) lv_mem_free(buf); return GET_POS(pos_conv_buf[visual_pos]); } +/** + * Get the visual position of a character in a line + * @param str_in the input string. Can be only one line. + * @param bidi_txt internally the text is bidi processed which buffer can be get here. + * If not required anymore has to freed with `lv_mem_free()` + * Can be `NULL` is unused + * @param len length of the line in character count + * @param base_dir base direction of the text: `LV_BIDI_DIR_LTR` or `LV_BIDI_DIR_RTL` + * @param logical_pos the logical character position which visual position should be get + * @param is_rtl tell the the char at `logical_pos` is RTL or LTR context + * @return the visual character position + */ uint16_t lv_bidi_get_visual_pos(const char * str_in, char **bidi_txt, uint16_t len, lv_bidi_dir_t base_dir, uint32_t logical_pos, bool *is_rtl) { uint32_t pos_conv_len = get_txt_len(str_in, len); - void *buf = lv_draw_get_buf(len + pos_conv_len * sizeof(uint16_t)); + void *buf = lv_mem_alloc(len + pos_conv_len * sizeof(uint16_t)); + if(buf == NULL) return (uint16_t) -1; if (bidi_txt) *bidi_txt = buf; + uint16_t *pos_conv_buf = (uint16_t*) ((char*)buf + len); lv_bidi_process_paragraph(str_in, bidi_txt? *bidi_txt: NULL, len, base_dir, pos_conv_buf, pos_conv_len); for (uint16_t i = 0; i < pos_conv_len; i++){ if (GET_POS(pos_conv_buf[i]) == logical_pos){ if (is_rtl) *is_rtl = IS_RTL_POS(pos_conv_buf[i]); + if(bidi_txt == NULL) lv_mem_free(buf); return i; } } + if(bidi_txt == NULL) lv_mem_free(buf); return (uint16_t) -1; } +/** + * Bidi process a paragraph of text + * @param str_in the string to process + * @param str_out store the result here + * @param len length of teh text + * @param base_dir base dir of the text + * @param pos_conv_out an `uint16_t` array to store the related logical position of the character. + * Can be `NULL` is unused + * @param pos_conv_len length of `pos_conv_out` in element count + */ void lv_bidi_process_paragraph(const char * str_in, char * str_out, uint32_t len, lv_bidi_dir_t base_dir, uint16_t *pos_conv_out, uint16_t pos_conv_len) { uint32_t run_len = 0; @@ -258,6 +329,11 @@ void lv_bidi_process_paragraph(const char * str_in, char * str_out, uint32_t len } } +/** + * Get the next paragraph from a text + * @param txt the text to process + * @return the length of the current paragraph in byte count + */ uint32_t lv_bidi_get_next_paragraph(const char * txt) { uint32_t i = 0; diff --git a/src/lv_misc/lv_bidi.h b/src/lv_misc/lv_bidi.h index 215727aa7..dfa6565bd 100644 --- a/src/lv_misc/lv_bidi.h +++ b/src/lv_misc/lv_bidi.h @@ -52,17 +52,97 @@ typedef uint8_t lv_bidi_dir_t; **********************/ #if LV_USE_BIDI +/** + * Convert a text to get the characters in the correct visual order according to + * Unicode Bidirectional Algorithm + * @param str_in the text to process + * @param str_out store the result here. Has the be `strlen(str_in)` length + * @param base_dir `LV_BIDI_DIR_LTR` or `LV_BIDI_DIR_RTL` + */ void lv_bidi_process(const char * str_in, char * str_out, lv_bidi_dir_t base_dir); -void lv_bidi_process_paragraph(const char * str_in, char * str_out, uint32_t len, lv_bidi_dir_t base_dir, uint16_t *pos_conv_out, uint16_t pos_conv_len); -uint32_t lv_bidi_get_next_paragraph(const char * txt); + +/** + * Auto-detect the direction of a text based on the first strong character + * @param txt the text to process + * @return `LV_BIDI_DIR_LTR` or `LV_BIDI_DIR_RTL` + */ lv_bidi_dir_t lv_bidi_detect_base_dir(const char * txt); + +/** + * Get the direction of a character + * @param letter an Unicode character + * @return `LV_BIDI_DIR_RTL/LTR/WEAK/NEUTRAL` + */ lv_bidi_dir_t lv_bidi_get_letter_dir(uint32_t letter); + +/** + * Tell whether a character is weak or not + * @param letter an Unicode character + * @return true/false + */ bool lv_bidi_letter_is_weak(uint32_t letter); + +/** + * Tell whether a character is RTL or not + * @param letter an Unicode character + * @return true/false + */ bool lv_bidi_letter_is_rtl(uint32_t letter); + +/** + * Tell whether a character is neutral or not + * @param letter an Unicode character + * @return true/false + */ bool lv_bidi_letter_is_neutral(uint32_t letter); + +/** + * Get the logical position of a character in a line + * @param str_in the input string. Can be only one line. + * @param bidi_txt internally the text is bidi processed which buffer can be get here. + * If not required anymore has to freed with `lv_mem_free()` + * Can be `NULL` is unused + * @param len length of the line in character count + * @param base_dir base direction of the text: `LV_BIDI_DIR_LTR` or `LV_BIDI_DIR_RTL` + * @param vicual_pos the visual character position which logical position should be get + * @param is_rtl tell the the char at `viasual_pos` is RTL or LTR context + * @return the logical character position + */ uint16_t lv_bidi_get_logical_pos(const char * str_in, char **bidi_txt, uint32_t len, lv_bidi_dir_t base_dir, uint32_t visual_pos, bool *is_rtl); + +/** + * Get the visual position of a character in a line + * @param str_in the input string. Can be only one line. + * @param bidi_txt internally the text is bidi processed which buffer can be get here. + * If not required anymore has to freed with `lv_mem_free()` + * Can be `NULL` is unused + * @param len length of the line in character count + * @param base_dir base direction of the text: `LV_BIDI_DIR_LTR` or `LV_BIDI_DIR_RTL` + * @param logical_pos the logical character position which visual position should be get + * @param is_rtl tell the the char at `logical_pos` is RTL or LTR context + * @return the visual character position + */ uint16_t lv_bidi_get_visual_pos(const char * str_in, char **bidi_txt, uint16_t len, lv_bidi_dir_t base_dir, uint32_t logical_pos, bool *is_rtl); +/** + * Bidi process a paragraph of text + * @param str_in the string to process + * @param str_out store the result here + * @param len length of teh text + * @param base_dir base dir of the text + * @param pos_conv_out an `uint16_t` array to store the related logical position of the character. + * Can be `NULL` is unused + * @param pos_conv_len length of `pos_conv_out` in element count + */ +void lv_bidi_process_paragraph(const char * str_in, char * str_out, uint32_t len, lv_bidi_dir_t base_dir, uint16_t *pos_conv_out, uint16_t pos_conv_len); + +/** + * Get the next paragraph from a text + * @param txt the text to process + * @return the length of the current paragraph in byte count + */ +uint32_t lv_bidi_get_next_paragraph(const char * txt); + /********************** * MACROS **********************/ diff --git a/src/lv_objx/lv_label.c b/src/lv_objx/lv_label.c index 3cac59c02..b7930db70 100644 --- a/src/lv_objx/lv_label.c +++ b/src/lv_objx/lv_label.c @@ -12,6 +12,7 @@ #include "../lv_core/lv_obj.h" #include "../lv_core/lv_debug.h" #include "../lv_core/lv_group.h" +#include "../lv_draw/lv_draw.h" #include "../lv_misc/lv_color.h" #include "../lv_misc/lv_math.h" #include "../lv_misc/lv_bidi.h" @@ -629,6 +630,7 @@ void lv_label_get_letter_pos(const lv_obj_t * label, uint16_t char_id, lv_point_ const char *bidi_txt; uint16_t visual_byte_pos; #if LV_USE_BIDI + char *mutable_bidi_txt = NULL; /*Handle Bidi*/ if(new_line_start == byte_id) { visual_byte_pos = byte_id - line_start; @@ -638,7 +640,6 @@ void lv_label_get_letter_pos(const lv_obj_t * label, uint16_t char_id, lv_point_ uint16_t line_char_id = lv_txt_encoded_get_char_id(&txt[line_start], byte_id - line_start); bool is_rtl; - char *mutable_bidi_txt; uint16_t visual_char_pos = lv_bidi_get_visual_pos(&txt[line_start], &mutable_bidi_txt, new_line_start - line_start, lv_obj_get_base_dir(label), line_char_id, &is_rtl); bidi_txt = mutable_bidi_txt; if (is_rtl) visual_char_pos++; @@ -668,6 +669,10 @@ void lv_label_get_letter_pos(const lv_obj_t * label, uint16_t char_id, lv_point_ } pos->x = x; pos->y = y; + +#if LV_USE_BIDI + if(mutable_bidi_txt) lv_mem_free(mutable_bidi_txt); +#endif } /** @@ -726,7 +731,7 @@ uint16_t lv_label_get_letter_on(const lv_obj_t * label, lv_point_t * pos) } #if LV_USE_BIDI - bidi_txt = lv_draw_get_buf(new_line_start - line_start + 1); + bidi_txt = lv_draw_buf_get(new_line_start - line_start + 1); uint16_t txt_len = new_line_start - line_start; if(bidi_txt[new_line_start] == '\0') txt_len--; lv_bidi_process_paragraph(txt + line_start, bidi_txt, txt_len, lv_obj_get_base_dir(label), NULL, 0); @@ -782,6 +787,7 @@ uint16_t lv_label_get_letter_on(const lv_obj_t * label, lv_point_t * pos) } #if LV_USE_BIDI + lv_draw_buf_release(bidi_txt); /*Handle Bidi*/ bool is_rtl; logical_pos = lv_bidi_get_logical_pos(&txt[line_start], NULL, txt_len, lv_obj_get_base_dir(label), lv_txt_encoded_get_char_id(bidi_txt, i), &is_rtl); @@ -970,6 +976,7 @@ void lv_label_ins_text(lv_obj_t * label, uint32_t pos, const char * txt) #else lv_txt_ins(ext->text, pos, txt); lv_label_refr_text(label); +#endif } /** @@ -1076,12 +1083,7 @@ static lv_design_res_t lv_label_design(lv_obj_t * label, const lv_area_t * clip_ sel.start = lv_label_get_text_sel_start(label); sel.end = lv_label_get_text_sel_end(label); -<<<<<<< HEAD - lv_draw_label(&coords, clip_area, style, opa_scale, ext->text, flag, &ext->offset, &sel, hint); -======= - lv_draw_label(&coords, mask, style, opa_scale, ext->text, flag, &ext->offset, &sel, hint, lv_obj_get_base_dir(label)); - ->>>>>>> dev-6.1 + lv_draw_label(&coords, clip_area, style, opa_scale, ext->text, flag, &ext->offset, &sel, hint, lv_obj_get_base_dir(label)); if(ext->long_mode == LV_LABEL_LONG_SROLL_CIRC) { lv_point_t size; @@ -1096,23 +1098,14 @@ static lv_design_res_t lv_label_design(lv_obj_t * label, const lv_area_t * clip_ lv_font_get_glyph_width(style->text.font, ' ', ' ') * LV_LABEL_WAIT_CHAR_COUNT; ofs.y = ext->offset.y; -<<<<<<< HEAD - lv_draw_label(&coords, clip_area, style, opa_scale, ext->text, flag, &ofs, &sel, NULL); - lv_draw_label(&coords, clip_area, style, opa_scale, ext->text, flag, &ofs, &sel, NULL); -======= - lv_draw_label(&coords, mask, style, opa_scale, ext->text, flag, &ofs, &sel, NULL, lv_obj_get_base_dir(label)); ->>>>>>> dev-6.1 + lv_draw_label(&coords, clip_area, style, opa_scale, ext->text, flag, &ofs, &sel, NULL, lv_obj_get_base_dir(label)); } /*Draw the text again below the original to make an circular effect */ if(size.y > lv_obj_get_height(label)) { ofs.x = ext->offset.x; ofs.y = ext->offset.y + size.y + lv_font_get_line_height(style->text.font); -<<<<<<< HEAD - lv_draw_label(&coords, clip_area, style, opa_scale, ext->text, flag, &ofs, &sel, NULL); -======= - lv_draw_label(&coords, mask, style, opa_scale, ext->text, flag, &ofs, &sel, NULL, lv_obj_get_base_dir(label)); ->>>>>>> dev-6.1 + lv_draw_label(&coords, clip_area, style, opa_scale, ext->text, flag, &ofs, &sel, NULL, lv_obj_get_base_dir(label)); } } } diff --git a/src/lv_objx/lv_table.c b/src/lv_objx/lv_table.c index fc9d32241..b4f60e851 100644 --- a/src/lv_objx/lv_table.c +++ b/src/lv_objx/lv_table.c @@ -151,7 +151,6 @@ void lv_table_set_cell_value(lv_obj_t * table, uint16_t row, uint16_t col, const } /*Initialize the format byte*/ else { -#if LV_USE_BIDI lv_bidi_dir_t base_dir = lv_obj_get_base_dir(table); if(base_dir == LV_BIDI_DIR_LTR) format.s.align = LV_LABEL_ALIGN_LEFT; else if(base_dir == LV_BIDI_DIR_RTL) format.s.align = LV_LABEL_ALIGN_RIGHT;