fix conflicts

This commit is contained in:
Gabor Kiss-Vamosi
2019-11-12 06:55:08 +01:00
32 changed files with 2275 additions and 188 deletions

View File

@@ -344,14 +344,27 @@ typedef void * lv_font_user_data_t;
/*Can break (wrap) texts on these 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
/* 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 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
/* 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
/* Support bidirectional texts.
* Allows mixing Left-to-Right and Right-to-Left texts.
* The direction will be processed according to the Unicode Bidirectioanl Algorithm:
* https://www.w3.org/International/articles/inline-bidi-markup/uba-basics*/
#define LV_USE_BIDI 0
#if LV_USE_BIDI
/* Set the default direction. Supported values:
* `LV_BIDI_DIR_LTR` Left-to-Right
* `LV_BIDI_DIR_RTL` Right-to-Left
* `LV_BIDI_DIR_AUTO` detect texts base direction */
#define LV_BIDI_BASE_DIR_DEF LV_BIDI_DIR_AUTO
#endif
/*Change the built in (v)snprintf functions*/
#define LV_SPRINTF_CUSTOM 0

1
lvgl.h
View File

@@ -34,6 +34,7 @@ extern "C" {
#include "src/lv_font/lv_font.h"
#include "src/lv_font/lv_font_fmt_txt.h"
#include "src/lv_misc/lv_bidi.h"
#include "src/lv_objx/lv_btn.h"
#include "src/lv_objx/lv_imgbtn.h"

View File

@@ -473,19 +473,36 @@
#define LV_TXT_BREAK_CHARS " ,.;:-_"
#endif
/* If a character is at least this long, will break wherever "prettiest" */
/* 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 120
#define LV_TXT_LINE_BREAK_LONG_LEN 12
#endif
/* Minimum number of characters of a word to put on a line before a break */
/* 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
#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 */
/* 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
#define LV_TXT_LINE_BREAK_LONG_POST_MIN_LEN 3
#endif
/* Support bidirectional texts.
* Allows mixing Left-to-Right and Right-to-Left texts.
* The direction will be processed according to the Unicode Bidirectioanl Algorithm:
* https://www.w3.org/International/articles/inline-bidi-markup/uba-basics*/
#ifndef LV_USE_BIDI
#define LV_USE_BIDI 0
#endif
#if LV_USE_BIDI
/* Set the default direction. Supported values:
* `LV_BIDI_DIR_LTR` Left-to-Right
* `LV_BIDI_DIR_RTL` Right-to-Left
* `LV_BIDI_DIR_AUTO` detect texts base direction */
#ifndef LV_BIDI_BASE_DIR_DEF
#define LV_BIDI_BASE_DIR_DEF LV_BIDI_DIR_AUTO
#endif
#endif
/*Change the built in (v)snprintf functions*/

View File

@@ -52,6 +52,7 @@ static void refresh_children_position(lv_obj_t * obj, lv_coord_t x_diff, lv_coor
static void report_style_mod_core(void * style_p, lv_obj_t * obj);
static void refresh_children_style(lv_obj_t * obj);
static void delete_children(lv_obj_t * obj);
static void base_dir_refr_children(lv_obj_t * obj);
static void lv_event_mark_deleted(lv_obj_t * obj);
static void lv_obj_del_async_cb(void * obj);
static bool lv_obj_design(lv_obj_t * obj, const lv_area_t * mask_p, lv_design_mode_t mode);
@@ -207,6 +208,16 @@ lv_obj_t * lv_obj_create(lv_obj_t * parent, const lv_obj_t * copy)
new_obj->opa_scale_en = 0;
new_obj->opa_scale = LV_OPA_COVER;
new_obj->parent_event = 0;
#if LV_USE_BIDI
#if LV_BIDI_BASE_DIR_DEF == LV_BIDI_DIR_LTR || LV_BIDI_BASE_DIR_DEF == LV_BIDI_DIR_RTL || LV_BIDI_BASE_DIR_DEF == LV_BIDI_DIR_AUTO
new_obj->base_dir = LV_BIDI_BASE_DIR_DEF;
#else
#error "`LV_BIDI_BASE_DIR_DEF` should be `LV_BASE_DIR_LTR` or `LV_BASE_DIR_RTL` (See lv_conf.h)"
#endif
#else
new_obj->base_dir = LV_BIDI_DIR_LTR;
#endif
new_obj->reserved = 0;
new_obj->ext_attr = NULL;
@@ -225,11 +236,22 @@ lv_obj_t * lv_obj_create(lv_obj_t * parent, const lv_obj_t * copy)
new_obj->par = parent; /*Set the parent*/
lv_ll_init(&(new_obj->child_ll), sizeof(lv_obj_t));
#if LV_USE_BIDI
new_obj->base_dir = LV_BIDI_DIR_INHERIT;
#else
new_obj->base_dir = LV_BIDI_DIR_LTR;
#endif
/*Set coordinates left top corner of parent*/
new_obj->coords.x1 = parent->coords.x1;
new_obj->coords.y1 = parent->coords.y1;
new_obj->coords.x2 = parent->coords.x1 + LV_OBJ_DEF_WIDTH;
new_obj->coords.y2 = parent->coords.y1 + LV_OBJ_DEF_HEIGHT;
if(lv_obj_get_base_dir(new_obj) == LV_BIDI_DIR_RTL) {
new_obj->coords.x2 = parent->coords.x2;
new_obj->coords.x1 = parent->coords.x2 - LV_OBJ_DEF_WIDTH;
} else {
new_obj->coords.x1 = parent->coords.x1;
new_obj->coords.x2 = parent->coords.x1 + LV_OBJ_DEF_WIDTH;
}
new_obj->ext_draw_pad = 0;
#if LV_USE_EXT_CLICK_AREA == LV_EXT_CLICK_AREA_FULL
@@ -292,6 +314,7 @@ lv_obj_t * lv_obj_create(lv_obj_t * parent, const lv_obj_t * copy)
new_obj->opa_scale = LV_OPA_COVER;
new_obj->opa_scale_en = 0;
new_obj->parent_event = 0;
new_obj->reserved = 0;
new_obj->ext_attr = NULL;
}
@@ -725,8 +748,12 @@ void lv_obj_set_size(lv_obj_t * obj, lv_coord_t w, lv_coord_t h)
lv_obj_get_coords(obj, &ori);
/*Set the length and height*/
obj->coords.x2 = obj->coords.x1 + w - 1;
obj->coords.y2 = obj->coords.y1 + h - 1;
if(lv_obj_get_base_dir(obj) == LV_BIDI_DIR_RTL) {
obj->coords.x1 = obj->coords.x2 - w + 1;
} else {
obj->coords.x2 = obj->coords.x1 + w - 1;
}
/*Send a signal to the object with its new coordinates*/
obj->signal_cb(obj, LV_SIGNAL_CORD_CHG, &ori);
@@ -1321,6 +1348,23 @@ void lv_obj_set_parent_event(lv_obj_t * obj, bool en)
obj->parent_event = (en == true ? 1 : 0);
}
void lv_obj_set_base_dir(lv_obj_t * obj, lv_bidi_dir_t dir)
{
if(dir != LV_BIDI_DIR_LTR && dir != LV_BIDI_DIR_RTL &&
dir != LV_BIDI_DIR_AUTO && dir != LV_BIDI_DIR_INHERIT) {
LV_LOG_WARN("lv_obj_set_base_dir: invalid base dir");
return;
}
obj->base_dir = dir;
lv_signal_send(obj, LV_SIGNAL_BASE_DIR_CHG, NULL);
/* Notify the children about the parent base dir has changed.
* (The children might have `LV_BIDI_DIR_INHERIT`)*/
base_dir_refr_children(obj);
}
/**
* Set the opa scale enable parameter (required to set opa_scale with `lv_obj_set_opa_scale()`)
* @param obj pointer to an object
@@ -1742,8 +1786,11 @@ lv_coord_t lv_obj_get_x(const lv_obj_t * obj)
lv_coord_t rel_x;
lv_obj_t * parent = lv_obj_get_parent(obj);
rel_x = obj->coords.x1 - parent->coords.x1;
if(parent) {
rel_x = obj->coords.x1 - parent->coords.x1;
} else {
rel_x = obj->coords.x1;
}
return rel_x;
}
@@ -1758,8 +1805,11 @@ lv_coord_t lv_obj_get_y(const lv_obj_t * obj)
lv_coord_t rel_y;
lv_obj_t * parent = lv_obj_get_parent(obj);
rel_y = obj->coords.y1 - parent->coords.y1;
if(parent) {
rel_y = obj->coords.y1 - parent->coords.y1;
} else {
rel_y = obj->coords.y1;
}
return rel_y;
}
@@ -2068,6 +2118,25 @@ bool lv_obj_get_parent_event(const lv_obj_t * obj)
return obj->parent_event == 0 ? false : true;
}
lv_bidi_dir_t lv_obj_get_base_dir(const lv_obj_t * obj)
{
#if LV_USE_BIDI
const lv_obj_t * parent = obj;
while(parent) {
if(parent->base_dir != LV_BIDI_DIR_INHERIT) return parent->base_dir;
parent = lv_obj_get_parent(parent);
}
return LV_BIDI_BASE_DIR_DEF;
#else
return LV_BIDI_DIR_LTR;
#endif
}
/**
* Get the opa scale enable parameter
* @param obj pointer to an object
@@ -2512,6 +2581,22 @@ static void delete_children(lv_obj_t * obj)
lv_mem_free(obj); /*Free the object itself*/
}
static void base_dir_refr_children(lv_obj_t * obj)
{
lv_obj_t * child;
child = lv_obj_get_child(obj, NULL);
while(child) {
if(child->base_dir == LV_BIDI_DIR_INHERIT) {
lv_signal_send(child, LV_SIGNAL_BASE_DIR_CHG, NULL);
base_dir_refr_children(child);
}
child = lv_obj_get_child(obj, child);
}
}
static void lv_event_mark_deleted(lv_obj_t * obj)
{
lv_event_temp_data_t * t = event_temp_data_head;

View File

@@ -28,6 +28,7 @@ extern "C" {
#include "../lv_misc/lv_ll.h"
#include "../lv_misc/lv_color.h"
#include "../lv_misc/lv_log.h"
#include "../lv_misc/lv_bidi.h"
#include "../lv_hal/lv_hal.h"
/*********************
@@ -111,7 +112,8 @@ enum {
LV_SIGNAL_CHILD_CHG, /**< Child was removed/added */
LV_SIGNAL_CORD_CHG, /**< Object coordinates/size have changed */
LV_SIGNAL_PARENT_SIZE_CHG, /**< Parent's size has changed */
LV_SIGNAL_STYLE_CHG, /**< Object's style has changed */
LV_SIGNAL_STYLE_CHG, /**< Object's style has changed */
LV_SIGNAL_BASE_DIR_CHG, /**<The base dir has changed*/
LV_SIGNAL_REFR_EXT_DRAW_PAD, /**< Object's extra padding has changed */
LV_SIGNAL_GET_TYPE, /**< LittlevGL needs to retrieve the object's type */
@@ -123,7 +125,8 @@ enum {
LV_SIGNAL_LONG_PRESS, /**< Object has been pressed for at least `LV_INDEV_LONG_PRESS_TIME`. Not called if dragged.*/
LV_SIGNAL_LONG_PRESS_REP, /**< Called after `LV_INDEV_LONG_PRESS_TIME` in every `LV_INDEV_LONG_PRESS_REP_TIME` ms. Not called if dragged.*/
LV_SIGNAL_DRAG_BEGIN,
LV_SIGNAL_DRAG_END,
LV_SIGNAL_DRAG_END,
/*Group related*/
LV_SIGNAL_FOCUS,
LV_SIGNAL_DEFOCUS,
@@ -218,7 +221,8 @@ typedef struct _lv_obj_t
uint8_t opa_scale_en : 1; /**< 1: opa_scale is set*/
uint8_t parent_event : 1; /**< 1: Send the object's events to the parent too. */
lv_drag_dir_t drag_dir : 2; /**< Which directions the object can be dragged in */
uint8_t reserved : 6; /**< Reserved for future use*/
lv_bidi_dir_t base_dir : 2; /**< Base direction of texts related to this object */
uint8_t reserved : 3; /**< Reserved for future use*/
uint8_t protect; /**< Automatically happening actions can be prevented. 'OR'ed values from
`lv_protect_t`*/
lv_opa_t opa_scale; /**< Scale down the opacity by this factor. Effects all children as well*/
@@ -510,6 +514,7 @@ void lv_obj_set_drag_parent(lv_obj_t * obj, bool en);
*/
void lv_obj_set_parent_event(lv_obj_t * obj, bool en);
void lv_obj_set_base_dir(lv_obj_t * obj, lv_bidi_dir_t dir);
/**
* Set the opa scale enable parameter (required to set opa_scale with `lv_obj_set_opa_scale()`)
* @param obj pointer to an object
@@ -849,6 +854,9 @@ bool lv_obj_get_drag_parent(const lv_obj_t * obj);
*/
bool lv_obj_get_parent_event(const lv_obj_t * obj);
lv_bidi_dir_t lv_obj_get_base_dir(const lv_obj_t * obj);
/**
* Get the opa scale enable parameter
* @param obj pointer to an object

View File

@@ -90,11 +90,11 @@ void lv_style_init(void)
lv_style_scr.body.shadow.color = LV_COLOR_GRAY;
lv_style_scr.body.shadow.type = LV_SHADOW_FULL;
lv_style_scr.body.shadow.width = 0;
LV_FONT_DECLARE(lv_font_heb_16);
lv_style_scr.text.opa = LV_OPA_COVER;
lv_style_scr.text.color = lv_color_make(0x30, 0x30, 0x30);
lv_style_scr.text.sel_color = lv_color_make(0x55, 0x96, 0xd8);
lv_style_scr.text.font = LV_FONT_DEFAULT;
lv_style_scr.text.font = &lv_font_heb_16;//LV_FONT_DEFAULT;
lv_style_scr.text.letter_space = 0;
lv_style_scr.text.line_space = 2;

View File

@@ -51,7 +51,7 @@ void lv_draw_img(const lv_area_t * coords, const lv_area_t * mask, const void *
if(src == NULL) {
LV_LOG_WARN("Image draw: src is NULL");
lv_draw_rect(coords, mask, &lv_style_plain, LV_OPA_COVER);
lv_draw_label(coords, mask, &lv_style_plain, LV_OPA_COVER, "No\ndata", LV_TXT_FLAG_NONE, NULL, NULL, NULL);
lv_draw_label(coords, mask, &lv_style_plain, LV_OPA_COVER, "No\ndata", LV_TXT_FLAG_NONE, NULL, NULL, NULL, LV_BIDI_DIR_LTR);
return;
}
@@ -61,7 +61,7 @@ void lv_draw_img(const lv_area_t * coords, const lv_area_t * mask, const void *
if(res == LV_RES_INV) {
LV_LOG_WARN("Image draw error");
lv_draw_rect(coords, mask, &lv_style_plain, LV_OPA_COVER);
lv_draw_label(coords, mask, &lv_style_plain, LV_OPA_COVER, "No\ndata", LV_TXT_FLAG_NONE, NULL, NULL, NULL);
lv_draw_label(coords, mask, &lv_style_plain, LV_OPA_COVER, "No\ndata", LV_TXT_FLAG_NONE, NULL, NULL, NULL, LV_BIDI_DIR_LTR);
return;
}
}
@@ -562,7 +562,7 @@ static lv_res_t lv_img_draw_core(const lv_area_t * coords, const lv_area_t * mas
if(cdsc->dec_dsc.error_msg != NULL) {
LV_LOG_WARN("Image draw error");
lv_draw_rect(coords, mask, &lv_style_plain, LV_OPA_COVER);
lv_draw_label(coords, mask, &lv_style_plain, LV_OPA_COVER, cdsc->dec_dsc.error_msg, LV_TXT_FLAG_NONE, NULL, NULL, NULL);
lv_draw_label(coords, mask, &lv_style_plain, LV_OPA_COVER, cdsc->dec_dsc.error_msg, LV_TXT_FLAG_NONE, NULL, NULL, NULL, LV_BIDI_DIR_LTR);
}
/* The decoder open could open the image and gave the entire uncompressed image.
* Just draw it!*/

View File

@@ -8,6 +8,7 @@
*********************/
#include "lv_draw_label.h"
#include "../lv_misc/lv_math.h"
#include "../lv_misc/lv_bidi.h"
/*********************
* DEFINES
@@ -55,16 +56,13 @@ static uint8_t hex_char_to_num(char hex);
*/
void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_style_t * style, lv_opa_t opa_scale,
const char * txt, lv_txt_flag_t flag, lv_point_t * offset, lv_draw_label_txt_sel_t * sel,
lv_draw_label_hint_t * hint)
lv_draw_label_hint_t * hint, lv_bidi_dir_t bidi_dir)
{
const lv_font_t * font = style->text.font;
lv_coord_t w;
/*No need to waste processor time if string is empty*/
if (txt[0] == '\0')
{
return;
}
if (txt[0] == '\0') return;
if((flag & LV_TXT_FLAG_EXPAND) == 0) {
/*Normally use the label's width as width*/
@@ -73,7 +71,7 @@ void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_st
/*If EXAPND is enabled then not limit the text's width to the object's width*/
lv_point_t p;
lv_txt_get_size(&p, txt, style->text.font, style->text.letter_space, style->text.line_space, LV_COORD_MAX,
flag);
flag);
w = p.x;
}
@@ -111,6 +109,7 @@ void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_st
pos.y += hint->y;
}
uint32_t line_end = line_start + lv_txt_get_next_line(&txt[line_start], font, style->text.letter_space, w, flag);
/*Go the first visible line*/
@@ -145,6 +144,18 @@ void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_st
lv_opa_t opa = opa_scale == LV_OPA_COVER ? style->text.opa : (uint16_t)((uint16_t)style->text.opa * opa_scale) >> 8;
uint16_t sel_start = 0xFFFF;
uint16_t sel_end = 0xFFFF;
if(sel) {
sel_start = sel->start;
sel_end = sel->end;
if(sel_start > sel_end) {
uint16_t tmp = sel_start;
sel_start = sel_end;
sel_end = tmp;
}
}
cmd_state_t cmd_state = CMD_STATE_WAIT;
uint32_t i;
uint16_t par_start = 0;
@@ -161,12 +172,31 @@ void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_st
}
/*Write all letter of a line*/
cmd_state = CMD_STATE_WAIT;
i = line_start;
i = 0;
uint32_t letter;
uint32_t letter_next;
while(i < line_end) {
letter = lv_txt_encoded_next(txt, &i);
letter_next = lv_txt_encoded_next(&txt[i], NULL);
#if LV_USE_BIDI
char *bidi_txt = lv_draw_get_buf(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;
#endif
while(i < line_end - line_start) {
uint16_t logical_char_pos = 0;
if(sel_start != 0xFFFF && sel_end != 0xFFFF) {
#if LV_USE_BIDI
logical_char_pos = lv_txt_encoded_get_char_id(txt, line_start);
uint16_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, bidi_dir, t, NULL);
#else
logical_char_pos = lv_txt_encoded_get_char_id(txt, line_start + i);
#endif
}
letter = lv_txt_encoded_next(bidi_txt, &i);
letter_next = lv_txt_encoded_next(&bidi_txt[i], NULL);
/*Handle the re-color command*/
if((flag & LV_TXT_FLAG_RECOLOR) != 0) {
@@ -189,7 +219,7 @@ void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_st
/*Get the parameter*/
if(i - par_start == LABEL_RECOLOR_PAR_LENGTH + 1) {
char buf[LABEL_RECOLOR_PAR_LENGTH + 1];
memcpy(buf, &txt[par_start], LABEL_RECOLOR_PAR_LENGTH);
memcpy(buf, &bidi_txt[par_start], LABEL_RECOLOR_PAR_LENGTH);
buf[LABEL_RECOLOR_PAR_LENGTH] = '\0';
int r, g, b;
r = (hex_char_to_num(buf[0]) << 4) + hex_char_to_num(buf[1]);
@@ -211,18 +241,14 @@ void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_st
letter_w = lv_font_get_glyph_width(font, letter, letter_next);
if(sel) {
if(sel->start != 0xFFFF && sel->end != 0xFFFF) {
int char_ind = lv_encoded_get_char_id(txt, i);
/*Do not draw the rectangle on the character at `sel_start`.*/
if(char_ind > sel->start && char_ind <= sel->end) {
lv_area_t sel_coords;
sel_coords.x1 = pos.x;
sel_coords.y1 = pos.y;
sel_coords.x2 = pos.x + letter_w + style->text.letter_space - 1;
sel_coords.y2 = pos.y + line_height - 1;
lv_draw_rect(&sel_coords, mask, &sel_style, opa);
}
if(sel_start != 0xFFFF && sel_end != 0xFFFF) {
if(logical_char_pos >= sel_start && logical_char_pos < sel_end) {
lv_area_t sel_coords;
sel_coords.x1 = pos.x;
sel_coords.y1 = pos.y;
sel_coords.x2 = pos.x + letter_w + style->text.letter_space - 1;
sel_coords.y2 = pos.y + line_height - 1;
lv_draw_rect(&sel_coords, mask, &sel_style, opa);
}
}
@@ -240,7 +266,7 @@ void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_st
/*Align to middle*/
if(flag & LV_TXT_FLAG_CENTER) {
line_width =
lv_txt_get_width(&txt[line_start], line_end - line_start, font, style->text.letter_space, flag);
lv_txt_get_width(&txt[line_start], line_end - line_start, font, style->text.letter_space, flag);
pos.x += (lv_area_get_width(coords) - line_width) / 2;
@@ -248,7 +274,7 @@ void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_st
/*Align to the right*/
else if(flag & LV_TXT_FLAG_RIGHT) {
line_width =
lv_txt_get_width(&txt[line_start], line_end - line_start, font, style->text.letter_space, flag);
lv_txt_get_width(&txt[line_start], line_end - line_start, font, style->text.letter_space, flag);
pos.x += lv_area_get_width(coords) - line_width;
}
@@ -278,13 +304,13 @@ static uint8_t hex_char_to_num(char hex)
if(hex >= 'a') hex -= 'a' - 'A'; /*Convert to upper case*/
switch(hex) {
case 'A': result = 10; break;
case 'B': result = 11; break;
case 'C': result = 12; break;
case 'D': result = 13; break;
case 'E': result = 14; break;
case 'F': result = 15; break;
default: result = 0; break;
case 'A': result = 10; break;
case 'B': result = 11; break;
case 'C': result = 12; break;
case 'D': result = 13; break;
case 'E': result = 14; break;
case 'F': result = 15; break;
default: result = 0; break;
}
}

View File

@@ -14,6 +14,7 @@ extern "C" {
* INCLUDES
*********************/
#include "lv_draw.h"
#include "../lv_misc/lv_bidi.h"
/*********************
* DEFINES
@@ -62,10 +63,11 @@ typedef struct {
* @param flag settings for the text from 'txt_flag_t' enum
* @param offset text offset in x and y direction (NULL if unused)
* @param sel_start start index of selected area (`LV_LABEL_TXT_SEL_OFF` if none)
* @param bidi_dir base direction of the text
*/
void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_style_t * style, lv_opa_t opa_scale,
const char * txt, lv_txt_flag_t flag, lv_point_t * offset, lv_draw_label_txt_sel_t * sel,
lv_draw_label_hint_t * hint);
lv_draw_label_hint_t * hint, lv_bidi_dir_t bidi_dir);
/**********************
* MACROS

1133
src/lv_font/lv_font_heb_16.c Normal file

File diff suppressed because it is too large Load Diff

540
src/lv_misc/lv_bidi.c Normal file
View File

@@ -0,0 +1,540 @@
/**
* @file lv_bidi.c
*
*/
/*********************
* INCLUDES
*********************/
#include <stddef.h>
#include "lv_bidi.h"
#include "lv_txt.h"
#include "../lv_draw/lv_draw.h"
#if LV_USE_BIDI
/*********************
* DEFINES
*********************/
#define LV_BIDI_BRACKLET_DEPTH 4
// Highest bit of the 16-bit pos_conv value specifies whether this pos is RTL or not
#define GET_POS(x) ((x) & 0x7FFF)
#define IS_RTL_POS(x) (((x) & 0x8000) != 0)
#define SET_RTL_POS(x, is_rtl) (GET_POS(x) | ((is_rtl)? 0x8000: 0))
/**********************
* TYPEDEFS
**********************/
typedef struct
{
uint32_t bracklet_pos;
lv_bidi_dir_t dir;
}bracket_stack_t;
/**********************
* STATIC PROTOTYPES
**********************/
static lv_bidi_dir_t get_next_run(const char * txt, lv_bidi_dir_t base_dir, uint32_t max_len, uint32_t * len, uint16_t * pos_conv_len);
static void rtl_reverse(char * dest, const char * src, uint32_t len, uint16_t *pos_conv_out, uint16_t pos_conv_rd_base, uint16_t pos_conv_len);
static uint32_t char_change_to_pair(uint32_t letter);
static lv_bidi_dir_t bracket_process(const char * txt, uint32_t next_pos, uint32_t len, uint32_t letter, lv_bidi_dir_t base_dir);
static void fill_pos_conv(uint16_t * out, uint16_t len, uint16_t index);
static uint32_t get_txt_len(const char * txt, uint32_t max_len);
/**********************
* STATIC VARIABLES
**********************/
static const uint8_t bracket_left[] = {"<({["};
static const uint8_t bracket_right[] = {">)}]"};
static bracket_stack_t br_stack[LV_BIDI_BRACKLET_DEPTH];
static uint8_t br_stack_p;
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
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);
uint32_t par_start = 0;
uint32_t par_len;
while(str_in[par_start] == '\n' || str_in[par_start] == '\r') {
str_out[par_start] = str_in[par_start];
par_start ++;
}
while(str_in[par_start] != '\0') {
par_len = lv_bidi_get_next_paragraph(&str_in[par_start]);
lv_bidi_process_paragraph(&str_in[par_start], &str_out[par_start], par_len, base_dir, NULL, 0);
par_start += par_len;
while(str_in[par_start] == '\n' || str_in[par_start] == '\r') {
str_out[par_start] = str_in[par_start];
par_start ++;
}
}
str_out[par_start] = '\0';
}
lv_bidi_dir_t lv_bidi_detect_base_dir(const char * txt)
{
uint32_t i = 0;
uint32_t letter;
while(txt[i] != '\0') {
letter = lv_txt_encoded_next(txt, &i);
lv_bidi_dir_t dir;
dir = lv_bidi_get_letter_dir(letter);
if(dir == LV_BIDI_DIR_RTL || dir == LV_BIDI_DIR_LTR) return dir;
}
/*If there were no strong char earlier return with the default base dir */
if(LV_BIDI_BASE_DIR_DEF == LV_BIDI_DIR_AUTO) return LV_BIDI_DIR_LTR;
else return LV_BIDI_BASE_DIR_DEF;
}
lv_bidi_dir_t lv_bidi_get_letter_dir(uint32_t letter)
{
if(lv_bidi_letter_is_rtl(letter)) return LV_BIDI_DIR_RTL;
if(lv_bidi_letter_is_neutral(letter)) return LV_BIDI_DIR_NEUTRAL;
if(lv_bidi_letter_is_weak(letter)) return LV_BIDI_DIR_WEAK;
return LV_BIDI_DIR_LTR;
}
bool lv_bidi_letter_is_weak(uint32_t letter)
{
uint32_t i = 0;
static const char weaks[] = "0123456789";
do {
uint32_t x = lv_txt_encoded_next(weaks, &i);
if(letter == x) {
return true;
}
} while(weaks[i] != '\0');
return 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;
}
bool lv_bidi_letter_is_neutral(uint32_t letter)
{
uint16_t i;
static const char neutrals[] = " \t\n\r.,:;'\"`!?%/\\-=()[]{}<>@#&$|";
for(i = 0; neutrals[i] != '\0'; i++) {
if(letter == (uint32_t)neutrals[i]) return true;
}
return false;
}
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));
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]);
return GET_POS(pos_conv_buf[visual_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, 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));
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]);
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)
{
uint32_t run_len = 0;
lv_bidi_dir_t run_dir;
uint32_t rd = 0;
uint32_t wr;
uint16_t pos_conv_run_len = 0;
uint16_t pos_conv_rd = 0;
uint16_t pos_conv_wr;
if(base_dir == LV_BIDI_DIR_AUTO) base_dir = lv_bidi_detect_base_dir(str_in);
if(base_dir == LV_BIDI_DIR_RTL) {
wr = len;
pos_conv_wr = pos_conv_len;
}
else {
wr = 0;
pos_conv_wr = 0;
}
if (str_out) str_out[len] = '\0';
lv_bidi_dir_t dir = base_dir;
/*Empty the bracket stack*/
br_stack_p = 0;
/*Process neutral chars in the beginning*/
while(rd < len) {
uint32_t letter = lv_txt_encoded_next(str_in, &rd);
pos_conv_rd++;
dir = lv_bidi_get_letter_dir(letter);
if(dir == LV_BIDI_DIR_NEUTRAL) dir = bracket_process(str_in, rd, len, letter, base_dir);
if(dir != LV_BIDI_DIR_NEUTRAL && dir != LV_BIDI_DIR_WEAK) break;
}
if(rd && str_in[rd] != '\0') {
lv_txt_encoded_prev(str_in, &rd);
pos_conv_rd--;
}
if(rd) {
if(base_dir == LV_BIDI_DIR_LTR) {
if (str_out) {
memcpy(&str_out[wr], str_in, rd);
wr += rd;
}
if (pos_conv_out) {
fill_pos_conv(&pos_conv_out[pos_conv_wr], pos_conv_rd, 0);
pos_conv_wr += pos_conv_rd;
}
} else {
wr -= 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_wr]: NULL, 0, pos_conv_rd);
}
}
/*Get and process the runs*/
while(rd < len && str_in[rd]) {
run_dir = get_next_run(&str_in[rd], base_dir, len - rd, &run_len, &pos_conv_run_len);
if(base_dir == LV_BIDI_DIR_LTR) {
if(run_dir == LV_BIDI_DIR_LTR) {
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);
}
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;
pos_conv_wr += pos_conv_run_len;
} else {
wr -= run_len;
pos_conv_wr -= pos_conv_run_len;
if(run_dir == LV_BIDI_DIR_LTR) {
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);
}
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;
pos_conv_rd += pos_conv_run_len;
}
}
uint32_t lv_bidi_get_next_paragraph(const char * txt)
{
uint32_t i = 0;
lv_txt_encoded_next(txt, &i);
while(txt[i] != '\0' && txt[i] != '\n' && txt[i] != '\r') {
lv_txt_encoded_next(txt, &i);
}
return i;
}
/**********************
* STATIC FUNCTIONS
**********************/
static uint32_t get_txt_len(const char * txt, uint32_t max_len)
{
uint32_t len = 0;
uint32_t i = 0;
while(i < max_len && txt[i] != '\0') {
lv_txt_encoded_next(txt, &i);
len++;
}
return len;
}
static void fill_pos_conv(uint16_t * out, uint16_t len, uint16_t index)
{
for (uint16_t i = 0; i < len; i++)
{
out[i] = SET_RTL_POS(index, false);
index++;
}
}
static lv_bidi_dir_t get_next_run(const char * txt, lv_bidi_dir_t base_dir, uint32_t max_len, uint32_t * len, uint16_t * pos_conv_len)
{
uint32_t i = 0;
uint32_t letter;
uint16_t pos_conv_i = 0;
letter = lv_txt_encoded_next(txt, NULL);
lv_bidi_dir_t dir = lv_bidi_get_letter_dir(letter);
if(dir == LV_BIDI_DIR_NEUTRAL) dir = bracket_process(txt, 0, max_len, letter, base_dir);
/*Find the first strong char. Skip the neutrals*/
while(dir == LV_BIDI_DIR_NEUTRAL || dir == LV_BIDI_DIR_WEAK) {
letter = lv_txt_encoded_next(txt, &i);
pos_conv_i++;
dir = lv_bidi_get_letter_dir(letter);
if(dir == LV_BIDI_DIR_NEUTRAL) dir = bracket_process(txt, i, max_len, letter, base_dir);
if(i >= max_len || txt[i] == '\0' || txt[i] == '\n' || txt[i] == '\r') {
*len = i;
*pos_conv_len = pos_conv_i;
return base_dir;
}
}
lv_bidi_dir_t run_dir = dir;
uint32_t i_prev = i;
uint32_t i_last_strong = i;
uint16_t pos_conv_i_prev = pos_conv_i;
uint16_t pos_conv_i_last_strong = pos_conv_i;
/*Find the next char which has different direction*/
lv_bidi_dir_t next_dir = base_dir;
while(i_prev < max_len && txt[i] != '\0' && txt[i] != '\n' && txt[i] != '\r') {
letter = lv_txt_encoded_next(txt, &i);
pos_conv_i++;
next_dir = lv_bidi_get_letter_dir(letter);
if(next_dir == LV_BIDI_DIR_NEUTRAL) next_dir = bracket_process(txt, i, max_len, letter, base_dir);
/*New dir found?*/
if((next_dir == LV_BIDI_DIR_RTL || next_dir == LV_BIDI_DIR_LTR) && next_dir != run_dir) {
/*Include neutrals if `run_dir == base_dir` */
if(run_dir == base_dir) {
*len = i_prev;
*pos_conv_len = pos_conv_i_prev;
}
/*Exclude neutrals if `run_dir != base_dir` */
else {
*len = i_last_strong;
*pos_conv_len = pos_conv_i_last_strong;
}
return run_dir;
}
if(next_dir != LV_BIDI_DIR_NEUTRAL) {
i_last_strong = i;
pos_conv_i_last_strong = pos_conv_i;
}
i_prev = i;
pos_conv_i_prev = pos_conv_i;
}
/*Handle end of of string. Apply `base_dir` on trailing neutrals*/
/*Include neutrals if `run_dir == base_dir` */
if(run_dir == base_dir) {
*len = i_prev;
*pos_conv_len = pos_conv_i_prev;
}
/*Exclude neutrals if `run_dir != base_dir` */
else {
*len = i_last_strong;
*pos_conv_len = pos_conv_i_last_strong;
}
return run_dir;
}
static void rtl_reverse(char * dest, const char * src, uint32_t len, uint16_t *pos_conv_out, uint16_t pos_conv_rd_base, uint16_t pos_conv_len)
{
uint32_t i = len;
uint32_t wr = 0;
uint16_t pos_conv_i = pos_conv_len;
uint16_t pos_conv_wr = 0;
while(i) {
uint32_t letter = lv_txt_encoded_prev(src, &i);
uint16_t pos_conv_letter = --pos_conv_i;
/*Keep weak letters (numbers) as LTR*/
if(lv_bidi_letter_is_weak(letter)) {
uint32_t last_weak = i;
uint32_t first_weak = i;
uint16_t pos_conv_last_weak = pos_conv_i;
uint16_t pos_conv_first_weak = pos_conv_i;
while(i) {
letter = lv_txt_encoded_prev(src, &i);
pos_conv_letter = --pos_conv_i;
/*No need to call `char_change_to_pair` because there not such chars here*/
/*Finish on non-weak char */
/*but treat number and currency related chars as weak*/
if (lv_bidi_letter_is_weak(letter) == false && letter != '.' && letter != ',' && letter != '$' && letter != '%') {
lv_txt_encoded_next(src, &i); /*Rewind one letter*/
pos_conv_i++;
first_weak = i;
pos_conv_first_weak = pos_conv_i;
break;
}
}
if(i == 0) {
first_weak = 0;
pos_conv_first_weak = 0;
}
if (dest) memcpy(&dest[wr], &src[first_weak], last_weak - first_weak + 1);
if (pos_conv_out) fill_pos_conv(&pos_conv_out[pos_conv_wr], pos_conv_last_weak - pos_conv_first_weak + 1, pos_conv_rd_base + pos_conv_first_weak);
wr += last_weak - first_weak + 1;
pos_conv_wr += pos_conv_last_weak - pos_conv_first_weak + 1;
}
/*Simply store in reversed order*/
else {
uint32_t letter_size = lv_txt_encoded_size((const char *)&src[i]);
/*Swap arithmetical symbols*/
if(letter_size == 1) {
uint32_t new_letter = letter = char_change_to_pair(letter);
if (dest) dest[wr] = (uint8_t)new_letter;
if (pos_conv_out) pos_conv_out[pos_conv_wr] = SET_RTL_POS(pos_conv_rd_base + pos_conv_letter, true);
wr++;
pos_conv_wr++;
}
/*Just store the letter*/
else {
if (dest) memcpy(&dest[wr], &src[i], letter_size);
if (pos_conv_out) pos_conv_out[pos_conv_wr] = SET_RTL_POS(pos_conv_rd_base + pos_conv_i, true);
wr += letter_size;
pos_conv_wr++;
}
}
}
}
static uint32_t char_change_to_pair(uint32_t letter)
{
uint8_t i;
for(i = 0; bracket_left[i] != '\0'; i++) {
if(letter == bracket_left[i]) return bracket_right[i];
}
for(i = 0; bracket_right[i] != '\0'; i++) {
if(letter == bracket_right[i]) return bracket_left[i];
}
return letter;
}
static lv_bidi_dir_t bracket_process(const char * txt, uint32_t next_pos, uint32_t len, uint32_t letter, lv_bidi_dir_t base_dir)
{
lv_bidi_dir_t bracket_dir = LV_BIDI_DIR_NEUTRAL;
uint8_t i;
/*Is the letter an opening bracket?*/
for(i = 0; bracket_left[i] != '\0'; i++) {
if(bracket_left[i] == letter) {
/* If so find it's matching closing bracket.
* If a char with base dir. direction is found then the brackets will have `base_dir` direction*/
uint32_t txt_i = next_pos;
while(txt_i < len) {
uint32_t letter_next = lv_txt_encoded_next(txt, &txt_i);
if(letter_next == bracket_right[i]) {
/*Closing bracket found*/
break;
} else {
/*Save the dir*/
lv_bidi_dir_t letter_dir = lv_bidi_get_letter_dir(letter_next);
if(letter_dir == base_dir) {
bracket_dir = base_dir;
}
}
}
/*There were no matching closing bracket*/
if(txt_i > len) return LV_BIDI_DIR_NEUTRAL;
/*There where a strong char with base dir in the bracket so the dir is found.*/
if(bracket_dir != LV_BIDI_DIR_NEUTRAL && bracket_dir != LV_BIDI_DIR_WEAK) break;
/*If there were no matching strong chars in the brackets then check the previous chars*/
txt_i = next_pos;
if(txt_i) lv_txt_encoded_prev(txt, &txt_i);
while(txt_i > 0) {
uint32_t letter_next = lv_txt_encoded_prev(txt, &txt_i);
lv_bidi_dir_t letter_dir = lv_bidi_get_letter_dir(letter_next);
if(letter_dir == LV_BIDI_DIR_LTR || letter_dir == LV_BIDI_DIR_RTL) {
bracket_dir = letter_dir;
break;
}
}
/*There where a previous strong char which can be used*/
if(bracket_dir != LV_BIDI_DIR_NEUTRAL) break;
/*There were no strong chars before the bracket, so use the base dir.*/
if(txt_i == 0) bracket_dir = base_dir;
break;
}
}
/*The letter was an opening bracket*/
if(bracket_left[i] != '\0') {
if(bracket_dir == LV_BIDI_DIR_NEUTRAL || br_stack_p == LV_BIDI_BRACKLET_DEPTH) return LV_BIDI_DIR_NEUTRAL;
br_stack[br_stack_p].bracklet_pos = i;
br_stack[br_stack_p].dir = bracket_dir;
br_stack_p++;
return bracket_dir;
} else if(br_stack_p > 0) {
/*Is the letter a closing bracket of the last opening?*/
if(letter == bracket_right[br_stack[br_stack_p - 1].bracklet_pos]) {
bracket_dir = br_stack[br_stack_p - 1].dir;
br_stack_p--;
return bracket_dir;
}
}
return LV_BIDI_DIR_NEUTRAL;
}
#endif /*LV_USE_BIDI*/

76
src/lv_misc/lv_bidi.h Normal file
View File

@@ -0,0 +1,76 @@
/**
* @file lv_bifi.h
*
*/
#ifndef LV_BIDI_H
#define LV_BIDI_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#ifdef LV_CONF_INCLUDE_SIMPLE
#include "lv_conf.h"
#else
#include "../../../lv_conf.h"
#endif
#include <stdbool.h>
#include <stdint.h>
/*********************
* DEFINES
*********************/
/* Special non printable strong characters.
* They can be inserted to texts to affect the run's direction*/
#define LV_BIDI_LRO "\xE2\x80\xAD" /*U+202D*/
#define LV_BIDI_RLO "\xE2\x80\xAE" /*U+202E*/
/**********************
* TYPEDEFS
**********************/
enum
{
/*The first 4 values are stored in `lv_obj_t` on 2 bits*/
LV_BIDI_DIR_LTR = 0x00,
LV_BIDI_DIR_RTL = 0x01,
LV_BIDI_DIR_AUTO = 0x02,
LV_BIDI_DIR_INHERIT = 0x03,
LV_BIDI_DIR_NEUTRAL = 0x20,
LV_BIDI_DIR_WEAK = 0x21,
};
typedef uint8_t lv_bidi_dir_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
#if LV_USE_BIDI
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);
lv_bidi_dir_t lv_bidi_detect_base_dir(const char * txt);
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_rtl(uint32_t letter);
bool lv_bidi_letter_is_neutral(uint32_t letter);
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);
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);
/**********************
* MACROS
**********************/
#endif /*LV_USE_BIDI*/
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /*LV_BIDI_H*/

View File

@@ -56,7 +56,7 @@ uint32_t (*lv_txt_encoded_conv_wc)(uint32_t) = lv_txt_utf8_con
uint32_t (*lv_txt_encoded_next)(const char *, uint32_t *) = lv_txt_utf8_next;
uint32_t (*lv_txt_encoded_prev)(const char *, uint32_t *) = lv_txt_utf8_prev;
uint32_t (*lv_txt_encoded_get_byte_id)(const char *, uint32_t) = lv_txt_utf8_get_byte_id;
uint32_t (*lv_encoded_get_char_id)(const char *, uint32_t) = lv_txt_utf8_get_char_id;
uint32_t (*lv_txt_encoded_get_char_id)(const char *, uint32_t) = lv_txt_utf8_get_char_id;
uint32_t (*lv_txt_get_encoded_length)(const char *) = lv_txt_utf8_get_length;
#elif LV_TXT_ENC == LV_TXT_ENC_ASCII
uint8_t (*lv_txt_encoded_size)(const char *) = lv_txt_iso8859_1_size;
@@ -65,7 +65,7 @@ uint32_t (*lv_txt_encoded_conv_wc)(uint32_t) = lv_txt_iso8859_
uint32_t (*lv_txt_encoded_next)(const char *, uint32_t *) = lv_txt_iso8859_1_next;
uint32_t (*lv_txt_encoded_prev)(const char *, uint32_t *) = lv_txt_iso8859_1_prev;
uint32_t (*lv_txt_encoded_get_byte_id)(const char *, uint32_t) = lv_txt_iso8859_1_get_byte_id;
uint32_t (*lv_encoded_get_char_id)(const char *, uint32_t) = lv_txt_iso8859_1_get_char_id;
uint32_t (*lv_txt_encoded_get_char_id)(const char *, uint32_t) = lv_txt_iso8859_1_get_char_id;
uint32_t (*lv_txt_get_encoded_length)(const char *) = lv_txt_iso8859_1_get_length;
#endif
@@ -468,7 +468,7 @@ static uint8_t lv_txt_utf8_size(const char * str)
return 3;
else if((str[0] & 0xF8) == 0xF0)
return 4;
return 1; /*If the char was invalid step tell it's 1 byte long*/
return 0; /*If the char was invalid tell it's 1 byte long*/
}
/**
@@ -645,7 +645,8 @@ static uint32_t lv_txt_utf8_get_byte_id(const char * txt, uint32_t utf8_id)
uint32_t i;
uint32_t byte_cnt = 0;
for(i = 0; i < utf8_id; i++) {
byte_cnt += lv_txt_encoded_size(&txt[byte_cnt]);
uint8_t c_size = lv_txt_encoded_size(&txt[byte_cnt]);
byte_cnt += c_size > 0 ? c_size : 1;
}
return byte_cnt;

View File

@@ -188,7 +188,7 @@ extern uint32_t (*lv_txt_encoded_get_byte_id)(const char *, uint32_t);
* @param byte_id byte index
* @return character index of the letter at 'byte_id'th position
*/
extern uint32_t (*lv_encoded_get_char_id)(const char *, uint32_t);
extern uint32_t (*lv_txt_encoded_get_char_id)(const char *, uint32_t);
/**
* Get the number of characters (and NOT bytes) in a string.

View File

@@ -207,6 +207,8 @@ void lv_btnm_set_map(const lv_obj_t * btnm, const char * map[])
btn_h = lv_obj_get_height(btnm)- act_y - style_bg->body.padding.bottom - 1;
}
lv_bidi_dir_t base_dir = lv_obj_get_base_dir(btnm);
/*Only deal with the non empty lines*/
if(btn_cnt != 0) {
/*Calculate the width of all units*/
@@ -214,7 +216,8 @@ void lv_btnm_set_map(const lv_obj_t * btnm, const char * map[])
/*Set the button size and positions and set the texts*/
uint16_t i;
lv_coord_t act_x = style_bg->body.padding.left;
lv_coord_t act_x;
lv_coord_t act_unit_w;
unit_act_cnt = 0;
for(i = 0; i < btn_cnt; i++) {
@@ -225,9 +228,13 @@ void lv_btnm_set_map(const lv_obj_t * btnm, const char * map[])
act_unit_w--; /*-1 because e.g. width = 100 means 101 pixels (0..100)*/
/*Always recalculate act_x because of rounding errors */
act_x = (unit_act_cnt * all_unit_w) / unit_cnt + i * style_bg->body.padding.inner +
style_bg->body.padding.left;
if(base_dir == LV_BIDI_DIR_RTL) {
act_x = (unit_act_cnt * all_unit_w) / unit_cnt + i * style_bg->body.padding.inner;
act_x = lv_obj_get_width(btnm) - style_bg->body.padding.right - act_x - act_unit_w - 1;
} else {
act_x = (unit_act_cnt * all_unit_w) / unit_cnt + i * style_bg->body.padding.inner +
style_bg->body.padding.left;
}
/* Set the button's area.
* If inner padding is zero then use the prev. button x2 as x1 to avoid rounding
* errors*/
@@ -644,7 +651,6 @@ static bool lv_btnm_design(lv_obj_t * btnm, const lv_area_t * mask, lv_design_mo
}
/*Draw the object*/
else if(mode == LV_DESIGN_DRAW_MAIN) {
ancestor_design_f(btnm, mask, mode);
lv_btnm_ext_t * ext = lv_obj_get_ext_attr(btnm);
@@ -665,7 +671,6 @@ static bool lv_btnm_design(lv_obj_t * btnm, const lv_area_t * mask, lv_design_mo
lv_txt_flag_t txt_flag = LV_TXT_FLAG_NONE;
if(ext->recolor) txt_flag = LV_TXT_FLAG_RECOLOR;
for(btn_i = 0; btn_i < ext->btn_cnt; btn_i++, txt_i++) {
/*Search the next valid text in the map*/
while(strcmp(ext->map_p[txt_i], "\n") == 0) {
@@ -734,9 +739,10 @@ static bool lv_btnm_design(lv_obj_t * btnm, const lv_area_t * mask, lv_design_mo
area_tmp.x2 = area_tmp.x1 + txt_size.x;
area_tmp.y2 = area_tmp.y1 + txt_size.y;
lv_draw_label(&area_tmp, mask, btn_style, opa_scale, ext->map_p[txt_i], txt_flag, NULL, NULL, NULL);
lv_draw_label(&area_tmp, mask, btn_style, opa_scale, ext->map_p[txt_i], txt_flag, NULL, NULL, NULL, lv_obj_get_base_dir(btnm));
}
}
return true;
}

View File

@@ -670,6 +670,9 @@ static lv_coord_t get_day_names_height(lv_obj_t * calendar)
static void draw_header(lv_obj_t * calendar, const lv_area_t * mask)
{
lv_calendar_ext_t * ext = lv_obj_get_ext_attr(calendar);
lv_bidi_dir_t bidi_dir = lv_obj_get_base_dir(calendar);
lv_opa_t opa_scale = lv_obj_get_opa_scale(calendar);
lv_area_t header_area;
@@ -687,19 +690,19 @@ static void draw_header(lv_obj_t * calendar, const lv_area_t * mask)
txt_buf[5] = '\0';
strcpy(&txt_buf[5], get_month_name(calendar, ext->showed_date.month));
header_area.y1 += ext->style_header->body.padding.top;
lv_draw_label(&header_area, mask, ext->style_header, opa_scale, txt_buf, LV_TXT_FLAG_CENTER, NULL, NULL, NULL);
lv_draw_label(&header_area, mask, ext->style_header, opa_scale, txt_buf, LV_TXT_FLAG_CENTER, NULL, NULL, NULL, bidi_dir);
/*Add the left arrow*/
const lv_style_t * arrow_style = ext->btn_pressing < 0 ? ext->style_header_pr : ext->style_header;
header_area.x1 += ext->style_header->body.padding.left;
lv_draw_label(&header_area, mask, arrow_style, opa_scale, LV_SYMBOL_LEFT, LV_TXT_FLAG_NONE, NULL, NULL, NULL);
lv_draw_label(&header_area, mask, arrow_style, opa_scale, LV_SYMBOL_LEFT, LV_TXT_FLAG_NONE, NULL, NULL, NULL, bidi_dir);
/*Add the right arrow*/
arrow_style = ext->btn_pressing > 0 ? ext->style_header_pr : ext->style_header;
header_area.x1 = header_area.x2 - ext->style_header->body.padding.right -
lv_txt_get_width(LV_SYMBOL_RIGHT, strlen(LV_SYMBOL_RIGHT), arrow_style->text.font,
arrow_style->text.line_space, LV_TXT_FLAG_NONE);
lv_draw_label(&header_area, mask, arrow_style, opa_scale, LV_SYMBOL_RIGHT, LV_TXT_FLAG_NONE, NULL, NULL, NULL);
lv_draw_label(&header_area, mask, arrow_style, opa_scale, LV_SYMBOL_RIGHT, LV_TXT_FLAG_NONE, NULL, NULL, NULL, bidi_dir);
}
/**
@@ -710,6 +713,7 @@ static void draw_header(lv_obj_t * calendar, const lv_area_t * mask)
static void draw_day_names(lv_obj_t * calendar, const lv_area_t * mask)
{
lv_calendar_ext_t * ext = lv_obj_get_ext_attr(calendar);
lv_bidi_dir_t bidi_dir = lv_obj_get_base_dir(calendar);
lv_opa_t opa_scale = lv_obj_get_opa_scale(calendar);
lv_coord_t l_pad = ext->style_day_names->body.padding.left;
@@ -724,7 +728,7 @@ static void draw_day_names(lv_obj_t * calendar, const lv_area_t * mask)
label_area.x1 = calendar->coords.x1 + (w * i) / 7 + l_pad;
label_area.x2 = label_area.x1 + box_w - 1;
lv_draw_label(&label_area, mask, ext->style_day_names, opa_scale, get_day_name(calendar, i), LV_TXT_FLAG_CENTER,
NULL, NULL, NULL);
NULL, NULL, NULL, bidi_dir);
}
}
@@ -736,6 +740,7 @@ static void draw_day_names(lv_obj_t * calendar, const lv_area_t * mask)
static void draw_days(lv_obj_t * calendar, const lv_area_t * mask)
{
lv_calendar_ext_t * ext = lv_obj_get_ext_attr(calendar);
lv_bidi_dir_t bidi_dir = lv_obj_get_base_dir(calendar);
const lv_style_t * style_bg = lv_calendar_get_style(calendar, LV_CALENDAR_STYLE_BG);
lv_area_t label_area;
lv_opa_t opa_scale = lv_obj_get_opa_scale(calendar);
@@ -853,7 +858,7 @@ static void draw_days(lv_obj_t * calendar, const lv_area_t * mask)
/*Write the day's number*/
lv_utils_num_to_str(day_cnt, buf);
lv_draw_label(&label_area, mask, final_style, opa_scale, buf, LV_TXT_FLAG_CENTER, NULL, NULL, NULL);
lv_draw_label(&label_area, mask, final_style, opa_scale, buf, LV_TXT_FLAG_CENTER, NULL, NULL, NULL, bidi_dir);
/*Go to the next day*/
day_cnt++;

View File

@@ -585,7 +585,7 @@ void lv_canvas_draw_text(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, lv_coord
default: flag = LV_TXT_FLAG_NONE; break;
}
lv_draw_label(&coords, &mask, style, LV_OPA_COVER, txt, flag, NULL, NULL, NULL);
lv_draw_label(&coords, &mask, style, LV_OPA_COVER, txt, flag, NULL, NULL, NULL, lv_obj_get_base_dir(canvas));
lv_refr_set_disp_refreshing(refr_ori);
}

View File

@@ -1379,7 +1379,7 @@ static void lv_chart_draw_y_ticks(lv_obj_t * chart, const lv_area_t * mask, uint
a.x2 = p2.x + size.x + LV_CHART_AXIS_TO_LABEL_DISTANCE;
}
lv_draw_label(&a, mask, style, opa_scale, buf, LV_TXT_FLAG_CENTER, NULL, NULL, NULL);
lv_draw_label(&a, mask, style, opa_scale, buf, LV_TXT_FLAG_CENTER, NULL, NULL, NULL, lv_obj_get_base_dir(chart));
}
}
@@ -1465,7 +1465,7 @@ static void lv_chart_draw_x_ticks(lv_obj_t * chart, const lv_area_t * mask)
/* set the area at some distance of the major tick len under of the tick */
lv_area_t a = {(p2.x - size.x / 2), (p2.y + LV_CHART_AXIS_TO_LABEL_DISTANCE), (p2.x + size.x / 2),
(p2.y + size.y + LV_CHART_AXIS_TO_LABEL_DISTANCE)};
lv_draw_label(&a, mask, style, opa_scale, buf, LV_TXT_FLAG_CENTER, NULL, NULL, NULL);
lv_draw_label(&a, mask, style, opa_scale, buf, LV_TXT_FLAG_CENTER, NULL, NULL, NULL, lv_obj_get_base_dir(chart));
}
}
}

View File

@@ -21,6 +21,7 @@
#include "../lv_misc/lv_area.h"
#include "../lv_misc/lv_color.h"
#include "../lv_misc/lv_math.h"
#include "../lv_misc/lv_bidi.h"
/*********************
* DEFINES
@@ -364,23 +365,23 @@ static void lv_cont_layout_row(lv_obj_t * cont)
lv_align_t align;
const lv_style_t * style = lv_obj_get_style(cont);
lv_coord_t vpad_corr;
lv_bidi_dir_t base_dir = lv_obj_get_base_dir(cont);
switch(type) {
case LV_LAYOUT_ROW_T:
vpad_corr = style->body.padding.top;
align = LV_ALIGN_IN_TOP_LEFT;
align = base_dir == LV_BIDI_DIR_RTL ? LV_ALIGN_IN_TOP_RIGHT : LV_ALIGN_IN_TOP_LEFT;
break;
case LV_LAYOUT_ROW_M:
vpad_corr = 0;
align = LV_ALIGN_IN_LEFT_MID;
align = base_dir == LV_BIDI_DIR_RTL ? LV_ALIGN_IN_RIGHT_MID: LV_ALIGN_IN_LEFT_MID;
break;
case LV_LAYOUT_ROW_B:
vpad_corr = -style->body.padding.bottom;
align = LV_ALIGN_IN_BOTTOM_LEFT;
align = base_dir == LV_BIDI_DIR_RTL ? LV_ALIGN_IN_BOTTOM_RIGHT: LV_ALIGN_IN_BOTTOM_LEFT;
break;
default:
vpad_corr = 0;
align = LV_ALIGN_IN_TOP_LEFT;
align = base_dir == LV_BIDI_DIR_RTL ? LV_ALIGN_IN_TOP_RIGHT : LV_ALIGN_IN_TOP_LEFT;
break;
}
@@ -389,12 +390,19 @@ static void lv_cont_layout_row(lv_obj_t * cont)
lv_obj_set_protect(cont, LV_PROTECT_CHILD_CHG);
/* Align the children */
lv_coord_t last_cord = style->body.padding.left;
lv_coord_t last_cord;
if(base_dir == LV_BIDI_DIR_RTL) last_cord = style->body.padding.right;
else last_cord = style->body.padding.left;
LV_LL_READ_BACK(cont->child_ll, child)
{
if(lv_obj_get_hidden(child) != false || lv_obj_is_protected(child, LV_PROTECT_POS) != false) continue;
lv_obj_align(child, cont, align, last_cord, vpad_corr);
// last_cord -= lv_obj_get_width(child);
if(base_dir == LV_BIDI_DIR_RTL) lv_obj_align(child, cont, align, -last_cord, vpad_corr);
else lv_obj_align(child, cont, align, last_cord, vpad_corr);
last_cord += lv_obj_get_width(child) + style->body.padding.inner;
}

View File

@@ -113,6 +113,11 @@ lv_obj_t * lv_ddlist_create(lv_obj_t * par, const lv_obj_t * copy)
lv_obj_set_drag(scrl, false);
lv_page_set_scrl_fit2(new_ddlist, LV_FIT_FILL, LV_FIT_TIGHT);
/*Save (a later restore) the original X coordinate because it changes as the FITs applies*/
lv_coord_t x;
if(lv_obj_get_base_dir(new_ddlist) == LV_BIDI_DIR_RTL) x = lv_obj_get_x(new_ddlist) + lv_obj_get_width(new_ddlist);
else x = lv_obj_get_x(new_ddlist);
ext->label = lv_label_create(new_ddlist, NULL);
lv_cont_set_fit2(new_ddlist, LV_FIT_TIGHT, LV_FIT_NONE);
lv_page_set_sb_mode(new_ddlist, LV_SB_MODE_HIDE);
@@ -120,6 +125,10 @@ lv_obj_t * lv_ddlist_create(lv_obj_t * par, const lv_obj_t * copy)
lv_ddlist_set_options(new_ddlist, "Option 1\nOption 2\nOption 3");
/*Restore the original X coordinate*/
if(lv_obj_get_base_dir(new_ddlist) == LV_BIDI_DIR_RTL) lv_obj_set_x(new_ddlist, x - lv_obj_get_width(new_ddlist));
else lv_obj_set_x(new_ddlist, x);
/*Set the default styles*/
lv_theme_t * th = lv_theme_get_current();
if(th) {
@@ -131,6 +140,8 @@ lv_obj_t * lv_ddlist_create(lv_obj_t * par, const lv_obj_t * copy)
lv_ddlist_set_style(new_ddlist, LV_DDLIST_STYLE_SEL, &lv_style_plain_color);
lv_ddlist_set_style(new_ddlist, LV_DDLIST_STYLE_SB, &lv_style_pretty_color);
}
}
/*Copy an existing drop down list*/
else {
@@ -186,7 +197,8 @@ void lv_ddlist_set_options(lv_obj_t * ddlist, const char * options)
lv_ddlist_refr_width(ddlist);
switch(lv_label_get_align(ext->label)) {
lv_label_align_t align = lv_label_get_align(ext->label);
switch(align) {
case LV_LABEL_ALIGN_LEFT: lv_obj_align(ext->label, NULL, LV_ALIGN_IN_LEFT_MID, 0, 0); break;
case LV_LABEL_ALIGN_CENTER: lv_obj_align(ext->label, NULL, LV_ALIGN_CENTER, 0, 0); break;
case LV_LABEL_ALIGN_RIGHT: lv_obj_align(ext->label, NULL, LV_ALIGN_IN_RIGHT_MID, 0, 0); break;
@@ -597,7 +609,7 @@ static bool lv_ddlist_design(lv_obj_t * ddlist, const lv_area_t * mask, lv_desig
new_style.text.opa = sel_style->text.opa;
lv_txt_flag_t flag = lv_ddlist_get_txt_flag(ddlist);
lv_draw_label(&ext->label->coords, &mask_sel, &new_style, opa_scale, lv_label_get_text(ext->label),
flag, NULL, NULL, NULL);
flag, NULL, NULL, NULL, lv_obj_get_base_dir(ddlist));
}
}
@@ -630,9 +642,9 @@ static bool lv_ddlist_design(lv_obj_t * ddlist, const lv_area_t * mask, lv_desig
bool area_ok;
area_ok = lv_area_intersect(&mask_arrow, mask, &area_arrow);
if(area_ok) {
/*Use a down arrow in ddlist, you can replace it with yourcustom symbol*/
lv_draw_label(&area_arrow, &mask_arrow, &new_style, opa_scale, LV_SYMBOL_DOWN, LV_TXT_FLAG_NONE,
NULL, NULL, NULL); /*Use a down arrow in ddlist, you can replace it with your
custom symbol*/
NULL, NULL, NULL, lv_obj_get_base_dir(ddlist));
}
}
}
@@ -662,7 +674,15 @@ static lv_res_t lv_ddlist_signal(lv_obj_t * ddlist, lv_signal_t sign, void * par
if(sign == LV_SIGNAL_STYLE_CHG) {
lv_ddlist_refr_size(ddlist, 0);
} else if(sign == LV_SIGNAL_BASE_DIR_CHG) {
lv_label_align_t align = lv_label_get_align(ext->label);
switch(align) {
case LV_LABEL_ALIGN_LEFT: lv_obj_align(ext->label, NULL, LV_ALIGN_IN_LEFT_MID, 0, 0); break;
case LV_LABEL_ALIGN_CENTER: lv_obj_align(ext->label, NULL, LV_ALIGN_CENTER, 0, 0); break;
case LV_LABEL_ALIGN_RIGHT: lv_obj_align(ext->label, NULL, LV_ALIGN_IN_RIGHT_MID, 0, 0); break;
}
lv_ddlist_refr_size(ddlist, 0);
} else if(sign == LV_SIGNAL_CLEANUP) {
ext->label = NULL;
} else if(sign == LV_SIGNAL_FOCUS) {
@@ -981,7 +1001,12 @@ static void lv_ddlist_pos_current_option(lv_obj_t * ddlist)
*/
static void lv_ddlist_refr_width(lv_obj_t * ddlist)
{
lv_ddlist_ext_t * ext = lv_obj_get_ext_attr(ddlist);
lv_ddlist_ext_t * ext = lv_obj_get_ext_attr(ddlist);
/*Save the current x coordinate because it should be kept after the refrsh*/
lv_coord_t x;
if(lv_obj_get_base_dir(ddlist) == LV_BIDI_DIR_RTL) x = lv_obj_get_x(ddlist) + lv_obj_get_width(ddlist);
else x = lv_obj_get_x(ddlist);
/*Set the TIGHT fit horizontally the set the width to the content*/
lv_page_set_scrl_fit2(ddlist, LV_FIT_TIGHT, lv_page_get_scrl_fit_bottom(ddlist));
@@ -989,6 +1014,9 @@ static void lv_ddlist_refr_width(lv_obj_t * ddlist)
/*Revert FILL fit to fill the parent with the options area. It allows to RIGHT/CENTER align the text*/
lv_page_set_scrl_fit2(ddlist, LV_FIT_FILL, lv_page_get_scrl_fit_bottom(ddlist));
if(lv_obj_get_base_dir(ddlist) == LV_BIDI_DIR_RTL) lv_obj_set_x(ddlist, x - lv_obj_get_width(ddlist));
else lv_obj_set_x(ddlist, x);
switch(lv_label_get_align(ext->label)) {
case LV_LABEL_ALIGN_LEFT: lv_obj_align(ext->label, NULL, LV_ALIGN_IN_LEFT_MID, 0, 0); break;
case LV_LABEL_ALIGN_CENTER: lv_obj_align(ext->label, NULL, LV_ALIGN_CENTER, 0, 0); break;

View File

@@ -389,7 +389,7 @@ static void lv_gauge_draw_scale(lv_obj_t * gauge, const lv_area_t * mask)
label_cord.x2 = label_cord.x1 + label_size.x;
label_cord.y2 = label_cord.y1 + label_size.y;
lv_draw_label(&label_cord, mask, style, opa_scale, scale_txt, LV_TXT_FLAG_NONE, NULL, NULL, NULL);
lv_draw_label(&label_cord, mask, style, opa_scale, scale_txt, LV_TXT_FLAG_NONE, NULL, NULL, NULL, lv_obj_get_base_dir(gauge));
}
}
/**

View File

@@ -384,7 +384,7 @@ static bool lv_img_design(lv_obj_t * img, const lv_area_t * mask, lv_design_mode
lv_style_t style_mod;
lv_style_copy(&style_mod, style);
style_mod.text.color = style->image.color;
lv_draw_label(&coords, mask, &style_mod, opa_scale, ext->src, LV_TXT_FLAG_NONE, NULL, NULL, NULL);
lv_draw_label(&coords, mask, &style_mod, opa_scale, ext->src, LV_TXT_FLAG_NONE, NULL, NULL, NULL, lv_obj_get_base_dir(img));
} else {
/*Trigger the error handler of image drawer*/
LV_LOG_WARN("lv_img_design: image source type is unknown");

View File

@@ -304,7 +304,7 @@ static bool lv_imgbtn_design(lv_obj_t * imgbtn, const lv_area_t * mask, lv_desig
#if LV_IMGBTN_TILED == 0
const void * src = ext->img_src[state];
if(lv_img_src_get_type(src) == LV_IMG_SRC_SYMBOL) {
lv_draw_label(&imgbtn->coords, mask, style, opa_scale, src, LV_TXT_FLAG_NONE, NULL, NULL, NULL);
lv_draw_label(&imgbtn->coords, mask, style, opa_scale, src, LV_TXT_FLAG_NONE, NULL, NULL, NULL, lv_obj_get_base_dir(imgbtn));
} else {
lv_draw_img(&imgbtn->coords, mask, src, style, opa_scale);
}

View File

@@ -131,6 +131,7 @@ lv_obj_t * lv_kb_create(lv_obj_t * par, const lv_obj_t * copy)
lv_obj_set_event_cb(new_kb, lv_kb_def_event_cb);
lv_btnm_set_map(new_kb, kb_map_lc);
lv_btnm_set_ctrl_map(new_kb, kb_ctrl_lc_map);
lv_obj_set_base_dir(new_kb, LV_BIDI_DIR_LTR);
/*Set the default styles*/
lv_theme_t * th = lv_theme_get_current();

View File

@@ -14,6 +14,7 @@
#include "../lv_core/lv_group.h"
#include "../lv_misc/lv_color.h"
#include "../lv_misc/lv_math.h"
#include "../lv_misc/lv_bidi.h"
#include "../lv_misc/lv_printf.h"
/*********************
@@ -92,7 +93,7 @@ lv_obj_t * lv_label_create(lv_obj_t * par, const lv_obj_t * copy)
ext->static_txt = 0;
ext->recolor = 0;
ext->body_draw = 0;
ext->align = LV_LABEL_ALIGN_LEFT;
ext->align = LV_LABEL_ALIGN_AUTO;
ext->dot_end = LV_LABEL_DOT_END_INV;
ext->long_mode = LV_LABEL_LONG_EXPAND;
#if LV_USE_ANIMATION
@@ -205,7 +206,9 @@ void lv_label_set_text(lv_obj_t * label, const char * text)
if(ext->text == NULL) return;
strcpy(ext->text, text);
ext->static_txt = 0; /*Now the text is dynamically allocated*/
/*Now the text is dynamically allocated*/
ext->static_txt = 0;
}
lv_label_refr_text(label);
@@ -506,7 +509,22 @@ lv_label_align_t lv_label_get_align(const lv_obj_t * label)
LV_ASSERT_OBJ(label, LV_OBJX_NAME);
lv_label_ext_t * ext = lv_obj_get_ext_attr(label);
return ext->align;
lv_label_align_t align = ext->align;
if(align == LV_LABEL_ALIGN_AUTO) {
#if LV_USE_BIDI
lv_bidi_dir_t base_dir = lv_obj_get_base_dir(label);
if(base_dir == LV_BIDI_DIR_AUTO) base_dir = lv_bidi_detect_base_dir(ext->text);
if(base_dir == LV_BIDI_DIR_LTR) align = LV_LABEL_ALIGN_LEFT;
else if (base_dir == LV_BIDI_DIR_RTL) align = LV_LABEL_ALIGN_RIGHT;
#else
align = LV_LABEL_ALIGN_LEFT;
#endif
}
return align;
}
/**
@@ -560,7 +578,7 @@ uint16_t lv_label_get_anim_speed(const lv_obj_t * label)
* index (different in UTF-8)
* @param pos store the result here (E.g. index = 0 gives 0;0 coordinates)
*/
void lv_label_get_letter_pos(const lv_obj_t * label, uint16_t index, lv_point_t * pos)
void lv_label_get_letter_pos(const lv_obj_t * label, uint16_t char_id, lv_point_t * pos)
{
LV_ASSERT_OBJ(label, LV_OBJX_NAME);
LV_ASSERT_NULL(pos);
@@ -578,19 +596,22 @@ void lv_label_get_letter_pos(const lv_obj_t * label, uint16_t index, lv_point_t
if(ext->recolor != 0) flag |= LV_TXT_FLAG_RECOLOR;
if(ext->expand != 0) flag |= LV_TXT_FLAG_EXPAND;
if(ext->align == LV_LABEL_ALIGN_CENTER) flag |= LV_TXT_FLAG_CENTER;
lv_label_align_t align = lv_label_get_align(label);
if(align == LV_LABEL_ALIGN_CENTER) flag |= LV_TXT_FLAG_CENTER;
if(align == LV_LABEL_ALIGN_RIGHT) flag |= LV_TXT_FLAG_RIGHT;
/*If the width will be expanded the set the max length to very big */
if(ext->long_mode == LV_LABEL_LONG_EXPAND) {
max_w = LV_COORD_MAX;
}
index = lv_txt_encoded_get_byte_id(txt, index);
uint16_t byte_id = lv_txt_encoded_get_byte_id(txt, char_id);
/*Search the line of the index letter */;
while(txt[new_line_start] != '\0') {
new_line_start += lv_txt_get_next_line(&txt[line_start], font, style->text.letter_space, max_w, flag);
if(index < new_line_start || txt[new_line_start] == '\0')
if(byte_id < new_line_start || txt[new_line_start] == '\0')
break; /*The line of 'index' letter begins at 'line_start'*/
y += letter_height + style->text.line_space;
@@ -598,26 +619,50 @@ void lv_label_get_letter_pos(const lv_obj_t * label, uint16_t index, lv_point_t
}
/*If the last character is line break then go to the next line*/
if(index > 0) {
if((txt[index - 1] == '\n' || txt[index - 1] == '\r') && txt[index] == '\0') {
if(byte_id > 0) {
if((txt[byte_id - 1] == '\n' || txt[byte_id - 1] == '\r') && txt[byte_id] == '\0') {
y += letter_height + style->text.line_space;
line_start = index;
line_start = byte_id;
}
}
const char *bidi_txt;
uint16_t visual_byte_pos;
#if LV_USE_BIDI
/*Handle Bidi*/
if(new_line_start == byte_id) {
visual_byte_pos = byte_id - line_start;
bidi_txt = &txt[line_start];
}
else {
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++;
visual_byte_pos = lv_txt_encoded_get_byte_id(bidi_txt, visual_char_pos);
}
#else
bidi_txt = &txt[line_start];
visual_byte_pos = byte_id - line_start;
#endif
/*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_byte_pos, font, style->text.letter_space, flag);
if(index != line_start) x += style->text.letter_space;
if(char_id != line_start) x += style->text.letter_space;
if(ext->align == LV_LABEL_ALIGN_CENTER) {
if(align == LV_LABEL_ALIGN_CENTER) {
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;
} else if(ext->align == LV_LABEL_ALIGN_RIGHT) {
} else if(align == LV_LABEL_ALIGN_RIGHT) {
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;
}
@@ -647,10 +692,15 @@ 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);
lv_coord_t y = 0;
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->expand != 0) flag |= LV_TXT_FLAG_EXPAND;
if(ext->align == LV_LABEL_ALIGN_CENTER) flag |= LV_TXT_FLAG_CENTER;
lv_label_align_t align = lv_label_get_align(label);
if(align == LV_LABEL_ALIGN_CENTER) flag |= LV_TXT_FLAG_CENTER;
if(align == LV_LABEL_ALIGN_RIGHT) flag |= LV_TXT_FLAG_RIGHT;
/*If the width will be expanded set the max length to very big */
if(ext->long_mode == LV_LABEL_LONG_EXPAND) {
@@ -675,47 +725,72 @@ uint16_t lv_label_get_letter_on(const lv_obj_t * label, lv_point_t * pos)
line_start = new_line_start;
}
#if LV_USE_BIDI
bidi_txt = lv_draw_get_buf(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);
#else
bidi_txt = txt + line_start;
#endif
/*Calculate the x coordinate*/
lv_coord_t x = 0;
if(ext->align == LV_LABEL_ALIGN_CENTER) {
if(align == LV_LABEL_ALIGN_CENTER) {
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;
}
else if(align == LV_LABEL_ALIGN_RIGHT) {
lv_coord_t line_w;
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;
}
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 letter;
uint32_t letter_next;
while(i < new_line_start) {
/* Get the current letter.*/
letter = lv_txt_encoded_next(txt, &i);
if(new_line_start > 0) {
while(i + line_start < new_line_start) {
/* Get the current letter.*/
letter = lv_txt_encoded_next(bidi_txt, &i);
/*Get the next letter too for kerning*/
letter_next = lv_txt_encoded_next(&txt[i], NULL);
/*Get the next letter too for kerning*/
letter_next = lv_txt_encoded_next(&bidi_txt[i], NULL);
/*Handle the recolor command*/
if((flag & LV_TXT_FLAG_RECOLOR) != 0) {
if(lv_txt_is_cmd(&cmd_state, txt[i]) != false) {
continue; /*Skip the letter is it is part of a command*/
/*Handle the recolor command*/
if((flag & LV_TXT_FLAG_RECOLOR) != 0) {
if(lv_txt_is_cmd(&cmd_state, bidi_txt[i]) != false) {
continue; /*Skip the letter is it is part of a command*/
}
}
}
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*/
if(pos->x < x || i == new_line_start) {
i = i_act;
break;
/*Finish if the x position or the last char of the line is reached*/
if(pos->x < x || i + line_start == new_line_start) {
i = i_act;
break;
}
x += style->text.letter_space;
i_act = i;
}
x += style->text.letter_space;
i_act = i;
}
return lv_encoded_get_char_id(txt, i);
#if LV_USE_BIDI
/*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);
if (is_rtl) logical_pos++;
#else
logical_pos = lv_txt_encoded_get_char_id(bidi_txt, i);
#endif
return logical_pos + lv_txt_encoded_get_char_id(txt, line_start);
}
/**
@@ -776,10 +851,11 @@ bool lv_label_is_char_under_pos(const lv_obj_t * label, lv_point_t * pos)
uint8_t letter_height = lv_font_get_line_height(font);
lv_coord_t y = 0;
lv_txt_flag_t flag = LV_TXT_FLAG_NONE;
lv_label_align_t align = lv_label_get_align(label);
if(ext->recolor != 0) flag |= LV_TXT_FLAG_RECOLOR;
if(ext->expand != 0) flag |= LV_TXT_FLAG_EXPAND;
if(ext->align == LV_LABEL_ALIGN_CENTER) flag |= LV_TXT_FLAG_CENTER;
if(align == LV_LABEL_ALIGN_CENTER) flag |= LV_TXT_FLAG_CENTER;
/*If the width will be expanded set the max length to very big */
if(ext->long_mode == LV_LABEL_LONG_EXPAND) {
@@ -799,11 +875,16 @@ bool lv_label_is_char_under_pos(const lv_obj_t * label, lv_point_t * pos)
/*Calculate the x coordinate*/
lv_coord_t x = 0;
lv_coord_t last_x = 0;
if(ext->align == LV_LABEL_ALIGN_CENTER) {
if(align == LV_LABEL_ALIGN_CENTER) {
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);
x += lv_obj_get_width(label) / 2 - line_w / 2;
}
else if(align == LV_LABEL_ALIGN_RIGHT) {
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);
x += lv_obj_get_width(label) - line_w;
}
lv_txt_cmd_state_t cmd_state = LV_TXT_CMD_STATE_WAIT;
@@ -878,7 +959,6 @@ void lv_label_ins_text(lv_obj_t * label, uint32_t pos, const char * txt)
}
lv_txt_ins(ext->text, pos, txt);
lv_label_refr_text(label);
}
@@ -953,14 +1033,13 @@ static bool lv_label_design(lv_obj_t * label, const lv_area_t * mask, lv_design_
lv_draw_rect(&bg, mask, style, lv_obj_get_opa_scale(label));
}
/*TEST: draw a background for the label*/
// lv_draw_rect(&label->coords, mask, &lv_style_plain_color, LV_OPA_COVER);
lv_label_align_t align = lv_label_get_align(label);
lv_txt_flag_t flag = LV_TXT_FLAG_NONE;
if(ext->recolor != 0) flag |= LV_TXT_FLAG_RECOLOR;
if(ext->expand != 0) flag |= LV_TXT_FLAG_EXPAND;
if(ext->align == LV_LABEL_ALIGN_CENTER) flag |= LV_TXT_FLAG_CENTER;
if(ext->align == LV_LABEL_ALIGN_RIGHT) flag |= LV_TXT_FLAG_RIGHT;
if(align == LV_LABEL_ALIGN_CENTER) flag |= LV_TXT_FLAG_CENTER;
if(align == LV_LABEL_ALIGN_RIGHT) flag |= LV_TXT_FLAG_RIGHT;
/* In ROLL mode the CENTER and RIGHT are pointless so remove them.
* (In addition they will result mis-alignment is this case)*/
@@ -987,7 +1066,7 @@ static bool lv_label_design(lv_obj_t * label, const lv_area_t * mask, lv_design_
sel.start = lv_label_get_text_sel_start(label);
sel.end = lv_label_get_text_sel_end(label);
lv_draw_label(&coords, mask, 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));
if(ext->long_mode == LV_LABEL_LONG_SROLL_CIRC) {
@@ -1003,14 +1082,14 @@ static bool lv_label_design(lv_obj_t * label, const lv_area_t * mask, lv_design_
lv_font_get_glyph_width(style->text.font, ' ', ' ') * LV_LABEL_WAIT_CHAR_COUNT;
ofs.y = ext->offset.y;
lv_draw_label(&coords, mask, 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));
}
/*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);
lv_draw_label(&coords, mask, 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));
}
}
}
@@ -1061,6 +1140,18 @@ static lv_res_t lv_label_signal(lv_obj_t * label, lv_signal_t sign, void * param
label->ext_draw_pad = LV_MATH_MAX(label->ext_draw_pad, style->body.padding.bottom);
}
}
else if(sign == LV_SIGNAL_BASE_DIR_CHG) {
#if LV_USE_BIDI
if(ext->static_txt == 0) lv_label_set_text(label, NULL);
#endif
} else if(sign == LV_SIGNAL_GET_TYPE) {
lv_obj_type_t * buf = param;
uint8_t i;
for(i = 0; i < LV_MAX_ANCESTOR_NUM - 1; i++) { /*Find the last set data*/
if(buf->type[i] == NULL) break;
}
buf->type[i] = "lv_label";
}
return res;
}
@@ -1144,11 +1235,12 @@ static void lv_label_refr_text(lv_obj_t * label)
/*In roll inf. mode keep the size but start offset animations*/
else if(ext->long_mode == LV_LABEL_LONG_SROLL_CIRC) {
#if LV_USE_ANIMATION
lv_label_align_t align = lv_label_get_align(label);
lv_anim_t anim;
anim.var = label;
anim.repeat = 1;
anim.playback = 0;
anim.start = 0;
anim.act_time = -(((lv_font_get_glyph_width(style->text.font, ' ', ' ') + style->text.letter_space) * 1000) /
ext->anim_speed) *
LV_LABEL_WAIT_CHAR_COUNT;
@@ -1159,7 +1251,14 @@ static void lv_label_refr_text(lv_obj_t * label)
bool hor_anim = false;
if(size.x > lv_obj_get_width(label)) {
anim.end = -size.x - lv_font_get_glyph_width(font, ' ', ' ') * LV_LABEL_WAIT_CHAR_COUNT;
if(align == LV_LABEL_ALIGN_RIGHT) {
anim.end = 0;
anim.start = -size.x - lv_font_get_glyph_width(font, ' ', ' ') * LV_LABEL_WAIT_CHAR_COUNT;
} else {
anim.start = 0;
anim.end = -size.x - lv_font_get_glyph_width(font, ' ', ' ') * LV_LABEL_WAIT_CHAR_COUNT;
}
anim.exec_cb = (lv_anim_exec_xcb_t)lv_label_set_offset_x;
anim.time = lv_anim_speed_to_time(ext->anim_speed, anim.start, anim.end);
lv_anim_create(&anim);
@@ -1171,7 +1270,14 @@ static void lv_label_refr_text(lv_obj_t * label)
}
if(size.y > lv_obj_get_height(label) && hor_anim == false) {
anim.end = -size.y - (lv_font_get_line_height(font));
if(align == LV_LABEL_ALIGN_RIGHT) {
anim.end = 0;
anim.start = -size.y - (lv_font_get_line_height(font));
} else {
anim.start = 0;
anim.end = -size.y - (lv_font_get_line_height(font));
}
anim.exec_cb = (lv_anim_exec_xcb_t)lv_label_set_offset_y;
anim.time = lv_anim_speed_to_time(ext->anim_speed, anim.start, anim.end);
lv_anim_create(&anim);

View File

@@ -60,6 +60,7 @@ enum {
LV_LABEL_ALIGN_LEFT, /**< Align text to left */
LV_LABEL_ALIGN_CENTER, /**< Align text to center */
LV_LABEL_ALIGN_RIGHT, /**< Align text to right */
LV_LABEL_ALIGN_AUTO, /**< Use LEFT or RIGHT depending on the direction of the text (LTR/RTL)*/
};
typedef uint8_t lv_label_align_t;
@@ -68,12 +69,13 @@ typedef struct
{
/*Inherited from 'base_obj' so no inherited ext.*/ /*Ext. of ancestor*/
/*New data for this type */
char * text; /*Text of the label*/
char * text; /*Text of the label*/
union
{
char * tmp_ptr; /* Pointer to the allocated memory containing the character which are replaced by dots (Handled
by the library)*/
char tmp[sizeof(char *)]; /* Directly store the characters if <=4 characters */
char tmp[LV_LABEL_DOT_NUM + 1]; /* Directly store the characters if <=4 characters */
} dot;
uint16_t dot_end; /*The text end position in dot mode (Handled by the library)*/
lv_point_t offset; /*Text draw position offset*/

View File

@@ -218,7 +218,8 @@ lv_obj_t * lv_list_add_btn(lv_obj_t * list, const void * img_src, const char * t
lv_label_set_text(label, txt);
lv_obj_set_click(label, false);
lv_label_set_long_mode(label, LV_LABEL_LONG_SROLL_CIRC);
lv_obj_set_width(label, liste->coords.x2 - label->coords.x1 - btn_hor_pad);
if(lv_obj_get_base_dir(liste) == LV_BIDI_DIR_RTL) lv_obj_set_width(label, label->coords.x2 - liste->coords.x1 - btn_hor_pad);
else lv_obj_set_width(label, liste->coords.x2 - label->coords.x1 - btn_hor_pad);
if(label_signal == NULL) label_signal = lv_obj_get_signal_cb(label);
}
#if LV_USE_GROUP

View File

@@ -828,8 +828,10 @@ static lv_res_t lv_page_signal(lv_obj_t * page, lv_signal_t sign, void * param)
lv_page_ext_t * ext = lv_obj_get_ext_attr(page);
lv_obj_t * child;
if(sign == LV_SIGNAL_CHILD_CHG) { /*Automatically move children to the scrollable object*/
const lv_style_t * style = lv_page_get_style(page, LV_PAGE_STYLE_SCRL);
const lv_style_t * style_bg = lv_page_get_style(page, LV_PAGE_STYLE_BG);
const lv_style_t * style_scrl = lv_page_get_style(page, LV_PAGE_STYLE_SCRL);
lv_fit_t fit_left = lv_page_get_scrl_fit_left(page);
lv_fit_t fit_right = lv_page_get_scrl_fit_right(page);
lv_fit_t fit_top = lv_page_get_scrl_fit_top(page);
child = lv_obj_get_child(page, NULL);
while(child != NULL) {
@@ -837,15 +839,19 @@ static lv_res_t lv_page_signal(lv_obj_t * page, lv_signal_t sign, void * param)
lv_obj_t * tmp = child;
child = lv_obj_get_child(page, child); /*Get the next child before move this*/
/* Reposition the child to take padding into account (Only if it's on (0;0) now)
/* Reposition the child to take padding into account (Only if it's on (0;0) or (widht;height) coordinates now)
* It's required to keep new the object on the same coordinate if FIT is enabled.*/
if((tmp->coords.x1 == page->coords.x1) && (fit_left == LV_FIT_TIGHT || fit_left == LV_FIT_FILL)) {
tmp->coords.x1 += style->body.padding.left;
tmp->coords.x2 += style->body.padding.left;
tmp->coords.x1 += style_scrl->body.padding.left;
tmp->coords.x2 += style_scrl->body.padding.left;
}
else if((tmp->coords.x2 == page->coords.x2) && (fit_right == LV_FIT_TIGHT || fit_right == LV_FIT_FILL)) {
tmp->coords.x1 -= style_scrl->body.padding.right + style_bg->body.padding.right;
tmp->coords.x2 -= style_scrl->body.padding.right + style_bg->body.padding.right;
}
if((tmp->coords.y1 == page->coords.y1) && (fit_top == LV_FIT_TIGHT || fit_top == LV_FIT_FILL)) {
tmp->coords.y1 += style->body.padding.top;
tmp->coords.y2 += style->body.padding.top;
tmp->coords.y1 += style_scrl->body.padding.top;
tmp->coords.y2 += style_scrl->body.padding.top;
}
lv_obj_set_parent(tmp, ext->scrl);
} else {

View File

@@ -397,7 +397,7 @@ static bool lv_roller_design(lv_obj_t * roller, const lv_area_t * mask, lv_desig
new_style.text.color = sel_style->text.color;
new_style.text.opa = sel_style->text.opa;
lv_draw_label(&ext->ddlist.label->coords, &mask_sel, &new_style, opa_scale,
lv_label_get_text(ext->ddlist.label), txt_align, NULL, NULL, NULL);
lv_label_get_text(ext->ddlist.label), txt_align, NULL, NULL, NULL, lv_obj_get_base_dir(ext->ddlist.label));
}
}

View File

@@ -1391,7 +1391,7 @@ static bool lv_ta_scrollable_design(lv_obj_t * scrl, const lv_area_t * mask, lv_
cur_area.x1 += cur_style.body.padding.left;
cur_area.y1 += cur_style.body.padding.top;
lv_draw_label(&cur_area, mask, &cur_style, opa_scale, letter_buf, LV_TXT_FLAG_NONE, NULL, NULL, NULL);
lv_draw_label(&cur_area, mask, &cur_style, opa_scale, letter_buf, LV_TXT_FLAG_NONE, NULL, NULL, NULL, lv_obj_get_base_dir(ta));
} else if(ext->cursor.type == LV_CURSOR_OUTLINE) {
cur_style.body.opa = LV_OPA_TRANSP;
@@ -1855,53 +1855,53 @@ static void update_cursor_position_on_click(lv_obj_t * ta, lv_signal_t sign, lv_
lv_indev_get_vect(click_source, &vect_act);
if(point_act.x < 0 || point_act.y < 0) return; /*Ignore event from keypad*/
lv_point_t relative_position;
relative_position.x = point_act.x - label_coords.x1;
relative_position.y = point_act.y - label_coords.y1;
lv_point_t rel_pos;
rel_pos.x = point_act.x - label_coords.x1;
rel_pos.y = point_act.y - label_coords.y1;
lv_coord_t label_width = lv_obj_get_width(ext->label);
uint16_t index_of_char_at_position;
uint16_t char_id_at_click;
#if LV_LABEL_TEXT_SEL
lv_label_ext_t * ext_label = lv_obj_get_ext_attr(ext->label);
bool click_outside_label;
/*Check if the click happened on the left side of the area outside the label*/
if(relative_position.x < 0) {
index_of_char_at_position = 0;
if(rel_pos.x < 0) {
char_id_at_click = 0;
click_outside_label = true;
}
/*Check if the click happened on the right side of the area outside the label*/
else if(relative_position.x >= label_width) {
index_of_char_at_position = LV_TA_CURSOR_LAST;
else if(rel_pos.x >= label_width) {
char_id_at_click = LV_TA_CURSOR_LAST;
click_outside_label = true;
} else {
index_of_char_at_position = lv_label_get_letter_on(ext->label, &relative_position);
click_outside_label = !lv_label_is_char_under_pos(ext->label, &relative_position);
char_id_at_click = lv_label_get_letter_on(ext->label, &rel_pos);
click_outside_label = !lv_label_is_char_under_pos(ext->label, &rel_pos);
}
if(ext->text_sel_en) {
if(!ext->text_sel_in_prog && !click_outside_label && sign == LV_SIGNAL_PRESSED) {
/*Input device just went down. Store the selection start position*/
ext->sel.start = index_of_char_at_position;
ext->sel.end = LV_DRAW_LABEL_NO_TXT_SEL;
ext->sel.start = char_id_at_click;
ext->sel.end = LV_LABEL_TEXT_SEL_OFF;
ext->text_sel_in_prog = 1;
lv_obj_set_drag(lv_page_get_scrl(ta), false);
} else if(ext->text_sel_in_prog && sign == LV_SIGNAL_PRESSING) {
/*Input device may be moving. Store the end position */
ext->sel.end = index_of_char_at_position;
ext->sel.end = char_id_at_click;
} else if(ext->text_sel_in_prog && (sign == LV_SIGNAL_PRESS_LOST || sign == LV_SIGNAL_RELEASED)) {
/*Input device is released. Check if anything was selected.*/
lv_obj_set_drag(lv_page_get_scrl(ta), true);
}
}
if(ext->text_sel_in_prog || sign == LV_SIGNAL_PRESSED) lv_ta_set_cursor_pos(ta, index_of_char_at_position);
if(ext->text_sel_in_prog || sign == LV_SIGNAL_PRESSED) lv_ta_set_cursor_pos(ta, char_id_at_click);
if(ext->text_sel_in_prog) {
/*If the selected area has changed then update the real values and*/
/*invalidate the text area.*/
/*Invalidate the text area.*/
if(ext->sel.start > ext->sel.end) {
if(ext_label->txt_sel_start != ext->sel.end || ext_label->txt_sel_end != ext->sel.start) {
ext_label->txt_sel_start = ext->sel.end;
@@ -1928,17 +1928,17 @@ static void update_cursor_position_on_click(lv_obj_t * ta, lv_signal_t sign, lv_
}
#else
/*Check if the click happened on the left side of the area outside the label*/
if(relative_position.x < 0) {
index_of_char_at_position = 0;
if(rel_pos.x < 0) {
char_id_at_click = 0;
}
/*Check if the click happened on the right side of the area outside the label*/
else if(relative_position.x >= label_width) {
index_of_char_at_position = LV_TA_CURSOR_LAST;
else if(rel_pos.x >= label_width) {
char_id_at_click = LV_TA_CURSOR_LAST;
} else {
index_of_char_at_position = lv_label_get_letter_on(ext->label, &relative_position);
char_id_at_click = lv_label_get_letter_on(ext->label, &rel_pos);
}
if(sign == LV_SIGNAL_PRESSED) lv_ta_set_cursor_pos(ta, index_of_char_at_position);
if(sign == LV_SIGNAL_PRESSED) lv_ta_set_cursor_pos(ta, char_id_at_click);
#endif
}

View File

@@ -151,14 +151,23 @@ void lv_table_set_cell_value(lv_obj_t * table, uint16_t row, uint16_t col, const
}
/*Initialize the format byte*/
else {
format.s.align = LV_LABEL_ALIGN_LEFT;
#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;
else if(base_dir == LV_BIDI_DIR_AUTO) format.s.align = lv_bidi_detect_base_dir(txt);
#else
format.s.align = LV_LABEL_ALIGN_LEFT;
#endif
format.s.right_merge = 0;
format.s.type = 0;
format.s.crop = 0;
}
ext->cell_data[cell] = lv_mem_realloc(ext->cell_data[cell], strlen(txt) + 2); /*+1: trailing '\0; +1: format byte*/
strcpy(ext->cell_data[cell] + 1, txt); /*Leave the format byte*/
strcpy(ext->cell_data[cell] + 1, txt); /*+1 to skip the format byte*/
ext->cell_data[cell][0] = format.format_byte;
refr_size(table);
}
@@ -729,7 +738,7 @@ static bool lv_table_design(lv_obj_t * table, const lv_area_t * mask, lv_design_
label_mask_ok = lv_area_intersect(&label_mask, mask, &cell_area);
if(label_mask_ok) {
lv_draw_label(&txt_area, &label_mask, cell_style, opa_scale, ext->cell_data[cell] + 1,
txt_flags, NULL, NULL, NULL);
txt_flags, NULL, NULL, NULL, lv_obj_get_base_dir(table));
}
/*Draw lines after '\n's*/
lv_point_t p1;

View File

@@ -147,7 +147,7 @@ lv_obj_t * lv_tabview_create(lv_obj_t * par, const lv_obj_t * copy)
lv_tabview_set_style(new_tabview, LV_TABVIEW_STYLE_BTN_TGL_PR, th->style.tabview.btn.tgl_pr);
} else {
lv_tabview_set_style(new_tabview, LV_TABVIEW_STYLE_BG, &lv_style_plain);
lv_tabview_set_style(new_tabview, LV_TABVIEW_STYLE_BTN_BG, &lv_style_transp);
lv_tabview_set_style(new_tabview, LV_TABVIEW_STYLE_BTN_BG, &lv_style_pretty);//transp);
lv_tabview_set_style(new_tabview, LV_TABVIEW_STYLE_INDIC, &lv_style_plain_color);
}
}
@@ -222,8 +222,8 @@ lv_obj_t * lv_tabview_add_tab(lv_obj_t * tabview, const char * name)
lv_obj_t * h = lv_page_create(ext->content, NULL);
lv_obj_set_size(h, lv_obj_get_width(tabview), lv_obj_get_height(ext->content));
lv_page_set_sb_mode(h, LV_SB_MODE_AUTO);
lv_page_set_style(h, LV_PAGE_STYLE_BG, &lv_style_transp);
lv_page_set_style(h, LV_PAGE_STYLE_SCRL, &lv_style_transp);
lv_page_set_style(h, LV_PAGE_STYLE_BG, &lv_style_transp_tight);
lv_page_set_style(h, LV_PAGE_STYLE_SCRL, &lv_style_transp);//plain_color);
if(page_signal == NULL) page_signal = lv_obj_get_signal_cb(h);
if(page_scrl_signal == NULL) page_scrl_signal = lv_obj_get_signal_cb(lv_page_get_scrl(h));
@@ -351,6 +351,10 @@ void lv_tabview_set_tab_act(lv_obj_t * tabview, uint16_t id, lv_anim_enable_t an
ext->tab_cur = id;
if(lv_obj_get_base_dir(tabview) == LV_BIDI_DIR_RTL) {
id = (ext->tab_cnt - (id + 1));
}
lv_coord_t cont_x;
switch(ext->btns_pos) {
@@ -910,7 +914,11 @@ static void tabpage_pressing_handler(lv_obj_t * tabview, lv_obj_t * tabpage)
p = ((tabpage->coords.x1 - tabview->coords.x1) * (indic_size + tabs_style->body.padding.inner)) /
lv_obj_get_width(tabview);
lv_obj_set_x(ext->indic, indic_size * ext->tab_cur + tabs_style->body.padding.inner * ext->tab_cur +
uint16_t id = ext->tab_cur;
if(lv_obj_get_base_dir(tabview) == LV_BIDI_DIR_RTL) {
id = (ext->tab_cnt - (id + 1));
}
lv_obj_set_x(ext->indic, indic_size * id + tabs_style->body.padding.inner * id +
indic_style->body.padding.left - p);
break;
case LV_TABVIEW_BTNS_POS_LEFT:
@@ -953,13 +961,18 @@ static void tabpage_press_lost_handler(lv_obj_t * tabview, lv_obj_t * tabpage)
lv_coord_t page_x2 = page_x1 + lv_obj_get_width(tabpage);
lv_coord_t treshold = lv_obj_get_width(tabview) / 2;
uint16_t tab_cur = ext->tab_cur;
int16_t tab_cur = ext->tab_cur;
if(page_x1 > treshold) {
if(tab_cur != 0) tab_cur--;
if(lv_obj_get_base_dir(tabview) == LV_BIDI_DIR_RTL) tab_cur++;
else tab_cur--;
} else if(page_x2 < treshold) {
if(tab_cur < ext->tab_cnt - 1) tab_cur++;
if(lv_obj_get_base_dir(tabview) == LV_BIDI_DIR_RTL) tab_cur--;
else tab_cur++;
}
if(tab_cur > ext->tab_cnt - 1) tab_cur = ext->tab_cnt - 1;
else if(tab_cur < 0) tab_cur = 0;
uint32_t id_prev = lv_tabview_get_tab_act(tabview);
lv_tabview_set_tab_act(tabview, tab_cur, LV_ANIM_ON);
uint32_t id_new = lv_tabview_get_tab_act(tabview);