From 62c6ede15e54844ae5853bedfc8e3486ddf7dd72 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Mon, 23 Sep 2019 14:17:27 +0200 Subject: [PATCH 01/51] bidi: first attempt to get runs --- src/lv_misc/lv_txt.c | 96 ++++++++++++++++++++++++++++++++++++++++++++ src/lv_misc/lv_txt.h | 3 ++ 2 files changed, 99 insertions(+) diff --git a/src/lv_misc/lv_txt.c b/src/lv_misc/lv_txt.c index 8b35c7149..85daa0a9f 100644 --- a/src/lv_misc/lv_txt.c +++ b/src/lv_misc/lv_txt.c @@ -346,6 +346,102 @@ void lv_txt_cut(char * txt, uint32_t pos, uint32_t len) } } +typedef enum +{ + LV_TXT_DIR_LTR, + LV_TXT_DIR_RTL, + LV_TXT_DIR_NEUTRAL, + LV_TXT_DIR_WEAK, +}lv_txt_dir_t; + +lv_txt_dir_t lv_txt_get_letter_dir(uint32_t letter) +{ + + if(letter >= 'a' && letter <= 'z') return LV_TXT_DIR_RTL; + + uint16_t i; + + static const char neutrals[] = " \t\n\r"; + for(i = 0; neutrals[i] != '\0'; i++) { + if(letter == neutrals[i]) return LV_TXT_DIR_NEUTRAL; + } + + static const char weaks[] = "0123456789'\"`!?%/\\=()[]{}<>@#&|"; + for(i = 0; weaks[i] != '\0'; i++) { + if(letter == weaks[i]) return LV_TXT_DIR_WEAK; + } + + return LV_TXT_DIR_LTR; +} + + +lv_txt_dir_t lv_txt_rtl_next_run(const char * txt, lv_txt_dir_t base_dir, uint32_t * len) +{ + uint32_t i = 0; + uint32_t letter; + + letter = lv_txt_encoded_next(txt, &i); + + lv_txt_dir_t dir = lv_txt_get_letter_dir(letter); + + /*Find the first strong char. Skip the neutrals.*/ + while(dir == LV_TXT_DIR_NEUTRAL || dir == LV_TXT_DIR_WEAK) { + letter = lv_txt_encoded_next(txt, &i); + dir = lv_txt_get_letter_dir(letter); + if(txt[i] == '\0') return base_dir; + } + + lv_txt_dir_t run_dir = dir; + + uint32_t i_prev = i; + uint32_t i_last_strong = 1; + + /*Find the next char which has different direction*/ + while(txt[i] != '\0') { + letter = lv_txt_encoded_next(txt, &i); + lv_txt_dir_t next_dir = lv_txt_get_letter_dir(letter); + + /*New dir found?*/ + if((next_dir == LV_TXT_DIR_RTL || next_dir == LV_TXT_DIR_LTR) && next_dir != run_dir) { + /*Include neutrals if `run_dir == base_dir` */ + if(run_dir == base_dir) *len = i_prev; + /*Exclude neutrals if `run_dir != base_dir` */ + else *len = i_last_strong; + + return run_dir; + } + + if(next_dir != LV_TXT_DIR_NEUTRAL) i_last_strong = i; + + i_prev = i; + } + + *len = i; + + return run_dir; +} + + + +bool lv_txt_rtl_proc(const char * str_in, char * str_out) +{ + + uint32_t run_len = 0; + lv_txt_dir_t run_dir; + uint32_t rd = 0; + + while(str_in[rd] != '\0') { + run_dir = lv_txt_rtl_next_run(&str_in[rd], LV_TXT_DIR_LTR, &run_len); + + memcpy(str_out, &str_in[rd], run_len); + str_out[run_len] = '\0'; + printf("%s: \"%s\"\n", run_dir == LV_TXT_DIR_LTR ? "LTR" : "RTL", str_out); + rd += run_len; + } + + return true; +} + #if LV_TXT_ENC == LV_TXT_ENC_UTF8 /******************************* * UTF-8 ENCODER/DECOER diff --git a/src/lv_misc/lv_txt.h b/src/lv_misc/lv_txt.h index 6fc6e4a63..ec25ea79d 100644 --- a/src/lv_misc/lv_txt.h +++ b/src/lv_misc/lv_txt.h @@ -128,6 +128,9 @@ void lv_txt_ins(char * txt_buf, uint32_t pos, const char * ins_txt); */ void lv_txt_cut(char * txt, uint32_t pos, uint32_t len); + +bool lv_txt_rtl_proc(const char * str_in, char * str_out); + /*************************************************************** * GLOBAL FUNCTION POINTERS FOR CAHRACTER ENCODING INTERFACE ***************************************************************/ From 2c5c4abdcedfd527d0072c7b37ed9fde6cd8a369 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Mon, 23 Sep 2019 14:24:15 +0200 Subject: [PATCH 02/51] bidi: clean up --- src/lv_misc/lv_txt.c | 12 ++---------- src/lv_misc/lv_txt.h | 11 ++++++++++- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/lv_misc/lv_txt.c b/src/lv_misc/lv_txt.c index 85daa0a9f..ab872e463 100644 --- a/src/lv_misc/lv_txt.c +++ b/src/lv_misc/lv_txt.c @@ -346,14 +346,6 @@ void lv_txt_cut(char * txt, uint32_t pos, uint32_t len) } } -typedef enum -{ - LV_TXT_DIR_LTR, - LV_TXT_DIR_RTL, - LV_TXT_DIR_NEUTRAL, - LV_TXT_DIR_WEAK, -}lv_txt_dir_t; - lv_txt_dir_t lv_txt_get_letter_dir(uint32_t letter) { @@ -423,7 +415,7 @@ lv_txt_dir_t lv_txt_rtl_next_run(const char * txt, lv_txt_dir_t base_dir, uint32 -bool lv_txt_rtl_proc(const char * str_in, char * str_out) +bool lv_txt_rtl_proc(const char * str_in, char * str_out, lv_txt_dir_t base_dir) { uint32_t run_len = 0; @@ -431,7 +423,7 @@ bool lv_txt_rtl_proc(const char * str_in, char * str_out) uint32_t rd = 0; while(str_in[rd] != '\0') { - run_dir = lv_txt_rtl_next_run(&str_in[rd], LV_TXT_DIR_LTR, &run_len); + run_dir = lv_txt_rtl_next_run(&str_in[rd], base_dir, &run_len); memcpy(str_out, &str_in[rd], run_len); str_out[run_len] = '\0'; diff --git a/src/lv_misc/lv_txt.h b/src/lv_misc/lv_txt.h index ec25ea79d..59e655206 100644 --- a/src/lv_misc/lv_txt.h +++ b/src/lv_misc/lv_txt.h @@ -56,6 +56,15 @@ enum { }; typedef uint8_t lv_txt_cmd_state_t; + +typedef enum +{ + LV_TXT_DIR_LTR, + LV_TXT_DIR_RTL, + LV_TXT_DIR_NEUTRAL, + LV_TXT_DIR_WEAK, +}lv_txt_dir_t; + /********************** * GLOBAL PROTOTYPES **********************/ @@ -129,7 +138,7 @@ void lv_txt_ins(char * txt_buf, uint32_t pos, const char * ins_txt); void lv_txt_cut(char * txt, uint32_t pos, uint32_t len); -bool lv_txt_rtl_proc(const char * str_in, char * str_out); +bool lv_txt_rtl_proc(const char * str_in, char * str_out, lv_txt_dir_t base_dir); /*************************************************************** * GLOBAL FUNCTION POINTERS FOR CAHRACTER ENCODING INTERFACE From bddf31824ca4d5cd322caba1796513af8c6e9a54 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Tue, 24 Sep 2019 10:30:58 +0200 Subject: [PATCH 03/51] bidi: handle starting and trailing neutrals --- src/lv_misc/lv_txt.c | 43 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 36 insertions(+), 7 deletions(-) diff --git a/src/lv_misc/lv_txt.c b/src/lv_misc/lv_txt.c index ab872e463..87b1ad15d 100644 --- a/src/lv_misc/lv_txt.c +++ b/src/lv_misc/lv_txt.c @@ -353,7 +353,7 @@ lv_txt_dir_t lv_txt_get_letter_dir(uint32_t letter) uint16_t i; - static const char neutrals[] = " \t\n\r"; + static const char neutrals[] = " \t\n\r.,:;"; for(i = 0; neutrals[i] != '\0'; i++) { if(letter == neutrals[i]) return LV_TXT_DIR_NEUTRAL; } @@ -372,26 +372,29 @@ lv_txt_dir_t lv_txt_rtl_next_run(const char * txt, lv_txt_dir_t base_dir, uint32 uint32_t i = 0; uint32_t letter; - letter = lv_txt_encoded_next(txt, &i); - + letter = lv_txt_encoded_next(txt, NULL); lv_txt_dir_t dir = lv_txt_get_letter_dir(letter); /*Find the first strong char. Skip the neutrals.*/ while(dir == LV_TXT_DIR_NEUTRAL || dir == LV_TXT_DIR_WEAK) { letter = lv_txt_encoded_next(txt, &i); dir = lv_txt_get_letter_dir(letter); - if(txt[i] == '\0') return base_dir; + if(txt[i] == '\0') { + *len = i; + return base_dir; + } } lv_txt_dir_t run_dir = dir; uint32_t i_prev = i; - uint32_t i_last_strong = 1; + uint32_t i_last_strong = i; /*Find the next char which has different direction*/ + lv_txt_dir_t next_dir = base_dir; while(txt[i] != '\0') { letter = lv_txt_encoded_next(txt, &i); - lv_txt_dir_t next_dir = lv_txt_get_letter_dir(letter); + next_dir = lv_txt_get_letter_dir(letter); /*New dir found?*/ if((next_dir == LV_TXT_DIR_RTL || next_dir == LV_TXT_DIR_LTR) && next_dir != run_dir) { @@ -408,9 +411,16 @@ lv_txt_dir_t lv_txt_rtl_next_run(const char * txt, lv_txt_dir_t base_dir, uint32 i_prev = i; } - *len = i; + + /*Handle end of of string. Apply `base_dir` on trailing neutrals*/ + + /*Include neutrals if `run_dir == base_dir` */ + if(run_dir == base_dir) *len = i_prev; + /*Exclude neutrals if `run_dir != base_dir` */ + else *len = i_last_strong; return run_dir; + } @@ -422,6 +432,25 @@ bool lv_txt_rtl_proc(const char * str_in, char * str_out, lv_txt_dir_t base_dir) lv_txt_dir_t run_dir; uint32_t rd = 0; + lv_txt_dir_t dir = base_dir; + + /*Process neutral chars in the beginning*/ + while(str_in[rd] != '\0') { + uint32_t letter = lv_txt_encoded_next(str_in, &rd); + dir = lv_txt_get_letter_dir(letter); + if(dir != LV_TXT_DIR_NEUTRAL) break; + } + + /*if there were neutrals in the beginning apply `base_dir` on them */ + if(rd && str_in[rd] != '\0') lv_txt_encoded_prev(str_in, &rd); + + if(rd) { + memcpy(str_out, str_in, rd); + str_out[rd] = '\0'; + printf("%s: \"%s\"\n", base_dir == LV_TXT_DIR_LTR ? "LTR" : "RTL", str_out); + } + + /*Get and process the runs*/ while(str_in[rd] != '\0') { run_dir = lv_txt_rtl_next_run(&str_in[rd], base_dir, &run_len); From 7ef624054a7ac224f648fa85a767d1d854b78559 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Tue, 24 Sep 2019 10:50:43 +0200 Subject: [PATCH 04/51] bidi: update list weak and neutral chars --- src/lv_misc/lv_txt.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lv_misc/lv_txt.c b/src/lv_misc/lv_txt.c index 87b1ad15d..85e81d064 100644 --- a/src/lv_misc/lv_txt.c +++ b/src/lv_misc/lv_txt.c @@ -353,12 +353,12 @@ lv_txt_dir_t lv_txt_get_letter_dir(uint32_t letter) uint16_t i; - static const char neutrals[] = " \t\n\r.,:;"; + static const char neutrals[] = " \t\n\r.,:;'\"`!?%/\\=()[]{}<>@#&|"; for(i = 0; neutrals[i] != '\0'; i++) { if(letter == neutrals[i]) return LV_TXT_DIR_NEUTRAL; } - static const char weaks[] = "0123456789'\"`!?%/\\=()[]{}<>@#&|"; + static const char weaks[] = "0123456789"; for(i = 0; weaks[i] != '\0'; i++) { if(letter == weaks[i]) return LV_TXT_DIR_WEAK; } From 3dfbc5c85dfee85e9a27e045f5d887bcd6a9e5e3 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Tue, 24 Sep 2019 21:00:58 +0200 Subject: [PATCH 05/51] create lv_bidi.c/h --- src/lv_misc/lv_bidi.c | 221 ++++++++++++++++++++++++++++++++++++++++++ src/lv_misc/lv_bidi.h | 52 ++++++++++ src/lv_misc/lv_txt.c | 117 ---------------------- src/lv_misc/lv_txt.h | 12 --- 4 files changed, 273 insertions(+), 129 deletions(-) create mode 100644 src/lv_misc/lv_bidi.c create mode 100644 src/lv_misc/lv_bidi.h diff --git a/src/lv_misc/lv_bidi.c b/src/lv_misc/lv_bidi.c new file mode 100644 index 000000000..2bc9afe2d --- /dev/null +++ b/src/lv_misc/lv_bidi.c @@ -0,0 +1,221 @@ +/** + * @file lv_bidi.c + * + */ + +/********************* + * INCLUDES + *********************/ +#include "lv_bidi.h" +#include +#include "lv_txt.h" + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ + +/********************** + * STATIC PROTOTYPES + **********************/ +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 VARIABLES + **********************/ + +/********************** + * MACROS + **********************/ + +/********************** + * GLOBAL FUNCTIONS + **********************/ + +void lv_bidi_process(const char * str_in, char * str_out, lv_bidi_dir_t base_dir) +{ + uint32_t run_len = 0; + lv_bidi_dir_t run_dir; + uint32_t rd = 0; + + lv_bidi_dir_t dir = base_dir; + + /*Process neutral chars in the beginning*/ + while(str_in[rd] != '\0') { + uint32_t letter = lv_txt_encoded_next(str_in, &rd); + dir = lv_bidi_get_letter_dir(letter); + if(dir != LV_BIDI_DIR_NEUTRAL) break; + } + + /*if there were neutrals in the beginning apply `base_dir` on them */ + if(rd && str_in[rd] != '\0') lv_txt_encoded_prev(str_in, &rd); + + if(rd) { + memcpy(str_out, str_in, rd); + str_out[rd] = '\0'; + printf("%s: \"%s\"\n", base_dir == LV_BIDI_DIR_LTR ? "LTR" : "RTL", str_out); + } + + /*Get and process the runs*/ + while(str_in[rd] != '\0') { + run_dir = get_next_run(&str_in[rd], base_dir, &run_len); + + memcpy(str_out, &str_in[rd], run_len); + str_out[run_len] = '\0'; + if(run_dir == LV_BIDI_DIR_LTR) { + printf("%s: \"%s\"\n", "LTR" , str_out); + } else { + printf("%s: \"%s\" -> ", "RTL" , str_out); + + rtl_reverse(str_out, &str_in[rd], run_len); + printf("\"%s\"\n", str_out); + + } + + rd += run_len; + } +} + + +lv_bidi_dir_t lv_bidi_get_letter_dir(uint32_t letter) +{ + if(lv_bidi_letter_is_rtl(letter)) return LV_BIDI_DIR_RTL; + if(lv_bidi_letter_is_neutral(letter)) return LV_BIDI_DIR_NEUTRAL; + if(lv_bidi_letter_is_weak(letter)) return LV_BIDI_DIR_WEAK; + + return LV_BIDI_DIR_LTR; +} + +bool lv_bidi_letter_is_weak(uint32_t letter) +{ + uint32_t i = 0; + static const char weaks[] = "0123456789"; + + do { + uint32_t x = lv_txt_encoded_next(weaks, &i); + if(letter == x) { + return true; + } + } while(weaks[i] != '\0'); + + return false; +} + +bool lv_bidi_letter_is_rtl(uint32_t letter) +{ + if(letter >= 'a' && letter <= 'z') return true; + + return false; +} + +bool lv_bidi_letter_is_neutral(uint32_t letter) +{ + uint16_t i; + static const char neutrals[] = " \t\n\r.,:;'\"`!?%/\\=()[]{}<>@#&|"; + for(i = 0; neutrals[i] != '\0'; i++) { + if(letter == (uint32_t)neutrals[i]) return true; + } + + return false; +} + + +/********************** + * STATIC FUNCTIONS + **********************/ + +static lv_bidi_dir_t get_next_run(const char * txt, lv_bidi_dir_t base_dir, uint32_t * len) +{ + uint32_t i = 0; + uint32_t letter; + + letter = lv_txt_encoded_next(txt, NULL); + lv_bidi_dir_t dir = lv_bidi_get_letter_dir(letter); + + /*Find the first strong char. Skip the neutrals.*/ + while(dir == LV_BIDI_DIR_NEUTRAL || dir == LV_BIDI_DIR_WEAK) { + letter = lv_txt_encoded_next(txt, &i); + dir = lv_bidi_get_letter_dir(letter); + if(txt[i] == '\0') { + *len = i; + return base_dir; + } + } + + lv_bidi_dir_t run_dir = dir; + + uint32_t i_prev = i; + uint32_t i_last_strong = i; + + /*Find the next char which has different direction*/ + lv_bidi_dir_t next_dir = base_dir; + while(txt[i] != '\0') { + letter = lv_txt_encoded_next(txt, &i); + next_dir = lv_bidi_get_letter_dir(letter); + + /*New dir found?*/ + if((next_dir == LV_BIDI_DIR_RTL || next_dir == LV_BIDI_DIR_LTR) && next_dir != run_dir) { + /*Include neutrals if `run_dir == base_dir` */ + if(run_dir == base_dir) *len = i_prev; + /*Exclude neutrals if `run_dir != base_dir` */ + else *len = i_last_strong; + + return run_dir; + } + + if(next_dir != LV_BIDI_DIR_NEUTRAL) i_last_strong = i; + + i_prev = i; + } + + + /*Handle end of of string. Apply `base_dir` on trailing neutrals*/ + + /*Include neutrals if `run_dir == base_dir` */ + if(run_dir == base_dir) *len = i_prev; + /*Exclude neutrals if `run_dir != base_dir` */ + else *len = i_last_strong; + + return run_dir; + +} + +static void rtl_reverse(char * dest, const char * src, uint32_t len) +{ + uint32_t i = len; + uint32_t wr = 0; + + while(i) { + uint32_t letter = lv_txt_encoded_prev(src, &i); + + /*Keep weak letters as LTR*/ + if(lv_bidi_letter_is_weak(letter)) { + uint32_t last_weak = i; + uint32_t first_weak = i; + while(i) { + letter = lv_txt_encoded_prev(src, &i); + if(lv_bidi_letter_is_weak(letter) == false) { + lv_txt_encoded_next(src, &i); /*Rewind one letter*/ + first_weak = i; + break; + } + } + if(i == 0) first_weak = 0; + + memcpy(&dest[wr], &src[first_weak], last_weak - first_weak + 1); + wr += last_weak - first_weak + 1; + + } + /*Simply store in reversed order*/ + else { + uint32_t letter_size = lv_txt_encoded_size((const char *)&letter); + memcpy(&dest[wr], &src[i], letter_size); + wr += letter_size; + } + } +} + diff --git a/src/lv_misc/lv_bidi.h b/src/lv_misc/lv_bidi.h new file mode 100644 index 000000000..8adbac674 --- /dev/null +++ b/src/lv_misc/lv_bidi.h @@ -0,0 +1,52 @@ +/** + * @file lv_bifi.h + * + */ + +#ifndef LV_BIDI_H +#define LV_BIDI_H + +#ifdef __cplusplus +extern "C" { +#endif + +/********************* + * INCLUDES + *********************/ +#include +#include + +/********************* + * DEFINES + *********************/ + +/********************** + * TYPEDEFS + **********************/ +typedef enum +{ + LV_BIDI_DIR_LTR, + LV_BIDI_DIR_RTL, + LV_BIDI_DIR_NEUTRAL, + LV_BIDI_DIR_WEAK, +}lv_bidi_dir_t; + +/********************** + * GLOBAL PROTOTYPES + **********************/ +void lv_bidi_process(const char * str_in, char * str_out, lv_bidi_dir_t base_dir); + +lv_bidi_dir_t lv_bidi_get_letter_dir(uint32_t letter); +bool lv_bidi_letter_is_weak(uint32_t letter); +bool lv_bidi_letter_is_rtl(uint32_t letter); +bool lv_bidi_letter_is_neutral(uint32_t letter); + +/********************** + * MACROS + **********************/ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /*LV_BIDI_H*/ diff --git a/src/lv_misc/lv_txt.c b/src/lv_misc/lv_txt.c index 85e81d064..8b35c7149 100644 --- a/src/lv_misc/lv_txt.c +++ b/src/lv_misc/lv_txt.c @@ -346,123 +346,6 @@ void lv_txt_cut(char * txt, uint32_t pos, uint32_t len) } } -lv_txt_dir_t lv_txt_get_letter_dir(uint32_t letter) -{ - - if(letter >= 'a' && letter <= 'z') return LV_TXT_DIR_RTL; - - uint16_t i; - - static const char neutrals[] = " \t\n\r.,:;'\"`!?%/\\=()[]{}<>@#&|"; - for(i = 0; neutrals[i] != '\0'; i++) { - if(letter == neutrals[i]) return LV_TXT_DIR_NEUTRAL; - } - - static const char weaks[] = "0123456789"; - for(i = 0; weaks[i] != '\0'; i++) { - if(letter == weaks[i]) return LV_TXT_DIR_WEAK; - } - - return LV_TXT_DIR_LTR; -} - - -lv_txt_dir_t lv_txt_rtl_next_run(const char * txt, lv_txt_dir_t base_dir, uint32_t * len) -{ - uint32_t i = 0; - uint32_t letter; - - letter = lv_txt_encoded_next(txt, NULL); - lv_txt_dir_t dir = lv_txt_get_letter_dir(letter); - - /*Find the first strong char. Skip the neutrals.*/ - while(dir == LV_TXT_DIR_NEUTRAL || dir == LV_TXT_DIR_WEAK) { - letter = lv_txt_encoded_next(txt, &i); - dir = lv_txt_get_letter_dir(letter); - if(txt[i] == '\0') { - *len = i; - return base_dir; - } - } - - lv_txt_dir_t run_dir = dir; - - uint32_t i_prev = i; - uint32_t i_last_strong = i; - - /*Find the next char which has different direction*/ - lv_txt_dir_t next_dir = base_dir; - while(txt[i] != '\0') { - letter = lv_txt_encoded_next(txt, &i); - next_dir = lv_txt_get_letter_dir(letter); - - /*New dir found?*/ - if((next_dir == LV_TXT_DIR_RTL || next_dir == LV_TXT_DIR_LTR) && next_dir != run_dir) { - /*Include neutrals if `run_dir == base_dir` */ - if(run_dir == base_dir) *len = i_prev; - /*Exclude neutrals if `run_dir != base_dir` */ - else *len = i_last_strong; - - return run_dir; - } - - if(next_dir != LV_TXT_DIR_NEUTRAL) i_last_strong = i; - - i_prev = i; - } - - - /*Handle end of of string. Apply `base_dir` on trailing neutrals*/ - - /*Include neutrals if `run_dir == base_dir` */ - if(run_dir == base_dir) *len = i_prev; - /*Exclude neutrals if `run_dir != base_dir` */ - else *len = i_last_strong; - - return run_dir; - -} - - - -bool lv_txt_rtl_proc(const char * str_in, char * str_out, lv_txt_dir_t base_dir) -{ - - uint32_t run_len = 0; - lv_txt_dir_t run_dir; - uint32_t rd = 0; - - lv_txt_dir_t dir = base_dir; - - /*Process neutral chars in the beginning*/ - while(str_in[rd] != '\0') { - uint32_t letter = lv_txt_encoded_next(str_in, &rd); - dir = lv_txt_get_letter_dir(letter); - if(dir != LV_TXT_DIR_NEUTRAL) break; - } - - /*if there were neutrals in the beginning apply `base_dir` on them */ - if(rd && str_in[rd] != '\0') lv_txt_encoded_prev(str_in, &rd); - - if(rd) { - memcpy(str_out, str_in, rd); - str_out[rd] = '\0'; - printf("%s: \"%s\"\n", base_dir == LV_TXT_DIR_LTR ? "LTR" : "RTL", str_out); - } - - /*Get and process the runs*/ - while(str_in[rd] != '\0') { - run_dir = lv_txt_rtl_next_run(&str_in[rd], base_dir, &run_len); - - memcpy(str_out, &str_in[rd], run_len); - str_out[run_len] = '\0'; - printf("%s: \"%s\"\n", run_dir == LV_TXT_DIR_LTR ? "LTR" : "RTL", str_out); - rd += run_len; - } - - return true; -} - #if LV_TXT_ENC == LV_TXT_ENC_UTF8 /******************************* * UTF-8 ENCODER/DECOER diff --git a/src/lv_misc/lv_txt.h b/src/lv_misc/lv_txt.h index 59e655206..6fc6e4a63 100644 --- a/src/lv_misc/lv_txt.h +++ b/src/lv_misc/lv_txt.h @@ -56,15 +56,6 @@ enum { }; typedef uint8_t lv_txt_cmd_state_t; - -typedef enum -{ - LV_TXT_DIR_LTR, - LV_TXT_DIR_RTL, - LV_TXT_DIR_NEUTRAL, - LV_TXT_DIR_WEAK, -}lv_txt_dir_t; - /********************** * GLOBAL PROTOTYPES **********************/ @@ -137,9 +128,6 @@ void lv_txt_ins(char * txt_buf, uint32_t pos, const char * ins_txt); */ void lv_txt_cut(char * txt, uint32_t pos, uint32_t len); - -bool lv_txt_rtl_proc(const char * str_in, char * str_out, lv_txt_dir_t base_dir); - /*************************************************************** * GLOBAL FUNCTION POINTERS FOR CAHRACTER ENCODING INTERFACE ***************************************************************/ From ac269ebaad50b9d537c73eaaa60e7ae9555fa15f Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Fri, 27 Sep 2019 06:03:54 +0200 Subject: [PATCH 06/51] bidi: fixes --- src/lv_misc/lv_bidi.c | 8 ++++++-- src/lv_misc/lv_txt.c | 5 +++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/lv_misc/lv_bidi.c b/src/lv_misc/lv_bidi.c index 2bc9afe2d..e773e7940 100644 --- a/src/lv_misc/lv_bidi.c +++ b/src/lv_misc/lv_bidi.c @@ -38,6 +38,8 @@ static void rtl_reverse(char * dest, const char * src, uint32_t len); void lv_bidi_process(const char * str_in, char * str_out, lv_bidi_dir_t base_dir) { + printf("Input str: \"%s\"\n", str_in); + uint32_t run_len = 0; lv_bidi_dir_t run_dir; uint32_t rd = 0; @@ -107,7 +109,9 @@ bool lv_bidi_letter_is_weak(uint32_t letter) bool lv_bidi_letter_is_rtl(uint32_t letter) { - if(letter >= 'a' && letter <= 'z') return true; +// if(letter >= 0x7f && letter <= 0x2000) return true; + if(letter >= 0x5d0 && letter <= 0x5ea) return true; +// if(letter >= 'a' && letter <= 'z') return true; return false; } @@ -212,7 +216,7 @@ static void rtl_reverse(char * dest, const char * src, uint32_t len) } /*Simply store in reversed order*/ else { - uint32_t letter_size = lv_txt_encoded_size((const char *)&letter); + uint32_t letter_size = lv_txt_encoded_size((const char *)&src[i]); memcpy(&dest[wr], &src[i], letter_size); wr += letter_size; } diff --git a/src/lv_misc/lv_txt.c b/src/lv_misc/lv_txt.c index 8b35c7149..bbab38772 100644 --- a/src/lv_misc/lv_txt.c +++ b/src/lv_misc/lv_txt.c @@ -366,7 +366,7 @@ static uint8_t lv_txt_utf8_size(const char * str) return 3; else if((str[0] & 0xF8) == 0xF0) return 4; - return 1; /*If the char was invalid step tell it's 1 byte long*/ + return 0; /*If the char was invalid tell it's 1 byte long*/ } /** @@ -543,7 +543,8 @@ static uint32_t lv_txt_utf8_get_byte_id(const char * txt, uint32_t utf8_id) uint32_t i; uint32_t byte_cnt = 0; for(i = 0; i < utf8_id; i++) { - byte_cnt += lv_txt_encoded_size(&txt[byte_cnt]); + uint8_t c_size = lv_txt_encoded_size(&txt[byte_cnt]); + byte_cnt += c_size > 0 ? c_size : 1; } return byte_cnt; From a50e5979420e285527cb8404765e5dde6a27ae02 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Sat, 28 Sep 2019 08:40:02 +0200 Subject: [PATCH 07/51] bidi: support currencies in rtl --- src/lv_misc/lv_bidi.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/lv_misc/lv_bidi.c b/src/lv_misc/lv_bidi.c index e773e7940..13d3925ca 100644 --- a/src/lv_misc/lv_bidi.c +++ b/src/lv_misc/lv_bidi.c @@ -119,7 +119,7 @@ bool lv_bidi_letter_is_rtl(uint32_t letter) bool lv_bidi_letter_is_neutral(uint32_t letter) { uint16_t i; - static const char neutrals[] = " \t\n\r.,:;'\"`!?%/\\=()[]{}<>@#&|"; + static const char neutrals[] = " \t\n\r.,:;'\"`!?%/\\=()[]{}<>@#&$|"; for(i = 0; neutrals[i] != '\0'; i++) { if(letter == (uint32_t)neutrals[i]) return true; } @@ -202,7 +202,9 @@ static void rtl_reverse(char * dest, const char * src, uint32_t len) uint32_t first_weak = i; while(i) { letter = lv_txt_encoded_prev(src, &i); - if(lv_bidi_letter_is_weak(letter) == false) { + /*Finish on non-weak char */ + /*but treat number and currency related chars as weak*/ + if(lv_bidi_letter_is_weak(letter) == false && letter != '.' && letter != ',' && letter != '$') { lv_txt_encoded_next(src, &i); /*Rewind one letter*/ first_weak = i; break; From c64dc1d645a311a17899a14b10fa5000e0bce3a6 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Tue, 1 Oct 2019 05:48:46 +0200 Subject: [PATCH 08/51] bidi: compose otput string and swap arithmetical symbols --- src/lv_misc/lv_bidi.c | 84 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 71 insertions(+), 13 deletions(-) diff --git a/src/lv_misc/lv_bidi.c b/src/lv_misc/lv_bidi.c index 13d3925ca..d9839f17e 100644 --- a/src/lv_misc/lv_bidi.c +++ b/src/lv_misc/lv_bidi.c @@ -23,6 +23,7 @@ **********************/ 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 VARIABLES @@ -40,9 +41,17 @@ void lv_bidi_process(const char * str_in, char * str_out, lv_bidi_dir_t base_dir { printf("Input str: \"%s\"\n", str_in); + char print_buf[256]; + uint32_t run_len = 0; lv_bidi_dir_t run_dir; uint32_t rd = 0; + uint32_t wr; + uint32_t in_len = strlen(str_in); + if(base_dir == LV_BIDI_DIR_RTL) wr = in_len; + else wr = 0; + + str_out[in_len] = '\0'; lv_bidi_dir_t dir = base_dir; @@ -57,29 +66,48 @@ void lv_bidi_process(const char * str_in, char * str_out, lv_bidi_dir_t base_dir if(rd && str_in[rd] != '\0') lv_txt_encoded_prev(str_in, &rd); if(rd) { - memcpy(str_out, str_in, rd); - str_out[rd] = '\0'; - printf("%s: \"%s\"\n", base_dir == LV_BIDI_DIR_LTR ? "LTR" : "RTL", str_out); + if(base_dir == LV_BIDI_DIR_LTR) { + memcpy(&str_out[wr], str_in, rd); + wr += rd; + } else { + wr -= rd; + memcpy(&str_out[wr], str_in, rd); + } + memcpy(print_buf, str_in, rd); + print_buf[rd] = '\0'; + printf("%s: \"%s\"\n", base_dir == LV_BIDI_DIR_LTR ? "LTR" : "RTL", print_buf); } /*Get and process the runs*/ while(str_in[rd] != '\0') { run_dir = get_next_run(&str_in[rd], base_dir, &run_len); - memcpy(str_out, &str_in[rd], run_len); - str_out[run_len] = '\0'; + memcpy(print_buf, &str_in[rd], run_len); + print_buf[run_len] = '\0'; if(run_dir == LV_BIDI_DIR_LTR) { - printf("%s: \"%s\"\n", "LTR" , str_out); + printf("%s: \"%s\"\n", "LTR" , print_buf); } else { - printf("%s: \"%s\" -> ", "RTL" , str_out); - - rtl_reverse(str_out, &str_in[rd], run_len); - printf("\"%s\"\n", str_out); + printf("%s: \"%s\" -> ", "RTL" , print_buf); + rtl_reverse(print_buf, &str_in[rd], run_len); + printf("\"%s\"\n", print_buf); } + if(base_dir == LV_BIDI_DIR_LTR) { + if(run_dir == LV_BIDI_DIR_LTR) memcpy(&str_out[wr], &str_in[rd], run_len); + else rtl_reverse(&str_out[wr], &str_in[rd], run_len); + wr += run_len; + } else { + wr -= run_len; + if(run_dir == LV_BIDI_DIR_LTR) memcpy(&str_out[wr], &str_in[rd], run_len); + else rtl_reverse(&str_out[wr], &str_in[rd], run_len); + } + rd += run_len; } + + printf("result: %s\n", str_out); + } @@ -196,12 +224,14 @@ static void rtl_reverse(char * dest, const char * src, uint32_t len) while(i) { uint32_t letter = lv_txt_encoded_prev(src, &i); - /*Keep weak letters as LTR*/ + /*Keep weak letters (numbers) as LTR*/ if(lv_bidi_letter_is_weak(letter)) { uint32_t last_weak = i; uint32_t first_weak = i; while(i) { letter = lv_txt_encoded_prev(src, &i); + /*No need to call `char_change_to_pair` because there not such chars here*/ + /*Finish on non-weak char */ /*but treat number and currency related chars as weak*/ if(lv_bidi_letter_is_weak(letter) == false && letter != '.' && letter != ',' && letter != '$') { @@ -219,9 +249,37 @@ static void rtl_reverse(char * dest, const char * src, uint32_t len) /*Simply store in reversed order*/ else { uint32_t letter_size = lv_txt_encoded_size((const char *)&src[i]); - memcpy(&dest[wr], &src[i], letter_size); - wr += letter_size; + /*Swap arithmetical symbols*/ + if(letter_size == 1) { + uint32_t new_letter = letter = char_change_to_pair(letter); + dest[wr] = (uint8_t)new_letter; + wr += 1; + } + /*Just store the letter*/ + else { + memcpy(&dest[wr], &src[i], letter_size); + wr += letter_size; + } } } } +static uint32_t char_change_to_pair(uint32_t letter) +{ + static uint8_t left[] = {"<({["}; + static uint8_t right[] = {">)}]"}; + + uint8_t i; + for(i = 0; left[i] != '\0'; i++) { + if(letter == left[i]) return right[i]; + } + + for(i = 0; right[i] != '\0'; i++) { + if(letter == right[i]) return left[i]; + } + + return letter; + + +} + From 6190763382edd3a5a18a09d326aa5051305e359e Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Tue, 8 Oct 2019 16:26:55 +0200 Subject: [PATCH 09/51] bidi: add LV_LABEL_ALIGN_AUTO, LV_BIDI_DIR_AOUT/INHERIT, LV_SIGNAL_BASE_DIR_CHG --- lv_conf_template.h | 13 ++++++++ lvgl.h | 1 + src/lv_conf_checker.h | 17 ++++++++++ src/lv_core/lv_obj.c | 69 +++++++++++++++++++++++++++++++++++++++++ src/lv_core/lv_obj.h | 14 +++++++-- src/lv_core/lv_style.c | 4 +-- src/lv_misc/lv_bidi.c | 21 +++++++++++-- src/lv_misc/lv_bidi.h | 24 +++++++++----- src/lv_objx/lv_ddlist.c | 12 ++++++- src/lv_objx/lv_label.c | 51 +++++++++++++++++++++++++----- src/lv_objx/lv_label.h | 10 ++++-- 11 files changed, 211 insertions(+), 25 deletions(-) diff --git a/lv_conf_template.h b/lv_conf_template.h index 08e9beb9e..c616dfa08 100644 --- a/lv_conf_template.h +++ b/lv_conf_template.h @@ -297,6 +297,19 @@ typedef void * lv_font_user_data_t; /*Can break (wrap) texts on these chars*/ #define LV_TXT_BREAK_CHARS " ,.;:-_" +/* Support bidirectional texts. + * Allows mixing Left-to-Right and Right-to-Left texts. + * The direction will be processed according to the Unicode Bidirectioanl Algorithm: + * https://www.w3.org/International/articles/inline-bidi-markup/uba-basics*/ +#define LV_USE_BIDI 1 +#if LV_USE_BIDI +/* Set the default direction. Supported values: + * `LV_BIDI_DIR_LTR` Left-to-Right + * `LV_BIDI_DIR_RTL` Right-to-Left + * `LV_BIDI_DIR_AUTO` detect texts base direction */ +#define LV_BIDI_BASE_DIR_DEF LV_BIDI_DIR_AUTO +#endif + /*=================== * LV_OBJ SETTINGS *==================*/ diff --git a/lvgl.h b/lvgl.h index b6e29b61b..586344832 100644 --- a/lvgl.h +++ b/lvgl.h @@ -33,6 +33,7 @@ extern "C" { #include "src/lv_font/lv_font.h" #include "src/lv_font/lv_font_fmt_txt.h" +#include "src/lv_misc/lv_bidi.h" #include "src/lv_objx/lv_btn.h" #include "src/lv_objx/lv_imgbtn.h" diff --git a/src/lv_conf_checker.h b/src/lv_conf_checker.h index ff7ac05df..c2700e76a 100644 --- a/src/lv_conf_checker.h +++ b/src/lv_conf_checker.h @@ -412,6 +412,23 @@ #define LV_TXT_BREAK_CHARS " ,.;:-_" #endif +/* Support bidirectional texts. + * Allows mixing Left-to-Right and Right-to-Left texts. + * The direction will be processed according to the Unicode Bidirectioanl Algorithm: + * https://www.w3.org/International/articles/inline-bidi-markup/uba-basics*/ +#ifndef LV_USE_BIDI +#define LV_USE_BIDI 1 +#endif +#if LV_USE_BIDI +/* Set the default direction. Supported values: + * `LV_BIDI_DIR_LTR` Left-to-Right + * `LV_BIDI_DIR_RTL` Right-to-Left + * `LV_BIDI_DIR_AUTO` detect texts base direction */ +#ifndef LV_BIDI_BASE_DIR_DEF +#define LV_BIDI_BASE_DIR_DEF LV_BIDI_DIR_AUTO +#endif +#endif + /*=================== * LV_OBJ SETTINGS *==================*/ diff --git a/src/lv_core/lv_obj.c b/src/lv_core/lv_obj.c index e0ad6c42c..47ce8262d 100644 --- a/src/lv_core/lv_obj.c +++ b/src/lv_core/lv_obj.c @@ -49,6 +49,7 @@ static void refresh_children_position(lv_obj_t * obj, lv_coord_t x_diff, lv_coor static void report_style_mod_core(void * style_p, lv_obj_t * obj); static void refresh_children_style(lv_obj_t * obj); static void delete_children(lv_obj_t * obj); +static void base_dir_refr_children(lv_obj_t * obj); static void lv_event_mark_deleted(lv_obj_t * obj); static void lv_obj_del_async_cb(void * obj); static bool lv_obj_design(lv_obj_t * obj, const lv_area_t * mask_p, lv_design_mode_t mode); @@ -204,6 +205,16 @@ lv_obj_t * lv_obj_create(lv_obj_t * parent, const lv_obj_t * copy) new_obj->opa_scale_en = 0; new_obj->opa_scale = LV_OPA_COVER; new_obj->parent_event = 0; +#if LV_USE_BIDI +#if LV_BIDI_BASE_DIR_DEF == LV_BIDI_DIR_LTR || LV_BIDI_BASE_DIR_DEF == LV_BIDI_DIR_RTL || LV_BIDI_BASE_DIR_DEF == LV_BIDI_DIR_AUTO + new_obj->base_dir = LV_BIDI_BASE_DIR_DEF; +#else +#error "`LV_BIDI_BASE_DIR_DEF` should be `LV_BASE_DIR_LTR` or `LV_BASE_DIR_RTL` (See lv_conf.h)" +#endif +#else + new_obj->base_dir = LV_BIDI_DIR_LTR; +#endif + new_obj->reserved = 0; new_obj->ext_attr = NULL; @@ -288,6 +299,12 @@ lv_obj_t * lv_obj_create(lv_obj_t * parent, const lv_obj_t * copy) new_obj->opa_scale = LV_OPA_COVER; new_obj->opa_scale_en = 0; new_obj->parent_event = 0; +#if LV_USE_BIDI + new_obj->base_dir = LV_BIDI_DIR_INHERIT; +#else + new_obj->base_dir = LV_BIDI_DIR_LTR; +#endif + new_obj->reserved = 0; new_obj->ext_attr = NULL; } @@ -1266,6 +1283,23 @@ void lv_obj_set_parent_event(lv_obj_t * obj, bool en) obj->parent_event = (en == true ? 1 : 0); } +void lv_obj_set_base_dir(lv_obj_t * obj, lv_bidi_dir_t dir) +{ + if(dir != LV_BIDI_DIR_LTR && dir != LV_BIDI_DIR_RTL && + dir != LV_BIDI_DIR_AUTO && dir != LV_BIDI_DIR_INHERIT) { + + LV_LOG_WARN("lv_obj_set_base_dir: invalid base dir"); + return; + } + + obj->base_dir = dir; + lv_signal_send(obj, LV_SIGNAL_BASE_DIR_CHG, NULL); + + /* Notify the children about the parent base dir has changed. + * (The children might have `LV_BIDI_DIR_INHERIT`)*/ + base_dir_refr_children(obj); +} + /** * Set the opa scale enable parameter (required to set opa_scale with `lv_obj_set_opa_scale()`) * @param obj pointer to an object @@ -1931,6 +1965,25 @@ bool lv_obj_get_parent_event(const lv_obj_t * obj) return obj->parent_event == 0 ? false : true; } + +lv_bidi_dir_t lv_obj_get_base_dir(const lv_obj_t * obj) +{ +#if LV_USE_BIDI + const lv_obj_t * parent = obj; + + while(parent) { + if(parent->base_dir != LV_BIDI_DIR_INHERIT) return parent->base_dir; + + parent = lv_obj_get_parent(parent); + } + + return LV_BIDI_BASE_DIR_DEF; +#else + return LV_BIDI_DIR_LTR; +#endif +} + + /** * Get the opa scale enable parameter * @param obj pointer to an object @@ -2326,6 +2379,22 @@ static void delete_children(lv_obj_t * obj) lv_mem_free(obj); /*Free the object itself*/ } +static void base_dir_refr_children(lv_obj_t * obj) +{ + lv_obj_t * child; + child = lv_obj_get_child(obj, NULL); + + while(child) { + if(child->base_dir == LV_BIDI_DIR_INHERIT) { + lv_signal_send(child, LV_SIGNAL_BASE_DIR_CHG, NULL); + base_dir_refr_children(child); + } + + child = lv_obj_get_child(obj, child); + } +} + + static void lv_event_mark_deleted(lv_obj_t * obj) { lv_event_temp_data_t * t = event_temp_data_head; diff --git a/src/lv_core/lv_obj.h b/src/lv_core/lv_obj.h index c2062e969..c6da4016b 100644 --- a/src/lv_core/lv_obj.h +++ b/src/lv_core/lv_obj.h @@ -28,6 +28,7 @@ extern "C" { #include "../lv_misc/lv_ll.h" #include "../lv_misc/lv_color.h" #include "../lv_misc/lv_log.h" +#include "../lv_misc/lv_bidi.h" #include "../lv_hal/lv_hal.h" /********************* @@ -111,7 +112,8 @@ enum { LV_SIGNAL_CHILD_CHG, /**< Child was removed/added */ LV_SIGNAL_CORD_CHG, /**< Object coordinates/size have changed */ LV_SIGNAL_PARENT_SIZE_CHG, /**< Parent's size has changed */ - LV_SIGNAL_STYLE_CHG, /**< Object's style has changed */ + LV_SIGNAL_STYLE_CHG, /**< Object's style has changed */ + LV_SIGNAL_BASE_DIR_CHG, /** #include "lv_txt.h" +#if LV_USE_BIDI + /********************* * DEFINES *********************/ @@ -62,7 +64,6 @@ void lv_bidi_process(const char * str_in, char * str_out, lv_bidi_dir_t base_dir if(dir != LV_BIDI_DIR_NEUTRAL) break; } - /*if there were neutrals in the beginning apply `base_dir` on them */ if(rd && str_in[rd] != '\0') lv_txt_encoded_prev(str_in, &rd); if(rd) { @@ -110,6 +111,21 @@ void lv_bidi_process(const char * str_in, char * str_out, lv_bidi_dir_t base_dir } +lv_bidi_dir_t lv_bidi_detect_base_dir(const char * txt) +{ + uint32_t i = 0; + uint32_t letter; + while(txt[i] != '\0') { + letter = lv_txt_encoded_next(txt, &i); + + lv_bidi_dir_t dir; + dir = lv_bidi_get_letter_dir(letter); + if(dir == LV_BIDI_DIR_RTL || dir == LV_BIDI_DIR_LTR) return dir; + } + + /*If there were no strong char earlier return with the default base dir */ + return LV_BIDI_BASE_DIR_DEF; +} lv_bidi_dir_t lv_bidi_get_letter_dir(uint32_t letter) { @@ -279,7 +295,6 @@ static uint32_t char_change_to_pair(uint32_t letter) } return letter; - - } +#endif /*LV_USE_BIDI*/ diff --git a/src/lv_misc/lv_bidi.h b/src/lv_misc/lv_bidi.h index 8adbac674..fa0d1e9ca 100644 --- a/src/lv_misc/lv_bidi.h +++ b/src/lv_misc/lv_bidi.h @@ -23,19 +23,27 @@ extern "C" { /********************** * TYPEDEFS **********************/ -typedef enum +enum { - LV_BIDI_DIR_LTR, - LV_BIDI_DIR_RTL, - LV_BIDI_DIR_NEUTRAL, - LV_BIDI_DIR_WEAK, -}lv_bidi_dir_t; + /*The first 4 values are stored in `lv_obj_t` on 2 bits*/ + LV_BIDI_DIR_LTR = 0x00, + LV_BIDI_DIR_RTL = 0x01, + LV_BIDI_DIR_AUTO = 0x02, + LV_BIDI_DIR_INHERIT = 0x03, + + LV_BIDI_DIR_NEUTRAL = 0x20, + LV_BIDI_DIR_WEAK = 0x21, +}; + +typedef uint8_t lv_bidi_dir_t; /********************** * GLOBAL PROTOTYPES **********************/ -void lv_bidi_process(const char * str_in, char * str_out, lv_bidi_dir_t base_dir); +#if LV_USE_BIDI +void lv_bidi_process(const char * str_in, char * str_out, lv_bidi_dir_t base_dir); +lv_bidi_dir_t lv_bidi_detect_base_dir(const char * txt); lv_bidi_dir_t lv_bidi_get_letter_dir(uint32_t letter); bool lv_bidi_letter_is_weak(uint32_t letter); bool lv_bidi_letter_is_rtl(uint32_t letter); @@ -45,6 +53,8 @@ bool lv_bidi_letter_is_neutral(uint32_t letter); * MACROS **********************/ +#endif /*LV_USE_BIDI*/ + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/src/lv_objx/lv_ddlist.c b/src/lv_objx/lv_ddlist.c index 3deeed174..5a3854a93 100644 --- a/src/lv_objx/lv_ddlist.c +++ b/src/lv_objx/lv_ddlist.c @@ -180,7 +180,8 @@ void lv_ddlist_set_options(lv_obj_t * ddlist, const char * options) lv_ddlist_refr_width(ddlist); - switch(lv_label_get_align(ext->label)) { + lv_label_align_t align = lv_label_get_align(ext->label); + switch(align) { case LV_LABEL_ALIGN_LEFT: lv_obj_align(ext->label, NULL, LV_ALIGN_IN_LEFT_MID, 0, 0); break; case LV_LABEL_ALIGN_CENTER: lv_obj_align(ext->label, NULL, LV_ALIGN_CENTER, 0, 0); break; case LV_LABEL_ALIGN_RIGHT: lv_obj_align(ext->label, NULL, LV_ALIGN_IN_RIGHT_MID, 0, 0); break; @@ -621,6 +622,15 @@ static lv_res_t lv_ddlist_signal(lv_obj_t * ddlist, lv_signal_t sign, void * par lv_ddlist_ext_t * ext = lv_obj_get_ext_attr(ddlist); if(sign == LV_SIGNAL_STYLE_CHG) { + lv_ddlist_refr_size(ddlist, 0); + } else if(sign == LV_SIGNAL_BASE_DIR_CHG) { + lv_label_align_t align = lv_label_get_align(ext->label); + switch(align) { + case LV_LABEL_ALIGN_LEFT: lv_obj_align(ext->label, NULL, LV_ALIGN_IN_LEFT_MID, 0, 0); break; + case LV_LABEL_ALIGN_CENTER: lv_obj_align(ext->label, NULL, LV_ALIGN_CENTER, 0, 0); break; + case LV_LABEL_ALIGN_RIGHT: lv_obj_align(ext->label, NULL, LV_ALIGN_IN_RIGHT_MID, 0, 0); break; + } + lv_ddlist_refr_size(ddlist, 0); } else if(sign == LV_SIGNAL_CLEANUP) { ext->label = NULL; diff --git a/src/lv_objx/lv_label.c b/src/lv_objx/lv_label.c index 0b6046c76..3b0417c97 100644 --- a/src/lv_objx/lv_label.c +++ b/src/lv_objx/lv_label.c @@ -13,6 +13,7 @@ #include "../lv_core/lv_group.h" #include "../lv_misc/lv_color.h" #include "../lv_misc/lv_math.h" +#include "../lv_misc/lv_bidi.h" /********************* * DEFINES @@ -88,7 +89,7 @@ lv_obj_t * lv_label_create(lv_obj_t * par, const lv_obj_t * copy) ext->static_txt = 0; ext->recolor = 0; ext->body_draw = 0; - ext->align = LV_LABEL_ALIGN_LEFT; + ext->align = LV_LABEL_ALIGN_AUTO; ext->dot_end = LV_LABEL_DOT_END_INV; ext->long_mode = LV_LABEL_LONG_EXPAND; #if LV_USE_ANIMATION @@ -190,14 +191,33 @@ void lv_label_set_text(lv_obj_t * label, const char * text) if(ext->text != NULL && ext->static_txt == 0) { lv_mem_free(ext->text); ext->text = NULL; + +#if LV_USE_BIDI + lv_mem_free(ext->text_ori); + ext->text_ori = NULL; +#endif } ext->text = lv_mem_alloc(len); lv_mem_assert(ext->text); if(ext->text == NULL) return; +#if LV_USE_BIDI == 0 strcpy(ext->text, text); - ext->static_txt = 0; /*Now the text is dynamically allocated*/ +#else + ext->text_ori = lv_mem_alloc(len); + lv_mem_assert(ext->text_ori); + if(ext->text_ori == NULL) return; + + strcpy(ext->text_ori, text); + + lv_bidi_dir_t base_dir = lv_obj_get_base_dir(label); + if(base_dir == LV_BIDI_DIR_AUTO) base_dir = lv_bidi_detect_base_dir(text); + + lv_bidi_process(ext->text_ori, ext->text, base_dir); +#endif + /*Now the text is dynamically allocated*/ + ext->static_txt = 0; } lv_label_refr_text(label); @@ -425,7 +445,22 @@ lv_label_long_mode_t lv_label_get_long_mode(const lv_obj_t * label) lv_label_align_t lv_label_get_align(const lv_obj_t * label) { lv_label_ext_t * ext = lv_obj_get_ext_attr(label); - return ext->align; + + lv_label_align_t align = ext->align; + + if(align == LV_LABEL_ALIGN_AUTO) { +#if LV_USE_BIDI + lv_bidi_dir_t base_dir = lv_obj_get_base_dir(label); + if(base_dir == LV_BIDI_DIR_AUTO) base_dir = lv_bidi_detect_base_dir(ext->text); + + if(base_dir == LV_BIDI_DIR_LTR) align = LV_LABEL_ALIGN_LEFT; + else if (base_dir == LV_BIDI_DIR_RTL) align = LV_LABEL_ALIGN_RIGHT; +#else + align = LV_LABEL_ALIGN_LEFT; +#endif + } + + return align; } /** @@ -842,14 +877,13 @@ static bool lv_label_design(lv_obj_t * label, const lv_area_t * mask, lv_design_ lv_draw_rect(&bg, mask, style, lv_obj_get_opa_scale(label)); } - /*TEST: draw a background for the label*/ - // lv_draw_rect(&label->coords, mask, &lv_style_plain_color, LV_OPA_COVER); + lv_label_align_t align = lv_label_get_align(label); lv_txt_flag_t flag = LV_TXT_FLAG_NONE; if(ext->recolor != 0) flag |= LV_TXT_FLAG_RECOLOR; if(ext->expand != 0) flag |= LV_TXT_FLAG_EXPAND; - if(ext->align == LV_LABEL_ALIGN_CENTER) flag |= LV_TXT_FLAG_CENTER; - if(ext->align == LV_LABEL_ALIGN_RIGHT) flag |= LV_TXT_FLAG_RIGHT; + if(align == LV_LABEL_ALIGN_CENTER) flag |= LV_TXT_FLAG_CENTER; + if(align == LV_LABEL_ALIGN_RIGHT) flag |= LV_TXT_FLAG_RIGHT; /* In ROLL mode the CENTER and RIGHT are pointless so remove them. * (In addition they will result mis-alignment is this case)*/ @@ -947,6 +981,9 @@ static lv_res_t lv_label_signal(lv_obj_t * label, lv_signal_t sign, void * param label->ext_draw_pad = LV_MATH_MAX(label->ext_draw_pad, style->body.padding.top); label->ext_draw_pad = LV_MATH_MAX(label->ext_draw_pad, style->body.padding.bottom); } + } + else if(sign == LV_SIGNAL_BASE_DIR_CHG) { + if(ext->static_txt == 0) lv_label_set_text(label, NULL); } else if(sign == LV_SIGNAL_GET_TYPE) { lv_obj_type_t * buf = param; uint8_t i; diff --git a/src/lv_objx/lv_label.h b/src/lv_objx/lv_label.h index 16b1a6e8f..ff7f62167 100644 --- a/src/lv_objx/lv_label.h +++ b/src/lv_objx/lv_label.h @@ -55,6 +55,7 @@ enum { LV_LABEL_ALIGN_LEFT, /**< Align text to left */ LV_LABEL_ALIGN_CENTER, /**< Align text to center */ LV_LABEL_ALIGN_RIGHT, /**< Align text to right */ + LV_LABEL_ALIGN_AUTO, /**< Use LEFT or RIGHT depending on the direction of the text (LTR/RTL)*/ }; typedef uint8_t lv_label_align_t; @@ -63,12 +64,17 @@ typedef struct { /*Inherited from 'base_obj' so no inherited ext.*/ /*Ext. of ancestor*/ /*New data for this type */ - char * text; /*Text of the label*/ + char * text; /*Text of the label*/ + +#if LV_USE_BIDI + char * text_ori; /*The original text. With BiDi `text` stores the characters in "bidi" ordered text*/ +#endif + union { char * tmp_ptr; /* Pointer to the allocated memory containing the character which are replaced by dots (Handled by the library)*/ - char tmp[sizeof(char *)]; /* Directly store the characters if <=4 characters */ + char tmp[LV_LABEL_DOT_NUM + 1]; /* Directly store the characters if <=4 characters */ } dot; uint16_t dot_end; /*The text end position in dot mode (Handled by the library)*/ lv_point_t offset; /*Text draw position offset*/ From 34e133586e576184bd1ec4b1b6255f970e48fad7 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Tue, 8 Oct 2019 16:31:32 +0200 Subject: [PATCH 10/51] make LV_USE_BIDI = 0 by default --- lv_conf_template.h | 2 +- src/lv_conf_checker.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lv_conf_template.h b/lv_conf_template.h index 50ffb6782..8b351b817 100644 --- a/lv_conf_template.h +++ b/lv_conf_template.h @@ -355,7 +355,7 @@ typedef void * lv_font_user_data_t; * Allows mixing Left-to-Right and Right-to-Left texts. * The direction will be processed according to the Unicode Bidirectioanl Algorithm: * https://www.w3.org/International/articles/inline-bidi-markup/uba-basics*/ -#define LV_USE_BIDI 1 +#define LV_USE_BIDI 0 #if LV_USE_BIDI /* Set the default direction. Supported values: * `LV_BIDI_DIR_LTR` Left-to-Right diff --git a/src/lv_conf_checker.h b/src/lv_conf_checker.h index 0cefbfb51..50e19422a 100644 --- a/src/lv_conf_checker.h +++ b/src/lv_conf_checker.h @@ -493,7 +493,7 @@ * The direction will be processed according to the Unicode Bidirectioanl Algorithm: * https://www.w3.org/International/articles/inline-bidi-markup/uba-basics*/ #ifndef LV_USE_BIDI -#define LV_USE_BIDI 1 +#define LV_USE_BIDI 0 #endif #if LV_USE_BIDI /* Set the default direction. Supported values: From eeabd32b9e7643016d6fe84160cace0c232e72d0 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Tue, 8 Oct 2019 16:54:28 +0200 Subject: [PATCH 11/51] bidi: minor fixes --- src/lv_conf_checker.h | 2 +- src/lv_misc/lv_bidi.h | 6 ++++++ src/lv_objx/lv_label.c | 13 ++++++++++++- 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/lv_conf_checker.h b/src/lv_conf_checker.h index 50e19422a..70e11eaba 100644 --- a/src/lv_conf_checker.h +++ b/src/lv_conf_checker.h @@ -270,7 +270,7 @@ * This macro is used with constants in the form of LV_ that * should also appear on lvgl binding API such as Micropython */ -#ifndef LV_EXPORT_CONST_INT(int_value) +#ifndef LV_EXPORT_CONST_INT #define LV_EXPORT_CONST_INT(int_value) #endif diff --git a/src/lv_misc/lv_bidi.h b/src/lv_misc/lv_bidi.h index fa0d1e9ca..0721fb808 100644 --- a/src/lv_misc/lv_bidi.h +++ b/src/lv_misc/lv_bidi.h @@ -13,6 +13,12 @@ extern "C" { /********************* * INCLUDES *********************/ +#ifdef LV_CONF_INCLUDE_SIMPLE +#include "lv_conf.h" +#else +#include "../../../lv_conf.h" +#endif + #include #include diff --git a/src/lv_objx/lv_label.c b/src/lv_objx/lv_label.c index fd319a7c2..ef71684fe 100644 --- a/src/lv_objx/lv_label.c +++ b/src/lv_objx/lv_label.c @@ -182,7 +182,16 @@ void lv_label_set_text(lv_obj_t * label, const char * text) /*If text is NULL then refresh */ if(text == NULL) { +#if LV_USE_BIDI == 0 lv_label_refr_text(label); +#else + lv_bidi_dir_t base_dir = lv_obj_get_base_dir(label); + if(base_dir == LV_BIDI_DIR_AUTO) base_dir = lv_bidi_detect_base_dir(text); + + lv_bidi_process(ext->text_ori, ext->text, base_dir); + lv_label_refr_text(label); +#endif + return; } @@ -214,7 +223,7 @@ void lv_label_set_text(lv_obj_t * label, const char * text) strcpy(ext->text, text); #else ext->text_ori = lv_mem_alloc(len); - lv_mem_assert(ext->text_ori); + LV_ASSERT_MEM(ext->text_ori); if(ext->text_ori == NULL) return; strcpy(ext->text_ori, text); @@ -1089,7 +1098,9 @@ static lv_res_t lv_label_signal(lv_obj_t * label, lv_signal_t sign, void * param } } else if(sign == LV_SIGNAL_BASE_DIR_CHG) { +#if LV_USE_BIDI if(ext->static_txt == 0) lv_label_set_text(label, NULL); +#endif } else if(sign == LV_SIGNAL_GET_TYPE) { lv_obj_type_t * buf = param; uint8_t i; From 0257fbcd5a2c3a586c3fea1853c17371bf163943 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Wed, 9 Oct 2019 14:00:28 +0200 Subject: [PATCH 12/51] bidi: process in paragraphs --- src/lv_misc/lv_bidi.c | 160 +++++++++++++++++++++++++++--------------- 1 file changed, 103 insertions(+), 57 deletions(-) diff --git a/src/lv_misc/lv_bidi.c b/src/lv_misc/lv_bidi.c index f97508aeb..4373f520e 100644 --- a/src/lv_misc/lv_bidi.c +++ b/src/lv_misc/lv_bidi.c @@ -23,6 +23,8 @@ /********************** * STATIC PROTOTYPES **********************/ +static void process_paragraph(const char * str_in, char * str_out, uint32_t len, lv_bidi_dir_t base_dir); +static uint32_t get_next_paragraph(const char * txt); 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); @@ -41,73 +43,33 @@ 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) { - printf("Input str: \"%s\"\n", str_in); + printf("\nInput str: \"%s\"\n", str_in); - char print_buf[256]; - uint32_t run_len = 0; - lv_bidi_dir_t run_dir; - uint32_t rd = 0; - uint32_t wr; - uint32_t in_len = strlen(str_in); - if(base_dir == LV_BIDI_DIR_RTL) wr = in_len; - else wr = 0; + uint32_t par_start = 0; + uint32_t par_len; - str_out[in_len] = '\0'; - - lv_bidi_dir_t dir = base_dir; - - /*Process neutral chars in the beginning*/ - while(str_in[rd] != '\0') { - uint32_t letter = lv_txt_encoded_next(str_in, &rd); - dir = lv_bidi_get_letter_dir(letter); - if(dir != LV_BIDI_DIR_NEUTRAL) break; + while(str_in[par_start] == '\n' || str_in[par_start] == '\r') { + str_out[par_start] = str_in[par_start]; + par_start ++; } - if(rd && str_in[rd] != '\0') lv_txt_encoded_prev(str_in, &rd); + while(str_in[par_start] != '\0') { + par_len = get_next_paragraph(&str_in[par_start]); + process_paragraph(&str_in[par_start], &str_out[par_start], par_len, base_dir); + par_start += par_len; - if(rd) { - if(base_dir == LV_BIDI_DIR_LTR) { - memcpy(&str_out[wr], str_in, rd); - wr += rd; - } else { - wr -= rd; - memcpy(&str_out[wr], str_in, rd); + while(str_in[par_start] == '\n' || str_in[par_start] == '\r') { + str_out[par_start] = str_in[par_start]; + par_start ++; } - memcpy(print_buf, str_in, rd); - print_buf[rd] = '\0'; - printf("%s: \"%s\"\n", base_dir == LV_BIDI_DIR_LTR ? "LTR" : "RTL", print_buf); } - /*Get and process the runs*/ - while(str_in[rd] != '\0') { - run_dir = get_next_run(&str_in[rd], base_dir, &run_len); + str_out[par_start] = '\0'; - memcpy(print_buf, &str_in[rd], run_len); - print_buf[run_len] = '\0'; - if(run_dir == LV_BIDI_DIR_LTR) { - printf("%s: \"%s\"\n", "LTR" , print_buf); - } else { - printf("%s: \"%s\" -> ", "RTL" , print_buf); + printf("\nOutput str: \"%s\"\n", str_out); - rtl_reverse(print_buf, &str_in[rd], run_len); - printf("\"%s\"\n", print_buf); - } - if(base_dir == LV_BIDI_DIR_LTR) { - if(run_dir == LV_BIDI_DIR_LTR) memcpy(&str_out[wr], &str_in[rd], run_len); - else rtl_reverse(&str_out[wr], &str_in[rd], run_len); - wr += run_len; - } else { - wr -= run_len; - if(run_dir == LV_BIDI_DIR_LTR) memcpy(&str_out[wr], &str_in[rd], run_len); - else rtl_reverse(&str_out[wr], &str_in[rd], run_len); - } - - rd += run_len; - } - - printf("result: %s\n", str_out); } @@ -176,6 +138,90 @@ bool lv_bidi_letter_is_neutral(uint32_t letter) * STATIC FUNCTIONS **********************/ +static void process_paragraph(const char * str_in, char * str_out, uint32_t len, lv_bidi_dir_t base_dir) +{ + printf("new paragraph\n"); + + char print_buf[256]; + + uint32_t run_len = 0; + lv_bidi_dir_t run_dir; + uint32_t rd = 0; + uint32_t wr; + if(base_dir == LV_BIDI_DIR_RTL) wr = len; + else wr = 0; + + str_out[len] = '\0'; + + lv_bidi_dir_t dir = base_dir; + + /*Process neutral chars in the beginning*/ + while(rd < len) { + uint32_t letter = lv_txt_encoded_next(str_in, &rd); + dir = lv_bidi_get_letter_dir(letter); + if(dir != LV_BIDI_DIR_NEUTRAL) break; + } + + if(rd && str_in[rd] != '\0') lv_txt_encoded_prev(str_in, &rd); + + if(rd) { + if(base_dir == LV_BIDI_DIR_LTR) { + memcpy(&str_out[wr], str_in, rd); + wr += rd; + } else { + wr -= rd; + memcpy(&str_out[wr], str_in, rd); + } + memcpy(print_buf, str_in, rd); + print_buf[rd] = '\0'; + printf("%s: \"%s\"\n", base_dir == LV_BIDI_DIR_LTR ? "LTR" : "RTL", print_buf); + } + + /*Get and process the runs*/ + while(rd < len) { + run_dir = get_next_run(&str_in[rd], base_dir, &run_len); + + memcpy(print_buf, &str_in[rd], run_len); + print_buf[run_len] = '\0'; + if(run_dir == LV_BIDI_DIR_LTR) { + printf("%s: \"%s\"\n", "LTR" , print_buf); + } else { + printf("%s: \"%s\" -> ", "RTL" , print_buf); + + rtl_reverse(print_buf, &str_in[rd], run_len); + printf("\"%s\"\n", print_buf); + } + + if(base_dir == LV_BIDI_DIR_LTR) { + if(run_dir == LV_BIDI_DIR_LTR) memcpy(&str_out[wr], &str_in[rd], run_len); + else rtl_reverse(&str_out[wr], &str_in[rd], run_len); + wr += run_len; + } else { + wr -= run_len; + if(run_dir == LV_BIDI_DIR_LTR) memcpy(&str_out[wr], &str_in[rd], run_len); + else rtl_reverse(&str_out[wr], &str_in[rd], run_len); + } + + rd += run_len; + } + + printf("result: %s\n", str_out); + +} + +static uint32_t get_next_paragraph(const char * txt) +{ + uint32_t i = 0; + + lv_txt_encoded_next(txt, &i); + + while(txt[i] != '\0' && txt[i] != '\n' && txt[i] != '\r') { + lv_txt_encoded_next(txt, &i); + } + + return i; +} + static lv_bidi_dir_t get_next_run(const char * txt, lv_bidi_dir_t base_dir, uint32_t * len) { uint32_t i = 0; @@ -188,7 +234,7 @@ static lv_bidi_dir_t get_next_run(const char * txt, lv_bidi_dir_t base_dir, uint while(dir == LV_BIDI_DIR_NEUTRAL || dir == LV_BIDI_DIR_WEAK) { letter = lv_txt_encoded_next(txt, &i); dir = lv_bidi_get_letter_dir(letter); - if(txt[i] == '\0') { + if(txt[i] == '\0' || txt[i] == '\n' || txt[i] == '\r') { *len = i; return base_dir; } @@ -201,7 +247,7 @@ static lv_bidi_dir_t get_next_run(const char * txt, lv_bidi_dir_t base_dir, uint /*Find the next char which has different direction*/ lv_bidi_dir_t next_dir = base_dir; - while(txt[i] != '\0') { + while(txt[i] != '\0'&& txt[i] != '\n' && txt[i] != '\r') { letter = lv_txt_encoded_next(txt, &i); next_dir = lv_bidi_get_letter_dir(letter); From 7a0728fc3c2b7fd11f049ac3ac097ab67b5fb65a Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Wed, 9 Oct 2019 15:36:38 +0200 Subject: [PATCH 13/51] bidi: minor fixes --- src/lv_misc/lv_bidi.c | 8 ++++---- src/lv_misc/lv_bidi.h | 4 ++++ src/lv_objx/lv_label.c | 2 +- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/lv_misc/lv_bidi.c b/src/lv_misc/lv_bidi.c index 4373f520e..5e4a264c5 100644 --- a/src/lv_misc/lv_bidi.c +++ b/src/lv_misc/lv_bidi.c @@ -115,8 +115,8 @@ bool lv_bidi_letter_is_weak(uint32_t letter) bool lv_bidi_letter_is_rtl(uint32_t letter) { -// if(letter >= 0x7f && letter <= 0x2000) return true; if(letter >= 0x5d0 && letter <= 0x5ea) return true; + if(letter == 0x202E) return true; /*Unicode of LV_BIDI_RLO*/ // if(letter >= 'a' && letter <= 'z') return true; return false; @@ -159,7 +159,7 @@ static void process_paragraph(const char * str_in, char * str_out, uint32_t len, while(rd < len) { uint32_t letter = lv_txt_encoded_next(str_in, &rd); dir = lv_bidi_get_letter_dir(letter); - if(dir != LV_BIDI_DIR_NEUTRAL) 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); @@ -170,7 +170,7 @@ static void process_paragraph(const char * str_in, char * str_out, uint32_t len, wr += rd; } else { wr -= rd; - memcpy(&str_out[wr], str_in, rd); + rtl_reverse(&str_out[wr], str_in, rd); } memcpy(print_buf, str_in, rd); print_buf[rd] = '\0'; @@ -230,7 +230,7 @@ static lv_bidi_dir_t get_next_run(const char * txt, lv_bidi_dir_t base_dir, uint letter = lv_txt_encoded_next(txt, NULL); lv_bidi_dir_t dir = lv_bidi_get_letter_dir(letter); - /*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) { letter = lv_txt_encoded_next(txt, &i); dir = lv_bidi_get_letter_dir(letter); diff --git a/src/lv_misc/lv_bidi.h b/src/lv_misc/lv_bidi.h index 0721fb808..233765ca2 100644 --- a/src/lv_misc/lv_bidi.h +++ b/src/lv_misc/lv_bidi.h @@ -25,6 +25,10 @@ extern "C" { /********************* * DEFINES *********************/ +/* Special non printable strong characters. + * They can be inserted to texts to affect the run's direction*/ +#define LV_BIDI_LRO "\xE2\x80\xAD" /*U+202D*/ +#define LV_BIDI_RLO "\xE2\x80\xAE" /*U+202E*/ /********************** * TYPEDEFS diff --git a/src/lv_objx/lv_label.c b/src/lv_objx/lv_label.c index ef71684fe..34201342a 100644 --- a/src/lv_objx/lv_label.c +++ b/src/lv_objx/lv_label.c @@ -186,7 +186,7 @@ void lv_label_set_text(lv_obj_t * label, const char * text) lv_label_refr_text(label); #else lv_bidi_dir_t base_dir = lv_obj_get_base_dir(label); - if(base_dir == LV_BIDI_DIR_AUTO) base_dir = lv_bidi_detect_base_dir(text); + if(base_dir == LV_BIDI_DIR_AUTO) base_dir = lv_bidi_detect_base_dir(ext->text_ori); lv_bidi_process(ext->text_ori, ext->text, base_dir); lv_label_refr_text(label); From cadf2bd97d53c53aa7715ea0d63c904377421486 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Thu, 10 Oct 2019 14:16:07 +0200 Subject: [PATCH 14/51] with RTL base dir: create the object on the right and grow to the right in lv_obj_set_width --- src/lv_core/lv_obj.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/src/lv_core/lv_obj.c b/src/lv_core/lv_obj.c index 153e6045a..a442c55b8 100644 --- a/src/lv_core/lv_obj.c +++ b/src/lv_core/lv_obj.c @@ -235,11 +235,22 @@ lv_obj_t * lv_obj_create(lv_obj_t * parent, const lv_obj_t * copy) new_obj->par = parent; /*Set the parent*/ lv_ll_init(&(new_obj->child_ll), sizeof(lv_obj_t)); +#if LV_USE_BIDI + new_obj->base_dir = LV_BIDI_DIR_INHERIT; +#else + new_obj->base_dir = LV_BIDI_DIR_LTR; +#endif + /*Set coordinates left top corner of parent*/ - new_obj->coords.x1 = parent->coords.x1; new_obj->coords.y1 = parent->coords.y1; - new_obj->coords.x2 = parent->coords.x1 + LV_OBJ_DEF_WIDTH; new_obj->coords.y2 = parent->coords.y1 + LV_OBJ_DEF_HEIGHT; + if(lv_obj_get_base_dir(new_obj) == LV_BIDI_DIR_RTL) { + new_obj->coords.x2 = parent->coords.x2; + new_obj->coords.x1 = parent->coords.x2 - LV_OBJ_DEF_WIDTH; + } else { + new_obj->coords.x1 = parent->coords.x1; + new_obj->coords.x2 = parent->coords.x1 + LV_OBJ_DEF_WIDTH; + } new_obj->ext_draw_pad = 0; #if LV_USE_EXT_CLICK_AREA == LV_EXT_CLICK_AREA_FULL @@ -302,11 +313,6 @@ lv_obj_t * lv_obj_create(lv_obj_t * parent, const lv_obj_t * copy) new_obj->opa_scale = LV_OPA_COVER; new_obj->opa_scale_en = 0; new_obj->parent_event = 0; -#if LV_USE_BIDI - new_obj->base_dir = LV_BIDI_DIR_INHERIT; -#else - new_obj->base_dir = LV_BIDI_DIR_LTR; -#endif new_obj->reserved = 0; new_obj->ext_attr = NULL; @@ -741,8 +747,12 @@ void lv_obj_set_size(lv_obj_t * obj, lv_coord_t w, lv_coord_t h) lv_obj_get_coords(obj, &ori); /*Set the length and height*/ - obj->coords.x2 = obj->coords.x1 + w - 1; obj->coords.y2 = obj->coords.y1 + h - 1; + if(lv_obj_get_base_dir(obj) == LV_BIDI_DIR_RTL) { + obj->coords.x1 = obj->coords.x2 - w + 1; + } else { + obj->coords.x2 = obj->coords.x1 + w - 1; + } /*Send a signal to the object with its new coordinates*/ obj->signal_cb(obj, LV_SIGNAL_CORD_CHG, &ori); From c747f29664f463bb01d1e4e4005fab5e60cc6bc9 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Thu, 10 Oct 2019 14:34:39 +0200 Subject: [PATCH 15/51] ddlist: RTL deafult pos fixes --- src/lv_core/lv_obj.c | 14 ++++++++++---- src/lv_objx/lv_ddlist.c | 5 +++++ 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/lv_core/lv_obj.c b/src/lv_core/lv_obj.c index a442c55b8..2a25b3ac3 100644 --- a/src/lv_core/lv_obj.c +++ b/src/lv_core/lv_obj.c @@ -1800,8 +1800,11 @@ lv_coord_t lv_obj_get_x(const lv_obj_t * obj) lv_coord_t rel_x; lv_obj_t * parent = lv_obj_get_parent(obj); - rel_x = obj->coords.x1 - parent->coords.x1; - + if(parent) { + rel_x = obj->coords.x1 - parent->coords.x1; + } else { + rel_x = obj->coords.x1; + } return rel_x; } @@ -1816,8 +1819,11 @@ lv_coord_t lv_obj_get_y(const lv_obj_t * obj) lv_coord_t rel_y; lv_obj_t * parent = lv_obj_get_parent(obj); - rel_y = obj->coords.y1 - parent->coords.y1; - + if(parent) { + rel_y = obj->coords.y1 - parent->coords.y1; + } else { + rel_y = obj->coords.y1; + } return rel_y; } diff --git a/src/lv_objx/lv_ddlist.c b/src/lv_objx/lv_ddlist.c index 49d3b9856..82b5f5309 100644 --- a/src/lv_objx/lv_ddlist.c +++ b/src/lv_objx/lv_ddlist.c @@ -131,6 +131,11 @@ lv_obj_t * lv_ddlist_create(lv_obj_t * par, const lv_obj_t * copy) lv_ddlist_set_style(new_ddlist, LV_DDLIST_STYLE_SEL, &lv_style_plain_color); lv_ddlist_set_style(new_ddlist, LV_DDLIST_STYLE_SB, &lv_style_pretty_color); } + + if(lv_obj_get_base_dir(new_ddlist) == LV_BIDI_DIR_RTL) { + lv_obj_set_x(new_ddlist, lv_obj_get_width(par) - lv_obj_get_width(new_ddlist)); + } + } /*Copy an existing drop down list*/ else { From 6f001958ceac7bb15b1c33ed1fc38b587a4e5c29 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Fri, 11 Oct 2019 12:01:58 +0200 Subject: [PATCH 16/51] bidi: fix btnm, kb, ta, table behaviour in RTL context --- src/lv_misc/lv_bidi.c | 10 +++---- src/lv_objx/lv_btnm.c | 20 ++++++++++++- src/lv_objx/lv_kb.c | 2 +- src/lv_objx/lv_label.c | 66 ++++++++++++++++++++++-------------------- src/lv_objx/lv_label.h | 4 --- src/lv_objx/lv_ta.c | 40 ++++++++++++------------- src/lv_objx/lv_table.c | 6 +++- 7 files changed, 85 insertions(+), 63 deletions(-) diff --git a/src/lv_misc/lv_bidi.c b/src/lv_misc/lv_bidi.c index 5e4a264c5..668ae180d 100644 --- a/src/lv_misc/lv_bidi.c +++ b/src/lv_misc/lv_bidi.c @@ -43,8 +43,10 @@ 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) { - printf("\nInput str: \"%s\"\n", str_in); + if(base_dir == LV_BIDI_DIR_AUTO) base_dir = lv_bidi_detect_base_dir(str_in); + + printf("\nInput str: \"%s\"\n", str_in); uint32_t par_start = 0; uint32_t par_len; @@ -68,9 +70,6 @@ void lv_bidi_process(const char * str_in, char * str_out, lv_bidi_dir_t base_dir str_out[par_start] = '\0'; printf("\nOutput str: \"%s\"\n", str_out); - - - } lv_bidi_dir_t lv_bidi_detect_base_dir(const char * txt) @@ -86,7 +85,8 @@ lv_bidi_dir_t lv_bidi_detect_base_dir(const char * txt) } /*If there were no strong char earlier return with the default base dir */ - return LV_BIDI_BASE_DIR_DEF; + if(LV_BIDI_BASE_DIR_DEF == LV_BIDI_DIR_AUTO) return LV_BIDI_DIR_LTR; + else return LV_BIDI_BASE_DIR_DEF; } lv_bidi_dir_t lv_bidi_get_letter_dir(uint32_t letter) diff --git a/src/lv_objx/lv_btnm.c b/src/lv_objx/lv_btnm.c index 179213a60..6493f1c94 100644 --- a/src/lv_objx/lv_btnm.c +++ b/src/lv_objx/lv_btnm.c @@ -644,7 +644,6 @@ static bool lv_btnm_design(lv_obj_t * btnm, const lv_area_t * mask, lv_design_mo } /*Draw the object*/ else if(mode == LV_DESIGN_DRAW_MAIN) { - ancestor_design_f(btnm, mask, mode); lv_btnm_ext_t * ext = lv_obj_get_ext_attr(btnm); @@ -665,6 +664,10 @@ static bool lv_btnm_design(lv_obj_t * btnm, const lv_area_t * mask, lv_design_mo lv_txt_flag_t txt_flag = LV_TXT_FLAG_NONE; if(ext->recolor) txt_flag = LV_TXT_FLAG_RECOLOR; +#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++) { /*Search the next valid text in the map*/ @@ -734,9 +737,24 @@ static bool lv_btnm_design(lv_obj_t * btnm, const lv_area_t * mask, lv_design_mo area_tmp.x2 = area_tmp.x1 + txt_size.x; area_tmp.y2 = area_tmp.y1 + txt_size.y; +#if LV_USE_BIDI == 0 lv_draw_label(&area_tmp, mask, btn_style, opa_scale, ext->map_p[txt_i], txt_flag, NULL, -1, -1, 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, mask, btn_style, opa_scale, bidi_buf, txt_flag, NULL, -1, -1, NULL); +#endif } + +#if LV_USE_BIDI + lv_mem_free(bidi_buf); +#endif } + return true; } diff --git a/src/lv_objx/lv_kb.c b/src/lv_objx/lv_kb.c index 1229ffa8b..55d17b868 100644 --- a/src/lv_objx/lv_kb.c +++ b/src/lv_objx/lv_kb.c @@ -395,7 +395,7 @@ void lv_kb_def_event_cb(lv_obj_t * kb, lv_event_t event) /*Add the characters to the text area if set*/ if(ext->ta == NULL) return; - if(strcmp(txt, "Enter") == 0) + if(strcmp(txt, LV_SYMBOL_NEW_LINE) == 0) lv_ta_add_char(ext->ta, '\n'); else if(strcmp(txt, LV_SYMBOL_LEFT) == 0) lv_ta_cursor_left(ext->ta); diff --git a/src/lv_objx/lv_label.c b/src/lv_objx/lv_label.c index 34201342a..069ea9812 100644 --- a/src/lv_objx/lv_label.c +++ b/src/lv_objx/lv_label.c @@ -182,16 +182,7 @@ void lv_label_set_text(lv_obj_t * label, const char * text) /*If text is NULL then refresh */ if(text == NULL) { -#if LV_USE_BIDI == 0 lv_label_refr_text(label); -#else - lv_bidi_dir_t base_dir = lv_obj_get_base_dir(label); - if(base_dir == LV_BIDI_DIR_AUTO) base_dir = lv_bidi_detect_base_dir(ext->text_ori); - - lv_bidi_process(ext->text_ori, ext->text, base_dir); - lv_label_refr_text(label); -#endif - return; } @@ -208,11 +199,6 @@ void lv_label_set_text(lv_obj_t * label, const char * text) if(ext->text != NULL && ext->static_txt == 0) { lv_mem_free(ext->text); ext->text = NULL; - -#if LV_USE_BIDI - lv_mem_free(ext->text_ori); - ext->text_ori = NULL; -#endif } ext->text = lv_mem_alloc(len); @@ -222,16 +208,8 @@ void lv_label_set_text(lv_obj_t * label, const char * text) #if LV_USE_BIDI == 0 strcpy(ext->text, text); #else - ext->text_ori = lv_mem_alloc(len); - LV_ASSERT_MEM(ext->text_ori); - if(ext->text_ori == NULL) return; - - strcpy(ext->text_ori, text); - lv_bidi_dir_t base_dir = lv_obj_get_base_dir(label); - if(base_dir == LV_BIDI_DIR_AUTO) base_dir = lv_bidi_detect_base_dir(text); - - lv_bidi_process(ext->text_ori, ext->text, base_dir); + lv_bidi_process(text, ext->text, base_dir); #endif /*Now the text is dynamically allocated*/ ext->static_txt = 0; @@ -622,7 +600,10 @@ void lv_label_get_letter_pos(const lv_obj_t * label, uint16_t index, lv_point_t if(ext->recolor != 0) flag |= LV_TXT_FLAG_RECOLOR; if(ext->expand != 0) flag |= LV_TXT_FLAG_EXPAND; - if(ext->align == LV_LABEL_ALIGN_CENTER) flag |= LV_TXT_FLAG_CENTER; + + lv_label_align_t align = lv_label_get_align(label); + if(align == LV_LABEL_ALIGN_CENTER) flag |= LV_TXT_FLAG_CENTER; + if(align == LV_LABEL_ALIGN_RIGHT) flag |= LV_TXT_FLAG_RIGHT; /*If the width will be expanded the set the max length to very big */ if(ext->long_mode == LV_LABEL_LONG_EXPAND) { @@ -654,12 +635,12 @@ void lv_label_get_letter_pos(const lv_obj_t * label, uint16_t index, lv_point_t if(index != line_start) x += style->text.letter_space; - if(ext->align == LV_LABEL_ALIGN_CENTER) { + if(align == LV_LABEL_ALIGN_CENTER) { lv_coord_t line_w; line_w = lv_txt_get_width(&txt[line_start], new_line_start - line_start, font, style->text.letter_space, flag); x += lv_obj_get_width(label) / 2 - line_w / 2; - } else if(ext->align == LV_LABEL_ALIGN_RIGHT) { + } else if(align == LV_LABEL_ALIGN_RIGHT) { lv_coord_t line_w; line_w = lv_txt_get_width(&txt[line_start], new_line_start - line_start, font, style->text.letter_space, flag); @@ -694,7 +675,10 @@ uint16_t lv_label_get_letter_on(const lv_obj_t * label, lv_point_t * pos) if(ext->recolor != 0) flag |= LV_TXT_FLAG_RECOLOR; if(ext->expand != 0) flag |= LV_TXT_FLAG_EXPAND; - if(ext->align == LV_LABEL_ALIGN_CENTER) flag |= LV_TXT_FLAG_CENTER; + + lv_label_align_t align = lv_label_get_align(label); + if(align == LV_LABEL_ALIGN_CENTER) flag |= LV_TXT_FLAG_CENTER; + if(align == LV_LABEL_ALIGN_RIGHT) flag |= LV_TXT_FLAG_RIGHT; /*If the width will be expanded set the max length to very big */ if(ext->long_mode == LV_LABEL_LONG_EXPAND) { @@ -713,11 +697,16 @@ uint16_t lv_label_get_letter_on(const lv_obj_t * label, lv_point_t * pos) /*Calculate the x coordinate*/ lv_coord_t x = 0; - if(ext->align == LV_LABEL_ALIGN_CENTER) { + if(align == LV_LABEL_ALIGN_CENTER) { lv_coord_t line_w; line_w = lv_txt_get_width(&txt[line_start], new_line_start - line_start, font, style->text.letter_space, flag); 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; @@ -1192,11 +1181,12 @@ static void lv_label_refr_text(lv_obj_t * label) /*In roll inf. mode keep the size but start offset animations*/ else if(ext->long_mode == LV_LABEL_LONG_SROLL_CIRC) { #if LV_USE_ANIMATION + lv_label_align_t align = lv_label_get_align(label); + lv_anim_t anim; anim.var = label; anim.repeat = 1; anim.playback = 0; - anim.start = 0; anim.act_time = -(((lv_font_get_glyph_width(style->text.font, ' ', ' ') + style->text.letter_space) * 1000) / ext->anim_speed) * LV_LABEL_WAIT_CHAR_COUNT; @@ -1207,7 +1197,14 @@ static void lv_label_refr_text(lv_obj_t * label) bool hor_anim = false; if(size.x > lv_obj_get_width(label)) { - anim.end = -size.x - lv_font_get_glyph_width(font, ' ', ' ') * LV_LABEL_WAIT_CHAR_COUNT; + if(align == LV_LABEL_ALIGN_RIGHT) { + anim.end = 0; + anim.start = -size.x - lv_font_get_glyph_width(font, ' ', ' ') * LV_LABEL_WAIT_CHAR_COUNT; + } else { + anim.start = 0; + anim.end = -size.x - lv_font_get_glyph_width(font, ' ', ' ') * LV_LABEL_WAIT_CHAR_COUNT; + } + anim.exec_cb = (lv_anim_exec_xcb_t)lv_label_set_offset_x; anim.time = lv_anim_speed_to_time(ext->anim_speed, anim.start, anim.end); lv_anim_create(&anim); @@ -1219,7 +1216,14 @@ static void lv_label_refr_text(lv_obj_t * label) } if(size.y > lv_obj_get_height(label) && hor_anim == false) { - anim.end = -size.y - (lv_font_get_line_height(font)); + if(align == LV_LABEL_ALIGN_RIGHT) { + anim.end = 0; + anim.start = -size.y - (lv_font_get_line_height(font)); + } else { + anim.start = 0; + anim.end = -size.y - (lv_font_get_line_height(font)); + } + anim.exec_cb = (lv_anim_exec_xcb_t)lv_label_set_offset_y; anim.time = lv_anim_speed_to_time(ext->anim_speed, anim.start, anim.end); lv_anim_create(&anim); diff --git a/src/lv_objx/lv_label.h b/src/lv_objx/lv_label.h index 13a0f6eed..6660c3c9d 100644 --- a/src/lv_objx/lv_label.h +++ b/src/lv_objx/lv_label.h @@ -71,10 +71,6 @@ typedef struct /*New data for this type */ char * text; /*Text of the label*/ -#if LV_USE_BIDI - char * text_ori; /*The original text. With BiDi `text` stores the characters in "bidi" ordered text*/ -#endif - union { char * tmp_ptr; /* Pointer to the allocated memory containing the character which are replaced by dots (Handled diff --git a/src/lv_objx/lv_ta.c b/src/lv_objx/lv_ta.c index b3da2abf4..77ea629d4 100644 --- a/src/lv_objx/lv_ta.c +++ b/src/lv_objx/lv_ta.c @@ -1850,53 +1850,53 @@ static void update_cursor_position_on_click(lv_obj_t * ta, lv_signal_t sign, lv_ lv_indev_get_vect(click_source, &vect_act); if(point_act.x < 0 || point_act.y < 0) return; /*Ignore event from keypad*/ - lv_point_t relative_position; - relative_position.x = point_act.x - label_coords.x1; - relative_position.y = point_act.y - label_coords.y1; + lv_point_t rel_pos; + rel_pos.x = point_act.x - label_coords.x1; + rel_pos.y = point_act.y - label_coords.y1; lv_coord_t label_width = lv_obj_get_width(ext->label); - uint16_t index_of_char_at_position; + uint16_t char_id_at_click; #if LV_LABEL_TEXT_SEL lv_label_ext_t * ext_label = lv_obj_get_ext_attr(ext->label); bool click_outside_label; /*Check if the click happened on the left side of the area outside the label*/ - if(relative_position.x < 0) { - index_of_char_at_position = 0; + if(rel_pos.x < 0) { + char_id_at_click = 0; click_outside_label = true; } /*Check if the click happened on the right side of the area outside the label*/ - else if(relative_position.x >= label_width) { - index_of_char_at_position = LV_TA_CURSOR_LAST; + else if(rel_pos.x >= label_width) { + char_id_at_click = LV_TA_CURSOR_LAST; click_outside_label = true; } else { - index_of_char_at_position = lv_label_get_letter_on(ext->label, &relative_position); - click_outside_label = !lv_label_is_char_under_pos(ext->label, &relative_position); + char_id_at_click = lv_label_get_letter_on(ext->label, &rel_pos); + click_outside_label = !lv_label_is_char_under_pos(ext->label, &rel_pos); } if(ext->text_sel_en) { if(!ext->text_sel_in_prog && !click_outside_label && sign == LV_SIGNAL_PRESSED) { /*Input device just went down. Store the selection start position*/ - ext->tmp_sel_start = index_of_char_at_position; + ext->tmp_sel_start = char_id_at_click; ext->tmp_sel_end = LV_LABEL_TEXT_SEL_OFF; ext->text_sel_in_prog = 1; lv_obj_set_drag(lv_page_get_scrl(ta), false); } else if(ext->text_sel_in_prog && sign == LV_SIGNAL_PRESSING) { /*Input device may be moving. Store the end position */ - ext->tmp_sel_end = index_of_char_at_position; + ext->tmp_sel_end = char_id_at_click; } else if(ext->text_sel_in_prog && (sign == LV_SIGNAL_PRESS_LOST || sign == LV_SIGNAL_RELEASED)) { /*Input device is released. Check if anything was selected.*/ lv_obj_set_drag(lv_page_get_scrl(ta), true); } } - if(ext->text_sel_in_prog || sign == LV_SIGNAL_PRESSED) lv_ta_set_cursor_pos(ta, index_of_char_at_position); + if(ext->text_sel_in_prog || sign == LV_SIGNAL_PRESSED) lv_ta_set_cursor_pos(ta, char_id_at_click); if(ext->text_sel_in_prog) { /*If the selected area has changed then update the real values and*/ - /*invalidate the text area.*/ + /*Invalidate the text area.*/ if(ext->tmp_sel_start > ext->tmp_sel_end) { if(ext_label->txt_sel_start != ext->tmp_sel_end || ext_label->txt_sel_end != ext->tmp_sel_start) { ext_label->txt_sel_start = ext->tmp_sel_end; @@ -1923,17 +1923,17 @@ static void update_cursor_position_on_click(lv_obj_t * ta, lv_signal_t sign, lv_ } #else /*Check if the click happened on the left side of the area outside the label*/ - if(relative_position.x < 0) { - index_of_char_at_position = 0; + if(rel_pos.x < 0) { + char_id_at_click = 0; } /*Check if the click happened on the right side of the area outside the label*/ - else if(relative_position.x >= label_width) { - index_of_char_at_position = LV_TA_CURSOR_LAST; + else if(rel_pos.x >= label_width) { + char_id_at_click = LV_TA_CURSOR_LAST; } else { - index_of_char_at_position = lv_label_get_letter_on(ext->label, &relative_position); + char_id_at_click = lv_label_get_letter_on(ext->label, &rel_pos); } - if(sign == LV_SIGNAL_PRESSED) lv_ta_set_cursor_pos(ta, index_of_char_at_position); + if(sign == LV_SIGNAL_PRESSED) lv_ta_set_cursor_pos(ta, char_id_at_click); #endif } diff --git a/src/lv_objx/lv_table.c b/src/lv_objx/lv_table.c index b99c055f1..52f8604ce 100644 --- a/src/lv_objx/lv_table.c +++ b/src/lv_objx/lv_table.c @@ -151,7 +151,11 @@ void lv_table_set_cell_value(lv_obj_t * table, uint16_t row, uint16_t col, const } /*Initialize the format byte*/ else { - format.s.align = LV_LABEL_ALIGN_LEFT; + lv_bidi_dir_t base_dir = lv_obj_get_base_dir(table); + if(base_dir == LV_BIDI_DIR_LTR) format.s.align = LV_LABEL_ALIGN_LEFT; + else if(base_dir == LV_BIDI_DIR_RTL) format.s.align = LV_LABEL_ALIGN_RIGHT; + else if(base_dir == LV_BIDI_DIR_AUTO) format.s.align = lv_bidi_detect_base_dir(txt); + format.s.right_merge = 0; format.s.type = 0; format.s.crop = 0; From fe35307d9fa23b7eb817caf78b32c66d28404bf7 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Fri, 11 Oct 2019 14:15:38 +0200 Subject: [PATCH 17/51] fix page oveflow with right aligned object (due to RTL base dir) --- src/lv_objx/lv_page.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/lv_objx/lv_page.c b/src/lv_objx/lv_page.c index 64f6ba923..8e37f7321 100644 --- a/src/lv_objx/lv_page.c +++ b/src/lv_objx/lv_page.c @@ -828,8 +828,10 @@ static lv_res_t lv_page_signal(lv_obj_t * page, lv_signal_t sign, void * param) lv_page_ext_t * ext = lv_obj_get_ext_attr(page); lv_obj_t * child; if(sign == LV_SIGNAL_CHILD_CHG) { /*Automatically move children to the scrollable object*/ - const lv_style_t * style = lv_page_get_style(page, LV_PAGE_STYLE_SCRL); + const lv_style_t * style_bg = lv_page_get_style(page, LV_PAGE_STYLE_BG); + const lv_style_t * style_scrl = lv_page_get_style(page, LV_PAGE_STYLE_SCRL); lv_fit_t fit_left = lv_page_get_scrl_fit_left(page); + lv_fit_t fit_right = lv_page_get_scrl_fit_right(page); lv_fit_t fit_top = lv_page_get_scrl_fit_top(page); child = lv_obj_get_child(page, NULL); while(child != NULL) { @@ -837,15 +839,19 @@ static lv_res_t lv_page_signal(lv_obj_t * page, lv_signal_t sign, void * param) lv_obj_t * tmp = child; child = lv_obj_get_child(page, child); /*Get the next child before move this*/ - /* Reposition the child to take padding into account (Only if it's on (0;0) now) + /* Reposition the child to take padding into account (Only if it's on (0;0) or (widht;height) coordinates now) * It's required to keep new the object on the same coordinate if FIT is enabled.*/ if((tmp->coords.x1 == page->coords.x1) && (fit_left == LV_FIT_TIGHT || fit_left == LV_FIT_FILL)) { - tmp->coords.x1 += style->body.padding.left; - tmp->coords.x2 += style->body.padding.left; + tmp->coords.x1 += style_scrl->body.padding.left; + tmp->coords.x2 += style_scrl->body.padding.left; + } + else if((tmp->coords.x2 == page->coords.x2) && (fit_right == LV_FIT_TIGHT || fit_right == LV_FIT_FILL)) { + tmp->coords.x1 -= style_scrl->body.padding.right * 2 + style_bg->body.padding.right; + tmp->coords.x2 -= style_scrl->body.padding.right * 2 + style_bg->body.padding.right; } if((tmp->coords.y1 == page->coords.y1) && (fit_top == LV_FIT_TIGHT || fit_top == LV_FIT_FILL)) { - tmp->coords.y1 += style->body.padding.top; - tmp->coords.y2 += style->body.padding.top; + tmp->coords.y1 += style_scrl->body.padding.top; + tmp->coords.y2 += style_scrl->body.padding.top; } lv_obj_set_parent(tmp, ext->scrl); } else { From 9d2a2c58f9447164d52a62acb5e6168a209cc15c Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Mon, 14 Oct 2019 15:25:40 +0200 Subject: [PATCH 18/51] In case of RTL with LV_LAYOUT_ROW_X arrangle from the right --- src/lv_objx/lv_cont.c | 22 +++++++++++++++------- src/lv_objx/lv_list.c | 3 ++- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/lv_objx/lv_cont.c b/src/lv_objx/lv_cont.c index f819923a9..22e9f5145 100644 --- a/src/lv_objx/lv_cont.c +++ b/src/lv_objx/lv_cont.c @@ -21,6 +21,7 @@ #include "../lv_misc/lv_area.h" #include "../lv_misc/lv_color.h" #include "../lv_misc/lv_math.h" +#include "../lv_misc/lv_bidi.h" /********************* * DEFINES @@ -364,23 +365,23 @@ static void lv_cont_layout_row(lv_obj_t * cont) lv_align_t align; const lv_style_t * style = lv_obj_get_style(cont); lv_coord_t vpad_corr; - + lv_bidi_dir_t base_dir = lv_obj_get_base_dir(cont); switch(type) { case LV_LAYOUT_ROW_T: vpad_corr = style->body.padding.top; - align = LV_ALIGN_IN_TOP_LEFT; + align = base_dir == LV_BIDI_DIR_RTL ? LV_ALIGN_IN_TOP_RIGHT : LV_ALIGN_IN_TOP_LEFT; break; case LV_LAYOUT_ROW_M: vpad_corr = 0; - align = LV_ALIGN_IN_LEFT_MID; + align = base_dir == LV_BIDI_DIR_RTL ? LV_ALIGN_IN_RIGHT_MID: LV_ALIGN_IN_LEFT_MID; break; case LV_LAYOUT_ROW_B: vpad_corr = -style->body.padding.bottom; - align = LV_ALIGN_IN_BOTTOM_LEFT; + align = base_dir == LV_BIDI_DIR_RTL ? LV_ALIGN_IN_BOTTOM_RIGHT: LV_ALIGN_IN_BOTTOM_LEFT; break; default: vpad_corr = 0; - align = LV_ALIGN_IN_TOP_LEFT; + align = base_dir == LV_BIDI_DIR_RTL ? LV_ALIGN_IN_TOP_RIGHT : LV_ALIGN_IN_TOP_LEFT; break; } @@ -389,12 +390,19 @@ static void lv_cont_layout_row(lv_obj_t * cont) lv_obj_set_protect(cont, LV_PROTECT_CHILD_CHG); /* Align the children */ - lv_coord_t last_cord = style->body.padding.left; + lv_coord_t last_cord; + if(base_dir == LV_BIDI_DIR_RTL) last_cord = style->body.padding.right; + else last_cord = style->body.padding.left; + LV_LL_READ_BACK(cont->child_ll, child) { if(lv_obj_get_hidden(child) != false || lv_obj_is_protected(child, LV_PROTECT_POS) != false) continue; - lv_obj_align(child, cont, align, last_cord, vpad_corr); +// last_cord -= lv_obj_get_width(child); + + if(base_dir == LV_BIDI_DIR_RTL) lv_obj_align(child, cont, align, -last_cord, vpad_corr); + else lv_obj_align(child, cont, align, last_cord, vpad_corr); + last_cord += lv_obj_get_width(child) + style->body.padding.inner; } diff --git a/src/lv_objx/lv_list.c b/src/lv_objx/lv_list.c index 10b31816e..2732428c9 100644 --- a/src/lv_objx/lv_list.c +++ b/src/lv_objx/lv_list.c @@ -218,7 +218,8 @@ lv_obj_t * lv_list_add_btn(lv_obj_t * list, const void * img_src, const char * t lv_label_set_text(label, txt); lv_obj_set_click(label, false); lv_label_set_long_mode(label, LV_LABEL_LONG_SROLL_CIRC); - lv_obj_set_width(label, liste->coords.x2 - label->coords.x1 - btn_hor_pad); + if(lv_obj_get_base_dir(liste) == LV_BIDI_DIR_RTL) lv_obj_set_width(label, label->coords.x2 - liste->coords.x1 - btn_hor_pad); + else lv_obj_set_width(label, liste->coords.x2 - label->coords.x1 - btn_hor_pad); if(label_signal == NULL) label_signal = lv_obj_get_signal_cb(label); } #if LV_USE_GROUP From f1c7e19985f711ceb80557e8be55d2826671d921 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Mon, 14 Oct 2019 16:02:28 +0200 Subject: [PATCH 19/51] bidi: remove debug printfs --- src/lv_misc/lv_bidi.c | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/src/lv_misc/lv_bidi.c b/src/lv_misc/lv_bidi.c index 668ae180d..e9929bc67 100644 --- a/src/lv_misc/lv_bidi.c +++ b/src/lv_misc/lv_bidi.c @@ -46,8 +46,6 @@ 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); - printf("\nInput str: \"%s\"\n", str_in); - uint32_t par_start = 0; uint32_t par_len; @@ -68,8 +66,6 @@ void lv_bidi_process(const char * str_in, char * str_out, lv_bidi_dir_t base_dir } str_out[par_start] = '\0'; - - printf("\nOutput str: \"%s\"\n", str_out); } lv_bidi_dir_t lv_bidi_detect_base_dir(const char * txt) @@ -140,10 +136,6 @@ bool lv_bidi_letter_is_neutral(uint32_t letter) static void process_paragraph(const char * str_in, char * str_out, uint32_t len, lv_bidi_dir_t base_dir) { - printf("new paragraph\n"); - - char print_buf[256]; - uint32_t run_len = 0; lv_bidi_dir_t run_dir; uint32_t rd = 0; @@ -172,26 +164,12 @@ static void process_paragraph(const char * str_in, char * str_out, uint32_t len, wr -= rd; rtl_reverse(&str_out[wr], str_in, rd); } - memcpy(print_buf, str_in, rd); - print_buf[rd] = '\0'; - printf("%s: \"%s\"\n", base_dir == LV_BIDI_DIR_LTR ? "LTR" : "RTL", print_buf); } /*Get and process the runs*/ while(rd < len) { run_dir = get_next_run(&str_in[rd], base_dir, &run_len); - memcpy(print_buf, &str_in[rd], run_len); - print_buf[run_len] = '\0'; - if(run_dir == LV_BIDI_DIR_LTR) { - printf("%s: \"%s\"\n", "LTR" , print_buf); - } else { - printf("%s: \"%s\" -> ", "RTL" , print_buf); - - rtl_reverse(print_buf, &str_in[rd], run_len); - printf("\"%s\"\n", print_buf); - } - if(base_dir == LV_BIDI_DIR_LTR) { if(run_dir == LV_BIDI_DIR_LTR) memcpy(&str_out[wr], &str_in[rd], run_len); else rtl_reverse(&str_out[wr], &str_in[rd], run_len); @@ -204,9 +182,6 @@ static void process_paragraph(const char * str_in, char * str_out, uint32_t len, rd += run_len; } - - printf("result: %s\n", str_out); - } static uint32_t get_next_paragraph(const char * txt) From 06746dfd63a3267f08314860b08189921e50147f Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Tue, 15 Oct 2019 10:32:15 +0200 Subject: [PATCH 20/51] fix page overflow when object created on the right due to RTL base dir --- src/lv_objx/lv_ddlist.c | 20 +++++++++++++++++--- src/lv_objx/lv_page.c | 4 ++-- src/lv_objx/lv_tabview.c | 14 ++++++++++---- 3 files changed, 29 insertions(+), 9 deletions(-) diff --git a/src/lv_objx/lv_ddlist.c b/src/lv_objx/lv_ddlist.c index 82b5f5309..b26c6a933 100644 --- a/src/lv_objx/lv_ddlist.c +++ b/src/lv_objx/lv_ddlist.c @@ -113,6 +113,10 @@ lv_obj_t * lv_ddlist_create(lv_obj_t * par, const lv_obj_t * copy) lv_obj_set_drag(scrl, false); lv_page_set_scrl_fit2(new_ddlist, LV_FIT_FILL, LV_FIT_TIGHT); + lv_coord_t x; + if(lv_obj_get_base_dir(new_ddlist) == LV_BIDI_DIR_RTL) x = lv_obj_get_x(new_ddlist) + lv_obj_get_width(new_ddlist); + else x = lv_obj_get_x(new_ddlist); + ext->label = lv_label_create(new_ddlist, NULL); lv_cont_set_fit2(new_ddlist, LV_FIT_TIGHT, LV_FIT_NONE); lv_page_set_sb_mode(new_ddlist, LV_SB_MODE_HIDE); @@ -120,6 +124,10 @@ lv_obj_t * lv_ddlist_create(lv_obj_t * par, const lv_obj_t * copy) lv_ddlist_set_options(new_ddlist, "Option 1\nOption 2\nOption 3"); + + if(lv_obj_get_base_dir(new_ddlist) == LV_BIDI_DIR_RTL) lv_obj_set_x(new_ddlist, x - lv_obj_get_width(new_ddlist)); + else lv_obj_set_x(new_ddlist, x); + /*Set the default styles*/ lv_theme_t * th = lv_theme_get_current(); if(th) { @@ -132,9 +140,6 @@ lv_obj_t * lv_ddlist_create(lv_obj_t * par, const lv_obj_t * copy) lv_ddlist_set_style(new_ddlist, LV_DDLIST_STYLE_SB, &lv_style_pretty_color); } - if(lv_obj_get_base_dir(new_ddlist) == LV_BIDI_DIR_RTL) { - lv_obj_set_x(new_ddlist, lv_obj_get_width(par) - lv_obj_get_width(new_ddlist)); - } } /*Copy an existing drop down list*/ @@ -995,11 +1000,20 @@ static void lv_ddlist_pos_current_option(lv_obj_t * ddlist) */ static void lv_ddlist_refr_width(lv_obj_t * ddlist) { + + /*Save the current x coordinate because it should be kept after the refrsh*/ + lv_coord_t x; + if(lv_obj_get_base_dir(ddlist) == LV_BIDI_DIR_RTL) x = lv_obj_get_x(ddlist) + lv_obj_get_width(ddlist); + else x = lv_obj_get_x(ddlist); + /*Set the TIGHT fit horizontally the set the width to the content*/ lv_page_set_scrl_fit2(ddlist, LV_FIT_TIGHT, lv_page_get_scrl_fit_bottom(ddlist)); /*Revert FILL fit to fill the parent with the options area. It allows to RIGHT/CENTER align the text*/ lv_page_set_scrl_fit2(ddlist, LV_FIT_FILL, lv_page_get_scrl_fit_bottom(ddlist)); + + if(lv_obj_get_base_dir(ddlist) == LV_BIDI_DIR_RTL) lv_obj_set_x(ddlist, x - lv_obj_get_width(ddlist)); + else lv_obj_set_x(ddlist, x); } #endif diff --git a/src/lv_objx/lv_page.c b/src/lv_objx/lv_page.c index 8e37f7321..b0d308d65 100644 --- a/src/lv_objx/lv_page.c +++ b/src/lv_objx/lv_page.c @@ -846,8 +846,8 @@ static lv_res_t lv_page_signal(lv_obj_t * page, lv_signal_t sign, void * param) tmp->coords.x2 += style_scrl->body.padding.left; } else if((tmp->coords.x2 == page->coords.x2) && (fit_right == LV_FIT_TIGHT || fit_right == LV_FIT_FILL)) { - tmp->coords.x1 -= style_scrl->body.padding.right * 2 + style_bg->body.padding.right; - tmp->coords.x2 -= style_scrl->body.padding.right * 2 + style_bg->body.padding.right; + tmp->coords.x1 -= style_scrl->body.padding.right + style_bg->body.padding.right; + tmp->coords.x2 -= style_scrl->body.padding.right + style_bg->body.padding.right; } if((tmp->coords.y1 == page->coords.y1) && (fit_top == LV_FIT_TIGHT || fit_top == LV_FIT_FILL)) { tmp->coords.y1 += style_scrl->body.padding.top; diff --git a/src/lv_objx/lv_tabview.c b/src/lv_objx/lv_tabview.c index da48aad11..ac6e08d90 100644 --- a/src/lv_objx/lv_tabview.c +++ b/src/lv_objx/lv_tabview.c @@ -147,7 +147,7 @@ lv_obj_t * lv_tabview_create(lv_obj_t * par, const lv_obj_t * copy) lv_tabview_set_style(new_tabview, LV_TABVIEW_STYLE_BTN_TGL_PR, th->style.tabview.btn.tgl_pr); } else { lv_tabview_set_style(new_tabview, LV_TABVIEW_STYLE_BG, &lv_style_plain); - lv_tabview_set_style(new_tabview, LV_TABVIEW_STYLE_BTN_BG, &lv_style_transp); + lv_tabview_set_style(new_tabview, LV_TABVIEW_STYLE_BTN_BG, &lv_style_pretty);//transp); lv_tabview_set_style(new_tabview, LV_TABVIEW_STYLE_INDIC, &lv_style_plain_color); } } @@ -222,8 +222,8 @@ lv_obj_t * lv_tabview_add_tab(lv_obj_t * tabview, const char * name) lv_obj_t * h = lv_page_create(ext->content, NULL); lv_obj_set_size(h, lv_obj_get_width(tabview), lv_obj_get_height(ext->content)); lv_page_set_sb_mode(h, LV_SB_MODE_AUTO); - lv_page_set_style(h, LV_PAGE_STYLE_BG, &lv_style_transp); - lv_page_set_style(h, LV_PAGE_STYLE_SCRL, &lv_style_transp); + lv_page_set_style(h, LV_PAGE_STYLE_BG, &lv_style_transp_tight); + lv_page_set_style(h, LV_PAGE_STYLE_SCRL, &lv_style_transp);//plain_color); if(page_signal == NULL) page_signal = lv_obj_get_signal_cb(h); if(page_scrl_signal == NULL) page_scrl_signal = lv_obj_get_signal_cb(lv_page_get_scrl(h)); @@ -400,7 +400,13 @@ void lv_tabview_set_tab_act(lv_obj_t * tabview, uint16_t id, lv_anim_enable_t an case LV_TABVIEW_BTNS_POS_TOP: case LV_TABVIEW_BTNS_POS_BOTTOM: indic_size = lv_obj_get_width(ext->indic); - indic_pos = indic_size * id + tabs_style->body.padding.inner * id + tabs_style->body.padding.left; + if(lv_obj_get_base_dir(tabview) == LV_BIDI_DIR_RTL) { + uint16_t id_rtl = (ext->tab_cnt - (id + 1)); + printf("id:%d, id_Rtl:%d\n", id, id_rtl); + indic_pos = indic_size * id_rtl + tabs_style->body.padding.inner * id_rtl + tabs_style->body.padding.left; + } else { + indic_pos = indic_size * id + tabs_style->body.padding.inner * id + tabs_style->body.padding.left; + } break; case LV_TABVIEW_BTNS_POS_LEFT: case LV_TABVIEW_BTNS_POS_RIGHT: From 54e34c15b9bbfcf3b7464df5da9fe6b8e0d0a1c5 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Tue, 15 Oct 2019 11:04:49 +0200 Subject: [PATCH 21/51] btnm, tabview: revers the button/tab order with RTL base dir --- src/lv_objx/lv_btnm.c | 15 +++++++++++---- src/lv_objx/lv_ddlist.c | 3 ++- src/lv_objx/lv_kb.c | 1 + src/lv_objx/lv_tabview.c | 29 ++++++++++++++++++----------- 4 files changed, 32 insertions(+), 16 deletions(-) diff --git a/src/lv_objx/lv_btnm.c b/src/lv_objx/lv_btnm.c index 6493f1c94..c9f095ac4 100644 --- a/src/lv_objx/lv_btnm.c +++ b/src/lv_objx/lv_btnm.c @@ -207,6 +207,8 @@ void lv_btnm_set_map(const lv_obj_t * btnm, const char * map[]) btn_h = lv_obj_get_height(btnm)- act_y - style_bg->body.padding.bottom - 1; } + lv_bidi_dir_t base_dir = lv_obj_get_base_dir(btnm); + /*Only deal with the non empty lines*/ if(btn_cnt != 0) { /*Calculate the width of all units*/ @@ -214,7 +216,8 @@ void lv_btnm_set_map(const lv_obj_t * btnm, const char * map[]) /*Set the button size and positions and set the texts*/ uint16_t i; - lv_coord_t act_x = style_bg->body.padding.left; + lv_coord_t act_x; + lv_coord_t act_unit_w; unit_act_cnt = 0; for(i = 0; i < btn_cnt; i++) { @@ -225,9 +228,13 @@ void lv_btnm_set_map(const lv_obj_t * btnm, const char * map[]) act_unit_w--; /*-1 because e.g. width = 100 means 101 pixels (0..100)*/ /*Always recalculate act_x because of rounding errors */ - act_x = (unit_act_cnt * all_unit_w) / unit_cnt + i * style_bg->body.padding.inner + - style_bg->body.padding.left; - + if(base_dir == LV_BIDI_DIR_RTL) { + act_x = (unit_act_cnt * all_unit_w) / unit_cnt + i * style_bg->body.padding.inner; + act_x = lv_obj_get_width(btnm) - style_bg->body.padding.right - act_x - act_unit_w - 1; + } else { + act_x = (unit_act_cnt * all_unit_w) / unit_cnt + i * style_bg->body.padding.inner + + style_bg->body.padding.left; + } /* Set the button's area. * If inner padding is zero then use the prev. button x2 as x1 to avoid rounding * errors*/ diff --git a/src/lv_objx/lv_ddlist.c b/src/lv_objx/lv_ddlist.c index b26c6a933..a6066729d 100644 --- a/src/lv_objx/lv_ddlist.c +++ b/src/lv_objx/lv_ddlist.c @@ -113,6 +113,7 @@ lv_obj_t * lv_ddlist_create(lv_obj_t * par, const lv_obj_t * copy) lv_obj_set_drag(scrl, false); lv_page_set_scrl_fit2(new_ddlist, LV_FIT_FILL, LV_FIT_TIGHT); + /*Save (a later restore) the original X coordinate because it changes as the FITs applies*/ lv_coord_t x; if(lv_obj_get_base_dir(new_ddlist) == LV_BIDI_DIR_RTL) x = lv_obj_get_x(new_ddlist) + lv_obj_get_width(new_ddlist); else x = lv_obj_get_x(new_ddlist); @@ -124,7 +125,7 @@ lv_obj_t * lv_ddlist_create(lv_obj_t * par, const lv_obj_t * copy) lv_ddlist_set_options(new_ddlist, "Option 1\nOption 2\nOption 3"); - + /*Restore the original X coordinate*/ if(lv_obj_get_base_dir(new_ddlist) == LV_BIDI_DIR_RTL) lv_obj_set_x(new_ddlist, x - lv_obj_get_width(new_ddlist)); else lv_obj_set_x(new_ddlist, x); diff --git a/src/lv_objx/lv_kb.c b/src/lv_objx/lv_kb.c index 55d17b868..003bd4d33 100644 --- a/src/lv_objx/lv_kb.c +++ b/src/lv_objx/lv_kb.c @@ -131,6 +131,7 @@ lv_obj_t * lv_kb_create(lv_obj_t * par, const lv_obj_t * copy) lv_obj_set_event_cb(new_kb, lv_kb_def_event_cb); lv_btnm_set_map(new_kb, kb_map_lc); lv_btnm_set_ctrl_map(new_kb, kb_ctrl_lc_map); + lv_obj_set_base_dir(new_kb, LV_BIDI_DIR_LTR); /*Set the default styles*/ lv_theme_t * th = lv_theme_get_current(); diff --git a/src/lv_objx/lv_tabview.c b/src/lv_objx/lv_tabview.c index ac6e08d90..1353dcbf6 100644 --- a/src/lv_objx/lv_tabview.c +++ b/src/lv_objx/lv_tabview.c @@ -351,6 +351,10 @@ void lv_tabview_set_tab_act(lv_obj_t * tabview, uint16_t id, lv_anim_enable_t an ext->tab_cur = id; + if(lv_obj_get_base_dir(tabview) == LV_BIDI_DIR_RTL) { + id = (ext->tab_cnt - (id + 1)); + } + lv_coord_t cont_x; switch(ext->btns_pos) { @@ -400,13 +404,7 @@ void lv_tabview_set_tab_act(lv_obj_t * tabview, uint16_t id, lv_anim_enable_t an case LV_TABVIEW_BTNS_POS_TOP: case LV_TABVIEW_BTNS_POS_BOTTOM: indic_size = lv_obj_get_width(ext->indic); - if(lv_obj_get_base_dir(tabview) == LV_BIDI_DIR_RTL) { - uint16_t id_rtl = (ext->tab_cnt - (id + 1)); - printf("id:%d, id_Rtl:%d\n", id, id_rtl); - indic_pos = indic_size * id_rtl + tabs_style->body.padding.inner * id_rtl + tabs_style->body.padding.left; - } else { - indic_pos = indic_size * id + tabs_style->body.padding.inner * id + tabs_style->body.padding.left; - } + indic_pos = indic_size * id + tabs_style->body.padding.inner * id + tabs_style->body.padding.left; break; case LV_TABVIEW_BTNS_POS_LEFT: case LV_TABVIEW_BTNS_POS_RIGHT: @@ -911,7 +909,11 @@ static void tabpage_pressing_handler(lv_obj_t * tabview, lv_obj_t * tabpage) p = ((tabpage->coords.x1 - tabview->coords.x1) * (indic_size + tabs_style->body.padding.inner)) / lv_obj_get_width(tabview); - lv_obj_set_x(ext->indic, indic_size * ext->tab_cur + tabs_style->body.padding.inner * ext->tab_cur + + uint16_t id = ext->tab_cur; + if(lv_obj_get_base_dir(tabview) == LV_BIDI_DIR_RTL) { + id = (ext->tab_cnt - (id + 1)); + } + lv_obj_set_x(ext->indic, indic_size * id + tabs_style->body.padding.inner * id + indic_style->body.padding.left - p); break; case LV_TABVIEW_BTNS_POS_LEFT: @@ -954,13 +956,18 @@ static void tabpage_press_lost_handler(lv_obj_t * tabview, lv_obj_t * tabpage) lv_coord_t page_x2 = page_x1 + lv_obj_get_width(tabpage); lv_coord_t treshold = lv_obj_get_width(tabview) / 2; - uint16_t tab_cur = ext->tab_cur; + int16_t tab_cur = ext->tab_cur; if(page_x1 > treshold) { - if(tab_cur != 0) tab_cur--; + if(lv_obj_get_base_dir(tabview) == LV_BIDI_DIR_RTL) tab_cur++; + else tab_cur--; } else if(page_x2 < treshold) { - if(tab_cur < ext->tab_cnt - 1) tab_cur++; + if(lv_obj_get_base_dir(tabview) == LV_BIDI_DIR_RTL) tab_cur--; + else tab_cur++; } + if(tab_cur > ext->tab_cnt - 1) tab_cur = ext->tab_cnt - 1; + else if(tab_cur < 0) tab_cur = 0; + uint32_t id_prev = lv_tabview_get_tab_act(tabview); lv_tabview_set_tab_act(tabview, tab_cur, LV_ANIM_ON); uint32_t id_new = lv_tabview_get_tab_act(tabview); From 6b5c89baf7976ebf0a7ce63d8847eb7c0ac7b279 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Tue, 15 Oct 2019 14:25:47 +0200 Subject: [PATCH 22/51] lv_label_ins_text: consider base dir --- src/lv_objx/lv_label.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/lv_objx/lv_label.c b/src/lv_objx/lv_label.c index 069ea9812..4ce18f42f 100644 --- a/src/lv_objx/lv_label.c +++ b/src/lv_objx/lv_label.c @@ -904,7 +904,18 @@ void lv_label_ins_text(lv_obj_t * label, uint32_t pos, const char * txt) pos = lv_txt_get_encoded_length(ext->text); } +#if LV_USE_BIDI + char * bidi_buf = lv_mem_alloc(ins_len) + 1; + LV_ASSERT_MEM(bidi_buf); + if(bidi_buf == NULL) return; + + lv_bidi_process(txt, bidi_buf, lv_obj_get_base_dir(label)); + lv_txt_ins(ext->text, pos, bidi_buf); + + lv_mem_free(bidi_buf); +#else lv_txt_ins(ext->text, pos, txt); +#endif lv_label_refr_text(label); } From bcdd680a2f54364a072ee55507e4db5cd8b03c2a Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Wed, 16 Oct 2019 05:08:21 +0200 Subject: [PATCH 23/51] table: apply bidi on cell values --- src/lv_objx/lv_table.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/lv_objx/lv_table.c b/src/lv_objx/lv_table.c index 52f8604ce..e1ca6a2d0 100644 --- a/src/lv_objx/lv_table.c +++ b/src/lv_objx/lv_table.c @@ -145,13 +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; lv_table_cell_format_t format; + lv_bidi_dir_t base_dir = lv_obj_get_base_dir(table); + /*Save the format byte*/ if(ext->cell_data[cell]) { format.format_byte = ext->cell_data[cell][0]; } /*Initialize the format byte*/ else { - lv_bidi_dir_t base_dir = lv_obj_get_base_dir(table); if(base_dir == LV_BIDI_DIR_LTR) format.s.align = LV_LABEL_ALIGN_LEFT; else if(base_dir == LV_BIDI_DIR_RTL) format.s.align = LV_LABEL_ALIGN_RIGHT; else if(base_dir == LV_BIDI_DIR_AUTO) format.s.align = lv_bidi_detect_base_dir(txt); @@ -162,7 +163,13 @@ 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*/ - strcpy(ext->cell_data[cell] + 1, txt); /*Leave the format byte*/ + +#if LV_USE_BIDI == 0 + 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; refr_size(table); } From 770645ecd06553327418f30684ffd5e538ae2b33 Mon Sep 17 00:00:00 2001 From: Amir Gonnen Date: Fri, 27 Sep 2019 22:32:45 +0300 Subject: [PATCH 24/51] add Hebrew font --- src/lv_font/lv_font_heb_16.c | 1133 ++++++++++++++++++++++++++++++++++ 1 file changed, 1133 insertions(+) create mode 100644 src/lv_font/lv_font_heb_16.c diff --git a/src/lv_font/lv_font_heb_16.c b/src/lv_font/lv_font_heb_16.c new file mode 100644 index 000000000..5cff45178 --- /dev/null +++ b/src/lv_font/lv_font_heb_16.c @@ -0,0 +1,1133 @@ +#include "lvgl/lvgl.h" + +/******************************************************************************* + * Size: 16 px + * Bpp: 4 + * Opts: --font /usr/share/fonts/truetype/culmus/FrankRuehlCLM-Medium.ttf -r 0x20-0x7F -r 0x5d0-0x5ea --size 16 --format lvgl --bpp 4 --no-compress -o /home/amirgon/esp/projects/lv_mpy/lib/lv_bindings/lvgl/src/lv_font/lv_font_heb_16.c + ******************************************************************************/ + +#ifndef LV_FONT_HEB_16 +#define LV_FONT_HEB_16 1 +#endif + +#if LV_FONT_HEB_16 + +/*----------------- + * BITMAPS + *----------------*/ + +/*Store the image of the glyphs*/ +static LV_ATTRIBUTE_LARGE_CONST const uint8_t gylph_bitmap[] = { + /* U+20 " " */ + + /* U+21 "!" */ + 0xab, 0xef, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x1, + 0x46, 0xde, 0x57, + + /* U+22 "\"" */ + 0xa, 0xc3, 0xe4, 0xf, 0x87, 0xf1, 0x1f, 0x18, + 0x90, 0x2a, 0x9, 0x20, 0x12, 0x3, 0x0, + + /* U+23 "#" */ + 0x0, 0x69, 0xc, 0x20, 0x0, 0x86, 0xe, 0x0, + 0x0, 0xa4, 0xe, 0x0, 0x3f, 0xff, 0xff, 0xf2, + 0x0, 0xe0, 0x4a, 0x0, 0x0, 0xe0, 0x68, 0x0, + 0x8f, 0xff, 0xff, 0xc0, 0x4, 0xa0, 0xa4, 0x0, + 0x6, 0x80, 0xd2, 0x0, 0x9, 0x60, 0xf0, 0x0, + + /* U+24 "$" */ + 0x0, 0xc, 0x10, 0x0, 0x1, 0xd4, 0x0, 0x6, + 0xce, 0xab, 0x1, 0xe0, 0xc4, 0xf5, 0x3e, 0xc, + 0x4f, 0x31, 0xfb, 0xd1, 0x0, 0x5, 0xff, 0xd5, + 0x0, 0x2, 0xde, 0xf6, 0x6, 0x1c, 0x1a, 0xb5, + 0xf6, 0xc1, 0x5b, 0x3f, 0x1c, 0x1a, 0x60, 0x6d, + 0xfc, 0x80, 0x0, 0xc, 0x10, 0x0, 0x0, 0x60, + 0x0, + + /* U+25 "%" */ + 0x0, 0x8e, 0x60, 0x3, 0x90, 0x0, 0x8f, 0x49, + 0x11, 0xc2, 0x0, 0x1f, 0x80, 0x7c, 0xa9, 0x0, + 0x5, 0xf1, 0xc, 0x15, 0x10, 0x0, 0x4f, 0x6, + 0x90, 0x80, 0x0, 0x0, 0xac, 0x80, 0x71, 0x2b, + 0xc3, 0x0, 0x0, 0x18, 0xe, 0x91, 0xa0, 0x0, + 0x9, 0x17, 0xf1, 0xa, 0x0, 0x2, 0x90, 0xc9, + 0x3, 0x60, 0x0, 0xa1, 0xc, 0x70, 0xa0, 0x0, + 0x39, 0x0, 0x4e, 0xc3, 0x0, + + /* U+26 "&" */ + 0x0, 0x9, 0xab, 0x20, 0x0, 0x0, 0x5, 0xc0, + 0x5b, 0x0, 0x0, 0x0, 0x8c, 0x5, 0xc0, 0x0, + 0x0, 0x7, 0xf2, 0xc6, 0x0, 0x0, 0x0, 0x3f, + 0xf7, 0x0, 0x0, 0x0, 0x8, 0xdc, 0x7, 0xcd, + 0xb0, 0xb, 0x54, 0xf5, 0x7, 0xa0, 0x3, 0xf2, + 0xb, 0xe0, 0xa1, 0x0, 0x4f, 0x60, 0x2f, 0xc6, + 0x2, 0x20, 0xee, 0x30, 0x9f, 0xa3, 0xb1, 0x3, + 0xcf, 0xc6, 0x6e, 0xe5, 0x0, + + /* U+27 "'" */ + 0xa, 0xc0, 0xf8, 0x1f, 0x12, 0xa0, 0x12, 0x0, + + /* U+28 "(" */ + 0x0, 0x6, 0x0, 0xa6, 0x6, 0xc0, 0xe, 0x60, + 0x4f, 0x30, 0x6f, 0x10, 0x7f, 0x0, 0x7f, 0x10, + 0x4f, 0x20, 0xe, 0x60, 0x7, 0xb0, 0x0, 0xb4, + 0x0, 0x7, + + /* U+29 ")" */ + 0x24, 0x0, 0x0, 0xb5, 0x0, 0x2, 0xf1, 0x0, + 0xc, 0x80, 0x0, 0x8e, 0x0, 0x7, 0xf1, 0x0, + 0x6f, 0x20, 0x7, 0xf1, 0x0, 0x8e, 0x0, 0xb, + 0x90, 0x1, 0xf2, 0x0, 0xa6, 0x0, 0x25, 0x0, + 0x0, + + /* U+2A "*" */ + 0x0, 0xb, 0x0, 0x0, 0x50, 0xb0, 0x50, 0x1c, + 0x77, 0x7b, 0x0, 0x6, 0xf4, 0x0, 0x1d, 0x57, + 0x7d, 0x0, 0x30, 0xc0, 0x40, 0x0, 0x9, 0x0, + 0x0, + + /* U+2B "+" */ + 0x0, 0x4, 0x40, 0x0, 0x0, 0x8, 0x90, 0x0, + 0x0, 0x8, 0x90, 0x0, 0x0, 0x8, 0x90, 0x0, + 0x4f, 0xff, 0xff, 0xf6, 0x2, 0x29, 0xa2, 0x21, + 0x0, 0x8, 0x90, 0x0, 0x0, 0x8, 0x90, 0x0, + + /* U+2C "," */ + 0x3b, 0xa, 0xf4, 0x4c, 0x6, 0x40, 0x10, 0x0, + + /* U+2D "-" */ + 0x19, 0x99, 0x90, 0x5f, 0xff, 0xd0, + + /* U+2E "." */ + 0x18, 0xa, 0xf3, 0x3b, 0x0, + + /* U+2F "/" */ + 0x0, 0x0, 0xe1, 0x0, 0x3, 0xb0, 0x0, 0x8, + 0x60, 0x0, 0xe, 0x10, 0x0, 0x3c, 0x0, 0x0, + 0x87, 0x0, 0x0, 0xd2, 0x0, 0x2, 0xc0, 0x0, + 0x8, 0x70, 0x0, 0xd, 0x20, 0x0, 0x2d, 0x0, + 0x0, + + /* U+30 "0" */ + 0x0, 0x8d, 0xd4, 0x0, 0x7, 0xd0, 0x4f, 0x20, + 0xe, 0x70, 0xe, 0x80, 0x3f, 0x50, 0xb, 0xd0, + 0x6f, 0x40, 0xb, 0xf0, 0x7f, 0x40, 0xb, 0xf0, + 0x6f, 0x40, 0xb, 0xf0, 0x4f, 0x50, 0xc, 0xd0, + 0xe, 0x70, 0xe, 0x80, 0x7, 0xd0, 0x4f, 0x20, + 0x0, 0x9d, 0xd4, 0x0, + + /* U+31 "1" */ + 0x0, 0xd, 0x0, 0x1, 0xbf, 0x0, 0x6d, 0xff, + 0x0, 0x0, 0xbf, 0x0, 0x0, 0xbf, 0x0, 0x0, + 0xbf, 0x0, 0x0, 0xbf, 0x0, 0x0, 0xbf, 0x0, + 0x0, 0xbf, 0x0, 0x0, 0xbf, 0x0, 0x6c, 0xff, + 0xd8, + + /* U+32 "2" */ + 0x1, 0xac, 0xd8, 0x0, 0xc2, 0x4, 0xf7, 0x2e, + 0x20, 0xe, 0xc2, 0xfc, 0x0, 0xfd, 0x7, 0x50, + 0x3f, 0x90, 0x0, 0xb, 0xe2, 0x0, 0x7, 0xf3, + 0x0, 0x3, 0xe3, 0x2, 0x1, 0xe3, 0x0, 0xb0, + 0xbd, 0xaa, 0xbd, 0x5f, 0xff, 0xff, 0xb0, + + /* U+33 "3" */ + 0x1, 0xac, 0xd8, 0x0, 0xb6, 0x4, 0xf6, 0xf, + 0xb0, 0xf, 0xa0, 0x96, 0x0, 0xf8, 0x0, 0x0, + 0x6c, 0x10, 0x7, 0xef, 0x90, 0x0, 0x0, 0x4f, + 0x91, 0x83, 0x0, 0xde, 0x6f, 0x70, 0xd, 0xd3, + 0xe0, 0x3, 0xf7, 0x5, 0xcc, 0xd7, 0x0, + + /* U+34 "4" */ + 0x0, 0x0, 0x4b, 0x0, 0x0, 0x0, 0xdb, 0x0, + 0x0, 0x6, 0xfb, 0x0, 0x0, 0xd, 0xfb, 0x0, + 0x0, 0x87, 0xfb, 0x0, 0x1, 0xd0, 0xfb, 0x0, + 0xa, 0x50, 0xfb, 0x0, 0x3c, 0x0, 0xfb, 0x0, + 0x7d, 0xdd, 0xff, 0xd1, 0x0, 0x0, 0xfb, 0x0, + 0x0, 0x1c, 0xff, 0x90, + + /* U+35 "5" */ + 0x6, 0x82, 0x5, 0x50, 0x8f, 0xff, 0xe1, 0x9, + 0xab, 0x92, 0x0, 0xa2, 0x0, 0x0, 0xc, 0xce, + 0xd7, 0x0, 0xc2, 0x6, 0xf6, 0x0, 0x0, 0xe, + 0xc1, 0xa4, 0x0, 0xde, 0x6f, 0x80, 0xe, 0xb2, + 0xf0, 0x5, 0xf4, 0x5, 0xcc, 0xc5, 0x0, + + /* U+36 "6" */ + 0x0, 0x3c, 0xcd, 0x30, 0x3, 0xf4, 0xf, 0xc0, + 0xb, 0xa0, 0xb, 0x80, 0x1f, 0x60, 0x0, 0x0, + 0x5f, 0x6b, 0xd9, 0x0, 0x7f, 0xe4, 0x5f, 0x90, + 0x6f, 0x80, 0xb, 0xf0, 0x5f, 0x60, 0xa, 0xf1, + 0x1f, 0x70, 0xb, 0xe0, 0x9, 0xd0, 0x1f, 0x60, + 0x0, 0x9d, 0xd8, 0x0, + + /* U+37 "7" */ + 0x0, 0x0, 0x0, 0x0, 0xef, 0xff, 0xfd, 0xf, + 0xaa, 0xad, 0x82, 0xa0, 0x0, 0xc2, 0x25, 0x0, + 0x3c, 0x0, 0x0, 0xa, 0x60, 0x0, 0x1, 0xf1, + 0x0, 0x0, 0x7d, 0x0, 0x0, 0xd, 0xb0, 0x0, + 0x1, 0xfa, 0x0, 0x0, 0x4f, 0xa0, 0x0, 0x2, + 0xe6, 0x0, + + /* U+38 "8" */ + 0x1, 0x9c, 0xd8, 0x0, 0xa, 0x80, 0xd, 0x60, + 0xf, 0x40, 0x9, 0xa0, 0xf, 0xb0, 0xc, 0x60, + 0x8, 0xfe, 0xb9, 0x0, 0x0, 0xdf, 0xfe, 0x30, + 0xd, 0x70, 0x6f, 0xc0, 0x5f, 0x0, 0x6, 0xf0, + 0x7e, 0x0, 0x5, 0xe0, 0x2f, 0x40, 0xb, 0x80, + 0x4, 0xcc, 0xc8, 0x0, + + /* U+39 "9" */ + 0x1, 0xbd, 0xd5, 0x0, 0xc, 0xa0, 0x4f, 0x30, + 0x4f, 0x50, 0xe, 0xa0, 0x7f, 0x30, 0xc, 0xe0, + 0x6f, 0x40, 0xd, 0xf0, 0x2f, 0xa0, 0x5f, 0xf0, + 0x5, 0xef, 0xbc, 0xf0, 0x0, 0x0, 0xd, 0xb0, + 0x9, 0x40, 0x1f, 0x60, 0x3f, 0x90, 0x9c, 0x0, + 0x8, 0xdc, 0x91, 0x0, + + /* U+3A ":" */ + 0x3b, 0xa, 0xf3, 0x18, 0x0, 0x0, 0x0, 0x1, + 0x80, 0xaf, 0x33, 0xb0, + + /* U+3B ";" */ + 0x18, 0xa, 0xf3, 0x3b, 0x0, 0x0, 0x0, 0x0, + 0x40, 0x8f, 0x26, 0xf1, 0x48, 0x5, 0x10, + + /* U+3C "<" */ + 0x0, 0x0, 0x0, 0x23, 0x0, 0x0, 0x2a, 0xf5, + 0x0, 0x2a, 0xf9, 0x10, 0x1a, 0xfa, 0x20, 0x0, + 0x5f, 0xa0, 0x0, 0x0, 0x4, 0xce, 0x70, 0x0, + 0x0, 0x4, 0xce, 0x70, 0x0, 0x0, 0x4, 0xc6, + 0x0, 0x0, 0x0, 0x0, + + /* U+3D "=" */ + 0x4f, 0xff, 0xff, 0xf6, 0x2, 0x22, 0x22, 0x21, + 0x0, 0x0, 0x0, 0x0, 0x5f, 0xff, 0xff, 0xf6, + 0x2, 0x22, 0x22, 0x21, + + /* U+3E ">" */ + 0x33, 0x0, 0x0, 0x0, 0x4f, 0xb3, 0x0, 0x0, + 0x1, 0x9f, 0xb3, 0x0, 0x0, 0x1, 0x9f, 0xb2, + 0x0, 0x0, 0x9, 0xf6, 0x0, 0x7, 0xed, 0x50, + 0x6, 0xed, 0x50, 0x0, 0x5d, 0x50, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, + + /* U+3F "?" */ + 0x7, 0xce, 0xc2, 0x5, 0xf5, 0xe, 0xe0, 0x6f, + 0x60, 0xbf, 0x10, 0x20, 0xe, 0xe0, 0x0, 0x7, + 0xf3, 0x0, 0x1, 0xe3, 0x0, 0x0, 0x48, 0x0, + 0x0, 0x0, 0x10, 0x0, 0x0, 0x55, 0x0, 0x0, + 0xd, 0xd0, 0x0, 0x0, 0x66, 0x0, 0x0, + + /* U+40 "@" */ + 0x0, 0x19, 0xbb, 0xb3, 0x0, 0x1, 0xc3, 0x0, + 0x1a, 0x40, 0xa, 0x20, 0x0, 0x0, 0xd0, 0x1a, + 0x1, 0xa7, 0x84, 0x74, 0x56, 0xe, 0x54, 0xf2, + 0x56, 0x65, 0x7e, 0x4, 0xe0, 0x64, 0x56, 0x9a, + 0x8, 0xb0, 0xa0, 0x2a, 0x8a, 0xd, 0x74, 0x60, + 0xa, 0x39, 0x84, 0xa5, 0x91, 0x1, 0xc3, 0x0, + 0x9, 0x60, 0x0, 0x19, 0xcb, 0xb4, 0x0, + + /* U+41 "A" */ + 0x0, 0x0, 0xb, 0x30, 0x0, 0x0, 0x0, 0x1, + 0xf9, 0x0, 0x0, 0x0, 0x0, 0x6f, 0xe0, 0x0, + 0x0, 0x0, 0xc, 0xaf, 0x50, 0x0, 0x0, 0x1, + 0xd1, 0xfa, 0x0, 0x0, 0x0, 0x77, 0xb, 0xf1, + 0x0, 0x0, 0xc, 0x20, 0x5f, 0x60, 0x0, 0x2, + 0xfc, 0xcc, 0xfc, 0x0, 0x0, 0x86, 0x0, 0x9, + 0xf2, 0x0, 0xe, 0x20, 0x0, 0x2f, 0x80, 0x1d, + 0xfd, 0x40, 0x4c, 0xff, 0x80, + + /* U+42 "B" */ + 0x6d, 0xfe, 0xbc, 0xd5, 0x0, 0x2f, 0x50, 0x8, + 0xf1, 0x2, 0xf5, 0x0, 0x3f, 0x60, 0x2f, 0x50, + 0x3, 0xf4, 0x2, 0xf5, 0x0, 0xac, 0x0, 0x2f, + 0xcb, 0xed, 0x20, 0x2, 0xf5, 0x0, 0x5f, 0x50, + 0x2f, 0x50, 0x0, 0xdd, 0x2, 0xf5, 0x0, 0xb, + 0xd0, 0x2f, 0x50, 0x2, 0xf8, 0x6d, 0xfd, 0xbb, + 0xc7, 0x0, + + /* U+43 "C" */ + 0x0, 0x19, 0xba, 0xa5, 0x80, 0x1d, 0x60, 0x3, + 0xf9, 0x9, 0xd0, 0x0, 0x7, 0xa1, 0xf8, 0x0, + 0x0, 0x1a, 0x4f, 0x60, 0x0, 0x0, 0x26, 0xf5, + 0x0, 0x0, 0x0, 0x5f, 0x60, 0x0, 0x0, 0x2, + 0xf8, 0x0, 0x0, 0x9, 0xc, 0xc0, 0x0, 0x2, + 0x80, 0x2e, 0x50, 0x0, 0xb1, 0x0, 0x2a, 0xba, + 0xa2, 0x0, + + /* U+44 "D" */ + 0x6d, 0xfd, 0xab, 0xc6, 0x0, 0x2, 0xf5, 0x0, + 0x2e, 0x80, 0x2, 0xf5, 0x0, 0x7, 0xf2, 0x2, + 0xf5, 0x0, 0x2, 0xf8, 0x2, 0xf5, 0x0, 0x0, + 0xfa, 0x2, 0xf5, 0x0, 0x0, 0xfb, 0x2, 0xf5, + 0x0, 0x0, 0xfa, 0x2, 0xf5, 0x0, 0x2, 0xf7, + 0x2, 0xf5, 0x0, 0x6, 0xf2, 0x2, 0xf5, 0x0, + 0x1e, 0x80, 0x6d, 0xfd, 0xaa, 0xb5, 0x0, + + /* U+45 "E" */ + 0x6d, 0xfd, 0xbb, 0xef, 0x60, 0x2f, 0x50, 0x1, + 0xc7, 0x2, 0xf5, 0x0, 0x5, 0x80, 0x2f, 0x50, + 0x71, 0x19, 0x2, 0xf5, 0x1d, 0x20, 0x10, 0x2f, + 0xce, 0xf2, 0x0, 0x2, 0xf5, 0xd, 0x20, 0x0, + 0x2f, 0x50, 0x92, 0x9, 0x2, 0xf5, 0x0, 0x1, + 0xb0, 0x2f, 0x50, 0x0, 0xaa, 0x6d, 0xfd, 0xbb, + 0xef, 0x90, + + /* U+46 "F" */ + 0x6d, 0xfd, 0xbb, 0xff, 0x50, 0x2f, 0x50, 0x1, + 0xd6, 0x2, 0xf5, 0x0, 0x6, 0x60, 0x2f, 0x50, + 0x71, 0x37, 0x2, 0xf5, 0x1d, 0x20, 0x10, 0x2f, + 0xce, 0xf2, 0x0, 0x2, 0xf5, 0xd, 0x20, 0x0, + 0x2f, 0x50, 0x92, 0x0, 0x2, 0xf5, 0x0, 0x0, + 0x0, 0x2f, 0x50, 0x0, 0x0, 0x6d, 0xfd, 0xa0, + 0x0, 0x0, + + /* U+47 "G" */ + 0x0, 0x19, 0xbb, 0xb4, 0xa0, 0x0, 0x1d, 0x60, + 0x2, 0xeb, 0x0, 0xa, 0xc0, 0x0, 0x5, 0xc0, + 0x1, 0xf8, 0x0, 0x0, 0xb, 0x0, 0x5f, 0x50, + 0x0, 0x0, 0x0, 0x6, 0xf5, 0x0, 0x0, 0x0, + 0x0, 0x6f, 0x50, 0x0, 0xad, 0xdb, 0x33, 0xf7, + 0x0, 0x0, 0x8e, 0x0, 0xc, 0xc0, 0x0, 0x9, + 0xe0, 0x0, 0x2e, 0x60, 0x1, 0xde, 0x0, 0x0, + 0x2a, 0xba, 0xa2, 0xb0, 0x0, + + /* U+48 "H" */ + 0x6d, 0xfd, 0x80, 0x6d, 0xfd, 0x70, 0x2f, 0x50, + 0x0, 0x3f, 0x40, 0x2, 0xf5, 0x0, 0x3, 0xf4, + 0x0, 0x2f, 0x50, 0x0, 0x3f, 0x40, 0x2, 0xf5, + 0x0, 0x3, 0xf4, 0x0, 0x2f, 0xdc, 0xcc, 0xdf, + 0x40, 0x2, 0xf5, 0x0, 0x3, 0xf4, 0x0, 0x2f, + 0x50, 0x0, 0x3f, 0x40, 0x2, 0xf5, 0x0, 0x3, + 0xf4, 0x0, 0x2f, 0x50, 0x0, 0x3f, 0x40, 0x6d, + 0xfd, 0x80, 0x7d, 0xfd, 0x70, + + /* U+49 "I" */ + 0x5c, 0xfe, 0xa0, 0xf, 0x70, 0x0, 0xf7, 0x0, + 0xf, 0x70, 0x0, 0xf7, 0x0, 0xf, 0x70, 0x0, + 0xf7, 0x0, 0xf, 0x70, 0x0, 0xf7, 0x0, 0xf, + 0x70, 0x5c, 0xfe, 0xa0, + + /* U+4A "J" */ + 0x0, 0x2b, 0xff, 0xb1, 0x0, 0x0, 0xcb, 0x0, + 0x0, 0x0, 0xcb, 0x0, 0x0, 0x0, 0xcb, 0x0, + 0x0, 0x0, 0xcb, 0x0, 0x0, 0x0, 0xcb, 0x0, + 0x0, 0x0, 0xcb, 0x0, 0x9f, 0x40, 0xca, 0x0, + 0xef, 0x30, 0xd9, 0x0, 0xa1, 0x3, 0xf4, 0x0, + 0x2a, 0xad, 0x70, 0x0, + + /* U+4B "K" */ + 0x6d, 0xfd, 0x80, 0xbf, 0xfc, 0x10, 0x2f, 0x50, + 0x0, 0xd5, 0x0, 0x2, 0xf5, 0x0, 0x96, 0x0, + 0x0, 0x2f, 0x50, 0x78, 0x0, 0x0, 0x2, 0xf5, + 0x5f, 0x20, 0x0, 0x0, 0x2f, 0x9c, 0xfb, 0x0, + 0x0, 0x2, 0xfd, 0x17, 0xf4, 0x0, 0x0, 0x2f, + 0x50, 0xd, 0xd0, 0x0, 0x2, 0xf5, 0x0, 0x4f, + 0x80, 0x0, 0x2f, 0x50, 0x0, 0xbf, 0x20, 0x6d, + 0xfd, 0x80, 0x9e, 0xfe, 0x70, + + /* U+4C "L" */ + 0x5c, 0xfe, 0x90, 0x0, 0x0, 0x1f, 0x60, 0x0, + 0x0, 0x1, 0xf6, 0x0, 0x0, 0x0, 0x1f, 0x60, + 0x0, 0x0, 0x1, 0xf6, 0x0, 0x0, 0x0, 0x1f, + 0x60, 0x0, 0x0, 0x1, 0xf6, 0x0, 0x0, 0x10, + 0x1f, 0x60, 0x0, 0x19, 0x1, 0xf6, 0x0, 0x5, + 0x70, 0x1f, 0x60, 0x1, 0xd6, 0x5c, 0xfe, 0xbb, + 0xff, 0x50, + + /* U+4D "M" */ + 0x6d, 0xff, 0x0, 0x0, 0x5f, 0xfb, 0x10, 0x2d, + 0xf4, 0x0, 0x9, 0xdb, 0x0, 0x2, 0x9e, 0x90, + 0x0, 0xbc, 0xb0, 0x0, 0x29, 0xae, 0x0, 0x37, + 0xcb, 0x0, 0x2, 0x95, 0xf3, 0x8, 0x2c, 0xb0, + 0x0, 0x29, 0xf, 0x80, 0xb0, 0xcb, 0x0, 0x2, + 0x90, 0xbd, 0x19, 0xc, 0xb0, 0x0, 0x29, 0x5, + 0xf9, 0x40, 0xcb, 0x0, 0x2, 0x90, 0x1f, 0xf0, + 0xc, 0xb0, 0x0, 0x5c, 0x0, 0xbb, 0x0, 0xcb, + 0x0, 0x8f, 0xfc, 0x16, 0x62, 0xbf, 0xfb, 0x10, + + /* U+4E "N" */ + 0x8e, 0xf5, 0x0, 0x2d, 0xff, 0x70, 0x3f, 0xe1, + 0x0, 0xe, 0x30, 0x3, 0xbf, 0xa0, 0x0, 0xb1, + 0x0, 0x38, 0x7f, 0x40, 0xb, 0x0, 0x3, 0x80, + 0xce, 0x0, 0xb0, 0x0, 0x38, 0x2, 0xf9, 0xb, + 0x0, 0x3, 0x80, 0x8, 0xf4, 0xb0, 0x0, 0x38, + 0x0, 0xd, 0xdb, 0x0, 0x3, 0x80, 0x0, 0x3f, + 0xf0, 0x0, 0x6b, 0x0, 0x0, 0x8f, 0x0, 0x8f, + 0xfd, 0x0, 0x0, 0xd0, 0x0, + + /* U+4F "O" */ + 0x0, 0x1a, 0xbb, 0xb4, 0x0, 0x1, 0xe6, 0x0, + 0x2e, 0x50, 0xa, 0xd0, 0x0, 0x7, 0xf1, 0x1f, + 0x80, 0x0, 0x2, 0xf7, 0x4f, 0x60, 0x0, 0x0, + 0xfa, 0x6f, 0x50, 0x0, 0x0, 0xfb, 0x5f, 0x60, + 0x0, 0x0, 0xfa, 0x1f, 0x80, 0x0, 0x2, 0xf7, + 0xb, 0xd0, 0x0, 0x7, 0xf1, 0x1, 0xe6, 0x0, + 0x2e, 0x50, 0x0, 0x1a, 0xbb, 0xb4, 0x0, + + /* U+50 "P" */ + 0x6d, 0xfd, 0xbb, 0xc6, 0x0, 0x3f, 0x50, 0x5, + 0xf4, 0x3, 0xf5, 0x0, 0xf, 0x90, 0x3f, 0x50, + 0x1, 0xf9, 0x3, 0xf5, 0x0, 0x8f, 0x30, 0x3f, + 0xca, 0xba, 0x30, 0x3, 0xf5, 0x0, 0x0, 0x0, + 0x3f, 0x50, 0x0, 0x0, 0x3, 0xf5, 0x0, 0x0, + 0x0, 0x3f, 0x50, 0x0, 0x0, 0x6d, 0xfd, 0x90, + 0x0, 0x0, + + /* U+51 "Q" */ + 0x0, 0x19, 0xbb, 0xb4, 0x0, 0x1, 0xd6, 0x0, + 0x2e, 0x50, 0x9, 0xd0, 0x0, 0x6, 0xf1, 0x1f, + 0x90, 0x0, 0x2, 0xf7, 0x4f, 0x70, 0x0, 0x0, + 0xfb, 0x6f, 0x60, 0x0, 0x0, 0xfc, 0x5f, 0x60, + 0x0, 0x0, 0xfa, 0x1f, 0x82, 0xab, 0x31, 0xf6, + 0xa, 0xca, 0x1, 0xd7, 0xe0, 0x1, 0xdd, 0x0, + 0xaf, 0x40, 0x0, 0x19, 0xba, 0xec, 0x0, 0x0, + 0x0, 0x0, 0x7f, 0x18, 0x0, 0x0, 0x0, 0x4f, + 0x8a, 0x0, 0x0, 0x0, 0xa, 0xe4, + + /* U+52 "R" */ + 0x7d, 0xfd, 0xbb, 0xc4, 0x0, 0x3, 0xf4, 0x0, + 0x7f, 0x20, 0x3, 0xf4, 0x0, 0x3f, 0x60, 0x3, + 0xf4, 0x0, 0x3f, 0x50, 0x3, 0xf4, 0x0, 0xad, + 0x0, 0x3, 0xfc, 0xce, 0x70, 0x0, 0x3, 0xf4, + 0x7, 0xd0, 0x0, 0x3, 0xf4, 0x0, 0xf6, 0x0, + 0x3, 0xf4, 0x0, 0xea, 0x3, 0x3, 0xf4, 0x0, + 0xbe, 0x55, 0x7d, 0xfd, 0x70, 0x4e, 0xc1, + + /* U+53 "S" */ + 0x1, 0xab, 0xa8, 0x84, 0xb, 0x40, 0x5, 0xf5, + 0xf, 0x0, 0x0, 0xa6, 0xf, 0x70, 0x0, 0x35, + 0xb, 0xfd, 0x84, 0x0, 0x0, 0x9e, 0xff, 0xd1, + 0x11, 0x0, 0x38, 0xf9, 0x47, 0x0, 0x0, 0x6c, + 0x4d, 0x0, 0x0, 0x3b, 0x4f, 0x90, 0x0, 0x96, + 0x48, 0x6b, 0xab, 0x70, + + /* U+54 "T" */ + 0x9f, 0xdd, 0xfd, 0xdf, 0x79, 0xa0, 0x4f, 0x30, + 0xb8, 0xa2, 0x4, 0xf3, 0x4, 0x8a, 0x0, 0x4f, + 0x30, 0x9, 0x20, 0x4, 0xf3, 0x0, 0x20, 0x0, + 0x4f, 0x30, 0x0, 0x0, 0x4, 0xf3, 0x0, 0x0, + 0x0, 0x4f, 0x30, 0x0, 0x0, 0x4, 0xf3, 0x0, + 0x0, 0x0, 0x4f, 0x30, 0x0, 0x0, 0x9d, 0xfd, + 0x80, 0x0, + + /* U+55 "U" */ + 0x8d, 0xfc, 0x60, 0x1d, 0xff, 0x70, 0x5f, 0x20, + 0x0, 0xc, 0x40, 0x5, 0xf2, 0x0, 0x0, 0xa2, + 0x0, 0x5f, 0x20, 0x0, 0x9, 0x10, 0x5, 0xf2, + 0x0, 0x0, 0x91, 0x0, 0x5f, 0x20, 0x0, 0x9, + 0x10, 0x5, 0xf2, 0x0, 0x0, 0x91, 0x0, 0x5f, + 0x20, 0x0, 0xa, 0x0, 0x4, 0xf4, 0x0, 0x0, + 0xb0, 0x0, 0xd, 0xd1, 0x0, 0x86, 0x0, 0x0, + 0x1a, 0xec, 0xc6, 0x0, 0x0, + + /* U+56 "V" */ + 0x1c, 0xff, 0xb0, 0xa, 0xff, 0x80, 0xd, 0xd0, + 0x0, 0x9, 0x70, 0x0, 0x7f, 0x20, 0x0, 0xc0, + 0x0, 0x1, 0xf8, 0x0, 0x2a, 0x0, 0x0, 0xc, + 0xe0, 0x7, 0x50, 0x0, 0x0, 0x6f, 0x30, 0xc0, + 0x0, 0x0, 0x1, 0xf9, 0x2a, 0x0, 0x0, 0x0, + 0xa, 0xe8, 0x40, 0x0, 0x0, 0x0, 0x5f, 0xe0, + 0x0, 0x0, 0x0, 0x0, 0xf9, 0x0, 0x0, 0x0, + 0x0, 0x9, 0x40, 0x0, 0x0, + + /* U+57 "W" */ + 0xaf, 0xe9, 0x3d, 0xfd, 0x62, 0xdf, 0xd0, 0xc, + 0xc0, 0x1, 0xf7, 0x0, 0xd, 0x0, 0x7, 0xf1, + 0x0, 0xec, 0x0, 0x38, 0x0, 0x3, 0xf5, 0x2, + 0xff, 0x0, 0x74, 0x0, 0x0, 0xea, 0x6, 0x7f, + 0x50, 0xb0, 0x0, 0x0, 0x9e, 0xa, 0x1e, 0x90, + 0xb0, 0x0, 0x0, 0x5f, 0x4b, 0x9, 0xd4, 0x70, + 0x0, 0x0, 0xf, 0xc8, 0x4, 0xfb, 0x30, 0x0, + 0x0, 0xb, 0xf4, 0x0, 0xfe, 0x0, 0x0, 0x0, + 0x6, 0xf0, 0x0, 0xba, 0x0, 0x0, 0x0, 0x2, + 0xb0, 0x0, 0x66, 0x0, 0x0, + + /* U+58 "X" */ + 0xb, 0xff, 0xb0, 0x7f, 0xfb, 0x0, 0x9, 0xf3, + 0x0, 0xa6, 0x0, 0x0, 0x1e, 0xc0, 0x2b, 0x0, + 0x0, 0x0, 0x6f, 0x6b, 0x10, 0x0, 0x0, 0x0, + 0xcf, 0x70, 0x0, 0x0, 0x0, 0x4, 0xf8, 0x0, + 0x0, 0x0, 0x0, 0xab, 0xf2, 0x0, 0x0, 0x0, + 0x49, 0x1e, 0xc0, 0x0, 0x0, 0xc, 0x0, 0x6f, + 0x50, 0x0, 0x9, 0x90, 0x0, 0xce, 0x10, 0xd, + 0xff, 0x80, 0x9e, 0xfd, 0x60, + + /* U+59 "Y" */ + 0x1c, 0xff, 0xb1, 0x3c, 0xfe, 0x50, 0xb, 0xf1, + 0x0, 0xe, 0x10, 0x0, 0x3f, 0x90, 0x5, 0x70, + 0x0, 0x0, 0xaf, 0x20, 0xc0, 0x0, 0x0, 0x2, + 0xfb, 0x68, 0x0, 0x0, 0x0, 0x8, 0xfe, 0x10, + 0x0, 0x0, 0x0, 0x1f, 0xa0, 0x0, 0x0, 0x0, + 0x0, 0xe9, 0x0, 0x0, 0x0, 0x0, 0xe, 0x90, + 0x0, 0x0, 0x0, 0x0, 0xe9, 0x0, 0x0, 0x0, + 0x5, 0xbf, 0xeb, 0x10, 0x0, + + /* U+5A "Z" */ + 0x1f, 0xfc, 0xbc, 0xf8, 0x2f, 0x20, 0xb, 0xf1, + 0x39, 0x0, 0x3f, 0x70, 0x35, 0x0, 0xce, 0x0, + 0x0, 0x5, 0xf5, 0x0, 0x0, 0xe, 0xc0, 0x0, + 0x0, 0x7f, 0x30, 0x2, 0x1, 0xfa, 0x0, 0x1a, + 0x9, 0xf2, 0x0, 0x59, 0x2f, 0x90, 0x0, 0xc8, + 0xaf, 0xbb, 0xbe, 0xf7, + + /* U+5B "[" */ + 0x2f, 0x98, 0x2f, 0x10, 0x2f, 0x10, 0x2f, 0x10, + 0x2f, 0x10, 0x2f, 0x10, 0x2f, 0x10, 0x2f, 0x10, + 0x2f, 0x10, 0x2f, 0x10, 0x2f, 0x10, 0x1c, 0x88, + + /* U+5C "\\" */ + 0xb1, 0x0, 0x0, 0x4, 0x70, 0x0, 0x0, 0xb, + 0x0, 0x0, 0x0, 0x57, 0x0, 0x0, 0x0, 0xb0, + 0x0, 0x0, 0x5, 0x60, 0x0, 0x0, 0xb, 0x0, + 0x0, 0x0, 0x66, 0x0, 0x0, 0x0, 0xb0, 0x0, + 0x0, 0x6, 0x50, 0x0, 0x0, 0xb, 0x0, + + /* U+5D "]" */ + 0x48, 0xd8, 0x0, 0xa8, 0x0, 0xa8, 0x0, 0xa8, + 0x0, 0xa8, 0x0, 0xa8, 0x0, 0xa8, 0x0, 0xa8, + 0x0, 0xa8, 0x0, 0xa8, 0x0, 0xa8, 0x48, 0xa6, + + /* U+5E "^" */ + 0x0, 0xc, 0xd0, 0x0, 0x0, 0x3e, 0xe4, 0x0, + 0x0, 0xa8, 0x6c, 0x0, 0x2, 0xf1, 0xe, 0x30, + 0x9, 0x90, 0x7, 0xb0, 0x1f, 0x10, 0x0, 0xe2, + + /* U+5F "_" */ + 0xee, 0xee, 0xee, 0x90, + + /* U+60 "`" */ + 0x41, 0x0, 0x7c, 0x0, 0x3, 0x90, + + /* U+61 "a" */ + 0x4, 0xaa, 0xc5, 0x0, 0xf, 0x40, 0x5e, 0x0, + 0x8, 0x20, 0x5f, 0x0, 0x3, 0xa9, 0x9f, 0x0, + 0x2f, 0x30, 0x4f, 0x0, 0x5f, 0x0, 0xaf, 0x10, + 0xb, 0xdb, 0x4c, 0xd1, + + /* U+62 "b" */ + 0xaf, 0x60, 0x0, 0x0, 0xd6, 0x0, 0x0, 0xd, + 0x60, 0x0, 0x0, 0xd6, 0x0, 0x0, 0xd, 0x9a, + 0xd9, 0x0, 0xdc, 0x0, 0xe7, 0xd, 0x70, 0x9, + 0xc0, 0xd5, 0x0, 0x7e, 0xe, 0x60, 0x8, 0xc0, + 0xeb, 0x0, 0xd6, 0xb, 0x5b, 0xb7, 0x0, + + /* U+63 "c" */ + 0x3, 0xca, 0xb1, 0xe, 0x50, 0xe6, 0x6f, 0x0, + 0x82, 0x8e, 0x0, 0x0, 0x6f, 0x0, 0x2, 0x1f, + 0x70, 0x56, 0x4, 0xde, 0x90, + + /* U+64 "d" */ + 0x0, 0x3, 0xbf, 0x50, 0x0, 0x0, 0xf, 0x50, + 0x0, 0x0, 0xf, 0x50, 0x0, 0x0, 0xf, 0x50, + 0x3, 0xdc, 0x7f, 0x50, 0xe, 0x70, 0x7f, 0x50, + 0x4f, 0x10, 0xf, 0x50, 0x6f, 0x0, 0xf, 0x50, + 0x4f, 0x0, 0xf, 0x50, 0xe, 0x50, 0x6f, 0x50, + 0x3, 0xcb, 0x7f, 0xd4, + + /* U+65 "e" */ + 0x3, 0xba, 0xb1, 0x0, 0xe4, 0x7, 0xa0, 0x5f, + 0x0, 0x4f, 0x7, 0xfa, 0xab, 0xd2, 0x6f, 0x0, + 0x0, 0x1, 0xf6, 0x0, 0xa0, 0x3, 0xcc, 0xb3, + 0x0, + + /* U+66 "f" */ + 0x0, 0x7b, 0xc5, 0x3, 0xe0, 0xab, 0x8, 0xb0, + 0x11, 0x9, 0xb0, 0x0, 0x7d, 0xea, 0x10, 0x9, + 0xb0, 0x0, 0x9, 0xb0, 0x0, 0x9, 0xb0, 0x0, + 0x9, 0xb0, 0x0, 0x9, 0xb0, 0x0, 0x5e, 0xe8, + 0x0, + + /* U+67 "g" */ + 0x4, 0xb9, 0xb9, 0xe1, 0xf, 0x20, 0x7a, 0x60, + 0x2f, 0x0, 0x5e, 0x0, 0xe, 0x40, 0x9a, 0x0, + 0x9, 0xc9, 0x81, 0x0, 0x4b, 0x43, 0x31, 0x0, + 0x1d, 0xff, 0xff, 0x20, 0x5b, 0x0, 0xb, 0x60, + 0xa7, 0x0, 0xa, 0x30, 0x2b, 0xa9, 0xa6, 0x0, + + /* U+68 "h" */ + 0x8e, 0xa0, 0x0, 0x0, 0x9, 0xa0, 0x0, 0x0, + 0x9, 0xa0, 0x0, 0x0, 0x9, 0xa0, 0x0, 0x0, + 0x9, 0xa8, 0xed, 0x20, 0x9, 0xe4, 0xb, 0xb0, + 0x9, 0xc0, 0x6, 0xd0, 0x9, 0xa0, 0x6, 0xd0, + 0x9, 0xa0, 0x6, 0xd0, 0x9, 0xa0, 0x6, 0xd0, + 0x5e, 0xe6, 0x4c, 0xf8, + + /* U+69 "i" */ + 0x7, 0xa0, 0x4, 0x60, 0x0, 0x0, 0x0, 0x0, + 0x8e, 0xc0, 0x8, 0xc0, 0x8, 0xc0, 0x8, 0xc0, + 0x8, 0xc0, 0x8, 0xc0, 0x5d, 0xe7, + + /* U+6A "j" */ + 0x0, 0x7, 0xb0, 0x0, 0x46, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x9e, 0xc0, 0x0, 0x8c, 0x0, + 0x8, 0xc0, 0x0, 0x8c, 0x0, 0x8, 0xc0, 0x0, + 0x8c, 0x0, 0x8, 0xb0, 0x0, 0x8a, 0xf, 0x3a, + 0x60, 0xbb, 0xa0, + + /* U+6B "k" */ + 0x9e, 0xa0, 0x0, 0x0, 0x9, 0xa0, 0x0, 0x0, + 0x9, 0xa0, 0x0, 0x0, 0x9, 0xa0, 0x0, 0x0, + 0x9, 0xa2, 0xbf, 0xc2, 0x9, 0xa0, 0xa5, 0x0, + 0x9, 0xa8, 0x90, 0x0, 0x9, 0xfb, 0xe1, 0x0, + 0x9, 0xb0, 0xda, 0x0, 0x9, 0xa0, 0x3f, 0x50, + 0x5e, 0xe6, 0x6f, 0xf8, + + /* U+6C "l" */ + 0x8e, 0xb0, 0x8, 0xb0, 0x8, 0xb0, 0x8, 0xb0, + 0x8, 0xb0, 0x8, 0xb0, 0x8, 0xb0, 0x8, 0xb0, + 0x8, 0xb0, 0x8, 0xb0, 0x5d, 0xe7, + + /* U+6D "m" */ + 0x7e, 0xba, 0xec, 0x3b, 0xea, 0x0, 0x9, 0xf3, + 0xd, 0xe2, 0x1e, 0x60, 0x9, 0xc0, 0xa, 0xa0, + 0xc, 0x80, 0x9, 0xb0, 0xa, 0x90, 0xb, 0x80, + 0x9, 0xb0, 0xa, 0x90, 0xb, 0x80, 0x9, 0xb0, + 0xa, 0x90, 0xb, 0x80, 0x5e, 0xe6, 0x6e, 0xd5, + 0x7e, 0xd5, + + /* U+6E "n" */ + 0x7e, 0xb9, 0xed, 0x10, 0x9, 0xf4, 0xb, 0xb0, + 0x9, 0xc0, 0x6, 0xd0, 0x9, 0xa0, 0x6, 0xd0, + 0x9, 0xa0, 0x6, 0xd0, 0x9, 0xa0, 0x6, 0xd0, + 0x5e, 0xe6, 0x4c, 0xf8, + + /* U+6F "o" */ + 0x3, 0xba, 0xa0, 0x0, 0xe3, 0x8, 0xa0, 0x6f, + 0x0, 0x4f, 0x8, 0xe0, 0x3, 0xf2, 0x6f, 0x0, + 0x4f, 0x0, 0xe3, 0x9, 0xa0, 0x3, 0xba, 0xa1, + 0x0, + + /* U+70 "p" */ + 0x7e, 0xba, 0xca, 0x0, 0x9, 0xf3, 0xb, 0xa0, + 0x9, 0xc0, 0x5, 0xf0, 0x9, 0xb0, 0x4, 0xf1, + 0x9, 0xc0, 0x6, 0xf0, 0x9, 0xf2, 0xb, 0x90, + 0x9, 0xba, 0xda, 0x0, 0x9, 0xb0, 0x0, 0x0, + 0x9, 0xb0, 0x0, 0x0, 0x5d, 0xe7, 0x0, 0x0, + + /* U+71 "q" */ + 0x3, 0xca, 0x94, 0x60, 0xe, 0x40, 0x6f, 0x40, + 0x5f, 0x0, 0x1f, 0x40, 0x7e, 0x0, 0xf, 0x40, + 0x6f, 0x0, 0x1f, 0x40, 0x1f, 0x50, 0x7f, 0x40, + 0x4, 0xdc, 0x7f, 0x40, 0x0, 0x0, 0xf, 0x40, + 0x0, 0x0, 0xf, 0x40, 0x0, 0x1, 0x9f, 0xb2, + + /* U+72 "r" */ + 0x8e, 0xa5, 0xb8, 0x9, 0xc4, 0xaa, 0x9, 0xf0, + 0x0, 0x9, 0xc0, 0x0, 0x9, 0xa0, 0x0, 0x9, + 0xa0, 0x0, 0x5e, 0xe7, 0x0, + + /* U+73 "s" */ + 0x8, 0xaa, 0xb3, 0x29, 0x0, 0xb3, 0x2e, 0x73, + 0x31, 0x7, 0xef, 0xe2, 0x34, 0x2, 0xa8, 0x5c, + 0x0, 0x47, 0x59, 0xa9, 0xa1, + + /* U+74 "t" */ + 0x0, 0x90, 0x0, 0x39, 0x0, 0xb, 0x90, 0x7, + 0xed, 0xa5, 0xa, 0x90, 0x0, 0xa9, 0x0, 0xa, + 0x90, 0x0, 0xa9, 0x8, 0x9, 0xb0, 0xa0, 0x3d, + 0xd4, + + /* U+75 "u" */ + 0x8f, 0x90, 0x8e, 0xc0, 0xa, 0x90, 0x8, 0xc0, + 0xa, 0x90, 0x8, 0xc0, 0xa, 0x90, 0x8, 0xc0, + 0xa, 0x90, 0x9, 0xc0, 0x8, 0xb0, 0x1e, 0xc0, + 0x1, 0xcc, 0x99, 0xfb, + + /* U+76 "v" */ + 0x9f, 0xb2, 0x5f, 0xc0, 0xc, 0x80, 0xb, 0x0, + 0x6, 0xe0, 0x28, 0x0, 0x0, 0xf5, 0x82, 0x0, + 0x0, 0x9b, 0xa0, 0x0, 0x0, 0x3f, 0x60, 0x0, + 0x0, 0xc, 0x10, 0x0, + + /* U+77 "w" */ + 0x7f, 0xb2, 0xcf, 0x72, 0xdd, 0x10, 0xc8, 0x3, + 0xf1, 0x9, 0x20, 0x6, 0xd0, 0x8e, 0x70, 0xa0, + 0x0, 0x1f, 0x3a, 0x6c, 0x37, 0x0, 0x0, 0xbc, + 0x71, 0xfb, 0x10, 0x0, 0x6, 0xf1, 0xb, 0xc0, + 0x0, 0x0, 0x1b, 0x0, 0x56, 0x0, 0x0, + + /* U+78 "x" */ + 0x8f, 0xd3, 0xaf, 0x70, 0x9, 0xe1, 0x76, 0x0, + 0x0, 0xdc, 0x90, 0x0, 0x0, 0x4f, 0x50, 0x0, + 0x0, 0xa9, 0xe1, 0x0, 0x7, 0x60, 0xda, 0x0, + 0x9f, 0x92, 0xdf, 0xb0, + + /* U+79 "y" */ + 0x8f, 0xc2, 0x5e, 0xc0, 0xb, 0xa0, 0xb, 0x0, + 0x4, 0xf1, 0x19, 0x0, 0x0, 0xe6, 0x73, 0x0, + 0x0, 0x8d, 0xb0, 0x0, 0x0, 0x2f, 0x80, 0x0, + 0x0, 0xb, 0x20, 0x0, 0x0, 0xa, 0x0, 0x0, + 0xc6, 0x74, 0x0, 0x0, 0xad, 0x70, 0x0, 0x0, + + /* U+7A "z" */ + 0x2f, 0xba, 0xfa, 0x29, 0x6, 0xf2, 0x13, 0x1e, + 0x70, 0x0, 0xad, 0x0, 0x4, 0xf3, 0x6, 0xd, + 0x90, 0x1b, 0x6f, 0xba, 0xeb, + + /* U+7B "{" */ + 0x0, 0x99, 0x0, 0xf0, 0x1, 0xe0, 0x1, 0xe0, + 0x2, 0xd0, 0xb, 0x60, 0x8, 0x90, 0x1, 0xd0, + 0x1, 0xe0, 0x1, 0xe0, 0x0, 0xf0, 0x0, 0x69, + + /* U+7C "|" */ + 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, 0x79, + 0x79, 0x79, 0x79, + + /* U+7D "}" */ + 0x4c, 0x20, 0x8, 0x70, 0x7, 0x80, 0x7, 0x80, + 0x6, 0x90, 0x1, 0xc4, 0x3, 0xc2, 0x7, 0x80, + 0x7, 0x80, 0x7, 0x80, 0x9, 0x60, 0x49, 0x10, + + /* U+7E "~" */ + 0x8, 0xeb, 0x50, 0x72, 0x1a, 0x15, 0xdf, 0xb0, + 0x0, 0x0, 0x1, 0x0, + + /* U+5D0 "א" */ + 0x5, 0x0, 0x3, 0x0, 0xe, 0x80, 0x3f, 0xd3, + 0x9, 0xf5, 0x1d, 0xf7, 0x0, 0xcf, 0x37, 0x61, + 0x2, 0xde, 0xed, 0x0, 0xb, 0x82, 0xff, 0x0, + 0xd, 0xd0, 0x5f, 0xa0, 0xb, 0xf5, 0x7, 0xf5, + 0x2f, 0xf7, 0x0, 0xb5, 0x0, 0x0, 0x0, 0x0, + + /* U+5D1 "ב" */ + 0x13, 0x0, 0x0, 0x4, 0xff, 0xff, 0x70, 0x2d, + 0xee, 0xfd, 0x0, 0x0, 0x4, 0xf0, 0x0, 0x0, + 0xe, 0x0, 0x0, 0x0, 0xc0, 0x0, 0x0, 0x27, + 0x2, 0xee, 0xef, 0xe7, 0x6f, 0xff, 0xff, 0x40, + + /* U+5D2 "ג" */ + 0x3, 0x0, 0x0, 0xa, 0xff, 0x30, 0x6, 0xef, + 0x60, 0x0, 0x9, 0x50, 0x0, 0x7, 0x40, 0x0, + 0x8, 0x70, 0x0, 0xd, 0xc0, 0x1e, 0xf4, 0xe1, + 0x5f, 0xd0, 0x72, + + /* U+5D3 "ד" */ + 0x22, 0x0, 0x0, 0x8, 0xff, 0xff, 0xfa, 0x4d, + 0xee, 0xef, 0x90, 0x0, 0x0, 0xb0, 0x0, 0x0, + 0x49, 0x0, 0x0, 0x5, 0xa0, 0x0, 0x0, 0x5b, + 0x0, 0x0, 0x5, 0xd0, 0x0, 0x0, 0x68, 0x0, + + /* U+5D4 "ה" */ + 0x4, 0x0, 0x0, 0x0, 0x2f, 0xff, 0xff, 0xf0, + 0x1c, 0xee, 0xee, 0xf0, 0x0, 0x0, 0x3, 0x90, + 0x0, 0x0, 0x6, 0x80, 0xd, 0x20, 0x7, 0x90, + 0xf, 0x20, 0x6, 0xb0, 0xf, 0x20, 0x6, 0xc0, + 0x1f, 0x0, 0x7, 0x70, 0x1, 0x0, 0x0, 0x0, + + /* U+5D5 "ו" */ + 0x3, 0x0, 0x4f, 0xf7, 0x2d, 0xfd, 0x0, 0x2d, + 0x0, 0xd, 0x0, 0xd, 0x0, 0xd, 0x0, 0xd, + 0x0, 0x9, + + /* U+5D6 "ז" */ + 0x4, 0x0, 0x3, 0xff, 0xa0, 0x1d, 0xff, 0x0, + 0xa, 0x0, 0x3, 0xb0, 0x0, 0x4c, 0x0, 0x3, + 0xe0, 0x0, 0x3e, 0x0, 0x4, 0x90, 0x0, + + /* U+5D7 "ח" */ + 0x3, 0x0, 0x0, 0x0, 0x4f, 0xff, 0xff, 0xf3, + 0x1d, 0xfe, 0xee, 0xf4, 0x8, 0x60, 0x0, 0xc0, + 0xd, 0x20, 0x2, 0xc0, 0xd, 0x30, 0x2, 0xe0, + 0xe, 0x30, 0x1, 0xf0, 0xe, 0x40, 0x1, 0xf0, + 0xd, 0x0, 0x2, 0xb0, + + /* U+5D8 "ט" */ + 0x3, 0x0, 0x0, 0x0, 0x2f, 0xf3, 0x2e, 0xb0, + 0x1d, 0xf6, 0xdf, 0xf3, 0x5, 0x64, 0xb4, 0xe5, + 0xa, 0x31, 0x0, 0x75, 0xc, 0x40, 0x0, 0x74, + 0xa, 0x80, 0x0, 0xc1, 0x7, 0xfe, 0xee, 0xd0, + 0x5, 0xff, 0xff, 0x70, + + /* U+5D9 "י" */ + 0x3, 0x0, 0x4f, 0xf7, 0x2d, 0xfc, 0x0, 0x4a, + 0x0, 0x84, 0x0, 0x50, + + /* U+5DA "ך" */ + 0x22, 0x0, 0x0, 0x6, 0xff, 0xff, 0xe0, 0x3d, + 0xee, 0xed, 0x0, 0x0, 0x4, 0x60, 0x0, 0x0, + 0x56, 0x0, 0x0, 0x5, 0x60, 0x0, 0x0, 0x67, + 0x0, 0x0, 0x6, 0x80, 0x0, 0x0, 0x69, 0x0, + 0x0, 0x7, 0xa0, 0x0, 0x0, 0x7b, 0x0, 0x0, + 0x8, 0x90, 0x0, 0x0, 0x41, 0x0, + + /* U+5DB "כ" */ + 0x4, 0x0, 0x0, 0x1, 0xff, 0xff, 0x80, 0xc, + 0xee, 0xff, 0x30, 0x0, 0x0, 0xb7, 0x0, 0x0, + 0x3, 0x90, 0x0, 0x0, 0x39, 0x0, 0x0, 0x9, + 0x70, 0xde, 0xee, 0xf2, 0x3f, 0xff, 0xf7, 0x0, + + /* U+5DC "ל" */ + 0x31, 0x0, 0x0, 0x8, 0xf1, 0x0, 0x0, 0xc, + 0x0, 0x0, 0x0, 0x90, 0x0, 0x0, 0x2a, 0x0, + 0x0, 0x3, 0xff, 0xff, 0xf7, 0x2e, 0xee, 0xef, + 0xa0, 0x0, 0x0, 0x7b, 0x0, 0x0, 0x9, 0x80, + 0x0, 0x4, 0xd1, 0x0, 0x8, 0x90, 0x0, 0x5, + 0xb0, 0x0, 0x0, 0x69, 0x0, 0x0, + + /* U+5DD "ם" */ + 0x3, 0x0, 0x0, 0x0, 0xff, 0xff, 0xf8, 0xb, + 0xfe, 0xef, 0xe0, 0xa2, 0x0, 0x1e, 0xc, 0x0, + 0x0, 0xc1, 0xb0, 0x0, 0xc, 0x2c, 0x0, 0x0, + 0xd2, 0xfe, 0xee, 0xee, 0x1f, 0xff, 0xff, 0xc0, + + /* U+5DE "מ" */ + 0x3, 0x0, 0x0, 0x0, 0x2f, 0xd1, 0x8e, 0x40, + 0x1f, 0xf8, 0xff, 0xf0, 0x0, 0xa8, 0x14, 0xe5, + 0x2, 0xb0, 0x0, 0x76, 0x8, 0x60, 0x0, 0x56, + 0xc, 0x20, 0x0, 0x65, 0xe, 0x18, 0xee, 0xf3, + 0xe, 0xd, 0xff, 0xf0, 0x0, 0x0, 0x0, 0x0, + + /* U+5DF "ן" */ + 0x13, 0x0, 0x5f, 0xf8, 0x2d, 0xfb, 0x0, 0x86, + 0x0, 0xb1, 0x0, 0xd0, 0x0, 0xd0, 0x0, 0xe1, + 0x0, 0xe2, 0x0, 0xe2, 0x0, 0xf3, 0x0, 0xf2, + 0x0, 0x50, + + /* U+5E0 "נ" */ + 0x3, 0x10, 0x0, 0x9f, 0xe2, 0x6, 0xef, 0x40, + 0x0, 0xa2, 0x0, 0xb, 0x10, 0x0, 0xb1, 0x0, + 0xb, 0x53, 0xee, 0xf7, 0x7f, 0xff, 0x50, + + /* U+5E1 "ס" */ + 0x3, 0x0, 0x0, 0x0, 0xff, 0xff, 0xa0, 0xc, + 0xfe, 0xef, 0x80, 0xa2, 0x0, 0x5c, 0xb, 0x0, + 0x0, 0xb2, 0xb0, 0x0, 0xc, 0xf, 0x40, 0x7, + 0xb0, 0xcf, 0xff, 0xf6, 0x2, 0xcf, 0xe8, 0x0, + + /* U+5E2 "ע" */ + 0x3, 0x0, 0x21, 0x0, 0x3f, 0xd3, 0x8f, 0xe2, + 0x1e, 0xf7, 0x5f, 0xf3, 0x0, 0xa0, 0x2, 0xb0, + 0x2, 0xd0, 0xa, 0x30, 0x0, 0xd9, 0x2e, 0x0, + 0x0, 0x2d, 0x8a, 0x0, 0x0, 0xb, 0xf6, 0x0, + 0x6, 0xdf, 0xd0, 0x0, 0x5f, 0xf9, 0x10, 0x0, + 0x59, 0x10, 0x0, 0x0, + + /* U+5E3 "ף" */ + 0x4, 0x0, 0x0, 0x1, 0xff, 0xff, 0xd1, 0xc, + 0xfe, 0xef, 0x60, 0x93, 0x0, 0x77, 0xf, 0xfa, + 0x3, 0x81, 0xb5, 0xa0, 0x49, 0x0, 0x0, 0x4, + 0x90, 0x0, 0x0, 0x5a, 0x0, 0x0, 0x5, 0xb0, + 0x0, 0x0, 0x6b, 0x0, 0x0, 0x6, 0xc0, 0x0, + 0x0, 0x7a, 0x0, 0x0, 0x4, 0x20, + + /* U+5E4 "פ" */ + 0x4, 0x0, 0x0, 0x0, 0xff, 0xff, 0xe2, 0xb, + 0xfe, 0xef, 0x90, 0x75, 0x0, 0x4c, 0xe, 0xfb, + 0x0, 0xb0, 0xc5, 0xc0, 0xc, 0x0, 0x0, 0x4, + 0xb0, 0xde, 0xee, 0xf9, 0x3f, 0xff, 0xff, 0x40, + + /* U+5E5 "ץ" */ + 0x13, 0x0, 0x40, 0x5, 0xff, 0x2e, 0xf6, 0x2d, + 0xf4, 0xaf, 0xa0, 0xd, 0x15, 0x91, 0x2, 0xa3, + 0xa0, 0x0, 0x3a, 0xc0, 0x0, 0x2, 0xf7, 0x0, + 0x0, 0x1f, 0x30, 0x0, 0x0, 0xf2, 0x0, 0x0, + 0xe, 0x30, 0x0, 0x0, 0xd4, 0x0, 0x0, 0xd, + 0x40, 0x0, 0x0, 0x60, 0x0, 0x0, + + /* U+5E6 "צ" */ + 0x3, 0x0, 0x30, 0x3, 0xff, 0x3b, 0xf9, 0x1c, + 0xe5, 0x8f, 0xc0, 0x6, 0x54, 0xa0, 0x0, 0x5c, + 0xc0, 0x0, 0x0, 0xcd, 0x50, 0x0, 0x0, 0x7f, + 0x80, 0xde, 0xee, 0xfc, 0x2f, 0xff, 0xff, 0x80, + + /* U+5E7 "ק" */ + 0x4, 0x0, 0x0, 0x0, 0x2f, 0xff, 0xff, 0x90, + 0x1c, 0xee, 0xef, 0xf1, 0x1, 0x0, 0x2, 0xf2, + 0xe, 0x0, 0x0, 0xf1, 0xf, 0x0, 0x9, 0xb0, + 0xf, 0x2, 0xca, 0x10, 0xf, 0x1d, 0x30, 0x0, + 0xf, 0x57, 0x0, 0x0, 0xf, 0x0, 0x0, 0x0, + 0xf, 0x0, 0x0, 0x0, 0xf, 0x0, 0x0, 0x0, + 0x5, 0x0, 0x0, 0x0, + + /* U+5E8 "ר" */ + 0x3, 0x0, 0x0, 0x4, 0xff, 0xff, 0xd1, 0x2d, + 0xee, 0xef, 0x50, 0x0, 0x0, 0xa6, 0x0, 0x0, + 0x8, 0x60, 0x0, 0x0, 0x86, 0x0, 0x0, 0x8, + 0x60, 0x0, 0x0, 0x86, 0x0, 0x0, 0x7, 0x40, + + /* U+5E9 "ש" */ + 0x2, 0x0, 0x20, 0x1, 0x0, 0x3f, 0xd7, 0xea, + 0x6e, 0x80, 0x2f, 0xf7, 0xef, 0x7f, 0xf0, 0x6, + 0x60, 0x86, 0x1, 0xd0, 0xb, 0x31, 0xe0, 0x9, + 0x50, 0xb, 0x46, 0x90, 0x4b, 0x0, 0x8, 0x9a, + 0x21, 0xe2, 0x0, 0x4, 0xff, 0xef, 0xa0, 0x0, + 0x0, 0xff, 0xff, 0x20, 0x0, + + /* U+5EA "ת" */ + 0x2, 0x10, 0x0, 0x0, 0x8, 0xff, 0xff, 0xd1, + 0x5, 0xef, 0xee, 0xf5, 0x0, 0xb3, 0x0, 0xa6, + 0x3, 0xc0, 0x0, 0x86, 0x4, 0xb0, 0x0, 0x86, + 0x3, 0xd0, 0x0, 0x86, 0x6e, 0xf0, 0x0, 0x86, + 0xaf, 0xb0, 0x0, 0x73 +}; + + +/*--------------------- + * GLYPH DESCRIPTION + *--------------------*/ + +static const lv_font_fmt_txt_glyph_dsc_t glyph_dsc[] = { + {.bitmap_index = 0, .adv_w = 0, .box_w = 0, .box_h = 0, .ofs_x = 0, .ofs_y = 0} /* id = 0 reserved */, + {.bitmap_index = 0, .adv_w = 80, .box_w = 0, .box_h = 0, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 0, .adv_w = 64, .box_w = 2, .box_h = 11, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 11, .adv_w = 96, .box_w = 6, .box_h = 5, .ofs_x = 0, .ofs_y = 6}, + {.bitmap_index = 26, .adv_w = 128, .box_w = 8, .box_h = 10, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 66, .adv_w = 112, .box_w = 7, .box_h = 14, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 115, .adv_w = 176, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 176, .adv_w = 176, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 237, .adv_w = 48, .box_w = 3, .box_h = 5, .ofs_x = 0, .ofs_y = 6}, + {.bitmap_index = 245, .adv_w = 80, .box_w = 4, .box_h = 13, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 271, .adv_w = 80, .box_w = 5, .box_h = 13, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 304, .adv_w = 112, .box_w = 7, .box_h = 7, .ofs_x = 0, .ofs_y = 4}, + {.bitmap_index = 329, .adv_w = 128, .box_w = 8, .box_h = 8, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 361, .adv_w = 64, .box_w = 3, .box_h = 5, .ofs_x = 1, .ofs_y = -2}, + {.bitmap_index = 369, .adv_w = 96, .box_w = 6, .box_h = 2, .ofs_x = 0, .ofs_y = 4}, + {.bitmap_index = 375, .adv_w = 64, .box_w = 3, .box_h = 3, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 380, .adv_w = 64, .box_w = 6, .box_h = 11, .ofs_x = -1, .ofs_y = 0}, + {.bitmap_index = 413, .adv_w = 128, .box_w = 8, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 457, .adv_w = 128, .box_w = 6, .box_h = 11, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 490, .adv_w = 128, .box_w = 7, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 529, .adv_w = 128, .box_w = 7, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 568, .adv_w = 128, .box_w = 8, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 612, .adv_w = 128, .box_w = 7, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 651, .adv_w = 128, .box_w = 8, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 695, .adv_w = 128, .box_w = 7, .box_h = 12, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 737, .adv_w = 128, .box_w = 8, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 781, .adv_w = 128, .box_w = 8, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 825, .adv_w = 64, .box_w = 3, .box_h = 8, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 837, .adv_w = 64, .box_w = 3, .box_h = 10, .ofs_x = 1, .ofs_y = -2}, + {.bitmap_index = 852, .adv_w = 128, .box_w = 8, .box_h = 9, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 888, .adv_w = 128, .box_w = 8, .box_h = 5, .ofs_x = 0, .ofs_y = 1}, + {.bitmap_index = 908, .adv_w = 128, .box_w = 8, .box_h = 9, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 944, .adv_w = 112, .box_w = 7, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 983, .adv_w = 160, .box_w = 10, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1038, .adv_w = 160, .box_w = 11, .box_h = 11, .ofs_x = -1, .ofs_y = 0}, + {.bitmap_index = 1099, .adv_w = 160, .box_w = 9, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1149, .adv_w = 160, .box_w = 9, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1199, .adv_w = 160, .box_w = 10, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1254, .adv_w = 160, .box_w = 9, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1304, .adv_w = 144, .box_w = 9, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1354, .adv_w = 160, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1415, .adv_w = 176, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1476, .adv_w = 80, .box_w = 5, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1504, .adv_w = 112, .box_w = 8, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1548, .adv_w = 160, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1609, .adv_w = 144, .box_w = 9, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1659, .adv_w = 208, .box_w = 13, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1731, .adv_w = 176, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1792, .adv_w = 160, .box_w = 10, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1847, .adv_w = 144, .box_w = 9, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 1897, .adv_w = 160, .box_w = 10, .box_h = 14, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 1967, .adv_w = 160, .box_w = 10, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2022, .adv_w = 128, .box_w = 8, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2066, .adv_w = 144, .box_w = 9, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2116, .adv_w = 176, .box_w = 11, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2177, .adv_w = 160, .box_w = 11, .box_h = 11, .ofs_x = -1, .ofs_y = 0}, + {.bitmap_index = 2238, .adv_w = 208, .box_w = 14, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2315, .adv_w = 144, .box_w = 11, .box_h = 11, .ofs_x = -1, .ofs_y = 0}, + {.bitmap_index = 2376, .adv_w = 144, .box_w = 11, .box_h = 11, .ofs_x = -1, .ofs_y = 0}, + {.bitmap_index = 2437, .adv_w = 128, .box_w = 8, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2481, .adv_w = 64, .box_w = 4, .box_h = 12, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 2505, .adv_w = 128, .box_w = 7, .box_h = 11, .ofs_x = 1, .ofs_y = 0}, + {.bitmap_index = 2544, .adv_w = 64, .box_w = 4, .box_h = 12, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 2568, .adv_w = 128, .box_w = 8, .box_h = 6, .ofs_x = 0, .ofs_y = 5}, + {.bitmap_index = 2592, .adv_w = 112, .box_w = 7, .box_h = 1, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 2596, .adv_w = 64, .box_w = 4, .box_h = 3, .ofs_x = 0, .ofs_y = 8}, + {.bitmap_index = 2602, .adv_w = 112, .box_w = 8, .box_h = 7, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2630, .adv_w = 112, .box_w = 7, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2669, .adv_w = 96, .box_w = 6, .box_h = 7, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2690, .adv_w = 128, .box_w = 8, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2734, .adv_w = 112, .box_w = 7, .box_h = 7, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2759, .adv_w = 64, .box_w = 6, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2792, .adv_w = 112, .box_w = 8, .box_h = 10, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 2832, .adv_w = 128, .box_w = 8, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2876, .adv_w = 64, .box_w = 4, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2898, .adv_w = 64, .box_w = 5, .box_h = 14, .ofs_x = -2, .ofs_y = -3}, + {.bitmap_index = 2933, .adv_w = 128, .box_w = 8, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2977, .adv_w = 64, .box_w = 4, .box_h = 11, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 2999, .adv_w = 192, .box_w = 12, .box_h = 7, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 3041, .adv_w = 128, .box_w = 8, .box_h = 7, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 3069, .adv_w = 112, .box_w = 7, .box_h = 7, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 3094, .adv_w = 128, .box_w = 8, .box_h = 10, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 3134, .adv_w = 112, .box_w = 8, .box_h = 10, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 3174, .adv_w = 96, .box_w = 6, .box_h = 7, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 3195, .adv_w = 96, .box_w = 6, .box_h = 7, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 3216, .adv_w = 80, .box_w = 5, .box_h = 10, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 3241, .adv_w = 128, .box_w = 8, .box_h = 7, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 3269, .adv_w = 112, .box_w = 8, .box_h = 7, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 3297, .adv_w = 160, .box_w = 11, .box_h = 7, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 3336, .adv_w = 112, .box_w = 8, .box_h = 7, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 3364, .adv_w = 112, .box_w = 8, .box_h = 10, .ofs_x = 0, .ofs_y = -3}, + {.bitmap_index = 3404, .adv_w = 96, .box_w = 6, .box_h = 7, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 3425, .adv_w = 64, .box_w = 4, .box_h = 12, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 3449, .adv_w = 128, .box_w = 2, .box_h = 11, .ofs_x = 3, .ofs_y = 0}, + {.bitmap_index = 3460, .adv_w = 64, .box_w = 4, .box_h = 12, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 3484, .adv_w = 128, .box_w = 8, .box_h = 3, .ofs_x = 0, .ofs_y = 2}, + {.bitmap_index = 3496, .adv_w = 128, .box_w = 8, .box_h = 10, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 3536, .adv_w = 112, .box_w = 7, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 3568, .adv_w = 96, .box_w = 6, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 3595, .adv_w = 112, .box_w = 7, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 3627, .adv_w = 128, .box_w = 8, .box_h = 10, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 3667, .adv_w = 80, .box_w = 4, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 3685, .adv_w = 80, .box_w = 5, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 3708, .adv_w = 128, .box_w = 8, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 3744, .adv_w = 128, .box_w = 8, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 3780, .adv_w = 64, .box_w = 4, .box_h = 6, .ofs_x = 0, .ofs_y = 3}, + {.bitmap_index = 3792, .adv_w = 112, .box_w = 7, .box_h = 13, .ofs_x = 0, .ofs_y = -4}, + {.bitmap_index = 3838, .adv_w = 112, .box_w = 7, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 3870, .adv_w = 112, .box_w = 7, .box_h = 13, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 3916, .adv_w = 112, .box_w = 7, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 3948, .adv_w = 128, .box_w = 8, .box_h = 10, .ofs_x = 0, .ofs_y = -1}, + {.bitmap_index = 3988, .adv_w = 64, .box_w = 4, .box_h = 13, .ofs_x = 0, .ofs_y = -4}, + {.bitmap_index = 4014, .adv_w = 80, .box_w = 5, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 4037, .adv_w = 112, .box_w = 7, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 4069, .adv_w = 128, .box_w = 8, .box_h = 11, .ofs_x = 0, .ofs_y = -2}, + {.bitmap_index = 4113, .adv_w = 112, .box_w = 7, .box_h = 13, .ofs_x = 0, .ofs_y = -4}, + {.bitmap_index = 4159, .adv_w = 112, .box_w = 7, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 4191, .adv_w = 112, .box_w = 7, .box_h = 13, .ofs_x = 0, .ofs_y = -4}, + {.bitmap_index = 4237, .adv_w = 112, .box_w = 7, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 4269, .adv_w = 128, .box_w = 8, .box_h = 13, .ofs_x = 0, .ofs_y = -4}, + {.bitmap_index = 4321, .adv_w = 112, .box_w = 7, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 4353, .adv_w = 160, .box_w = 10, .box_h = 9, .ofs_x = 0, .ofs_y = 0}, + {.bitmap_index = 4398, .adv_w = 128, .box_w = 8, .box_h = 9, .ofs_x = 0, .ofs_y = 0} +}; + +/*--------------------- + * CHARACTER MAPPING + *--------------------*/ + + + +/*Collect the unicode lists and glyph_id offsets*/ +static const lv_font_fmt_txt_cmap_t cmaps[] = +{ + { + .range_start = 32, .range_length = 95, .glyph_id_start = 1, + .unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY + }, + { + .range_start = 1488, .range_length = 27, .glyph_id_start = 96, + .unicode_list = NULL, .glyph_id_ofs_list = NULL, .list_length = 0, .type = LV_FONT_FMT_TXT_CMAP_FORMAT0_TINY + } +}; + +/*----------------- + * KERNING + *----------------*/ + + +/*Pair left and right glyphs for kerning*/ +static const uint8_t kern_pair_glyph_ids[] = +{ + 13, 18, + 14, 34, + 14, 53, + 14, 55, + 14, 56, + 14, 58, + 15, 18, + 17, 18, + 17, 21, + 17, 24, + 18, 13, + 18, 15, + 18, 17, + 18, 18, + 18, 19, + 18, 20, + 18, 21, + 18, 22, + 18, 23, + 18, 24, + 18, 25, + 18, 26, + 19, 18, + 19, 21, + 19, 24, + 20, 18, + 20, 21, + 20, 24, + 21, 18, + 21, 21, + 21, 24, + 22, 18, + 22, 21, + 22, 24, + 23, 18, + 23, 21, + 23, 24, + 24, 13, + 24, 15, + 24, 18, + 24, 19, + 24, 20, + 24, 21, + 24, 22, + 24, 23, + 24, 24, + 24, 25, + 24, 27, + 24, 28, + 25, 18, + 25, 21, + 25, 24, + 26, 18, + 26, 24 +}; + +/* Kerning between the respective left and right glyphs + * 4.4 format which needs to scaled with `kern_scale`*/ +static const int8_t kern_pair_values[] = +{ + -7, -1, -16, -12, -9, -19, -9, -11, + 1, -2, -5, -5, -11, -7, 0, -6, + -12, -6, -11, -18, -7, -5, -8, 1, + -3, -10, 0, -6, -7, 3, -10, -13, + 1, -8, -8, 2, -4, -15, -15, -8, + -7, -7, -16, -8, -8, -4, -8, -16, + -16, -9, 2, -5, -10, -2 +}; + +/*Collect the kern pair's data in one place*/ +static const lv_font_fmt_txt_kern_pair_t kern_pairs = +{ + .glyph_ids = kern_pair_glyph_ids, + .values = kern_pair_values, + .pair_cnt = 54, + .glyph_ids_size = 0 +}; + +/*-------------------- + * ALL CUSTOM DATA + *--------------------*/ + +/*Store all the custom data of the font*/ +static lv_font_fmt_txt_dsc_t font_dsc = { + .glyph_bitmap = gylph_bitmap, + .glyph_dsc = glyph_dsc, + .cmaps = cmaps, + .kern_dsc = &kern_pairs, + .kern_scale = 16, + .cmap_num = 2, + .bpp = 4, + .kern_classes = 0, + .bitmap_format = 0 +}; + + +/*----------------- + * PUBLIC FONT + *----------------*/ + +/*Initialize a public general font descriptor*/ +lv_font_t lv_font_heb_16 = { + .get_glyph_dsc = lv_font_get_glyph_dsc_fmt_txt, /*Function pointer to get glyph's data*/ + .get_glyph_bitmap = lv_font_get_bitmap_fmt_txt, /*Function pointer to get glyph's bitmap*/ + .line_height = 17, /*The maximum line height required by the font*/ + .base_line = 4, /*Baseline measured from the bottom of the line*/ + .dsc = &font_dsc /*The custom font data. Will be accessed by `get_glyph_bitmap/dsc` */ +}; + +#endif /*#if LV_FONT_HEB_16*/ + From c6b7cf130bebd205b0d355622bb8755d541e3d85 Mon Sep 17 00:00:00 2001 From: Amir Gonnen Date: Fri, 18 Oct 2019 02:13:41 +0300 Subject: [PATCH 25/51] Support text wrap for bidi text TODO: conditional LV_USE_BIDI, allocate global buffer once, pass dir as parameter to lv_draw_label --- src/lv_draw/lv_draw_label.c | 17 +++++++++++------ src/lv_misc/lv_bidi.c | 20 +++++++++----------- src/lv_misc/lv_bidi.h | 2 ++ src/lv_objx/lv_btnm.c | 19 ------------------- src/lv_objx/lv_label.c | 18 +----------------- src/lv_objx/lv_table.c | 5 ----- 6 files changed, 23 insertions(+), 58 deletions(-) diff --git a/src/lv_draw/lv_draw_label.c b/src/lv_draw/lv_draw_label.c index 23c660396..c2dc52ebe 100644 --- a/src/lv_draw/lv_draw_label.c +++ b/src/lv_draw/lv_draw_label.c @@ -8,6 +8,7 @@ *********************/ #include "lv_draw_label.h" #include "../lv_misc/lv_math.h" +#include "../lv_misc/lv_bidi.h" /********************* * DEFINES @@ -162,12 +163,16 @@ void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_st } /*Write all letter of a line*/ cmd_state = CMD_STATE_WAIT; - i = line_start; + i = 0; uint32_t letter; uint32_t letter_next; - while(i < line_end) { - letter = lv_txt_encoded_next(txt, &i); - letter_next = lv_txt_encoded_next(&txt[i], NULL); + while(i < line_end - line_start) { + // TODO handle bidi conditionally on ifdef + static char bidi_txt[1000]; // TODO: allocate dynamically once (gloablly?), according to max label size + lv_bidi_process_paragraph(txt + line_start, bidi_txt, line_end - line_start, LV_BIDI_DIR_RTL /* lv_obj_get_base_dir(label) */ ); // TODO: pass base dir as paramter + + letter = lv_txt_encoded_next(bidi_txt, &i); + letter_next = lv_txt_encoded_next(&bidi_txt[i], NULL); /*Handle the re-color command*/ if((flag & LV_TXT_FLAG_RECOLOR) != 0) { @@ -190,7 +195,7 @@ void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_st /*Get the parameter*/ if(i - par_start == LABEL_RECOLOR_PAR_LENGTH + 1) { char buf[LABEL_RECOLOR_PAR_LENGTH + 1]; - memcpy(buf, &txt[par_start], LABEL_RECOLOR_PAR_LENGTH); + memcpy(buf, &bidi_txt[par_start], LABEL_RECOLOR_PAR_LENGTH); buf[LABEL_RECOLOR_PAR_LENGTH] = '\0'; int r, g, b; r = (hex_char_to_num(buf[0]) << 4) + hex_char_to_num(buf[1]); @@ -213,7 +218,7 @@ void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_st letter_w = lv_font_get_glyph_width(font, letter, letter_next); if(sel_start != 0xFFFF && sel_end != 0xFFFF) { - int char_ind = lv_encoded_get_char_id(txt, i); + int char_ind = lv_encoded_get_char_id(bidi_txt, i); /*Do not draw the rectangle on the character at `sel_start`.*/ if(char_ind > sel_start && char_ind <= sel_end) { lv_area_t sel_coords; diff --git a/src/lv_misc/lv_bidi.c b/src/lv_misc/lv_bidi.c index e9929bc67..7f829354b 100644 --- a/src/lv_misc/lv_bidi.c +++ b/src/lv_misc/lv_bidi.c @@ -23,9 +23,7 @@ /********************** * STATIC PROTOTYPES **********************/ -static void process_paragraph(const char * str_in, char * str_out, uint32_t len, lv_bidi_dir_t base_dir); -static uint32_t get_next_paragraph(const char * txt); -static lv_bidi_dir_t get_next_run(const char * txt, lv_bidi_dir_t base_dir, uint32_t * len); +static lv_bidi_dir_t get_next_run(const char * txt, lv_bidi_dir_t base_dir, uint32_t max_len, 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); @@ -55,8 +53,8 @@ void lv_bidi_process(const char * str_in, char * str_out, lv_bidi_dir_t base_dir } while(str_in[par_start] != '\0') { - par_len = get_next_paragraph(&str_in[par_start]); - process_paragraph(&str_in[par_start], &str_out[par_start], par_len, base_dir); + par_len = lv_bidi_get_next_paragraph(&str_in[par_start]); + lv_bidi_process_paragraph(&str_in[par_start], &str_out[par_start], par_len, base_dir); par_start += par_len; while(str_in[par_start] == '\n' || str_in[par_start] == '\r') { @@ -134,7 +132,7 @@ bool lv_bidi_letter_is_neutral(uint32_t letter) * STATIC FUNCTIONS **********************/ -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) { uint32_t run_len = 0; lv_bidi_dir_t run_dir; @@ -168,7 +166,7 @@ static void process_paragraph(const char * str_in, char * str_out, uint32_t len, /*Get and process the runs*/ while(rd < len) { - run_dir = get_next_run(&str_in[rd], base_dir, &run_len); + run_dir = get_next_run(&str_in[rd], base_dir, len - rd, &run_len); if(base_dir == LV_BIDI_DIR_LTR) { if(run_dir == LV_BIDI_DIR_LTR) memcpy(&str_out[wr], &str_in[rd], run_len); @@ -184,7 +182,7 @@ static void process_paragraph(const char * str_in, char * str_out, uint32_t len, } } -static uint32_t get_next_paragraph(const char * txt) +uint32_t lv_bidi_get_next_paragraph(const char * txt) { uint32_t i = 0; @@ -197,7 +195,7 @@ static uint32_t get_next_paragraph(const char * txt) return i; } -static lv_bidi_dir_t get_next_run(const char * txt, lv_bidi_dir_t base_dir, uint32_t * len) +static lv_bidi_dir_t get_next_run(const char * txt, lv_bidi_dir_t base_dir, uint32_t max_len, uint32_t * len) { uint32_t i = 0; uint32_t letter; @@ -209,7 +207,7 @@ static lv_bidi_dir_t get_next_run(const char * txt, lv_bidi_dir_t base_dir, uint while(dir == LV_BIDI_DIR_NEUTRAL || dir == LV_BIDI_DIR_WEAK) { letter = lv_txt_encoded_next(txt, &i); dir = lv_bidi_get_letter_dir(letter); - if(txt[i] == '\0' || txt[i] == '\n' || txt[i] == '\r') { + if(i >= max_len || txt[i] == '\0' || txt[i] == '\n' || txt[i] == '\r') { *len = i; return base_dir; } @@ -222,7 +220,7 @@ static lv_bidi_dir_t get_next_run(const char * txt, lv_bidi_dir_t base_dir, uint /*Find the next char which has different direction*/ 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); next_dir = lv_bidi_get_letter_dir(letter); diff --git a/src/lv_misc/lv_bidi.h b/src/lv_misc/lv_bidi.h index 233765ca2..9ce0fffa1 100644 --- a/src/lv_misc/lv_bidi.h +++ b/src/lv_misc/lv_bidi.h @@ -53,6 +53,8 @@ typedef uint8_t lv_bidi_dir_t; #if LV_USE_BIDI void lv_bidi_process(const char * str_in, char * str_out, lv_bidi_dir_t base_dir); +void lv_bidi_process_paragraph(const char * str_in, char * str_out, uint32_t len, lv_bidi_dir_t base_dir); +uint32_t lv_bidi_get_next_paragraph(const char * txt); lv_bidi_dir_t lv_bidi_detect_base_dir(const char * txt); lv_bidi_dir_t lv_bidi_get_letter_dir(uint32_t letter); bool lv_bidi_letter_is_weak(uint32_t letter); diff --git a/src/lv_objx/lv_btnm.c b/src/lv_objx/lv_btnm.c index c9f095ac4..729b745a2 100644 --- a/src/lv_objx/lv_btnm.c +++ b/src/lv_objx/lv_btnm.c @@ -671,11 +671,6 @@ static bool lv_btnm_design(lv_obj_t * btnm, const lv_area_t * mask, lv_design_mo lv_txt_flag_t txt_flag = LV_TXT_FLAG_NONE; if(ext->recolor) txt_flag = LV_TXT_FLAG_RECOLOR; -#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++) { /*Search the next valid text in the map*/ while(strcmp(ext->map_p[txt_i], "\n") == 0) { @@ -744,22 +739,8 @@ static bool lv_btnm_design(lv_obj_t * btnm, const lv_area_t * mask, lv_design_mo area_tmp.x2 = area_tmp.x1 + txt_size.x; area_tmp.y2 = area_tmp.y1 + txt_size.y; -#if LV_USE_BIDI == 0 lv_draw_label(&area_tmp, mask, btn_style, opa_scale, ext->map_p[txt_i], txt_flag, NULL, -1, -1, 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, mask, btn_style, opa_scale, bidi_buf, txt_flag, NULL, -1, -1, NULL); -#endif } - -#if LV_USE_BIDI - lv_mem_free(bidi_buf); -#endif } return true; diff --git a/src/lv_objx/lv_label.c b/src/lv_objx/lv_label.c index 4ce18f42f..4bb547ffe 100644 --- a/src/lv_objx/lv_label.c +++ b/src/lv_objx/lv_label.c @@ -205,12 +205,8 @@ void lv_label_set_text(lv_obj_t * label, const char * text) LV_ASSERT_MEM(ext->text); if(ext->text == NULL) return; -#if LV_USE_BIDI == 0 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*/ ext->static_txt = 0; } @@ -904,19 +900,7 @@ void lv_label_ins_text(lv_obj_t * label, uint32_t pos, const char * txt) pos = lv_txt_get_encoded_length(ext->text); } -#if LV_USE_BIDI - char * bidi_buf = lv_mem_alloc(ins_len) + 1; - LV_ASSERT_MEM(bidi_buf); - if(bidi_buf == NULL) return; - - lv_bidi_process(txt, bidi_buf, lv_obj_get_base_dir(label)); - lv_txt_ins(ext->text, pos, bidi_buf); - - lv_mem_free(bidi_buf); -#else lv_txt_ins(ext->text, pos, txt); -#endif - lv_label_refr_text(label); } diff --git a/src/lv_objx/lv_table.c b/src/lv_objx/lv_table.c index e1ca6a2d0..3a7ec3f56 100644 --- a/src/lv_objx/lv_table.c +++ b/src/lv_objx/lv_table.c @@ -163,12 +163,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*/ - -#if LV_USE_BIDI == 0 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; refr_size(table); From f7c2512c76ca3edebc5241465638e59c273e6f67 Mon Sep 17 00:00:00 2001 From: Amir Gonnen Date: Sun, 20 Oct 2019 02:16:57 +0300 Subject: [PATCH 26/51] Bidi fixes Add bidi_dir parameter to lv_draw_label Use draw buffer for bidi processing condition bidi code according to LV_USE_BIDI --- src/lv_draw/lv_draw_img.c | 6 +++--- src/lv_draw/lv_draw_label.c | 12 +++++++----- src/lv_draw/lv_draw_label.h | 3 ++- src/lv_misc/lv_bidi.c | 2 +- src/lv_objx/lv_btnm.c | 2 +- src/lv_objx/lv_calendar.c | 10 +++++----- src/lv_objx/lv_canvas.c | 2 +- src/lv_objx/lv_chart.c | 4 ++-- src/lv_objx/lv_ddlist.c | 4 ++-- src/lv_objx/lv_gauge.c | 2 +- src/lv_objx/lv_img.c | 2 +- src/lv_objx/lv_imgbtn.c | 2 +- src/lv_objx/lv_label.c | 6 +++--- src/lv_objx/lv_roller.c | 2 +- src/lv_objx/lv_ta.c | 2 +- src/lv_objx/lv_table.c | 9 ++++++--- 16 files changed, 38 insertions(+), 32 deletions(-) diff --git a/src/lv_draw/lv_draw_img.c b/src/lv_draw/lv_draw_img.c index eacaa2d23..dcaa444a8 100644 --- a/src/lv_draw/lv_draw_img.c +++ b/src/lv_draw/lv_draw_img.c @@ -51,7 +51,7 @@ void lv_draw_img(const lv_area_t * coords, const lv_area_t * mask, const void * if(src == NULL) { LV_LOG_WARN("Image draw: src is NULL"); lv_draw_rect(coords, mask, &lv_style_plain, LV_OPA_COVER); - lv_draw_label(coords, mask, &lv_style_plain, LV_OPA_COVER, "No\ndata", LV_TXT_FLAG_NONE, NULL, -1, -1, NULL); + lv_draw_label(coords, mask, &lv_style_plain, LV_OPA_COVER, "No\ndata", LV_TXT_FLAG_NONE, NULL, -1, -1, NULL, LV_BIDI_DIR_LTR); return; } @@ -61,7 +61,7 @@ void lv_draw_img(const lv_area_t * coords, const lv_area_t * mask, const void * if(res == LV_RES_INV) { LV_LOG_WARN("Image draw error"); lv_draw_rect(coords, mask, &lv_style_plain, LV_OPA_COVER); - lv_draw_label(coords, mask, &lv_style_plain, LV_OPA_COVER, "No\ndata", LV_TXT_FLAG_NONE, NULL, -1, -1, NULL); + lv_draw_label(coords, mask, &lv_style_plain, LV_OPA_COVER, "No\ndata", LV_TXT_FLAG_NONE, NULL, -1, -1, NULL, LV_BIDI_DIR_LTR); return; } } @@ -563,7 +563,7 @@ static lv_res_t lv_img_draw_core(const lv_area_t * coords, const lv_area_t * mas LV_LOG_WARN("Image draw error"); lv_draw_rect(coords, mask, &lv_style_plain, LV_OPA_COVER); lv_draw_label(coords, mask, &lv_style_plain, LV_OPA_COVER, cdsc->dec_dsc.error_msg, LV_TXT_FLAG_NONE, NULL, -1, - -1, NULL); + -1, NULL, LV_BIDI_DIR_LTR); } /* The decoder open could open the image and gave the entire uncompressed image. * Just draw it!*/ diff --git a/src/lv_draw/lv_draw_label.c b/src/lv_draw/lv_draw_label.c index c2dc52ebe..86b486002 100644 --- a/src/lv_draw/lv_draw_label.c +++ b/src/lv_draw/lv_draw_label.c @@ -57,7 +57,7 @@ static uint8_t hex_char_to_num(char hex); */ void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_style_t * style, lv_opa_t opa_scale, const char * txt, lv_txt_flag_t flag, lv_point_t * offset, uint16_t sel_start, uint16_t sel_end, - lv_draw_label_hint_t * hint) + lv_draw_label_hint_t * hint, lv_bidi_dir_t bidi_dir) { const lv_font_t * font = style->text.font; lv_coord_t w; @@ -167,10 +167,12 @@ void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_st uint32_t letter; uint32_t letter_next; while(i < line_end - line_start) { - // TODO handle bidi conditionally on ifdef - static char bidi_txt[1000]; // TODO: allocate dynamically once (gloablly?), according to max label size - lv_bidi_process_paragraph(txt + line_start, bidi_txt, line_end - line_start, LV_BIDI_DIR_RTL /* lv_obj_get_base_dir(label) */ ); // TODO: pass base dir as paramter - +#if LV_USE_BIDI + char *bidi_txt = lv_draw_get_buf(line_end - line_start + 1); + lv_bidi_process_paragraph(txt + line_start, bidi_txt, line_end - line_start, bidi_dir); +#else + const char *bidi_txt = txt + line_start; +#endif letter = lv_txt_encoded_next(bidi_txt, &i); letter_next = lv_txt_encoded_next(&bidi_txt[i], NULL); diff --git a/src/lv_draw/lv_draw_label.h b/src/lv_draw/lv_draw_label.h index 2328aa2b3..39ec60607 100644 --- a/src/lv_draw/lv_draw_label.h +++ b/src/lv_draw/lv_draw_label.h @@ -14,6 +14,7 @@ extern "C" { * INCLUDES *********************/ #include "lv_draw.h" +#include "../lv_misc/lv_bidi.h" /********************* * DEFINES @@ -58,7 +59,7 @@ typedef struct { */ 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, uint16_t sel_start, uint16_t sel_end, - lv_draw_label_hint_t * hint); + lv_draw_label_hint_t * hint, lv_bidi_dir_t bidi_dir); /********************** * MACROS diff --git a/src/lv_misc/lv_bidi.c b/src/lv_misc/lv_bidi.c index 7f829354b..ceae844a0 100644 --- a/src/lv_misc/lv_bidi.c +++ b/src/lv_misc/lv_bidi.c @@ -269,7 +269,7 @@ static void rtl_reverse(char * dest, const char * src, uint32_t len) /*Finish on non-weak char */ /*but treat number and currency related chars as weak*/ - if(lv_bidi_letter_is_weak(letter) == false && letter != '.' && letter != ',' && letter != '$') { + if(lv_bidi_letter_is_weak(letter) == false && letter != '.' && letter != ',' && letter != '$' && letter != '%') { lv_txt_encoded_next(src, &i); /*Rewind one letter*/ first_weak = i; break; diff --git a/src/lv_objx/lv_btnm.c b/src/lv_objx/lv_btnm.c index 729b745a2..9c2634c93 100644 --- a/src/lv_objx/lv_btnm.c +++ b/src/lv_objx/lv_btnm.c @@ -739,7 +739,7 @@ static bool lv_btnm_design(lv_obj_t * btnm, const lv_area_t * mask, lv_design_mo area_tmp.x2 = area_tmp.x1 + txt_size.x; area_tmp.y2 = area_tmp.y1 + txt_size.y; - lv_draw_label(&area_tmp, mask, btn_style, opa_scale, ext->map_p[txt_i], txt_flag, NULL, -1, -1, NULL); + lv_draw_label(&area_tmp, mask, btn_style, opa_scale, ext->map_p[txt_i], txt_flag, NULL, -1, -1, NULL, lv_obj_get_base_dir(btnm)); } } diff --git a/src/lv_objx/lv_calendar.c b/src/lv_objx/lv_calendar.c index e33eccf10..cbeca7c54 100644 --- a/src/lv_objx/lv_calendar.c +++ b/src/lv_objx/lv_calendar.c @@ -687,19 +687,19 @@ static void draw_header(lv_obj_t * calendar, const lv_area_t * mask) txt_buf[5] = '\0'; strcpy(&txt_buf[5], get_month_name(calendar, ext->showed_date.month)); header_area.y1 += ext->style_header->body.padding.top; - lv_draw_label(&header_area, mask, ext->style_header, opa_scale, txt_buf, LV_TXT_FLAG_CENTER, NULL, -1, -1, NULL); + lv_draw_label(&header_area, mask, ext->style_header, opa_scale, txt_buf, LV_TXT_FLAG_CENTER, NULL, -1, -1, NULL, lv_obj_get_base_dir(calendar)); /*Add the left arrow*/ const lv_style_t * arrow_style = ext->btn_pressing < 0 ? ext->style_header_pr : ext->style_header; header_area.x1 += ext->style_header->body.padding.left; - lv_draw_label(&header_area, mask, arrow_style, opa_scale, LV_SYMBOL_LEFT, LV_TXT_FLAG_NONE, NULL, -1, -1, NULL); + lv_draw_label(&header_area, mask, arrow_style, opa_scale, LV_SYMBOL_LEFT, LV_TXT_FLAG_NONE, NULL, -1, -1, NULL, lv_obj_get_base_dir(calendar)); /*Add the right arrow*/ arrow_style = ext->btn_pressing > 0 ? ext->style_header_pr : ext->style_header; header_area.x1 = header_area.x2 - ext->style_header->body.padding.right - lv_txt_get_width(LV_SYMBOL_RIGHT, strlen(LV_SYMBOL_RIGHT), arrow_style->text.font, arrow_style->text.line_space, LV_TXT_FLAG_NONE); - lv_draw_label(&header_area, mask, arrow_style, opa_scale, LV_SYMBOL_RIGHT, LV_TXT_FLAG_NONE, NULL, -1, -1, NULL); + lv_draw_label(&header_area, mask, arrow_style, opa_scale, LV_SYMBOL_RIGHT, LV_TXT_FLAG_NONE, NULL, -1, -1, NULL, lv_obj_get_base_dir(calendar)); } /** @@ -724,7 +724,7 @@ static void draw_day_names(lv_obj_t * calendar, const lv_area_t * mask) label_area.x1 = calendar->coords.x1 + (w * i) / 7 + l_pad; label_area.x2 = label_area.x1 + box_w - 1; lv_draw_label(&label_area, mask, ext->style_day_names, opa_scale, get_day_name(calendar, i), LV_TXT_FLAG_CENTER, - NULL, -1, -1, NULL); + NULL, -1, -1, NULL, lv_obj_get_base_dir(calendar)); } } @@ -853,7 +853,7 @@ static void draw_days(lv_obj_t * calendar, const lv_area_t * mask) /*Write the day's number*/ lv_utils_num_to_str(day_cnt, buf); - lv_draw_label(&label_area, mask, final_style, opa_scale, buf, LV_TXT_FLAG_CENTER, NULL, -1, -1, NULL); + lv_draw_label(&label_area, mask, final_style, opa_scale, buf, LV_TXT_FLAG_CENTER, NULL, -1, -1, NULL, lv_obj_get_base_dir(calendar)); /*Go to the next day*/ day_cnt++; diff --git a/src/lv_objx/lv_canvas.c b/src/lv_objx/lv_canvas.c index a39c11a31..8ba051b46 100644 --- a/src/lv_objx/lv_canvas.c +++ b/src/lv_objx/lv_canvas.c @@ -586,7 +586,7 @@ void lv_canvas_draw_text(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, lv_coord } lv_draw_label(&coords, &mask, style, LV_OPA_COVER, txt, flag, NULL, LV_LABEL_TEXT_SEL_OFF, LV_LABEL_TEXT_SEL_OFF, - NULL); + NULL, lv_obj_get_base_dir(canvas)); lv_refr_set_disp_refreshing(refr_ori); } diff --git a/src/lv_objx/lv_chart.c b/src/lv_objx/lv_chart.c index c326c8c6b..e82d00f7f 100644 --- a/src/lv_objx/lv_chart.c +++ b/src/lv_objx/lv_chart.c @@ -1379,7 +1379,7 @@ static void lv_chart_draw_y_ticks(lv_obj_t * chart, const lv_area_t * mask, uint a.x2 = p2.x + size.x + LV_CHART_AXIS_TO_LABEL_DISTANCE; } - lv_draw_label(&a, mask, style, opa_scale, buf, LV_TXT_FLAG_CENTER, NULL, -1, -1, NULL); + lv_draw_label(&a, mask, style, opa_scale, buf, LV_TXT_FLAG_CENTER, NULL, -1, -1, NULL, lv_obj_get_base_dir(chart)); } } @@ -1465,7 +1465,7 @@ static void lv_chart_draw_x_ticks(lv_obj_t * chart, const lv_area_t * mask) /* set the area at some distance of the major tick len under of the tick */ lv_area_t a = {(p2.x - size.x / 2), (p2.y + LV_CHART_AXIS_TO_LABEL_DISTANCE), (p2.x + size.x / 2), (p2.y + size.y + LV_CHART_AXIS_TO_LABEL_DISTANCE)}; - lv_draw_label(&a, mask, style, opa_scale, buf, LV_TXT_FLAG_CENTER, NULL, -1, -1, NULL); + lv_draw_label(&a, mask, style, opa_scale, buf, LV_TXT_FLAG_CENTER, NULL, -1, -1, NULL, lv_obj_get_base_dir(chart)); } } } diff --git a/src/lv_objx/lv_ddlist.c b/src/lv_objx/lv_ddlist.c index a6066729d..771902e26 100644 --- a/src/lv_objx/lv_ddlist.c +++ b/src/lv_objx/lv_ddlist.c @@ -609,7 +609,7 @@ static bool lv_ddlist_design(lv_obj_t * ddlist, const lv_area_t * mask, lv_desig new_style.text.opa = sel_style->text.opa; lv_txt_flag_t flag = lv_ddlist_get_txt_flag(ddlist); lv_draw_label(&ext->label->coords, &mask_sel, &new_style, opa_scale, lv_label_get_text(ext->label), - flag, NULL, -1, -1, NULL); + flag, NULL, -1, -1, NULL, lv_obj_get_base_dir(ddlist)); } } @@ -643,7 +643,7 @@ static bool lv_ddlist_design(lv_obj_t * ddlist, const lv_area_t * mask, lv_desig area_ok = lv_area_intersect(&mask_arrow, mask, &area_arrow); if(area_ok) { lv_draw_label(&area_arrow, &mask_arrow, &new_style, opa_scale, LV_SYMBOL_DOWN, LV_TXT_FLAG_NONE, - NULL, -1, -1, NULL); /*Use a down arrow in ddlist, you can replace it with your + NULL, -1, -1, NULL, lv_obj_get_base_dir(ddlist)); /*Use a down arrow in ddlist, you can replace it with your custom symbol*/ } } diff --git a/src/lv_objx/lv_gauge.c b/src/lv_objx/lv_gauge.c index 3ebb1cb7c..4a9b06e5b 100644 --- a/src/lv_objx/lv_gauge.c +++ b/src/lv_objx/lv_gauge.c @@ -390,7 +390,7 @@ static void lv_gauge_draw_scale(lv_obj_t * gauge, const lv_area_t * mask) label_cord.x2 = label_cord.x1 + label_size.x; label_cord.y2 = label_cord.y1 + label_size.y; - lv_draw_label(&label_cord, mask, style, opa_scale, scale_txt, LV_TXT_FLAG_NONE, NULL, -1, -1, NULL); + lv_draw_label(&label_cord, mask, style, opa_scale, scale_txt, LV_TXT_FLAG_NONE, NULL, -1, -1, NULL, lv_obj_get_base_dir(gauge)); } } /** diff --git a/src/lv_objx/lv_img.c b/src/lv_objx/lv_img.c index 302891ac3..30e994a13 100644 --- a/src/lv_objx/lv_img.c +++ b/src/lv_objx/lv_img.c @@ -384,7 +384,7 @@ static bool lv_img_design(lv_obj_t * img, const lv_area_t * mask, lv_design_mode lv_style_t style_mod; lv_style_copy(&style_mod, style); style_mod.text.color = style->image.color; - lv_draw_label(&coords, mask, &style_mod, opa_scale, ext->src, LV_TXT_FLAG_NONE, NULL, -1, -1, NULL); + lv_draw_label(&coords, mask, &style_mod, opa_scale, ext->src, LV_TXT_FLAG_NONE, NULL, -1, -1, NULL, lv_obj_get_base_dir(img)); } else { /*Trigger the error handler of image drawer*/ LV_LOG_WARN("lv_img_design: image source type is unknown"); diff --git a/src/lv_objx/lv_imgbtn.c b/src/lv_objx/lv_imgbtn.c index e1c4c0309..a17fe8b50 100644 --- a/src/lv_objx/lv_imgbtn.c +++ b/src/lv_objx/lv_imgbtn.c @@ -304,7 +304,7 @@ static bool lv_imgbtn_design(lv_obj_t * imgbtn, const lv_area_t * mask, lv_desig #if LV_IMGBTN_TILED == 0 const void * src = ext->img_src[state]; if(lv_img_src_get_type(src) == LV_IMG_SRC_SYMBOL) { - lv_draw_label(&imgbtn->coords, mask, style, opa_scale, src, LV_TXT_FLAG_NONE, NULL, LV_LABEL_TEXT_SEL_OFF, LV_LABEL_TEXT_SEL_OFF, NULL); + lv_draw_label(&imgbtn->coords, mask, style, opa_scale, src, LV_TXT_FLAG_NONE, NULL, LV_LABEL_TEXT_SEL_OFF, LV_LABEL_TEXT_SEL_OFF, NULL, lv_obj_get_base_dir(imgbtn)); } else { lv_draw_img(&imgbtn->coords, mask, src, style, opa_scale); } diff --git a/src/lv_objx/lv_label.c b/src/lv_objx/lv_label.c index 4bb547ffe..46cc451c4 100644 --- a/src/lv_objx/lv_label.c +++ b/src/lv_objx/lv_label.c @@ -1005,7 +1005,7 @@ static bool lv_label_design(lv_obj_t * label, const lv_area_t * mask, lv_design_ lv_draw_label_hint_t * hint = NULL; #endif lv_draw_label(&coords, mask, style, opa_scale, ext->text, flag, &ext->offset, - lv_label_get_text_sel_start(label), lv_label_get_text_sel_end(label), hint); + lv_label_get_text_sel_start(label), lv_label_get_text_sel_end(label), hint, lv_obj_get_base_dir(label)); if(ext->long_mode == LV_LABEL_LONG_SROLL_CIRC) { @@ -1022,7 +1022,7 @@ static bool lv_label_design(lv_obj_t * label, const lv_area_t * mask, lv_design_ ofs.y = ext->offset.y; lv_draw_label(&coords, mask, style, opa_scale, ext->text, flag, &ofs, - lv_label_get_text_sel_start(label), lv_label_get_text_sel_end(label), NULL); + lv_label_get_text_sel_start(label), lv_label_get_text_sel_end(label), NULL, lv_obj_get_base_dir(label)); } /*Draw the text again below the original to make an circular effect */ @@ -1030,7 +1030,7 @@ static bool lv_label_design(lv_obj_t * label, const lv_area_t * mask, lv_design_ ofs.x = ext->offset.x; ofs.y = ext->offset.y + size.y + lv_font_get_line_height(style->text.font); lv_draw_label(&coords, mask, style, opa_scale, ext->text, flag, &ofs, - lv_label_get_text_sel_start(label), lv_label_get_text_sel_end(label), NULL); + lv_label_get_text_sel_start(label), lv_label_get_text_sel_end(label), NULL, lv_obj_get_base_dir(label)); } } } diff --git a/src/lv_objx/lv_roller.c b/src/lv_objx/lv_roller.c index 75eb9cf74..62c949db5 100644 --- a/src/lv_objx/lv_roller.c +++ b/src/lv_objx/lv_roller.c @@ -397,7 +397,7 @@ static bool lv_roller_design(lv_obj_t * roller, const lv_area_t * mask, lv_desig new_style.text.color = sel_style->text.color; new_style.text.opa = sel_style->text.opa; lv_draw_label(&ext->ddlist.label->coords, &mask_sel, &new_style, opa_scale, - lv_label_get_text(ext->ddlist.label), txt_align, NULL, -1, -1, NULL); + lv_label_get_text(ext->ddlist.label), txt_align, NULL, -1, -1, NULL, lv_obj_get_base_dir(ext->ddlist.label)); } } diff --git a/src/lv_objx/lv_ta.c b/src/lv_objx/lv_ta.c index 77ea629d4..c8ffee521 100644 --- a/src/lv_objx/lv_ta.c +++ b/src/lv_objx/lv_ta.c @@ -1386,7 +1386,7 @@ static bool lv_ta_scrollable_design(lv_obj_t * scrl, const lv_area_t * mask, lv_ cur_area.x1 += cur_style.body.padding.left; cur_area.y1 += cur_style.body.padding.top; lv_draw_label(&cur_area, mask, &cur_style, opa_scale, letter_buf, LV_TXT_FLAG_NONE, 0, - LV_LABEL_TEXT_SEL_OFF, LV_LABEL_TEXT_SEL_OFF, NULL); + LV_LABEL_TEXT_SEL_OFF, LV_LABEL_TEXT_SEL_OFF, NULL, lv_obj_get_base_dir(ta)); } else if(ext->cursor.type == LV_CURSOR_OUTLINE) { cur_style.body.opa = LV_OPA_TRANSP; diff --git a/src/lv_objx/lv_table.c b/src/lv_objx/lv_table.c index 3a7ec3f56..ef49559aa 100644 --- a/src/lv_objx/lv_table.c +++ b/src/lv_objx/lv_table.c @@ -145,17 +145,20 @@ 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; lv_table_cell_format_t format; - lv_bidi_dir_t base_dir = lv_obj_get_base_dir(table); - /*Save the format byte*/ if(ext->cell_data[cell]) { format.format_byte = ext->cell_data[cell][0]; } /*Initialize the format byte*/ else { +#if LV_USE_BIDI + lv_bidi_dir_t base_dir = lv_obj_get_base_dir(table); if(base_dir == LV_BIDI_DIR_LTR) format.s.align = LV_LABEL_ALIGN_LEFT; else if(base_dir == LV_BIDI_DIR_RTL) format.s.align = LV_LABEL_ALIGN_RIGHT; else if(base_dir == LV_BIDI_DIR_AUTO) format.s.align = lv_bidi_detect_base_dir(txt); +#else + format.s.align = LV_LABEL_ALIGN_LEFT; +#endif format.s.right_merge = 0; format.s.type = 0; @@ -735,7 +738,7 @@ static bool lv_table_design(lv_obj_t * table, const lv_area_t * mask, lv_design_ label_mask_ok = lv_area_intersect(&label_mask, mask, &cell_area); if(label_mask_ok) { lv_draw_label(&txt_area, &label_mask, cell_style, opa_scale, ext->cell_data[cell] + 1, - txt_flags, NULL, -1, -1, NULL); + txt_flags, NULL, -1, -1, NULL, lv_obj_get_base_dir(table)); } /*Draw lines after '\n's*/ lv_point_t p1; From 0634b11578fd9f0c4ca31fde6bde31c859d83b3c Mon Sep 17 00:00:00 2001 From: Amir Gonnen Date: Tue, 22 Oct 2019 01:36:37 +0300 Subject: [PATCH 27/51] Add minus (hyphen) as neutral letter --- src/lv_misc/lv_bidi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lv_misc/lv_bidi.c b/src/lv_misc/lv_bidi.c index ceae844a0..61c12e5b2 100644 --- a/src/lv_misc/lv_bidi.c +++ b/src/lv_misc/lv_bidi.c @@ -119,7 +119,7 @@ bool lv_bidi_letter_is_rtl(uint32_t letter) bool lv_bidi_letter_is_neutral(uint32_t letter) { uint16_t i; - static const char neutrals[] = " \t\n\r.,:;'\"`!?%/\\=()[]{}<>@#&$|"; + static const char neutrals[] = " \t\n\r.,:;'\"`!?%/\\-=()[]{}<>@#&$|"; for(i = 0; neutrals[i] != '\0'; i++) { if(letter == (uint32_t)neutrals[i]) return true; } From 4158334a400563217cca99ed29131962b9fc8c18 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Thu, 24 Oct 2019 07:15:00 +0200 Subject: [PATCH 28/51] bidi: ahndle LV_BIDI_DIR_AUTO in lv_bidi_process_paragraph --- src/lv_misc/lv_bidi.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/lv_misc/lv_bidi.c b/src/lv_misc/lv_bidi.c index 61c12e5b2..933773d93 100644 --- a/src/lv_misc/lv_bidi.c +++ b/src/lv_misc/lv_bidi.c @@ -138,6 +138,8 @@ void lv_bidi_process_paragraph(const char * str_in, char * str_out, uint32_t len lv_bidi_dir_t run_dir; uint32_t rd = 0; uint32_t wr; + + if(base_dir == LV_BIDI_DIR_AUTO) base_dir = lv_bidi_detect_base_dir(str_in); if(base_dir == LV_BIDI_DIR_RTL) wr = len; else wr = 0; From 57a8ee8e325e861be920d0860bedd3e388f0b027 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Fri, 25 Oct 2019 06:15:11 +0200 Subject: [PATCH 29/51] bidi: add bracket algorithm --- src/lv_misc/lv_bidi.c | 110 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 104 insertions(+), 6 deletions(-) diff --git a/src/lv_misc/lv_bidi.c b/src/lv_misc/lv_bidi.c index e9929bc67..4c365d660 100644 --- a/src/lv_misc/lv_bidi.c +++ b/src/lv_misc/lv_bidi.c @@ -15,10 +15,16 @@ /********************* * DEFINES *********************/ +#define LV_BIDI_BRACKLET_DEPTH 4 /********************** * TYPEDEFS **********************/ +typedef struct +{ + uint32_t bracklet_pos; + lv_bidi_dir_t dir; +}bracket_stack_t; /********************** * STATIC PROTOTYPES @@ -28,10 +34,15 @@ static uint32_t get_next_paragraph(const char * txt); 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 lv_bidi_dir_t bracket_process(const uint8_t * txt, uint32_t next_pos, uint32_t len, uint32_t letter, lv_bidi_dir_t base_dir); /********************** * 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 @@ -43,6 +54,7 @@ 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) { + br_stack_p = 0; if(base_dir == LV_BIDI_DIR_AUTO) base_dir = lv_bidi_detect_base_dir(str_in); @@ -151,6 +163,8 @@ static void process_paragraph(const char * str_in, char * str_out, uint32_t len, while(rd < len) { uint32_t letter = lv_txt_encoded_next(str_in, &rd); dir = lv_bidi_get_letter_dir(letter); + if(dir == LV_BIDI_DIR_NEUTRAL) dir = bracket_process(str_in, rd, len, letter, base_dir); + if(dir != LV_BIDI_DIR_NEUTRAL && dir != LV_BIDI_DIR_WEAK) break; } @@ -204,11 +218,15 @@ static lv_bidi_dir_t get_next_run(const char * txt, lv_bidi_dir_t base_dir, uint letter = lv_txt_encoded_next(txt, NULL); lv_bidi_dir_t dir = lv_bidi_get_letter_dir(letter); + if(dir == LV_BIDI_DIR_NEUTRAL) dir = bracket_process(txt, 0, len, letter, base_dir); + /*Find the first strong char. Skip the neutrals*/ while(dir == LV_BIDI_DIR_NEUTRAL || dir == LV_BIDI_DIR_WEAK) { letter = lv_txt_encoded_next(txt, &i); dir = lv_bidi_get_letter_dir(letter); + if(dir == LV_BIDI_DIR_NEUTRAL) dir = bracket_process(txt, i, len, letter, base_dir); + if(txt[i] == '\0' || txt[i] == '\n' || txt[i] == '\r') { *len = i; return base_dir; @@ -225,6 +243,7 @@ static lv_bidi_dir_t get_next_run(const char * txt, lv_bidi_dir_t base_dir, uint while(txt[i] != '\0'&& txt[i] != '\n' && txt[i] != '\r') { letter = lv_txt_encoded_next(txt, &i); next_dir = lv_bidi_get_letter_dir(letter); + if(dir == LV_BIDI_DIR_NEUTRAL) dir = bracket_process(txt, i, len, letter, base_dir); /*New dir found?*/ if((next_dir == LV_BIDI_DIR_RTL || next_dir == LV_BIDI_DIR_LTR) && next_dir != run_dir) { @@ -303,19 +322,98 @@ static void rtl_reverse(char * dest, const char * src, uint32_t len) static uint32_t char_change_to_pair(uint32_t letter) { - static uint8_t left[] = {"<({["}; - static uint8_t right[] = {">)}]"}; uint8_t i; - for(i = 0; left[i] != '\0'; i++) { - if(letter == left[i]) return right[i]; + for(i = 0; bracket_left[i] != '\0'; i++) { + if(letter == bracket_left[i]) return bracket_right[i]; } - for(i = 0; right[i] != '\0'; i++) { - if(letter == right[i]) return left[i]; + for(i = 0; bracket_right[i] != '\0'; i++) { + if(letter == bracket_right[i]) return bracket_left[i]; } return letter; } +static lv_bidi_dir_t bracket_process(const uint8_t * txt, uint32_t next_pos, uint32_t len, uint32_t letter, lv_bidi_dir_t base_dir) +{ + if(br_stack_p >= LV_BIDI_BRACKLET_DEPTH) return LV_BIDI_DIR_NEUTRAL; + + 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); + 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) 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); + 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); + 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) break; + + br_stack[br_stack_p].bracklet_pos = i; + br_stack[br_stack_p].dir = bracket_dir; + + br_stack_p++; + return bracket_dir; + } else { + /*Is the letter a closing bracket of the last opening?*/ + if(letter == bracket_right[br_stack[br_stack_p].bracklet_pos]) { + bracket_dir = br_stack[br_stack_p].dir; + br_stack_p--; + return bracket_dir; + } + } + + return LV_BIDI_DIR_NEUTRAL; +} + + #endif /*LV_USE_BIDI*/ From 081b2c2271ae4c42d051f2c670a4e92aaebb8546 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Sun, 27 Oct 2019 10:21:37 +0100 Subject: [PATCH 30/51] bidi: barcket handle fixes --- src/lv_misc/lv_bidi.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/lv_misc/lv_bidi.c b/src/lv_misc/lv_bidi.c index 4c365d660..c00485dc6 100644 --- a/src/lv_misc/lv_bidi.c +++ b/src/lv_misc/lv_bidi.c @@ -34,7 +34,7 @@ static uint32_t get_next_paragraph(const char * txt); 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 lv_bidi_dir_t bracket_process(const uint8_t * txt, uint32_t next_pos, uint32_t len, uint32_t letter, lv_bidi_dir_t base_dir); +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 VARIABLES @@ -54,8 +54,6 @@ static uint8_t br_stack_p; void lv_bidi_process(const char * str_in, char * str_out, lv_bidi_dir_t base_dir) { - br_stack_p = 0; - if(base_dir == LV_BIDI_DIR_AUTO) base_dir = lv_bidi_detect_base_dir(str_in); uint32_t par_start = 0; @@ -159,6 +157,9 @@ static void process_paragraph(const char * str_in, char * str_out, uint32_t len, lv_bidi_dir_t dir = base_dir; + /*Empty the bracket stack*/ + br_stack_p = 0; + /*Process neutral chars in the beginning*/ while(rd < len) { uint32_t letter = lv_txt_encoded_next(str_in, &rd); @@ -218,14 +219,14 @@ static lv_bidi_dir_t get_next_run(const char * txt, lv_bidi_dir_t base_dir, uint letter = lv_txt_encoded_next(txt, NULL); lv_bidi_dir_t dir = lv_bidi_get_letter_dir(letter); - if(dir == LV_BIDI_DIR_NEUTRAL) dir = bracket_process(txt, 0, len, letter, base_dir); + if(dir == LV_BIDI_DIR_NEUTRAL) dir = bracket_process(txt, 0, *len, letter, base_dir); /*Find the first strong char. Skip the neutrals*/ while(dir == LV_BIDI_DIR_NEUTRAL || dir == LV_BIDI_DIR_WEAK) { letter = lv_txt_encoded_next(txt, &i); dir = lv_bidi_get_letter_dir(letter); - if(dir == LV_BIDI_DIR_NEUTRAL) dir = bracket_process(txt, i, len, letter, base_dir); + if(dir == LV_BIDI_DIR_NEUTRAL) dir = bracket_process(txt, i, *len, letter, base_dir); if(txt[i] == '\0' || txt[i] == '\n' || txt[i] == '\r') { *len = i; @@ -243,7 +244,7 @@ static lv_bidi_dir_t get_next_run(const char * txt, lv_bidi_dir_t base_dir, uint while(txt[i] != '\0'&& txt[i] != '\n' && txt[i] != '\r') { letter = lv_txt_encoded_next(txt, &i); next_dir = lv_bidi_get_letter_dir(letter); - if(dir == LV_BIDI_DIR_NEUTRAL) dir = bracket_process(txt, i, len, letter, base_dir); + if(dir == LV_BIDI_DIR_NEUTRAL) dir = bracket_process(txt, i, *len, letter, base_dir); /*New dir found?*/ if((next_dir == LV_BIDI_DIR_RTL || next_dir == LV_BIDI_DIR_LTR) && next_dir != run_dir) { @@ -335,7 +336,7 @@ static uint32_t char_change_to_pair(uint32_t letter) return letter; } -static lv_bidi_dir_t bracket_process(const uint8_t * txt, uint32_t next_pos, uint32_t len, uint32_t letter, lv_bidi_dir_t base_dir) +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) { if(br_stack_p >= LV_BIDI_BRACKLET_DEPTH) return LV_BIDI_DIR_NEUTRAL; @@ -396,7 +397,7 @@ static lv_bidi_dir_t bracket_process(const uint8_t * txt, uint32_t next_pos, uin /*The letter was an opening bracket*/ if(bracket_left[i] != '\0') { - if(bracket_dir == LV_BIDI_DIR_NEUTRAL) break; + if(bracket_dir == LV_BIDI_DIR_NEUTRAL) return bracket_dir; br_stack[br_stack_p].bracklet_pos = i; br_stack[br_stack_p].dir = bracket_dir; From 98a4d9b06291e14ec83b41ba85bcb6cdd61e4ba5 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Sun, 27 Oct 2019 10:44:00 +0100 Subject: [PATCH 31/51] bidi: barcket process fixes --- src/lv_misc/lv_bidi.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/lv_misc/lv_bidi.c b/src/lv_misc/lv_bidi.c index ea67499dc..13ecdc17d 100644 --- a/src/lv_misc/lv_bidi.c +++ b/src/lv_misc/lv_bidi.c @@ -219,14 +219,14 @@ static lv_bidi_dir_t get_next_run(const char * txt, lv_bidi_dir_t base_dir, uint letter = lv_txt_encoded_next(txt, NULL); lv_bidi_dir_t dir = lv_bidi_get_letter_dir(letter); - if(dir == LV_BIDI_DIR_NEUTRAL) dir = bracket_process(txt, 0, *len, letter, base_dir); + if(dir == LV_BIDI_DIR_NEUTRAL) dir = bracket_process(txt, 0, max_len, letter, base_dir); /*Find the first strong char. Skip the neutrals*/ while(dir == LV_BIDI_DIR_NEUTRAL || dir == LV_BIDI_DIR_WEAK) { letter = lv_txt_encoded_next(txt, &i); dir = lv_bidi_get_letter_dir(letter); - if(dir == LV_BIDI_DIR_NEUTRAL) dir = bracket_process(txt, i, *len, letter, base_dir); + 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; @@ -244,7 +244,7 @@ static lv_bidi_dir_t get_next_run(const char * txt, lv_bidi_dir_t base_dir, uint while(i_prev < max_len && txt[i] != '\0' && txt[i] != '\n' && txt[i] != '\r') { letter = lv_txt_encoded_next(txt, &i); next_dir = lv_bidi_get_letter_dir(letter); - if(dir == LV_BIDI_DIR_NEUTRAL) dir = bracket_process(txt, i, *len, letter, base_dir); + if(next_dir == LV_BIDI_DIR_NEUTRAL) next_dir = bracket_process(txt, i, max_len, letter, base_dir); /*New dir found?*/ if((next_dir == LV_BIDI_DIR_RTL || next_dir == LV_BIDI_DIR_LTR) && next_dir != run_dir) { @@ -356,7 +356,7 @@ static lv_bidi_dir_t bracket_process(const char * txt, uint32_t next_pos, uint32 break; } else { /*Save the dir*/ - lv_bidi_dir_t letter_dir = lv_bidi_get_letter_dir(letter); + lv_bidi_dir_t letter_dir = lv_bidi_get_letter_dir(letter_next); if(letter_dir == base_dir) { bracket_dir = base_dir; } @@ -364,18 +364,17 @@ static lv_bidi_dir_t bracket_process(const char * txt, uint32_t next_pos, uint32 } /*There were no matching closing bracket*/ - if(txt_i >= len) return LV_BIDI_DIR_NEUTRAL; + 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) break; + 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); - 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); + 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; @@ -404,10 +403,10 @@ static lv_bidi_dir_t bracket_process(const char * txt, uint32_t next_pos, uint32 br_stack_p++; return bracket_dir; - } else { + } 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].bracklet_pos]) { - bracket_dir = br_stack[br_stack_p].dir; + 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; } From dd68877aae8cd70f3b4a26118770d1735e21e1e0 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Mon, 28 Oct 2019 05:47:31 +0100 Subject: [PATCH 32/51] bidi bracket handling fixies --- src/lv_misc/lv_bidi.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/lv_misc/lv_bidi.c b/src/lv_misc/lv_bidi.c index 13ecdc17d..634e1f896 100644 --- a/src/lv_misc/lv_bidi.c +++ b/src/lv_misc/lv_bidi.c @@ -338,8 +338,6 @@ 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) { - if(br_stack_p >= LV_BIDI_BRACKLET_DEPTH) return LV_BIDI_DIR_NEUTRAL; - lv_bidi_dir_t bracket_dir = LV_BIDI_DIR_NEUTRAL; uint8_t i; @@ -396,7 +394,7 @@ static lv_bidi_dir_t bracket_process(const char * txt, uint32_t next_pos, uint32 /*The letter was an opening bracket*/ if(bracket_left[i] != '\0') { - if(bracket_dir == LV_BIDI_DIR_NEUTRAL) return bracket_dir; + 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; From 9472d0d0c7e601e92b6ded005605004e2dfb35c4 Mon Sep 17 00:00:00 2001 From: Jan Van Winkel Date: Sun, 3 Nov 2019 14:43:26 +0100 Subject: [PATCH 33/51] Added missing lv_indev.h includes (#1251) --- lvgl.h | 1 + src/lv_objx/lv_slider.c | 1 + src/lv_objx/lv_sw.c | 1 + 3 files changed, 3 insertions(+) diff --git a/lvgl.h b/lvgl.h index b6e29b61b..8344953f8 100644 --- a/lvgl.h +++ b/lvgl.h @@ -25,6 +25,7 @@ extern "C" { #include "src/lv_core/lv_obj.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_disp.h" diff --git a/src/lv_objx/lv_slider.c b/src/lv_objx/lv_slider.c index a7fb4333b..a1624e37f 100644 --- a/src/lv_objx/lv_slider.c +++ b/src/lv_objx/lv_slider.c @@ -11,6 +11,7 @@ #if LV_USE_SLIDER != 0 #include "../lv_core/lv_group.h" +#include "../lv_core/lv_indev.h" #include "../lv_draw/lv_draw.h" #include "../lv_themes/lv_theme.h" #include "../lv_misc/lv_math.h" diff --git a/src/lv_objx/lv_sw.c b/src/lv_objx/lv_sw.c index 80854b0a0..c710dbc65 100644 --- a/src/lv_objx/lv_sw.c +++ b/src/lv_objx/lv_sw.c @@ -17,6 +17,7 @@ #include "../lv_themes/lv_theme.h" #include "../lv_misc/lv_math.h" +#include "../lv_core/lv_indev.h" /********************* * DEFINES From f6829a17b22f0f89917197957e120f951b2585a4 Mon Sep 17 00:00:00 2001 From: Amir Gonnen Date: Mon, 4 Nov 2019 01:31:54 +0200 Subject: [PATCH 34/51] WIP: Bidi pos_conv --- src/lv_draw/lv_draw_label.c | 2 +- src/lv_misc/lv_bidi.c | 152 +++++++++++++++++++++++++++--------- src/lv_misc/lv_bidi.h | 2 +- 3 files changed, 116 insertions(+), 40 deletions(-) diff --git a/src/lv_draw/lv_draw_label.c b/src/lv_draw/lv_draw_label.c index 86b486002..5bd0592c5 100644 --- a/src/lv_draw/lv_draw_label.c +++ b/src/lv_draw/lv_draw_label.c @@ -169,7 +169,7 @@ void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_st while(i < line_end - line_start) { #if LV_USE_BIDI char *bidi_txt = lv_draw_get_buf(line_end - line_start + 1); - lv_bidi_process_paragraph(txt + line_start, bidi_txt, line_end - line_start, bidi_dir); + 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 diff --git a/src/lv_misc/lv_bidi.c b/src/lv_misc/lv_bidi.c index 634e1f896..1d962c64a 100644 --- a/src/lv_misc/lv_bidi.c +++ b/src/lv_misc/lv_bidi.c @@ -29,10 +29,11 @@ typedef struct /********************** * STATIC PROTOTYPES **********************/ -static lv_bidi_dir_t get_next_run(const char * txt, lv_bidi_dir_t base_dir, uint32_t max_len, uint32_t * len); -static void rtl_reverse(char * dest, const char * src, uint32_t len); +static lv_bidi_dir_t get_next_run(const char * txt, lv_bidi_dir_t base_dir, uint32_t max_len, uint32_t * len, uint16_t * pos_conv_len); +static void rtl_reverse(char * dest, const char * src, uint32_t len, uint16_t *pos_conv_out, uint16_t pos_conv_rd_base, uint16_t pos_conv_len); static uint32_t char_change_to_pair(uint32_t letter); static lv_bidi_dir_t bracket_process(const char * txt, uint32_t next_pos, uint32_t len, uint32_t letter, lv_bidi_dir_t base_dir); +static void fill_pos_conv(uint16_t * out, uint16_t len, uint16_t index); /********************** * STATIC VARIABLES @@ -64,7 +65,7 @@ void lv_bidi_process(const char * str_in, char * str_out, lv_bidi_dir_t base_dir while(str_in[par_start] != '\0') { par_len = lv_bidi_get_next_paragraph(&str_in[par_start]); - lv_bidi_process_paragraph(&str_in[par_start], &str_out[par_start], par_len, base_dir); + lv_bidi_process_paragraph(&str_in[par_start], &str_out[par_start], par_len, base_dir, NULL, 0); par_start += par_len; while(str_in[par_start] == '\n' || str_in[par_start] == '\r') { @@ -137,23 +138,27 @@ bool lv_bidi_letter_is_neutral(uint32_t letter) return false; } - -/********************** - * STATIC FUNCTIONS - **********************/ - -void lv_bidi_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; lv_bidi_dir_t run_dir; uint32_t rd = 0; uint32_t wr; + uint16_t pos_conv_run_len = 0; + uint16_t pos_conv_rd = 0; + uint16_t pos_conv_wr; if(base_dir == LV_BIDI_DIR_AUTO) base_dir = lv_bidi_detect_base_dir(str_in); - if(base_dir == LV_BIDI_DIR_RTL) wr = len; - else wr = 0; + if(base_dir == LV_BIDI_DIR_RTL) { + wr = len; + pos_conv_wr = pos_conv_len; + } + else { + wr = 0; + pos_conv_wr = 0; + } - str_out[len] = '\0'; + if (str_out) str_out[len] = '\0'; lv_bidi_dir_t dir = base_dir; @@ -163,39 +168,59 @@ void lv_bidi_process_paragraph(const char * str_in, char * str_out, uint32_t len /*Process neutral chars in the beginning*/ while(rd < len) { uint32_t letter = lv_txt_encoded_next(str_in, &rd); + pos_conv_rd++; dir = lv_bidi_get_letter_dir(letter); if(dir == LV_BIDI_DIR_NEUTRAL) dir = bracket_process(str_in, rd, len, letter, base_dir); - if(dir != LV_BIDI_DIR_NEUTRAL && dir != LV_BIDI_DIR_WEAK) break; } - if(rd && str_in[rd] != '\0') lv_txt_encoded_prev(str_in, &rd); + if(rd && str_in[rd] != '\0') { + lv_txt_encoded_prev(str_in, &rd); + pos_conv_rd--; + } if(rd) { if(base_dir == LV_BIDI_DIR_LTR) { - memcpy(&str_out[wr], str_in, rd); - wr += rd; + if (str_out) { + memcpy(&str_out[wr], str_in, rd); + wr += rd; + } + if (pos_conv_out) { + fill_pos_conv(&pos_conv_out[pos_conv_wr], pos_conv_rd, 0); + pos_conv_wr += pos_conv_rd; + } } else { wr -= rd; - 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*/ + while(rd < len) { - run_dir = get_next_run(&str_in[rd], base_dir, len - rd, &run_len); + run_dir = get_next_run(&str_in[rd], base_dir, len - rd, &run_len, &pos_conv_run_len); if(base_dir == LV_BIDI_DIR_LTR) { - if(run_dir == LV_BIDI_DIR_LTR) memcpy(&str_out[wr], &str_in[rd], 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); wr += run_len; + pos_conv_wr += pos_conv_run_len; } else { wr -= run_len; - if(run_dir == LV_BIDI_DIR_LTR) memcpy(&str_out[wr], &str_in[rd], run_len); - else rtl_reverse(&str_out[wr], &str_in[rd], run_len); + pos_conv_wr -= pos_conv_run_len; + if(run_dir == LV_BIDI_DIR_LTR) { + if (str_out) memcpy(&str_out[wr], &str_in[rd], run_len); + if (pos_conv_out) fill_pos_conv(&pos_conv_out[pos_conv_wr], pos_conv_run_len, pos_conv_rd); + } + else rtl_reverse(str_out? &str_out[wr]: NULL, &str_in[rd], run_len, pos_conv_out? &pos_conv_out[pos_conv_wr] : NULL, pos_conv_rd, pos_conv_run_len); } rd += run_len; + pos_conv_rd += pos_conv_run_len; } } @@ -212,24 +237,40 @@ uint32_t lv_bidi_get_next_paragraph(const char * txt) return i; } -static lv_bidi_dir_t get_next_run(const char * txt, lv_bidi_dir_t base_dir, uint32_t max_len, uint32_t * len) +/********************** + * STATIC FUNCTIONS + **********************/ + +static void fill_pos_conv(uint16_t * out, uint16_t len, uint16_t index) +{ + for (uint16_t i = 0; i < len; i++) + { + out[i] = index; + index++; + } +} + +static lv_bidi_dir_t get_next_run(const char * txt, lv_bidi_dir_t base_dir, uint32_t max_len, uint32_t * len, uint16_t * pos_conv_len) { uint32_t i = 0; uint32_t letter; + uint16_t pos_conv_i = 0; + letter = lv_txt_encoded_next(txt, NULL); lv_bidi_dir_t dir = lv_bidi_get_letter_dir(letter); if(dir == LV_BIDI_DIR_NEUTRAL) dir = bracket_process(txt, 0, max_len, letter, base_dir); - /*Find the first strong char. Skip the neutrals*/ while(dir == LV_BIDI_DIR_NEUTRAL || dir == LV_BIDI_DIR_WEAK) { letter = lv_txt_encoded_next(txt, &i); + pos_conv_i++; dir = lv_bidi_get_letter_dir(letter); if(dir == LV_BIDI_DIR_NEUTRAL) dir = bracket_process(txt, i, max_len, letter, base_dir); if(i >= max_len || txt[i] == '\0' || txt[i] == '\n' || txt[i] == '\r') { *len = i; + *pos_conv_len = pos_conv_i; return base_dir; } } @@ -238,84 +279,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_last_strong = i; + uint16_t pos_conv_i_prev = pos_conv_i; + uint16_t pos_conv_i_last_strong = pos_conv_i; /*Find the next char which has different direction*/ lv_bidi_dir_t next_dir = base_dir; while(i_prev < max_len && txt[i] != '\0' && txt[i] != '\n' && txt[i] != '\r') { letter = lv_txt_encoded_next(txt, &i); + pos_conv_i++; next_dir = lv_bidi_get_letter_dir(letter); if(next_dir == LV_BIDI_DIR_NEUTRAL) next_dir = bracket_process(txt, i, max_len, letter, base_dir); /*New dir found?*/ if((next_dir == LV_BIDI_DIR_RTL || next_dir == LV_BIDI_DIR_LTR) && next_dir != run_dir) { /*Include neutrals if `run_dir == base_dir` */ - if(run_dir == base_dir) *len = i_prev; + if(run_dir == base_dir) { + *len = i_prev; + *pos_conv_len = pos_conv_i_prev; + } /*Exclude neutrals if `run_dir != base_dir` */ - else *len = i_last_strong; + else { + *len = i_last_strong; + *pos_conv_len = pos_conv_i_last_strong; + } return run_dir; } - if(next_dir != LV_BIDI_DIR_NEUTRAL) i_last_strong = i; + if(next_dir != LV_BIDI_DIR_NEUTRAL) { + i_last_strong = i; + pos_conv_i_last_strong = pos_conv_i; + } i_prev = i; + pos_conv_i_prev = pos_conv_i; } - /*Handle end of of string. Apply `base_dir` on trailing neutrals*/ /*Include neutrals if `run_dir == base_dir` */ - if(run_dir == base_dir) *len = i_prev; + if(run_dir == base_dir) { + *len = i_prev; + *pos_conv_len = pos_conv_i_prev; + } /*Exclude neutrals if `run_dir != base_dir` */ - else *len = i_last_strong; + else { + *len = i_last_strong; + *pos_conv_len = pos_conv_i_last_strong; + } return run_dir; - } -static void rtl_reverse(char * dest, const char * src, uint32_t len) +static void rtl_reverse(char * dest, const char * src, uint32_t len, uint16_t *pos_conv_out, uint16_t pos_conv_rd_base, uint16_t pos_conv_len) { uint32_t i = len; uint32_t wr = 0; + uint16_t pos_conv_i = pos_conv_len; + uint16_t pos_conv_wr = 0; while(i) { uint32_t letter = lv_txt_encoded_prev(src, &i); + uint16_t pos_conv_letter = --pos_conv_i; /*Keep weak letters (numbers) as LTR*/ if(lv_bidi_letter_is_weak(letter)) { uint32_t last_weak = i; uint32_t first_weak = i; + uint16_t pos_conv_last_weak = pos_conv_i; + uint16_t pos_conv_first_weak = pos_conv_i; while(i) { letter = lv_txt_encoded_prev(src, &i); + pos_conv_letter = --pos_conv_i; + /*No need to call `char_change_to_pair` because there not such chars here*/ /*Finish on non-weak char */ /*but treat number and currency related chars as weak*/ - if(lv_bidi_letter_is_weak(letter) == false && letter != '.' && letter != ',' && letter != '$' && letter != '%') { + if (lv_bidi_letter_is_weak(letter) == false && letter != '.' && letter != ',' && letter != '$' && letter != '%') { lv_txt_encoded_next(src, &i); /*Rewind one letter*/ + pos_conv_i++; first_weak = i; + pos_conv_first_weak = pos_conv_i; break; } } - if(i == 0) first_weak = 0; + 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; - + pos_conv_wr += pos_conv_last_weak - pos_conv_first_weak + 1; } + /*Simply store in reversed order*/ else { uint32_t letter_size = lv_txt_encoded_size((const char *)&src[i]); /*Swap arithmetical symbols*/ if(letter_size == 1) { uint32_t new_letter = letter = char_change_to_pair(letter); - dest[wr] = (uint8_t)new_letter; + if (dest) dest[wr] = (uint8_t)new_letter; + if (pos_conv_out) pos_conv_out[pos_conv_wr] = pos_conv_rd_base + pos_conv_letter; wr += 1; + pos_conv_wr += 1; } /*Just store the letter*/ 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] = pos_conv_rd_base + pos_conv_i; wr += letter_size; + pos_conv_wr++; } } } diff --git a/src/lv_misc/lv_bidi.h b/src/lv_misc/lv_bidi.h index 9ce0fffa1..4d586e570 100644 --- a/src/lv_misc/lv_bidi.h +++ b/src/lv_misc/lv_bidi.h @@ -53,7 +53,7 @@ typedef uint8_t lv_bidi_dir_t; #if LV_USE_BIDI void lv_bidi_process(const char * str_in, char * str_out, lv_bidi_dir_t base_dir); -void lv_bidi_process_paragraph(const char * str_in, char * str_out, uint32_t len, lv_bidi_dir_t base_dir); +void lv_bidi_process_paragraph(const char * str_in, char * str_out, uint32_t len, lv_bidi_dir_t base_dir, uint16_t *pos_conv_out, uint16_t pos_conv_len); uint32_t lv_bidi_get_next_paragraph(const char * txt); lv_bidi_dir_t lv_bidi_detect_base_dir(const char * txt); lv_bidi_dir_t lv_bidi_get_letter_dir(uint32_t letter); From c7a7d1adca367fdccc86dd690e77a581229247ec Mon Sep 17 00:00:00 2001 From: Amir Gonnen Date: Mon, 4 Nov 2019 09:26:52 +0200 Subject: [PATCH 35/51] WIP: pos_conv add lv_bidi_get_logical/visual_pos functions --- src/lv_misc/lv_bidi.c | 36 ++++++++++++++++++++++++++++++++---- src/lv_misc/lv_bidi.h | 2 ++ 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/src/lv_misc/lv_bidi.c b/src/lv_misc/lv_bidi.c index 1d962c64a..fcb2f7b7c 100644 --- a/src/lv_misc/lv_bidi.c +++ b/src/lv_misc/lv_bidi.c @@ -6,9 +6,10 @@ /********************* * INCLUDES *********************/ -#include "lv_bidi.h" #include +#include "lv_bidi.h" #include "lv_txt.h" +#include "../lv_draw/lv_draw.h" #if LV_USE_BIDI @@ -34,6 +35,7 @@ static void rtl_reverse(char * dest, const char * src, uint32_t len, uint16_t *p 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 @@ -138,6 +140,19 @@ bool lv_bidi_letter_is_neutral(uint32_t letter) return false; } +uint16_t lv_bidi_get_logical_pos(const char * str_in, uint16_t len, lv_bidi_dir_t base_dir, uint32_t visual_pos) +{ + return 0; // TODO +} + +uint16_t lv_bidi_get_visual_pos(const char * str_in, uint16_t len, lv_bidi_dir_t base_dir, uint32_t logical_pos) +{ + uint32_t pos_conv_len = get_txt_len(str_in, len) * sizeof(uint16_t); + uint16_t *pos_conv_buf = lv_draw_get_buf(pos_conv_len); + lv_bidi_process_paragraph(str_in, NULL, len, base_dir, pos_conv_buf, pos_conv_len); + return pos_conv_buf[logical_pos]; +} + 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; @@ -192,7 +207,7 @@ void lv_bidi_process_paragraph(const char * str_in, char * str_out, uint32_t len } else { wr -= rd; pos_conv_wr -= pos_conv_rd; - rtl_reverse(str_out? &str_out[wr]: NULL, str_in, rd, pos_conv_out? &pos_conv_out[pos_conv_wr]: NULL, 0, pos_conv_rd); + rtl_reverse(str_out? &str_out[wr]: NULL, str_in, rd, pos_conv_out? &pos_conv_out[pos_conv_rd]: NULL, 0, pos_conv_rd); } } @@ -206,7 +221,7 @@ void lv_bidi_process_paragraph(const char * str_in, char * str_out, uint32_t len if (str_out) memcpy(&str_out[wr], &str_in[rd], run_len); if (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); + else rtl_reverse(str_out? &str_out[wr]: NULL, &str_in[rd], run_len, pos_conv_out? &pos_conv_out[pos_conv_rd] : NULL, pos_conv_rd, pos_conv_run_len); wr += run_len; pos_conv_wr += pos_conv_run_len; } else { @@ -216,7 +231,7 @@ void lv_bidi_process_paragraph(const char * str_in, char * str_out, uint32_t len if (str_out) memcpy(&str_out[wr], &str_in[rd], run_len); if (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); + else rtl_reverse(str_out? &str_out[wr]: NULL, &str_in[rd], run_len, pos_conv_out? &pos_conv_out[pos_conv_rd] : NULL, pos_conv_rd, pos_conv_run_len); } rd += run_len; @@ -241,6 +256,19 @@ uint32_t lv_bidi_get_next_paragraph(const char * txt) * 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++) diff --git a/src/lv_misc/lv_bidi.h b/src/lv_misc/lv_bidi.h index 4d586e570..d5129c4cc 100644 --- a/src/lv_misc/lv_bidi.h +++ b/src/lv_misc/lv_bidi.h @@ -60,6 +60,8 @@ lv_bidi_dir_t lv_bidi_get_letter_dir(uint32_t letter); bool lv_bidi_letter_is_weak(uint32_t letter); bool lv_bidi_letter_is_rtl(uint32_t letter); bool lv_bidi_letter_is_neutral(uint32_t letter); +uint16_t lv_bidi_get_logical_pos(const char * str_in, uint16_t len, lv_bidi_dir_t base_dir, uint32_t visual_pos); +uint16_t lv_bidi_get_visual_pos(const char * str_in, uint16_t len, lv_bidi_dir_t base_dir, uint32_t logical_pos); /********************** * MACROS From 6f57de051b35486ee219674d3a5ac8786257476f Mon Sep 17 00:00:00 2001 From: Amir Gonnen Date: Tue, 5 Nov 2019 01:03:40 +0200 Subject: [PATCH 36/51] WIP: pos_conv, bugfixes, use in lv_label --- src/lv_misc/lv_bidi.c | 35 +++++++++++++++++++---------- src/lv_misc/lv_bidi.h | 4 ++-- src/lv_objx/lv_label.c | 50 ++++++++++++++++++++++++++++++++---------- 3 files changed, 63 insertions(+), 26 deletions(-) diff --git a/src/lv_misc/lv_bidi.c b/src/lv_misc/lv_bidi.c index fcb2f7b7c..c52e3212a 100644 --- a/src/lv_misc/lv_bidi.c +++ b/src/lv_misc/lv_bidi.c @@ -140,17 +140,28 @@ bool lv_bidi_letter_is_neutral(uint32_t letter) return false; } -uint16_t lv_bidi_get_logical_pos(const char * str_in, uint16_t len, lv_bidi_dir_t base_dir, uint32_t visual_pos) +uint16_t lv_bidi_get_logical_pos(const char * str_in, char **bidi_txt, uint32_t len, lv_bidi_dir_t base_dir, uint32_t visual_pos) { - return 0; // TODO + uint32_t pos_conv_len = get_txt_len(str_in, len); + void *buf = lv_draw_get_buf(len + pos_conv_len * sizeof(uint16_t)); + if (bidi_txt) *bidi_txt = buf; + uint16_t *pos_conv_buf = (uint16_t*) ((char*)buf + len); + lv_bidi_process_paragraph(str_in, bidi_txt? *bidi_txt: NULL, len, base_dir, pos_conv_buf, pos_conv_len); + return pos_conv_buf[visual_pos]; } -uint16_t lv_bidi_get_visual_pos(const char * str_in, uint16_t len, lv_bidi_dir_t base_dir, uint32_t logical_pos) +uint16_t lv_bidi_get_visual_pos(const char * str_in, char **bidi_txt, uint16_t len, lv_bidi_dir_t base_dir, uint32_t logical_pos) { - uint32_t pos_conv_len = get_txt_len(str_in, len) * sizeof(uint16_t); - uint16_t *pos_conv_buf = lv_draw_get_buf(pos_conv_len); - lv_bidi_process_paragraph(str_in, NULL, len, base_dir, pos_conv_buf, pos_conv_len); - return pos_conv_buf[logical_pos]; + 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 (pos_conv_buf[i] == logical_pos) + return i; + } + return (uint16_t) -1; } void lv_bidi_process_paragraph(const char * str_in, char * str_out, uint32_t len, lv_bidi_dir_t base_dir, uint16_t *pos_conv_out, uint16_t pos_conv_len) @@ -207,7 +218,7 @@ void lv_bidi_process_paragraph(const char * str_in, char * str_out, uint32_t len } else { wr -= rd; pos_conv_wr -= pos_conv_rd; - rtl_reverse(str_out? &str_out[wr]: NULL, str_in, rd, pos_conv_out? &pos_conv_out[pos_conv_rd]: NULL, 0, pos_conv_rd); + rtl_reverse(str_out? &str_out[wr]: NULL, str_in, rd, pos_conv_out? &pos_conv_out[pos_conv_wr]: NULL, 0, pos_conv_rd); } } @@ -221,7 +232,7 @@ void lv_bidi_process_paragraph(const char * str_in, char * str_out, uint32_t len if (str_out) memcpy(&str_out[wr], &str_in[rd], run_len); if (pos_conv_out) fill_pos_conv(&pos_conv_out[pos_conv_wr], pos_conv_run_len, pos_conv_rd); } - else rtl_reverse(str_out? &str_out[wr]: NULL, &str_in[rd], run_len, pos_conv_out? &pos_conv_out[pos_conv_rd] : NULL, pos_conv_rd, pos_conv_run_len); + else rtl_reverse(str_out? &str_out[wr]: NULL, &str_in[rd], run_len, pos_conv_out? &pos_conv_out[pos_conv_wr] : NULL, pos_conv_rd, pos_conv_run_len); wr += run_len; pos_conv_wr += pos_conv_run_len; } else { @@ -231,7 +242,7 @@ void lv_bidi_process_paragraph(const char * str_in, char * str_out, uint32_t len if (str_out) memcpy(&str_out[wr], &str_in[rd], run_len); if (pos_conv_out) fill_pos_conv(&pos_conv_out[pos_conv_wr], pos_conv_run_len, pos_conv_rd); } - else rtl_reverse(str_out? &str_out[wr]: NULL, &str_in[rd], run_len, pos_conv_out? &pos_conv_out[pos_conv_rd] : NULL, pos_conv_rd, pos_conv_run_len); + else rtl_reverse(str_out? &str_out[wr]: NULL, &str_in[rd], run_len, pos_conv_out? &pos_conv_out[pos_conv_wr] : NULL, pos_conv_rd, pos_conv_run_len); } rd += run_len; @@ -411,8 +422,8 @@ static void rtl_reverse(char * dest, const char * src, uint32_t len, uint16_t *p uint32_t new_letter = letter = char_change_to_pair(letter); if (dest) dest[wr] = (uint8_t)new_letter; if (pos_conv_out) pos_conv_out[pos_conv_wr] = pos_conv_rd_base + pos_conv_letter; - wr += 1; - pos_conv_wr += 1; + wr++; + pos_conv_wr++; } /*Just store the letter*/ else { diff --git a/src/lv_misc/lv_bidi.h b/src/lv_misc/lv_bidi.h index d5129c4cc..09bb04efd 100644 --- a/src/lv_misc/lv_bidi.h +++ b/src/lv_misc/lv_bidi.h @@ -60,8 +60,8 @@ lv_bidi_dir_t lv_bidi_get_letter_dir(uint32_t letter); bool lv_bidi_letter_is_weak(uint32_t letter); bool lv_bidi_letter_is_rtl(uint32_t letter); bool lv_bidi_letter_is_neutral(uint32_t letter); -uint16_t lv_bidi_get_logical_pos(const char * str_in, uint16_t len, lv_bidi_dir_t base_dir, uint32_t visual_pos); -uint16_t lv_bidi_get_visual_pos(const char * str_in, uint16_t len, lv_bidi_dir_t base_dir, uint32_t logical_pos); +uint16_t lv_bidi_get_logical_pos(const char * str_in, char **bidi_txt, uint32_t len, lv_bidi_dir_t base_dir, uint32_t visual_pos); +uint16_t lv_bidi_get_visual_pos(const char * str_in, char **bidi_txt, uint16_t len, lv_bidi_dir_t base_dir, uint32_t logical_pos); /********************** * MACROS diff --git a/src/lv_objx/lv_label.c b/src/lv_objx/lv_label.c index 46cc451c4..bbf6a8469 100644 --- a/src/lv_objx/lv_label.c +++ b/src/lv_objx/lv_label.c @@ -593,6 +593,8 @@ void lv_label_get_letter_pos(const lv_obj_t * label, uint16_t index, lv_point_t uint8_t letter_height = lv_font_get_line_height(font); lv_coord_t y = 0; lv_txt_flag_t flag = LV_TXT_FLAG_NONE; + uint16_t visual_pos; + char *bidi_txt; if(ext->recolor != 0) flag |= LV_TXT_FLAG_RECOLOR; if(ext->expand != 0) flag |= LV_TXT_FLAG_EXPAND; @@ -626,19 +628,27 @@ void lv_label_get_letter_pos(const lv_obj_t * label, uint16_t index, lv_point_t } } +#if LV_USE_BIDI + /*Handle Bidi*/ + visual_pos = lv_bidi_get_visual_pos(&txt[line_start], &bidi_txt, new_line_start - line_start, lv_obj_get_base_dir(label), index - line_start); +#else + visual_pos = index - line_start; + bidi_txt = &txt[line_start]; +#endif + /*Calculate the x coordinate*/ - lv_coord_t x = lv_txt_get_width(&txt[line_start], index - line_start, font, style->text.letter_space, flag); + lv_coord_t x = lv_txt_get_width(bidi_txt, visual_pos, font, style->text.letter_space, flag); if(index != line_start) x += style->text.letter_space; if(align == LV_LABEL_ALIGN_CENTER) { lv_coord_t line_w; - line_w = lv_txt_get_width(&txt[line_start], new_line_start - line_start, font, style->text.letter_space, flag); + line_w = lv_txt_get_width(bidi_txt, new_line_start - line_start, font, style->text.letter_space, flag); x += lv_obj_get_width(label) / 2 - line_w / 2; } else if(align == LV_LABEL_ALIGN_RIGHT) { lv_coord_t line_w; - line_w = lv_txt_get_width(&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; } @@ -668,6 +678,8 @@ uint16_t lv_label_get_letter_on(const lv_obj_t * label, lv_point_t * pos) uint8_t letter_height = lv_font_get_line_height(font); lv_coord_t y = 0; lv_txt_flag_t flag = LV_TXT_FLAG_NONE; + uint16_t logical_pos; + char *bidi_txt; if(ext->recolor != 0) flag |= LV_TXT_FLAG_RECOLOR; if(ext->expand != 0) flag |= LV_TXT_FLAG_EXPAND; @@ -691,37 +703,44 @@ uint16_t lv_label_get_letter_on(const lv_obj_t * label, lv_point_t * pos) line_start = new_line_start; } +#if LV_USE_BIDI + bidi_txt = lv_draw_get_buf(new_line_start - line_start + 1); + lv_bidi_process_paragraph(txt + line_start, bidi_txt, new_line_start - line_start, lv_obj_get_base_dir(label), NULL, 0); +#else + bidi_txt = txt + line_start; +#endif + /*Calculate the x coordinate*/ lv_coord_t x = 0; if(align == LV_LABEL_ALIGN_CENTER) { lv_coord_t line_w; - line_w = lv_txt_get_width(&txt[line_start], new_line_start - line_start, font, style->text.letter_space, flag); + line_w = lv_txt_get_width(bidi_txt, new_line_start - line_start, font, style->text.letter_space, flag); x += lv_obj_get_width(label) / 2 - line_w / 2; } else if(align == LV_LABEL_ALIGN_RIGHT) { lv_coord_t line_w; - line_w = lv_txt_get_width(&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; } lv_txt_cmd_state_t cmd_state = LV_TXT_CMD_STATE_WAIT; - uint32_t i = line_start; + uint32_t i = 0; uint32_t i_act = i; uint32_t letter; uint32_t letter_next; if(new_line_start > 0) { - while(i < new_line_start) { + while(i + line_start < new_line_start) { /* 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*/ - letter_next = lv_txt_encoded_next(&txt[i], NULL); + letter_next = lv_txt_encoded_next(&bidi_txt[i], NULL); /*Handle the recolor command*/ if((flag & LV_TXT_FLAG_RECOLOR) != 0) { - if(lv_txt_is_cmd(&cmd_state, txt[i]) != false) { + if(lv_txt_is_cmd(&cmd_state, bidi_txt[i]) != false) { continue; /*Skip the letter is it is part of a command*/ } } @@ -729,7 +748,7 @@ uint16_t lv_label_get_letter_on(const lv_obj_t * label, lv_point_t * pos) x += lv_font_get_glyph_width(font, letter, letter_next); /*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; break; } @@ -738,7 +757,14 @@ uint16_t lv_label_get_letter_on(const lv_obj_t * label, lv_point_t * pos) } } - return lv_encoded_get_char_id(txt, i); +#if LV_USE_BIDI + /*Handle Bidi*/ + logical_pos = lv_bidi_get_logical_pos(&txt[line_start], NULL, new_line_start - line_start, lv_obj_get_base_dir(label), lv_encoded_get_char_id(bidi_txt, i)); +#else + logical_pos = lv_encoded_get_char_id(bidi_txt, i); +#endif + + return logical_pos; } /** From 5d5a8b4894f54988bf0f904b389284c23417d4d3 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Tue, 5 Nov 2019 16:00:32 +0100 Subject: [PATCH 37/51] convert lv_bidi_get_visual_pos to byteindex --- src/lv_objx/lv_label.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/lv_objx/lv_label.c b/src/lv_objx/lv_label.c index bbf6a8469..7427e69a7 100644 --- a/src/lv_objx/lv_label.c +++ b/src/lv_objx/lv_label.c @@ -631,11 +631,16 @@ void lv_label_get_letter_pos(const lv_obj_t * label, uint16_t index, lv_point_t #if LV_USE_BIDI /*Handle Bidi*/ visual_pos = lv_bidi_get_visual_pos(&txt[line_start], &bidi_txt, new_line_start - line_start, lv_obj_get_base_dir(label), index - line_start); + + printf("vp:%d, ", visual_pos); + visual_pos = lv_txt_encoded_get_byte_id(bidi_txt, visual_pos); + printf("vpb:%d, ", visual_pos); #else visual_pos = index - line_start; bidi_txt = &txt[line_start]; #endif + /*Calculate the x coordinate*/ lv_coord_t x = lv_txt_get_width(bidi_txt, visual_pos, font, style->text.letter_space, flag); From 74254975cddbd90911f44bb77d70eb64e9899728 Mon Sep 17 00:00:00 2001 From: Maximilian Schwab Date: Wed, 6 Nov 2019 01:40:22 +0100 Subject: [PATCH 38/51] Update comment for logging callback (#1255) Changed lv_log_register_print to lv_log_register_print_cb --- lv_conf_template.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lv_conf_template.h b/lv_conf_template.h index 08e9beb9e..707e4a238 100644 --- a/lv_conf_template.h +++ b/lv_conf_template.h @@ -225,7 +225,7 @@ typedef void * lv_indev_drv_user_data_t; /*Type of user data in the i # define LV_LOG_LEVEL LV_LOG_LEVEL_WARN /* 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 #endif /*LV_USE_LOG*/ From 5441cf9998aadb7393d09e451130c6f6b26d6bae Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Wed, 6 Nov 2019 05:19:06 +0100 Subject: [PATCH 39/51] bidi fixes + add missing prefix to lv_encoded_get_char_id --- src/lv_draw/lv_draw_label.c | 2 +- src/lv_misc/lv_txt.c | 4 ++-- src/lv_misc/lv_txt.h | 2 +- src/lv_objx/lv_label.c | 29 +++++++++++++---------------- 4 files changed, 17 insertions(+), 20 deletions(-) diff --git a/src/lv_draw/lv_draw_label.c b/src/lv_draw/lv_draw_label.c index 5bd0592c5..d7650690c 100644 --- a/src/lv_draw/lv_draw_label.c +++ b/src/lv_draw/lv_draw_label.c @@ -220,7 +220,7 @@ void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_st letter_w = lv_font_get_glyph_width(font, letter, letter_next); if(sel_start != 0xFFFF && sel_end != 0xFFFF) { - int char_ind = lv_encoded_get_char_id(bidi_txt, i); + int char_ind = lv_txt_encoded_get_char_id(bidi_txt, i); /*Do not draw the rectangle on the character at `sel_start`.*/ if(char_ind > sel_start && char_ind <= sel_end) { lv_area_t sel_coords; diff --git a/src/lv_misc/lv_txt.c b/src/lv_misc/lv_txt.c index d18e456b0..0c4027761 100644 --- a/src/lv_misc/lv_txt.c +++ b/src/lv_misc/lv_txt.c @@ -56,7 +56,7 @@ uint32_t (*lv_txt_encoded_conv_wc)(uint32_t) = lv_txt_utf8_con uint32_t (*lv_txt_encoded_next)(const char *, uint32_t *) = lv_txt_utf8_next; uint32_t (*lv_txt_encoded_prev)(const char *, uint32_t *) = lv_txt_utf8_prev; uint32_t (*lv_txt_encoded_get_byte_id)(const char *, uint32_t) = lv_txt_utf8_get_byte_id; -uint32_t (*lv_encoded_get_char_id)(const char *, uint32_t) = lv_txt_utf8_get_char_id; +uint32_t (*lv_txt_encoded_get_char_id)(const char *, uint32_t) = lv_txt_utf8_get_char_id; uint32_t (*lv_txt_get_encoded_length)(const char *) = lv_txt_utf8_get_length; #elif LV_TXT_ENC == LV_TXT_ENC_ASCII uint8_t (*lv_txt_encoded_size)(const char *) = lv_txt_iso8859_1_size; @@ -65,7 +65,7 @@ uint32_t (*lv_txt_encoded_conv_wc)(uint32_t) = lv_txt_iso8859_ uint32_t (*lv_txt_encoded_next)(const char *, uint32_t *) = lv_txt_iso8859_1_next; uint32_t (*lv_txt_encoded_prev)(const char *, uint32_t *) = lv_txt_iso8859_1_prev; uint32_t (*lv_txt_encoded_get_byte_id)(const char *, uint32_t) = lv_txt_iso8859_1_get_byte_id; -uint32_t (*lv_encoded_get_char_id)(const char *, uint32_t) = lv_txt_iso8859_1_get_char_id; +uint32_t (*lv_txt_encoded_get_char_id)(const char *, uint32_t) = lv_txt_iso8859_1_get_char_id; uint32_t (*lv_txt_get_encoded_length)(const char *) = lv_txt_iso8859_1_get_length; #endif diff --git a/src/lv_misc/lv_txt.h b/src/lv_misc/lv_txt.h index 6fc6e4a63..865e2c97c 100644 --- a/src/lv_misc/lv_txt.h +++ b/src/lv_misc/lv_txt.h @@ -188,7 +188,7 @@ extern uint32_t (*lv_txt_encoded_get_byte_id)(const char *, uint32_t); * @param byte_id byte index * @return character index of the letter at 'byte_id'th position */ -extern uint32_t (*lv_encoded_get_char_id)(const char *, uint32_t); +extern uint32_t (*lv_txt_encoded_get_char_id)(const char *, uint32_t); /** * Get the number of characters (and NOT bytes) in a string. diff --git a/src/lv_objx/lv_label.c b/src/lv_objx/lv_label.c index 7427e69a7..3bdfd04a8 100644 --- a/src/lv_objx/lv_label.c +++ b/src/lv_objx/lv_label.c @@ -578,7 +578,7 @@ uint16_t lv_label_get_anim_speed(const lv_obj_t * label) * index (different in UTF-8) * @param pos store the result here (E.g. index = 0 gives 0;0 coordinates) */ -void lv_label_get_letter_pos(const lv_obj_t * label, uint16_t index, lv_point_t * pos) +void lv_label_get_letter_pos(const lv_obj_t * label, uint16_t char_id, lv_point_t * pos) { LV_ASSERT_OBJ(label, LV_OBJX_NAME); LV_ASSERT_NULL(pos); @@ -593,8 +593,6 @@ void lv_label_get_letter_pos(const lv_obj_t * label, uint16_t index, lv_point_t uint8_t letter_height = lv_font_get_line_height(font); lv_coord_t y = 0; lv_txt_flag_t flag = LV_TXT_FLAG_NONE; - uint16_t visual_pos; - char *bidi_txt; if(ext->recolor != 0) flag |= LV_TXT_FLAG_RECOLOR; if(ext->expand != 0) flag |= LV_TXT_FLAG_EXPAND; @@ -608,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; } - index = lv_txt_encoded_get_byte_id(txt, index); + uint16_t byte_id = lv_txt_encoded_get_byte_id(txt, char_id); /*Search the line of the index letter */; while(txt[new_line_start] != '\0') { new_line_start += lv_txt_get_next_line(&txt[line_start], font, style->text.letter_space, max_w, flag); - if(index < new_line_start || txt[new_line_start] == '\0') + if(byte_id < new_line_start || txt[new_line_start] == '\0') break; /*The line of 'index' letter begins at 'line_start'*/ y += letter_height + style->text.line_space; @@ -621,30 +619,29 @@ void lv_label_get_letter_pos(const lv_obj_t * label, uint16_t index, lv_point_t } /*If the last character is line break then go to the next line*/ - if(index > 0) { - if((txt[index - 1] == '\n' || txt[index - 1] == '\r') && txt[index] == '\0') { + if(byte_id > 0) { + if((txt[byte_id - 1] == '\n' || txt[byte_id - 1] == '\r') && txt[byte_id] == '\0') { y += letter_height + style->text.line_space; - line_start = index; + line_start = byte_id; } } + char *bidi_txt; #if LV_USE_BIDI /*Handle Bidi*/ - visual_pos = lv_bidi_get_visual_pos(&txt[line_start], &bidi_txt, new_line_start - line_start, lv_obj_get_base_dir(label), index - line_start); + uint16_t line_char_id = lv_txt_encoded_get_char_id(&txt[line_start], byte_id - line_start); - printf("vp:%d, ", visual_pos); - visual_pos = lv_txt_encoded_get_byte_id(bidi_txt, visual_pos); - printf("vpb:%d, ", visual_pos); + uint16_t visual_char_pos = lv_bidi_get_visual_pos(&txt[line_start], &bidi_txt, new_line_start - line_start, lv_obj_get_base_dir(label), line_char_id); + uint16_t visual_byte_pos = lv_txt_encoded_get_byte_id(bidi_txt, visual_char_pos); #else - visual_pos = index - line_start; bidi_txt = &txt[line_start]; #endif /*Calculate the x coordinate*/ - lv_coord_t x = lv_txt_get_width(bidi_txt, visual_pos, font, style->text.letter_space, flag); + lv_coord_t x = lv_txt_get_width(bidi_txt, visual_byte_pos, font, style->text.letter_space, flag); - if(index != line_start) x += style->text.letter_space; + if(char_id != line_start) x += style->text.letter_space; if(align == LV_LABEL_ALIGN_CENTER) { lv_coord_t line_w; @@ -764,7 +761,7 @@ uint16_t lv_label_get_letter_on(const lv_obj_t * label, lv_point_t * pos) #if LV_USE_BIDI /*Handle Bidi*/ - logical_pos = lv_bidi_get_logical_pos(&txt[line_start], NULL, new_line_start - line_start, lv_obj_get_base_dir(label), lv_encoded_get_char_id(bidi_txt, i)); + logical_pos = lv_bidi_get_logical_pos(&txt[line_start], NULL, new_line_start - line_start, lv_obj_get_base_dir(label), lv_txt_encoded_get_char_id(bidi_txt, i)); #else logical_pos = lv_encoded_get_char_id(bidi_txt, i); #endif From a3a326c2ffaffeefd1d5ad6faa33031b497a0fb8 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Fri, 8 Nov 2019 13:49:52 +0100 Subject: [PATCH 40/51] fix lv_label_get_letter_on in case of multi-line texts --- src/lv_objx/lv_label.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lv_objx/lv_label.c b/src/lv_objx/lv_label.c index 3bdfd04a8..ab81f4a24 100644 --- a/src/lv_objx/lv_label.c +++ b/src/lv_objx/lv_label.c @@ -766,7 +766,7 @@ uint16_t lv_label_get_letter_on(const lv_obj_t * label, lv_point_t * pos) logical_pos = lv_encoded_get_char_id(bidi_txt, i); #endif - return logical_pos; + return logical_pos + line_start; } /** From 0130f3e5f2606388d466d5476fdd1c4c80810b8c Mon Sep 17 00:00:00 2001 From: Amir Gonnen Date: Sat, 9 Nov 2019 01:02:51 +0200 Subject: [PATCH 41/51] Add RTL indication to pos_conv When getting visual/logical pos, also get whether this pos is RTL (was reversed) --- src/lv_misc/lv_bidi.c | 22 +++++++++++++++------- src/lv_misc/lv_bidi.h | 4 ++-- src/lv_objx/lv_label.c | 8 ++++++-- 3 files changed, 23 insertions(+), 11 deletions(-) diff --git a/src/lv_misc/lv_bidi.c b/src/lv_misc/lv_bidi.c index c52e3212a..0f1153b52 100644 --- a/src/lv_misc/lv_bidi.c +++ b/src/lv_misc/lv_bidi.c @@ -18,6 +18,11 @@ *********************/ #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 **********************/ @@ -140,17 +145,18 @@ bool lv_bidi_letter_is_neutral(uint32_t letter) 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) +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); - return pos_conv_buf[visual_pos]; + 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) +uint16_t lv_bidi_get_visual_pos(const char * str_in, char **bidi_txt, uint16_t len, lv_bidi_dir_t base_dir, uint32_t logical_pos, bool *is_rtl) { uint32_t pos_conv_len = get_txt_len(str_in, len); void *buf = lv_draw_get_buf(len + pos_conv_len * sizeof(uint16_t)); @@ -158,8 +164,10 @@ uint16_t lv_bidi_get_visual_pos(const char * str_in, char **bidi_txt, uint16_t l uint16_t *pos_conv_buf = (uint16_t*) ((char*)buf + len); lv_bidi_process_paragraph(str_in, bidi_txt? *bidi_txt: NULL, len, base_dir, pos_conv_buf, pos_conv_len); for (uint16_t i = 0; i < pos_conv_len; i++){ - if (pos_conv_buf[i] == logical_pos) + 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; } @@ -284,7 +292,7 @@ static void fill_pos_conv(uint16_t * out, uint16_t len, uint16_t index) { for (uint16_t i = 0; i < len; i++) { - out[i] = index; + out[i] = SET_RTL_POS(index, false); index++; } } @@ -421,14 +429,14 @@ static void rtl_reverse(char * dest, const char * src, uint32_t len, uint16_t *p if(letter_size == 1) { uint32_t new_letter = letter = char_change_to_pair(letter); if (dest) dest[wr] = (uint8_t)new_letter; - if (pos_conv_out) pos_conv_out[pos_conv_wr] = pos_conv_rd_base + pos_conv_letter; + if (pos_conv_out) pos_conv_out[pos_conv_wr] = SET_RTL_POS(pos_conv_rd_base + pos_conv_letter, true); wr++; pos_conv_wr++; } /*Just store the letter*/ else { if (dest) memcpy(&dest[wr], &src[i], letter_size); - if (pos_conv_out) pos_conv_out[pos_conv_wr] = pos_conv_rd_base + pos_conv_i; + if (pos_conv_out) pos_conv_out[pos_conv_wr] = SET_RTL_POS(pos_conv_rd_base + pos_conv_i, true); wr += letter_size; pos_conv_wr++; } diff --git a/src/lv_misc/lv_bidi.h b/src/lv_misc/lv_bidi.h index 09bb04efd..215727aa7 100644 --- a/src/lv_misc/lv_bidi.h +++ b/src/lv_misc/lv_bidi.h @@ -60,8 +60,8 @@ lv_bidi_dir_t lv_bidi_get_letter_dir(uint32_t letter); bool lv_bidi_letter_is_weak(uint32_t letter); bool lv_bidi_letter_is_rtl(uint32_t letter); bool lv_bidi_letter_is_neutral(uint32_t letter); -uint16_t lv_bidi_get_logical_pos(const char * str_in, char **bidi_txt, uint32_t len, lv_bidi_dir_t base_dir, uint32_t visual_pos); -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); +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 diff --git a/src/lv_objx/lv_label.c b/src/lv_objx/lv_label.c index ab81f4a24..de3874fe4 100644 --- a/src/lv_objx/lv_label.c +++ b/src/lv_objx/lv_label.c @@ -631,7 +631,9 @@ void lv_label_get_letter_pos(const lv_obj_t * label, uint16_t char_id, lv_point_ /*Handle Bidi*/ uint16_t line_char_id = lv_txt_encoded_get_char_id(&txt[line_start], byte_id - line_start); - uint16_t visual_char_pos = lv_bidi_get_visual_pos(&txt[line_start], &bidi_txt, new_line_start - line_start, lv_obj_get_base_dir(label), line_char_id); + bool is_rtl; + uint16_t visual_char_pos = lv_bidi_get_visual_pos(&txt[line_start], &bidi_txt, new_line_start - line_start, lv_obj_get_base_dir(label), line_char_id, &is_rtl); + if (is_rtl) visual_char_pos++; uint16_t visual_byte_pos = lv_txt_encoded_get_byte_id(bidi_txt, visual_char_pos); #else bidi_txt = &txt[line_start]; @@ -761,7 +763,9 @@ uint16_t lv_label_get_letter_on(const lv_obj_t * label, lv_point_t * pos) #if LV_USE_BIDI /*Handle Bidi*/ - logical_pos = lv_bidi_get_logical_pos(&txt[line_start], NULL, new_line_start - line_start, lv_obj_get_base_dir(label), lv_txt_encoded_get_char_id(bidi_txt, i)); + bool is_rtl; + logical_pos = lv_bidi_get_logical_pos(&txt[line_start], NULL, new_line_start - line_start, 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_encoded_get_char_id(bidi_txt, i); #endif From 96b9114a5afbe06b5d37b8c83d3cbd9135248241 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Sat, 9 Nov 2019 01:53:02 +0100 Subject: [PATCH 42/51] bidi fixes for multi line text handling --- src/lv_draw/lv_draw_label.c | 5 +++-- src/lv_objx/lv_label.c | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/lv_draw/lv_draw_label.c b/src/lv_draw/lv_draw_label.c index d7650690c..2a5b22903 100644 --- a/src/lv_draw/lv_draw_label.c +++ b/src/lv_draw/lv_draw_label.c @@ -166,13 +166,14 @@ void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_st i = 0; uint32_t letter; uint32_t letter_next; - while(i < line_end - line_start) { #if LV_USE_BIDI char *bidi_txt = lv_draw_get_buf(line_end - line_start + 1); lv_bidi_process_paragraph(txt + line_start, bidi_txt, line_end - line_start, bidi_dir, NULL, 0); #else const char *bidi_txt = txt + line_start; #endif + while(i < line_end - line_start) { + letter = lv_txt_encoded_next(bidi_txt, &i); letter_next = lv_txt_encoded_next(&bidi_txt[i], NULL); @@ -220,7 +221,7 @@ void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_st letter_w = lv_font_get_glyph_width(font, letter, letter_next); if(sel_start != 0xFFFF && sel_end != 0xFFFF) { - int char_ind = lv_txt_encoded_get_char_id(bidi_txt, i); + int char_ind = lv_txt_encoded_get_char_id(bidi_txt, i + line_start); /*Do not draw the rectangle on the character at `sel_start`.*/ if(char_ind > sel_start && char_ind <= sel_end) { lv_area_t sel_coords; diff --git a/src/lv_objx/lv_label.c b/src/lv_objx/lv_label.c index de3874fe4..cd02a0ed0 100644 --- a/src/lv_objx/lv_label.c +++ b/src/lv_objx/lv_label.c @@ -767,10 +767,10 @@ uint16_t lv_label_get_letter_on(const lv_obj_t * label, lv_point_t * pos) logical_pos = lv_bidi_get_logical_pos(&txt[line_start], NULL, new_line_start - line_start, 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_encoded_get_char_id(bidi_txt, i); + logical_pos = lv_txt_encoded_get_char_id(bidi_txt, i); #endif - return logical_pos + line_start; + return logical_pos + lv_txt_encoded_get_char_id(txt, line_start) ; } /** From 8dfcba6aa864f3aeb66139c815c8b7e44b3e7db0 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Sun, 10 Nov 2019 10:52:49 +0100 Subject: [PATCH 43/51] text sel fixes with bidi --- src/lv_draw/lv_draw_label.c | 21 +++++++++++++++++++-- src/lv_objx/lv_label.c | 2 +- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/lv_draw/lv_draw_label.c b/src/lv_draw/lv_draw_label.c index 2a5b22903..ae6470ab8 100644 --- a/src/lv_draw/lv_draw_label.c +++ b/src/lv_draw/lv_draw_label.c @@ -113,6 +113,24 @@ void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_st pos.y += hint->y; } + if(sel_start != 0xFFFF) { + sel_start = lv_bidi_get_visual_pos(txt, NULL, strlen(txt), bidi_dir, sel_start, NULL); + sel_start = lv_txt_encoded_get_byte_id(txt, sel_start); + } + + if(sel_end != 0xFFFF) { + sel_end = lv_bidi_get_visual_pos(txt, NULL, strlen(txt), bidi_dir, sel_end, NULL); + sel_end = lv_txt_encoded_get_byte_id(txt, sel_end); + } + + if(sel_start > sel_end) { + uint16_t tmp = sel_start; + sel_start = sel_end; + sel_end = tmp; + } + + + 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*/ @@ -221,9 +239,8 @@ void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_st letter_w = lv_font_get_glyph_width(font, letter, letter_next); if(sel_start != 0xFFFF && sel_end != 0xFFFF) { - int char_ind = lv_txt_encoded_get_char_id(bidi_txt, i + line_start); /*Do not draw the rectangle on the character at `sel_start`.*/ - if(char_ind > sel_start && char_ind <= sel_end) { + if(i + line_start > sel_start && i + line_start <= sel_end) { lv_area_t sel_coords; sel_coords.x1 = pos.x; sel_coords.y1 = pos.y; diff --git a/src/lv_objx/lv_label.c b/src/lv_objx/lv_label.c index cd02a0ed0..004da981b 100644 --- a/src/lv_objx/lv_label.c +++ b/src/lv_objx/lv_label.c @@ -770,7 +770,7 @@ uint16_t lv_label_get_letter_on(const lv_obj_t * label, lv_point_t * pos) logical_pos = lv_txt_encoded_get_char_id(bidi_txt, i); #endif - return logical_pos + lv_txt_encoded_get_char_id(txt, line_start) ; + return logical_pos + lv_txt_encoded_get_char_id(txt, line_start); } /** From 6eaf8dd6d3eefc87455ad856999295bbe92b812d Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Sun, 10 Nov 2019 11:03:19 +0100 Subject: [PATCH 44/51] text sel fix, if start > end --- src/lv_objx/lv_label.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/lv_objx/lv_label.c b/src/lv_objx/lv_label.c index 004da981b..40d2cead5 100644 --- a/src/lv_objx/lv_label.c +++ b/src/lv_objx/lv_label.c @@ -831,10 +831,11 @@ bool lv_label_is_char_under_pos(const lv_obj_t * label, lv_point_t * pos) uint8_t letter_height = lv_font_get_line_height(font); lv_coord_t y = 0; lv_txt_flag_t flag = LV_TXT_FLAG_NONE; + lv_label_align_t align = lv_label_get_align(label); if(ext->recolor != 0) flag |= LV_TXT_FLAG_RECOLOR; if(ext->expand != 0) flag |= LV_TXT_FLAG_EXPAND; - if(ext->align == LV_LABEL_ALIGN_CENTER) flag |= LV_TXT_FLAG_CENTER; + if(align == LV_LABEL_ALIGN_CENTER) flag |= LV_TXT_FLAG_CENTER; /*If the width will be expanded set the max length to very big */ if(ext->long_mode == LV_LABEL_LONG_EXPAND) { @@ -854,11 +855,16 @@ bool lv_label_is_char_under_pos(const lv_obj_t * label, lv_point_t * pos) /*Calculate the x coordinate*/ lv_coord_t x = 0; lv_coord_t last_x = 0; - if(ext->align == LV_LABEL_ALIGN_CENTER) { + if(align == LV_LABEL_ALIGN_CENTER) { lv_coord_t line_w; line_w = lv_txt_get_width(&txt[line_start], new_line_start - line_start, font, style->text.letter_space, flag); x += lv_obj_get_width(label) / 2 - line_w / 2; } + else if(align == LV_LABEL_ALIGN_RIGHT) { + lv_coord_t line_w; + line_w = lv_txt_get_width(&txt[line_start], new_line_start - line_start, font, style->text.letter_space, flag); + x += lv_obj_get_width(label) - line_w; + } lv_txt_cmd_state_t cmd_state = LV_TXT_CMD_STATE_WAIT; From c4f8d8cd5bbe267cada86d3817d59ec3fd097875 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Mon, 11 Nov 2019 11:10:01 +0100 Subject: [PATCH 45/51] bidi: txt_sel fixes --- src/lv_draw/lv_draw_label.c | 63 ++++++++++++++++++------------------- 1 file changed, 30 insertions(+), 33 deletions(-) diff --git a/src/lv_draw/lv_draw_label.c b/src/lv_draw/lv_draw_label.c index ae6470ab8..4990d3e13 100644 --- a/src/lv_draw/lv_draw_label.c +++ b/src/lv_draw/lv_draw_label.c @@ -56,8 +56,8 @@ static uint8_t hex_char_to_num(char hex); * @param sel_end end index of selected area (`LV_LABEL_TXT_SEL_OFF` if none) */ 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, uint16_t sel_start, uint16_t sel_end, - lv_draw_label_hint_t * hint, lv_bidi_dir_t bidi_dir) + const char * txt, lv_txt_flag_t flag, lv_point_t * offset, uint16_t sel_start, uint16_t sel_end, + lv_draw_label_hint_t * hint, lv_bidi_dir_t bidi_dir) { const lv_font_t * font = style->text.font; lv_coord_t w; @@ -75,7 +75,7 @@ void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_st /*If EXAPND is enabled then not limit the text's width to the object's width*/ lv_point_t p; lv_txt_get_size(&p, txt, style->text.font, style->text.letter_space, style->text.line_space, LV_COORD_MAX, - flag); + flag); w = p.x; } @@ -113,23 +113,6 @@ void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_st pos.y += hint->y; } - if(sel_start != 0xFFFF) { - sel_start = lv_bidi_get_visual_pos(txt, NULL, strlen(txt), bidi_dir, sel_start, NULL); - sel_start = lv_txt_encoded_get_byte_id(txt, sel_start); - } - - if(sel_end != 0xFFFF) { - sel_end = lv_bidi_get_visual_pos(txt, NULL, strlen(txt), bidi_dir, sel_end, NULL); - sel_end = lv_txt_encoded_get_byte_id(txt, sel_end); - } - - if(sel_start > sel_end) { - uint16_t tmp = sel_start; - sel_start = sel_end; - sel_end = tmp; - } - - uint32_t line_end = line_start + lv_txt_get_next_line(&txt[line_start], font, style->text.letter_space, w, flag); @@ -165,6 +148,12 @@ 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; + if(sel_start > sel_end) { + uint16_t tmp = sel_start; + sel_start = sel_end; + sel_end = tmp; + } + cmd_state_t cmd_state = CMD_STATE_WAIT; uint32_t i; uint16_t par_start = 0; @@ -185,16 +174,24 @@ void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_st uint32_t letter; uint32_t letter_next; #if LV_USE_BIDI - char *bidi_txt = lv_draw_get_buf(line_end - line_start + 1); - lv_bidi_process_paragraph(txt + line_start, bidi_txt, line_end - line_start, bidi_dir, NULL, 0); + char *bidi_txt = lv_draw_get_buf(line_end - line_start + 1); + lv_bidi_process_paragraph(txt + line_start, bidi_txt, line_end - line_start, bidi_dir, NULL, 0); #else - const char *bidi_txt = txt + line_start; + 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) { + 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); + } letter = lv_txt_encoded_next(bidi_txt, &i); letter_next = lv_txt_encoded_next(&bidi_txt[i], NULL); + /*Handle the re-color command*/ if((flag & LV_TXT_FLAG_RECOLOR) != 0) { if(letter == (uint32_t)LV_TXT_COLOR_CMD[0]) { @@ -240,7 +237,7 @@ void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_st if(sel_start != 0xFFFF && sel_end != 0xFFFF) { /*Do not draw the rectangle on the character at `sel_start`.*/ - if(i + line_start > sel_start && i + line_start <= sel_end) { + if(logical_char_pos > sel_start && logical_char_pos <= sel_end) { lv_area_t sel_coords; sel_coords.x1 = pos.x; sel_coords.y1 = pos.y; @@ -263,7 +260,7 @@ void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_st /*Align to middle*/ if(flag & LV_TXT_FLAG_CENTER) { line_width = - lv_txt_get_width(&txt[line_start], line_end - line_start, font, style->text.letter_space, flag); + lv_txt_get_width(&txt[line_start], line_end - line_start, font, style->text.letter_space, flag); pos.x += (lv_area_get_width(coords) - line_width) / 2; @@ -271,7 +268,7 @@ void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_st /*Align to the right*/ else if(flag & LV_TXT_FLAG_RIGHT) { line_width = - lv_txt_get_width(&txt[line_start], line_end - line_start, font, style->text.letter_space, flag); + lv_txt_get_width(&txt[line_start], line_end - line_start, font, style->text.letter_space, flag); pos.x += lv_area_get_width(coords) - line_width; } @@ -301,13 +298,13 @@ static uint8_t hex_char_to_num(char hex) if(hex >= 'a') hex -= 'a' - 'A'; /*Convert to upper case*/ switch(hex) { - case 'A': result = 10; break; - case 'B': result = 11; break; - case 'C': result = 12; break; - case 'D': result = 13; break; - case 'E': result = 14; break; - case 'F': result = 15; break; - default: result = 0; break; + case 'A': result = 10; break; + case 'B': result = 11; break; + case 'C': result = 12; break; + case 'D': result = 13; break; + case 'E': result = 14; break; + case 'F': result = 15; break; + default: result = 0; break; } } From 23b58d598de37bf5e6ede52671a5b128b46791d7 Mon Sep 17 00:00:00 2001 From: Amir Gonnen Date: Mon, 11 Nov 2019 22:43:12 +0200 Subject: [PATCH 46/51] bugfixes Prevent infinite loop when reaching end of string on get_next_run Prevent warning about conversion to non const bidi_txt --- src/lv_misc/lv_bidi.c | 2 +- src/lv_objx/lv_label.c | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/lv_misc/lv_bidi.c b/src/lv_misc/lv_bidi.c index 0f1153b52..bde752071 100644 --- a/src/lv_misc/lv_bidi.c +++ b/src/lv_misc/lv_bidi.c @@ -232,7 +232,7 @@ void lv_bidi_process_paragraph(const char * str_in, char * str_out, uint32_t len /*Get and process the runs*/ - while(rd < 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) { diff --git a/src/lv_objx/lv_label.c b/src/lv_objx/lv_label.c index 29fae15b0..bd99c10c8 100644 --- a/src/lv_objx/lv_label.c +++ b/src/lv_objx/lv_label.c @@ -626,7 +626,7 @@ void lv_label_get_letter_pos(const lv_obj_t * label, uint16_t char_id, lv_point_ } } - char *bidi_txt; + const char *bidi_txt; uint16_t visual_byte_pos; #if LV_USE_BIDI /*Handle Bidi*/ @@ -638,7 +638,9 @@ void lv_label_get_letter_pos(const lv_obj_t * label, uint16_t char_id, lv_point_ uint16_t line_char_id = lv_txt_encoded_get_char_id(&txt[line_start], byte_id - line_start); bool is_rtl; - uint16_t visual_char_pos = lv_bidi_get_visual_pos(&txt[line_start], &bidi_txt, new_line_start - line_start, lv_obj_get_base_dir(label), line_char_id, &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); } From f3b88a57cac92e5bedbba4286980a07c30049485 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Tue, 12 Nov 2019 05:38:26 +0100 Subject: [PATCH 47/51] add LV_COLOR_SET/GET_R/G/B It was mainly because when LV_COLOR_16_SWAP = 1 and green is split to green_h and green_l --- src/lv_conf_checker.h | 2 +- src/lv_draw/lv_draw_basic.c | 32 ++------ src/lv_misc/lv_color.h | 141 ++++++++++++++++++++---------------- src/lv_objx/lv_cpicker.c | 8 +- 4 files changed, 90 insertions(+), 93 deletions(-) diff --git a/src/lv_conf_checker.h b/src/lv_conf_checker.h index a855707b4..a6ad94c81 100644 --- a/src/lv_conf_checker.h +++ b/src/lv_conf_checker.h @@ -475,7 +475,7 @@ /* If a character is at least this long, will break wherever "prettiest" */ #ifndef LV_TXT_LINE_BREAK_LONG_LEN -#define LV_TXT_LINE_BREAK_LONG_LEN 12 +#define LV_TXT_LINE_BREAK_LONG_LEN 120 #endif /* Minimum number of characters of a word to put on a line before a break */ diff --git a/src/lv_draw/lv_draw_basic.c b/src/lv_draw/lv_draw_basic.c index f00a30b65..d15429c7b 100644 --- a/src/lv_draw/lv_draw_basic.c +++ b/src/lv_draw/lv_draw_basic.c @@ -343,11 +343,7 @@ void lv_draw_letter(const lv_point_t * pos_p, const lv_area_t * mask_p, const lv #endif uint8_t font_rgb[3]; -#if LV_COLOR_16_SWAP == 0 - uint8_t txt_rgb[3] = {color.ch.red, color.ch.green, color.ch.blue}; -#else - uint8_t txt_rgb[3] = {color.ch.red, (color.ch.green_h << 3) + color.ch.green_l, color.ch.blue}; -#endif + uint8_t txt_rgb[3] = {LV_COLOR_GET_R(color), LV_COLOR_GET_G(color), LV_COLOR_GET_B(color)}; for(row = row_start; row < row_end; row++) { bitmask = bitmask_init >> col_bit; @@ -407,30 +403,16 @@ void lv_draw_letter(const lv_point_t * pos_p, const lv_area_t * mask_p, const lv res_color = *vdb_buf_tmp; } else { -#if LV_COLOR_16_SWAP == 0 - uint8_t bg_rgb[3] = {vdb_buf_tmp->ch.red, vdb_buf_tmp->ch.green, vdb_buf_tmp->ch.blue}; -#else - uint8_t bg_rgb[3] = {vdb_buf_tmp->ch.red, - (vdb_buf_tmp->ch.green_h << 3) + vdb_buf_tmp->ch.green_l, - vdb_buf_tmp->ch.blue}; -#endif + uint8_t bg_rgb[3] = {LV_COLOR_GET_R(*vdb_buf_tmp), LV_COLOR_GET_G(*vdb_buf_tmp), LV_COLOR_GET_B(*vdb_buf_tmp)}; #if LV_SUBPX_BGR - res_color.ch.blue = (uint16_t)((uint16_t)txt_rgb[0] * font_rgb[0] + (bg_rgb[2] * (255 - font_rgb[0]))) >> 8; - res_color.ch.red = (uint16_t)((uint16_t)txt_rgb[2] * font_rgb[2] + (bg_rgb[0] * (255 - font_rgb[2]))) >> 8; + LV_COLOR_SET_B(res_color, (uint16_t)((uint16_t)txt_rgb[0] * font_rgb[0] + (bg_rgb[2] * (255 - font_rgb[0]))) >> 8); + LV_COLOR_SET_R(res_color, (uint16_t)((uint16_t)txt_rgb[2] * font_rgb[2] + (bg_rgb[0] * (255 - font_rgb[2]))) >> 8); #else - res_color.ch.red = (uint16_t)((uint16_t)txt_rgb[0] * font_rgb[0] + (bg_rgb[0] * (255 - font_rgb[0]))) >> 8; - res_color.ch.blue = (uint16_t)((uint16_t)txt_rgb[2] * font_rgb[2] + (bg_rgb[2] * (255 - font_rgb[2]))) >> 8; + LV_COLOR_SET_R(res_color, (uint16_t)((uint16_t)txt_rgb[0] * font_rgb[0] + (bg_rgb[0] * (255 - font_rgb[0]))) >> 8); + LV_COLOR_SET_B(res_color, (uint16_t)((uint16_t)txt_rgb[2] * font_rgb[2] + (bg_rgb[2] * (255 - font_rgb[2]))) >> 8); #endif - -#if LV_COLOR_16_SWAP == 0 - res_color.ch.green = (uint16_t)((uint16_t)txt_rgb[1] * font_rgb[1] + (bg_rgb[1] * (255 - font_rgb[1]))) >> 8; -#else - uint8_t green = (uint16_t)((uint16_t)txt_rgb[1] * font_rgb[1] + (bg_rgb[1] * (255 - font_rgb[1]))) >> 8; - res_color.ch.green_h = green >> 3; - res_color.ch.green_l = green & 0x7; -#endif - + LV_COLOR_SET_G(res_color, (uint16_t)((uint16_t)txt_rgb[1] * font_rgb[1] + (bg_rgb[1] * (255 - font_rgb[1]))) >> 8); } if(scr_transp == false) { vdb_buf_tmp->full = res_color.full; diff --git a/src/lv_misc/lv_color.h b/src/lv_misc/lv_color.h index 95542afb6..ddc4a7436 100644 --- a/src/lv_misc/lv_color.h +++ b/src/lv_misc/lv_color.h @@ -90,6 +90,55 @@ enum { #error "Invalid LV_COLOR_DEPTH in lv_conf.h! Set it to 1, 8, 16 or 32!" #endif +/*----------------------- + * Macros to set/get values + * of the color channels + *-----------------------*/ +#if LV_COLOR_DEPTH == 1 +# define LV_COLOR_SET_R(c, v) (c).ch.red = v & 0x1; +# define LV_COLOR_SET_G(c, v) (c).ch.green = v & 0x1; +# define LV_COLOR_SET_B(c, v) (c).ch.blue = v & 0x1; + +# define LV_COLOR_GET_R(c) (c).ch.red +# define LV_COLOR_GET_G(c) (c).ch.green +# define LV_COLOR_GET_B(c) (c).ch.blue + +#elif LV_COLOR_DEPTH == 8 +# define LV_COLOR_SET_R(c, v) (c).ch.red = v & 0x7; +# define LV_COLOR_SET_G(c, v) (c).ch.green = v & 0x7; +# define LV_COLOR_SET_B(c, v) c(c).ch.blue = v & 0x3; + +# define LV_COLOR_GET_R(c) (c).ch.red +# define LV_COLOR_GET_G(c) (c).ch.green +# define LV_COLOR_GET_B(c) (c).ch.blue + +#elif LV_COLOR_DEPTH == 16 +# define LV_COLOR_SET_R(c, v) (c).ch.red = v & 0x1F; +# if LV_COLOR_16_SWAP == 0 +# define LV_COLOR_SET_G(c, v) (c).ch.green = v & 0x3F; +# else +# define LV_COLOR_SET_G(c, v) {(c).ch.green_h = ((v) >> 3) & 0x3; (c).ch.green_l = (v) & 0x3;} +# endif +# define LV_COLOR_SET_B(c, v) (c).ch.blue= v & 0x1F; + +# define LV_COLOR_GET_R(c) (c).ch.red +# if LV_COLOR_16_SWAP == 0 +# define LV_COLOR_GET_G(c) (c).ch.green +# else +# define LV_COLOR_GET_G(c) (((c).ch.green_h << 3) + (c).ch.green_l) +# endif +# define LV_COLOR_GET_B(c) (c).ch.blue + +#elif LV_COLOR_DEPTH == 32 +# define LV_COLOR_SET_R(c, v) (c).ch.red = v & 0xFF; +# define LV_COLOR_SET_G(c, v) (c).ch.green = v & 0xFF; +# define LV_COLOR_SET_B(c, v) (c).ch.blue = v & 0xFF; + +# define LV_COLOR_GET_R(c) (c).ch.red +# define LV_COLOR_GET_G(c) (c).ch.green +# define LV_COLOR_GET_B(c) (c).ch.blue +#endif + /********************** * TYPEDEFS **********************/ @@ -194,24 +243,19 @@ static inline uint8_t lv_color_to1(lv_color_t color) #if LV_COLOR_DEPTH == 1 return color.full; #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; } else { return 0; } #elif LV_COLOR_DEPTH == 16 -#if LV_COLOR_16_SWAP == 0 - if((color.ch.red & 0x10) || (color.ch.green & 0x20) || (color.ch.blue & 0x10)) { + if((LV_COLOR_GET_R(color) & 0x10) || (LV_COLOR_GET_G(color) & 0x20) || (LV_COLOR_GET_B(color) & 0x10)) { return 1; -#else - if((color.ch.red & 0x10) || (color.ch.green_h & 0x20) || (color.ch.blue & 0x10)) { - return 1; -#endif } else { return 0; } #elif LV_COLOR_DEPTH == 32 - if((color.ch.red & 0x80) || (color.ch.green & 0x80) || (color.ch.blue & 0x80)) { + if((cLV_COLOR_GET_R(color) & 0x80) || (LV_COLOR_GET_G(color) & 0x80) || (LV_COLOR_GET_B(color) & 0x80)) { return 1; } else { return 0; @@ -229,25 +273,16 @@ static inline uint8_t lv_color_to8(lv_color_t color) #elif LV_COLOR_DEPTH == 8 return color.full; #elif LV_COLOR_DEPTH == 16 - -#if LV_COLOR_16_SWAP == 0 lv_color8_t ret; - ret.ch.red = color.ch.red >> 2; /* 5 - 3 = 2*/ - ret.ch.green = color.ch.green >> 3; /* 6 - 3 = 3*/ - ret.ch.blue = color.ch.blue >> 3; /* 5 - 2 = 3*/ + ret.ch.red = LV_COLOR_GET_R(color) >> 2; /* 5 - 3 = 2*/ + ret.ch.green = LV_COLOR_GET_G(color) >> 3; /* 6 - 3 = 3*/ + ret.ch.blue = LV_COLOR_GET_B(color) >> 3; /* 5 - 2 = 3*/ 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 lv_color8_t ret; - ret.ch.red = color.ch.red >> 5; /* 8 - 3 = 5*/ - ret.ch.green = color.ch.green >> 5; /* 8 - 3 = 5*/ - ret.ch.blue = color.ch.blue >> 6; /* 8 - 2 = 6*/ + ret.ch.red = LV_COLOR_GET_R(color) >> 5; /* 8 - 3 = 5*/ + ret.ch.green = LV_COLOR_GET_G(color) >> 5; /* 8 - 3 = 5*/ + ret.ch.blue = LV_COLOR_GET_B(color) >> 6; /* 8 - 2 = 6*/ return ret.full; #endif } @@ -261,32 +296,29 @@ static inline uint16_t lv_color_to16(lv_color_t color) return 0xFFFF; #elif LV_COLOR_DEPTH == 8 lv_color16_t ret; + ret.ch.red = LV_COLOR_GET_R(color) * 4; /*(2^5 - 1)/(2^3 - 1) = 31/7 = 4*/ #if LV_COLOR_16_SWAP == 0 - ret.ch.red = color.ch.red * 4; /*(2^5 - 1)/(2^3 - 1) = 31/7 = 4*/ - 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*/ + ret.ch.green = LV_COLOR_GET_G(color) * 9; /*(2^6 - 1)/(2^3 - 1) = 63/7 = 9*/ #else - ret.red = color.ch.red * 4; - 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; + ret.ch.green_h = (LV_COLOR_GET_G(color) * 9) >> 3; /*(2^6 - 1)/(2^3 - 1) = 63/7 = 9*/ + ret.ch.green_l = (LV_COLOR_GET_G(color) * 9) & 0x7; #endif + ret.ch.blue = LV_COLOR_GET_B(color) * 10; /*(2^5 - 1)/(2^2 - 1) = 31/3 = 10*/ return ret.full; #elif LV_COLOR_DEPTH == 16 return color.full; #elif LV_COLOR_DEPTH == 32 lv_color16_t ret; + ret.ch.red = LV_COLOR_GET_R(color) >> 3; /* 8 - 5 = 3*/ + #if LV_COLOR_16_SWAP == 0 - ret.ch.red = color.ch.red >> 3; /* 8 - 5 = 3*/ - ret.ch.green = color.ch.green >> 2; /* 8 - 6 = 2*/ - ret.ch.blue = color.ch.blue >> 3; /* 8 - 5 = 3*/ + ret.ch.green = LV_COLOR_GET_G(color) >> 2; /* 8 - 6 = 2*/ #else - ret.ch.red = color.ch.red >> 3; - 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; + ret.ch.green_h = (LV_COLOR_GET_G(color) >> 5; /*(2^6 - 1)/(2^3 - 1) = 63/7 = 9*/ + ret.ch.green_l = (LV_COLOR_GET_G(color) >> 2) & 0x7; #endif + ret.ch.green = LV_COLOR_GET_G(color) >> 2; /* 8 - 6 = 2*/ + ret.ch.blue = LV_COLOR_GET_B(color) >> 3; /* 8 - 5 = 3*/ return ret.full; #endif } @@ -300,9 +332,9 @@ static inline uint32_t lv_color_to32(lv_color_t color) return 0xFFFFFFFF; #elif LV_COLOR_DEPTH == 8 lv_color32_t ret; - ret.ch.red = color.ch.red * 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*/ - ret.ch.blue = color.ch.blue * 85; /*(2^8 - 1)/(2^2 - 1) = 255/3 = 85*/ + ret.ch.red = LV_COLOR_GET_R(color) * 36; /*(2^8 - 1)/(2^3 - 1) = 255/7 = 36*/ + ret.ch.green = LV_COLOR_GET_G(color) * 36; /*(2^8 - 1)/(2^3 - 1) = 255/7 = 36*/ + ret.ch.blue = LV_COLOR_GET_B(color) * 85; /*(2^8 - 1)/(2^2 - 1) = 255/3 = 85*/ ret.ch.alpha = 0xFF; return ret.full; #elif LV_COLOR_DEPTH == 16 @@ -335,13 +367,9 @@ static inline uint32_t lv_color_to32(lv_color_t color) * 6 259 3 0 255 */ lv_color32_t ret; - ret.ch.red = ( color.ch.red * 263 + 7 ) >> 5; -#if LV_COLOR_16_SWAP == 0 - ret.ch.green = ( color.ch.green * 259 + 3 ) >> 6; -#else - 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.red = (LV_COLOR_GET_R(color) * 263 + 7 ) >> 5; + ret.ch.green = (LV_COLOR_GET_G(color) * 259 + 3 ) >> 6; + ret.ch.blue = (LV_COLOR_GET_B(color) * 263 + 7 ) >> 5; ret.ch.alpha = 0xFF; return ret.full; #elif LV_COLOR_DEPTH == 32 @@ -354,18 +382,9 @@ static inline lv_color_t lv_color_mix(lv_color_t c1, lv_color_t c2, uint8_t mix) lv_color_t ret; #if LV_COLOR_DEPTH != 1 /*LV_COLOR_DEPTH == 8, 16 or 32*/ - ret.ch.red = (uint16_t)((uint16_t)c1.ch.red * mix + (c2.ch.red * (255 - mix))) >> 8; -#if LV_COLOR_DEPTH == 16 && LV_COLOR_16_SWAP - /*If swapped Green is in 2 parts*/ - uint16_t g_1 = (c1.ch.green_h << 3) + c1.ch.green_l; - 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 * (255 - 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 * (255 - mix))) >> 8; -#endif - ret.ch.blue = (uint16_t)((uint16_t)c1.ch.blue * mix + (c2.ch.blue * (255 - 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); + LV_COLOR_SET_G(ret, (uint16_t)((uint16_t) LV_COLOR_GET_G(c1) * mix + LV_COLOR_GET_G(c2) * (255 - mix)) >> 8); + LV_COLOR_SET_B(ret, (uint16_t)((uint16_t) LV_COLOR_GET_B(c1) * mix + LV_COLOR_GET_B(c2) * (255 - mix)) >> 8); #if LV_COLOR_DEPTH == 32 ret.ch.alpha = 0xFF; #endif @@ -386,7 +405,7 @@ static inline uint8_t lv_color_brightness(lv_color_t color) { lv_color32_t c32; c32.full = lv_color_to32(color); - uint16_t bright = 3 * c32.ch.red + c32.ch.blue + 4 * c32.ch.green; + uint16_t bright = 3 * LV_COLOR_GET_R(c32) + LV_COLOR_GET_B(c32) + 4 * LV_COLOR_GET_G(c32); return (uint16_t)bright >> 3; } diff --git a/src/lv_objx/lv_cpicker.c b/src/lv_objx/lv_cpicker.c index 73197d374..383607171 100644 --- a/src/lv_objx/lv_cpicker.c +++ b/src/lv_objx/lv_cpicker.c @@ -275,12 +275,8 @@ bool lv_cpicker_set_hsv(lv_obj_t * cpicker, lv_color_hsv_t hsv) */ bool lv_cpicker_set_color(lv_obj_t * cpicker, lv_color_t color) { -#if LV_COLOR_DEPTH == 16 && LV_COLOR_16_SWAP != 0 - uint8_t green = (color.ch.green_h << 3) + color.ch.green_l; - return lv_cpicker_set_hsv(cpicker, lv_color_rgb_to_hsv(color.ch.red, green, color.ch.blue)); -#else - return lv_cpicker_set_hsv(cpicker, lv_color_rgb_to_hsv(color.ch.red, color.ch.green, color.ch.blue)); -#endif + 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))); } /** From 49e105917ecf2504024c6cc80b4bd84e53f16bf4 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Tue, 12 Nov 2019 06:39:26 +0100 Subject: [PATCH 48/51] add LV_COLOR_SET/GET for every color depth configuration --- src/lv_misc/lv_color.h | 208 +++++++++++++++++++++++++---------------- 1 file changed, 127 insertions(+), 81 deletions(-) diff --git a/src/lv_misc/lv_color.h b/src/lv_misc/lv_color.h index ddc4a7436..d45aa0a61 100644 --- a/src/lv_misc/lv_color.h +++ b/src/lv_misc/lv_color.h @@ -90,53 +90,108 @@ enum { #error "Invalid LV_COLOR_DEPTH in lv_conf.h! Set it to 1, 8, 16 or 32!" #endif -/*----------------------- - * Macros to set/get values - * of the color channels - *-----------------------*/ -#if LV_COLOR_DEPTH == 1 -# define LV_COLOR_SET_R(c, v) (c).ch.red = v & 0x1; -# define LV_COLOR_SET_G(c, v) (c).ch.green = v & 0x1; -# define LV_COLOR_SET_B(c, v) (c).ch.blue = v & 0x1; +/*--------------------------------------- + * Macros for all existing color depths + * to set/get values of the color channels + *------------------------------------------*/ +# define LV_COLOR_SET_R1(c, v) (c).ch.red = (v) & 0x1; +# define LV_COLOR_SET_G1(c, v) (c).ch.green = (v) & 0x1; +# define LV_COLOR_SET_B1(c, v) (c).ch.blue = (v) & 0x1; +# define LV_COLOR_SET_A1(c, v) -# define LV_COLOR_GET_R(c) (c).ch.red -# define LV_COLOR_GET_G(c) (c).ch.green -# define LV_COLOR_GET_B(c) (c).ch.blue +# 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 = (v) & 0x7; +# define LV_COLOR_SET_G8(c, v) (c).ch.green = (v) & 0x7; +# define LV_COLOR_SET_B8(c, v) (c).ch.blue = (v) & 0x3; +# define LV_COLOR_SET_A8(c, v) + +# 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 = (v) & 0x1F; +# define LV_COLOR_SET_G16(c, v) (c).ch.green = (v) & 0x3F; +# define LV_COLOR_SET_G16_SWAP(c, v) {(c).ch.green_h = ((v) >> 3) & 0x7; (c).ch.green_l = (v) & 0x7;} +# define LV_COLOR_SET_B16(c, v) (c).ch.blue = (v) & 0x1F; +# define LV_COLOR_SET_A16(c, v) + +# 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 = (v) & 0xFF; +# define LV_COLOR_SET_G32(c, v) (c).ch.green = (v) & 0xFF; +# define LV_COLOR_SET_B32(c, v) (c).ch.blue = (v) & 0xFF; +# define LV_COLOR_SET_A32(c, v) (c).ch.alpha = (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) (c).ch.red = v & 0x7; -# define LV_COLOR_SET_G(c, v) (c).ch.green = v & 0x7; -# define LV_COLOR_SET_B(c, v) c(c).ch.blue = v & 0x3; +# 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) (c).ch.red -# define LV_COLOR_GET_G(c) (c).ch.green -# define LV_COLOR_GET_B(c) (c).ch.blue +# 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) (c).ch.red = v & 0x1F; +# 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) (c).ch.green = v & 0x3F; +# define LV_COLOR_SET_G(c, v) LV_COLOR_SET_G16(c,v) # else -# define LV_COLOR_SET_G(c, v) {(c).ch.green_h = ((v) >> 3) & 0x3; (c).ch.green_l = (v) & 0x3;} +# define LV_COLOR_SET_G(c, v) LV_COLOR_SET_G16_SWAP(c,v) # endif -# define LV_COLOR_SET_B(c, v) (c).ch.blue= v & 0x1F; +# 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) (c).ch.red +# define LV_COLOR_GET_R(c) LV_COLOR_GET_R16(c) # if LV_COLOR_16_SWAP == 0 -# define LV_COLOR_GET_G(c) (c).ch.green +# define LV_COLOR_GET_G(c) LV_COLOR_GET_G16(c) # else -# define LV_COLOR_GET_G(c) (((c).ch.green_h << 3) + (c).ch.green_l) +# define LV_COLOR_GET_G(c) LV_COLOR_GET_G16_SWAP(c) # endif -# define LV_COLOR_GET_B(c) (c).ch.blue +# 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) (c).ch.red = v & 0xFF; -# define LV_COLOR_SET_G(c, v) (c).ch.green = v & 0xFF; -# define LV_COLOR_SET_B(c, v) (c).ch.blue = v & 0xFF; +# 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) (c).ch.red -# define LV_COLOR_GET_G(c) (c).ch.green -# define LV_COLOR_GET_B(c) (c).ch.blue +# 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 /********************** @@ -255,7 +310,7 @@ static inline uint8_t lv_color_to1(lv_color_t color) return 0; } #elif LV_COLOR_DEPTH == 32 - if((cLV_COLOR_GET_R(color) & 0x80) || (LV_COLOR_GET_G(color) & 0x80) || (LV_COLOR_GET_B(color) & 0x80)) { + if((LV_COLOR_GET_R(color) & 0x80) || (LV_COLOR_GET_G(color) & 0x80) || (LV_COLOR_GET_B(color) & 0x80)) { return 1; } else { return 0; @@ -274,21 +329,22 @@ static inline uint8_t lv_color_to8(lv_color_t color) return color.full; #elif LV_COLOR_DEPTH == 16 lv_color8_t ret; - ret.ch.red = LV_COLOR_GET_R(color) >> 2; /* 5 - 3 = 2*/ - ret.ch.green = LV_COLOR_GET_G(color) >> 3; /* 6 - 3 = 3*/ - ret.ch.blue = LV_COLOR_GET_B(color) >> 3; /* 5 - 2 = 3*/ + LV_COLOR_SET_R8(ret, LV_COLOR_GET_R(color) >> 2); /* 5 - 3 = 2*/ + LV_COLOR_SET_G8(ret, LV_COLOR_GET_G(color) >> 3); /* 6 - 3 = 3*/ + LV_COLOR_SET_B8(ret, LV_COLOR_GET_B(color) >> 3); /* 5 - 2 = 3*/ return ret.full; #elif LV_COLOR_DEPTH == 32 lv_color8_t ret; - ret.ch.red = LV_COLOR_GET_R(color) >> 5; /* 8 - 3 = 5*/ - ret.ch.green = LV_COLOR_GET_G(color) >> 5; /* 8 - 3 = 5*/ - ret.ch.blue = LV_COLOR_GET_B(color) >> 6; /* 8 - 2 = 6*/ + LV_COLOR_SET_R8(ret, LV_COLOR_GET_R(color) >> 5); /* 8 - 3 = 5*/ + LV_COLOR_SET_G8(ret, LV_COLOR_GET_G(color) >> 5); /* 8 - 3 = 5*/ + LV_COLOR_SET_B8(ret, LV_COLOR_GET_B(color) >> 6); /* 8 - 2 = 6*/ return ret.full; #endif } static inline uint16_t lv_color_to16(lv_color_t color) { + #if LV_COLOR_DEPTH == 1 if(color.full == 0) return 0; @@ -296,31 +352,30 @@ static inline uint16_t lv_color_to16(lv_color_t color) return 0xFFFF; #elif LV_COLOR_DEPTH == 8 lv_color16_t ret; - ret.ch.red = LV_COLOR_GET_R(color) * 4; /*(2^5 - 1)/(2^3 - 1) = 31/7 = 4*/ + 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 - ret.ch.green = LV_COLOR_GET_G(color) * 9; /*(2^6 - 1)/(2^3 - 1) = 63/7 = 9*/ + LV_COLOR_SET_G16(ret, LV_COLOR_GET_G(color) * 9); /*(2^6 - 1)/(2^3 - 1) = 63/7 = 9*/ #else - ret.ch.green_h = (LV_COLOR_GET_G(color) * 9) >> 3; /*(2^6 - 1)/(2^3 - 1) = 63/7 = 9*/ - ret.ch.green_l = (LV_COLOR_GET_G(color) * 9) & 0x7; + LV_COLOR_SET_G16_SWAP(ret, (LV_COLOR_GET_G(color) * 9)); /*(2^6 - 1)/(2^3 - 1) = 63/7 = 9*/ #endif - ret.ch.blue = LV_COLOR_GET_B(color) * 10; /*(2^5 - 1)/(2^2 - 1) = 31/3 = 10*/ + LV_COLOR_SET_B16(ret, LV_COLOR_GET_B(color) * 10); /*(2^5 - 1)/(2^2 - 1) = 31/3 = 10*/ return ret.full; #elif LV_COLOR_DEPTH == 16 return color.full; #elif LV_COLOR_DEPTH == 32 lv_color16_t ret; - ret.ch.red = LV_COLOR_GET_R(color) >> 3; /* 8 - 5 = 3*/ + LV_COLOR_SET_R16(ret, LV_COLOR_GET_R(color) >> 3); /* 8 - 5 = 3*/ #if LV_COLOR_16_SWAP == 0 - ret.ch.green = LV_COLOR_GET_G(color) >> 2; /* 8 - 6 = 2*/ + LV_COLOR_SET_G16(ret, LV_COLOR_GET_G(color) >> 2); /* 8 - 6 = 2*/ #else - ret.ch.green_h = (LV_COLOR_GET_G(color) >> 5; /*(2^6 - 1)/(2^3 - 1) = 63/7 = 9*/ - ret.ch.green_l = (LV_COLOR_GET_G(color) >> 2) & 0x7; + 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*/ #endif - ret.ch.green = LV_COLOR_GET_G(color) >> 2; /* 8 - 6 = 2*/ - ret.ch.blue = LV_COLOR_GET_B(color) >> 3; /* 8 - 5 = 3*/ + LV_COLOR_SET_B16(ret, LV_COLOR_GET_B(color) >> 3); /* 8 - 5 = 3*/ return ret.full; #endif + + return 0; } static inline uint32_t lv_color_to32(lv_color_t color) @@ -332,10 +387,10 @@ static inline uint32_t lv_color_to32(lv_color_t color) return 0xFFFFFFFF; #elif LV_COLOR_DEPTH == 8 lv_color32_t ret; - ret.ch.red = LV_COLOR_GET_R(color) * 36; /*(2^8 - 1)/(2^3 - 1) = 255/7 = 36*/ - ret.ch.green = LV_COLOR_GET_G(color) * 36; /*(2^8 - 1)/(2^3 - 1) = 255/7 = 36*/ - ret.ch.blue = LV_COLOR_GET_B(color) * 85; /*(2^8 - 1)/(2^2 - 1) = 255/3 = 85*/ - ret.ch.alpha = 0xFF; + LV_COLOR_SET_R32(ret, LV_COLOR_GET_R(color) * 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*/ + LV_COLOR_SET_B32(ret, LV_COLOR_GET_B(color) * 85); /*(2^8 - 1)/(2^2 - 1) = 255/3 = 85*/ + LV_COLOR_SET_A32(color, 0xFF); return ret.full; #elif LV_COLOR_DEPTH == 16 /** @@ -367,10 +422,10 @@ static inline uint32_t lv_color_to32(lv_color_t color) * 6 259 3 0 255 */ lv_color32_t ret; - ret.ch.red = (LV_COLOR_GET_R(color) * 263 + 7 ) >> 5; - ret.ch.green = (LV_COLOR_GET_G(color) * 259 + 3 ) >> 6; - ret.ch.blue = (LV_COLOR_GET_B(color) * 263 + 7 ) >> 5; - ret.ch.alpha = 0xFF; + LV_COLOR_SET_R32(ret, (LV_COLOR_GET_R(color) * 263 + 7 ) >> 5); + LV_COLOR_SET_G32(ret, (LV_COLOR_GET_G(color) * 259 + 3 ) >> 6); + LV_COLOR_SET_B32(ret, (LV_COLOR_GET_B(color) * 263 + 7 ) >> 5); + LV_COLOR_SET_A32(ret, 0xFF); return ret.full; #elif LV_COLOR_DEPTH == 32 return color.full; @@ -385,9 +440,7 @@ static inline lv_color_t lv_color_mix(lv_color_t c1, lv_color_t c2, uint8_t mix) LV_COLOR_SET_R(ret, (uint16_t)((uint16_t) LV_COLOR_GET_R(c1) * mix + LV_COLOR_GET_R(c2) * (255 - mix)) >> 8); LV_COLOR_SET_G(ret, (uint16_t)((uint16_t) LV_COLOR_GET_G(c1) * mix + LV_COLOR_GET_G(c2) * (255 - mix)) >> 8); LV_COLOR_SET_B(ret, (uint16_t)((uint16_t) LV_COLOR_GET_B(c1) * mix + LV_COLOR_GET_B(c2) * (255 - mix)) >> 8); -#if LV_COLOR_DEPTH == 32 - ret.ch.alpha = 0xFF; -#endif + LV_COLOR_SET_A(ret, 0xFF); #else /*LV_COLOR_DEPTH == 1*/ ret.full = mix > LV_OPA_50 ? c1.full : c2.full; @@ -405,7 +458,7 @@ static inline uint8_t lv_color_brightness(lv_color_t color) { lv_color32_t c32; c32.full = lv_color_to32(color); - uint16_t bright = 3 * LV_COLOR_GET_R(c32) + LV_COLOR_GET_B(c32) + 4 * LV_COLOR_GET_G(c32); + uint16_t bright = 3 * LV_COLOR_GET_R32(c32) + LV_COLOR_GET_B32(c32) + 4 * LV_COLOR_GET_G32(c32); return (uint16_t)bright >> 3; } @@ -423,43 +476,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) { lv_color_t color; - color.ch.blue = b8 >> 6; - color.ch.green = g8 >> 5; - color.ch.red = r8 >> 5; + LV_COLOR_SET_B(color, b8 >> 6); + LV_COLOR_SET_G(color, g8 >> 5); + LV_COLOR_SET_R(color, r8 >> 5); + LV_COLOR_SET_A(color, 0xFF); return color; } #elif LV_COLOR_DEPTH == 16 #if LV_COLOR_16_SWAP == 0 #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 #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) { lv_color_t color; - color.ch.green_h = (uint16_t)(g8 >> 5); - color.ch.red = (uint16_t)(r8 >> 3); - color.ch.blue = (uint16_t)(b8 >> 3); - color.ch.green_l = (uint16_t)((g8 >> 2) & 0x7); + LV_COLOR_SET_B(color, b8 >> 3); + LV_COLOR_SET_G(color, g8 >> 2); + LV_COLOR_SET_R(color, r8 >> 3); + LV_COLOR_SET_A(color, 0xFF); return color; } -#endif #elif LV_COLOR_DEPTH == 32 #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) { lv_color_t color; - color.ch.blue = b8; - color.ch.green = g8; - color.ch.red = r8; - color.ch.alpha = 0xff; + LV_COLOR_SET_B(color, b8); + LV_COLOR_SET_G(color, g8); + LV_COLOR_SET_R(color, r8); + LV_COLOR_SET_A(color, 0xFF); return color; } #endif From 3cd2120b60983a6cc6c34c55910d7115cdfe126f Mon Sep 17 00:00:00 2001 From: Mattia Maldini Date: Tue, 12 Nov 2019 13:07:26 +0100 Subject: [PATCH 49/51] Added rotation feature to the lmeter --- src/lv_objx/lv_lmeter.c | 17 ++++++++++++++++- src/lv_objx/lv_lmeter.h | 8 ++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/lv_objx/lv_lmeter.c b/src/lv_objx/lv_lmeter.c index 78f7a8e61..b77211009 100644 --- a/src/lv_objx/lv_lmeter.c +++ b/src/lv_objx/lv_lmeter.c @@ -168,6 +168,21 @@ void lv_lmeter_set_scale(lv_obj_t * lmeter, uint16_t angle, uint8_t line_cnt) lv_obj_invalidate(lmeter); } +/** + * 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_rotation(lv_obj_t * lmeter, uint16_t angle) +{ + lv_lmeter_ext_t * ext = lv_obj_get_ext_attr(lmeter); + if(ext->rotation == angle) return; + + ext->rotation = angle; + + lv_obj_invalidate(lmeter); +} + /*===================== * Getter functions *====================*/ @@ -268,7 +283,7 @@ static bool lv_lmeter_design(lv_obj_t * lmeter, const lv_area_t * mask, lv_desig 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; - int16_t angle_ofs = 90 + (360 - ext->scale_angle) / 2; + int16_t angle_ofs = ext->rotation + 90 + (360 - ext->scale_angle) / 2; int16_t level = (int32_t)((int32_t)(ext->cur_value - ext->min_value) * ext->line_cnt) / (ext->max_value - ext->min_value); uint8_t i; diff --git a/src/lv_objx/lv_lmeter.h b/src/lv_objx/lv_lmeter.h index e1a70a64f..ea7c08236 100644 --- a/src/lv_objx/lv_lmeter.h +++ b/src/lv_objx/lv_lmeter.h @@ -36,6 +36,7 @@ typedef struct /*No inherited ext.*/ /*Ext. of ancestor*/ /*New data for this type */ uint16_t scale_angle; /*Angle of the scale in deg. (0..360)*/ + uint16_t rotation; uint8_t line_cnt; /*Count of lines */ int16_t cur_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); +/** + * 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_rotation(lv_obj_t * lmeter, uint16_t angle); + /** * Set the styles of a line meter * @param lmeter pointer to a line meter object From b7c3732da73b5a0dd6c5dd33ef65f734d171d5cb Mon Sep 17 00:00:00 2001 From: Mattia Maldini Date: Tue, 12 Nov 2019 16:14:18 +0100 Subject: [PATCH 50/51] Different wording --- src/lv_objx/lv_lmeter.c | 12 ++++++------ src/lv_objx/lv_lmeter.h | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/lv_objx/lv_lmeter.c b/src/lv_objx/lv_lmeter.c index b77211009..6e23f24ae 100644 --- a/src/lv_objx/lv_lmeter.c +++ b/src/lv_objx/lv_lmeter.c @@ -169,16 +169,16 @@ void lv_lmeter_set_scale(lv_obj_t * lmeter, uint16_t angle, uint8_t line_cnt) } /** - * Set the rotation settings of a line meter + * Set the angle settings of a line meter * @param lmeter pointer to a line meter object - * @param angle angle of rotation (relative to the northen axis) + * @param angle angle where the meter will be facing (with its center) */ -void lv_lmeter_set_rotation(lv_obj_t * lmeter, uint16_t angle) +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->rotation == angle) return; + if(ext->angle == angle) return; - ext->rotation = angle; + ext->angle = angle; lv_obj_invalidate(lmeter); } @@ -283,7 +283,7 @@ static bool lv_lmeter_design(lv_obj_t * lmeter, const lv_area_t * mask, lv_desig 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; - int16_t angle_ofs = ext->rotation + 90 + (360 - ext->scale_angle) / 2; + int16_t angle_ofs = ext->angle + 90 + (360 - ext->scale_angle) / 2; int16_t level = (int32_t)((int32_t)(ext->cur_value - ext->min_value) * ext->line_cnt) / (ext->max_value - ext->min_value); uint8_t i; diff --git a/src/lv_objx/lv_lmeter.h b/src/lv_objx/lv_lmeter.h index ea7c08236..49d662819 100644 --- a/src/lv_objx/lv_lmeter.h +++ b/src/lv_objx/lv_lmeter.h @@ -36,7 +36,7 @@ typedef struct /*No inherited ext.*/ /*Ext. of ancestor*/ /*New data for this type */ uint16_t scale_angle; /*Angle of the scale in deg. (0..360)*/ - uint16_t rotation; + uint16_t angle; uint8_t line_cnt; /*Count of lines */ int16_t cur_value; int16_t min_value; @@ -94,7 +94,7 @@ void lv_lmeter_set_scale(lv_obj_t * lmeter, uint16_t angle, uint8_t line_cnt); * @param lmeter pointer to a line meter object * @param angle angle of rotation (relative to the northen axis) */ -void lv_lmeter_set_rotation(lv_obj_t * lmeter, uint16_t angle); +void lv_lmeter_set_angle(lv_obj_t * lmeter, uint16_t angle); /** * Set the styles of a line meter From 1e4ce0b14323ff97e5a9c58b7bb1d3a4a4615550 Mon Sep 17 00:00:00 2001 From: Pete Bone Date: Tue, 12 Nov 2019 15:26:35 +0000 Subject: [PATCH 51/51] Dev 6.1 Minor fixes lv_draw_arc.c -> line 218 Removed unsed fast_atan2() function which appears to have been moved to lv_math.c as lv_atan2() function. lv_font_heb_16.c -> line 1 Fixed inconsistent include path. lv_label.c -> line 734 Added (char*) cast to const char* variable 'txt' to silence compiler warning when LV_USE_BIDI is disabled. lv_style.c -> line 93 Removed this line lv_style.c -> line 97 Reverted this line to remove override of LV_FONT_DEFAULT defined in lv_conf.h --- src/lv_core/lv_style.c | 4 +- src/lv_draw/lv_draw_arc.c | 73 ------------------------------------ src/lv_font/lv_font_heb_16.c | 2 +- src/lv_objx/lv_label.c | 2 +- 4 files changed, 4 insertions(+), 77 deletions(-) diff --git a/src/lv_core/lv_style.c b/src/lv_core/lv_style.c index d86f262ef..718fa6b37 100644 --- a/src/lv_core/lv_style.c +++ b/src/lv_core/lv_style.c @@ -90,11 +90,11 @@ void lv_style_init(void) lv_style_scr.body.shadow.color = LV_COLOR_GRAY; lv_style_scr.body.shadow.type = LV_SHADOW_FULL; lv_style_scr.body.shadow.width = 0; - LV_FONT_DECLARE(lv_font_heb_16); + lv_style_scr.text.opa = LV_OPA_COVER; lv_style_scr.text.color = lv_color_make(0x30, 0x30, 0x30); lv_style_scr.text.sel_color = lv_color_make(0x55, 0x96, 0xd8); - lv_style_scr.text.font = &lv_font_heb_16;//LV_FONT_DEFAULT; + lv_style_scr.text.font = LV_FONT_DEFAULT; lv_style_scr.text.letter_space = 0; lv_style_scr.text.line_space = 2; diff --git a/src/lv_draw/lv_draw_arc.c b/src/lv_draw/lv_draw_arc.c index ed4192dfe..e42a67dbf 100644 --- a/src/lv_draw/lv_draw_arc.c +++ b/src/lv_draw/lv_draw_arc.c @@ -215,79 +215,6 @@ void lv_draw_arc(lv_coord_t center_x, lv_coord_t center_y, uint16_t radius, cons } } -static uint16_t fast_atan2(int x, int y) -{ - // Fast XY vector to integer degree algorithm - Jan 2011 www.RomanBlack.com - // Converts any XY values including 0 to a degree value that should be - // within +/- 1 degree of the accurate value without needing - // large slow trig functions like ArcTan() or ArcCos(). - // NOTE! at least one of the X or Y values must be non-zero! - // This is the full version, for all 4 quadrants and will generate - // the angle in integer degrees from 0-360. - // Any values of X and Y are usable including negative values provided - // they are between -1456 and 1456 so the 16bit multiply does not overflow. - - unsigned char negflag; - unsigned char tempdegree; - unsigned char comp; - unsigned int degree; /*this will hold the result*/ - unsigned int ux; - unsigned int uy; - - /*Save the sign flags then remove signs and get XY as unsigned ints*/ - negflag = 0; - if(x < 0) { - negflag += 0x01; /*x flag bit*/ - x = (0 - x); /*is now +*/ - } - ux = x; /*copy to unsigned var before multiply*/ - if(y < 0) { - negflag += 0x02; /*y flag bit*/ - y = (0 - y); /*is now +*/ - } - uy = y; /*copy to unsigned var before multiply*/ - - /*1. Calc the scaled "degrees"*/ - if(ux > uy) { - degree = (uy * 45) / ux; /*degree result will be 0-45 range*/ - negflag += 0x10; /*octant flag bit*/ - } else { - degree = (ux * 45) / uy; /*degree result will be 0-45 range*/ - } - - /*2. Compensate for the 4 degree error curve*/ - comp = 0; - tempdegree = degree; /*use an unsigned char for speed!*/ - if(tempdegree > 22) { /*if top half of range*/ - if(tempdegree <= 44) comp++; - if(tempdegree <= 41) comp++; - if(tempdegree <= 37) comp++; - if(tempdegree <= 32) comp++; /*max is 4 degrees compensated*/ - } else { /*else is lower half of range*/ - if(tempdegree >= 2) comp++; - if(tempdegree >= 6) comp++; - if(tempdegree >= 10) comp++; - if(tempdegree >= 15) comp++; /*max is 4 degrees compensated*/ - } - degree += comp; /*degree is now accurate to +/- 1 degree!*/ - - /*Invert degree if it was X>Y octant, makes 0-45 into 90-45*/ - if(negflag & 0x10) degree = (90 - degree); - - /*3. Degree is now 0-90 range for this quadrant,*/ - /*need to invert it for whichever quadrant it was in*/ - if(negflag & 0x02) { /*if -Y*/ - if(negflag & 0x01) /*if -Y -X*/ - degree = (180 + degree); - else /*else is -Y +X*/ - degree = (180 - degree); - } else { /*else is +Y*/ - if(negflag & 0x01) /*if +Y -X*/ - degree = (360 - degree); - } - return degree; -} - /********************** * STATIC FUNCTIONS **********************/ diff --git a/src/lv_font/lv_font_heb_16.c b/src/lv_font/lv_font_heb_16.c index 5cff45178..b7723192e 100644 --- a/src/lv_font/lv_font_heb_16.c +++ b/src/lv_font/lv_font_heb_16.c @@ -1,4 +1,4 @@ -#include "lvgl/lvgl.h" +#include "../../lvgl.h" /******************************************************************************* * Size: 16 px diff --git a/src/lv_objx/lv_label.c b/src/lv_objx/lv_label.c index bd99c10c8..9d7072006 100644 --- a/src/lv_objx/lv_label.c +++ b/src/lv_objx/lv_label.c @@ -731,7 +731,7 @@ uint16_t lv_label_get_letter_on(const lv_obj_t * label, lv_point_t * pos) if(bidi_txt[new_line_start] == '\0') txt_len--; lv_bidi_process_paragraph(txt + line_start, bidi_txt, txt_len, lv_obj_get_base_dir(label), NULL, 0); #else - bidi_txt = txt + line_start; + bidi_txt = (char*)txt + line_start; #endif /*Calculate the x coordinate*/