WIP: pos_conv, bugfixes, use in lv_label

This commit is contained in:
Amir Gonnen
2019-11-05 01:03:40 +02:00
parent c7a7d1adca
commit 6f57de051b
3 changed files with 63 additions and 26 deletions

View File

@@ -140,17 +140,28 @@ bool lv_bidi_letter_is_neutral(uint32_t letter)
return false; return false;
} }
uint16_t lv_bidi_get_logical_pos(const char * str_in, uint16_t len, lv_bidi_dir_t base_dir, uint32_t visual_pos) 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)
{ {
return 0; // TODO uint32_t pos_conv_len = get_txt_len(str_in, len);
void *buf = lv_draw_get_buf(len + pos_conv_len * sizeof(uint16_t));
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);
return pos_conv_buf[visual_pos];
} }
uint16_t lv_bidi_get_visual_pos(const char * str_in, uint16_t len, lv_bidi_dir_t base_dir, uint32_t logical_pos) 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)
{ {
uint32_t pos_conv_len = get_txt_len(str_in, len) * sizeof(uint16_t); uint32_t pos_conv_len = get_txt_len(str_in, len);
uint16_t *pos_conv_buf = lv_draw_get_buf(pos_conv_len); void *buf = lv_draw_get_buf(len + pos_conv_len * sizeof(uint16_t));
lv_bidi_process_paragraph(str_in, NULL, len, base_dir, pos_conv_buf, pos_conv_len); if (bidi_txt) *bidi_txt = buf;
return pos_conv_buf[logical_pos]; 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 (pos_conv_buf[i] == logical_pos)
return i;
}
return (uint16_t) -1;
} }
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) 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)
@@ -207,7 +218,7 @@ void lv_bidi_process_paragraph(const char * str_in, char * str_out, uint32_t len
} else { } else {
wr -= rd; wr -= rd;
pos_conv_wr -= pos_conv_rd; pos_conv_wr -= pos_conv_rd;
rtl_reverse(str_out? &str_out[wr]: NULL, str_in, rd, pos_conv_out? &pos_conv_out[pos_conv_rd]: NULL, 0, pos_conv_rd); rtl_reverse(str_out? &str_out[wr]: NULL, str_in, rd, pos_conv_out? &pos_conv_out[pos_conv_wr]: NULL, 0, pos_conv_rd);
} }
} }
@@ -221,7 +232,7 @@ void lv_bidi_process_paragraph(const char * str_in, char * str_out, uint32_t len
if (str_out) memcpy(&str_out[wr], &str_in[rd], run_len); if (str_out) memcpy(&str_out[wr], &str_in[rd], run_len);
if (pos_conv_out) fill_pos_conv(&pos_conv_out[pos_conv_wr], pos_conv_run_len, pos_conv_rd); if (pos_conv_out) fill_pos_conv(&pos_conv_out[pos_conv_wr], pos_conv_run_len, pos_conv_rd);
} }
else rtl_reverse(str_out? &str_out[wr]: NULL, &str_in[rd], run_len, pos_conv_out? &pos_conv_out[pos_conv_rd] : NULL, pos_conv_rd, pos_conv_run_len); else rtl_reverse(str_out? &str_out[wr]: NULL, &str_in[rd], run_len, pos_conv_out? &pos_conv_out[pos_conv_wr] : NULL, pos_conv_rd, pos_conv_run_len);
wr += run_len; wr += run_len;
pos_conv_wr += pos_conv_run_len; pos_conv_wr += pos_conv_run_len;
} else { } else {
@@ -231,7 +242,7 @@ void lv_bidi_process_paragraph(const char * str_in, char * str_out, uint32_t len
if (str_out) memcpy(&str_out[wr], &str_in[rd], run_len); if (str_out) memcpy(&str_out[wr], &str_in[rd], run_len);
if (pos_conv_out) fill_pos_conv(&pos_conv_out[pos_conv_wr], pos_conv_run_len, pos_conv_rd); if (pos_conv_out) fill_pos_conv(&pos_conv_out[pos_conv_wr], pos_conv_run_len, pos_conv_rd);
} }
else rtl_reverse(str_out? &str_out[wr]: NULL, &str_in[rd], run_len, pos_conv_out? &pos_conv_out[pos_conv_rd] : NULL, pos_conv_rd, pos_conv_run_len); else rtl_reverse(str_out? &str_out[wr]: NULL, &str_in[rd], run_len, pos_conv_out? &pos_conv_out[pos_conv_wr] : NULL, pos_conv_rd, pos_conv_run_len);
} }
rd += run_len; rd += run_len;
@@ -411,8 +422,8 @@ static void rtl_reverse(char * dest, const char * src, uint32_t len, uint16_t *p
uint32_t new_letter = letter = char_change_to_pair(letter); uint32_t new_letter = letter = char_change_to_pair(letter);
if (dest) dest[wr] = (uint8_t)new_letter; if (dest) dest[wr] = (uint8_t)new_letter;
if (pos_conv_out) pos_conv_out[pos_conv_wr] = pos_conv_rd_base + pos_conv_letter; if (pos_conv_out) pos_conv_out[pos_conv_wr] = pos_conv_rd_base + pos_conv_letter;
wr += 1; wr++;
pos_conv_wr += 1; pos_conv_wr++;
} }
/*Just store the letter*/ /*Just store the letter*/
else { else {

View File

@@ -60,8 +60,8 @@ lv_bidi_dir_t lv_bidi_get_letter_dir(uint32_t letter);
bool lv_bidi_letter_is_weak(uint32_t letter); bool lv_bidi_letter_is_weak(uint32_t letter);
bool lv_bidi_letter_is_rtl(uint32_t letter); bool lv_bidi_letter_is_rtl(uint32_t letter);
bool lv_bidi_letter_is_neutral(uint32_t letter); bool lv_bidi_letter_is_neutral(uint32_t letter);
uint16_t lv_bidi_get_logical_pos(const char * str_in, uint16_t len, lv_bidi_dir_t base_dir, uint32_t visual_pos); 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);
uint16_t lv_bidi_get_visual_pos(const char * str_in, uint16_t len, lv_bidi_dir_t base_dir, uint32_t logical_pos); 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);
/********************** /**********************
* MACROS * MACROS

View File

@@ -593,6 +593,8 @@ void lv_label_get_letter_pos(const lv_obj_t * label, uint16_t index, lv_point_t
uint8_t letter_height = lv_font_get_line_height(font); uint8_t letter_height = lv_font_get_line_height(font);
lv_coord_t y = 0; lv_coord_t y = 0;
lv_txt_flag_t flag = LV_TXT_FLAG_NONE; lv_txt_flag_t flag = LV_TXT_FLAG_NONE;
uint16_t visual_pos;
char *bidi_txt;
if(ext->recolor != 0) flag |= LV_TXT_FLAG_RECOLOR; if(ext->recolor != 0) flag |= LV_TXT_FLAG_RECOLOR;
if(ext->expand != 0) flag |= LV_TXT_FLAG_EXPAND; if(ext->expand != 0) flag |= LV_TXT_FLAG_EXPAND;
@@ -626,19 +628,27 @@ void lv_label_get_letter_pos(const lv_obj_t * label, uint16_t index, lv_point_t
} }
} }
#if LV_USE_BIDI
/*Handle Bidi*/
visual_pos = lv_bidi_get_visual_pos(&txt[line_start], &bidi_txt, new_line_start - line_start, lv_obj_get_base_dir(label), index - line_start);
#else
visual_pos = index - line_start;
bidi_txt = &txt[line_start];
#endif
/*Calculate the x coordinate*/ /*Calculate the x coordinate*/
lv_coord_t x = lv_txt_get_width(&txt[line_start], index - line_start, font, style->text.letter_space, flag); lv_coord_t x = lv_txt_get_width(bidi_txt, visual_pos, font, style->text.letter_space, flag);
if(index != line_start) x += style->text.letter_space; if(index != line_start) x += style->text.letter_space;
if(align == LV_LABEL_ALIGN_CENTER) { if(align == LV_LABEL_ALIGN_CENTER) {
lv_coord_t line_w; lv_coord_t line_w;
line_w = lv_txt_get_width(&txt[line_start], new_line_start - line_start, font, style->text.letter_space, flag); line_w = lv_txt_get_width(bidi_txt, new_line_start - line_start, font, style->text.letter_space, flag);
x += lv_obj_get_width(label) / 2 - line_w / 2; x += lv_obj_get_width(label) / 2 - line_w / 2;
} else if(align == LV_LABEL_ALIGN_RIGHT) { } else if(align == LV_LABEL_ALIGN_RIGHT) {
lv_coord_t line_w; lv_coord_t line_w;
line_w = lv_txt_get_width(&txt[line_start], new_line_start - line_start, font, style->text.letter_space, flag); line_w = lv_txt_get_width(bidi_txt, new_line_start - line_start, font, style->text.letter_space, flag);
x += lv_obj_get_width(label) - line_w; x += lv_obj_get_width(label) - line_w;
} }
@@ -668,6 +678,8 @@ uint16_t lv_label_get_letter_on(const lv_obj_t * label, lv_point_t * pos)
uint8_t letter_height = lv_font_get_line_height(font); uint8_t letter_height = lv_font_get_line_height(font);
lv_coord_t y = 0; lv_coord_t y = 0;
lv_txt_flag_t flag = LV_TXT_FLAG_NONE; lv_txt_flag_t flag = LV_TXT_FLAG_NONE;
uint16_t logical_pos;
char *bidi_txt;
if(ext->recolor != 0) flag |= LV_TXT_FLAG_RECOLOR; if(ext->recolor != 0) flag |= LV_TXT_FLAG_RECOLOR;
if(ext->expand != 0) flag |= LV_TXT_FLAG_EXPAND; if(ext->expand != 0) flag |= LV_TXT_FLAG_EXPAND;
@@ -691,37 +703,44 @@ uint16_t lv_label_get_letter_on(const lv_obj_t * label, lv_point_t * pos)
line_start = new_line_start; line_start = new_line_start;
} }
#if LV_USE_BIDI
bidi_txt = lv_draw_get_buf(new_line_start - line_start + 1);
lv_bidi_process_paragraph(txt + line_start, bidi_txt, new_line_start - line_start, lv_obj_get_base_dir(label), NULL, 0);
#else
bidi_txt = txt + line_start;
#endif
/*Calculate the x coordinate*/ /*Calculate the x coordinate*/
lv_coord_t x = 0; lv_coord_t x = 0;
if(align == LV_LABEL_ALIGN_CENTER) { if(align == LV_LABEL_ALIGN_CENTER) {
lv_coord_t line_w; lv_coord_t line_w;
line_w = lv_txt_get_width(&txt[line_start], new_line_start - line_start, font, style->text.letter_space, flag); line_w = lv_txt_get_width(bidi_txt, new_line_start - line_start, font, style->text.letter_space, flag);
x += lv_obj_get_width(label) / 2 - line_w / 2; x += lv_obj_get_width(label) / 2 - line_w / 2;
} }
else if(align == LV_LABEL_ALIGN_RIGHT) { else if(align == LV_LABEL_ALIGN_RIGHT) {
lv_coord_t line_w; lv_coord_t line_w;
line_w = lv_txt_get_width(&txt[line_start], new_line_start - line_start, font, style->text.letter_space, flag); line_w = lv_txt_get_width(bidi_txt, new_line_start - line_start, font, style->text.letter_space, flag);
x += lv_obj_get_width(label) - line_w; x += lv_obj_get_width(label) - line_w;
} }
lv_txt_cmd_state_t cmd_state = LV_TXT_CMD_STATE_WAIT; lv_txt_cmd_state_t cmd_state = LV_TXT_CMD_STATE_WAIT;
uint32_t i = line_start; uint32_t i = 0;
uint32_t i_act = i; uint32_t i_act = i;
uint32_t letter; uint32_t letter;
uint32_t letter_next; uint32_t letter_next;
if(new_line_start > 0) { if(new_line_start > 0) {
while(i < new_line_start) { while(i + line_start < new_line_start) {
/* Get the current letter.*/ /* Get the current letter.*/
letter = lv_txt_encoded_next(txt, &i); letter = lv_txt_encoded_next(bidi_txt, &i);
/*Get the next letter too for kerning*/ /*Get the next letter too for kerning*/
letter_next = lv_txt_encoded_next(&txt[i], NULL); letter_next = lv_txt_encoded_next(&bidi_txt[i], NULL);
/*Handle the recolor command*/ /*Handle the recolor command*/
if((flag & LV_TXT_FLAG_RECOLOR) != 0) { if((flag & LV_TXT_FLAG_RECOLOR) != 0) {
if(lv_txt_is_cmd(&cmd_state, txt[i]) != false) { if(lv_txt_is_cmd(&cmd_state, bidi_txt[i]) != false) {
continue; /*Skip the letter is it is part of a command*/ continue; /*Skip the letter is it is part of a command*/
} }
} }
@@ -729,7 +748,7 @@ uint16_t lv_label_get_letter_on(const lv_obj_t * label, lv_point_t * pos)
x += lv_font_get_glyph_width(font, letter, letter_next); x += lv_font_get_glyph_width(font, letter, letter_next);
/*Finish if the x position or the last char of the line is reached*/ /*Finish if the x position or the last char of the line is reached*/
if(pos->x < x || i == new_line_start) { if(pos->x < x || i + line_start == new_line_start) {
i = i_act; i = i_act;
break; break;
} }
@@ -738,7 +757,14 @@ uint16_t lv_label_get_letter_on(const lv_obj_t * label, lv_point_t * pos)
} }
} }
return lv_encoded_get_char_id(txt, i); #if LV_USE_BIDI
/*Handle Bidi*/
logical_pos = lv_bidi_get_logical_pos(&txt[line_start], NULL, new_line_start - line_start, lv_obj_get_base_dir(label), lv_encoded_get_char_id(bidi_txt, i));
#else
logical_pos = lv_encoded_get_char_id(bidi_txt, i);
#endif
return logical_pos;
} }
/** /**