merge dev-6.1
This commit is contained in:
@@ -236,7 +236,7 @@ typedef void * lv_indev_drv_user_data_t; /*Type of user data in the i
|
||||
# define LV_LOG_LEVEL LV_LOG_LEVEL_WARN
|
||||
|
||||
/* 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*/
|
||||
|
||||
@@ -344,15 +344,19 @@ typedef void * lv_font_user_data_t;
|
||||
/*Can break (wrap) texts on these chars*/
|
||||
#define LV_TXT_BREAK_CHARS " ,.;:-_"
|
||||
|
||||
/* If a character is at least this long, will break wherever "prettiest" */
|
||||
#define LV_TXT_LINE_BREAK_LONG_LEN 12
|
||||
|
||||
/* Minimum number of characters of a word to put on a line before a break */
|
||||
#define LV_TXT_LINE_BREAK_LONG_PRE_MIN_LEN 3
|
||||
/* If a word is at least this long, will break wherever "prettiest"
|
||||
* To disable, set to a value <= 0 */
|
||||
#define LV_TXT_LINE_BREAK_LONG_LEN 12
|
||||
|
||||
/* Minimum number of characters of a word to put on a line after a break */
|
||||
#define LV_TXT_LINE_BREAK_LONG_POST_MIN_LEN 3
|
||||
/* Minimum number of characters in a long word to put on a line before a break.
|
||||
* Depends on LV_TXT_LINE_BREAK_LONG_LEN. */
|
||||
#define LV_TXT_LINE_BREAK_LONG_PRE_MIN_LEN 3
|
||||
|
||||
/* Minimum number of characters in a long word to put on a line after a break.
|
||||
* Depends on LV_TXT_LINE_BREAK_LONG_LEN. */
|
||||
#define LV_TXT_LINE_BREAK_LONG_POST_MIN_LEN 3
|
||||
|
||||
/* Support bidirectional texts.
|
||||
* Allows mixing Left-to-Right and Right-to-Left texts.
|
||||
* The direction will be processed according to the Unicode Bidirectioanl Algorithm:
|
||||
|
||||
1
lvgl.h
1
lvgl.h
@@ -23,6 +23,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"
|
||||
|
||||
@@ -269,9 +269,11 @@
|
||||
/* Export integer constant to binding.
|
||||
* This macro is used with constants in the form of LV_<CONST> that
|
||||
* should also appear on lvgl binding API such as Micropython
|
||||
*
|
||||
* The default value just prevents a GCC warning.
|
||||
*/
|
||||
#ifndef LV_EXPORT_CONST_INT
|
||||
#define LV_EXPORT_CONST_INT(int_value)
|
||||
#define LV_EXPORT_CONST_INT(int_value) struct _silence_gcc_warning
|
||||
#endif
|
||||
|
||||
/*===================
|
||||
@@ -314,7 +316,7 @@
|
||||
#endif
|
||||
|
||||
/* 1: Print the log with 'printf';
|
||||
* 0: user need to register a callback with `lv_log_register_print`*/
|
||||
* 0: user need to register a callback with `lv_log_register_print_cb`*/
|
||||
#ifndef LV_LOG_PRINTF
|
||||
# define LV_LOG_PRINTF 0
|
||||
#endif
|
||||
@@ -473,21 +475,25 @@
|
||||
#define LV_TXT_BREAK_CHARS " ,.;:-_"
|
||||
#endif
|
||||
|
||||
/* If a character is at least this long, will break wherever "prettiest" */
|
||||
|
||||
/* If a word is at least this long, will break wherever "prettiest"
|
||||
* To disable, set to a value <= 0 */
|
||||
#ifndef LV_TXT_LINE_BREAK_LONG_LEN
|
||||
#define LV_TXT_LINE_BREAK_LONG_LEN 12
|
||||
#define LV_TXT_LINE_BREAK_LONG_LEN 12
|
||||
#endif
|
||||
|
||||
/* Minimum number of characters of a word to put on a line before a break */
|
||||
/* Minimum number of characters in a long word to put on a line before a break.
|
||||
* Depends on LV_TXT_LINE_BREAK_LONG_LEN. */
|
||||
#ifndef LV_TXT_LINE_BREAK_LONG_PRE_MIN_LEN
|
||||
#define LV_TXT_LINE_BREAK_LONG_PRE_MIN_LEN 3
|
||||
#define LV_TXT_LINE_BREAK_LONG_PRE_MIN_LEN 3
|
||||
#endif
|
||||
|
||||
/* Minimum number of characters of a word to put on a line after a break */
|
||||
/* Minimum number of characters in a long word to put on a line after a break.
|
||||
* Depends on LV_TXT_LINE_BREAK_LONG_LEN. */
|
||||
#ifndef LV_TXT_LINE_BREAK_LONG_POST_MIN_LEN
|
||||
#define LV_TXT_LINE_BREAK_LONG_POST_MIN_LEN 3
|
||||
#define LV_TXT_LINE_BREAK_LONG_POST_MIN_LEN 3
|
||||
#endif
|
||||
|
||||
|
||||
/* Support bidirectional texts.
|
||||
* Allows mixing Left-to-Right and Right-to-Left texts.
|
||||
* The direction will be processed according to the Unicode Bidirectioanl Algorithm:
|
||||
|
||||
@@ -136,6 +136,8 @@ do { \
|
||||
|
||||
#else /* LV_USE_DEBUG == 0 */
|
||||
|
||||
#define LV_DEBUG_ASSERT(expr, msg, value) do{}while(0)
|
||||
|
||||
#define LV_ASSERT_NULL(p) true
|
||||
#define LV_ASSERT_MEM(p) true
|
||||
#define LV_ASSERT_STR(p) true
|
||||
|
||||
@@ -318,19 +318,19 @@ static void lv_refr_area(const lv_area_t * area_p)
|
||||
tmp.x2 = 0;
|
||||
tmp.y1 = 0;
|
||||
|
||||
lv_coord_t y_tmp = max_row - 1;
|
||||
lv_coord_t h_tmp = max_row;
|
||||
do {
|
||||
tmp.y2 = y_tmp;
|
||||
tmp.y2 = h_tmp - 1;
|
||||
disp_refr->driver.rounder_cb(&disp_refr->driver, &tmp);
|
||||
|
||||
/*If this height fits into `max_row` then fine*/
|
||||
if(lv_area_get_height(&tmp) <= max_row) break;
|
||||
|
||||
/*Decrement the height of the area until it fits into `max_row` after rounding*/
|
||||
y_tmp--;
|
||||
} while(y_tmp != 0);
|
||||
h_tmp--;
|
||||
} while(h_tmp > 0);
|
||||
|
||||
if(y_tmp == 0) {
|
||||
if(h_tmp <= 0) {
|
||||
LV_LOG_WARN("Can't set VDB height using the round function. (Wrong round_cb or to "
|
||||
"small VDB)");
|
||||
return;
|
||||
|
||||
@@ -212,7 +212,7 @@ void lv_style_anim_set_styles(lv_anim_t * a, lv_style_t * to_anim, const lv_styl
|
||||
* @param duration duration of the animation in milliseconds
|
||||
* @param delay delay before the animation in milliseconds
|
||||
*/
|
||||
static inline void lv_style_anim_set_time(lv_anim_t * a, uint16_t duration, uint16_t delay)
|
||||
static inline void lv_style_anim_set_time(lv_anim_t * a, uint16_t duration, int16_t delay)
|
||||
{
|
||||
lv_anim_set_time(a, duration, delay);
|
||||
}
|
||||
|
||||
@@ -98,7 +98,6 @@ void lv_draw_arc(lv_coord_t center_x, lv_coord_t center_y, uint16_t radius, cons
|
||||
|
||||
lv_draw_rect(&round_area, clip_area, &circle_style, LV_OPA_COVER);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ void lv_draw_img(const lv_area_t * coords, const lv_area_t * mask, const void *
|
||||
if(src == NULL) {
|
||||
LV_LOG_WARN("Image draw: src is NULL");
|
||||
lv_draw_rect(coords, mask, &lv_style_plain, LV_OPA_COVER);
|
||||
lv_draw_label(coords, mask, &lv_style_plain, LV_OPA_COVER, "No\ndata", LV_TXT_FLAG_NONE, NULL, NULL, NULL);
|
||||
lv_draw_label(coords, mask, &lv_style_plain, LV_OPA_COVER, "No\ndata", LV_TXT_FLAG_NONE, NULL, NULL, NULL, LV_BIDI_DIR_LTR);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ void lv_draw_img(const lv_area_t * coords, const lv_area_t * mask, const void *
|
||||
if(res == LV_RES_INV) {
|
||||
LV_LOG_WARN("Image draw error");
|
||||
lv_draw_rect(coords, mask, &lv_style_plain, LV_OPA_COVER);
|
||||
lv_draw_label(coords, mask, &lv_style_plain, LV_OPA_COVER, "No\ndata", LV_TXT_FLAG_NONE, NULL, NULL, NULL);
|
||||
lv_draw_label(coords, mask, &lv_style_plain, LV_OPA_COVER, "No\ndata", LV_TXT_FLAG_NONE, NULL, NULL, NULL, LV_BIDI_DIR_LTR);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -205,7 +205,7 @@ static lv_res_t lv_img_draw_core(const lv_area_t * coords, const lv_area_t * mas
|
||||
if(cdsc->dec_dsc.error_msg != NULL) {
|
||||
LV_LOG_WARN("Image draw error");
|
||||
lv_draw_rect(coords, mask, &lv_style_plain, LV_OPA_COVER);
|
||||
lv_draw_label(coords, mask, &lv_style_plain, LV_OPA_COVER, cdsc->dec_dsc.error_msg, LV_TXT_FLAG_NONE, NULL, NULL, NULL);
|
||||
lv_draw_label(coords, mask, &lv_style_plain, LV_OPA_COVER, cdsc->dec_dsc.error_msg, LV_TXT_FLAG_NONE, NULL, NULL, NULL, LV_BIDI_DIR_LTR);
|
||||
}
|
||||
/* The decoder open could open the image and gave the entire uncompressed image.
|
||||
* Just draw it!*/
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "../lv_misc/lv_math.h"
|
||||
#include "../lv_hal/lv_hal_disp.h"
|
||||
#include "../lv_core/lv_refr.h"
|
||||
#include "../lv_misc/lv_bidi.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
@@ -71,16 +72,13 @@ static const uint8_t bpp4_opa_table[16] = {0, 17, 34, 51, /*Opacity mapping w
|
||||
*/
|
||||
void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_style_t * style, lv_opa_t opa_scale,
|
||||
const char * txt, lv_txt_flag_t flag, lv_point_t * offset, lv_draw_label_txt_sel_t * sel,
|
||||
lv_draw_label_hint_t * hint)
|
||||
lv_draw_label_hint_t * hint, lv_bidi_dir_t bidi_dir)
|
||||
{
|
||||
const lv_font_t * font = style->text.font;
|
||||
lv_coord_t w;
|
||||
|
||||
/*No need to waste processor time if string is empty*/
|
||||
if (txt[0] == '\0')
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (txt[0] == '\0') return;
|
||||
|
||||
if((flag & LV_TXT_FLAG_EXPAND) == 0) {
|
||||
/*Normally use the label's width as width*/
|
||||
@@ -89,7 +87,7 @@ void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_st
|
||||
/*If EXAPND is enabled then not limit the text's width to the object's width*/
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -127,6 +125,7 @@ void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_st
|
||||
pos.y += hint->y;
|
||||
}
|
||||
|
||||
|
||||
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*/
|
||||
@@ -161,6 +160,18 @@ void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_st
|
||||
|
||||
lv_opa_t opa = opa_scale == LV_OPA_COVER ? style->text.opa : (uint16_t)((uint16_t)style->text.opa * opa_scale) >> 8;
|
||||
|
||||
uint16_t sel_start = 0xFFFF;
|
||||
uint16_t sel_end = 0xFFFF;
|
||||
if(sel) {
|
||||
sel_start = sel->start;
|
||||
sel_end = sel->end;
|
||||
if(sel_start > sel_end) {
|
||||
uint16_t tmp = sel_start;
|
||||
sel_start = sel_end;
|
||||
sel_end = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
cmd_state_t cmd_state = CMD_STATE_WAIT;
|
||||
uint32_t i;
|
||||
uint16_t par_start = 0;
|
||||
@@ -177,12 +188,31 @@ void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_st
|
||||
}
|
||||
/*Write all letter of a line*/
|
||||
cmd_state = CMD_STATE_WAIT;
|
||||
i = line_start;
|
||||
i = 0;
|
||||
uint32_t letter;
|
||||
uint32_t letter_next;
|
||||
while(i < line_end) {
|
||||
letter = lv_txt_encoded_next(txt, &i);
|
||||
letter_next = lv_txt_encoded_next(&txt[i], NULL);
|
||||
#if LV_USE_BIDI
|
||||
char *bidi_txt = lv_draw_get_buf(line_end - line_start + 1);
|
||||
lv_bidi_process_paragraph(txt + line_start, bidi_txt, line_end - line_start, bidi_dir, NULL, 0);
|
||||
#else
|
||||
const char *bidi_txt = txt + line_start;
|
||||
#endif
|
||||
|
||||
while(i < line_end - line_start) {
|
||||
uint16_t logical_char_pos = 0;
|
||||
if(sel_start != 0xFFFF && sel_end != 0xFFFF) {
|
||||
#if LV_USE_BIDI
|
||||
logical_char_pos = lv_txt_encoded_get_char_id(txt, line_start);
|
||||
uint16_t t = lv_txt_encoded_get_char_id(bidi_txt, i);
|
||||
logical_char_pos += lv_bidi_get_logical_pos(bidi_txt, NULL, line_end - line_start, bidi_dir, t, NULL);
|
||||
#else
|
||||
logical_char_pos = lv_txt_encoded_get_char_id(txt, line_start + i);
|
||||
#endif
|
||||
}
|
||||
|
||||
letter = lv_txt_encoded_next(bidi_txt, &i);
|
||||
letter_next = lv_txt_encoded_next(&bidi_txt[i], NULL);
|
||||
|
||||
|
||||
/*Handle the re-color command*/
|
||||
if((flag & LV_TXT_FLAG_RECOLOR) != 0) {
|
||||
@@ -205,7 +235,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]);
|
||||
@@ -227,18 +257,14 @@ void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_st
|
||||
|
||||
letter_w = lv_font_get_glyph_width(font, letter, letter_next);
|
||||
|
||||
if(sel) {
|
||||
if(sel->start != 0xFFFF && sel->end != 0xFFFF) {
|
||||
int char_ind = lv_encoded_get_char_id(txt, i);
|
||||
/*Do not draw the rectangle on the character at `sel_start`.*/
|
||||
if(char_ind > sel->start && char_ind <= sel->end) {
|
||||
lv_area_t sel_coords;
|
||||
sel_coords.x1 = pos.x;
|
||||
sel_coords.y1 = pos.y;
|
||||
sel_coords.x2 = pos.x + letter_w + style->text.letter_space - 1;
|
||||
sel_coords.y2 = pos.y + line_height - 1;
|
||||
lv_draw_rect(&sel_coords, mask, &sel_style, opa);
|
||||
}
|
||||
if(sel_start != 0xFFFF && sel_end != 0xFFFF) {
|
||||
if(logical_char_pos >= sel_start && logical_char_pos < sel_end) {
|
||||
lv_area_t sel_coords;
|
||||
sel_coords.x1 = pos.x;
|
||||
sel_coords.y1 = pos.y;
|
||||
sel_coords.x2 = pos.x + letter_w + style->text.letter_space - 1;
|
||||
sel_coords.y2 = pos.y + line_height - 1;
|
||||
lv_draw_rect(&sel_coords, mask, &sel_style, opa);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -256,7 +282,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;
|
||||
|
||||
@@ -264,7 +290,7 @@ void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_st
|
||||
/*Align to the right*/
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -684,13 +710,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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ extern "C" {
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_draw.h"
|
||||
#include "../lv_misc/lv_bidi.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
@@ -62,10 +63,11 @@ typedef struct {
|
||||
* @param flag settings for the text from 'txt_flag_t' enum
|
||||
* @param offset text offset in x and y direction (NULL if unused)
|
||||
* @param sel_start start index of selected area (`LV_LABEL_TXT_SEL_OFF` if none)
|
||||
* @param bidi_dir base direction of the text
|
||||
*/
|
||||
void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_style_t * style, lv_opa_t opa_scale,
|
||||
const char * txt, lv_txt_flag_t flag, lv_point_t * offset, lv_draw_label_txt_sel_t * sel,
|
||||
lv_draw_label_hint_t * hint);
|
||||
lv_draw_label_hint_t * hint, lv_bidi_dir_t bidi_dir);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
|
||||
1133
src/lv_font/lv_font_heb_16.c
Normal file
1133
src/lv_font/lv_font_heb_16.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -129,10 +129,10 @@ static inline void lv_anim_set_exec_cb(lv_anim_t * a, void * var, lv_anim_exec_x
|
||||
* @param duration duration of the animation in milliseconds
|
||||
* @param delay delay before the animation in milliseconds
|
||||
*/
|
||||
static inline void lv_anim_set_time(lv_anim_t * a, uint16_t duration, uint16_t delay)
|
||||
static inline void lv_anim_set_time(lv_anim_t * a, uint16_t duration, int16_t delay)
|
||||
{
|
||||
a->time = duration;
|
||||
a->act_time = -delay;
|
||||
a->act_time = (int16_t)(-delay);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -192,6 +192,19 @@ bool lv_area_is_in(const lv_area_t * ain_p, const lv_area_t * aholder_p)
|
||||
return is_in;
|
||||
}
|
||||
|
||||
/**
|
||||
* Increment or decrement an area's size by a single amount
|
||||
* @param a_p pointer to an area to grow
|
||||
* @param amount amount to increment the area, or negative to decrement
|
||||
*/
|
||||
void lv_area_increment(lv_area_t * a_p, const lv_coord_t amount)
|
||||
{
|
||||
a_p->x1 -= amount;
|
||||
a_p->y1 -= amount;
|
||||
a_p->x2 += amount;
|
||||
a_p->y2 += amount;
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
@@ -85,7 +85,7 @@ inline static void lv_area_copy(lv_area_t * dest, const lv_area_t * src)
|
||||
*/
|
||||
static inline lv_coord_t lv_area_get_width(const lv_area_t * area_p)
|
||||
{
|
||||
return area_p->x2 - area_p->x1 + 1;
|
||||
return (lv_coord_t)(area_p->x2 - area_p->x1 + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -95,7 +95,7 @@ static inline lv_coord_t lv_area_get_width(const lv_area_t * area_p)
|
||||
*/
|
||||
static inline lv_coord_t lv_area_get_height(const lv_area_t * area_p)
|
||||
{
|
||||
return area_p->y2 - area_p->y1 + 1;
|
||||
return (lv_coord_t)(area_p->y2 - area_p->y1 + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -168,6 +168,13 @@ bool lv_area_is_on(const lv_area_t * a1_p, const lv_area_t * a2_p);
|
||||
*/
|
||||
bool lv_area_is_in(const lv_area_t * ain_p, const lv_area_t * aholder_p);
|
||||
|
||||
/**
|
||||
* Increment or decrement an area's size by a single amount
|
||||
* @param a_p pointer to an area to grow
|
||||
* @param amount amount to increment the area, or negative to decrement
|
||||
*/
|
||||
void lv_area_increment(lv_area_t * a_p, const lv_coord_t amount);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
@@ -6,32 +6,49 @@
|
||||
/*********************
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_bidi.h"
|
||||
#include <stddef.h>
|
||||
#include "lv_bidi.h"
|
||||
#include "lv_txt.h"
|
||||
#include "../lv_draw/lv_draw.h"
|
||||
|
||||
#if LV_USE_BIDI
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
#define LV_BIDI_BRACKLET_DEPTH 4
|
||||
|
||||
// Highest bit of the 16-bit pos_conv value specifies whether this pos is RTL or not
|
||||
#define GET_POS(x) ((x) & 0x7FFF)
|
||||
#define IS_RTL_POS(x) (((x) & 0x8000) != 0)
|
||||
#define SET_RTL_POS(x, is_rtl) (GET_POS(x) | ((is_rtl)? 0x8000: 0))
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
typedef struct
|
||||
{
|
||||
uint32_t bracklet_pos;
|
||||
lv_bidi_dir_t dir;
|
||||
}bracket_stack_t;
|
||||
|
||||
/**********************
|
||||
* STATIC PROTOTYPES
|
||||
**********************/
|
||||
static 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 lv_bidi_dir_t get_next_run(const char * txt, lv_bidi_dir_t base_dir, uint32_t max_len, uint32_t * len, uint16_t * pos_conv_len);
|
||||
static void rtl_reverse(char * dest, const char * src, uint32_t len, uint16_t *pos_conv_out, uint16_t pos_conv_rd_base, uint16_t pos_conv_len);
|
||||
static uint32_t char_change_to_pair(uint32_t letter);
|
||||
static lv_bidi_dir_t bracket_process(const char * txt, uint32_t next_pos, uint32_t len, uint32_t letter, lv_bidi_dir_t base_dir);
|
||||
static void fill_pos_conv(uint16_t * out, uint16_t len, uint16_t index);
|
||||
static uint32_t get_txt_len(const char * txt, uint32_t max_len);
|
||||
|
||||
/**********************
|
||||
* STATIC VARIABLES
|
||||
**********************/
|
||||
static const uint8_t bracket_left[] = {"<({["};
|
||||
static const uint8_t bracket_right[] = {">)}]"};
|
||||
static bracket_stack_t br_stack[LV_BIDI_BRACKLET_DEPTH];
|
||||
static uint8_t br_stack_p;
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
@@ -43,7 +60,6 @@ static uint32_t char_change_to_pair(uint32_t letter);
|
||||
|
||||
void lv_bidi_process(const char * str_in, char * str_out, lv_bidi_dir_t base_dir)
|
||||
{
|
||||
|
||||
if(base_dir == LV_BIDI_DIR_AUTO) base_dir = lv_bidi_detect_base_dir(str_in);
|
||||
|
||||
uint32_t par_start = 0;
|
||||
@@ -55,8 +71,8 @@ void lv_bidi_process(const char * str_in, char * str_out, lv_bidi_dir_t base_dir
|
||||
}
|
||||
|
||||
while(str_in[par_start] != '\0') {
|
||||
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, NULL, 0);
|
||||
par_start += par_len;
|
||||
|
||||
while(str_in[par_start] == '\n' || str_in[par_start] == '\r') {
|
||||
@@ -121,7 +137,7 @@ bool lv_bidi_letter_is_rtl(uint32_t letter)
|
||||
bool lv_bidi_letter_is_neutral(uint32_t letter)
|
||||
{
|
||||
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;
|
||||
}
|
||||
@@ -129,62 +145,120 @@ 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, bool *is_rtl)
|
||||
{
|
||||
uint32_t pos_conv_len = get_txt_len(str_in, len);
|
||||
void *buf = lv_draw_get_buf(len + pos_conv_len * sizeof(uint16_t));
|
||||
if (bidi_txt) *bidi_txt = buf;
|
||||
uint16_t *pos_conv_buf = (uint16_t*) ((char*)buf + len);
|
||||
lv_bidi_process_paragraph(str_in, bidi_txt? *bidi_txt: NULL, len, base_dir, pos_conv_buf, pos_conv_len);
|
||||
if (is_rtl) *is_rtl = IS_RTL_POS(pos_conv_buf[visual_pos]);
|
||||
return GET_POS(pos_conv_buf[visual_pos]);
|
||||
}
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
uint16_t lv_bidi_get_visual_pos(const char * str_in, char **bidi_txt, uint16_t len, lv_bidi_dir_t base_dir, uint32_t logical_pos, bool *is_rtl)
|
||||
{
|
||||
uint32_t pos_conv_len = get_txt_len(str_in, len);
|
||||
void *buf = lv_draw_get_buf(len + pos_conv_len * sizeof(uint16_t));
|
||||
if (bidi_txt) *bidi_txt = buf;
|
||||
uint16_t *pos_conv_buf = (uint16_t*) ((char*)buf + len);
|
||||
lv_bidi_process_paragraph(str_in, bidi_txt? *bidi_txt: NULL, len, base_dir, pos_conv_buf, pos_conv_len);
|
||||
for (uint16_t i = 0; i < pos_conv_len; i++){
|
||||
if (GET_POS(pos_conv_buf[i]) == logical_pos){
|
||||
if (is_rtl) *is_rtl = IS_RTL_POS(pos_conv_buf[i]);
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return (uint16_t) -1;
|
||||
}
|
||||
|
||||
static void process_paragraph(const char * str_in, char * str_out, uint32_t len, lv_bidi_dir_t base_dir)
|
||||
void lv_bidi_process_paragraph(const char * str_in, char * str_out, uint32_t len, lv_bidi_dir_t base_dir, uint16_t *pos_conv_out, uint16_t pos_conv_len)
|
||||
{
|
||||
uint32_t run_len = 0;
|
||||
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;
|
||||
uint16_t pos_conv_run_len = 0;
|
||||
uint16_t pos_conv_rd = 0;
|
||||
uint16_t pos_conv_wr;
|
||||
|
||||
str_out[len] = '\0';
|
||||
if(base_dir == LV_BIDI_DIR_AUTO) base_dir = lv_bidi_detect_base_dir(str_in);
|
||||
if(base_dir == LV_BIDI_DIR_RTL) {
|
||||
wr = len;
|
||||
pos_conv_wr = pos_conv_len;
|
||||
}
|
||||
else {
|
||||
wr = 0;
|
||||
pos_conv_wr = 0;
|
||||
}
|
||||
|
||||
if (str_out) str_out[len] = '\0';
|
||||
|
||||
lv_bidi_dir_t dir = base_dir;
|
||||
|
||||
/*Empty the bracket stack*/
|
||||
br_stack_p = 0;
|
||||
|
||||
/*Process neutral chars in the beginning*/
|
||||
while(rd < len) {
|
||||
uint32_t letter = lv_txt_encoded_next(str_in, &rd);
|
||||
pos_conv_rd++;
|
||||
dir = lv_bidi_get_letter_dir(letter);
|
||||
if(dir == LV_BIDI_DIR_NEUTRAL) dir = bracket_process(str_in, rd, len, letter, base_dir);
|
||||
if(dir != LV_BIDI_DIR_NEUTRAL && dir != LV_BIDI_DIR_WEAK) break;
|
||||
}
|
||||
|
||||
if(rd && str_in[rd] != '\0') lv_txt_encoded_prev(str_in, &rd);
|
||||
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, &run_len);
|
||||
|
||||
while(rd < len && str_in[rd]) {
|
||||
run_dir = get_next_run(&str_in[rd], base_dir, len - rd, &run_len, &pos_conv_run_len);
|
||||
|
||||
if(base_dir == LV_BIDI_DIR_LTR) {
|
||||
if(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;
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t get_next_paragraph(const char * txt)
|
||||
uint32_t lv_bidi_get_next_paragraph(const char * txt)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
|
||||
@@ -197,20 +271,53 @@ 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 FUNCTIONS
|
||||
**********************/
|
||||
|
||||
static uint32_t get_txt_len(const char * txt, uint32_t max_len)
|
||||
{
|
||||
uint32_t len = 0;
|
||||
uint32_t i = 0;
|
||||
|
||||
while(i < max_len && txt[i] != '\0') {
|
||||
lv_txt_encoded_next(txt, &i);
|
||||
len++;
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static void fill_pos_conv(uint16_t * out, uint16_t len, uint16_t index)
|
||||
{
|
||||
for (uint16_t i = 0; i < len; i++)
|
||||
{
|
||||
out[i] = SET_RTL_POS(index, false);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
static lv_bidi_dir_t get_next_run(const char * txt, lv_bidi_dir_t base_dir, uint32_t max_len, uint32_t * len, uint16_t * pos_conv_len)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
uint32_t letter;
|
||||
|
||||
uint16_t pos_conv_i = 0;
|
||||
|
||||
letter = lv_txt_encoded_next(txt, NULL);
|
||||
lv_bidi_dir_t dir = lv_bidi_get_letter_dir(letter);
|
||||
if(dir == LV_BIDI_DIR_NEUTRAL) dir = bracket_process(txt, 0, max_len, letter, base_dir);
|
||||
|
||||
/*Find the first strong char. Skip the neutrals*/
|
||||
while(dir == LV_BIDI_DIR_NEUTRAL || dir == LV_BIDI_DIR_WEAK) {
|
||||
letter = lv_txt_encoded_next(txt, &i);
|
||||
pos_conv_i++;
|
||||
dir = lv_bidi_get_letter_dir(letter);
|
||||
if(txt[i] == '\0' || txt[i] == '\n' || txt[i] == '\r') {
|
||||
if(dir == LV_BIDI_DIR_NEUTRAL) dir = bracket_process(txt, i, max_len, letter, base_dir);
|
||||
|
||||
if(i >= max_len || txt[i] == '\0' || txt[i] == '\n' || txt[i] == '\r') {
|
||||
*len = i;
|
||||
*pos_conv_len = pos_conv_i;
|
||||
return base_dir;
|
||||
}
|
||||
}
|
||||
@@ -219,83 +326,119 @@ static lv_bidi_dir_t get_next_run(const char * txt, lv_bidi_dir_t base_dir, uint
|
||||
|
||||
uint32_t i_prev = i;
|
||||
uint32_t i_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(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);
|
||||
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 != '$') {
|
||||
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;
|
||||
wr += 1;
|
||||
if (dest) dest[wr] = (uint8_t)new_letter;
|
||||
if (pos_conv_out) pos_conv_out[pos_conv_wr] = SET_RTL_POS(pos_conv_rd_base + pos_conv_letter, true);
|
||||
wr++;
|
||||
pos_conv_wr++;
|
||||
}
|
||||
/*Just store the letter*/
|
||||
else {
|
||||
memcpy(&dest[wr], &src[i], letter_size);
|
||||
if (dest) memcpy(&dest[wr], &src[i], letter_size);
|
||||
if (pos_conv_out) pos_conv_out[pos_conv_wr] = SET_RTL_POS(pos_conv_rd_base + pos_conv_i, true);
|
||||
wr += letter_size;
|
||||
pos_conv_wr++;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -303,19 +446,95 @@ static void rtl_reverse(char * dest, const char * src, uint32_t len)
|
||||
|
||||
static uint32_t char_change_to_pair(uint32_t letter)
|
||||
{
|
||||
static 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 char * txt, uint32_t next_pos, uint32_t len, uint32_t letter, lv_bidi_dir_t base_dir)
|
||||
{
|
||||
lv_bidi_dir_t bracket_dir = LV_BIDI_DIR_NEUTRAL;
|
||||
|
||||
uint8_t i;
|
||||
/*Is the letter an opening bracket?*/
|
||||
for(i = 0; bracket_left[i] != '\0'; i++) {
|
||||
if(bracket_left[i] == letter) {
|
||||
/* If so find it's matching closing bracket.
|
||||
* If a char with base dir. direction is found then the brackets will have `base_dir` direction*/
|
||||
uint32_t txt_i = next_pos;
|
||||
while(txt_i < len) {
|
||||
uint32_t letter_next = lv_txt_encoded_next(txt, &txt_i);
|
||||
if(letter_next == bracket_right[i]) {
|
||||
/*Closing bracket found*/
|
||||
break;
|
||||
} else {
|
||||
/*Save the dir*/
|
||||
lv_bidi_dir_t letter_dir = lv_bidi_get_letter_dir(letter_next);
|
||||
if(letter_dir == base_dir) {
|
||||
bracket_dir = base_dir;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*There were no matching closing bracket*/
|
||||
if(txt_i > len) return LV_BIDI_DIR_NEUTRAL;
|
||||
|
||||
/*There where a strong char with base dir in the bracket so the dir is found.*/
|
||||
if(bracket_dir != LV_BIDI_DIR_NEUTRAL && bracket_dir != LV_BIDI_DIR_WEAK) break;
|
||||
|
||||
/*If there were no matching strong chars in the brackets then check the previous chars*/
|
||||
txt_i = next_pos;
|
||||
if(txt_i) lv_txt_encoded_prev(txt, &txt_i);
|
||||
while(txt_i > 0) {
|
||||
uint32_t letter_next = lv_txt_encoded_prev(txt, &txt_i);
|
||||
lv_bidi_dir_t letter_dir = lv_bidi_get_letter_dir(letter_next);
|
||||
if(letter_dir == LV_BIDI_DIR_LTR || letter_dir == LV_BIDI_DIR_RTL) {
|
||||
bracket_dir = letter_dir;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*There where a previous strong char which can be used*/
|
||||
if(bracket_dir != LV_BIDI_DIR_NEUTRAL) break;
|
||||
|
||||
/*There were no strong chars before the bracket, so use the base dir.*/
|
||||
if(txt_i == 0) bracket_dir = base_dir;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*The letter was an opening bracket*/
|
||||
if(bracket_left[i] != '\0') {
|
||||
|
||||
if(bracket_dir == LV_BIDI_DIR_NEUTRAL || br_stack_p == LV_BIDI_BRACKLET_DEPTH) return LV_BIDI_DIR_NEUTRAL;
|
||||
|
||||
br_stack[br_stack_p].bracklet_pos = i;
|
||||
br_stack[br_stack_p].dir = bracket_dir;
|
||||
|
||||
br_stack_p++;
|
||||
return bracket_dir;
|
||||
} else if(br_stack_p > 0) {
|
||||
/*Is the letter a closing bracket of the last opening?*/
|
||||
if(letter == bracket_right[br_stack[br_stack_p - 1].bracklet_pos]) {
|
||||
bracket_dir = br_stack[br_stack_p - 1].dir;
|
||||
br_stack_p--;
|
||||
return bracket_dir;
|
||||
}
|
||||
}
|
||||
|
||||
return LV_BIDI_DIR_NEUTRAL;
|
||||
}
|
||||
|
||||
|
||||
#endif /*LV_USE_BIDI*/
|
||||
|
||||
@@ -53,11 +53,15 @@ 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, uint16_t *pos_conv_out, uint16_t pos_conv_len);
|
||||
uint32_t lv_bidi_get_next_paragraph(const char * txt);
|
||||
lv_bidi_dir_t lv_bidi_detect_base_dir(const char * txt);
|
||||
lv_bidi_dir_t lv_bidi_get_letter_dir(uint32_t letter);
|
||||
bool lv_bidi_letter_is_weak(uint32_t letter);
|
||||
bool lv_bidi_letter_is_rtl(uint32_t letter);
|
||||
bool lv_bidi_letter_is_neutral(uint32_t letter);
|
||||
uint16_t lv_bidi_get_logical_pos(const char * str_in, char **bidi_txt, uint32_t len, lv_bidi_dir_t base_dir, uint32_t visual_pos, bool *is_rtl);
|
||||
uint16_t lv_bidi_get_visual_pos(const char * str_in, char **bidi_txt, uint16_t len, lv_bidi_dir_t base_dir, uint32_t logical_pos, bool *is_rtl);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
* INCLUDES
|
||||
*********************/
|
||||
#include "lv_color.h"
|
||||
#include "lv_math.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
@@ -105,39 +106,66 @@ lv_color_t lv_color_hsv_to_rgb(uint16_t h, uint8_t s, uint8_t v)
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert an RGB color to HSV
|
||||
* @param r red
|
||||
* @param g green
|
||||
* @param b blue
|
||||
* @return the given RGB color n HSV
|
||||
* Convert a 32-bit RGB color to HSV
|
||||
* @param r8 8-bit red
|
||||
* @param g8 8-bit green
|
||||
* @param b8 8-bit blue
|
||||
* @return the given RGB color in HSV
|
||||
*/
|
||||
lv_color_hsv_t lv_color_rgb_to_hsv(uint8_t r, uint8_t g, uint8_t b)
|
||||
lv_color_hsv_t lv_color_rgb_to_hsv(uint8_t r8, uint8_t g8, uint8_t b8)
|
||||
{
|
||||
uint16_t r = ((uint32_t)r8 << 10) / 255;
|
||||
uint16_t g = ((uint32_t)g8 << 10) / 255;
|
||||
uint16_t b = ((uint32_t)b8 << 10) / 255;
|
||||
|
||||
uint16_t rgbMin = r < g ? (r < b ? r : b) : (g < b ? g : b);
|
||||
uint16_t rgbMax = r > g ? (r > b ? r : b) : (g > b ? g : b);
|
||||
|
||||
lv_color_hsv_t hsv;
|
||||
uint8_t rgbMin, rgbMax;
|
||||
|
||||
rgbMin = r < g ? (r < b ? r : b) : (g < b ? g : b);
|
||||
rgbMax = r > g ? (r > b ? r : b) : (g > b ? g : b);
|
||||
// https://en.wikipedia.org/wiki/HSL_and_HSV#Lightness
|
||||
hsv.v = (100 * rgbMax) >> 10;
|
||||
|
||||
hsv.v = rgbMax;
|
||||
if(hsv.v == 0) {
|
||||
int32_t delta = rgbMax - rgbMin;
|
||||
if (LV_MATH_ABS(delta) < 3) {
|
||||
hsv.h = 0;
|
||||
hsv.s = 0;
|
||||
return hsv;
|
||||
}
|
||||
|
||||
hsv.s = 255 * (long)(rgbMax - rgbMin) / hsv.v;
|
||||
if(hsv.s == 0) {
|
||||
// https://en.wikipedia.org/wiki/HSL_and_HSV#Saturation
|
||||
hsv.s = 100 * delta / rgbMax;
|
||||
if(hsv.s < 3) {
|
||||
hsv.h = 0;
|
||||
return hsv;
|
||||
}
|
||||
|
||||
// https://en.wikipedia.org/wiki/HSL_and_HSV#Hue_and_chroma
|
||||
int32_t h;
|
||||
if(rgbMax == r)
|
||||
hsv.h = 0 + 43 * (g - b) / (rgbMax - rgbMin);
|
||||
h = (((g - b) << 10) / delta) + (g < b ? (6 << 10) : 0); // between yellow & magenta
|
||||
else if(rgbMax == g)
|
||||
hsv.h = 85 + 43 * (b - r) / (rgbMax - rgbMin);
|
||||
h = (((b - r) << 10) / delta) + (2 << 10); // between cyan & yellow
|
||||
else if(rgbMax == b)
|
||||
h = (((r - g) << 10) / delta) + (4 << 10); // between magenta & cyan
|
||||
else
|
||||
hsv.h = 171 + 43 * (r - g) / (rgbMax - rgbMin);
|
||||
h = 0;
|
||||
h *= 60;
|
||||
h >>= 10;
|
||||
if (h < 0) h += 360;
|
||||
|
||||
hsv.h = h;
|
||||
return hsv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a color to HSV
|
||||
* @param color color
|
||||
* @return the given color in HSV
|
||||
*/
|
||||
lv_color_hsv_t lv_color_to_hsv(lv_color_t color)
|
||||
{
|
||||
lv_color32_t color32;
|
||||
color32.full = lv_color_to32(color);
|
||||
return lv_color_rgb_to_hsv(color32.ch.red, color32.ch.green, color32.ch.blue);
|
||||
}
|
||||
|
||||
@@ -90,6 +90,110 @@ enum {
|
||||
#error "Invalid LV_COLOR_DEPTH in lv_conf.h! Set it to 1, 8, 16 or 32!"
|
||||
#endif
|
||||
|
||||
/*---------------------------------------
|
||||
* Macros for all existing color depths
|
||||
* to set/get values of the color channels
|
||||
*------------------------------------------*/
|
||||
# define LV_COLOR_SET_R1(c, v) (c).ch.red = (uint8_t)((v) & 0x1);
|
||||
# define LV_COLOR_SET_G1(c, v) (c).ch.green = (uint8_t)((v) & 0x1);
|
||||
# define LV_COLOR_SET_B1(c, v) (c).ch.blue = (uint8_t)((v) & 0x1);
|
||||
# define LV_COLOR_SET_A1(c, v)
|
||||
|
||||
# define LV_COLOR_GET_R1(c) (c).ch.red
|
||||
# define LV_COLOR_GET_G1(c) (c).ch.green
|
||||
# define LV_COLOR_GET_B1(c) (c).ch.blue
|
||||
# define LV_COLOR_GET_A1(c) 1
|
||||
|
||||
# define LV_COLOR_SET_R8(c, v) (c).ch.red = (uint8_t)((v) & 0x7);
|
||||
# define LV_COLOR_SET_G8(c, v) (c).ch.green = (uint8_t)((v) & 0x7);
|
||||
# define LV_COLOR_SET_B8(c, v) (c).ch.blue = (uint8_t)((v) & 0x3);
|
||||
# define LV_COLOR_SET_A8(c, v) do {} while(0)
|
||||
|
||||
# define LV_COLOR_GET_R8(c) (c).ch.red
|
||||
# define LV_COLOR_GET_G8(c) (c).ch.green
|
||||
# define LV_COLOR_GET_B8(c) (c).ch.blue
|
||||
# define LV_COLOR_GET_A8(c) 0xFF
|
||||
|
||||
# define LV_COLOR_SET_R16(c, v) (c).ch.red = (uint16_t)((v) & 0x1F);
|
||||
# define LV_COLOR_SET_G16(c, v) (c).ch.green = (uint16_t)((v) & 0x3F);
|
||||
# define LV_COLOR_SET_G16_SWAP(c, v) {(c).ch.green_h = (uint16_t)(((v) >> 3) & 0x7); (c).ch.green_l = (uint16_t)((v) & 0x7);}
|
||||
# define LV_COLOR_SET_B16(c, v) (c).ch.blue = (uint16_t)((v) & 0x1F);
|
||||
# define LV_COLOR_SET_A16(c, v) do {} while(0)
|
||||
|
||||
# define LV_COLOR_GET_R16(c) (c).ch.red
|
||||
# define LV_COLOR_GET_G16(c) (c).ch.green
|
||||
# define LV_COLOR_GET_G16_SWAP(c) (((c).ch.green_h << 3) + (c).ch.green_l)
|
||||
# define LV_COLOR_GET_B16(c) (c).ch.blue
|
||||
# define LV_COLOR_GET_A16(c) 0xFF
|
||||
|
||||
# define LV_COLOR_SET_R32(c, v) (c).ch.red = (uint32_t)((v) & 0xFF);
|
||||
# define LV_COLOR_SET_G32(c, v) (c).ch.green = (uint32_t)((v) & 0xFF);
|
||||
# define LV_COLOR_SET_B32(c, v) (c).ch.blue = (uint32_t)((v) & 0xFF);
|
||||
# define LV_COLOR_SET_A32(c, v) (c).ch.alpha = (uint32_t)((v) & 0xFF);
|
||||
|
||||
# define LV_COLOR_GET_R32(c) (c).ch.red
|
||||
# define LV_COLOR_GET_G32(c) (c).ch.green
|
||||
# define LV_COLOR_GET_B32(c) (c).ch.blue
|
||||
# define LV_COLOR_GET_A32(c) (c).ch.alpha
|
||||
|
||||
|
||||
/*---------------------------------------
|
||||
* Macros for the current color depth
|
||||
* to set/get values of the color channels
|
||||
*------------------------------------------*/
|
||||
#if LV_COLOR_DEPTH == 1
|
||||
# define LV_COLOR_SET_R(c, v) LV_COLOR_SET_R1(c,v)
|
||||
# define LV_COLOR_SET_G(c, v) LV_COLOR_SET_G1(c,v)
|
||||
# define LV_COLOR_SET_B(c, v) LV_COLOR_SET_B1(c,v)
|
||||
# define LV_COLOR_SET_A(c, v) LV_COLOR_SET_A1(c,v)
|
||||
|
||||
# define LV_COLOR_GET_R(c) LV_COLOR_GET_R1(c)
|
||||
# define LV_COLOR_GET_G(c) LV_COLOR_GET_G1(c)
|
||||
# define LV_COLOR_GET_B(c) LV_COLOR_GET_B1(c)
|
||||
# define LV_COLOR_GET_A(c) LV_COLOR_GET_A1(c)
|
||||
|
||||
#elif LV_COLOR_DEPTH == 8
|
||||
# define LV_COLOR_SET_R(c, v) LV_COLOR_SET_R8(c,v)
|
||||
# define LV_COLOR_SET_G(c, v) LV_COLOR_SET_G8(c,v)
|
||||
# define LV_COLOR_SET_B(c, v) LV_COLOR_SET_B8(c,v)
|
||||
# define LV_COLOR_SET_A(c, v) LV_COLOR_SET_A8(c,v)
|
||||
|
||||
# define LV_COLOR_GET_R(c) LV_COLOR_GET_R8(c)
|
||||
# define LV_COLOR_GET_G(c) LV_COLOR_GET_G8(c)
|
||||
# define LV_COLOR_GET_B(c) LV_COLOR_GET_B8(c)
|
||||
# define LV_COLOR_GET_A(c) LV_COLOR_GET_A8(c)
|
||||
|
||||
#elif LV_COLOR_DEPTH == 16
|
||||
# define LV_COLOR_SET_R(c, v) LV_COLOR_SET_R16(c,v)
|
||||
# if LV_COLOR_16_SWAP == 0
|
||||
# define LV_COLOR_SET_G(c, v) LV_COLOR_SET_G16(c,v)
|
||||
# else
|
||||
# define LV_COLOR_SET_G(c, v) LV_COLOR_SET_G16_SWAP(c,v)
|
||||
# endif
|
||||
# define LV_COLOR_SET_B(c, v) LV_COLOR_SET_B16(c,v)
|
||||
# define LV_COLOR_SET_A(c, v) LV_COLOR_SET_A16(c,v)
|
||||
|
||||
# define LV_COLOR_GET_R(c) LV_COLOR_GET_R16(c)
|
||||
# if LV_COLOR_16_SWAP == 0
|
||||
# define LV_COLOR_GET_G(c) LV_COLOR_GET_G16(c)
|
||||
# else
|
||||
# define LV_COLOR_GET_G(c) LV_COLOR_GET_G16_SWAP(c)
|
||||
# endif
|
||||
# define LV_COLOR_GET_B(c) LV_COLOR_GET_B16(c)
|
||||
# define LV_COLOR_GET_A(c) LV_COLOR_GET_A16(c)
|
||||
|
||||
#elif LV_COLOR_DEPTH == 32
|
||||
# define LV_COLOR_SET_R(c, v) LV_COLOR_SET_R32(c,v)
|
||||
# define LV_COLOR_SET_G(c, v) LV_COLOR_SET_G32(c,v)
|
||||
# define LV_COLOR_SET_B(c, v) LV_COLOR_SET_B32(c,v)
|
||||
# define LV_COLOR_SET_A(c, v) LV_COLOR_SET_A32(c,v)
|
||||
|
||||
# define LV_COLOR_GET_R(c) LV_COLOR_GET_R32(c)
|
||||
# define LV_COLOR_GET_G(c) LV_COLOR_GET_G32(c)
|
||||
# define LV_COLOR_GET_B(c) LV_COLOR_GET_B32(c)
|
||||
# define LV_COLOR_GET_A(c) LV_COLOR_GET_A32(c)
|
||||
#endif
|
||||
|
||||
/**********************
|
||||
* TYPEDEFS
|
||||
**********************/
|
||||
@@ -194,24 +298,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((LV_COLOR_GET_R(color) & 0x80) || (LV_COLOR_GET_G(color) & 0x80) || (LV_COLOR_GET_B(color) & 0x80)) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
@@ -229,31 +328,23 @@ 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*/
|
||||
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;
|
||||
#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*/
|
||||
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;
|
||||
@@ -261,34 +352,30 @@ static inline uint16_t lv_color_to16(lv_color_t color)
|
||||
return 0xFFFF;
|
||||
#elif LV_COLOR_DEPTH == 8
|
||||
lv_color16_t ret;
|
||||
LV_COLOR_SET_R16(ret, LV_COLOR_GET_R(color) * 4); /*(2^5 - 1)/(2^3 - 1) = 31/7 = 4*/
|
||||
#if LV_COLOR_16_SWAP == 0
|
||||
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*/
|
||||
LV_COLOR_SET_G16(ret, 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;
|
||||
LV_COLOR_SET_G16_SWAP(ret, (LV_COLOR_GET_G(color) * 9)); /*(2^6 - 1)/(2^3 - 1) = 63/7 = 9*/
|
||||
#endif
|
||||
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;
|
||||
LV_COLOR_SET_R16(ret, 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*/
|
||||
LV_COLOR_SET_G16(ret, 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;
|
||||
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
|
||||
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)
|
||||
@@ -300,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 = 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.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
|
||||
/**
|
||||
@@ -335,14 +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 = ( 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.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;
|
||||
@@ -362,21 +445,10 @@ static inline lv_color_t lv_color_mix(lv_color_t c1, lv_color_t c2, uint8_t mix)
|
||||
lv_color_t ret;
|
||||
#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 * (256 - 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 * (256 - mix))) >> 8;
|
||||
ret.ch.green_h = g_out >> 3;
|
||||
ret.ch.green_l = g_out & 0x7;
|
||||
#else
|
||||
ret.ch.green = (uint16_t)((uint16_t)c1.ch.green * mix + (c2.ch.green * (256 - mix))) >> 8;
|
||||
#endif
|
||||
ret.ch.blue = (uint16_t)((uint16_t)c1.ch.blue * mix + (c2.ch.blue * (256 - mix))) >> 8;
|
||||
#if LV_COLOR_DEPTH == 32
|
||||
ret.ch.alpha = 0xFF;
|
||||
#endif
|
||||
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);
|
||||
LV_COLOR_SET_A(ret, 0xFF);
|
||||
#else
|
||||
/*LV_COLOR_DEPTH == 1*/
|
||||
ret.full = mix > LV_OPA_50 ? c1.full : c2.full;
|
||||
@@ -454,16 +526,16 @@ static inline uint8_t lv_color_brightness(lv_color_t color)
|
||||
{
|
||||
lv_color32_t c32;
|
||||
c32.full = lv_color_to32(color);
|
||||
uint16_t bright = 3 * c32.ch.red + c32.ch.blue + 4 * c32.ch.green;
|
||||
return (uint16_t)bright >> 3;
|
||||
uint16_t bright = (uint16_t)(3u * LV_COLOR_GET_R32(c32) + LV_COLOR_GET_B32(c32) + 4u * LV_COLOR_GET_G32(c32));
|
||||
return (uint8_t)(bright >> 3);
|
||||
}
|
||||
|
||||
/* The most simple macro to create a color from R,G and B values */
|
||||
#if LV_COLOR_DEPTH == 1
|
||||
#define LV_COLOR_MAKE(r8, g8, b8) ((lv_color_t){(b8 >> 7 | g8 >> 7 | r8 >> 7)})
|
||||
#define LV_COLOR_MAKE(r8, g8, b8) ((lv_color_t){.full = (b8 >> 7 | g8 >> 7 | r8 >> 7)})
|
||||
static inline lv_color_t lv_color_make(int r8, int g8, int b8)
|
||||
{
|
||||
lv_color_t color;
|
||||
lv_color_t color = { 0 };
|
||||
color.full = (b8 >> 7 | g8 >> 7 | r8 >> 7);
|
||||
return color;
|
||||
}
|
||||
@@ -472,43 +544,36 @@ static inline lv_color_t lv_color_make(int r8, int g8, int b8)
|
||||
static inline lv_color_t lv_color_make(uint8_t r8, int g8, int b8)
|
||||
{
|
||||
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
|
||||
@@ -534,13 +599,20 @@ static inline lv_color_t lv_color_hex3(uint32_t c)
|
||||
lv_color_t lv_color_hsv_to_rgb(uint16_t h, uint8_t s, uint8_t v);
|
||||
|
||||
/**
|
||||
* Convert an RGB color to HSV
|
||||
* @param r red
|
||||
* @param g green
|
||||
* @param b blue
|
||||
* @return the given RGB color n HSV
|
||||
* Convert a 32-bit RGB color to HSV
|
||||
* @param r8 8-bit red
|
||||
* @param g8 8-bit green
|
||||
* @param b8 8-bit blue
|
||||
* @return the given RGB color in HSV
|
||||
*/
|
||||
lv_color_hsv_t lv_color_rgb_to_hsv(uint8_t r, uint8_t g, uint8_t b);
|
||||
lv_color_hsv_t lv_color_rgb_to_hsv(uint8_t r8, uint8_t g8, uint8_t b8);
|
||||
|
||||
/**
|
||||
* Convert a color to HSV
|
||||
* @param color color
|
||||
* @return the given color in HSV
|
||||
*/
|
||||
lv_color_hsv_t lv_color_to_hsv(lv_color_t color);
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#if LV_LOG_PRINTF
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
*********************/
|
||||
|
||||
@@ -312,7 +312,6 @@ uint16_t lv_atan2(int x, int y)
|
||||
return degree;
|
||||
}
|
||||
|
||||
|
||||
/**********************
|
||||
* STATIC FUNCTIONS
|
||||
**********************/
|
||||
|
||||
@@ -70,7 +70,6 @@ void lv_sqrt(uint32_t x, lv_sqrt_res_t * q);
|
||||
*/
|
||||
uint16_t lv_atan2(int x, int y);
|
||||
|
||||
|
||||
/**********************
|
||||
* MACROS
|
||||
**********************/
|
||||
|
||||
@@ -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
|
||||
@@ -149,17 +149,21 @@ void lv_txt_get_size(lv_point_t * size_res, const char * text, const lv_font_t *
|
||||
* 3. Return i=9, pointing at breakchar '\n'
|
||||
* 4. Parenting lv_txt_get_next_line() would detect subsequent '\0'
|
||||
*
|
||||
* TODO: Returned word_w_ptr may overestimate the returned word's width when
|
||||
* max_width is reached. In current usage, this has no impact.
|
||||
*
|
||||
* @param txt a '\0' terminated string
|
||||
* @param font pointer to a font
|
||||
* @param letter_space letter space
|
||||
* @param max_width max with of the text (break the lines to fit this size) Set CORD_MAX to avoid line breaks
|
||||
* @param flags settings for the text from 'txt_flag_type' enum
|
||||
* @param[out] word_w_ptr width (in pixels) of the parsed word. May be NULL.
|
||||
* @param force Force return the fraction of the word that can fit in the provided space.
|
||||
* @return the index of the first char of the next word (in byte index not letter index. With UTF-8 they are different)
|
||||
*/
|
||||
static uint16_t lv_txt_get_next_word(const char * txt, const lv_font_t * font,
|
||||
lv_coord_t letter_space, lv_coord_t max_width,
|
||||
lv_txt_flag_t flag, uint32_t *word_w_ptr)
|
||||
lv_txt_flag_t flag, uint32_t *word_w_ptr, bool force)
|
||||
{
|
||||
if(txt == NULL || txt[0] == '\0') return 0;
|
||||
if(font == NULL) return 0;
|
||||
@@ -179,6 +183,7 @@ static uint16_t lv_txt_get_next_word(const char * txt, const lv_font_t * font,
|
||||
letter = lv_txt_encoded_next(txt, &i_next);
|
||||
i_next_next = i_next;
|
||||
|
||||
/* Obtain the full word, regardless if it fits or not in max_width */
|
||||
while(txt[i] != '\0') {
|
||||
letter_next = lv_txt_encoded_next(txt, &i_next_next);
|
||||
word_len++;
|
||||
@@ -196,17 +201,10 @@ static uint16_t lv_txt_get_next_word(const char * txt, const lv_font_t * font,
|
||||
letter_w = lv_font_get_glyph_width(font, letter, letter_next);
|
||||
cur_w += letter_w;
|
||||
|
||||
|
||||
/* Test if this character fits within max_width */
|
||||
if( break_index == NO_BREAK_FOUND && cur_w > max_width) {
|
||||
if(break_index == NO_BREAK_FOUND && cur_w > max_width) {
|
||||
break_index = i;
|
||||
if(break_index > 0) { /* zero is possible if first character doesn't fit in width */
|
||||
lv_txt_encoded_prev(txt, &break_index);
|
||||
break_letter_count = word_len - 2;
|
||||
}
|
||||
else{
|
||||
break_letter_count = word_len - 1;
|
||||
}
|
||||
break_letter_count = word_len - 1;
|
||||
/* break_index is now pointing at the character that doesn't fit */
|
||||
}
|
||||
|
||||
@@ -237,14 +235,17 @@ static uint16_t lv_txt_get_next_word(const char * txt, const lv_font_t * font,
|
||||
return i;
|
||||
}
|
||||
|
||||
#if LV_TXT_LINE_BREAK_LONG_LEN > 0
|
||||
/* Word doesn't fit in provided space, but isn't "long" */
|
||||
if(word_len < LV_TXT_LINE_BREAK_LONG_LEN) {
|
||||
if(word_w_ptr != NULL) *word_w_ptr = 0;
|
||||
if( force ) return break_index;
|
||||
if(word_w_ptr != NULL) *word_w_ptr = 0; /* Return no word */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Word is "long," but insufficient amounts can fit in provided space */
|
||||
if(break_letter_count < LV_TXT_LINE_BREAK_LONG_PRE_MIN_LEN) {
|
||||
if( force ) return break_index;
|
||||
if(word_w_ptr != NULL) *word_w_ptr = 0;
|
||||
return 0;
|
||||
}
|
||||
@@ -256,16 +257,24 @@ static uint16_t lv_txt_get_next_word(const char * txt, const lv_font_t * font,
|
||||
/* Move pointer "i" backwards */
|
||||
for(;n_move>0; n_move--){
|
||||
lv_txt_encoded_prev(txt, &i);
|
||||
// todo: it would be appropriate to update the returned word width here
|
||||
// TODO: it would be appropriate to update the returned word width here
|
||||
// However, in current usage, this doesn't impact anything.
|
||||
}
|
||||
}
|
||||
|
||||
return i;
|
||||
#else
|
||||
if( force ) return break_index;
|
||||
if(word_w_ptr != NULL) *word_w_ptr = 0; /* Return no word */
|
||||
(void) break_letter_count;
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the next line of text. Check line length and break chars too.
|
||||
*
|
||||
* A line of txt includes the \n character.
|
||||
*
|
||||
* @param txt a '\0' terminated string
|
||||
* @param font pointer to a font
|
||||
* @param letter_space letter space
|
||||
@@ -285,7 +294,7 @@ uint16_t lv_txt_get_next_line(const char * txt, const lv_font_t * font,
|
||||
|
||||
while(txt[i] != '\0' && max_width > 0) {
|
||||
uint32_t word_w = 0;
|
||||
uint32_t advance = lv_txt_get_next_word(&txt[i], font, letter_space, max_width, flag, &word_w);
|
||||
uint32_t advance = lv_txt_get_next_word(&txt[i], font, letter_space, max_width, flag, &word_w, i==0);
|
||||
max_width -= word_w;
|
||||
|
||||
if( advance == 0 ){
|
||||
@@ -295,21 +304,16 @@ uint16_t lv_txt_get_next_line(const char * txt, const lv_font_t * font,
|
||||
|
||||
i += advance;
|
||||
|
||||
if(txt[i] == '\n') break;
|
||||
if(txt[0] == '\n') break;
|
||||
|
||||
if(txt[i] == '\n'){
|
||||
i++; /* Include the following newline in the current line */
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* If this is the last of the string, make sure pointer is at NULL-terminator.
|
||||
* This catches the case, for example of a string ending in "\n" */
|
||||
if(txt[i] != '\0'){
|
||||
uint32_t i_next = i;
|
||||
int tmp;
|
||||
uint32_t letter_next = lv_txt_encoded_next(txt, &i_next); /*Gets current character*/
|
||||
tmp = i_next;
|
||||
letter_next = lv_txt_encoded_next(txt, &i_next); /*Gets subsequent character*/
|
||||
if(letter_next == '\0') i = tmp;
|
||||
}
|
||||
|
||||
/*Always step at least one to avoid infinite loops*/
|
||||
/* Always step at least one to avoid infinite loops */
|
||||
if(i == 0) {
|
||||
lv_txt_encoded_next(txt, &i);
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -670,11 +670,6 @@ static lv_design_res_t lv_btnm_design(lv_obj_t * btnm, const lv_area_t * clip_ar
|
||||
lv_txt_flag_t txt_flag = LV_TXT_FLAG_NONE;
|
||||
|
||||
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) {
|
||||
@@ -743,22 +738,8 @@ static lv_design_res_t lv_btnm_design(lv_obj_t * btnm, const lv_area_t * clip_ar
|
||||
area_tmp.x2 = area_tmp.x1 + txt_size.x;
|
||||
area_tmp.y2 = area_tmp.y1 + txt_size.y;
|
||||
|
||||
#if LV_USE_BIDI == 0
|
||||
lv_draw_label(&area_tmp, clip_area, btn_style, opa_scale, ext->map_p[txt_i], txt_flag, NULL, NULL, NULL);
|
||||
#else
|
||||
uint32_t txt_len = strlen(ext->map_p[txt_i]) + 1;
|
||||
if(txt_len > lv_mem_get_size(bidi_buf)) {
|
||||
bidi_buf = lv_mem_realloc(bidi_buf, txt_len);
|
||||
}
|
||||
|
||||
lv_bidi_process(ext->map_p[txt_i], bidi_buf, base_dir);
|
||||
lv_draw_label(&area_tmp, clip_area, btn_style, opa_scale, bidi_buf, txt_flag, NULL, NULL, NULL);
|
||||
#endif
|
||||
lv_draw_label(&area_tmp, clip_area, btn_style, opa_scale, ext->map_p[txt_i], txt_flag, NULL, NULL, NULL, lv_obj_get_base_dir(btnm));
|
||||
}
|
||||
|
||||
#if LV_USE_BIDI
|
||||
lv_mem_free(bidi_buf);
|
||||
#endif
|
||||
}
|
||||
return LV_DESIGN_RES_OK;
|
||||
}
|
||||
|
||||
@@ -670,6 +670,9 @@ static lv_coord_t get_day_names_height(lv_obj_t * calendar)
|
||||
static void draw_header(lv_obj_t * calendar, const lv_area_t * mask)
|
||||
{
|
||||
lv_calendar_ext_t * ext = lv_obj_get_ext_attr(calendar);
|
||||
|
||||
lv_bidi_dir_t bidi_dir = lv_obj_get_base_dir(calendar);
|
||||
|
||||
lv_opa_t opa_scale = lv_obj_get_opa_scale(calendar);
|
||||
|
||||
lv_area_t header_area;
|
||||
@@ -687,19 +690,19 @@ static void draw_header(lv_obj_t * calendar, const lv_area_t * mask)
|
||||
txt_buf[5] = '\0';
|
||||
strcpy(&txt_buf[5], get_month_name(calendar, ext->showed_date.month));
|
||||
header_area.y1 += ext->style_header->body.padding.top;
|
||||
lv_draw_label(&header_area, mask, ext->style_header, opa_scale, txt_buf, LV_TXT_FLAG_CENTER, NULL, NULL, NULL);
|
||||
lv_draw_label(&header_area, mask, ext->style_header, opa_scale, txt_buf, LV_TXT_FLAG_CENTER, NULL, NULL, NULL, bidi_dir);
|
||||
|
||||
/*Add the left arrow*/
|
||||
const lv_style_t * arrow_style = ext->btn_pressing < 0 ? ext->style_header_pr : ext->style_header;
|
||||
header_area.x1 += ext->style_header->body.padding.left;
|
||||
lv_draw_label(&header_area, mask, arrow_style, opa_scale, LV_SYMBOL_LEFT, LV_TXT_FLAG_NONE, NULL, NULL, NULL);
|
||||
lv_draw_label(&header_area, mask, arrow_style, opa_scale, LV_SYMBOL_LEFT, LV_TXT_FLAG_NONE, NULL, NULL, NULL, bidi_dir);
|
||||
|
||||
/*Add the right arrow*/
|
||||
arrow_style = ext->btn_pressing > 0 ? ext->style_header_pr : ext->style_header;
|
||||
header_area.x1 = header_area.x2 - ext->style_header->body.padding.right -
|
||||
lv_txt_get_width(LV_SYMBOL_RIGHT, strlen(LV_SYMBOL_RIGHT), arrow_style->text.font,
|
||||
arrow_style->text.line_space, LV_TXT_FLAG_NONE);
|
||||
lv_draw_label(&header_area, mask, arrow_style, opa_scale, LV_SYMBOL_RIGHT, LV_TXT_FLAG_NONE, NULL, NULL, NULL);
|
||||
lv_draw_label(&header_area, mask, arrow_style, opa_scale, LV_SYMBOL_RIGHT, LV_TXT_FLAG_NONE, NULL, NULL, NULL, bidi_dir);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -710,6 +713,7 @@ static void draw_header(lv_obj_t * calendar, const lv_area_t * mask)
|
||||
static void draw_day_names(lv_obj_t * calendar, const lv_area_t * mask)
|
||||
{
|
||||
lv_calendar_ext_t * ext = lv_obj_get_ext_attr(calendar);
|
||||
lv_bidi_dir_t bidi_dir = lv_obj_get_base_dir(calendar);
|
||||
lv_opa_t opa_scale = lv_obj_get_opa_scale(calendar);
|
||||
|
||||
lv_coord_t l_pad = ext->style_day_names->body.padding.left;
|
||||
@@ -724,7 +728,7 @@ static void draw_day_names(lv_obj_t * calendar, const lv_area_t * mask)
|
||||
label_area.x1 = calendar->coords.x1 + (w * i) / 7 + l_pad;
|
||||
label_area.x2 = label_area.x1 + box_w - 1;
|
||||
lv_draw_label(&label_area, mask, ext->style_day_names, opa_scale, get_day_name(calendar, i), LV_TXT_FLAG_CENTER,
|
||||
NULL, NULL, NULL);
|
||||
NULL, NULL, NULL, bidi_dir);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -736,6 +740,7 @@ static void draw_day_names(lv_obj_t * calendar, const lv_area_t * mask)
|
||||
static void draw_days(lv_obj_t * calendar, const lv_area_t * mask)
|
||||
{
|
||||
lv_calendar_ext_t * ext = lv_obj_get_ext_attr(calendar);
|
||||
lv_bidi_dir_t bidi_dir = lv_obj_get_base_dir(calendar);
|
||||
const lv_style_t * style_bg = lv_calendar_get_style(calendar, LV_CALENDAR_STYLE_BG);
|
||||
lv_area_t label_area;
|
||||
lv_opa_t opa_scale = lv_obj_get_opa_scale(calendar);
|
||||
@@ -853,7 +858,7 @@ static void draw_days(lv_obj_t * calendar, const lv_area_t * mask)
|
||||
|
||||
/*Write the day's number*/
|
||||
lv_utils_num_to_str(day_cnt, buf);
|
||||
lv_draw_label(&label_area, mask, final_style, opa_scale, buf, LV_TXT_FLAG_CENTER, NULL, NULL, NULL);
|
||||
lv_draw_label(&label_area, mask, final_style, opa_scale, buf, LV_TXT_FLAG_CENTER, NULL, NULL, NULL, bidi_dir);
|
||||
|
||||
/*Go to the next day*/
|
||||
day_cnt++;
|
||||
|
||||
@@ -823,7 +823,7 @@ void lv_canvas_draw_text(lv_obj_t * canvas, lv_coord_t x, lv_coord_t y, lv_coord
|
||||
default: flag = LV_TXT_FLAG_NONE; break;
|
||||
}
|
||||
|
||||
lv_draw_label(&coords, &mask, style, LV_OPA_COVER, txt, flag, NULL, NULL, NULL);
|
||||
lv_draw_label(&coords, &mask, style, LV_OPA_COVER, txt, flag, NULL, NULL, NULL, lv_obj_get_base_dir(canvas));
|
||||
|
||||
lv_refr_set_disp_refreshing(refr_ori);
|
||||
}
|
||||
|
||||
@@ -1394,7 +1394,7 @@ static void lv_chart_draw_y_ticks(lv_obj_t * chart, const lv_area_t * mask, uint
|
||||
a.x2 = p2.x + size.x + LV_CHART_AXIS_TO_LABEL_DISTANCE;
|
||||
}
|
||||
|
||||
lv_draw_label(&a, mask, style, opa_scale, buf, LV_TXT_FLAG_CENTER, NULL, NULL, NULL);
|
||||
lv_draw_label(&a, mask, style, opa_scale, buf, LV_TXT_FLAG_CENTER, NULL, NULL, NULL, lv_obj_get_base_dir(chart));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1480,7 +1480,7 @@ static void lv_chart_draw_x_ticks(lv_obj_t * chart, const lv_area_t * mask)
|
||||
/* set the area at some distance of the major tick len under of the tick */
|
||||
lv_area_t a = {(p2.x - size.x / 2), (p2.y + LV_CHART_AXIS_TO_LABEL_DISTANCE), (p2.x + size.x / 2),
|
||||
(p2.y + size.y + LV_CHART_AXIS_TO_LABEL_DISTANCE)};
|
||||
lv_draw_label(&a, mask, style, opa_scale, buf, LV_TXT_FLAG_CENTER, NULL, NULL, NULL);
|
||||
lv_draw_label(&a, mask, style, opa_scale, buf, LV_TXT_FLAG_CENTER, NULL, NULL, NULL, lv_obj_get_base_dir(chart));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
/**
|
||||
* @file lv_cpicker.c
|
||||
*
|
||||
* From @AloyseTech and @paulpv.
|
||||
*/
|
||||
|
||||
/*********************
|
||||
@@ -57,10 +58,11 @@
|
||||
static lv_design_res_t lv_cpicker_design(lv_obj_t * cpicker, const lv_area_t * clip_area, lv_design_mode_t mode);
|
||||
static lv_res_t lv_cpicker_signal(lv_obj_t * cpicker, lv_signal_t sign, void * param);
|
||||
|
||||
static void invalidate_indic(lv_obj_t * cpicker);
|
||||
static void draw_rect_grad(lv_obj_t * cpicker, const lv_area_t * mask, lv_opa_t opa_scale);
|
||||
static void draw_disc_grad(lv_obj_t * cpicker, const lv_area_t * mask, lv_opa_t opa_scale);
|
||||
static void draw_indic(lv_obj_t * cpicker, const lv_area_t * mask, lv_opa_t opa_scale);
|
||||
static void invalidate_indic(lv_obj_t * cpicker);
|
||||
static lv_area_t get_indic_area(lv_obj_t * cpicker);
|
||||
|
||||
static void next_color_mode(lv_obj_t * cpicker);
|
||||
static lv_res_t double_click_reset(lv_obj_t * cpicker);
|
||||
@@ -105,6 +107,7 @@ lv_obj_t * lv_cpicker_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
if(ext == NULL) return NULL;
|
||||
|
||||
/*Initialize the allocated 'ext' */
|
||||
ext->type = LV_CPICKER_DEF_TYPE;
|
||||
ext->hsv = LV_CPICKER_DEF_HSV;
|
||||
ext->indic.style = &lv_style_plain;
|
||||
ext->indic.colored = 0;
|
||||
@@ -120,8 +123,8 @@ lv_obj_t * lv_cpicker_create(lv_obj_t * par, const lv_obj_t * copy)
|
||||
|
||||
/*If no copy do the basic initialization*/
|
||||
if(copy == NULL) {
|
||||
lv_obj_set_size(new_cpicker, LV_DPI * 2, LV_DPI * 2);
|
||||
lv_obj_set_protect(new_cpicker, LV_PROTECT_PRESS_LOST);
|
||||
refr_indic_pos(new_cpicker);
|
||||
lv_theme_t * th = lv_theme_get_current();
|
||||
if(th) {
|
||||
lv_cpicker_set_style(new_cpicker, LV_CPICKER_STYLE_MAIN, th->style.bg);
|
||||
@@ -200,91 +203,85 @@ void lv_cpicker_set_style(lv_obj_t * cpicker, lv_cpicker_style_t type, lv_style_
|
||||
* Set the current hue of a colorpicker.
|
||||
* @param cpicker pointer to colorpicker object
|
||||
* @param hue current selected hue [0..360]
|
||||
* @return true if changed, otherwise false
|
||||
*/
|
||||
void lv_cpicker_set_hue(lv_obj_t * cpicker, uint16_t hue)
|
||||
bool lv_cpicker_set_hue(lv_obj_t * cpicker, uint16_t hue)
|
||||
{
|
||||
LV_ASSERT_OBJ(cpicker, LV_OBJX_NAME);
|
||||
|
||||
lv_cpicker_ext_t * ext = lv_obj_get_ext_attr(cpicker);
|
||||
|
||||
ext->hsv.h = hue % 360;
|
||||
|
||||
if(ext->color_mode == LV_CPICKER_COLOR_MODE_HUE) refr_indic_pos(cpicker);
|
||||
|
||||
if(ext->preview && ext->type == LV_CPICKER_TYPE_DISC) {
|
||||
lv_obj_invalidate(cpicker);
|
||||
}
|
||||
lv_color_hsv_t hsv = lv_cpicker_get_hsv(cpicker);
|
||||
hsv.h = hue;
|
||||
return lv_cpicker_set_hsv(cpicker, hsv);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the current saturation of a colorpicker.
|
||||
* @param cpicker pointer to colorpicker object
|
||||
* @param saturation current selected saturation [0..100]
|
||||
* @return true if changed, otherwise false
|
||||
*/
|
||||
void lv_cpicker_set_saturation(lv_obj_t * cpicker, uint8_t saturation)
|
||||
bool lv_cpicker_set_saturation(lv_obj_t * cpicker, uint8_t saturation)
|
||||
{
|
||||
LV_ASSERT_OBJ(cpicker, LV_OBJX_NAME);
|
||||
|
||||
lv_cpicker_ext_t * ext = lv_obj_get_ext_attr(cpicker);
|
||||
|
||||
ext->hsv.s = saturation > 100 ? 100 : saturation;
|
||||
|
||||
if(ext->color_mode == LV_CPICKER_COLOR_MODE_SATURATION) refr_indic_pos(cpicker);
|
||||
|
||||
if(ext->preview && ext->type == LV_CPICKER_TYPE_DISC) {
|
||||
lv_obj_invalidate(cpicker);
|
||||
}
|
||||
lv_color_hsv_t hsv = lv_cpicker_get_hsv(cpicker);
|
||||
hsv.s = saturation;
|
||||
return lv_cpicker_set_hsv(cpicker, hsv);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the current value of a colorpicker.
|
||||
* @param cpicker pointer to colorpicker object
|
||||
* @param val current selected value [0..100]
|
||||
* @return true if changed, otherwise false
|
||||
*/
|
||||
void lv_cpicker_set_value(lv_obj_t * cpicker, uint8_t val)
|
||||
bool lv_cpicker_set_value(lv_obj_t * cpicker, uint8_t val)
|
||||
{
|
||||
LV_ASSERT_OBJ(cpicker, LV_OBJX_NAME);
|
||||
|
||||
lv_cpicker_ext_t * ext = lv_obj_get_ext_attr(cpicker);
|
||||
|
||||
ext->hsv.v = val > 100 ? 100 : val;
|
||||
|
||||
if(ext->color_mode == LV_CPICKER_COLOR_MODE_VALUE) refr_indic_pos(cpicker);
|
||||
|
||||
if(ext->preview && ext->type == LV_CPICKER_TYPE_DISC) {
|
||||
lv_obj_invalidate(cpicker);
|
||||
}
|
||||
lv_color_hsv_t hsv = lv_cpicker_get_hsv(cpicker);
|
||||
hsv.v = val;
|
||||
return lv_cpicker_set_hsv(cpicker, hsv);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the current hsv of a colorpicker.
|
||||
* @param cpicker pointer to colorpicker object
|
||||
* @param color current selected hsv
|
||||
* @return true if changed, otherwise false
|
||||
*/
|
||||
void lv_cpicker_set_hsv(lv_obj_t * cpicker, lv_color_hsv_t hsv)
|
||||
bool lv_cpicker_set_hsv(lv_obj_t * cpicker, lv_color_hsv_t hsv)
|
||||
{
|
||||
LV_ASSERT_OBJ(cpicker, LV_OBJX_NAME);
|
||||
|
||||
if (hsv.h > 360) hsv.h %= 360;
|
||||
if (hsv.s > 100) hsv.s = 100;
|
||||
if (hsv.v > 100) hsv.v = 100;
|
||||
|
||||
lv_cpicker_ext_t * ext = lv_obj_get_ext_attr(cpicker);
|
||||
|
||||
if (ext->hsv.h == hsv.h && ext->hsv.s == hsv.s && ext->hsv.v == hsv.v) return false;
|
||||
|
||||
ext->hsv = hsv;
|
||||
|
||||
refr_indic_pos(cpicker);
|
||||
lv_obj_invalidate(cpicker);
|
||||
|
||||
if (ext->preview && ext->type == LV_CPICKER_TYPE_DISC) {
|
||||
lv_obj_invalidate(cpicker);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the current color of a colorpicker.
|
||||
* @param cpicker pointer to colorpicker object
|
||||
* @param color current selected color
|
||||
* @return true if changed, otherwise false
|
||||
*/
|
||||
void lv_cpicker_set_color(lv_obj_t * cpicker, lv_color_t color)
|
||||
bool lv_cpicker_set_color(lv_obj_t * cpicker, lv_color_t color)
|
||||
{
|
||||
LV_ASSERT_OBJ(cpicker, LV_OBJX_NAME);
|
||||
|
||||
lv_color32_t c32;
|
||||
c32.full = lv_color_to32(color);
|
||||
|
||||
lv_cpicker_set_hsv(cpicker, lv_color_rgb_to_hsv(c32.ch.red, c32.ch.green, c32.ch.blue));
|
||||
return lv_cpicker_set_hsv(cpicker,
|
||||
lv_color_rgb_to_hsv(LV_COLOR_GET_R(color), LV_COLOR_GET_G(color), LV_COLOR_GET_B(color)));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -662,25 +659,10 @@ static void draw_rect_grad(lv_obj_t * cpicker, const lv_area_t * mask, lv_opa_t
|
||||
lv_draw_rect(&rect_area, mask, &style, opa_scale);
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Should roughly match up with `lv_cpicker_invalidate_disc_indicator_circle`
|
||||
*/
|
||||
|
||||
static void draw_indic(lv_obj_t * cpicker, const lv_area_t * mask, lv_opa_t opa_scale)
|
||||
{
|
||||
lv_cpicker_ext_t * ext = lv_obj_get_ext_attr(cpicker);
|
||||
const lv_style_t * style_main = lv_cpicker_get_style(cpicker, LV_CPICKER_STYLE_MAIN);
|
||||
const lv_style_t * style_indic = lv_cpicker_get_style(cpicker, LV_CPICKER_STYLE_INDICATOR);
|
||||
|
||||
lv_coord_t h = lv_obj_get_height(cpicker);
|
||||
uint16_t r;
|
||||
if(ext->type == LV_CPICKER_TYPE_DISC) r = style_main->line.width / 2;
|
||||
else if(ext->type == LV_CPICKER_TYPE_RECT) r = h / 2;
|
||||
|
||||
lv_area_t ind_area;
|
||||
ind_area.x1 = cpicker->coords.x1 + ext->indic.pos.x - r - style_indic->body.padding.left;
|
||||
ind_area.y1 = cpicker->coords.y1 + ext->indic.pos.y - r - style_indic->body.padding.right;
|
||||
ind_area.x2 = cpicker->coords.x1 + ext->indic.pos.x + r + style_indic->body.padding.top;
|
||||
ind_area.y2 = cpicker->coords.y1 + ext->indic.pos.y + r + style_indic->body.padding.bottom;
|
||||
|
||||
lv_style_t style_cir;
|
||||
lv_style_copy(&style_cir, ext->indic.style);
|
||||
@@ -691,8 +673,38 @@ static void draw_indic(lv_obj_t * cpicker, const lv_area_t * mask, lv_opa_t opa_
|
||||
style_cir.body.grad_color = style_cir.body.main_color;
|
||||
}
|
||||
|
||||
lv_area_t indic_area = get_indic_area(cpicker);
|
||||
|
||||
lv_draw_rect(&ind_area, mask, &style_cir, opa_scale);
|
||||
lv_draw_rect(&indic_area, mask, &style_cir, opa_scale);
|
||||
}
|
||||
|
||||
static void invalidate_indic(lv_obj_t * cpicker)
|
||||
{
|
||||
lv_area_t indic_area = get_indic_area(cpicker);
|
||||
|
||||
lv_inv_area(lv_obj_get_disp(cpicker), &indic_area);
|
||||
}
|
||||
|
||||
static lv_area_t get_indic_area(lv_obj_t * cpicker)
|
||||
{
|
||||
lv_cpicker_ext_t * ext = lv_obj_get_ext_attr(cpicker);
|
||||
const lv_style_t * style_main = lv_cpicker_get_style(cpicker, LV_CPICKER_STYLE_MAIN);
|
||||
const lv_style_t * style_indic = lv_cpicker_get_style(cpicker, LV_CPICKER_STYLE_INDICATOR);
|
||||
|
||||
uint16_t r;
|
||||
if(ext->type == LV_CPICKER_TYPE_DISC) r = style_main->line.width / 2;
|
||||
else if(ext->type == LV_CPICKER_TYPE_RECT) {
|
||||
lv_coord_t h = lv_obj_get_height(cpicker);
|
||||
r = h / 2;
|
||||
}
|
||||
|
||||
lv_area_t indic_area;
|
||||
indic_area.x1 = cpicker->coords.x1 + ext->indic.pos.x - r - style_indic->body.padding.left;
|
||||
indic_area.y1 = cpicker->coords.y1 + ext->indic.pos.y - r - style_indic->body.padding.right;
|
||||
indic_area.x2 = cpicker->coords.x1 + ext->indic.pos.x + r + style_indic->body.padding.top;
|
||||
indic_area.y2 = cpicker->coords.y1 + ext->indic.pos.y + r + style_indic->body.padding.bottom;
|
||||
|
||||
return indic_area;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -725,8 +737,7 @@ static lv_res_t lv_cpicker_signal(lv_obj_t * cpicker, lv_signal_t sign, void * p
|
||||
} else if(sign == LV_SIGNAL_CORD_CHG) {
|
||||
/*Refresh extended draw area to make knob visible*/
|
||||
if(lv_obj_get_width(cpicker) != lv_area_get_width(param) ||
|
||||
lv_obj_get_height(cpicker) != lv_area_get_height(param))
|
||||
{
|
||||
lv_obj_get_height(cpicker) != lv_area_get_height(param)) {
|
||||
lv_obj_refresh_ext_draw_pad(cpicker);
|
||||
refr_indic_pos(cpicker);
|
||||
}
|
||||
@@ -753,10 +764,10 @@ static lv_res_t lv_cpicker_signal(lv_obj_t * cpicker, lv_signal_t sign, void * p
|
||||
break;
|
||||
}
|
||||
|
||||
lv_cpicker_set_hsv(cpicker, hsv_cur);
|
||||
|
||||
res = lv_event_send(cpicker, LV_EVENT_VALUE_CHANGED, NULL);
|
||||
if(res != LV_RES_OK) return res;
|
||||
if (lv_cpicker_set_hsv(cpicker, hsv_cur)) {
|
||||
res = lv_event_send(cpicker, LV_EVENT_VALUE_CHANGED, NULL);
|
||||
if(res != LV_RES_OK) return res;
|
||||
}
|
||||
}
|
||||
else if(c == LV_KEY_LEFT || c == LV_KEY_DOWN) {
|
||||
lv_color_hsv_t hsv_cur;
|
||||
@@ -774,10 +785,10 @@ static lv_res_t lv_cpicker_signal(lv_obj_t * cpicker, lv_signal_t sign, void * p
|
||||
break;
|
||||
}
|
||||
|
||||
lv_cpicker_set_hsv(cpicker, hsv_cur);
|
||||
|
||||
res = lv_event_send(cpicker, LV_EVENT_VALUE_CHANGED, NULL);
|
||||
if(res != LV_RES_OK) return res;
|
||||
if (lv_cpicker_set_hsv(cpicker, hsv_cur)) {
|
||||
res = lv_event_send(cpicker, LV_EVENT_VALUE_CHANGED, NULL);
|
||||
if(res != LV_RES_OK) return res;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(sign == LV_SIGNAL_PRESSED) {
|
||||
@@ -785,7 +796,7 @@ static lv_res_t lv_cpicker_signal(lv_obj_t * cpicker, lv_signal_t sign, void * p
|
||||
lv_indev_get_point(lv_indev_get_act(), &ext->last_press_point);
|
||||
res = double_click_reset(cpicker);
|
||||
if(res != LV_RES_OK) return res;
|
||||
} else if(sign == LV_SIGNAL_PRESSING){
|
||||
} else if(sign == LV_SIGNAL_PRESSING) {
|
||||
lv_indev_t * indev = lv_indev_get_act();
|
||||
if(indev == NULL) return res;
|
||||
|
||||
@@ -846,30 +857,31 @@ static lv_res_t lv_cpicker_signal(lv_obj_t * cpicker, lv_signal_t sign, void * p
|
||||
angle = lv_atan2(p.x, p.y) % 360;
|
||||
}
|
||||
|
||||
lv_color_hsv_t hsv_cur;
|
||||
hsv_cur = ext->hsv;
|
||||
|
||||
switch(ext->color_mode) {
|
||||
case LV_CPICKER_COLOR_MODE_HUE:
|
||||
if(ext->hsv.h != angle) lv_cpicker_set_hue(cpicker, angle);
|
||||
hsv_cur.h = angle;
|
||||
break;
|
||||
case LV_CPICKER_COLOR_MODE_SATURATION:
|
||||
angle = (angle * 100) / 360;
|
||||
if(ext->hsv.s != angle) lv_cpicker_set_saturation(cpicker, angle);
|
||||
hsv_cur.s = (angle * 100) / 360;
|
||||
break;
|
||||
case LV_CPICKER_COLOR_MODE_VALUE:
|
||||
angle = (angle * 100) / 360;
|
||||
if(ext->hsv.v != angle) lv_cpicker_set_value(cpicker, angle);
|
||||
hsv_cur.v = (angle * 100) / 360;
|
||||
break;
|
||||
}
|
||||
|
||||
refr_indic_pos(cpicker);
|
||||
|
||||
res = lv_event_send(cpicker, LV_EVENT_VALUE_CHANGED, NULL);
|
||||
if(res != LV_RES_OK) return res;
|
||||
if (lv_cpicker_set_hsv(cpicker, hsv_cur)) {
|
||||
res = lv_event_send(cpicker, LV_EVENT_VALUE_CHANGED, NULL);
|
||||
if(res != LV_RES_OK) return res;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static void next_color_mode(lv_obj_t * cpicker )
|
||||
static void next_color_mode(lv_obj_t * cpicker)
|
||||
{
|
||||
lv_cpicker_ext_t * ext = lv_obj_get_ext_attr(cpicker);
|
||||
ext->color_mode = (ext->color_mode + 1) % 3;
|
||||
@@ -877,32 +889,6 @@ static void next_color_mode(lv_obj_t * cpicker )
|
||||
lv_obj_invalidate(cpicker);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Indicator points need to match those set in lv_cpicker_disc_design/lv_cpicker_rect_design
|
||||
*/
|
||||
static void invalidate_indic(lv_obj_t * cpicker)
|
||||
{
|
||||
|
||||
lv_cpicker_ext_t * ext = lv_obj_get_ext_attr(cpicker);
|
||||
const lv_style_t * style_main = lv_cpicker_get_style(cpicker, LV_CPICKER_STYLE_MAIN);
|
||||
const lv_style_t * style_indic = lv_cpicker_get_style(cpicker, LV_CPICKER_STYLE_INDICATOR);
|
||||
|
||||
lv_coord_t h = lv_obj_get_height(cpicker);
|
||||
|
||||
uint16_t r;
|
||||
if(ext->type == LV_CPICKER_TYPE_DISC) r = style_main->line.width / 2;
|
||||
else if(ext->type == LV_CPICKER_TYPE_RECT) r = h / 2;
|
||||
|
||||
lv_area_t indic_area;
|
||||
indic_area.x1 = cpicker->coords.x1 + ext->indic.pos.x - r - style_indic->body.padding.left;
|
||||
indic_area.y1 = cpicker->coords.y1 + ext->indic.pos.y - r - style_indic->body.padding.top;
|
||||
indic_area.x2 = cpicker->coords.x1 + ext->indic.pos.x + r + style_indic->body.padding.right;
|
||||
indic_area.y2 = cpicker->coords.y1 + ext->indic.pos.y + r + style_indic->body.padding.bottom;
|
||||
|
||||
lv_inv_area(lv_obj_get_disp(cpicker), &indic_area);
|
||||
}
|
||||
|
||||
static void refr_indic_pos(lv_obj_t * cpicker)
|
||||
{
|
||||
invalidate_indic(cpicker);
|
||||
@@ -927,15 +913,14 @@ static void refr_indic_pos(lv_obj_t * cpicker)
|
||||
|
||||
ext->indic.pos.x = ind_pos;
|
||||
ext->indic.pos.y = h / 2;
|
||||
}
|
||||
if(ext->type == LV_CPICKER_TYPE_DISC) {
|
||||
} else if(ext->type == LV_CPICKER_TYPE_DISC) {
|
||||
const lv_style_t * style_main = lv_cpicker_get_style(cpicker, LV_CPICKER_STYLE_MAIN);
|
||||
lv_coord_t r = w / 2 - style_main->line.width / 2;
|
||||
uint16_t angle = get_angle(cpicker);
|
||||
ext->indic.pos.x = (((int32_t)r * lv_trigo_sin(angle)) >> LV_TRIGO_SHIFT);
|
||||
ext->indic.pos.y = (((int32_t)r * lv_trigo_sin(angle + 90)) >> LV_TRIGO_SHIFT);
|
||||
ext->indic.pos.x = ext->indic.pos.x + w / 2;
|
||||
ext->indic.pos.y = ext->indic.pos.y + w / 2;
|
||||
ext->indic.pos.y = ext->indic.pos.y + h / 2;
|
||||
}
|
||||
|
||||
invalidate_indic(cpicker);
|
||||
@@ -947,21 +932,25 @@ static lv_res_t double_click_reset(lv_obj_t * cpicker)
|
||||
lv_indev_t * indev = lv_indev_get_act();
|
||||
/*Double clicked? Use long press time as double click time out*/
|
||||
if(lv_tick_elaps(ext->last_click_time) < indev->driver.long_press_time) {
|
||||
lv_color_hsv_t hsv_cur;
|
||||
hsv_cur = ext->hsv;
|
||||
|
||||
switch(ext->color_mode) {
|
||||
case LV_CPICKER_COLOR_MODE_HUE:
|
||||
lv_cpicker_set_hue(cpicker, LV_CPICKER_DEF_HUE);
|
||||
hsv_cur.h = LV_CPICKER_DEF_HUE;
|
||||
break;
|
||||
case LV_CPICKER_COLOR_MODE_SATURATION:
|
||||
lv_cpicker_set_saturation(cpicker, LV_CPICKER_DEF_SATURATION);
|
||||
hsv_cur.s = LV_CPICKER_DEF_SATURATION;
|
||||
break;
|
||||
case LV_CPICKER_COLOR_MODE_VALUE:
|
||||
lv_cpicker_set_value(cpicker, LV_CPICKER_DEF_VALUE);
|
||||
hsv_cur.v = LV_CPICKER_DEF_VALUE;
|
||||
break;
|
||||
}
|
||||
|
||||
lv_res_t res;
|
||||
res = lv_event_send(cpicker, LV_EVENT_VALUE_CHANGED, NULL);
|
||||
if(res != LV_RES_OK) return res;
|
||||
if (lv_cpicker_set_hsv(cpicker, hsv_cur)) {
|
||||
lv_res_t res = lv_event_send(cpicker, LV_EVENT_VALUE_CHANGED, NULL);
|
||||
if(res != LV_RES_OK) return res;
|
||||
}
|
||||
}
|
||||
ext->last_click_time = lv_tick_get();
|
||||
|
||||
|
||||
@@ -93,7 +93,7 @@ lv_obj_t * lv_cpicker_create(lv_obj_t * par, const lv_obj_t * copy);
|
||||
* @param cpicker pointer to a colorpicker object
|
||||
* @param type new type of the colorpicker (from 'lv_cpicker_type_t' enum)
|
||||
*/
|
||||
void lv_cpicker_set_type(lv_obj_t * chart, lv_cpicker_type_t type);
|
||||
void lv_cpicker_set_type(lv_obj_t * cpicker, lv_cpicker_type_t type);
|
||||
|
||||
/**
|
||||
* Set a style of a colorpicker.
|
||||
@@ -106,37 +106,42 @@ void lv_cpicker_set_style(lv_obj_t * cpicker, lv_cpicker_style_t type, lv_style_
|
||||
/**
|
||||
* Set the current hue of a colorpicker.
|
||||
* @param cpicker pointer to colorpicker object
|
||||
* @param hue current selected hue
|
||||
* @param hue current selected hue [0..360]
|
||||
* @return true if changed, otherwise false
|
||||
*/
|
||||
void lv_cpicker_set_hue(lv_obj_t * cpicker, uint16_t hue);
|
||||
bool lv_cpicker_set_hue(lv_obj_t * cpicker, uint16_t hue);
|
||||
|
||||
/**
|
||||
* Set the current saturation of a colorpicker.
|
||||
* @param cpicker pointer to colorpicker object
|
||||
* @param saturation current selected saturation
|
||||
* @param saturation current selected saturation [0..100]
|
||||
* @return true if changed, otherwise false
|
||||
*/
|
||||
void lv_cpicker_set_saturation(lv_obj_t * cpicker, uint8_t saturation);
|
||||
bool lv_cpicker_set_saturation(lv_obj_t * cpicker, uint8_t saturation);
|
||||
|
||||
/**
|
||||
* Set the current value of a colorpicker.
|
||||
* @param cpicker pointer to colorpicker object
|
||||
* @param val current selected value
|
||||
* @param val current selected value [0..100]
|
||||
* @return true if changed, otherwise false
|
||||
*/
|
||||
void lv_cpicker_set_value(lv_obj_t * cpicker, uint8_t val);
|
||||
bool lv_cpicker_set_value(lv_obj_t * cpicker, uint8_t val);
|
||||
|
||||
/**
|
||||
* Set the current hsv of a colorpicker.
|
||||
* @param cpicker pointer to colorpicker object
|
||||
* @param hsv current selected hsv
|
||||
* @return true if changed, otherwise false
|
||||
*/
|
||||
void lv_cpicker_set_hsv(lv_obj_t * cpicker, lv_color_hsv_t hsv);
|
||||
bool lv_cpicker_set_hsv(lv_obj_t * cpicker, lv_color_hsv_t hsv);
|
||||
|
||||
/**
|
||||
* Set the current color of a colorpicker.
|
||||
* @param cpicker pointer to colorpicker object
|
||||
* @param color current selected color
|
||||
* @return true if changed, otherwise false
|
||||
*/
|
||||
void lv_cpicker_set_color(lv_obj_t * cpicker, lv_color_t color);
|
||||
bool lv_cpicker_set_color(lv_obj_t * cpicker, lv_color_t color);
|
||||
|
||||
/**
|
||||
* Set the current color mode.
|
||||
|
||||
@@ -609,7 +609,7 @@ static lv_design_res_t lv_ddlist_design(lv_obj_t * ddlist, const lv_area_t * cli
|
||||
new_style.text.opa = sel_style->text.opa;
|
||||
lv_txt_flag_t flag = lv_ddlist_get_txt_flag(ddlist);
|
||||
lv_draw_label(&ext->label->coords, &mask_sel, &new_style, opa_scale, lv_label_get_text(ext->label),
|
||||
flag, NULL, NULL, NULL);
|
||||
flag, NULL, NULL, NULL, lv_obj_get_base_dir(ddlist));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -642,9 +642,9 @@ static lv_design_res_t lv_ddlist_design(lv_obj_t * ddlist, const lv_area_t * cli
|
||||
bool area_ok;
|
||||
area_ok = lv_area_intersect(&mask_arrow, clip_area, &area_arrow);
|
||||
if(area_ok) {
|
||||
/*Use a down arrow in ddlist, you can replace it with yourcustom symbol*/
|
||||
lv_draw_label(&area_arrow, &mask_arrow, &new_style, opa_scale, LV_SYMBOL_DOWN, LV_TXT_FLAG_NONE,
|
||||
NULL, NULL, NULL); /*Use a down arrow in ddlist, you can replace it with your
|
||||
custom symbol*/
|
||||
NULL, NULL, NULL, lv_obj_get_base_dir(ddlist));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -389,7 +389,7 @@ static void lv_gauge_draw_scale(lv_obj_t * gauge, const lv_area_t * mask)
|
||||
label_cord.x2 = label_cord.x1 + label_size.x;
|
||||
label_cord.y2 = label_cord.y1 + label_size.y;
|
||||
|
||||
lv_draw_label(&label_cord, mask, style, opa_scale, scale_txt, LV_TXT_FLAG_NONE, NULL, NULL, NULL);
|
||||
lv_draw_label(&label_cord, mask, style, opa_scale, scale_txt, LV_TXT_FLAG_NONE, NULL, NULL, NULL, lv_obj_get_base_dir(gauge));
|
||||
}
|
||||
}
|
||||
/**
|
||||
|
||||
@@ -479,10 +479,10 @@ static lv_design_res_t lv_img_design(lv_obj_t * img, const lv_area_t * clip_area
|
||||
cords_tmp.y1 = coords.y1;
|
||||
cords_tmp.y2 = coords.y1 + ext->h - 1;
|
||||
|
||||
for(; cords_tmp.y1 < coords.y2; cords_tmp.y1 += ext->h, cords_tmp.y2 += ext->h) {
|
||||
for(; cords_tmp.y1 <= coords.y2; cords_tmp.y1 += ext->h, cords_tmp.y2 += ext->h) {
|
||||
cords_tmp.x1 = coords.x1;
|
||||
cords_tmp.x2 = coords.x1 + ext->w - 1;
|
||||
for(; cords_tmp.x1 < coords.x2; cords_tmp.x1 += ext->w, cords_tmp.x2 += ext->w) {
|
||||
for(; cords_tmp.x1 <= coords.x2; cords_tmp.x1 += ext->w, cords_tmp.x2 += ext->w) {
|
||||
lv_draw_img(&cords_tmp, clip_area, ext->src, style, ext->angle, ext->zoom, ext->antialias, opa_scale);
|
||||
}
|
||||
}
|
||||
@@ -491,7 +491,7 @@ static lv_design_res_t lv_img_design(lv_obj_t * img, const lv_area_t * clip_area
|
||||
lv_style_t style_mod;
|
||||
lv_style_copy(&style_mod, style);
|
||||
style_mod.text.color = style->image.color;
|
||||
lv_draw_label(&coords, clip_area, &style_mod, opa_scale, ext->src, LV_TXT_FLAG_NONE, NULL, NULL, NULL);
|
||||
lv_draw_label(&coords, clip_area, &style_mod, opa_scale, ext->src, LV_TXT_FLAG_NONE, NULL, NULL, NULL, lv_obj_get_base_dir(img));
|
||||
} else {
|
||||
/*Trigger the error handler of image drawer*/
|
||||
LV_LOG_WARN("lv_img_design: image source type is unknown");
|
||||
|
||||
@@ -301,7 +301,7 @@ static lv_design_res_t lv_imgbtn_design(lv_obj_t * imgbtn, const lv_area_t * cli
|
||||
#if LV_IMGBTN_TILED == 0
|
||||
const void * src = ext->img_src[state];
|
||||
if(lv_img_src_get_type(src) == LV_IMG_SRC_SYMBOL) {
|
||||
lv_draw_label(&imgbtn->coords, clip_area, style, opa_scale, src, LV_TXT_FLAG_NONE, NULL, NULL, NULL);
|
||||
lv_draw_label(&imgbtn->coords, clip_area, style, opa_scale, src, LV_TXT_FLAG_NONE, NULL, NULL, NULL, lv_obj_get_base_dir(imgbtn));
|
||||
} else {
|
||||
lv_draw_img(&imgbtn->coords, clip_area, src, style, 0, LV_IMG_ZOOM_NONE, false, opa_scale);
|
||||
}
|
||||
|
||||
@@ -396,7 +396,7 @@ void lv_kb_def_event_cb(lv_obj_t * kb, lv_event_t event)
|
||||
/*Add the characters to the text area if set*/
|
||||
if(ext->ta == NULL) return;
|
||||
|
||||
if(strcmp(txt, LV_SYMBOL_NEW_LINE) == 0)
|
||||
if(strcmp(txt, "Enter") == 0 || strcmp(txt, LV_SYMBOL_NEW_LINE) == 0)
|
||||
lv_ta_add_char(ext->ta, '\n');
|
||||
else if(strcmp(txt, LV_SYMBOL_LEFT) == 0)
|
||||
lv_ta_cursor_left(ext->ta);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -582,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);
|
||||
@@ -610,12 +606,12 @@ void lv_label_get_letter_pos(const lv_obj_t * label, uint16_t index, lv_point_t
|
||||
max_w = LV_COORD_MAX;
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -623,26 +619,50 @@ void lv_label_get_letter_pos(const lv_obj_t * label, uint16_t index, lv_point_t
|
||||
}
|
||||
|
||||
/*If the last character is line break then go to the next line*/
|
||||
if(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;
|
||||
}
|
||||
}
|
||||
|
||||
/*Calculate the x coordinate*/
|
||||
lv_coord_t x = lv_txt_get_width(&txt[line_start], index - line_start, font, style->text.letter_space, flag);
|
||||
const char *bidi_txt;
|
||||
uint16_t visual_byte_pos;
|
||||
#if LV_USE_BIDI
|
||||
/*Handle Bidi*/
|
||||
if(new_line_start == byte_id) {
|
||||
visual_byte_pos = byte_id - line_start;
|
||||
bidi_txt = &txt[line_start];
|
||||
}
|
||||
else {
|
||||
uint16_t line_char_id = lv_txt_encoded_get_char_id(&txt[line_start], byte_id - line_start);
|
||||
|
||||
if(index != line_start) x += style->text.letter_space;
|
||||
bool is_rtl;
|
||||
char *mutable_bidi_txt;
|
||||
uint16_t visual_char_pos = lv_bidi_get_visual_pos(&txt[line_start], &mutable_bidi_txt, new_line_start - line_start, lv_obj_get_base_dir(label), line_char_id, &is_rtl);
|
||||
bidi_txt = mutable_bidi_txt;
|
||||
if (is_rtl) visual_char_pos++;
|
||||
visual_byte_pos = lv_txt_encoded_get_byte_id(bidi_txt, visual_char_pos);
|
||||
}
|
||||
#else
|
||||
bidi_txt = &txt[line_start];
|
||||
visual_byte_pos = byte_id - line_start;
|
||||
#endif
|
||||
|
||||
|
||||
/*Calculate the x coordinate*/
|
||||
lv_coord_t x = lv_txt_get_width(bidi_txt, visual_byte_pos, font, style->text.letter_space, flag);
|
||||
|
||||
if(char_id != line_start) x += style->text.letter_space;
|
||||
|
||||
if(align == LV_LABEL_ALIGN_CENTER) {
|
||||
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;
|
||||
}
|
||||
@@ -672,6 +692,8 @@ uint16_t lv_label_get_letter_on(const lv_obj_t * label, lv_point_t * pos)
|
||||
uint8_t letter_height = lv_font_get_line_height(font);
|
||||
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;
|
||||
@@ -689,43 +711,60 @@ uint16_t lv_label_get_letter_on(const lv_obj_t * label, lv_point_t * pos)
|
||||
while(txt[line_start] != '\0') {
|
||||
new_line_start += lv_txt_get_next_line(&txt[line_start], font, style->text.letter_space, max_w, flag);
|
||||
|
||||
if(pos->y <= y + letter_height) break; /*The line is found (stored in 'line_start')*/
|
||||
if(pos->y <= y + letter_height) {
|
||||
/*The line is found (stored in 'line_start')*/
|
||||
/* Include the NULL terminator in the last line */
|
||||
uint32_t tmp = new_line_start;
|
||||
uint32_t letter;
|
||||
letter = lv_txt_encoded_prev(txt, &tmp);
|
||||
if(letter != '\n' && txt[new_line_start] == '\0' ) new_line_start++;
|
||||
break;
|
||||
}
|
||||
y += letter_height + style->text.line_space;
|
||||
|
||||
line_start = new_line_start;
|
||||
}
|
||||
|
||||
#if LV_USE_BIDI
|
||||
bidi_txt = lv_draw_get_buf(new_line_start - line_start + 1);
|
||||
uint16_t txt_len = new_line_start - line_start;
|
||||
if(bidi_txt[new_line_start] == '\0') txt_len--;
|
||||
lv_bidi_process_paragraph(txt + line_start, bidi_txt, txt_len, lv_obj_get_base_dir(label), NULL, 0);
|
||||
#else
|
||||
bidi_txt = (char*)txt + line_start;
|
||||
#endif
|
||||
|
||||
/*Calculate the x coordinate*/
|
||||
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*/
|
||||
}
|
||||
}
|
||||
@@ -733,7 +772,7 @@ uint16_t lv_label_get_letter_on(const lv_obj_t * label, lv_point_t * pos)
|
||||
x += lv_font_get_glyph_width(font, letter, letter_next);
|
||||
|
||||
/*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;
|
||||
}
|
||||
@@ -742,7 +781,16 @@ uint16_t lv_label_get_letter_on(const lv_obj_t * label, lv_point_t * pos)
|
||||
}
|
||||
}
|
||||
|
||||
return lv_encoded_get_char_id(txt, i);
|
||||
#if LV_USE_BIDI
|
||||
/*Handle Bidi*/
|
||||
bool is_rtl;
|
||||
logical_pos = lv_bidi_get_logical_pos(&txt[line_start], NULL, txt_len, lv_obj_get_base_dir(label), lv_txt_encoded_get_char_id(bidi_txt, i), &is_rtl);
|
||||
if (is_rtl) logical_pos++;
|
||||
#else
|
||||
logical_pos = lv_txt_encoded_get_char_id(bidi_txt, i);
|
||||
#endif
|
||||
|
||||
return logical_pos + lv_txt_encoded_get_char_id(txt, line_start);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -803,10 +851,11 @@ bool lv_label_is_char_under_pos(const lv_obj_t * label, lv_point_t * pos)
|
||||
uint8_t letter_height = lv_font_get_line_height(font);
|
||||
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) {
|
||||
@@ -826,11 +875,16 @@ bool lv_label_is_char_under_pos(const lv_obj_t * label, lv_point_t * pos)
|
||||
/*Calculate the x coordinate*/
|
||||
lv_coord_t x = 0;
|
||||
lv_coord_t last_x = 0;
|
||||
if(ext->align == LV_LABEL_ALIGN_CENTER) {
|
||||
if(align == LV_LABEL_ALIGN_CENTER) {
|
||||
lv_coord_t line_w;
|
||||
line_w = lv_txt_get_width(&txt[line_start], new_line_start - line_start, font, style->text.letter_space, flag);
|
||||
x += lv_obj_get_width(label) / 2 - line_w / 2;
|
||||
}
|
||||
else if(align == LV_LABEL_ALIGN_RIGHT) {
|
||||
lv_coord_t line_w;
|
||||
line_w = lv_txt_get_width(&txt[line_start], new_line_start - line_start, font, style->text.letter_space, flag);
|
||||
x += lv_obj_get_width(label) - line_w;
|
||||
}
|
||||
|
||||
lv_txt_cmd_state_t cmd_state = LV_TXT_CMD_STATE_WAIT;
|
||||
|
||||
@@ -915,8 +969,6 @@ void lv_label_ins_text(lv_obj_t * label, uint32_t pos, const char * txt)
|
||||
lv_mem_free(bidi_buf);
|
||||
#else
|
||||
lv_txt_ins(ext->text, pos, txt);
|
||||
#endif
|
||||
|
||||
lv_label_refr_text(label);
|
||||
}
|
||||
|
||||
@@ -1024,7 +1076,12 @@ static lv_design_res_t lv_label_design(lv_obj_t * label, const lv_area_t * clip_
|
||||
|
||||
sel.start = lv_label_get_text_sel_start(label);
|
||||
sel.end = lv_label_get_text_sel_end(label);
|
||||
<<<<<<< HEAD
|
||||
lv_draw_label(&coords, clip_area, style, opa_scale, ext->text, flag, &ext->offset, &sel, hint);
|
||||
=======
|
||||
lv_draw_label(&coords, mask, style, opa_scale, ext->text, flag, &ext->offset, &sel, hint, lv_obj_get_base_dir(label));
|
||||
|
||||
>>>>>>> dev-6.1
|
||||
|
||||
if(ext->long_mode == LV_LABEL_LONG_SROLL_CIRC) {
|
||||
lv_point_t size;
|
||||
@@ -1039,15 +1096,23 @@ static lv_design_res_t lv_label_design(lv_obj_t * label, const lv_area_t * clip_
|
||||
lv_font_get_glyph_width(style->text.font, ' ', ' ') * LV_LABEL_WAIT_CHAR_COUNT;
|
||||
ofs.y = ext->offset.y;
|
||||
|
||||
<<<<<<< HEAD
|
||||
lv_draw_label(&coords, clip_area, style, opa_scale, ext->text, flag, &ofs, &sel, NULL);
|
||||
lv_draw_label(&coords, clip_area, style, opa_scale, ext->text, flag, &ofs, &sel, NULL);
|
||||
=======
|
||||
lv_draw_label(&coords, mask, style, opa_scale, ext->text, flag, &ofs, &sel, NULL, lv_obj_get_base_dir(label));
|
||||
>>>>>>> dev-6.1
|
||||
}
|
||||
|
||||
/*Draw the text again below the original to make an circular effect */
|
||||
if(size.y > lv_obj_get_height(label)) {
|
||||
ofs.x = ext->offset.x;
|
||||
ofs.y = ext->offset.y + size.y + lv_font_get_line_height(style->text.font);
|
||||
<<<<<<< HEAD
|
||||
lv_draw_label(&coords, clip_area, style, opa_scale, ext->text, flag, &ofs, &sel, NULL);
|
||||
=======
|
||||
lv_draw_label(&coords, mask, style, opa_scale, ext->text, flag, &ofs, &sel, NULL, lv_obj_get_base_dir(label));
|
||||
>>>>>>> dev-6.1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -177,6 +177,21 @@ void lv_lmeter_set_scale(lv_obj_t * lmeter, uint16_t angle, uint8_t line_cnt)
|
||||
lv_obj_invalidate(lmeter);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the angle settings of a line meter
|
||||
* @param lmeter pointer to a line meter object
|
||||
* @param angle angle where the meter will be facing (with its center)
|
||||
*/
|
||||
void lv_lmeter_set_angle(lv_obj_t * lmeter, uint16_t angle)
|
||||
{
|
||||
lv_lmeter_ext_t * ext = lv_obj_get_ext_attr(lmeter);
|
||||
if(ext->angle == angle) return;
|
||||
|
||||
ext->angle = angle;
|
||||
|
||||
lv_obj_invalidate(lmeter);
|
||||
}
|
||||
|
||||
/*=====================
|
||||
* Getter functions
|
||||
*====================*/
|
||||
@@ -287,7 +302,7 @@ static lv_design_res_t lv_lmeter_design(lv_obj_t * lmeter, const lv_area_t * cli
|
||||
|
||||
lv_coord_t x_ofs = lv_obj_get_width(lmeter) / 2 + lmeter->coords.x1;
|
||||
lv_coord_t y_ofs = lv_obj_get_height(lmeter) / 2 + lmeter->coords.y1;
|
||||
int16_t angle_ofs = 90 + (360 - ext->scale_angle) / 2;
|
||||
int16_t angle_ofs = ext->angle + 90 + (360 - ext->scale_angle) / 2;
|
||||
int16_t level =
|
||||
(int32_t)((int32_t)(ext->cur_value - ext->min_value) * ext->line_cnt) / (ext->max_value - ext->min_value);
|
||||
uint8_t i;
|
||||
|
||||
@@ -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 angle;
|
||||
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_angle(lv_obj_t * lmeter, uint16_t angle);
|
||||
|
||||
/**
|
||||
* Set the styles of a line meter
|
||||
* @param lmeter pointer to a line meter object
|
||||
|
||||
@@ -397,7 +397,7 @@ static lv_design_res_t lv_roller_design(lv_obj_t * roller, const lv_area_t * cli
|
||||
new_style.text.color = sel_style->text.color;
|
||||
new_style.text.opa = sel_style->text.opa;
|
||||
lv_draw_label(&ext->ddlist.label->coords, &mask_sel, &new_style, opa_scale,
|
||||
lv_label_get_text(ext->ddlist.label), txt_align, NULL, NULL, NULL);
|
||||
lv_label_get_text(ext->ddlist.label), txt_align, NULL, NULL, NULL, lv_obj_get_base_dir(ext->ddlist.label));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
#include "../lv_core/lv_debug.h"
|
||||
#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"
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "../lv_core/lv_debug.h"
|
||||
#include "../lv_themes/lv_theme.h"
|
||||
#include "../lv_misc/lv_math.h"
|
||||
#include "../lv_core/lv_indev.h"
|
||||
|
||||
/*********************
|
||||
* DEFINES
|
||||
|
||||
@@ -1391,7 +1391,7 @@ static lv_design_res_t lv_ta_scrollable_design(lv_obj_t * scrl, const lv_area_t
|
||||
|
||||
cur_area.x1 += cur_style.body.padding.left;
|
||||
cur_area.y1 += cur_style.body.padding.top;
|
||||
lv_draw_label(&cur_area, clip_area, &cur_style, opa_scale, letter_buf, LV_TXT_FLAG_NONE, NULL, NULL, NULL);
|
||||
lv_draw_label(&cur_area, clip_area, &cur_style, opa_scale, letter_buf, LV_TXT_FLAG_NONE, NULL, NULL, NULL, lv_obj_get_base_dir(ta));
|
||||
|
||||
} else if(ext->cursor.type == LV_CURSOR_OUTLINE) {
|
||||
cur_style.body.opa = LV_OPA_TRANSP;
|
||||
@@ -1889,7 +1889,7 @@ static void update_cursor_position_on_click(lv_obj_t * ta, lv_signal_t sign, lv_
|
||||
if(!ext->text_sel_in_prog && !click_outside_label && sign == LV_SIGNAL_PRESSED) {
|
||||
/*Input device just went down. Store the selection start position*/
|
||||
ext->sel.start = char_id_at_click;
|
||||
ext->sel.end = LV_DRAW_LABEL_NO_TXT_SEL;
|
||||
ext->sel.end = LV_LABEL_TEXT_SEL_OFF;
|
||||
ext->text_sel_in_prog = 1;
|
||||
lv_obj_set_drag(lv_page_get_scrl(ta), false);
|
||||
} else if(ext->text_sel_in_prog && sign == LV_SIGNAL_PRESSING) {
|
||||
|
||||
@@ -145,14 +145,14 @@ void lv_table_set_cell_value(lv_obj_t * table, uint16_t row, uint16_t col, const
|
||||
uint32_t cell = row * ext->col_cnt + col;
|
||||
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)
|
||||
@@ -167,12 +167,7 @@ void lv_table_set_cell_value(lv_obj_t * table, uint16_t row, uint16_t col, const
|
||||
}
|
||||
|
||||
ext->cell_data[cell] = lv_mem_realloc(ext->cell_data[cell], strlen(txt) + 2); /*+1: trailing '\0; +1: format byte*/
|
||||
|
||||
#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);
|
||||
@@ -744,7 +739,7 @@ static lv_design_res_t lv_table_design(lv_obj_t * table, const lv_area_t * clip_
|
||||
label_mask_ok = lv_area_intersect(&label_mask, clip_area, &cell_area);
|
||||
if(label_mask_ok) {
|
||||
lv_draw_label(&txt_area, &label_mask, cell_style, opa_scale, ext->cell_data[cell] + 1,
|
||||
txt_flags, NULL, NULL, NULL);
|
||||
txt_flags, NULL, NULL, NULL, lv_obj_get_base_dir(table));
|
||||
}
|
||||
/*Draw lines after '\n's*/
|
||||
lv_point_t p1;
|
||||
|
||||
Reference in New Issue
Block a user