fix(bidi) fix the handling of LV_BASE_DIR_AUTO in several widgets
fixes #2421
This commit is contained in:
@@ -22,7 +22,7 @@ static void btnm_event_handler(lv_event_t * e)
|
||||
void lv_example_textarea_1(void)
|
||||
{
|
||||
lv_obj_t * ta = lv_textarea_create(lv_scr_act());
|
||||
lv_textarea_set_one_line(ta, true);
|
||||
// lv_textarea_set_one_line(ta, true);
|
||||
lv_obj_align(ta, LV_ALIGN_TOP_MID, 0, 10);
|
||||
lv_obj_add_event_cb(ta, textarea_event_handler, LV_EVENT_READY, ta);
|
||||
lv_obj_add_state(ta, LV_STATE_FOCUSED); /*To be sure the cursor is visible*/
|
||||
@@ -38,6 +38,8 @@ void lv_example_textarea_1(void)
|
||||
lv_obj_add_event_cb(btnm, btnm_event_handler, LV_EVENT_VALUE_CHANGED, ta);
|
||||
lv_obj_clear_flag(btnm, LV_OBJ_FLAG_CLICK_FOCUSABLE); /*To keep the text area focused on button clicks*/
|
||||
lv_btnmatrix_set_map(btnm, btnm_map);
|
||||
|
||||
lv_textarea_set_text(ta, "שלום עולם!");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -206,10 +206,6 @@ void lv_obj_init_draw_label_dsc(lv_obj_t * obj, uint32_t part, lv_draw_label_dsc
|
||||
#endif
|
||||
|
||||
draw_dsc->align = lv_obj_get_style_text_align(obj, part);
|
||||
if(draw_dsc->align == LV_TEXT_ALIGN_AUTO) {
|
||||
if(draw_dsc->bidi_dir == LV_BASE_DIR_RTL) draw_dsc->align = LV_TEXT_ALIGN_RIGHT;
|
||||
else draw_dsc->align = LV_TEXT_ALIGN_LEFT;
|
||||
}
|
||||
}
|
||||
|
||||
void lv_obj_init_draw_img_dsc(lv_obj_t * obj, uint32_t part, lv_draw_img_dsc_t * draw_dsc)
|
||||
|
||||
@@ -457,6 +457,15 @@ lv_part_t lv_obj_style_get_selector_part(lv_style_selector_t selector)
|
||||
return selector & 0xFF0000;
|
||||
}
|
||||
|
||||
|
||||
lv_text_align_t lv_obj_calculate_style_text_align(struct _lv_obj_t * obj, lv_part_t part, const char * txt)
|
||||
{
|
||||
lv_text_align_t align = lv_obj_get_style_text_align(obj, part);
|
||||
lv_base_dir_t base_dir = lv_obj_get_style_base_dir(obj, part);
|
||||
lv_bidi_calculate_align(&align, &base_dir, txt);
|
||||
return align;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
@@ -220,6 +220,8 @@ static inline void lv_obj_set_style_size(struct _lv_obj_t * obj, lv_coord_t val
|
||||
lv_obj_set_style_height(obj, value, selector);
|
||||
}
|
||||
|
||||
lv_text_align_t lv_obj_calculate_style_text_align(struct _lv_obj_t * obj, lv_part_t part, const char * txt);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
@@ -128,6 +128,11 @@ LV_ATTRIBUTE_FAST_MEM void lv_draw_label(const lv_area_t * coords, const lv_area
|
||||
bool clip_ok = _lv_area_intersect(&clipped_area, coords, mask);
|
||||
if(!clip_ok) return;
|
||||
|
||||
lv_text_align_t align = dsc->align;
|
||||
lv_base_dir_t base_dir = dsc->bidi_dir;
|
||||
|
||||
lv_bidi_calculate_align(&align, &base_dir, txt);
|
||||
|
||||
if((dsc->flag & LV_TEXT_FLAG_EXPAND) == 0) {
|
||||
/*Normally use the label's width as width*/
|
||||
w = lv_area_get_width(coords);
|
||||
@@ -193,14 +198,14 @@ LV_ATTRIBUTE_FAST_MEM void lv_draw_label(const lv_area_t * coords, const lv_area
|
||||
}
|
||||
|
||||
/*Align to middle*/
|
||||
if(dsc->align == LV_TEXT_ALIGN_CENTER) {
|
||||
if(align == LV_TEXT_ALIGN_CENTER) {
|
||||
line_width = lv_txt_get_width(&txt[line_start], line_end - line_start, font, dsc->letter_space, dsc->flag);
|
||||
|
||||
pos.x += (lv_area_get_width(coords) - line_width) / 2;
|
||||
|
||||
}
|
||||
/*Align to the right*/
|
||||
else if(dsc->align == LV_TEXT_ALIGN_RIGHT) {
|
||||
else if(align == LV_TEXT_ALIGN_RIGHT) {
|
||||
line_width = lv_txt_get_width(&txt[line_start], line_end - line_start, font, dsc->letter_space, dsc->flag);
|
||||
pos.x += lv_area_get_width(coords) - line_width;
|
||||
}
|
||||
@@ -244,7 +249,7 @@ LV_ATTRIBUTE_FAST_MEM void lv_draw_label(const lv_area_t * coords, const lv_area
|
||||
i = 0;
|
||||
#if LV_USE_BIDI
|
||||
char * bidi_txt = lv_mem_buf_get(line_end - line_start + 1);
|
||||
_lv_bidi_process_paragraph(txt + line_start, bidi_txt, line_end - line_start, dsc->bidi_dir, NULL, 0);
|
||||
_lv_bidi_process_paragraph(txt + line_start, bidi_txt, line_end - line_start, base_dir, NULL, 0);
|
||||
#else
|
||||
const char * bidi_txt = txt + line_start;
|
||||
#endif
|
||||
@@ -255,7 +260,7 @@ LV_ATTRIBUTE_FAST_MEM void lv_draw_label(const lv_area_t * coords, const lv_area
|
||||
#if LV_USE_BIDI
|
||||
logical_char_pos = _lv_txt_encoded_get_char_id(txt, line_start);
|
||||
uint32_t t = _lv_txt_encoded_get_char_id(bidi_txt, i);
|
||||
logical_char_pos += _lv_bidi_get_logical_pos(bidi_txt, NULL, line_end - line_start, dsc->bidi_dir, t, NULL);
|
||||
logical_char_pos += _lv_bidi_get_logical_pos(bidi_txt, NULL, line_end - line_start, base_dir, t, NULL);
|
||||
#else
|
||||
logical_char_pos = _lv_txt_encoded_get_char_id(txt, line_start + i);
|
||||
#endif
|
||||
@@ -359,7 +364,7 @@ LV_ATTRIBUTE_FAST_MEM void lv_draw_label(const lv_area_t * coords, const lv_area
|
||||
|
||||
pos.x = coords->x1;
|
||||
/*Align to middle*/
|
||||
if(dsc->align == LV_TEXT_ALIGN_CENTER) {
|
||||
if(align == LV_TEXT_ALIGN_CENTER) {
|
||||
line_width =
|
||||
lv_txt_get_width(&txt[line_start], line_end - line_start, font, dsc->letter_space, dsc->flag);
|
||||
|
||||
@@ -367,7 +372,7 @@ LV_ATTRIBUTE_FAST_MEM void lv_draw_label(const lv_area_t * coords, const lv_area
|
||||
|
||||
}
|
||||
/*Align to the right*/
|
||||
else if(dsc->align == LV_TEXT_ALIGN_RIGHT) {
|
||||
else if(align == LV_TEXT_ALIGN_RIGHT) {
|
||||
line_width =
|
||||
lv_txt_get_width(&txt[line_start], line_end - line_start, font, dsc->letter_space, dsc->flag);
|
||||
pos.x += lv_area_get_width(coords) - line_width;
|
||||
|
||||
@@ -40,8 +40,8 @@ typedef struct {
|
||||
lv_coord_t ofs_y;
|
||||
lv_opa_t opa;
|
||||
lv_base_dir_t bidi_dir;
|
||||
lv_text_align_t align;
|
||||
lv_text_flag_t flag;
|
||||
lv_text_align_t align :2;
|
||||
lv_text_decor_t decor : 3;
|
||||
lv_blend_mode_t blend_mode: 3;
|
||||
} lv_draw_label_dsc_t;
|
||||
|
||||
@@ -305,6 +305,16 @@ void _lv_bidi_process_paragraph(const char * str_in, char * str_out, uint32_t le
|
||||
}
|
||||
}
|
||||
|
||||
void lv_bidi_calculate_align(lv_text_align_t * align, lv_base_dir_t * base_dir, const char * txt)
|
||||
{
|
||||
if(*base_dir == LV_BASE_DIR_AUTO) *base_dir = _lv_bidi_detect_base_dir(txt);
|
||||
|
||||
if(*align == LV_TEXT_ALIGN_AUTO) {
|
||||
if(*base_dir == LV_BASE_DIR_RTL) *align = LV_TEXT_ALIGN_RIGHT;
|
||||
else *align = LV_TEXT_ALIGN_LEFT;
|
||||
}
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
@@ -17,6 +17,7 @@ extern "C" {
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include "lv_txt.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
@@ -104,10 +105,33 @@ uint16_t _lv_bidi_get_visual_pos(const char * str_in, char ** bidi_txt, uint16_t
|
||||
void _lv_bidi_process_paragraph(const char * str_in, char * str_out, uint32_t len, lv_base_dir_t base_dir,
|
||||
uint16_t * pos_conv_out, uint16_t pos_conv_len);
|
||||
|
||||
/**
|
||||
* Get the real text alignment from the a text alignment, base direction and a text.
|
||||
* @param align LV_TEXT_ALIGN_..., write back the calculated align here (LV_TEXT_ALIGN_LEFT/RIGHT/CENTER)
|
||||
* @param base_dir LV_BASE_DIR_..., write the calculated base dir here (LV_BASE_DIR_LTR/RTL)
|
||||
* @param txt a text, used with LV_BASE_DIR_AUTO to determine the base direction
|
||||
*/
|
||||
void lv_bidi_calculate_align(lv_text_align_t * align, lv_base_dir_t * base_dir, const char * txt);
|
||||
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
#else /*LV_USE_BIDI*/
|
||||
/**
|
||||
* For compatibility if LV_USE_BIDI = 0
|
||||
* Get the real text alignment from the a text alignment, base direction and a text.
|
||||
* @param align For LV_TEXT_ALIGN_AUTO give LV_TEXT_ALIGN_LEFT else leave unchanged, write back the calculated align here
|
||||
* @param base_dir Unused
|
||||
* @param txt Unused
|
||||
*/
|
||||
static inline void lv_bidi_calculate_align(lv_text_align_t * align, lv_base_dir_t * base_dir, const char * txt)
|
||||
{
|
||||
LV_UNUSED(txt);
|
||||
LV_UNUSED(base_dir);
|
||||
if(*align == LV_TEXT_ALIGN_AUTO) * align = LV_TEXT_ALIGN_LEFT;
|
||||
}
|
||||
#endif /*LV_USE_BIDI*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
@@ -492,11 +492,7 @@ void lv_dropdown_open(lv_obj_t * dropdown_obj)
|
||||
}
|
||||
}
|
||||
|
||||
lv_text_align_t align = lv_obj_get_style_text_align(label, LV_PART_MAIN);
|
||||
if(align == LV_TEXT_ALIGN_AUTO) {
|
||||
if(lv_obj_get_style_base_dir(label, LV_PART_MAIN) == LV_BASE_DIR_RTL) align = LV_TEXT_ALIGN_RIGHT;
|
||||
else align = LV_TEXT_ALIGN_LEFT;
|
||||
}
|
||||
lv_text_align_t align = lv_obj_calculate_style_text_align(label, LV_PART_MAIN, dropdown->options);
|
||||
|
||||
switch(align) {
|
||||
default:
|
||||
|
||||
@@ -288,12 +288,9 @@ void lv_label_get_letter_pos(const lv_obj_t * obj, uint32_t char_id, lv_point_t
|
||||
LV_ASSERT_OBJ(obj, MY_CLASS);
|
||||
LV_ASSERT_NULL(pos);
|
||||
|
||||
lv_label_t * label = (lv_label_t *)obj;
|
||||
const char * txt = lv_label_get_text(obj);
|
||||
lv_text_align_t align = lv_obj_get_style_text_align(obj, LV_PART_MAIN);
|
||||
if(align == LV_TEXT_ALIGN_AUTO) {
|
||||
if(lv_obj_get_style_base_dir(obj, LV_PART_MAIN) == LV_BASE_DIR_RTL) align = LV_TEXT_ALIGN_RIGHT;
|
||||
else align = LV_TEXT_ALIGN_LEFT;
|
||||
}
|
||||
lv_text_align_t align = lv_obj_calculate_style_text_align(obj, LV_PART_MAIN, txt);
|
||||
|
||||
if(txt[0] == '\0') {
|
||||
pos->y = 0;
|
||||
@@ -314,7 +311,6 @@ void lv_label_get_letter_pos(const lv_obj_t * obj, uint32_t char_id, lv_point_t
|
||||
lv_area_t txt_coords;
|
||||
lv_obj_get_content_coords(obj, &txt_coords);
|
||||
|
||||
lv_label_t * label = (lv_label_t *)obj;
|
||||
uint32_t line_start = 0;
|
||||
uint32_t new_line_start = 0;
|
||||
lv_coord_t max_w = lv_area_get_width(&txt_coords);
|
||||
@@ -427,11 +423,7 @@ uint32_t lv_label_get_letter_on(const lv_obj_t * obj, lv_point_t * pos_in)
|
||||
if(label->expand != 0) flag |= LV_TEXT_FLAG_EXPAND;
|
||||
if(lv_obj_get_style_width(obj, LV_PART_MAIN) == LV_SIZE_CONTENT && !obj->w_layout) flag |= LV_TEXT_FLAG_FIT;
|
||||
|
||||
lv_text_align_t align = lv_obj_get_style_text_align(obj, LV_PART_MAIN);
|
||||
if(align == LV_TEXT_ALIGN_AUTO) {
|
||||
if(lv_obj_get_style_base_dir(obj, LV_PART_MAIN) == LV_BASE_DIR_RTL) align = LV_TEXT_ALIGN_RIGHT;
|
||||
else align = LV_TEXT_ALIGN_LEFT;
|
||||
}
|
||||
lv_text_align_t align = lv_obj_calculate_style_text_align(obj, LV_PART_MAIN, label->text);
|
||||
|
||||
/*Search the line of the index letter*/;
|
||||
while(txt[line_start] != '\0') {
|
||||
@@ -542,11 +534,7 @@ bool lv_label_is_char_under_pos(const lv_obj_t * obj, lv_point_t * pos)
|
||||
lv_coord_t line_space = lv_obj_get_style_text_line_space(obj, LV_PART_MAIN);
|
||||
lv_coord_t letter_space = lv_obj_get_style_text_letter_space(obj, LV_PART_MAIN);
|
||||
lv_coord_t letter_height = lv_font_get_line_height(font);
|
||||
lv_text_align_t align = lv_obj_get_style_text_align(obj, LV_PART_MAIN);
|
||||
if(align == LV_TEXT_ALIGN_AUTO) {
|
||||
if(lv_obj_get_style_base_dir(obj, LV_PART_MAIN) == LV_BASE_DIR_RTL) align = LV_TEXT_ALIGN_RIGHT;
|
||||
else align = LV_TEXT_ALIGN_LEFT;
|
||||
}
|
||||
lv_text_align_t align = lv_obj_calculate_style_text_align(obj, LV_PART_MAIN, label->text);
|
||||
|
||||
lv_coord_t y = 0;
|
||||
lv_text_flag_t flag = LV_TEXT_FLAG_NONE;
|
||||
@@ -701,7 +689,6 @@ void lv_label_cut_text(lv_obj_t * obj, uint32_t pos, uint32_t cnt)
|
||||
lv_label_refr_text(obj);
|
||||
}
|
||||
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
@@ -809,11 +796,6 @@ static void draw_main(lv_event_t * e)
|
||||
lv_area_t txt_coords;
|
||||
lv_obj_get_content_coords(obj, &txt_coords);
|
||||
|
||||
lv_text_align_t align = lv_obj_get_style_text_align(obj, LV_PART_MAIN);
|
||||
if(align == LV_TEXT_ALIGN_AUTO) {
|
||||
if(lv_obj_get_style_base_dir(obj, LV_PART_MAIN) == LV_BASE_DIR_RTL) align = LV_TEXT_ALIGN_RIGHT;
|
||||
else align = LV_TEXT_ALIGN_LEFT;
|
||||
}
|
||||
lv_text_flag_t flag = LV_TEXT_FLAG_NONE;
|
||||
if(label->recolor != 0) flag |= LV_TEXT_FLAG_RECOLOR;
|
||||
if(label->expand != 0) flag |= LV_TEXT_FLAG_EXPAND;
|
||||
@@ -827,6 +809,7 @@ static void draw_main(lv_event_t * e)
|
||||
|
||||
label_draw_dsc.flag = flag;
|
||||
lv_obj_init_draw_label_dsc(obj, LV_PART_MAIN, &label_draw_dsc);
|
||||
lv_bidi_calculate_align(&label_draw_dsc.align, &label_draw_dsc.bidi_dir, label->text);
|
||||
|
||||
label_draw_dsc.sel_start = lv_label_get_text_selection_start(obj);
|
||||
label_draw_dsc.sel_end = lv_label_get_text_selection_end(obj);
|
||||
@@ -838,7 +821,7 @@ static void draw_main(lv_event_t * e)
|
||||
/* In SROLL and SROLL_CIRC mode the CENTER and RIGHT are pointless so remove them.
|
||||
* (In addition they will result misalignment is this case)*/
|
||||
if((label->long_mode == LV_LABEL_LONG_SCROLL || label->long_mode == LV_LABEL_LONG_SCROLL_CIRCULAR) &&
|
||||
(align == LV_TEXT_ALIGN_CENTER || align == LV_TEXT_ALIGN_RIGHT)) {
|
||||
(label_draw_dsc.align == LV_TEXT_ALIGN_CENTER || label_draw_dsc.align == LV_TEXT_ALIGN_RIGHT)) {
|
||||
lv_point_t size;
|
||||
lv_txt_get_size(&size, label->text, label_draw_dsc.font, label_draw_dsc.letter_space, label_draw_dsc.line_space,
|
||||
LV_COORD_MAX, flag);
|
||||
|
||||
@@ -575,11 +575,7 @@ static void refr_position(lv_obj_t * obj, lv_anim_enable_t anim_en)
|
||||
lv_obj_t * label = get_label(obj);
|
||||
if(label == NULL) return;
|
||||
|
||||
lv_text_align_t align = lv_obj_get_style_text_align(label, LV_PART_MAIN);
|
||||
if(align == LV_TEXT_ALIGN_AUTO) {
|
||||
if(lv_obj_get_style_base_dir(obj, LV_PART_MAIN) == LV_BASE_DIR_RTL) align = LV_TEXT_ALIGN_RIGHT;
|
||||
else align = LV_TEXT_ALIGN_LEFT;
|
||||
}
|
||||
lv_text_align_t align = lv_obj_calculate_style_text_align(label, LV_PART_MAIN, lv_label_get_text(label));
|
||||
|
||||
switch(align) {
|
||||
case LV_TEXT_ALIGN_CENTER:
|
||||
|
||||
@@ -247,6 +247,7 @@ void lv_textarea_del_char(lv_obj_t * obj)
|
||||
|
||||
/*Delete a character*/
|
||||
_lv_txt_cut(label_txt, ta->cursor.pos - 1, 1);
|
||||
|
||||
/*Refresh the label*/
|
||||
lv_label_set_text(ta->label, label_txt);
|
||||
lv_textarea_clear_selection(obj);
|
||||
@@ -1076,11 +1077,7 @@ static void refr_cursor_area(lv_obj_t * obj)
|
||||
lv_point_t letter_pos;
|
||||
lv_label_get_letter_pos(ta->label, cur_pos, &letter_pos);
|
||||
|
||||
lv_text_align_t align = lv_obj_get_style_text_align(ta->label, LV_PART_MAIN);
|
||||
if(align == LV_TEXT_ALIGN_AUTO) {
|
||||
if(lv_obj_get_style_base_dir(obj, LV_PART_MAIN) == LV_BASE_DIR_RTL) align = LV_TEXT_ALIGN_RIGHT;
|
||||
else align = LV_TEXT_ALIGN_LEFT;
|
||||
}
|
||||
lv_text_align_t align = lv_obj_calculate_style_text_align(ta->label, LV_PART_MAIN, lv_label_get_text(ta->label));
|
||||
|
||||
/*If the cursor is out of the text (most right) draw it to the next line*/
|
||||
if(letter_pos.x + ta->label->coords.x1 + letter_w > ta->label->coords.x2 && ta->one_line == 0 && align != LV_TEXT_ALIGN_RIGHT) {
|
||||
|
||||
Reference in New Issue
Block a user