merge dev-6.1

This commit is contained in:
Gabor Kiss-Vamosi
2019-11-15 06:53:15 +01:00
42 changed files with 2044 additions and 460 deletions

View File

@@ -236,7 +236,7 @@ typedef void * lv_indev_drv_user_data_t; /*Type of user data in the i
# define LV_LOG_LEVEL LV_LOG_LEVEL_WARN # define LV_LOG_LEVEL LV_LOG_LEVEL_WARN
/* 1: Print the log with 'printf'; /* 1: Print the log with 'printf';
* 0: user need to register a callback with `lv_log_register_print`*/ * 0: user need to register a callback with `lv_log_register_print_cb`*/
# define LV_LOG_PRINTF 0 # define LV_LOG_PRINTF 0
#endif /*LV_USE_LOG*/ #endif /*LV_USE_LOG*/
@@ -344,15 +344,19 @@ typedef void * lv_font_user_data_t;
/*Can break (wrap) texts on these chars*/ /*Can break (wrap) texts on these chars*/
#define LV_TXT_BREAK_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
/* Minimum number of characters of a word to put on a line before a break */ /* If a word is at least this long, will break wherever "prettiest"
#define LV_TXT_LINE_BREAK_LONG_PRE_MIN_LEN 3 * To disable, set to a value <= 0 */
#define LV_TXT_LINE_BREAK_LONG_LEN 12
/* Minimum number of characters of a word to put on a line after a break */ /* Minimum number of characters in a long word to put on a line before a break.
#define LV_TXT_LINE_BREAK_LONG_POST_MIN_LEN 3 * Depends on LV_TXT_LINE_BREAK_LONG_LEN. */
#define LV_TXT_LINE_BREAK_LONG_PRE_MIN_LEN 3
/* Minimum number of characters in a long word to put on a line after a break.
* Depends on LV_TXT_LINE_BREAK_LONG_LEN. */
#define LV_TXT_LINE_BREAK_LONG_POST_MIN_LEN 3
/* Support bidirectional texts. /* Support bidirectional texts.
* Allows mixing Left-to-Right and Right-to-Left texts. * Allows mixing Left-to-Right and Right-to-Left texts.
* The direction will be processed according to the Unicode Bidirectioanl Algorithm: * The direction will be processed according to the Unicode Bidirectioanl Algorithm:

1
lvgl.h
View File

@@ -23,6 +23,7 @@ extern "C" {
#include "src/lv_core/lv_obj.h" #include "src/lv_core/lv_obj.h"
#include "src/lv_core/lv_group.h" #include "src/lv_core/lv_group.h"
#include "src/lv_core/lv_indev.h"
#include "src/lv_core/lv_refr.h" #include "src/lv_core/lv_refr.h"
#include "src/lv_core/lv_disp.h" #include "src/lv_core/lv_disp.h"

View File

@@ -269,9 +269,11 @@
/* Export integer constant to binding. /* Export integer constant to binding.
* This macro is used with constants in the form of LV_<CONST> that * This macro is used with constants in the form of LV_<CONST> that
* should also appear on lvgl binding API such as Micropython * should also appear on lvgl binding API such as Micropython
*
* The default value just prevents a GCC warning.
*/ */
#ifndef LV_EXPORT_CONST_INT #ifndef LV_EXPORT_CONST_INT
#define LV_EXPORT_CONST_INT(int_value) #define LV_EXPORT_CONST_INT(int_value) struct _silence_gcc_warning
#endif #endif
/*=================== /*===================
@@ -314,7 +316,7 @@
#endif #endif
/* 1: Print the log with 'printf'; /* 1: Print the log with 'printf';
* 0: user need to register a callback with `lv_log_register_print`*/ * 0: user need to register a callback with `lv_log_register_print_cb`*/
#ifndef LV_LOG_PRINTF #ifndef LV_LOG_PRINTF
# define LV_LOG_PRINTF 0 # define LV_LOG_PRINTF 0
#endif #endif
@@ -473,21 +475,25 @@
#define LV_TXT_BREAK_CHARS " ,.;:-_" #define LV_TXT_BREAK_CHARS " ,.;:-_"
#endif #endif
/* If a character is at least this long, will break wherever "prettiest" */
/* If a word is at least this long, will break wherever "prettiest"
* To disable, set to a value <= 0 */
#ifndef LV_TXT_LINE_BREAK_LONG_LEN #ifndef LV_TXT_LINE_BREAK_LONG_LEN
#define LV_TXT_LINE_BREAK_LONG_LEN 12 #define LV_TXT_LINE_BREAK_LONG_LEN 12
#endif #endif
/* Minimum number of characters of a word to put on a line before a break */ /* Minimum number of characters in a long word to put on a line before a break.
* Depends on LV_TXT_LINE_BREAK_LONG_LEN. */
#ifndef LV_TXT_LINE_BREAK_LONG_PRE_MIN_LEN #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 #endif
/* Minimum number of characters of a word to put on a line after a break */ /* Minimum number of characters in a long word to put on a line after a break.
* Depends on LV_TXT_LINE_BREAK_LONG_LEN. */
#ifndef LV_TXT_LINE_BREAK_LONG_POST_MIN_LEN #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 #endif
/* Support bidirectional texts. /* Support bidirectional texts.
* Allows mixing Left-to-Right and Right-to-Left texts. * Allows mixing Left-to-Right and Right-to-Left texts.
* The direction will be processed according to the Unicode Bidirectioanl Algorithm: * The direction will be processed according to the Unicode Bidirectioanl Algorithm:

View File

@@ -136,6 +136,8 @@ do { \
#else /* LV_USE_DEBUG == 0 */ #else /* LV_USE_DEBUG == 0 */
#define LV_DEBUG_ASSERT(expr, msg, value) do{}while(0)
#define LV_ASSERT_NULL(p) true #define LV_ASSERT_NULL(p) true
#define LV_ASSERT_MEM(p) true #define LV_ASSERT_MEM(p) true
#define LV_ASSERT_STR(p) true #define LV_ASSERT_STR(p) true

View File

@@ -318,19 +318,19 @@ static void lv_refr_area(const lv_area_t * area_p)
tmp.x2 = 0; tmp.x2 = 0;
tmp.y1 = 0; tmp.y1 = 0;
lv_coord_t y_tmp = max_row - 1; lv_coord_t h_tmp = max_row;
do { do {
tmp.y2 = y_tmp; tmp.y2 = h_tmp - 1;
disp_refr->driver.rounder_cb(&disp_refr->driver, &tmp); disp_refr->driver.rounder_cb(&disp_refr->driver, &tmp);
/*If this height fits into `max_row` then fine*/ /*If this height fits into `max_row` then fine*/
if(lv_area_get_height(&tmp) <= max_row) break; if(lv_area_get_height(&tmp) <= max_row) break;
/*Decrement the height of the area until it fits into `max_row` after rounding*/ /*Decrement the height of the area until it fits into `max_row` after rounding*/
y_tmp--; h_tmp--;
} while(y_tmp != 0); } while(h_tmp > 0);
if(y_tmp == 0) { if(h_tmp <= 0) {
LV_LOG_WARN("Can't set VDB height using the round function. (Wrong round_cb or to " LV_LOG_WARN("Can't set VDB height using the round function. (Wrong round_cb or to "
"small VDB)"); "small VDB)");
return; return;

View File

@@ -212,7 +212,7 @@ void lv_style_anim_set_styles(lv_anim_t * a, lv_style_t * to_anim, const lv_styl
* @param duration duration of the animation in milliseconds * @param duration duration of the animation in milliseconds
* @param delay delay before the animation in milliseconds * @param delay delay before the animation in milliseconds
*/ */
static inline void lv_style_anim_set_time(lv_anim_t * a, uint16_t duration, uint16_t delay) static inline void lv_style_anim_set_time(lv_anim_t * a, uint16_t duration, int16_t delay)
{ {
lv_anim_set_time(a, duration, delay); lv_anim_set_time(a, duration, delay);
} }

View File

@@ -98,7 +98,6 @@ void lv_draw_arc(lv_coord_t center_x, lv_coord_t center_y, uint16_t radius, cons
lv_draw_rect(&round_area, clip_area, &circle_style, LV_OPA_COVER); lv_draw_rect(&round_area, clip_area, &circle_style, LV_OPA_COVER);
} }
} }

View File

@@ -58,7 +58,7 @@ void lv_draw_img(const lv_area_t * coords, const lv_area_t * mask, const void *
if(src == NULL) { if(src == NULL) {
LV_LOG_WARN("Image draw: src is NULL"); LV_LOG_WARN("Image draw: src is NULL");
lv_draw_rect(coords, mask, &lv_style_plain, LV_OPA_COVER); 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; return;
} }
@@ -68,7 +68,7 @@ void lv_draw_img(const lv_area_t * coords, const lv_area_t * mask, const void *
if(res == LV_RES_INV) { if(res == LV_RES_INV) {
LV_LOG_WARN("Image draw error"); LV_LOG_WARN("Image draw error");
lv_draw_rect(coords, mask, &lv_style_plain, LV_OPA_COVER); 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; return;
} }
} }
@@ -205,7 +205,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) { if(cdsc->dec_dsc.error_msg != NULL) {
LV_LOG_WARN("Image draw error"); LV_LOG_WARN("Image draw error");
lv_draw_rect(coords, mask, &lv_style_plain, LV_OPA_COVER); 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. /* The decoder open could open the image and gave the entire uncompressed image.
* Just draw it!*/ * Just draw it!*/

View File

@@ -10,6 +10,7 @@
#include "../lv_misc/lv_math.h" #include "../lv_misc/lv_math.h"
#include "../lv_hal/lv_hal_disp.h" #include "../lv_hal/lv_hal_disp.h"
#include "../lv_core/lv_refr.h" #include "../lv_core/lv_refr.h"
#include "../lv_misc/lv_bidi.h"
/********************* /*********************
* DEFINES * DEFINES
@@ -71,16 +72,13 @@ static const uint8_t bpp4_opa_table[16] = {0, 17, 34, 51, /*Opacity mapping w
*/ */
void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_style_t * style, lv_opa_t opa_scale, 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, 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; const lv_font_t * font = style->text.font;
lv_coord_t w; lv_coord_t w;
/*No need to waste processor time if string is empty*/ /*No need to waste processor time if string is empty*/
if (txt[0] == '\0') if (txt[0] == '\0') return;
{
return;
}
if((flag & LV_TXT_FLAG_EXPAND) == 0) { if((flag & LV_TXT_FLAG_EXPAND) == 0) {
/*Normally use the label's width as width*/ /*Normally use the label's width as width*/
@@ -89,7 +87,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*/ /*If EXAPND is enabled then not limit the text's width to the object's width*/
lv_point_t p; lv_point_t p;
lv_txt_get_size(&p, txt, style->text.font, style->text.letter_space, style->text.line_space, LV_COORD_MAX, 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; w = p.x;
} }
@@ -127,6 +125,7 @@ void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_st
pos.y += hint->y; 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); 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*/ /*Go the first visible line*/
@@ -161,6 +160,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; 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; cmd_state_t cmd_state = CMD_STATE_WAIT;
uint32_t i; uint32_t i;
uint16_t par_start = 0; uint16_t par_start = 0;
@@ -177,12 +188,31 @@ void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_st
} }
/*Write all letter of a line*/ /*Write all letter of a line*/
cmd_state = CMD_STATE_WAIT; cmd_state = CMD_STATE_WAIT;
i = line_start; i = 0;
uint32_t letter; uint32_t letter;
uint32_t letter_next; uint32_t letter_next;
while(i < line_end) { #if LV_USE_BIDI
letter = lv_txt_encoded_next(txt, &i); char *bidi_txt = lv_draw_get_buf(line_end - line_start + 1);
letter_next = lv_txt_encoded_next(&txt[i], NULL); 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*/ /*Handle the re-color command*/
if((flag & LV_TXT_FLAG_RECOLOR) != 0) { if((flag & LV_TXT_FLAG_RECOLOR) != 0) {
@@ -205,7 +235,7 @@ void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_st
/*Get the parameter*/ /*Get the parameter*/
if(i - par_start == LABEL_RECOLOR_PAR_LENGTH + 1) { if(i - par_start == LABEL_RECOLOR_PAR_LENGTH + 1) {
char buf[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'; buf[LABEL_RECOLOR_PAR_LENGTH] = '\0';
int r, g, b; int r, g, b;
r = (hex_char_to_num(buf[0]) << 4) + hex_char_to_num(buf[1]); r = (hex_char_to_num(buf[0]) << 4) + hex_char_to_num(buf[1]);
@@ -227,18 +257,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); letter_w = lv_font_get_glyph_width(font, letter, letter_next);
if(sel) { if(sel_start != 0xFFFF && sel_end != 0xFFFF) {
if(sel->start != 0xFFFF && sel->end != 0xFFFF) { if(logical_char_pos >= sel_start && logical_char_pos < sel_end) {
int char_ind = lv_encoded_get_char_id(txt, i); lv_area_t sel_coords;
/*Do not draw the rectangle on the character at `sel_start`.*/ sel_coords.x1 = pos.x;
if(char_ind > sel->start && char_ind <= sel->end) { sel_coords.y1 = pos.y;
lv_area_t sel_coords; sel_coords.x2 = pos.x + letter_w + style->text.letter_space - 1;
sel_coords.x1 = pos.x; sel_coords.y2 = pos.y + line_height - 1;
sel_coords.y1 = pos.y; lv_draw_rect(&sel_coords, mask, &sel_style, opa);
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);
}
} }
} }
@@ -256,7 +282,7 @@ void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_st
/*Align to middle*/ /*Align to middle*/
if(flag & LV_TXT_FLAG_CENTER) { if(flag & LV_TXT_FLAG_CENTER) {
line_width = 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; pos.x += (lv_area_get_width(coords) - line_width) / 2;
@@ -264,7 +290,7 @@ void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_st
/*Align to the right*/ /*Align to the right*/
else if(flag & LV_TXT_FLAG_RIGHT) { else if(flag & LV_TXT_FLAG_RIGHT) {
line_width = 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; pos.x += lv_area_get_width(coords) - line_width;
} }
@@ -684,13 +710,13 @@ static uint8_t hex_char_to_num(char hex)
if(hex >= 'a') hex -= 'a' - 'A'; /*Convert to upper case*/ if(hex >= 'a') hex -= 'a' - 'A'; /*Convert to upper case*/
switch(hex) { switch(hex) {
case 'A': result = 10; break; case 'A': result = 10; break;
case 'B': result = 11; break; case 'B': result = 11; break;
case 'C': result = 12; break; case 'C': result = 12; break;
case 'D': result = 13; break; case 'D': result = 13; break;
case 'E': result = 14; break; case 'E': result = 14; break;
case 'F': result = 15; break; case 'F': result = 15; break;
default: result = 0; break; default: result = 0; break;
} }
} }

View File

@@ -14,6 +14,7 @@ extern "C" {
* INCLUDES * INCLUDES
*********************/ *********************/
#include "lv_draw.h" #include "lv_draw.h"
#include "../lv_misc/lv_bidi.h"
/********************* /*********************
* DEFINES * DEFINES
@@ -62,10 +63,11 @@ typedef struct {
* @param flag settings for the text from 'txt_flag_t' enum * @param flag settings for the text from 'txt_flag_t' enum
* @param offset text offset in x and y direction (NULL if unused) * @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 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, 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, 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 * MACROS

1133
src/lv_font/lv_font_heb_16.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -129,10 +129,10 @@ static inline void lv_anim_set_exec_cb(lv_anim_t * a, void * var, lv_anim_exec_x
* @param duration duration of the animation in milliseconds * @param duration duration of the animation in milliseconds
* @param delay delay before the animation in milliseconds * @param delay delay before the animation in milliseconds
*/ */
static inline void lv_anim_set_time(lv_anim_t * a, uint16_t duration, uint16_t delay) static inline void lv_anim_set_time(lv_anim_t * a, uint16_t duration, int16_t delay)
{ {
a->time = duration; a->time = duration;
a->act_time = -delay; a->act_time = (int16_t)(-delay);
} }
/** /**

View File

@@ -192,6 +192,19 @@ bool lv_area_is_in(const lv_area_t * ain_p, const lv_area_t * aholder_p)
return is_in; return is_in;
} }
/**
* Increment or decrement an area's size by a single amount
* @param a_p pointer to an area to grow
* @param amount amount to increment the area, or negative to decrement
*/
void lv_area_increment(lv_area_t * a_p, const lv_coord_t amount)
{
a_p->x1 -= amount;
a_p->y1 -= amount;
a_p->x2 += amount;
a_p->y2 += amount;
}
/********************** /**********************
* STATIC FUNCTIONS * STATIC FUNCTIONS
**********************/ **********************/

View File

@@ -85,7 +85,7 @@ inline static void lv_area_copy(lv_area_t * dest, const lv_area_t * src)
*/ */
static inline lv_coord_t lv_area_get_width(const lv_area_t * area_p) static inline lv_coord_t lv_area_get_width(const lv_area_t * area_p)
{ {
return area_p->x2 - area_p->x1 + 1; return (lv_coord_t)(area_p->x2 - area_p->x1 + 1);
} }
/** /**
@@ -95,7 +95,7 @@ static inline lv_coord_t lv_area_get_width(const lv_area_t * area_p)
*/ */
static inline lv_coord_t lv_area_get_height(const lv_area_t * area_p) static inline lv_coord_t lv_area_get_height(const lv_area_t * area_p)
{ {
return area_p->y2 - area_p->y1 + 1; return (lv_coord_t)(area_p->y2 - area_p->y1 + 1);
} }
/** /**
@@ -168,6 +168,13 @@ bool lv_area_is_on(const lv_area_t * a1_p, const lv_area_t * a2_p);
*/ */
bool lv_area_is_in(const lv_area_t * ain_p, const lv_area_t * aholder_p); bool lv_area_is_in(const lv_area_t * ain_p, const lv_area_t * aholder_p);
/**
* Increment or decrement an area's size by a single amount
* @param a_p pointer to an area to grow
* @param amount amount to increment the area, or negative to decrement
*/
void lv_area_increment(lv_area_t * a_p, const lv_coord_t amount);
/********************** /**********************
* MACROS * MACROS
**********************/ **********************/

View File

@@ -6,32 +6,49 @@
/********************* /*********************
* INCLUDES * INCLUDES
*********************/ *********************/
#include "lv_bidi.h"
#include <stddef.h> #include <stddef.h>
#include "lv_bidi.h"
#include "lv_txt.h" #include "lv_txt.h"
#include "../lv_draw/lv_draw.h"
#if LV_USE_BIDI #if LV_USE_BIDI
/********************* /*********************
* DEFINES * 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 * TYPEDEFS
**********************/ **********************/
typedef struct
{
uint32_t bracklet_pos;
lv_bidi_dir_t dir;
}bracket_stack_t;
/********************** /**********************
* STATIC PROTOTYPES * STATIC PROTOTYPES
**********************/ **********************/
static void process_paragraph(const char * str_in, char * str_out, uint32_t len, lv_bidi_dir_t base_dir); 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 uint32_t get_next_paragraph(const char * txt); 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 lv_bidi_dir_t get_next_run(const char * txt, lv_bidi_dir_t base_dir, uint32_t * len);
static void rtl_reverse(char * dest, const char * src, uint32_t len);
static uint32_t char_change_to_pair(uint32_t letter); 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 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 * MACROS
@@ -43,7 +60,6 @@ static uint32_t char_change_to_pair(uint32_t letter);
void lv_bidi_process(const char * str_in, char * str_out, lv_bidi_dir_t base_dir) 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); if(base_dir == LV_BIDI_DIR_AUTO) base_dir = lv_bidi_detect_base_dir(str_in);
uint32_t par_start = 0; uint32_t par_start = 0;
@@ -55,8 +71,8 @@ void lv_bidi_process(const char * str_in, char * str_out, lv_bidi_dir_t base_dir
} }
while(str_in[par_start] != '\0') { while(str_in[par_start] != '\0') {
par_len = get_next_paragraph(&str_in[par_start]); par_len = lv_bidi_get_next_paragraph(&str_in[par_start]);
process_paragraph(&str_in[par_start], &str_out[par_start], par_len, base_dir); lv_bidi_process_paragraph(&str_in[par_start], &str_out[par_start], par_len, base_dir, NULL, 0);
par_start += par_len; par_start += par_len;
while(str_in[par_start] == '\n' || str_in[par_start] == '\r') { while(str_in[par_start] == '\n' || str_in[par_start] == '\r') {
@@ -121,7 +137,7 @@ bool lv_bidi_letter_is_rtl(uint32_t letter)
bool lv_bidi_letter_is_neutral(uint32_t letter) bool lv_bidi_letter_is_neutral(uint32_t letter)
{ {
uint16_t i; uint16_t i;
static const char neutrals[] = " \t\n\r.,:;'\"`!?%/\\=()[]{}<>@#&$|"; static const char neutrals[] = " \t\n\r.,:;'\"`!?%/\\-=()[]{}<>@#&$|";
for(i = 0; neutrals[i] != '\0'; i++) { for(i = 0; neutrals[i] != '\0'; i++) {
if(letter == (uint32_t)neutrals[i]) return true; if(letter == (uint32_t)neutrals[i]) return true;
} }
@@ -129,62 +145,120 @@ bool lv_bidi_letter_is_neutral(uint32_t letter)
return false; 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)
* STATIC FUNCTIONS {
**********************/ 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;
}
static void process_paragraph(const char * str_in, char * str_out, uint32_t len, 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 run_len = 0; uint32_t run_len = 0;
lv_bidi_dir_t run_dir; lv_bidi_dir_t run_dir;
uint32_t rd = 0; uint32_t rd = 0;
uint32_t wr; uint32_t wr;
if(base_dir == LV_BIDI_DIR_RTL) wr = len; uint16_t pos_conv_run_len = 0;
else wr = 0; uint16_t pos_conv_rd = 0;
uint16_t pos_conv_wr;
str_out[len] = '\0'; 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; lv_bidi_dir_t dir = base_dir;
/*Empty the bracket stack*/
br_stack_p = 0;
/*Process neutral chars in the beginning*/ /*Process neutral chars in the beginning*/
while(rd < len) { while(rd < len) {
uint32_t letter = lv_txt_encoded_next(str_in, &rd); uint32_t letter = lv_txt_encoded_next(str_in, &rd);
pos_conv_rd++;
dir = lv_bidi_get_letter_dir(letter); 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(dir != LV_BIDI_DIR_NEUTRAL && dir != LV_BIDI_DIR_WEAK) break;
} }
if(rd && str_in[rd] != '\0') lv_txt_encoded_prev(str_in, &rd); if(rd && str_in[rd] != '\0') {
lv_txt_encoded_prev(str_in, &rd);
pos_conv_rd--;
}
if(rd) { if(rd) {
if(base_dir == LV_BIDI_DIR_LTR) { if(base_dir == LV_BIDI_DIR_LTR) {
memcpy(&str_out[wr], str_in, rd); if (str_out) {
wr += rd; 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 { } else {
wr -= rd; wr -= rd;
rtl_reverse(&str_out[wr], str_in, 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*/ /*Get and process the runs*/
while(rd < len) {
run_dir = get_next_run(&str_in[rd], base_dir, &run_len); 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(base_dir == LV_BIDI_DIR_LTR) {
if(run_dir == LV_BIDI_DIR_LTR) memcpy(&str_out[wr], &str_in[rd], run_len); if(run_dir == LV_BIDI_DIR_LTR) {
else rtl_reverse(&str_out[wr], &str_in[rd], run_len); if (str_out) memcpy(&str_out[wr], &str_in[rd], run_len);
if (pos_conv_out) fill_pos_conv(&pos_conv_out[pos_conv_wr], pos_conv_run_len, pos_conv_rd);
}
else rtl_reverse(str_out? &str_out[wr]: NULL, &str_in[rd], run_len, pos_conv_out? &pos_conv_out[pos_conv_wr] : NULL, pos_conv_rd, pos_conv_run_len);
wr += run_len; wr += run_len;
pos_conv_wr += pos_conv_run_len;
} else { } else {
wr -= run_len; wr -= run_len;
if(run_dir == LV_BIDI_DIR_LTR) memcpy(&str_out[wr], &str_in[rd], run_len); pos_conv_wr -= pos_conv_run_len;
else rtl_reverse(&str_out[wr], &str_in[rd], 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; rd += run_len;
pos_conv_rd += pos_conv_run_len;
} }
} }
static uint32_t get_next_paragraph(const char * txt) uint32_t lv_bidi_get_next_paragraph(const char * txt)
{ {
uint32_t i = 0; uint32_t i = 0;
@@ -197,20 +271,53 @@ static uint32_t get_next_paragraph(const char * txt)
return i; return i;
} }
static lv_bidi_dir_t get_next_run(const char * txt, lv_bidi_dir_t base_dir, uint32_t * len) /**********************
* 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 i = 0;
uint32_t letter; uint32_t letter;
uint16_t pos_conv_i = 0;
letter = lv_txt_encoded_next(txt, NULL); letter = lv_txt_encoded_next(txt, NULL);
lv_bidi_dir_t dir = lv_bidi_get_letter_dir(letter); 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*/ /*Find the first strong char. Skip the neutrals*/
while(dir == LV_BIDI_DIR_NEUTRAL || dir == LV_BIDI_DIR_WEAK) { while(dir == LV_BIDI_DIR_NEUTRAL || dir == LV_BIDI_DIR_WEAK) {
letter = lv_txt_encoded_next(txt, &i); letter = lv_txt_encoded_next(txt, &i);
pos_conv_i++;
dir = lv_bidi_get_letter_dir(letter); dir = lv_bidi_get_letter_dir(letter);
if(txt[i] == '\0' || txt[i] == '\n' || txt[i] == '\r') { 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; *len = i;
*pos_conv_len = pos_conv_i;
return base_dir; return base_dir;
} }
} }
@@ -219,83 +326,119 @@ static lv_bidi_dir_t get_next_run(const char * txt, lv_bidi_dir_t base_dir, uint
uint32_t i_prev = i; uint32_t i_prev = i;
uint32_t i_last_strong = 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*/ /*Find the next char which has different direction*/
lv_bidi_dir_t next_dir = base_dir; lv_bidi_dir_t next_dir = base_dir;
while(txt[i] != '\0'&& txt[i] != '\n' && txt[i] != '\r') { while(i_prev < max_len && txt[i] != '\0' && txt[i] != '\n' && txt[i] != '\r') {
letter = lv_txt_encoded_next(txt, &i); letter = lv_txt_encoded_next(txt, &i);
pos_conv_i++;
next_dir = lv_bidi_get_letter_dir(letter); 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?*/ /*New dir found?*/
if((next_dir == LV_BIDI_DIR_RTL || next_dir == LV_BIDI_DIR_LTR) && next_dir != run_dir) { if((next_dir == LV_BIDI_DIR_RTL || next_dir == LV_BIDI_DIR_LTR) && next_dir != run_dir) {
/*Include neutrals if `run_dir == base_dir` */ /*Include neutrals if `run_dir == base_dir` */
if(run_dir == base_dir) *len = i_prev; if(run_dir == base_dir) {
*len = i_prev;
*pos_conv_len = pos_conv_i_prev;
}
/*Exclude neutrals if `run_dir != base_dir` */ /*Exclude neutrals if `run_dir != base_dir` */
else *len = i_last_strong; else {
*len = i_last_strong;
*pos_conv_len = pos_conv_i_last_strong;
}
return run_dir; return run_dir;
} }
if(next_dir != LV_BIDI_DIR_NEUTRAL) i_last_strong = i; if(next_dir != LV_BIDI_DIR_NEUTRAL) {
i_last_strong = i;
pos_conv_i_last_strong = pos_conv_i;
}
i_prev = i; i_prev = i;
pos_conv_i_prev = pos_conv_i;
} }
/*Handle end of of string. Apply `base_dir` on trailing neutrals*/ /*Handle end of of string. Apply `base_dir` on trailing neutrals*/
/*Include neutrals if `run_dir == base_dir` */ /*Include neutrals if `run_dir == base_dir` */
if(run_dir == base_dir) *len = i_prev; if(run_dir == base_dir) {
*len = i_prev;
*pos_conv_len = pos_conv_i_prev;
}
/*Exclude neutrals if `run_dir != base_dir` */ /*Exclude neutrals if `run_dir != base_dir` */
else *len = i_last_strong; else {
*len = i_last_strong;
*pos_conv_len = pos_conv_i_last_strong;
}
return run_dir; return run_dir;
} }
static void rtl_reverse(char * dest, const char * src, uint32_t 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)
{ {
uint32_t i = len; uint32_t i = len;
uint32_t wr = 0; uint32_t wr = 0;
uint16_t pos_conv_i = pos_conv_len;
uint16_t pos_conv_wr = 0;
while(i) { while(i) {
uint32_t letter = lv_txt_encoded_prev(src, &i); uint32_t letter = lv_txt_encoded_prev(src, &i);
uint16_t pos_conv_letter = --pos_conv_i;
/*Keep weak letters (numbers) as LTR*/ /*Keep weak letters (numbers) as LTR*/
if(lv_bidi_letter_is_weak(letter)) { if(lv_bidi_letter_is_weak(letter)) {
uint32_t last_weak = i; uint32_t last_weak = i;
uint32_t first_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) { while(i) {
letter = lv_txt_encoded_prev(src, &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*/ /*No need to call `char_change_to_pair` because there not such chars here*/
/*Finish on non-weak char */ /*Finish on non-weak char */
/*but treat number and currency related chars as weak*/ /*but treat number and currency related chars as weak*/
if(lv_bidi_letter_is_weak(letter) == false && letter != '.' && letter != ',' && letter != '$') { if (lv_bidi_letter_is_weak(letter) == false && letter != '.' && letter != ',' && letter != '$' && letter != '%') {
lv_txt_encoded_next(src, &i); /*Rewind one letter*/ lv_txt_encoded_next(src, &i); /*Rewind one letter*/
pos_conv_i++;
first_weak = i; first_weak = i;
pos_conv_first_weak = pos_conv_i;
break; break;
} }
} }
if(i == 0) first_weak = 0; if(i == 0) {
first_weak = 0;
pos_conv_first_weak = 0;
}
memcpy(&dest[wr], &src[first_weak], last_weak - first_weak + 1); 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; wr += last_weak - first_weak + 1;
pos_conv_wr += pos_conv_last_weak - pos_conv_first_weak + 1;
} }
/*Simply store in reversed order*/ /*Simply store in reversed order*/
else { else {
uint32_t letter_size = lv_txt_encoded_size((const char *)&src[i]); uint32_t letter_size = lv_txt_encoded_size((const char *)&src[i]);
/*Swap arithmetical symbols*/ /*Swap arithmetical symbols*/
if(letter_size == 1) { if(letter_size == 1) {
uint32_t new_letter = letter = char_change_to_pair(letter); uint32_t new_letter = letter = char_change_to_pair(letter);
dest[wr] = (uint8_t)new_letter; if (dest) dest[wr] = (uint8_t)new_letter;
wr += 1; 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*/ /*Just store the letter*/
else { else {
memcpy(&dest[wr], &src[i], letter_size); 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; wr += letter_size;
pos_conv_wr++;
} }
} }
} }
@@ -303,19 +446,95 @@ static void rtl_reverse(char * dest, const char * src, uint32_t len)
static uint32_t char_change_to_pair(uint32_t letter) static uint32_t char_change_to_pair(uint32_t letter)
{ {
static uint8_t left[] = {"<({["};
static uint8_t right[] = {">)}]"};
uint8_t i; uint8_t i;
for(i = 0; left[i] != '\0'; i++) { for(i = 0; bracket_left[i] != '\0'; i++) {
if(letter == left[i]) return right[i]; if(letter == bracket_left[i]) return bracket_right[i];
} }
for(i = 0; right[i] != '\0'; i++) { for(i = 0; bracket_right[i] != '\0'; i++) {
if(letter == right[i]) return left[i]; if(letter == bracket_right[i]) return bracket_left[i];
} }
return letter; 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*/ #endif /*LV_USE_BIDI*/

View File

@@ -53,11 +53,15 @@ typedef uint8_t lv_bidi_dir_t;
#if LV_USE_BIDI #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(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_detect_base_dir(const char * txt);
lv_bidi_dir_t lv_bidi_get_letter_dir(uint32_t letter); lv_bidi_dir_t lv_bidi_get_letter_dir(uint32_t letter);
bool lv_bidi_letter_is_weak(uint32_t letter); bool lv_bidi_letter_is_weak(uint32_t letter);
bool lv_bidi_letter_is_rtl(uint32_t letter); bool lv_bidi_letter_is_rtl(uint32_t letter);
bool lv_bidi_letter_is_neutral(uint32_t letter); bool lv_bidi_letter_is_neutral(uint32_t letter);
uint16_t lv_bidi_get_logical_pos(const char * str_in, 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 * MACROS

View File

@@ -7,6 +7,7 @@
* INCLUDES * INCLUDES
*********************/ *********************/
#include "lv_color.h" #include "lv_color.h"
#include "lv_math.h"
/********************* /*********************
* DEFINES * DEFINES
@@ -105,39 +106,66 @@ lv_color_t lv_color_hsv_to_rgb(uint16_t h, uint8_t s, uint8_t v)
} }
/** /**
* Convert an RGB color to HSV * Convert a 32-bit RGB color to HSV
* @param r red * @param r8 8-bit red
* @param g green * @param g8 8-bit green
* @param b blue * @param b8 8-bit blue
* @return the given RGB color n HSV * @return the given RGB color in HSV
*/ */
lv_color_hsv_t lv_color_rgb_to_hsv(uint8_t r, uint8_t g, uint8_t b) lv_color_hsv_t lv_color_rgb_to_hsv(uint8_t r8, uint8_t g8, uint8_t b8)
{ {
uint16_t r = ((uint32_t)r8 << 10) / 255;
uint16_t g = ((uint32_t)g8 << 10) / 255;
uint16_t b = ((uint32_t)b8 << 10) / 255;
uint16_t rgbMin = r < g ? (r < b ? r : b) : (g < b ? g : b);
uint16_t rgbMax = r > g ? (r > b ? r : b) : (g > b ? g : b);
lv_color_hsv_t hsv; lv_color_hsv_t hsv;
uint8_t rgbMin, rgbMax;
rgbMin = r < g ? (r < b ? r : b) : (g < b ? g : b); // https://en.wikipedia.org/wiki/HSL_and_HSV#Lightness
rgbMax = r > g ? (r > b ? r : b) : (g > b ? g : b); hsv.v = (100 * rgbMax) >> 10;
hsv.v = rgbMax; int32_t delta = rgbMax - rgbMin;
if(hsv.v == 0) { if (LV_MATH_ABS(delta) < 3) {
hsv.h = 0; hsv.h = 0;
hsv.s = 0; hsv.s = 0;
return hsv; return hsv;
} }
hsv.s = 255 * (long)(rgbMax - rgbMin) / hsv.v; // https://en.wikipedia.org/wiki/HSL_and_HSV#Saturation
if(hsv.s == 0) { hsv.s = 100 * delta / rgbMax;
if(hsv.s < 3) {
hsv.h = 0; hsv.h = 0;
return hsv; return hsv;
} }
// https://en.wikipedia.org/wiki/HSL_and_HSV#Hue_and_chroma
int32_t h;
if(rgbMax == r) if(rgbMax == r)
hsv.h = 0 + 43 * (g - b) / (rgbMax - rgbMin); h = (((g - b) << 10) / delta) + (g < b ? (6 << 10) : 0); // between yellow & magenta
else if(rgbMax == g) else if(rgbMax == g)
hsv.h = 85 + 43 * (b - r) / (rgbMax - rgbMin); h = (((b - r) << 10) / delta) + (2 << 10); // between cyan & yellow
else if(rgbMax == b)
h = (((r - g) << 10) / delta) + (4 << 10); // between magenta & cyan
else else
hsv.h = 171 + 43 * (r - g) / (rgbMax - rgbMin); h = 0;
h *= 60;
h >>= 10;
if (h < 0) h += 360;
hsv.h = h;
return hsv; return hsv;
} }
/**
* Convert a color to HSV
* @param color color
* @return the given color in HSV
*/
lv_color_hsv_t lv_color_to_hsv(lv_color_t color)
{
lv_color32_t color32;
color32.full = lv_color_to32(color);
return lv_color_rgb_to_hsv(color32.ch.red, color32.ch.green, color32.ch.blue);
}

View File

@@ -90,6 +90,110 @@ enum {
#error "Invalid LV_COLOR_DEPTH in lv_conf.h! Set it to 1, 8, 16 or 32!" #error "Invalid LV_COLOR_DEPTH in lv_conf.h! Set it to 1, 8, 16 or 32!"
#endif #endif
/*---------------------------------------
* Macros for all existing color depths
* to set/get values of the color channels
*------------------------------------------*/
# define LV_COLOR_SET_R1(c, v) (c).ch.red = (uint8_t)((v) & 0x1);
# define LV_COLOR_SET_G1(c, v) (c).ch.green = (uint8_t)((v) & 0x1);
# define LV_COLOR_SET_B1(c, v) (c).ch.blue = (uint8_t)((v) & 0x1);
# define LV_COLOR_SET_A1(c, v)
# define LV_COLOR_GET_R1(c) (c).ch.red
# define LV_COLOR_GET_G1(c) (c).ch.green
# define LV_COLOR_GET_B1(c) (c).ch.blue
# define LV_COLOR_GET_A1(c) 1
# define LV_COLOR_SET_R8(c, v) (c).ch.red = (uint8_t)((v) & 0x7);
# define LV_COLOR_SET_G8(c, v) (c).ch.green = (uint8_t)((v) & 0x7);
# define LV_COLOR_SET_B8(c, v) (c).ch.blue = (uint8_t)((v) & 0x3);
# define LV_COLOR_SET_A8(c, v) do {} while(0)
# define LV_COLOR_GET_R8(c) (c).ch.red
# define LV_COLOR_GET_G8(c) (c).ch.green
# define LV_COLOR_GET_B8(c) (c).ch.blue
# define LV_COLOR_GET_A8(c) 0xFF
# define LV_COLOR_SET_R16(c, v) (c).ch.red = (uint16_t)((v) & 0x1F);
# define LV_COLOR_SET_G16(c, v) (c).ch.green = (uint16_t)((v) & 0x3F);
# define LV_COLOR_SET_G16_SWAP(c, v) {(c).ch.green_h = (uint16_t)(((v) >> 3) & 0x7); (c).ch.green_l = (uint16_t)((v) & 0x7);}
# define LV_COLOR_SET_B16(c, v) (c).ch.blue = (uint16_t)((v) & 0x1F);
# define LV_COLOR_SET_A16(c, v) do {} while(0)
# define LV_COLOR_GET_R16(c) (c).ch.red
# define LV_COLOR_GET_G16(c) (c).ch.green
# define LV_COLOR_GET_G16_SWAP(c) (((c).ch.green_h << 3) + (c).ch.green_l)
# define LV_COLOR_GET_B16(c) (c).ch.blue
# define LV_COLOR_GET_A16(c) 0xFF
# define LV_COLOR_SET_R32(c, v) (c).ch.red = (uint32_t)((v) & 0xFF);
# define LV_COLOR_SET_G32(c, v) (c).ch.green = (uint32_t)((v) & 0xFF);
# define LV_COLOR_SET_B32(c, v) (c).ch.blue = (uint32_t)((v) & 0xFF);
# define LV_COLOR_SET_A32(c, v) (c).ch.alpha = (uint32_t)((v) & 0xFF);
# define LV_COLOR_GET_R32(c) (c).ch.red
# define LV_COLOR_GET_G32(c) (c).ch.green
# define LV_COLOR_GET_B32(c) (c).ch.blue
# define LV_COLOR_GET_A32(c) (c).ch.alpha
/*---------------------------------------
* Macros for the current color depth
* to set/get values of the color channels
*------------------------------------------*/
#if LV_COLOR_DEPTH == 1
# define LV_COLOR_SET_R(c, v) LV_COLOR_SET_R1(c,v)
# define LV_COLOR_SET_G(c, v) LV_COLOR_SET_G1(c,v)
# define LV_COLOR_SET_B(c, v) LV_COLOR_SET_B1(c,v)
# define LV_COLOR_SET_A(c, v) LV_COLOR_SET_A1(c,v)
# define LV_COLOR_GET_R(c) LV_COLOR_GET_R1(c)
# define LV_COLOR_GET_G(c) LV_COLOR_GET_G1(c)
# define LV_COLOR_GET_B(c) LV_COLOR_GET_B1(c)
# define LV_COLOR_GET_A(c) LV_COLOR_GET_A1(c)
#elif LV_COLOR_DEPTH == 8
# define LV_COLOR_SET_R(c, v) LV_COLOR_SET_R8(c,v)
# define LV_COLOR_SET_G(c, v) LV_COLOR_SET_G8(c,v)
# define LV_COLOR_SET_B(c, v) LV_COLOR_SET_B8(c,v)
# define LV_COLOR_SET_A(c, v) LV_COLOR_SET_A8(c,v)
# define LV_COLOR_GET_R(c) LV_COLOR_GET_R8(c)
# define LV_COLOR_GET_G(c) LV_COLOR_GET_G8(c)
# define LV_COLOR_GET_B(c) LV_COLOR_GET_B8(c)
# define LV_COLOR_GET_A(c) LV_COLOR_GET_A8(c)
#elif LV_COLOR_DEPTH == 16
# define LV_COLOR_SET_R(c, v) LV_COLOR_SET_R16(c,v)
# if LV_COLOR_16_SWAP == 0
# define LV_COLOR_SET_G(c, v) LV_COLOR_SET_G16(c,v)
# else
# define LV_COLOR_SET_G(c, v) LV_COLOR_SET_G16_SWAP(c,v)
# endif
# define LV_COLOR_SET_B(c, v) LV_COLOR_SET_B16(c,v)
# define LV_COLOR_SET_A(c, v) LV_COLOR_SET_A16(c,v)
# define LV_COLOR_GET_R(c) LV_COLOR_GET_R16(c)
# if LV_COLOR_16_SWAP == 0
# define LV_COLOR_GET_G(c) LV_COLOR_GET_G16(c)
# else
# define LV_COLOR_GET_G(c) LV_COLOR_GET_G16_SWAP(c)
# endif
# define LV_COLOR_GET_B(c) LV_COLOR_GET_B16(c)
# define LV_COLOR_GET_A(c) LV_COLOR_GET_A16(c)
#elif LV_COLOR_DEPTH == 32
# define LV_COLOR_SET_R(c, v) LV_COLOR_SET_R32(c,v)
# define LV_COLOR_SET_G(c, v) LV_COLOR_SET_G32(c,v)
# define LV_COLOR_SET_B(c, v) LV_COLOR_SET_B32(c,v)
# define LV_COLOR_SET_A(c, v) LV_COLOR_SET_A32(c,v)
# define LV_COLOR_GET_R(c) LV_COLOR_GET_R32(c)
# define LV_COLOR_GET_G(c) LV_COLOR_GET_G32(c)
# define LV_COLOR_GET_B(c) LV_COLOR_GET_B32(c)
# define LV_COLOR_GET_A(c) LV_COLOR_GET_A32(c)
#endif
/********************** /**********************
* TYPEDEFS * TYPEDEFS
**********************/ **********************/
@@ -194,24 +298,19 @@ static inline uint8_t lv_color_to1(lv_color_t color)
#if LV_COLOR_DEPTH == 1 #if LV_COLOR_DEPTH == 1
return color.full; return color.full;
#elif LV_COLOR_DEPTH == 8 #elif LV_COLOR_DEPTH == 8
if((color.ch.red & 0x4) || (color.ch.green & 0x4) || (color.ch.blue & 0x2)) { if((LV_COLOR_GET_R(color) & 0x4) || (LV_COLOR_GET_G(color) & 0x4) || (LV_COLOR_GET_B(color) & 0x2)) {
return 1; return 1;
} else { } else {
return 0; return 0;
} }
#elif LV_COLOR_DEPTH == 16 #elif LV_COLOR_DEPTH == 16
#if LV_COLOR_16_SWAP == 0 if((LV_COLOR_GET_R(color) & 0x10) || (LV_COLOR_GET_G(color) & 0x20) || (LV_COLOR_GET_B(color) & 0x10)) {
if((color.ch.red & 0x10) || (color.ch.green & 0x20) || (color.ch.blue & 0x10)) {
return 1; return 1;
#else
if((color.ch.red & 0x10) || (color.ch.green_h & 0x20) || (color.ch.blue & 0x10)) {
return 1;
#endif
} else { } else {
return 0; return 0;
} }
#elif LV_COLOR_DEPTH == 32 #elif LV_COLOR_DEPTH == 32
if((color.ch.red & 0x80) || (color.ch.green & 0x80) || (color.ch.blue & 0x80)) { if((LV_COLOR_GET_R(color) & 0x80) || (LV_COLOR_GET_G(color) & 0x80) || (LV_COLOR_GET_B(color) & 0x80)) {
return 1; return 1;
} else { } else {
return 0; return 0;
@@ -229,31 +328,23 @@ static inline uint8_t lv_color_to8(lv_color_t color)
#elif LV_COLOR_DEPTH == 8 #elif LV_COLOR_DEPTH == 8
return color.full; return color.full;
#elif LV_COLOR_DEPTH == 16 #elif LV_COLOR_DEPTH == 16
#if LV_COLOR_16_SWAP == 0
lv_color8_t ret; lv_color8_t ret;
ret.ch.red = color.ch.red >> 2; /* 5 - 3 = 2*/ LV_COLOR_SET_R8(ret, LV_COLOR_GET_R(color) >> 2); /* 5 - 3 = 2*/
ret.ch.green = color.ch.green >> 3; /* 6 - 3 = 3*/ LV_COLOR_SET_G8(ret, LV_COLOR_GET_G(color) >> 3); /* 6 - 3 = 3*/
ret.ch.blue = color.ch.blue >> 3; /* 5 - 2 = 3*/ LV_COLOR_SET_B8(ret, LV_COLOR_GET_B(color) >> 3); /* 5 - 2 = 3*/
return ret.full; return ret.full;
#else
lv_color8_t ret;
ret.ch.red = color.ch.red >> 2; /* 5 - 3 = 2*/
ret.ch.green = color.ch.green_h; /* 6 - 3 = 3*/
ret.ch.blue = color.ch.blue >> 3; /* 5 - 2 = 3*/
return ret.full;
#endif
#elif LV_COLOR_DEPTH == 32 #elif LV_COLOR_DEPTH == 32
lv_color8_t ret; lv_color8_t ret;
ret.ch.red = color.ch.red >> 5; /* 8 - 3 = 5*/ LV_COLOR_SET_R8(ret, LV_COLOR_GET_R(color) >> 5); /* 8 - 3 = 5*/
ret.ch.green = color.ch.green >> 5; /* 8 - 3 = 5*/ LV_COLOR_SET_G8(ret, LV_COLOR_GET_G(color) >> 5); /* 8 - 3 = 5*/
ret.ch.blue = color.ch.blue >> 6; /* 8 - 2 = 6*/ LV_COLOR_SET_B8(ret, LV_COLOR_GET_B(color) >> 6); /* 8 - 2 = 6*/
return ret.full; return ret.full;
#endif #endif
} }
static inline uint16_t lv_color_to16(lv_color_t color) static inline uint16_t lv_color_to16(lv_color_t color)
{ {
#if LV_COLOR_DEPTH == 1 #if LV_COLOR_DEPTH == 1
if(color.full == 0) if(color.full == 0)
return 0; return 0;
@@ -261,34 +352,30 @@ static inline uint16_t lv_color_to16(lv_color_t color)
return 0xFFFF; return 0xFFFF;
#elif LV_COLOR_DEPTH == 8 #elif LV_COLOR_DEPTH == 8
lv_color16_t ret; lv_color16_t ret;
LV_COLOR_SET_R16(ret, LV_COLOR_GET_R(color) * 4); /*(2^5 - 1)/(2^3 - 1) = 31/7 = 4*/
#if LV_COLOR_16_SWAP == 0 #if LV_COLOR_16_SWAP == 0
ret.ch.red = color.ch.red * 4; /*(2^5 - 1)/(2^3 - 1) = 31/7 = 4*/ LV_COLOR_SET_G16(ret, LV_COLOR_GET_G(color) * 9); /*(2^6 - 1)/(2^3 - 1) = 63/7 = 9*/
ret.ch.green = color.ch.green * 9; /*(2^6 - 1)/(2^3 - 1) = 63/7 = 9*/
ret.ch.blue = color.ch.blue * 10; /*(2^5 - 1)/(2^2 - 1) = 31/3 = 10*/
#else #else
ret.red = color.ch.red * 4; LV_COLOR_SET_G16_SWAP(ret, (LV_COLOR_GET_G(color) * 9)); /*(2^6 - 1)/(2^3 - 1) = 63/7 = 9*/
uint8_t g_tmp = color.ch.green * 9;
ret.ch.green_h = (g_tmp & 0x1F) >> 3;
ret.ch.green_l = g_tmp & 0x07;
ret.ch.blue = color.ch.blue * 10;
#endif #endif
LV_COLOR_SET_B16(ret, LV_COLOR_GET_B(color) * 10); /*(2^5 - 1)/(2^2 - 1) = 31/3 = 10*/
return ret.full; return ret.full;
#elif LV_COLOR_DEPTH == 16 #elif LV_COLOR_DEPTH == 16
return color.full; return color.full;
#elif LV_COLOR_DEPTH == 32 #elif LV_COLOR_DEPTH == 32
lv_color16_t ret; lv_color16_t ret;
LV_COLOR_SET_R16(ret, LV_COLOR_GET_R(color) >> 3); /* 8 - 5 = 3*/
#if LV_COLOR_16_SWAP == 0 #if LV_COLOR_16_SWAP == 0
ret.ch.red = color.ch.red >> 3; /* 8 - 5 = 3*/ LV_COLOR_SET_G16(ret, LV_COLOR_GET_G(color) >> 2); /* 8 - 6 = 2*/
ret.ch.green = color.ch.green >> 2; /* 8 - 6 = 2*/
ret.ch.blue = color.ch.blue >> 3; /* 8 - 5 = 3*/
#else #else
ret.ch.red = color.ch.red >> 3; LV_COLOR_SET_G16_SWAP(ret, ret.ch.green_h = (LV_COLOR_GET_G(color) >> 2); /*(2^6 - 1)/(2^3 - 1) = 63/7 = 9*/
ret.ch.green_h = (color.ch.green & 0xE0) >> 5;
ret.ch.green_l = (color.ch.green & 0x1C) >> 2;
ret.ch.blue = color.ch.blue >> 3;
#endif #endif
LV_COLOR_SET_B16(ret, LV_COLOR_GET_B(color) >> 3); /* 8 - 5 = 3*/
return ret.full; return ret.full;
#endif #endif
return 0;
} }
static inline uint32_t lv_color_to32(lv_color_t color) static inline uint32_t lv_color_to32(lv_color_t color)
@@ -300,10 +387,10 @@ static inline uint32_t lv_color_to32(lv_color_t color)
return 0xFFFFFFFF; return 0xFFFFFFFF;
#elif LV_COLOR_DEPTH == 8 #elif LV_COLOR_DEPTH == 8
lv_color32_t ret; lv_color32_t ret;
ret.ch.red = color.ch.red * 36; /*(2^8 - 1)/(2^3 - 1) = 255/7 = 36*/ LV_COLOR_SET_R32(ret, LV_COLOR_GET_R(color) * 36); /*(2^8 - 1)/(2^3 - 1) = 255/7 = 36*/
ret.ch.green = color.ch.green * 36; /*(2^8 - 1)/(2^3 - 1) = 255/7 = 36*/ LV_COLOR_SET_G32(ret, LV_COLOR_GET_G(color) * 36); /*(2^8 - 1)/(2^3 - 1) = 255/7 = 36*/
ret.ch.blue = color.ch.blue * 85; /*(2^8 - 1)/(2^2 - 1) = 255/3 = 85*/ LV_COLOR_SET_B32(ret, LV_COLOR_GET_B(color) * 85); /*(2^8 - 1)/(2^2 - 1) = 255/3 = 85*/
ret.ch.alpha = 0xFF; LV_COLOR_SET_A32(color, 0xFF);
return ret.full; return ret.full;
#elif LV_COLOR_DEPTH == 16 #elif LV_COLOR_DEPTH == 16
/** /**
@@ -335,14 +422,10 @@ static inline uint32_t lv_color_to32(lv_color_t color)
* 6 259 3 0 255 * 6 259 3 0 255
*/ */
lv_color32_t ret; lv_color32_t ret;
ret.ch.red = ( color.ch.red * 263 + 7 ) >> 5; LV_COLOR_SET_R32(ret, (LV_COLOR_GET_R(color) * 263 + 7 ) >> 5);
#if LV_COLOR_16_SWAP == 0 LV_COLOR_SET_G32(ret, (LV_COLOR_GET_G(color) * 259 + 3 ) >> 6);
ret.ch.green = ( color.ch.green * 259 + 3 ) >> 6; LV_COLOR_SET_B32(ret, (LV_COLOR_GET_B(color) * 263 + 7 ) >> 5);
#else LV_COLOR_SET_A32(ret, 0xFF);
ret.ch.green = (((color.ch.green_h << 3) + color.ch.green_l) * 259 + 3 ) >> 6;
#endif
ret.ch.blue = ( color.ch.blue * 263 + 7 ) >> 5;
ret.ch.alpha = 0xFF;
return ret.full; return ret.full;
#elif LV_COLOR_DEPTH == 32 #elif LV_COLOR_DEPTH == 32
return color.full; return color.full;
@@ -362,21 +445,10 @@ static inline lv_color_t lv_color_mix(lv_color_t c1, lv_color_t c2, uint8_t mix)
lv_color_t ret; lv_color_t ret;
#if LV_COLOR_DEPTH != 1 #if LV_COLOR_DEPTH != 1
/*LV_COLOR_DEPTH == 8, 16 or 32*/ /*LV_COLOR_DEPTH == 8, 16 or 32*/
ret.ch.red = (uint16_t)((uint16_t)c1.ch.red * mix + (c2.ch.red * (256 - mix))) >> 8; LV_COLOR_SET_R(ret, (uint16_t)((uint16_t) LV_COLOR_GET_R(c1) * mix + LV_COLOR_GET_R(c2) * (255 - mix)) >> 8);
#if LV_COLOR_DEPTH == 16 && LV_COLOR_16_SWAP LV_COLOR_SET_G(ret, (uint16_t)((uint16_t) LV_COLOR_GET_G(c1) * mix + LV_COLOR_GET_G(c2) * (255 - mix)) >> 8);
/*If swapped Green is in 2 parts*/ LV_COLOR_SET_B(ret, (uint16_t)((uint16_t) LV_COLOR_GET_B(c1) * mix + LV_COLOR_GET_B(c2) * (255 - mix)) >> 8);
uint16_t g_1 = (c1.ch.green_h << 3) + c1.ch.green_l; LV_COLOR_SET_A(ret, 0xFF);
uint16_t g_2 = (c2.ch.green_h << 3) + c2.ch.green_l;
uint16_t g_out = (uint16_t)((uint16_t)g_1 * mix + (g_2 * (256 - mix))) >> 8;
ret.ch.green_h = g_out >> 3;
ret.ch.green_l = g_out & 0x7;
#else
ret.ch.green = (uint16_t)((uint16_t)c1.ch.green * mix + (c2.ch.green * (256 - mix))) >> 8;
#endif
ret.ch.blue = (uint16_t)((uint16_t)c1.ch.blue * mix + (c2.ch.blue * (256 - mix))) >> 8;
#if LV_COLOR_DEPTH == 32
ret.ch.alpha = 0xFF;
#endif
#else #else
/*LV_COLOR_DEPTH == 1*/ /*LV_COLOR_DEPTH == 1*/
ret.full = mix > LV_OPA_50 ? c1.full : c2.full; ret.full = mix > LV_OPA_50 ? c1.full : c2.full;
@@ -454,16 +526,16 @@ static inline uint8_t lv_color_brightness(lv_color_t color)
{ {
lv_color32_t c32; lv_color32_t c32;
c32.full = lv_color_to32(color); c32.full = lv_color_to32(color);
uint16_t bright = 3 * c32.ch.red + c32.ch.blue + 4 * c32.ch.green; uint16_t bright = (uint16_t)(3u * LV_COLOR_GET_R32(c32) + LV_COLOR_GET_B32(c32) + 4u * LV_COLOR_GET_G32(c32));
return (uint16_t)bright >> 3; return (uint8_t)(bright >> 3);
} }
/* The most simple macro to create a color from R,G and B values */ /* The most simple macro to create a color from R,G and B values */
#if LV_COLOR_DEPTH == 1 #if LV_COLOR_DEPTH == 1
#define LV_COLOR_MAKE(r8, g8, b8) ((lv_color_t){(b8 >> 7 | g8 >> 7 | r8 >> 7)}) #define LV_COLOR_MAKE(r8, g8, b8) ((lv_color_t){.full = (b8 >> 7 | g8 >> 7 | r8 >> 7)})
static inline lv_color_t lv_color_make(int r8, int g8, int b8) static inline lv_color_t lv_color_make(int r8, int g8, int b8)
{ {
lv_color_t color; lv_color_t color = { 0 };
color.full = (b8 >> 7 | g8 >> 7 | r8 >> 7); color.full = (b8 >> 7 | g8 >> 7 | r8 >> 7);
return color; return color;
} }
@@ -472,43 +544,36 @@ static inline lv_color_t lv_color_make(int r8, int g8, int b8)
static inline lv_color_t lv_color_make(uint8_t r8, int g8, int b8) static inline lv_color_t lv_color_make(uint8_t r8, int g8, int b8)
{ {
lv_color_t color; lv_color_t color;
color.ch.blue = b8 >> 6; LV_COLOR_SET_B(color, b8 >> 6);
color.ch.green = g8 >> 5; LV_COLOR_SET_G(color, g8 >> 5);
color.ch.red = r8 >> 5; LV_COLOR_SET_R(color, r8 >> 5);
LV_COLOR_SET_A(color, 0xFF);
return color; return color;
} }
#elif LV_COLOR_DEPTH == 16 #elif LV_COLOR_DEPTH == 16
#if LV_COLOR_16_SWAP == 0 #if LV_COLOR_16_SWAP == 0
#define LV_COLOR_MAKE(r8, g8, b8) ((lv_color_t){{b8 >> 3, g8 >> 2, r8 >> 3}}) #define LV_COLOR_MAKE(r8, g8, b8) ((lv_color_t){{b8 >> 3, g8 >> 2, r8 >> 3}})
static inline lv_color_t lv_color_make(uint8_t r8, uint8_t g8, uint8_t b8)
{
lv_color_t color;
color.ch.blue = (uint16_t)(b8 >> 3);
color.ch.green = (uint16_t)(g8 >> 2);
color.ch.red = (uint16_t)(r8 >> 3);
return color;
}
#else #else
#define LV_COLOR_MAKE(r8, g8, b8) ((lv_color_t){{g8 >> 5, r8 >> 3, b8 >> 3, (g8 >> 2) & 0x7}}) #define LV_COLOR_MAKE(r8, g8, b8) ((lv_color_t){{g8 >> 5, r8 >> 3, b8 >> 3, (g8 >> 2) & 0x7}})
#endif
static inline lv_color_t lv_color_make(uint8_t r8, uint8_t g8, uint8_t b8) static inline lv_color_t lv_color_make(uint8_t r8, uint8_t g8, uint8_t b8)
{ {
lv_color_t color; lv_color_t color;
color.ch.green_h = (uint16_t)(g8 >> 5); LV_COLOR_SET_B(color, b8 >> 3);
color.ch.red = (uint16_t)(r8 >> 3); LV_COLOR_SET_G(color, g8 >> 2);
color.ch.blue = (uint16_t)(b8 >> 3); LV_COLOR_SET_R(color, r8 >> 3);
color.ch.green_l = (uint16_t)((g8 >> 2) & 0x7); LV_COLOR_SET_A(color, 0xFF);
return color; return color;
} }
#endif
#elif LV_COLOR_DEPTH == 32 #elif LV_COLOR_DEPTH == 32
#define LV_COLOR_MAKE(r8, g8, b8) ((lv_color_t){{b8, g8, r8, 0xff}}) /*Fix 0xff alpha*/ #define LV_COLOR_MAKE(r8, g8, b8) ((lv_color_t){{b8, g8, r8, 0xff}}) /*Fix 0xff alpha*/
static inline lv_color_t lv_color_make(uint8_t r8, uint8_t g8, uint8_t b8) static inline lv_color_t lv_color_make(uint8_t r8, uint8_t g8, uint8_t b8)
{ {
lv_color_t color; lv_color_t color;
color.ch.blue = b8; LV_COLOR_SET_B(color, b8);
color.ch.green = g8; LV_COLOR_SET_G(color, g8);
color.ch.red = r8; LV_COLOR_SET_R(color, r8);
color.ch.alpha = 0xff; LV_COLOR_SET_A(color, 0xFF);
return color; return color;
} }
#endif #endif
@@ -534,13 +599,20 @@ static inline lv_color_t lv_color_hex3(uint32_t c)
lv_color_t lv_color_hsv_to_rgb(uint16_t h, uint8_t s, uint8_t v); lv_color_t lv_color_hsv_to_rgb(uint16_t h, uint8_t s, uint8_t v);
/** /**
* Convert an RGB color to HSV * Convert a 32-bit RGB color to HSV
* @param r red * @param r8 8-bit red
* @param g green * @param g8 8-bit green
* @param b blue * @param b8 8-bit blue
* @return the given RGB color n HSV * @return the given RGB color in HSV
*/ */
lv_color_hsv_t lv_color_rgb_to_hsv(uint8_t r, uint8_t g, uint8_t b); lv_color_hsv_t lv_color_rgb_to_hsv(uint8_t r8, uint8_t g8, uint8_t b8);
/**
* Convert a color to HSV
* @param color color
* @return the given color in HSV
*/
lv_color_hsv_t lv_color_to_hsv(lv_color_t color);
/********************** /**********************
* MACROS * MACROS

View File

@@ -12,6 +12,7 @@
#if LV_LOG_PRINTF #if LV_LOG_PRINTF
#include <stdio.h> #include <stdio.h>
#endif #endif
/********************* /*********************
* DEFINES * DEFINES
*********************/ *********************/

View File

@@ -312,7 +312,6 @@ uint16_t lv_atan2(int x, int y)
return degree; return degree;
} }
/********************** /**********************
* STATIC FUNCTIONS * STATIC FUNCTIONS
**********************/ **********************/

View File

@@ -70,7 +70,6 @@ void lv_sqrt(uint32_t x, lv_sqrt_res_t * q);
*/ */
uint16_t lv_atan2(int x, int y); uint16_t lv_atan2(int x, int y);
/********************** /**********************
* MACROS * MACROS
**********************/ **********************/

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_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_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_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; uint32_t (*lv_txt_get_encoded_length)(const char *) = lv_txt_utf8_get_length;
#elif LV_TXT_ENC == LV_TXT_ENC_ASCII #elif LV_TXT_ENC == LV_TXT_ENC_ASCII
uint8_t (*lv_txt_encoded_size)(const char *) = lv_txt_iso8859_1_size; 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_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_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_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; uint32_t (*lv_txt_get_encoded_length)(const char *) = lv_txt_iso8859_1_get_length;
#endif #endif
@@ -149,17 +149,21 @@ void lv_txt_get_size(lv_point_t * size_res, const char * text, const lv_font_t *
* 3. Return i=9, pointing at breakchar '\n' * 3. Return i=9, pointing at breakchar '\n'
* 4. Parenting lv_txt_get_next_line() would detect subsequent '\0' * 4. Parenting lv_txt_get_next_line() would detect subsequent '\0'
* *
* TODO: Returned word_w_ptr may overestimate the returned word's width when
* max_width is reached. In current usage, this has no impact.
*
* @param txt a '\0' terminated string * @param txt a '\0' terminated string
* @param font pointer to a font * @param font pointer to a font
* @param letter_space letter space * @param letter_space letter space
* @param max_width max with of the text (break the lines to fit this size) Set CORD_MAX to avoid line breaks * @param max_width max with of the text (break the lines to fit this size) Set CORD_MAX to avoid line breaks
* @param flags settings for the text from 'txt_flag_type' enum * @param flags settings for the text from 'txt_flag_type' enum
* @param[out] word_w_ptr width (in pixels) of the parsed word. May be NULL. * @param[out] word_w_ptr width (in pixels) of the parsed word. May be NULL.
* @param force Force return the fraction of the word that can fit in the provided space.
* @return the index of the first char of the next word (in byte index not letter index. With UTF-8 they are different) * @return the index of the first char of the next word (in byte index not letter index. With UTF-8 they are different)
*/ */
static uint16_t lv_txt_get_next_word(const char * txt, const lv_font_t * font, static uint16_t lv_txt_get_next_word(const char * txt, const lv_font_t * font,
lv_coord_t letter_space, lv_coord_t max_width, lv_coord_t letter_space, lv_coord_t max_width,
lv_txt_flag_t flag, uint32_t *word_w_ptr) lv_txt_flag_t flag, uint32_t *word_w_ptr, bool force)
{ {
if(txt == NULL || txt[0] == '\0') return 0; if(txt == NULL || txt[0] == '\0') return 0;
if(font == NULL) return 0; if(font == NULL) return 0;
@@ -179,6 +183,7 @@ static uint16_t lv_txt_get_next_word(const char * txt, const lv_font_t * font,
letter = lv_txt_encoded_next(txt, &i_next); letter = lv_txt_encoded_next(txt, &i_next);
i_next_next = i_next; i_next_next = i_next;
/* Obtain the full word, regardless if it fits or not in max_width */
while(txt[i] != '\0') { while(txt[i] != '\0') {
letter_next = lv_txt_encoded_next(txt, &i_next_next); letter_next = lv_txt_encoded_next(txt, &i_next_next);
word_len++; word_len++;
@@ -196,17 +201,10 @@ static uint16_t lv_txt_get_next_word(const char * txt, const lv_font_t * font,
letter_w = lv_font_get_glyph_width(font, letter, letter_next); letter_w = lv_font_get_glyph_width(font, letter, letter_next);
cur_w += letter_w; cur_w += letter_w;
/* Test if this character fits within max_width */ /* Test if this character fits within max_width */
if( break_index == NO_BREAK_FOUND && cur_w > max_width) { if(break_index == NO_BREAK_FOUND && cur_w > max_width) {
break_index = i; break_index = i;
if(break_index > 0) { /* zero is possible if first character doesn't fit in width */ break_letter_count = word_len - 1;
lv_txt_encoded_prev(txt, &break_index);
break_letter_count = word_len - 2;
}
else{
break_letter_count = word_len - 1;
}
/* break_index is now pointing at the character that doesn't fit */ /* break_index is now pointing at the character that doesn't fit */
} }
@@ -237,14 +235,17 @@ static uint16_t lv_txt_get_next_word(const char * txt, const lv_font_t * font,
return i; return i;
} }
#if LV_TXT_LINE_BREAK_LONG_LEN > 0
/* Word doesn't fit in provided space, but isn't "long" */ /* Word doesn't fit in provided space, but isn't "long" */
if(word_len < LV_TXT_LINE_BREAK_LONG_LEN) { if(word_len < LV_TXT_LINE_BREAK_LONG_LEN) {
if(word_w_ptr != NULL) *word_w_ptr = 0; if( force ) return break_index;
if(word_w_ptr != NULL) *word_w_ptr = 0; /* Return no word */
return 0; return 0;
} }
/* Word is "long," but insufficient amounts can fit in provided space */ /* Word is "long," but insufficient amounts can fit in provided space */
if(break_letter_count < LV_TXT_LINE_BREAK_LONG_PRE_MIN_LEN) { if(break_letter_count < LV_TXT_LINE_BREAK_LONG_PRE_MIN_LEN) {
if( force ) return break_index;
if(word_w_ptr != NULL) *word_w_ptr = 0; if(word_w_ptr != NULL) *word_w_ptr = 0;
return 0; return 0;
} }
@@ -256,16 +257,24 @@ static uint16_t lv_txt_get_next_word(const char * txt, const lv_font_t * font,
/* Move pointer "i" backwards */ /* Move pointer "i" backwards */
for(;n_move>0; n_move--){ for(;n_move>0; n_move--){
lv_txt_encoded_prev(txt, &i); lv_txt_encoded_prev(txt, &i);
// todo: it would be appropriate to update the returned word width here // TODO: it would be appropriate to update the returned word width here
// However, in current usage, this doesn't impact anything. // However, in current usage, this doesn't impact anything.
} }
} }
return i; return i;
#else
if( force ) return break_index;
if(word_w_ptr != NULL) *word_w_ptr = 0; /* Return no word */
(void) break_letter_count;
return 0;
#endif
} }
/** /**
* Get the next line of text. Check line length and break chars too. * Get the next line of text. Check line length and break chars too.
*
* A line of txt includes the \n character.
*
* @param txt a '\0' terminated string * @param txt a '\0' terminated string
* @param font pointer to a font * @param font pointer to a font
* @param letter_space letter space * @param letter_space letter space
@@ -285,7 +294,7 @@ uint16_t lv_txt_get_next_line(const char * txt, const lv_font_t * font,
while(txt[i] != '\0' && max_width > 0) { while(txt[i] != '\0' && max_width > 0) {
uint32_t word_w = 0; uint32_t word_w = 0;
uint32_t advance = lv_txt_get_next_word(&txt[i], font, letter_space, max_width, flag, &word_w); uint32_t advance = lv_txt_get_next_word(&txt[i], font, letter_space, max_width, flag, &word_w, i==0);
max_width -= word_w; max_width -= word_w;
if( advance == 0 ){ if( advance == 0 ){
@@ -295,21 +304,16 @@ uint16_t lv_txt_get_next_line(const char * txt, const lv_font_t * font,
i += advance; i += advance;
if(txt[i] == '\n') break; if(txt[0] == '\n') break;
if(txt[i] == '\n'){
i++; /* Include the following newline in the current line */
break;
}
} }
/* If this is the last of the string, make sure pointer is at NULL-terminator. /* Always step at least one to avoid infinite loops */
* This catches the case, for example of a string ending in "\n" */
if(txt[i] != '\0'){
uint32_t i_next = i;
int tmp;
uint32_t letter_next = lv_txt_encoded_next(txt, &i_next); /*Gets current character*/
tmp = i_next;
letter_next = lv_txt_encoded_next(txt, &i_next); /*Gets subsequent character*/
if(letter_next == '\0') i = tmp;
}
/*Always step at least one to avoid infinite loops*/
if(i == 0) { if(i == 0) {
lv_txt_encoded_next(txt, &i); lv_txt_encoded_next(txt, &i);
} }

View File

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

View File

@@ -670,11 +670,6 @@ static lv_design_res_t lv_btnm_design(lv_obj_t * btnm, const lv_area_t * clip_ar
lv_txt_flag_t txt_flag = LV_TXT_FLAG_NONE; lv_txt_flag_t txt_flag = LV_TXT_FLAG_NONE;
if(ext->recolor) txt_flag = LV_TXT_FLAG_RECOLOR; if(ext->recolor) txt_flag = LV_TXT_FLAG_RECOLOR;
#if LV_USE_BIDI
char * bidi_buf = lv_mem_alloc(64);
lv_bidi_dir_t base_dir = lv_obj_get_base_dir(btnm);
#endif
for(btn_i = 0; btn_i < ext->btn_cnt; btn_i++, txt_i++) { for(btn_i = 0; btn_i < ext->btn_cnt; btn_i++, txt_i++) {
/*Search the next valid text in the map*/ /*Search the next valid text in the map*/
while(strcmp(ext->map_p[txt_i], "\n") == 0) { while(strcmp(ext->map_p[txt_i], "\n") == 0) {
@@ -743,22 +738,8 @@ static lv_design_res_t lv_btnm_design(lv_obj_t * btnm, const lv_area_t * clip_ar
area_tmp.x2 = area_tmp.x1 + txt_size.x; area_tmp.x2 = area_tmp.x1 + txt_size.x;
area_tmp.y2 = area_tmp.y1 + txt_size.y; area_tmp.y2 = area_tmp.y1 + txt_size.y;
#if LV_USE_BIDI == 0 lv_draw_label(&area_tmp, clip_area, btn_style, opa_scale, ext->map_p[txt_i], txt_flag, NULL, NULL, NULL, lv_obj_get_base_dir(btnm));
lv_draw_label(&area_tmp, clip_area, btn_style, opa_scale, ext->map_p[txt_i], txt_flag, NULL, NULL, NULL);
#else
uint32_t txt_len = strlen(ext->map_p[txt_i]) + 1;
if(txt_len > lv_mem_get_size(bidi_buf)) {
bidi_buf = lv_mem_realloc(bidi_buf, txt_len);
}
lv_bidi_process(ext->map_p[txt_i], bidi_buf, base_dir);
lv_draw_label(&area_tmp, clip_area, btn_style, opa_scale, bidi_buf, txt_flag, NULL, NULL, NULL);
#endif
} }
#if LV_USE_BIDI
lv_mem_free(bidi_buf);
#endif
} }
return LV_DESIGN_RES_OK; return LV_DESIGN_RES_OK;
} }

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) 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_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_opa_t opa_scale = lv_obj_get_opa_scale(calendar);
lv_area_t header_area; 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'; txt_buf[5] = '\0';
strcpy(&txt_buf[5], get_month_name(calendar, ext->showed_date.month)); strcpy(&txt_buf[5], get_month_name(calendar, ext->showed_date.month));
header_area.y1 += ext->style_header->body.padding.top; 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*/ /*Add the left arrow*/
const lv_style_t * arrow_style = ext->btn_pressing < 0 ? ext->style_header_pr : ext->style_header; 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; 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*/ /*Add the right arrow*/
arrow_style = ext->btn_pressing > 0 ? ext->style_header_pr : ext->style_header; 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 - 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, lv_txt_get_width(LV_SYMBOL_RIGHT, strlen(LV_SYMBOL_RIGHT), arrow_style->text.font,
arrow_style->text.line_space, LV_TXT_FLAG_NONE); 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) 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_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_opa_t opa_scale = lv_obj_get_opa_scale(calendar);
lv_coord_t l_pad = ext->style_day_names->body.padding.left; 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.x1 = calendar->coords.x1 + (w * i) / 7 + l_pad;
label_area.x2 = label_area.x1 + box_w - 1; 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, 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) 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_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); const lv_style_t * style_bg = lv_calendar_get_style(calendar, LV_CALENDAR_STYLE_BG);
lv_area_t label_area; lv_area_t label_area;
lv_opa_t opa_scale = lv_obj_get_opa_scale(calendar); 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*/ /*Write the day's number*/
lv_utils_num_to_str(day_cnt, buf); 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*/ /*Go to the next day*/
day_cnt++; day_cnt++;

View File

@@ -823,7 +823,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; 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); lv_refr_set_disp_refreshing(refr_ori);
} }

View File

@@ -1394,7 +1394,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; 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));
} }
} }
@@ -1480,7 +1480,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 */ /* 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), 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)}; (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

@@ -1,6 +1,7 @@
/** /**
* @file lv_cpicker.c * @file lv_cpicker.c
* *
* From @AloyseTech and @paulpv.
*/ */
/********************* /*********************
@@ -57,10 +58,11 @@
static lv_design_res_t lv_cpicker_design(lv_obj_t * cpicker, const lv_area_t * clip_area, lv_design_mode_t mode); static lv_design_res_t lv_cpicker_design(lv_obj_t * cpicker, const lv_area_t * clip_area, lv_design_mode_t mode);
static lv_res_t lv_cpicker_signal(lv_obj_t * cpicker, lv_signal_t sign, void * param); static lv_res_t lv_cpicker_signal(lv_obj_t * cpicker, lv_signal_t sign, void * param);
static void invalidate_indic(lv_obj_t * cpicker);
static void draw_rect_grad(lv_obj_t * cpicker, const lv_area_t * mask, lv_opa_t opa_scale); static void draw_rect_grad(lv_obj_t * cpicker, const lv_area_t * mask, lv_opa_t opa_scale);
static void draw_disc_grad(lv_obj_t * cpicker, const lv_area_t * mask, lv_opa_t opa_scale); static void draw_disc_grad(lv_obj_t * cpicker, const lv_area_t * mask, lv_opa_t opa_scale);
static void draw_indic(lv_obj_t * cpicker, const lv_area_t * mask, lv_opa_t opa_scale); static void draw_indic(lv_obj_t * cpicker, const lv_area_t * mask, lv_opa_t opa_scale);
static void invalidate_indic(lv_obj_t * cpicker);
static lv_area_t get_indic_area(lv_obj_t * cpicker);
static void next_color_mode(lv_obj_t * cpicker); static void next_color_mode(lv_obj_t * cpicker);
static lv_res_t double_click_reset(lv_obj_t * cpicker); static lv_res_t double_click_reset(lv_obj_t * cpicker);
@@ -105,6 +107,7 @@ lv_obj_t * lv_cpicker_create(lv_obj_t * par, const lv_obj_t * copy)
if(ext == NULL) return NULL; if(ext == NULL) return NULL;
/*Initialize the allocated 'ext' */ /*Initialize the allocated 'ext' */
ext->type = LV_CPICKER_DEF_TYPE;
ext->hsv = LV_CPICKER_DEF_HSV; ext->hsv = LV_CPICKER_DEF_HSV;
ext->indic.style = &lv_style_plain; ext->indic.style = &lv_style_plain;
ext->indic.colored = 0; ext->indic.colored = 0;
@@ -120,8 +123,8 @@ lv_obj_t * lv_cpicker_create(lv_obj_t * par, const lv_obj_t * copy)
/*If no copy do the basic initialization*/ /*If no copy do the basic initialization*/
if(copy == NULL) { if(copy == NULL) {
lv_obj_set_size(new_cpicker, LV_DPI * 2, LV_DPI * 2);
lv_obj_set_protect(new_cpicker, LV_PROTECT_PRESS_LOST); lv_obj_set_protect(new_cpicker, LV_PROTECT_PRESS_LOST);
refr_indic_pos(new_cpicker);
lv_theme_t * th = lv_theme_get_current(); lv_theme_t * th = lv_theme_get_current();
if(th) { if(th) {
lv_cpicker_set_style(new_cpicker, LV_CPICKER_STYLE_MAIN, th->style.bg); lv_cpicker_set_style(new_cpicker, LV_CPICKER_STYLE_MAIN, th->style.bg);
@@ -200,91 +203,85 @@ void lv_cpicker_set_style(lv_obj_t * cpicker, lv_cpicker_style_t type, lv_style_
* Set the current hue of a colorpicker. * Set the current hue of a colorpicker.
* @param cpicker pointer to colorpicker object * @param cpicker pointer to colorpicker object
* @param hue current selected hue [0..360] * @param hue current selected hue [0..360]
* @return true if changed, otherwise false
*/ */
void lv_cpicker_set_hue(lv_obj_t * cpicker, uint16_t hue) bool lv_cpicker_set_hue(lv_obj_t * cpicker, uint16_t hue)
{ {
LV_ASSERT_OBJ(cpicker, LV_OBJX_NAME); lv_color_hsv_t hsv = lv_cpicker_get_hsv(cpicker);
hsv.h = hue;
lv_cpicker_ext_t * ext = lv_obj_get_ext_attr(cpicker); return lv_cpicker_set_hsv(cpicker, hsv);
ext->hsv.h = hue % 360;
if(ext->color_mode == LV_CPICKER_COLOR_MODE_HUE) refr_indic_pos(cpicker);
if(ext->preview && ext->type == LV_CPICKER_TYPE_DISC) {
lv_obj_invalidate(cpicker);
}
} }
/** /**
* Set the current saturation of a colorpicker. * Set the current saturation of a colorpicker.
* @param cpicker pointer to colorpicker object * @param cpicker pointer to colorpicker object
* @param saturation current selected saturation [0..100] * @param saturation current selected saturation [0..100]
* @return true if changed, otherwise false
*/ */
void lv_cpicker_set_saturation(lv_obj_t * cpicker, uint8_t saturation) bool lv_cpicker_set_saturation(lv_obj_t * cpicker, uint8_t saturation)
{ {
LV_ASSERT_OBJ(cpicker, LV_OBJX_NAME); lv_color_hsv_t hsv = lv_cpicker_get_hsv(cpicker);
hsv.s = saturation;
lv_cpicker_ext_t * ext = lv_obj_get_ext_attr(cpicker); return lv_cpicker_set_hsv(cpicker, hsv);
ext->hsv.s = saturation > 100 ? 100 : saturation;
if(ext->color_mode == LV_CPICKER_COLOR_MODE_SATURATION) refr_indic_pos(cpicker);
if(ext->preview && ext->type == LV_CPICKER_TYPE_DISC) {
lv_obj_invalidate(cpicker);
}
} }
/** /**
* Set the current value of a colorpicker. * Set the current value of a colorpicker.
* @param cpicker pointer to colorpicker object * @param cpicker pointer to colorpicker object
* @param val current selected value [0..100] * @param val current selected value [0..100]
* @return true if changed, otherwise false
*/ */
void lv_cpicker_set_value(lv_obj_t * cpicker, uint8_t val) bool lv_cpicker_set_value(lv_obj_t * cpicker, uint8_t val)
{ {
LV_ASSERT_OBJ(cpicker, LV_OBJX_NAME); lv_color_hsv_t hsv = lv_cpicker_get_hsv(cpicker);
hsv.v = val;
lv_cpicker_ext_t * ext = lv_obj_get_ext_attr(cpicker); return lv_cpicker_set_hsv(cpicker, hsv);
ext->hsv.v = val > 100 ? 100 : val;
if(ext->color_mode == LV_CPICKER_COLOR_MODE_VALUE) refr_indic_pos(cpicker);
if(ext->preview && ext->type == LV_CPICKER_TYPE_DISC) {
lv_obj_invalidate(cpicker);
}
} }
/** /**
* Set the current hsv of a colorpicker. * Set the current hsv of a colorpicker.
* @param cpicker pointer to colorpicker object * @param cpicker pointer to colorpicker object
* @param color current selected hsv * @param color current selected hsv
* @return true if changed, otherwise false
*/ */
void lv_cpicker_set_hsv(lv_obj_t * cpicker, lv_color_hsv_t hsv) bool lv_cpicker_set_hsv(lv_obj_t * cpicker, lv_color_hsv_t hsv)
{ {
LV_ASSERT_OBJ(cpicker, LV_OBJX_NAME); LV_ASSERT_OBJ(cpicker, LV_OBJX_NAME);
if (hsv.h > 360) hsv.h %= 360;
if (hsv.s > 100) hsv.s = 100;
if (hsv.v > 100) hsv.v = 100;
lv_cpicker_ext_t * ext = lv_obj_get_ext_attr(cpicker); lv_cpicker_ext_t * ext = lv_obj_get_ext_attr(cpicker);
if (ext->hsv.h == hsv.h && ext->hsv.s == hsv.s && ext->hsv.v == hsv.v) return false;
ext->hsv = hsv; ext->hsv = hsv;
refr_indic_pos(cpicker); refr_indic_pos(cpicker);
lv_obj_invalidate(cpicker);
if (ext->preview && ext->type == LV_CPICKER_TYPE_DISC) {
lv_obj_invalidate(cpicker);
}
return true;
} }
/** /**
* Set the current color of a colorpicker. * Set the current color of a colorpicker.
* @param cpicker pointer to colorpicker object * @param cpicker pointer to colorpicker object
* @param color current selected color * @param color current selected color
* @return true if changed, otherwise false
*/ */
void lv_cpicker_set_color(lv_obj_t * cpicker, lv_color_t color) bool lv_cpicker_set_color(lv_obj_t * cpicker, lv_color_t color)
{ {
LV_ASSERT_OBJ(cpicker, LV_OBJX_NAME); LV_ASSERT_OBJ(cpicker, LV_OBJX_NAME);
lv_color32_t c32; lv_color32_t c32;
c32.full = lv_color_to32(color); c32.full = lv_color_to32(color);
lv_cpicker_set_hsv(cpicker, lv_color_rgb_to_hsv(c32.ch.red, c32.ch.green, c32.ch.blue)); return lv_cpicker_set_hsv(cpicker,
lv_color_rgb_to_hsv(LV_COLOR_GET_R(color), LV_COLOR_GET_G(color), LV_COLOR_GET_B(color)));
} }
/** /**
@@ -662,25 +659,10 @@ static void draw_rect_grad(lv_obj_t * cpicker, const lv_area_t * mask, lv_opa_t
lv_draw_rect(&rect_area, mask, &style, opa_scale); lv_draw_rect(&rect_area, mask, &style, opa_scale);
} }
} }
/**
* Should roughly match up with `lv_cpicker_invalidate_disc_indicator_circle`
*/
static void draw_indic(lv_obj_t * cpicker, const lv_area_t * mask, lv_opa_t opa_scale) static void draw_indic(lv_obj_t * cpicker, const lv_area_t * mask, lv_opa_t opa_scale)
{ {
lv_cpicker_ext_t * ext = lv_obj_get_ext_attr(cpicker); lv_cpicker_ext_t * ext = lv_obj_get_ext_attr(cpicker);
const lv_style_t * style_main = lv_cpicker_get_style(cpicker, LV_CPICKER_STYLE_MAIN);
const lv_style_t * style_indic = lv_cpicker_get_style(cpicker, LV_CPICKER_STYLE_INDICATOR);
lv_coord_t h = lv_obj_get_height(cpicker);
uint16_t r;
if(ext->type == LV_CPICKER_TYPE_DISC) r = style_main->line.width / 2;
else if(ext->type == LV_CPICKER_TYPE_RECT) r = h / 2;
lv_area_t ind_area;
ind_area.x1 = cpicker->coords.x1 + ext->indic.pos.x - r - style_indic->body.padding.left;
ind_area.y1 = cpicker->coords.y1 + ext->indic.pos.y - r - style_indic->body.padding.right;
ind_area.x2 = cpicker->coords.x1 + ext->indic.pos.x + r + style_indic->body.padding.top;
ind_area.y2 = cpicker->coords.y1 + ext->indic.pos.y + r + style_indic->body.padding.bottom;
lv_style_t style_cir; lv_style_t style_cir;
lv_style_copy(&style_cir, ext->indic.style); lv_style_copy(&style_cir, ext->indic.style);
@@ -691,8 +673,38 @@ static void draw_indic(lv_obj_t * cpicker, const lv_area_t * mask, lv_opa_t opa_
style_cir.body.grad_color = style_cir.body.main_color; style_cir.body.grad_color = style_cir.body.main_color;
} }
lv_area_t indic_area = get_indic_area(cpicker);
lv_draw_rect(&ind_area, mask, &style_cir, opa_scale); lv_draw_rect(&indic_area, mask, &style_cir, opa_scale);
}
static void invalidate_indic(lv_obj_t * cpicker)
{
lv_area_t indic_area = get_indic_area(cpicker);
lv_inv_area(lv_obj_get_disp(cpicker), &indic_area);
}
static lv_area_t get_indic_area(lv_obj_t * cpicker)
{
lv_cpicker_ext_t * ext = lv_obj_get_ext_attr(cpicker);
const lv_style_t * style_main = lv_cpicker_get_style(cpicker, LV_CPICKER_STYLE_MAIN);
const lv_style_t * style_indic = lv_cpicker_get_style(cpicker, LV_CPICKER_STYLE_INDICATOR);
uint16_t r;
if(ext->type == LV_CPICKER_TYPE_DISC) r = style_main->line.width / 2;
else if(ext->type == LV_CPICKER_TYPE_RECT) {
lv_coord_t h = lv_obj_get_height(cpicker);
r = h / 2;
}
lv_area_t indic_area;
indic_area.x1 = cpicker->coords.x1 + ext->indic.pos.x - r - style_indic->body.padding.left;
indic_area.y1 = cpicker->coords.y1 + ext->indic.pos.y - r - style_indic->body.padding.right;
indic_area.x2 = cpicker->coords.x1 + ext->indic.pos.x + r + style_indic->body.padding.top;
indic_area.y2 = cpicker->coords.y1 + ext->indic.pos.y + r + style_indic->body.padding.bottom;
return indic_area;
} }
/** /**
@@ -725,8 +737,7 @@ static lv_res_t lv_cpicker_signal(lv_obj_t * cpicker, lv_signal_t sign, void * p
} else if(sign == LV_SIGNAL_CORD_CHG) { } else if(sign == LV_SIGNAL_CORD_CHG) {
/*Refresh extended draw area to make knob visible*/ /*Refresh extended draw area to make knob visible*/
if(lv_obj_get_width(cpicker) != lv_area_get_width(param) || if(lv_obj_get_width(cpicker) != lv_area_get_width(param) ||
lv_obj_get_height(cpicker) != lv_area_get_height(param)) lv_obj_get_height(cpicker) != lv_area_get_height(param)) {
{
lv_obj_refresh_ext_draw_pad(cpicker); lv_obj_refresh_ext_draw_pad(cpicker);
refr_indic_pos(cpicker); refr_indic_pos(cpicker);
} }
@@ -753,10 +764,10 @@ static lv_res_t lv_cpicker_signal(lv_obj_t * cpicker, lv_signal_t sign, void * p
break; break;
} }
lv_cpicker_set_hsv(cpicker, hsv_cur); if (lv_cpicker_set_hsv(cpicker, hsv_cur)) {
res = lv_event_send(cpicker, LV_EVENT_VALUE_CHANGED, NULL);
res = lv_event_send(cpicker, LV_EVENT_VALUE_CHANGED, NULL); if(res != LV_RES_OK) return res;
if(res != LV_RES_OK) return res; }
} }
else if(c == LV_KEY_LEFT || c == LV_KEY_DOWN) { else if(c == LV_KEY_LEFT || c == LV_KEY_DOWN) {
lv_color_hsv_t hsv_cur; lv_color_hsv_t hsv_cur;
@@ -774,10 +785,10 @@ static lv_res_t lv_cpicker_signal(lv_obj_t * cpicker, lv_signal_t sign, void * p
break; break;
} }
lv_cpicker_set_hsv(cpicker, hsv_cur); if (lv_cpicker_set_hsv(cpicker, hsv_cur)) {
res = lv_event_send(cpicker, LV_EVENT_VALUE_CHANGED, NULL);
res = lv_event_send(cpicker, LV_EVENT_VALUE_CHANGED, NULL); if(res != LV_RES_OK) return res;
if(res != LV_RES_OK) return res; }
} }
} }
else if(sign == LV_SIGNAL_PRESSED) { else if(sign == LV_SIGNAL_PRESSED) {
@@ -785,7 +796,7 @@ static lv_res_t lv_cpicker_signal(lv_obj_t * cpicker, lv_signal_t sign, void * p
lv_indev_get_point(lv_indev_get_act(), &ext->last_press_point); lv_indev_get_point(lv_indev_get_act(), &ext->last_press_point);
res = double_click_reset(cpicker); res = double_click_reset(cpicker);
if(res != LV_RES_OK) return res; if(res != LV_RES_OK) return res;
} else if(sign == LV_SIGNAL_PRESSING){ } else if(sign == LV_SIGNAL_PRESSING) {
lv_indev_t * indev = lv_indev_get_act(); lv_indev_t * indev = lv_indev_get_act();
if(indev == NULL) return res; if(indev == NULL) return res;
@@ -846,30 +857,31 @@ static lv_res_t lv_cpicker_signal(lv_obj_t * cpicker, lv_signal_t sign, void * p
angle = lv_atan2(p.x, p.y) % 360; angle = lv_atan2(p.x, p.y) % 360;
} }
lv_color_hsv_t hsv_cur;
hsv_cur = ext->hsv;
switch(ext->color_mode) { switch(ext->color_mode) {
case LV_CPICKER_COLOR_MODE_HUE: case LV_CPICKER_COLOR_MODE_HUE:
if(ext->hsv.h != angle) lv_cpicker_set_hue(cpicker, angle); hsv_cur.h = angle;
break; break;
case LV_CPICKER_COLOR_MODE_SATURATION: case LV_CPICKER_COLOR_MODE_SATURATION:
angle = (angle * 100) / 360; hsv_cur.s = (angle * 100) / 360;
if(ext->hsv.s != angle) lv_cpicker_set_saturation(cpicker, angle);
break; break;
case LV_CPICKER_COLOR_MODE_VALUE: case LV_CPICKER_COLOR_MODE_VALUE:
angle = (angle * 100) / 360; hsv_cur.v = (angle * 100) / 360;
if(ext->hsv.v != angle) lv_cpicker_set_value(cpicker, angle);
break; break;
} }
refr_indic_pos(cpicker); if (lv_cpicker_set_hsv(cpicker, hsv_cur)) {
res = lv_event_send(cpicker, LV_EVENT_VALUE_CHANGED, NULL);
res = lv_event_send(cpicker, LV_EVENT_VALUE_CHANGED, NULL); if(res != LV_RES_OK) return res;
if(res != LV_RES_OK) return res; }
} }
return res; return res;
} }
static void next_color_mode(lv_obj_t * cpicker ) static void next_color_mode(lv_obj_t * cpicker)
{ {
lv_cpicker_ext_t * ext = lv_obj_get_ext_attr(cpicker); lv_cpicker_ext_t * ext = lv_obj_get_ext_attr(cpicker);
ext->color_mode = (ext->color_mode + 1) % 3; ext->color_mode = (ext->color_mode + 1) % 3;
@@ -877,32 +889,6 @@ static void next_color_mode(lv_obj_t * cpicker )
lv_obj_invalidate(cpicker); lv_obj_invalidate(cpicker);
} }
/**
* Indicator points need to match those set in lv_cpicker_disc_design/lv_cpicker_rect_design
*/
static void invalidate_indic(lv_obj_t * cpicker)
{
lv_cpicker_ext_t * ext = lv_obj_get_ext_attr(cpicker);
const lv_style_t * style_main = lv_cpicker_get_style(cpicker, LV_CPICKER_STYLE_MAIN);
const lv_style_t * style_indic = lv_cpicker_get_style(cpicker, LV_CPICKER_STYLE_INDICATOR);
lv_coord_t h = lv_obj_get_height(cpicker);
uint16_t r;
if(ext->type == LV_CPICKER_TYPE_DISC) r = style_main->line.width / 2;
else if(ext->type == LV_CPICKER_TYPE_RECT) r = h / 2;
lv_area_t indic_area;
indic_area.x1 = cpicker->coords.x1 + ext->indic.pos.x - r - style_indic->body.padding.left;
indic_area.y1 = cpicker->coords.y1 + ext->indic.pos.y - r - style_indic->body.padding.top;
indic_area.x2 = cpicker->coords.x1 + ext->indic.pos.x + r + style_indic->body.padding.right;
indic_area.y2 = cpicker->coords.y1 + ext->indic.pos.y + r + style_indic->body.padding.bottom;
lv_inv_area(lv_obj_get_disp(cpicker), &indic_area);
}
static void refr_indic_pos(lv_obj_t * cpicker) static void refr_indic_pos(lv_obj_t * cpicker)
{ {
invalidate_indic(cpicker); invalidate_indic(cpicker);
@@ -927,15 +913,14 @@ static void refr_indic_pos(lv_obj_t * cpicker)
ext->indic.pos.x = ind_pos; ext->indic.pos.x = ind_pos;
ext->indic.pos.y = h / 2; ext->indic.pos.y = h / 2;
} } else if(ext->type == LV_CPICKER_TYPE_DISC) {
if(ext->type == LV_CPICKER_TYPE_DISC) {
const lv_style_t * style_main = lv_cpicker_get_style(cpicker, LV_CPICKER_STYLE_MAIN); const lv_style_t * style_main = lv_cpicker_get_style(cpicker, LV_CPICKER_STYLE_MAIN);
lv_coord_t r = w / 2 - style_main->line.width / 2; lv_coord_t r = w / 2 - style_main->line.width / 2;
uint16_t angle = get_angle(cpicker); uint16_t angle = get_angle(cpicker);
ext->indic.pos.x = (((int32_t)r * lv_trigo_sin(angle)) >> LV_TRIGO_SHIFT); ext->indic.pos.x = (((int32_t)r * lv_trigo_sin(angle)) >> LV_TRIGO_SHIFT);
ext->indic.pos.y = (((int32_t)r * lv_trigo_sin(angle + 90)) >> LV_TRIGO_SHIFT); ext->indic.pos.y = (((int32_t)r * lv_trigo_sin(angle + 90)) >> LV_TRIGO_SHIFT);
ext->indic.pos.x = ext->indic.pos.x + w / 2; ext->indic.pos.x = ext->indic.pos.x + w / 2;
ext->indic.pos.y = ext->indic.pos.y + w / 2; ext->indic.pos.y = ext->indic.pos.y + h / 2;
} }
invalidate_indic(cpicker); invalidate_indic(cpicker);
@@ -947,21 +932,25 @@ static lv_res_t double_click_reset(lv_obj_t * cpicker)
lv_indev_t * indev = lv_indev_get_act(); lv_indev_t * indev = lv_indev_get_act();
/*Double clicked? Use long press time as double click time out*/ /*Double clicked? Use long press time as double click time out*/
if(lv_tick_elaps(ext->last_click_time) < indev->driver.long_press_time) { if(lv_tick_elaps(ext->last_click_time) < indev->driver.long_press_time) {
lv_color_hsv_t hsv_cur;
hsv_cur = ext->hsv;
switch(ext->color_mode) { switch(ext->color_mode) {
case LV_CPICKER_COLOR_MODE_HUE: case LV_CPICKER_COLOR_MODE_HUE:
lv_cpicker_set_hue(cpicker, LV_CPICKER_DEF_HUE); hsv_cur.h = LV_CPICKER_DEF_HUE;
break; break;
case LV_CPICKER_COLOR_MODE_SATURATION: case LV_CPICKER_COLOR_MODE_SATURATION:
lv_cpicker_set_saturation(cpicker, LV_CPICKER_DEF_SATURATION); hsv_cur.s = LV_CPICKER_DEF_SATURATION;
break; break;
case LV_CPICKER_COLOR_MODE_VALUE: case LV_CPICKER_COLOR_MODE_VALUE:
lv_cpicker_set_value(cpicker, LV_CPICKER_DEF_VALUE); hsv_cur.v = LV_CPICKER_DEF_VALUE;
break; break;
} }
lv_res_t res; if (lv_cpicker_set_hsv(cpicker, hsv_cur)) {
res = lv_event_send(cpicker, LV_EVENT_VALUE_CHANGED, NULL); lv_res_t res = lv_event_send(cpicker, LV_EVENT_VALUE_CHANGED, NULL);
if(res != LV_RES_OK) return res; if(res != LV_RES_OK) return res;
}
} }
ext->last_click_time = lv_tick_get(); ext->last_click_time = lv_tick_get();

View File

@@ -93,7 +93,7 @@ lv_obj_t * lv_cpicker_create(lv_obj_t * par, const lv_obj_t * copy);
* @param cpicker pointer to a colorpicker object * @param cpicker pointer to a colorpicker object
* @param type new type of the colorpicker (from 'lv_cpicker_type_t' enum) * @param type new type of the colorpicker (from 'lv_cpicker_type_t' enum)
*/ */
void lv_cpicker_set_type(lv_obj_t * chart, lv_cpicker_type_t type); void lv_cpicker_set_type(lv_obj_t * cpicker, lv_cpicker_type_t type);
/** /**
* Set a style of a colorpicker. * Set a style of a colorpicker.
@@ -106,37 +106,42 @@ void lv_cpicker_set_style(lv_obj_t * cpicker, lv_cpicker_style_t type, lv_style_
/** /**
* Set the current hue of a colorpicker. * Set the current hue of a colorpicker.
* @param cpicker pointer to colorpicker object * @param cpicker pointer to colorpicker object
* @param hue current selected hue * @param hue current selected hue [0..360]
* @return true if changed, otherwise false
*/ */
void lv_cpicker_set_hue(lv_obj_t * cpicker, uint16_t hue); bool lv_cpicker_set_hue(lv_obj_t * cpicker, uint16_t hue);
/** /**
* Set the current saturation of a colorpicker. * Set the current saturation of a colorpicker.
* @param cpicker pointer to colorpicker object * @param cpicker pointer to colorpicker object
* @param saturation current selected saturation * @param saturation current selected saturation [0..100]
* @return true if changed, otherwise false
*/ */
void lv_cpicker_set_saturation(lv_obj_t * cpicker, uint8_t saturation); bool lv_cpicker_set_saturation(lv_obj_t * cpicker, uint8_t saturation);
/** /**
* Set the current value of a colorpicker. * Set the current value of a colorpicker.
* @param cpicker pointer to colorpicker object * @param cpicker pointer to colorpicker object
* @param val current selected value * @param val current selected value [0..100]
* @return true if changed, otherwise false
*/ */
void lv_cpicker_set_value(lv_obj_t * cpicker, uint8_t val); bool lv_cpicker_set_value(lv_obj_t * cpicker, uint8_t val);
/** /**
* Set the current hsv of a colorpicker. * Set the current hsv of a colorpicker.
* @param cpicker pointer to colorpicker object * @param cpicker pointer to colorpicker object
* @param hsv current selected hsv * @param hsv current selected hsv
* @return true if changed, otherwise false
*/ */
void lv_cpicker_set_hsv(lv_obj_t * cpicker, lv_color_hsv_t hsv); bool lv_cpicker_set_hsv(lv_obj_t * cpicker, lv_color_hsv_t hsv);
/** /**
* Set the current color of a colorpicker. * Set the current color of a colorpicker.
* @param cpicker pointer to colorpicker object * @param cpicker pointer to colorpicker object
* @param color current selected color * @param color current selected color
* @return true if changed, otherwise false
*/ */
void lv_cpicker_set_color(lv_obj_t * cpicker, lv_color_t color); bool lv_cpicker_set_color(lv_obj_t * cpicker, lv_color_t color);
/** /**
* Set the current color mode. * Set the current color mode.

View File

@@ -609,7 +609,7 @@ static lv_design_res_t lv_ddlist_design(lv_obj_t * ddlist, const lv_area_t * cli
new_style.text.opa = sel_style->text.opa; new_style.text.opa = sel_style->text.opa;
lv_txt_flag_t flag = lv_ddlist_get_txt_flag(ddlist); 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), 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));
} }
} }
@@ -642,9 +642,9 @@ static lv_design_res_t lv_ddlist_design(lv_obj_t * ddlist, const lv_area_t * cli
bool area_ok; bool area_ok;
area_ok = lv_area_intersect(&mask_arrow, clip_area, &area_arrow); area_ok = lv_area_intersect(&mask_arrow, clip_area, &area_arrow);
if(area_ok) { 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, 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 NULL, NULL, NULL, lv_obj_get_base_dir(ddlist));
custom symbol*/
} }
} }
} }

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.x2 = label_cord.x1 + label_size.x;
label_cord.y2 = label_cord.y1 + label_size.y; 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

@@ -479,10 +479,10 @@ static lv_design_res_t lv_img_design(lv_obj_t * img, const lv_area_t * clip_area
cords_tmp.y1 = coords.y1; cords_tmp.y1 = coords.y1;
cords_tmp.y2 = coords.y1 + ext->h - 1; cords_tmp.y2 = coords.y1 + ext->h - 1;
for(; cords_tmp.y1 < coords.y2; cords_tmp.y1 += ext->h, cords_tmp.y2 += ext->h) { for(; cords_tmp.y1 <= coords.y2; cords_tmp.y1 += ext->h, cords_tmp.y2 += ext->h) {
cords_tmp.x1 = coords.x1; cords_tmp.x1 = coords.x1;
cords_tmp.x2 = coords.x1 + ext->w - 1; cords_tmp.x2 = coords.x1 + ext->w - 1;
for(; cords_tmp.x1 < coords.x2; cords_tmp.x1 += ext->w, cords_tmp.x2 += ext->w) { for(; cords_tmp.x1 <= coords.x2; cords_tmp.x1 += ext->w, cords_tmp.x2 += ext->w) {
lv_draw_img(&cords_tmp, clip_area, ext->src, style, ext->angle, ext->zoom, ext->antialias, opa_scale); lv_draw_img(&cords_tmp, clip_area, ext->src, style, ext->angle, ext->zoom, ext->antialias, opa_scale);
} }
} }
@@ -491,7 +491,7 @@ static lv_design_res_t lv_img_design(lv_obj_t * img, const lv_area_t * clip_area
lv_style_t style_mod; lv_style_t style_mod;
lv_style_copy(&style_mod, style); lv_style_copy(&style_mod, style);
style_mod.text.color = style->image.color; style_mod.text.color = style->image.color;
lv_draw_label(&coords, clip_area, &style_mod, opa_scale, ext->src, LV_TXT_FLAG_NONE, NULL, NULL, NULL); lv_draw_label(&coords, clip_area, &style_mod, opa_scale, ext->src, LV_TXT_FLAG_NONE, NULL, NULL, NULL, lv_obj_get_base_dir(img));
} else { } else {
/*Trigger the error handler of image drawer*/ /*Trigger the error handler of image drawer*/
LV_LOG_WARN("lv_img_design: image source type is unknown"); LV_LOG_WARN("lv_img_design: image source type is unknown");

View File

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

View File

@@ -396,7 +396,7 @@ void lv_kb_def_event_cb(lv_obj_t * kb, lv_event_t event)
/*Add the characters to the text area if set*/ /*Add the characters to the text area if set*/
if(ext->ta == NULL) return; if(ext->ta == NULL) return;
if(strcmp(txt, LV_SYMBOL_NEW_LINE) == 0) if(strcmp(txt, "Enter") == 0 || strcmp(txt, LV_SYMBOL_NEW_LINE) == 0)
lv_ta_add_char(ext->ta, '\n'); lv_ta_add_char(ext->ta, '\n');
else if(strcmp(txt, LV_SYMBOL_LEFT) == 0) else if(strcmp(txt, LV_SYMBOL_LEFT) == 0)
lv_ta_cursor_left(ext->ta); lv_ta_cursor_left(ext->ta);

View File

@@ -205,12 +205,8 @@ void lv_label_set_text(lv_obj_t * label, const char * text)
LV_ASSERT_MEM(ext->text); LV_ASSERT_MEM(ext->text);
if(ext->text == NULL) return; if(ext->text == NULL) return;
#if LV_USE_BIDI == 0
strcpy(ext->text, text); strcpy(ext->text, text);
#else
lv_bidi_dir_t base_dir = lv_obj_get_base_dir(label);
lv_bidi_process(text, ext->text, base_dir);
#endif
/*Now the text is dynamically allocated*/ /*Now the text is dynamically allocated*/
ext->static_txt = 0; ext->static_txt = 0;
} }
@@ -582,7 +578,7 @@ uint16_t lv_label_get_anim_speed(const lv_obj_t * label)
* index (different in UTF-8) * index (different in UTF-8)
* @param pos store the result here (E.g. index = 0 gives 0;0 coordinates) * @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_OBJ(label, LV_OBJX_NAME);
LV_ASSERT_NULL(pos); LV_ASSERT_NULL(pos);
@@ -610,12 +606,12 @@ void lv_label_get_letter_pos(const lv_obj_t * label, uint16_t index, lv_point_t
max_w = LV_COORD_MAX; 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 */; /*Search the line of the index letter */;
while(txt[new_line_start] != '\0') { 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); 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'*/ break; /*The line of 'index' letter begins at 'line_start'*/
y += letter_height + style->text.line_space; y += letter_height + style->text.line_space;
@@ -623,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 the last character is line break then go to the next line*/
if(index > 0) { if(byte_id > 0) {
if((txt[index - 1] == '\n' || txt[index - 1] == '\r') && txt[index] == '\0') { if((txt[byte_id - 1] == '\n' || txt[byte_id - 1] == '\r') && txt[byte_id] == '\0') {
y += letter_height + style->text.line_space; y += letter_height + style->text.line_space;
line_start = index; line_start = byte_id;
} }
} }
/*Calculate the x coordinate*/ const char *bidi_txt;
lv_coord_t x = lv_txt_get_width(&txt[line_start], index - line_start, font, style->text.letter_space, flag); 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);
if(index != line_start) x += style->text.letter_space; 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(bidi_txt, visual_byte_pos, font, style->text.letter_space, flag);
if(char_id != line_start) x += style->text.letter_space;
if(align == LV_LABEL_ALIGN_CENTER) { if(align == LV_LABEL_ALIGN_CENTER) {
lv_coord_t line_w; lv_coord_t line_w;
line_w = lv_txt_get_width(&txt[line_start], new_line_start - line_start, font, style->text.letter_space, flag); line_w = lv_txt_get_width(bidi_txt, new_line_start - line_start, font, style->text.letter_space, flag);
x += lv_obj_get_width(label) / 2 - line_w / 2; x += lv_obj_get_width(label) / 2 - line_w / 2;
} else if(align == LV_LABEL_ALIGN_RIGHT) { } else if(align == LV_LABEL_ALIGN_RIGHT) {
lv_coord_t line_w; lv_coord_t line_w;
line_w = lv_txt_get_width(&txt[line_start], new_line_start - line_start, font, style->text.letter_space, flag); line_w = lv_txt_get_width(bidi_txt, new_line_start - line_start, font, style->text.letter_space, flag);
x += lv_obj_get_width(label) - line_w; x += lv_obj_get_width(label) - line_w;
} }
@@ -672,6 +692,8 @@ uint16_t lv_label_get_letter_on(const lv_obj_t * label, lv_point_t * pos)
uint8_t letter_height = lv_font_get_line_height(font); uint8_t letter_height = lv_font_get_line_height(font);
lv_coord_t y = 0; lv_coord_t y = 0;
lv_txt_flag_t flag = LV_TXT_FLAG_NONE; lv_txt_flag_t flag = LV_TXT_FLAG_NONE;
uint16_t logical_pos;
char *bidi_txt;
if(ext->recolor != 0) flag |= LV_TXT_FLAG_RECOLOR; if(ext->recolor != 0) flag |= LV_TXT_FLAG_RECOLOR;
if(ext->expand != 0) flag |= LV_TXT_FLAG_EXPAND; if(ext->expand != 0) flag |= LV_TXT_FLAG_EXPAND;
@@ -689,43 +711,60 @@ uint16_t lv_label_get_letter_on(const lv_obj_t * label, lv_point_t * pos)
while(txt[line_start] != '\0') { while(txt[line_start] != '\0') {
new_line_start += lv_txt_get_next_line(&txt[line_start], font, style->text.letter_space, max_w, flag); new_line_start += lv_txt_get_next_line(&txt[line_start], font, style->text.letter_space, max_w, flag);
if(pos->y <= y + letter_height) break; /*The line is found (stored in 'line_start')*/ if(pos->y <= y + letter_height) {
/*The line is found (stored in 'line_start')*/
/* Include the NULL terminator in the last line */
uint32_t tmp = new_line_start;
uint32_t letter;
letter = lv_txt_encoded_prev(txt, &tmp);
if(letter != '\n' && txt[new_line_start] == '\0' ) new_line_start++;
break;
}
y += letter_height + style->text.line_space; y += letter_height + style->text.line_space;
line_start = new_line_start; line_start = new_line_start;
} }
#if LV_USE_BIDI
bidi_txt = lv_draw_get_buf(new_line_start - line_start + 1);
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 = (char*)txt + line_start;
#endif
/*Calculate the x coordinate*/ /*Calculate the x coordinate*/
lv_coord_t x = 0; lv_coord_t x = 0;
if(align == LV_LABEL_ALIGN_CENTER) { if(align == LV_LABEL_ALIGN_CENTER) {
lv_coord_t line_w; lv_coord_t line_w;
line_w = lv_txt_get_width(&txt[line_start], new_line_start - line_start, font, style->text.letter_space, flag); line_w = lv_txt_get_width(bidi_txt, new_line_start - line_start, font, style->text.letter_space, flag);
x += lv_obj_get_width(label) / 2 - line_w / 2; x += lv_obj_get_width(label) / 2 - line_w / 2;
} }
else if(align == LV_LABEL_ALIGN_RIGHT) { else if(align == LV_LABEL_ALIGN_RIGHT) {
lv_coord_t line_w; lv_coord_t line_w;
line_w = lv_txt_get_width(&txt[line_start], new_line_start - line_start, font, style->text.letter_space, flag); line_w = lv_txt_get_width(bidi_txt, new_line_start - line_start, font, style->text.letter_space, flag);
x += lv_obj_get_width(label) - line_w; x += lv_obj_get_width(label) - line_w;
} }
lv_txt_cmd_state_t cmd_state = LV_TXT_CMD_STATE_WAIT; lv_txt_cmd_state_t cmd_state = LV_TXT_CMD_STATE_WAIT;
uint32_t i = line_start; uint32_t i = 0;
uint32_t i_act = i; uint32_t i_act = i;
uint32_t letter; uint32_t letter;
uint32_t letter_next; uint32_t letter_next;
if(new_line_start > 0) { if(new_line_start > 0) {
while(i < new_line_start) { while(i + line_start < new_line_start) {
/* Get the current letter.*/ /* Get the current letter.*/
letter = lv_txt_encoded_next(txt, &i); letter = lv_txt_encoded_next(bidi_txt, &i);
/*Get the next letter too for kerning*/ /*Get the next letter too for kerning*/
letter_next = lv_txt_encoded_next(&txt[i], NULL); letter_next = lv_txt_encoded_next(&bidi_txt[i], NULL);
/*Handle the recolor command*/ /*Handle the recolor command*/
if((flag & LV_TXT_FLAG_RECOLOR) != 0) { if((flag & LV_TXT_FLAG_RECOLOR) != 0) {
if(lv_txt_is_cmd(&cmd_state, txt[i]) != false) { if(lv_txt_is_cmd(&cmd_state, bidi_txt[i]) != false) {
continue; /*Skip the letter is it is part of a command*/ continue; /*Skip the letter is it is part of a command*/
} }
} }
@@ -733,7 +772,7 @@ uint16_t lv_label_get_letter_on(const lv_obj_t * label, lv_point_t * pos)
x += lv_font_get_glyph_width(font, letter, letter_next); x += lv_font_get_glyph_width(font, letter, letter_next);
/*Finish if the x position or the last char of the line is reached*/ /*Finish if the x position or the last char of the line is reached*/
if(pos->x < x || i == new_line_start) { if(pos->x < x || i + line_start == new_line_start) {
i = i_act; i = i_act;
break; break;
} }
@@ -742,7 +781,16 @@ uint16_t lv_label_get_letter_on(const lv_obj_t * label, lv_point_t * pos)
} }
} }
return lv_encoded_get_char_id(txt, i); #if LV_USE_BIDI
/*Handle Bidi*/
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);
} }
/** /**
@@ -803,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); uint8_t letter_height = lv_font_get_line_height(font);
lv_coord_t y = 0; lv_coord_t y = 0;
lv_txt_flag_t flag = LV_TXT_FLAG_NONE; lv_txt_flag_t flag = LV_TXT_FLAG_NONE;
lv_label_align_t align = lv_label_get_align(label);
if(ext->recolor != 0) flag |= LV_TXT_FLAG_RECOLOR; if(ext->recolor != 0) flag |= LV_TXT_FLAG_RECOLOR;
if(ext->expand != 0) flag |= LV_TXT_FLAG_EXPAND; if(ext->expand != 0) flag |= LV_TXT_FLAG_EXPAND;
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 the width will be expanded set the max length to very big */
if(ext->long_mode == LV_LABEL_LONG_EXPAND) { if(ext->long_mode == LV_LABEL_LONG_EXPAND) {
@@ -826,11 +875,16 @@ bool lv_label_is_char_under_pos(const lv_obj_t * label, lv_point_t * pos)
/*Calculate the x coordinate*/ /*Calculate the x coordinate*/
lv_coord_t x = 0; lv_coord_t x = 0;
lv_coord_t last_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; 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(&txt[line_start], new_line_start - line_start, font, style->text.letter_space, flag);
x += lv_obj_get_width(label) / 2 - line_w / 2; x += lv_obj_get_width(label) / 2 - line_w / 2;
} }
else if(align == LV_LABEL_ALIGN_RIGHT) {
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; lv_txt_cmd_state_t cmd_state = LV_TXT_CMD_STATE_WAIT;
@@ -915,8 +969,6 @@ void lv_label_ins_text(lv_obj_t * label, uint32_t pos, const char * txt)
lv_mem_free(bidi_buf); lv_mem_free(bidi_buf);
#else #else
lv_txt_ins(ext->text, pos, txt); lv_txt_ins(ext->text, pos, txt);
#endif
lv_label_refr_text(label); lv_label_refr_text(label);
} }
@@ -1024,7 +1076,12 @@ static lv_design_res_t lv_label_design(lv_obj_t * label, const lv_area_t * clip_
sel.start = lv_label_get_text_sel_start(label); sel.start = lv_label_get_text_sel_start(label);
sel.end = lv_label_get_text_sel_end(label); sel.end = lv_label_get_text_sel_end(label);
<<<<<<< HEAD
lv_draw_label(&coords, clip_area, style, opa_scale, ext->text, flag, &ext->offset, &sel, hint); lv_draw_label(&coords, clip_area, style, opa_scale, ext->text, flag, &ext->offset, &sel, hint);
=======
lv_draw_label(&coords, mask, style, opa_scale, ext->text, flag, &ext->offset, &sel, hint, lv_obj_get_base_dir(label));
>>>>>>> dev-6.1
if(ext->long_mode == LV_LABEL_LONG_SROLL_CIRC) { if(ext->long_mode == LV_LABEL_LONG_SROLL_CIRC) {
lv_point_t size; lv_point_t size;
@@ -1039,15 +1096,23 @@ static lv_design_res_t lv_label_design(lv_obj_t * label, const lv_area_t * clip_
lv_font_get_glyph_width(style->text.font, ' ', ' ') * LV_LABEL_WAIT_CHAR_COUNT; lv_font_get_glyph_width(style->text.font, ' ', ' ') * LV_LABEL_WAIT_CHAR_COUNT;
ofs.y = ext->offset.y; ofs.y = ext->offset.y;
<<<<<<< HEAD
lv_draw_label(&coords, clip_area, style, opa_scale, ext->text, flag, &ofs, &sel, NULL); lv_draw_label(&coords, clip_area, style, opa_scale, ext->text, flag, &ofs, &sel, NULL);
lv_draw_label(&coords, clip_area, style, opa_scale, ext->text, flag, &ofs, &sel, NULL); lv_draw_label(&coords, clip_area, style, opa_scale, ext->text, flag, &ofs, &sel, NULL);
=======
lv_draw_label(&coords, mask, style, opa_scale, ext->text, flag, &ofs, &sel, NULL, lv_obj_get_base_dir(label));
>>>>>>> dev-6.1
} }
/*Draw the text again below the original to make an circular effect */ /*Draw the text again below the original to make an circular effect */
if(size.y > lv_obj_get_height(label)) { if(size.y > lv_obj_get_height(label)) {
ofs.x = ext->offset.x; ofs.x = ext->offset.x;
ofs.y = ext->offset.y + size.y + lv_font_get_line_height(style->text.font); ofs.y = ext->offset.y + size.y + lv_font_get_line_height(style->text.font);
<<<<<<< HEAD
lv_draw_label(&coords, clip_area, style, opa_scale, ext->text, flag, &ofs, &sel, NULL); lv_draw_label(&coords, clip_area, style, opa_scale, ext->text, flag, &ofs, &sel, NULL);
=======
lv_draw_label(&coords, mask, style, opa_scale, ext->text, flag, &ofs, &sel, NULL, lv_obj_get_base_dir(label));
>>>>>>> dev-6.1
} }
} }
} }

View File

@@ -177,6 +177,21 @@ void lv_lmeter_set_scale(lv_obj_t * lmeter, uint16_t angle, uint8_t line_cnt)
lv_obj_invalidate(lmeter); lv_obj_invalidate(lmeter);
} }
/**
* Set the angle settings of a line meter
* @param lmeter pointer to a line meter object
* @param angle angle where the meter will be facing (with its center)
*/
void lv_lmeter_set_angle(lv_obj_t * lmeter, uint16_t angle)
{
lv_lmeter_ext_t * ext = lv_obj_get_ext_attr(lmeter);
if(ext->angle == angle) return;
ext->angle = angle;
lv_obj_invalidate(lmeter);
}
/*===================== /*=====================
* Getter functions * Getter functions
*====================*/ *====================*/
@@ -287,7 +302,7 @@ static lv_design_res_t lv_lmeter_design(lv_obj_t * lmeter, const lv_area_t * cli
lv_coord_t x_ofs = lv_obj_get_width(lmeter) / 2 + lmeter->coords.x1; lv_coord_t x_ofs = lv_obj_get_width(lmeter) / 2 + lmeter->coords.x1;
lv_coord_t y_ofs = lv_obj_get_height(lmeter) / 2 + lmeter->coords.y1; lv_coord_t y_ofs = lv_obj_get_height(lmeter) / 2 + lmeter->coords.y1;
int16_t angle_ofs = 90 + (360 - ext->scale_angle) / 2; int16_t angle_ofs = ext->angle + 90 + (360 - ext->scale_angle) / 2;
int16_t level = int16_t level =
(int32_t)((int32_t)(ext->cur_value - ext->min_value) * ext->line_cnt) / (ext->max_value - ext->min_value); (int32_t)((int32_t)(ext->cur_value - ext->min_value) * ext->line_cnt) / (ext->max_value - ext->min_value);
uint8_t i; uint8_t i;

View File

@@ -36,6 +36,7 @@ typedef struct
/*No inherited ext.*/ /*Ext. of ancestor*/ /*No inherited ext.*/ /*Ext. of ancestor*/
/*New data for this type */ /*New data for this type */
uint16_t scale_angle; /*Angle of the scale in deg. (0..360)*/ uint16_t scale_angle; /*Angle of the scale in deg. (0..360)*/
uint16_t angle;
uint8_t line_cnt; /*Count of lines */ uint8_t line_cnt; /*Count of lines */
int16_t cur_value; int16_t cur_value;
int16_t min_value; int16_t min_value;
@@ -88,6 +89,13 @@ void lv_lmeter_set_range(lv_obj_t * lmeter, int16_t min, int16_t max);
*/ */
void lv_lmeter_set_scale(lv_obj_t * lmeter, uint16_t angle, uint8_t line_cnt); void lv_lmeter_set_scale(lv_obj_t * lmeter, uint16_t angle, uint8_t line_cnt);
/**
* Set the rotation settings of a line meter
* @param lmeter pointer to a line meter object
* @param angle angle of rotation (relative to the northen axis)
*/
void lv_lmeter_set_angle(lv_obj_t * lmeter, uint16_t angle);
/** /**
* Set the styles of a line meter * Set the styles of a line meter
* @param lmeter pointer to a line meter object * @param lmeter pointer to a line meter object

View File

@@ -397,7 +397,7 @@ static lv_design_res_t lv_roller_design(lv_obj_t * roller, const lv_area_t * cli
new_style.text.color = sel_style->text.color; new_style.text.color = sel_style->text.color;
new_style.text.opa = sel_style->text.opa; new_style.text.opa = sel_style->text.opa;
lv_draw_label(&ext->ddlist.label->coords, &mask_sel, &new_style, opa_scale, 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

@@ -12,6 +12,7 @@
#include "../lv_core/lv_debug.h" #include "../lv_core/lv_debug.h"
#include "../lv_core/lv_group.h" #include "../lv_core/lv_group.h"
#include "../lv_core/lv_indev.h"
#include "../lv_draw/lv_draw.h" #include "../lv_draw/lv_draw.h"
#include "../lv_themes/lv_theme.h" #include "../lv_themes/lv_theme.h"
#include "../lv_misc/lv_math.h" #include "../lv_misc/lv_math.h"

View File

@@ -18,6 +18,7 @@
#include "../lv_core/lv_debug.h" #include "../lv_core/lv_debug.h"
#include "../lv_themes/lv_theme.h" #include "../lv_themes/lv_theme.h"
#include "../lv_misc/lv_math.h" #include "../lv_misc/lv_math.h"
#include "../lv_core/lv_indev.h"
/********************* /*********************
* DEFINES * DEFINES

View File

@@ -1391,7 +1391,7 @@ static lv_design_res_t lv_ta_scrollable_design(lv_obj_t * scrl, const lv_area_t
cur_area.x1 += cur_style.body.padding.left; cur_area.x1 += cur_style.body.padding.left;
cur_area.y1 += cur_style.body.padding.top; cur_area.y1 += cur_style.body.padding.top;
lv_draw_label(&cur_area, clip_area, &cur_style, opa_scale, letter_buf, LV_TXT_FLAG_NONE, NULL, NULL, NULL); lv_draw_label(&cur_area, clip_area, &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) { } else if(ext->cursor.type == LV_CURSOR_OUTLINE) {
cur_style.body.opa = LV_OPA_TRANSP; cur_style.body.opa = LV_OPA_TRANSP;
@@ -1889,7 +1889,7 @@ static void update_cursor_position_on_click(lv_obj_t * ta, lv_signal_t sign, lv_
if(!ext->text_sel_in_prog && !click_outside_label && sign == LV_SIGNAL_PRESSED) { if(!ext->text_sel_in_prog && !click_outside_label && sign == LV_SIGNAL_PRESSED) {
/*Input device just went down. Store the selection start position*/ /*Input device just went down. Store the selection start position*/
ext->sel.start = char_id_at_click; ext->sel.start = char_id_at_click;
ext->sel.end = LV_DRAW_LABEL_NO_TXT_SEL; ext->sel.end = LV_LABEL_TEXT_SEL_OFF;
ext->text_sel_in_prog = 1; ext->text_sel_in_prog = 1;
lv_obj_set_drag(lv_page_get_scrl(ta), false); lv_obj_set_drag(lv_page_get_scrl(ta), false);
} else if(ext->text_sel_in_prog && sign == LV_SIGNAL_PRESSING) { } else if(ext->text_sel_in_prog && sign == LV_SIGNAL_PRESSING) {

View File

@@ -145,14 +145,14 @@ void lv_table_set_cell_value(lv_obj_t * table, uint16_t row, uint16_t col, const
uint32_t cell = row * ext->col_cnt + col; uint32_t cell = row * ext->col_cnt + col;
lv_table_cell_format_t format; lv_table_cell_format_t format;
lv_bidi_dir_t base_dir = lv_obj_get_base_dir(table);
/*Save the format byte*/ /*Save the format byte*/
if(ext->cell_data[cell]) { if(ext->cell_data[cell]) {
format.format_byte = ext->cell_data[cell][0]; format.format_byte = ext->cell_data[cell][0];
} }
/*Initialize the format byte*/ /*Initialize the format byte*/
else { else {
#if LV_USE_BIDI
lv_bidi_dir_t base_dir = lv_obj_get_base_dir(table);
if(base_dir == LV_BIDI_DIR_LTR) format.s.align = LV_LABEL_ALIGN_LEFT; 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_RTL) format.s.align = LV_LABEL_ALIGN_RIGHT;
else if(base_dir == LV_BIDI_DIR_AUTO) else if(base_dir == LV_BIDI_DIR_AUTO)
@@ -167,12 +167,7 @@ void lv_table_set_cell_value(lv_obj_t * table, uint16_t row, uint16_t col, const
} }
ext->cell_data[cell] = lv_mem_realloc(ext->cell_data[cell], strlen(txt) + 2); /*+1: trailing '\0; +1: format byte*/ ext->cell_data[cell] = lv_mem_realloc(ext->cell_data[cell], strlen(txt) + 2); /*+1: trailing '\0; +1: format byte*/
#if LV_USE_BIDI == 0
strcpy(ext->cell_data[cell] + 1, txt); /*+1 to skip the format byte*/ strcpy(ext->cell_data[cell] + 1, txt); /*+1 to skip the format byte*/
#else
lv_bidi_process(txt, ext->cell_data[cell] + 1, base_dir);
#endif
ext->cell_data[cell][0] = format.format_byte; ext->cell_data[cell][0] = format.format_byte;
refr_size(table); refr_size(table);
@@ -744,7 +739,7 @@ static lv_design_res_t lv_table_design(lv_obj_t * table, const lv_area_t * clip_
label_mask_ok = lv_area_intersect(&label_mask, clip_area, &cell_area); label_mask_ok = lv_area_intersect(&label_mask, clip_area, &cell_area);
if(label_mask_ok) { if(label_mask_ok) {
lv_draw_label(&txt_area, &label_mask, cell_style, opa_scale, ext->cell_data[cell] + 1, 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*/ /*Draw lines after '\n's*/
lv_point_t p1; lv_point_t p1;