1
0
mirror of https://github.com/lvgl/lvgl.git synced 2025-01-28 07:03:00 +08:00

Merge pull request #1253 from amirgon/feat-bidi-pos_conv

Feat bidi pos conv
This commit is contained in:
Gabor Kiss-Vamosi 2019-11-12 06:49:05 +01:00 committed by GitHub
commit afb47ebf56
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
42 changed files with 1914 additions and 204 deletions

View File

@ -188,8 +188,8 @@ Styles can be assigned to the objects to changed their appearance. A style descr
You can create a new style like this:
```c
static lv_style_t style1; /*Declare a new style. Should be `static`*/
lv_style_copy(&style1, &lv_style_plain); /*Copy a buil-in style*/
static lv_style_t style1; /*Declare a new style. Should be `static`*/
lv_style_copy(&style1, &lv_style_plain); /*Copy a built-in style*/
style1.body.main_color = LV_COLOR_RED; /*Main color*/
style1.body.grad_color = lv_color_hex(0xffd83c) /*Gradient color (orange)*/
style1.body.radius = 3;

View File

@ -438,6 +438,9 @@ typedef void * lv_obj_user_data_t;
/*Container (dependencies: -*/
#define LV_USE_CONT 1
/*Color picker (dependencies: -*/
#define LV_USE_CPICKER 1
/*Drop down list (dependencies: lv_page, lv_label, lv_symbol_def.h)*/
#define LV_USE_DDLIST 1
#if LV_USE_DDLIST != 0

1
lvgl.h
View File

@ -47,6 +47,7 @@ extern "C" {
#include "src/lv_objx/lv_chart.h"
#include "src/lv_objx/lv_table.h"
#include "src/lv_objx/lv_cb.h"
#include "src/lv_objx/lv_cpicker.h"
#include "src/lv_objx/lv_bar.h"
#include "src/lv_objx/lv_slider.h"
#include "src/lv_objx/lv_led.h"

View File

@ -612,6 +612,11 @@
#define LV_USE_CONT 1
#endif
/*Color picker (dependencies: -*/
#ifndef LV_USE_CPICKER
#define LV_USE_CPICKER 1
#endif
/*Drop down list (dependencies: lv_page, lv_label, lv_symbol_def.h)*/
#ifndef LV_USE_DDLIST
#define LV_USE_DDLIST 1

View File

@ -7,6 +7,7 @@
* INCLUDES
*********************/
#include "lv_obj.h"
#include "lv_debug.h"
#if LV_USE_DEBUG
@ -126,7 +127,7 @@ bool lv_debug_check_str(const void * str)
return false;
}
void lv_debug_log_error(const char * msg, unsigned long int value)
void lv_debug_log_error(const char * msg, uint64_t value)
{
static const char hex[] = "0123456789ABCDEF";

View File

@ -34,7 +34,7 @@ bool lv_debug_check_obj_type(const lv_obj_t * obj, const char * obj_type);
bool lv_debug_check_obj_valid(const lv_obj_t * obj);
bool lv_debug_check_style(const void * str);
bool lv_debug_check_style(const lv_style_t * style);
bool lv_debug_check_str(const void * str);
@ -136,6 +136,8 @@ void lv_debug_log_error(const char * msg, uint64_t value);
#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

View File

@ -20,7 +20,6 @@
/**********************
* STATIC PROTOTYPES
**********************/
static uint16_t fast_atan2(int x, int y);
static void ver_line(lv_coord_t x, lv_coord_t y, const lv_area_t * mask, lv_coord_t len, lv_color_t color,
lv_opa_t opa);
static void hor_line(lv_coord_t x, lv_coord_t y, const lv_area_t * mask, lv_coord_t len, lv_color_t color,
@ -121,7 +120,7 @@ void lv_draw_arc(lv_coord_t center_x, lv_coord_t center_y, uint16_t radius, cons
if(r_act_sqr > r_out_sqr) continue;
#endif
deg_base = fast_atan2(xi, yi) - 180;
deg_base = lv_atan2(xi, yi) - 180;
#if LV_ANTIALIAS
int opa = -1;

View File

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

View File

@ -52,21 +52,17 @@ static uint8_t hex_char_to_num(char hex);
* @param txt 0 terminated text to write
* @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 sel_end end index of selected area (`LV_LABEL_TXT_SEL_OFF` if none)
* @param sel make the text selected in the range by drawing a background there
*/
void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_style_t * style, lv_opa_t opa_scale,
const char * txt, lv_txt_flag_t flag, lv_point_t * offset, uint16_t sel_start, uint16_t sel_end,
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_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*/
@ -75,7 +71,7 @@ void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_st
/*If EXAPND is enabled then not limit the text's width to the object's width*/
lv_point_t p;
lv_txt_get_size(&p, txt, style->text.font, style->text.letter_space, style->text.line_space, LV_COORD_MAX,
flag);
flag);
w = p.x;
}
@ -113,6 +109,7 @@ void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_st
pos.y += hint->y;
}
uint32_t line_end = line_start + lv_txt_get_next_line(&txt[line_start], font, style->text.letter_space, w, flag);
/*Go the first visible line*/
@ -147,6 +144,18 @@ void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_st
lv_opa_t opa = opa_scale == LV_OPA_COVER ? style->text.opa : (uint16_t)((uint16_t)style->text.opa * opa_scale) >> 8;
uint16_t sel_start = 0xFFFF;
uint16_t sel_end = 0xFFFF;
if(sel) {
sel_start = sel->start;
sel_end = sel->end;
if(sel_start > sel_end) {
uint16_t tmp = sel_start;
sel_start = sel_end;
sel_end = tmp;
}
}
cmd_state_t cmd_state = CMD_STATE_WAIT;
uint32_t i;
uint16_t par_start = 0;
@ -166,16 +175,29 @@ void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_st
i = 0;
uint32_t letter;
uint32_t letter_next;
while(i < line_end - line_start) {
#if LV_USE_BIDI
char *bidi_txt = lv_draw_get_buf(line_end - line_start + 1);
lv_bidi_process_paragraph(txt + line_start, bidi_txt, line_end - line_start, bidi_dir);
char *bidi_txt = lv_draw_get_buf(line_end - line_start + 1);
lv_bidi_process_paragraph(txt + line_start, bidi_txt, line_end - line_start, bidi_dir, NULL, 0);
#else
const char *bidi_txt = txt + line_start;
const char *bidi_txt = txt + line_start;
#endif
while(i < line_end - line_start) {
uint16_t logical_char_pos = 0;
if(sel_start != 0xFFFF && sel_end != 0xFFFF) {
#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) {
if(letter == (uint32_t)LV_TXT_COLOR_CMD[0]) {
@ -220,9 +242,7 @@ void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_st
letter_w = lv_font_get_glyph_width(font, letter, letter_next);
if(sel_start != 0xFFFF && sel_end != 0xFFFF) {
int char_ind = lv_encoded_get_char_id(bidi_txt, i);
/*Do not draw the rectangle on the character at `sel_start`.*/
if(char_ind > sel_start && char_ind <= sel_end) {
if(logical_char_pos >= sel_start && logical_char_pos < sel_end) {
lv_area_t sel_coords;
sel_coords.x1 = pos.x;
sel_coords.y1 = pos.y;
@ -231,6 +251,7 @@ void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_st
lv_draw_rect(&sel_coords, mask, &sel_style, opa);
}
}
lv_draw_letter(&pos, mask, font, letter, color, opa);
if(letter_w > 0) {
@ -245,7 +266,7 @@ void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_st
/*Align to middle*/
if(flag & LV_TXT_FLAG_CENTER) {
line_width =
lv_txt_get_width(&txt[line_start], line_end - line_start, font, style->text.letter_space, flag);
lv_txt_get_width(&txt[line_start], line_end - line_start, font, style->text.letter_space, flag);
pos.x += (lv_area_get_width(coords) - line_width) / 2;
@ -253,7 +274,7 @@ void lv_draw_label(const lv_area_t * coords, const lv_area_t * mask, const lv_st
/*Align to the right*/
else if(flag & LV_TXT_FLAG_RIGHT) {
line_width =
lv_txt_get_width(&txt[line_start], line_end - line_start, font, style->text.letter_space, flag);
lv_txt_get_width(&txt[line_start], line_end - line_start, font, style->text.letter_space, flag);
pos.x += lv_area_get_width(coords) - line_width;
}
@ -283,13 +304,13 @@ static uint8_t hex_char_to_num(char hex)
if(hex >= 'a') hex -= 'a' - 'A'; /*Convert to upper case*/
switch(hex) {
case 'A': result = 10; break;
case 'B': result = 11; break;
case 'C': result = 12; break;
case 'D': result = 13; break;
case 'E': result = 14; break;
case 'F': result = 15; break;
default: result = 0; break;
case 'A': result = 10; break;
case 'B': result = 11; break;
case 'C': result = 12; break;
case 'D': result = 13; break;
case 'E': result = 14; break;
case 'F': result = 15; break;
default: result = 0; break;
}
}

View File

@ -19,11 +19,19 @@ extern "C" {
/*********************
* DEFINES
*********************/
#define LV_DRAW_LABEL_NO_TXT_SEL (0xFFFF)
/**********************
* TYPEDEFS
**********************/
typedef struct
{
uint16_t start;
uint16_t end;
}lv_draw_label_txt_sel_t;
/** Store some info to speed up drawing of very large texts
* It takes a lot of time to get the first visible character because
* all the previous characters needs to be checked to calculate the positions.
@ -55,10 +63,10 @@ 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 sel_end end 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, uint16_t sel_start, uint16_t sel_end,
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_bidi_dir_t bidi_dir);
/**********************

View File

@ -45,8 +45,7 @@ static void point_swap(lv_point_t * p1, lv_point_t * p2);
*/
void lv_draw_triangle(const lv_point_t * points, const lv_area_t * mask, const lv_style_t * style, lv_opa_t opa_scale)
{
/*Return is the triangle is degenerated*/
/*Return if the triangle is degenerated*/
if(points[0].x == points[1].x && points[0].y == points[1].y) return;
if(points[1].x == points[2].x && points[1].y == points[2].y) return;
if(points[0].x == points[2].x && points[0].y == points[2].y) return;

View File

@ -192,6 +192,19 @@ bool lv_area_is_in(const lv_area_t * ain_p, const lv_area_t * aholder_p)
return is_in;
}
/**
* 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
**********************/

View File

@ -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
**********************/

View File

@ -6,9 +6,10 @@
/*********************
* 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
@ -17,6 +18,11 @@
*********************/
#define LV_BIDI_BRACKLET_DEPTH 4
// Highest bit of the 16-bit pos_conv value specifies whether this pos is RTL or not
#define GET_POS(x) ((x) & 0x7FFF)
#define IS_RTL_POS(x) (((x) & 0x8000) != 0)
#define SET_RTL_POS(x, is_rtl) (GET_POS(x) | ((is_rtl)? 0x8000: 0))
/**********************
* TYPEDEFS
**********************/
@ -29,10 +35,12 @@ typedef struct
/**********************
* STATIC PROTOTYPES
**********************/
static lv_bidi_dir_t get_next_run(const char * txt, lv_bidi_dir_t base_dir, uint32_t max_len, uint32_t * len);
static void rtl_reverse(char * dest, const char * src, uint32_t len);
static lv_bidi_dir_t get_next_run(const char * txt, lv_bidi_dir_t base_dir, uint32_t max_len, uint32_t * len, uint16_t * pos_conv_len);
static void rtl_reverse(char * dest, const char * src, uint32_t len, uint16_t *pos_conv_out, uint16_t pos_conv_rd_base, uint16_t pos_conv_len);
static uint32_t char_change_to_pair(uint32_t letter);
static lv_bidi_dir_t bracket_process(const char * txt, uint32_t next_pos, uint32_t len, uint32_t letter, lv_bidi_dir_t base_dir);
static void fill_pos_conv(uint16_t * out, uint16_t len, uint16_t index);
static uint32_t get_txt_len(const char * txt, uint32_t max_len);
/**********************
* STATIC VARIABLES
@ -64,7 +72,7 @@ void lv_bidi_process(const char * str_in, char * str_out, lv_bidi_dir_t base_dir
while(str_in[par_start] != '\0') {
par_len = lv_bidi_get_next_paragraph(&str_in[par_start]);
lv_bidi_process_paragraph(&str_in[par_start], &str_out[par_start], par_len, base_dir);
lv_bidi_process_paragraph(&str_in[par_start], &str_out[par_start], par_len, base_dir, NULL, 0);
par_start += par_len;
while(str_in[par_start] == '\n' || str_in[par_start] == '\r') {
@ -137,23 +145,54 @@ 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;
}
void lv_bidi_process_paragraph(const char * str_in, char * str_out, uint32_t len, lv_bidi_dir_t base_dir)
void lv_bidi_process_paragraph(const char * str_in, char * str_out, uint32_t len, lv_bidi_dir_t base_dir, uint16_t *pos_conv_out, uint16_t pos_conv_len)
{
uint32_t run_len = 0;
lv_bidi_dir_t run_dir;
uint32_t rd = 0;
uint32_t wr;
uint16_t pos_conv_run_len = 0;
uint16_t pos_conv_rd = 0;
uint16_t pos_conv_wr;
if(base_dir == LV_BIDI_DIR_AUTO) base_dir = lv_bidi_detect_base_dir(str_in);
if(base_dir == LV_BIDI_DIR_RTL) wr = len;
else wr = 0;
if(base_dir == LV_BIDI_DIR_RTL) {
wr = len;
pos_conv_wr = pos_conv_len;
}
else {
wr = 0;
pos_conv_wr = 0;
}
str_out[len] = '\0';
if (str_out) str_out[len] = '\0';
lv_bidi_dir_t dir = base_dir;
@ -163,39 +202,59 @@ void lv_bidi_process_paragraph(const char * str_in, char * str_out, uint32_t len
/*Process neutral chars in the beginning*/
while(rd < len) {
uint32_t letter = lv_txt_encoded_next(str_in, &rd);
pos_conv_rd++;
dir = lv_bidi_get_letter_dir(letter);
if(dir == LV_BIDI_DIR_NEUTRAL) dir = bracket_process(str_in, rd, len, letter, base_dir);
if(dir != LV_BIDI_DIR_NEUTRAL && dir != LV_BIDI_DIR_WEAK) break;
}
if(rd && str_in[rd] != '\0') lv_txt_encoded_prev(str_in, &rd);
if(rd && str_in[rd] != '\0') {
lv_txt_encoded_prev(str_in, &rd);
pos_conv_rd--;
}
if(rd) {
if(base_dir == LV_BIDI_DIR_LTR) {
memcpy(&str_out[wr], str_in, rd);
wr += rd;
if (str_out) {
memcpy(&str_out[wr], str_in, rd);
wr += rd;
}
if (pos_conv_out) {
fill_pos_conv(&pos_conv_out[pos_conv_wr], pos_conv_rd, 0);
pos_conv_wr += pos_conv_rd;
}
} else {
wr -= rd;
rtl_reverse(&str_out[wr], str_in, rd);
pos_conv_wr -= pos_conv_rd;
rtl_reverse(str_out? &str_out[wr]: NULL, str_in, rd, pos_conv_out? &pos_conv_out[pos_conv_wr]: NULL, 0, pos_conv_rd);
}
}
/*Get and process the runs*/
while(rd < len) {
run_dir = get_next_run(&str_in[rd], base_dir, len - rd, &run_len);
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;
}
}
@ -212,24 +271,53 @@ uint32_t lv_bidi_get_next_paragraph(const char * txt)
return i;
}
static lv_bidi_dir_t get_next_run(const char * txt, lv_bidi_dir_t base_dir, uint32_t max_len, uint32_t * len)
/**********************
* STATIC FUNCTIONS
**********************/
static uint32_t get_txt_len(const char * txt, uint32_t max_len)
{
uint32_t len = 0;
uint32_t i = 0;
while(i < max_len && txt[i] != '\0') {
lv_txt_encoded_next(txt, &i);
len++;
}
return len;
}
static void fill_pos_conv(uint16_t * out, uint16_t len, uint16_t index)
{
for (uint16_t i = 0; i < len; i++)
{
out[i] = SET_RTL_POS(index, false);
index++;
}
}
static lv_bidi_dir_t get_next_run(const char * txt, lv_bidi_dir_t base_dir, uint32_t max_len, uint32_t * len, uint16_t * pos_conv_len)
{
uint32_t i = 0;
uint32_t letter;
uint16_t pos_conv_i = 0;
letter = lv_txt_encoded_next(txt, NULL);
lv_bidi_dir_t dir = lv_bidi_get_letter_dir(letter);
if(dir == LV_BIDI_DIR_NEUTRAL) dir = bracket_process(txt, 0, max_len, letter, base_dir);
/*Find the first strong char. Skip the neutrals*/
while(dir == LV_BIDI_DIR_NEUTRAL || dir == LV_BIDI_DIR_WEAK) {
letter = lv_txt_encoded_next(txt, &i);
pos_conv_i++;
dir = lv_bidi_get_letter_dir(letter);
if(dir == LV_BIDI_DIR_NEUTRAL) dir = bracket_process(txt, i, max_len, letter, base_dir);
if(i >= max_len || txt[i] == '\0' || txt[i] == '\n' || txt[i] == '\r') {
*len = i;
*pos_conv_len = pos_conv_i;
return base_dir;
}
}
@ -238,84 +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(i_prev < max_len && txt[i] != '\0' && txt[i] != '\n' && txt[i] != '\r') {
letter = lv_txt_encoded_next(txt, &i);
pos_conv_i++;
next_dir = lv_bidi_get_letter_dir(letter);
if(next_dir == LV_BIDI_DIR_NEUTRAL) next_dir = bracket_process(txt, i, max_len, letter, base_dir);
/*New dir found?*/
if((next_dir == LV_BIDI_DIR_RTL || next_dir == LV_BIDI_DIR_LTR) && next_dir != run_dir) {
/*Include neutrals if `run_dir == base_dir` */
if(run_dir == base_dir) *len = i_prev;
if(run_dir == base_dir) {
*len = i_prev;
*pos_conv_len = pos_conv_i_prev;
}
/*Exclude neutrals if `run_dir != base_dir` */
else *len = i_last_strong;
else {
*len = i_last_strong;
*pos_conv_len = pos_conv_i_last_strong;
}
return run_dir;
}
if(next_dir != LV_BIDI_DIR_NEUTRAL) i_last_strong = i;
if(next_dir != LV_BIDI_DIR_NEUTRAL) {
i_last_strong = i;
pos_conv_i_last_strong = pos_conv_i;
}
i_prev = i;
pos_conv_i_prev = pos_conv_i;
}
/*Handle end of of string. Apply `base_dir` on trailing neutrals*/
/*Include neutrals if `run_dir == base_dir` */
if(run_dir == base_dir) *len = i_prev;
if(run_dir == base_dir) {
*len = i_prev;
*pos_conv_len = pos_conv_i_prev;
}
/*Exclude neutrals if `run_dir != base_dir` */
else *len = i_last_strong;
else {
*len = i_last_strong;
*pos_conv_len = pos_conv_i_last_strong;
}
return run_dir;
}
static void rtl_reverse(char * dest, const char * src, uint32_t len)
static void rtl_reverse(char * dest, const char * src, uint32_t len, uint16_t *pos_conv_out, uint16_t pos_conv_rd_base, uint16_t pos_conv_len)
{
uint32_t i = len;
uint32_t wr = 0;
uint16_t pos_conv_i = pos_conv_len;
uint16_t pos_conv_wr = 0;
while(i) {
uint32_t letter = lv_txt_encoded_prev(src, &i);
uint16_t pos_conv_letter = --pos_conv_i;
/*Keep weak letters (numbers) as LTR*/
if(lv_bidi_letter_is_weak(letter)) {
uint32_t last_weak = i;
uint32_t first_weak = i;
uint16_t pos_conv_last_weak = pos_conv_i;
uint16_t pos_conv_first_weak = pos_conv_i;
while(i) {
letter = lv_txt_encoded_prev(src, &i);
pos_conv_letter = --pos_conv_i;
/*No need to call `char_change_to_pair` because there not such chars here*/
/*Finish on non-weak char */
/*but treat number and currency related chars as weak*/
if(lv_bidi_letter_is_weak(letter) == false && letter != '.' && letter != ',' && letter != '$' && letter != '%') {
if (lv_bidi_letter_is_weak(letter) == false && letter != '.' && letter != ',' && letter != '$' && letter != '%') {
lv_txt_encoded_next(src, &i); /*Rewind one letter*/
pos_conv_i++;
first_weak = i;
pos_conv_first_weak = pos_conv_i;
break;
}
}
if(i == 0) first_weak = 0;
if(i == 0) {
first_weak = 0;
pos_conv_first_weak = 0;
}
memcpy(&dest[wr], &src[first_weak], last_weak - first_weak + 1);
if (dest) memcpy(&dest[wr], &src[first_weak], last_weak - first_weak + 1);
if (pos_conv_out) fill_pos_conv(&pos_conv_out[pos_conv_wr], pos_conv_last_weak - pos_conv_first_weak + 1, pos_conv_rd_base + pos_conv_first_weak);
wr += last_weak - first_weak + 1;
pos_conv_wr += pos_conv_last_weak - pos_conv_first_weak + 1;
}
/*Simply store in reversed order*/
else {
uint32_t letter_size = lv_txt_encoded_size((const char *)&src[i]);
/*Swap arithmetical symbols*/
if(letter_size == 1) {
uint32_t new_letter = letter = char_change_to_pair(letter);
dest[wr] = (uint8_t)new_letter;
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++;
}
}
}

View File

@ -53,13 +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);
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

View File

@ -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);
}

View File

@ -96,10 +96,13 @@ enum {
typedef union
{
uint8_t blue : 1;
uint8_t green : 1;
uint8_t red : 1;
uint8_t full : 1;
struct
{
uint8_t blue : 1;
uint8_t green : 1;
uint8_t red : 1;
} ch;
uint8_t full;
} lv_color1_t;
typedef union
@ -389,10 +392,10 @@ static inline uint8_t lv_color_brightness(lv_color_t color)
/* 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;
}
@ -463,13 +466,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

View File

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

View File

@ -94,6 +94,87 @@ int32_t lv_bezier3(uint32_t t, int32_t u0, int32_t u1, int32_t u2, int32_t u3)
return v1 + v2 + v3 + v4;
}
/**
* Calculate the atan2 of a vector.
* @param x
* @param y
* @return the angle in degree calculated from the given parameters in range of [0..360]
*/
uint16_t lv_atan2(int x, int y)
{
// Fast XY vector to integer degree algorithm - Jan 2011 www.RomanBlack.com
// Converts any XY values including 0 to a degree value that should be
// within +/- 1 degree of the accurate value without needing
// large slow trig functions like ArcTan() or ArcCos().
// NOTE! at least one of the X or Y values must be non-zero!
// This is the full version, for all 4 quadrants and will generate
// the angle in integer degrees from 0-360.
// Any values of X and Y are usable including negative values provided
// they are between -1456 and 1456 so the 16bit multiply does not overflow.
unsigned char negflag;
unsigned char tempdegree;
unsigned char comp;
unsigned int degree; // this will hold the result
//signed int x; // these hold the XY vector at the start
//signed int y; // (and they will be destroyed)
unsigned int ux;
unsigned int uy;
// Save the sign flags then remove signs and get XY as unsigned ints
negflag = 0;
if(x < 0) {
negflag += 0x01; // x flag bit
x = (0 - x); // is now +
}
ux = x; // copy to unsigned var before multiply
if(y < 0) {
negflag += 0x02; // y flag bit
y = (0 - y); // is now +
}
uy = y; // copy to unsigned var before multiply
// 1. Calc the scaled "degrees"
if(ux > uy) {
degree = (uy * 45) / ux; // degree result will be 0-45 range
negflag += 0x10; // octant flag bit
} else {
degree = (ux * 45) / uy; // degree result will be 0-45 range
}
// 2. Compensate for the 4 degree error curve
comp = 0;
tempdegree = degree; // use an unsigned char for speed!
if(tempdegree > 22) { // if top half of range
if(tempdegree <= 44) comp++;
if(tempdegree <= 41) comp++;
if(tempdegree <= 37) comp++;
if(tempdegree <= 32) comp++; // max is 4 degrees compensated
} else { // else is lower half of range
if(tempdegree >= 2) comp++;
if(tempdegree >= 6) comp++;
if(tempdegree >= 10) comp++;
if(tempdegree >= 15) comp++; // max is 4 degrees compensated
}
degree += comp; // degree is now accurate to +/- 1 degree!
// Invert degree if it was X>Y octant, makes 0-45 into 90-45
if(negflag & 0x10) degree = (90 - degree);
// 3. Degree is now 0-90 range for this quadrant,
// need to invert it for whichever quadrant it was in
if(negflag & 0x02) { // if -Y
if(negflag & 0x01) // if -Y -X
degree = (180 + degree);
else // else is -Y +X
degree = (180 - degree);
} else { // else is +Y
if(negflag & 0x01) // if +Y -X
degree = (360 - degree);
}
return degree;
}
/**
* Calculate the integer square root of a number.
* @param num

View File

@ -54,6 +54,14 @@ int16_t lv_trigo_sin(int16_t angle);
*/
int32_t lv_bezier3(uint32_t t, int32_t u0, int32_t u1, int32_t u2, int32_t u3);
/**
* Calculate the atan2 of a vector.
* @param x
* @param y
* @return the angle in degree calculated from the given parameters in range of [0..360]
*/
uint16_t lv_atan2(int x, int y);
/**
* Calculate the integer square root of a number.
* @param num

View File

@ -68,16 +68,16 @@ LV_ATTRIBUTE_TASK_HANDLER void lv_task_handler(void)
LV_LOG_TRACE("lv_task_handler started");
/*Avoid concurrent running of the task handler*/
static bool task_handler_mutex = false;
if(task_handler_mutex) return;
task_handler_mutex = true;
static bool already_running = false;
if(already_running) return;
already_running = true;
static uint32_t idle_period_start = 0;
static uint32_t handler_start = 0;
static uint32_t busy_time = 0;
if(lv_task_run == false) {
task_handler_mutex = false; /*Release mutex*/
already_running = false; /*Release mutex*/
return;
}
@ -154,7 +154,7 @@ LV_ATTRIBUTE_TASK_HANDLER void lv_task_handler(void)
idle_period_start = lv_tick_get();
}
task_handler_mutex = false; /*Release the mutex*/
already_running = false; /*Release the mutex*/
LV_LOG_TRACE("lv_task_handler ready");
}

View File

@ -56,7 +56,7 @@ uint32_t (*lv_txt_encoded_conv_wc)(uint32_t) = lv_txt_utf8_con
uint32_t (*lv_txt_encoded_next)(const char *, uint32_t *) = lv_txt_utf8_next;
uint32_t (*lv_txt_encoded_prev)(const char *, uint32_t *) = lv_txt_utf8_prev;
uint32_t (*lv_txt_encoded_get_byte_id)(const char *, uint32_t) = lv_txt_utf8_get_byte_id;
uint32_t (*lv_encoded_get_char_id)(const char *, uint32_t) = lv_txt_utf8_get_char_id;
uint32_t (*lv_txt_encoded_get_char_id)(const char *, uint32_t) = lv_txt_utf8_get_char_id;
uint32_t (*lv_txt_get_encoded_length)(const char *) = lv_txt_utf8_get_length;
#elif LV_TXT_ENC == LV_TXT_ENC_ASCII
uint8_t (*lv_txt_encoded_size)(const char *) = lv_txt_iso8859_1_size;
@ -65,7 +65,7 @@ uint32_t (*lv_txt_encoded_conv_wc)(uint32_t) = lv_txt_iso8859_
uint32_t (*lv_txt_encoded_next)(const char *, uint32_t *) = lv_txt_iso8859_1_next;
uint32_t (*lv_txt_encoded_prev)(const char *, uint32_t *) = lv_txt_iso8859_1_prev;
uint32_t (*lv_txt_encoded_get_byte_id)(const char *, uint32_t) = lv_txt_iso8859_1_get_byte_id;
uint32_t (*lv_encoded_get_char_id)(const char *, uint32_t) = lv_txt_iso8859_1_get_char_id;
uint32_t (*lv_txt_encoded_get_char_id)(const char *, uint32_t) = lv_txt_iso8859_1_get_char_id;
uint32_t (*lv_txt_get_encoded_length)(const char *) = lv_txt_iso8859_1_get_length;
#endif
@ -186,6 +186,9 @@ static uint16_t lv_txt_get_next_word(const char * txt, const lv_font_t * font,
/*Handle the recolor command*/
if((flag & LV_TXT_FLAG_RECOLOR) != 0) {
if(lv_txt_is_cmd(&cmd_state, letter) != false) {
i = i_next;
i_next = i_next_next;
letter = letter_next;
continue; /*Skip the letter is it is part of a command*/
}
}
@ -263,6 +266,9 @@ static uint16_t lv_txt_get_next_word(const char * txt, const lv_font_t * font,
/**
* 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
@ -292,18 +298,13 @@ 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*/

View File

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

View File

@ -739,7 +739,7 @@ static bool lv_btnm_design(lv_obj_t * btnm, const lv_area_t * mask, lv_design_mo
area_tmp.x2 = area_tmp.x1 + txt_size.x;
area_tmp.y2 = area_tmp.y1 + txt_size.y;
lv_draw_label(&area_tmp, mask, btn_style, opa_scale, ext->map_p[txt_i], txt_flag, NULL, -1, -1, NULL, lv_obj_get_base_dir(btnm));
lv_draw_label(&area_tmp, mask, btn_style, opa_scale, ext->map_p[txt_i], txt_flag, NULL, NULL, NULL, lv_obj_get_base_dir(btnm));
}
}

View File

@ -670,6 +670,9 @@ static lv_coord_t get_day_names_height(lv_obj_t * calendar)
static void draw_header(lv_obj_t * calendar, const lv_area_t * mask)
{
lv_calendar_ext_t * ext = lv_obj_get_ext_attr(calendar);
lv_bidi_dir_t bidi_dir = lv_obj_get_base_dir(calendar);
lv_opa_t opa_scale = lv_obj_get_opa_scale(calendar);
lv_area_t header_area;
@ -687,19 +690,19 @@ static void draw_header(lv_obj_t * calendar, const lv_area_t * mask)
txt_buf[5] = '\0';
strcpy(&txt_buf[5], get_month_name(calendar, ext->showed_date.month));
header_area.y1 += ext->style_header->body.padding.top;
lv_draw_label(&header_area, mask, ext->style_header, opa_scale, txt_buf, LV_TXT_FLAG_CENTER, NULL, -1, -1, NULL, lv_obj_get_base_dir(calendar));
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, -1, -1, NULL, lv_obj_get_base_dir(calendar));
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, -1, -1, NULL, lv_obj_get_base_dir(calendar));
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, -1, -1, NULL, lv_obj_get_base_dir(calendar));
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, -1, -1, NULL, lv_obj_get_base_dir(calendar));
lv_draw_label(&label_area, mask, final_style, opa_scale, buf, LV_TXT_FLAG_CENTER, NULL, NULL, NULL, bidi_dir);
/*Go to the next day*/
day_cnt++;

View File

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

View File

@ -149,7 +149,7 @@ static inline bool lv_cb_is_checked(const lv_obj_t * cb)
*/
static inline bool lv_cb_is_inactive(const lv_obj_t * cb)
{
return lv_btn_get_state(cb) == LV_BTN_STATE_INA ? false : true;
return lv_btn_get_state(cb) == LV_BTN_STATE_INA ? true :false;
}
/**

View File

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

1067
src/lv_objx/lv_cpicker.c Normal file

File diff suppressed because it is too large Load Diff

263
src/lv_objx/lv_cpicker.h Normal file
View File

@ -0,0 +1,263 @@
/**
* @file lv_cpicker.h
*
*/
#ifndef LV_CPICKER_H
#define LV_CPICKER_H
#ifdef __cplusplus
extern "C" {
#endif
/*********************
* INCLUDES
*********************/
#ifdef LV_CONF_INCLUDE_SIMPLE
#include "lv_conf.h"
#else
#include "../../../lv_conf.h"
#endif
#if LV_USE_CPICKER != 0
#include "../lv_core/lv_obj.h"
/*********************
* DEFINES
*********************/
/**********************
* TYPEDEFS
**********************/
enum {
LV_CPICKER_TYPE_RECT,
LV_CPICKER_TYPE_DISC,
};
typedef uint8_t lv_cpicker_type_t;
enum {
LV_CPICKER_COLOR_MODE_HUE,
LV_CPICKER_COLOR_MODE_SATURATION,
LV_CPICKER_COLOR_MODE_VALUE
};
typedef uint8_t lv_cpicker_color_mode_t;
/*Data of colorpicker*/
typedef struct {
lv_color_hsv_t hsv;
struct {
lv_style_t * style;
lv_point_t pos;
uint8_t colored :1;
} indic;
uint32_t last_click_time;
uint32_t last_change_time;
lv_point_t last_press_point;
lv_cpicker_color_mode_t color_mode :2;
uint8_t color_mode_fixed :1;
lv_cpicker_type_t type :1;
uint8_t preview :1;
} lv_cpicker_ext_t;
/*Styles*/
enum {
LV_CPICKER_STYLE_MAIN,
LV_CPICKER_STYLE_INDICATOR,
};
typedef uint8_t lv_cpicker_style_t;
/**********************
* GLOBAL PROTOTYPES
**********************/
/**
* Create a colorpicker objects
* @param par pointer to an object, it will be the parent of the new colorpicker
* @param copy pointer to a colorpicker object, if not NULL then the new object will be copied from it
* @return pointer to the created colorpicker
*/
lv_obj_t * lv_cpicker_create(lv_obj_t * par, const lv_obj_t * copy);
/*=====================
* Setter functions
*====================*/
/**
* Set a new type for a colorpicker
* @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 * cpicker, lv_cpicker_type_t type);
/**
* Set a style of a colorpicker.
* @param cpicker pointer to colorpicker object
* @param type which style should be set
* @param style pointer to a style
*/
void lv_cpicker_set_style(lv_obj_t * cpicker, lv_cpicker_style_t type, lv_style_t *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
*/
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 [0..100]
* @return true if changed, otherwise false
*/
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 [0..100]
* @return true if changed, otherwise false
*/
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
*/
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
*/
bool lv_cpicker_set_color(lv_obj_t * cpicker, lv_color_t color);
/**
* Set the current color mode.
* @param cpicker pointer to colorpicker object
* @param mode color mode (hue/sat/val)
*/
void lv_cpicker_set_color_mode(lv_obj_t * cpicker, lv_cpicker_color_mode_t mode);
/**
* Set if the color mode is changed on long press on center
* @param cpicker pointer to colorpicker object
* @param fixed color mode cannot be changed on long press
*/
void lv_cpicker_set_color_mode_fixed(lv_obj_t * cpicker, bool fixed);
/**
* Make the indicator to be colored to the current color
* @param cpicker pointer to colorpicker object
* @param en true: color the indicator; false: not color the indicator
*/
void lv_cpicker_set_indic_colored(lv_obj_t * cpicker, bool en);
/**
* Add a color preview in the middle of the DISC type color picker
* @param cpicker pointer to colorpicker object
* @param en true: enable preview; false: disable preview
*/
void lv_cpicker_set_preview(lv_obj_t * cpicker, bool en);
/*=====================
* Getter functions
*====================*/
/**
* Get the current color mode.
* @param cpicker pointer to colorpicker object
* @return color mode (hue/sat/val)
*/
lv_cpicker_color_mode_t lv_cpicker_get_color_mode(lv_obj_t * cpicker);
/**
* Get if the color mode is changed on long press on center
* @param cpicker pointer to colorpicker object
* @return mode cannot be changed on long press
*/
bool lv_cpicker_get_color_mode_fixed(lv_obj_t * cpicker);
/**
* Get style of a colorpicker.
* @param cpicker pointer to colorpicker object
* @param type which style should be get
* @return pointer to the style
*/
const lv_style_t * lv_cpicker_get_style(const lv_obj_t * cpicker, lv_cpicker_style_t type);
/**
* Get the current hue of a colorpicker.
* @param cpicker pointer to colorpicker object
* @return current selected hue
*/
uint16_t lv_cpicker_get_hue(lv_obj_t * cpicker);
/**
* Get the current saturation of a colorpicker.
* @param cpicker pointer to colorpicker object
* @return current selected saturation
*/
uint8_t lv_cpicker_get_saturation(lv_obj_t * cpicker);
/**
* Get the current hue of a colorpicker.
* @param cpicker pointer to colorpicker object
* @return current selected value
*/
uint8_t lv_cpicker_get_value(lv_obj_t * cpicker);
/**
* Get the current selected hsv of a colorpicker.
* @param cpicker pointer to colorpicker object
* @return current selected hsv
*/
lv_color_hsv_t lv_cpicker_get_hsv(lv_obj_t * cpicker);
/**
* Get the current selected color of a colorpicker.
* @param cpicker pointer to colorpicker object
* @return current selected color
*/
lv_color_t lv_cpicker_get_color(lv_obj_t * cpicker);
/**
* Whether the indicator is colored to the current color or not
* @param cpicker pointer to colorpicker object
* @return true: color the indicator; false: not color the indicator
*/
bool lv_cpicker_get_indic_colored(lv_obj_t * cpicker);
/**
* Whether the preview is enabled or not
* @param cpicker pointer to colorpicker object
* @return en true: preview is enabled; false: preview is disabled
*/
bool lv_cpicker_get_preview(lv_obj_t * cpicker);
/*=====================
* Other functions
*====================*/
/**********************
* MACROS
**********************/
#endif /*LV_USE_CPICKER*/
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /*LV_CPICKER_H*/

View File

@ -609,7 +609,7 @@ static bool lv_ddlist_design(lv_obj_t * ddlist, const lv_area_t * mask, lv_desig
new_style.text.opa = sel_style->text.opa;
lv_txt_flag_t flag = lv_ddlist_get_txt_flag(ddlist);
lv_draw_label(&ext->label->coords, &mask_sel, &new_style, opa_scale, lv_label_get_text(ext->label),
flag, NULL, -1, -1, NULL, lv_obj_get_base_dir(ddlist));
flag, NULL, NULL, NULL, lv_obj_get_base_dir(ddlist));
}
}
@ -642,9 +642,9 @@ static bool lv_ddlist_design(lv_obj_t * ddlist, const lv_area_t * mask, lv_desig
bool area_ok;
area_ok = lv_area_intersect(&mask_arrow, mask, &area_arrow);
if(area_ok) {
/*Use a down arrow in ddlist, you can replace it with yourcustom symbol*/
lv_draw_label(&area_arrow, &mask_arrow, &new_style, opa_scale, LV_SYMBOL_DOWN, LV_TXT_FLAG_NONE,
NULL, -1, -1, NULL, lv_obj_get_base_dir(ddlist)); /*Use a down arrow in ddlist, you can replace it with your
custom symbol*/
NULL, NULL, NULL, lv_obj_get_base_dir(ddlist));
}
}
}

View File

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

View File

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

View File

@ -304,23 +304,23 @@ static bool lv_imgbtn_design(lv_obj_t * imgbtn, const lv_area_t * mask, lv_desig
#if LV_IMGBTN_TILED == 0
const void * src = ext->img_src[state];
if(lv_img_src_get_type(src) == LV_IMG_SRC_SYMBOL) {
lv_draw_label(&imgbtn->coords, mask, style, opa_scale, src, LV_TXT_FLAG_NONE, NULL, LV_LABEL_TEXT_SEL_OFF, LV_LABEL_TEXT_SEL_OFF, NULL, lv_obj_get_base_dir(imgbtn));
lv_draw_label(&imgbtn->coords, mask, style, opa_scale, src, LV_TXT_FLAG_NONE, NULL, NULL, NULL, lv_obj_get_base_dir(imgbtn));
} else {
lv_draw_img(&imgbtn->coords, mask, src, style, opa_scale);
}
#else
const void * src;
src = ext->img_src_left[state];
if(lv_img_src_get_type(src) == LV_IMG_SRC_SYMBOL) {
LV_LOG_WARN("lv_imgbtn_design: SYMBOLS are not supported in tiled mode")
return;
return true;
}
const void * src;
lv_img_header_t header;
lv_area_t coords;
lv_coord_t left_w = 0;
lv_coord_t right_w = 0;
src = ext->img_src_left[state];
if(src) {
lv_img_decoder_get_info(src, &header);
left_w = header.w;

View File

@ -396,7 +396,7 @@ void lv_kb_def_event_cb(lv_obj_t * kb, lv_event_t event)
/*Add the characters to the text area if set*/
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);

View File

@ -109,8 +109,8 @@ lv_obj_t * lv_label_create(lv_obj_t * par, const lv_obj_t * copy)
#endif
#if LV_LABEL_TEXT_SEL
ext->txt_sel_start = LV_LABEL_TEXT_SEL_OFF;
ext->txt_sel_end = LV_LABEL_TEXT_SEL_OFF;
ext->txt_sel_start = LV_DRAW_LABEL_NO_TXT_SEL;
ext->txt_sel_end = LV_DRAW_LABEL_NO_TXT_SEL;
#endif
ext->dot.tmp_ptr = NULL;
ext->dot_tmp_alloc = 0;
@ -578,7 +578,7 @@ uint16_t lv_label_get_anim_speed(const lv_obj_t * label)
* index (different in UTF-8)
* @param pos store the result here (E.g. index = 0 gives 0;0 coordinates)
*/
void lv_label_get_letter_pos(const lv_obj_t * label, uint16_t index, lv_point_t * pos)
void lv_label_get_letter_pos(const lv_obj_t * label, uint16_t char_id, lv_point_t * pos)
{
LV_ASSERT_OBJ(label, LV_OBJX_NAME);
LV_ASSERT_NULL(pos);
@ -606,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;
@ -619,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;
}
@ -668,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;
@ -685,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 = txt + line_start;
#endif
/*Calculate the x coordinate*/
lv_coord_t x = 0;
if(align == LV_LABEL_ALIGN_CENTER) {
lv_coord_t line_w;
line_w = lv_txt_get_width(&txt[line_start], new_line_start - line_start, font, style->text.letter_space, flag);
line_w = lv_txt_get_width(bidi_txt, new_line_start - line_start, font, style->text.letter_space, flag);
x += lv_obj_get_width(label) / 2 - line_w / 2;
}
else if(align == LV_LABEL_ALIGN_RIGHT) {
lv_coord_t line_w;
line_w = lv_txt_get_width(&txt[line_start], new_line_start - line_start, font, style->text.letter_space, flag);
line_w = lv_txt_get_width(bidi_txt, new_line_start - line_start, font, style->text.letter_space, flag);
x += lv_obj_get_width(label) - line_w;
}
lv_txt_cmd_state_t cmd_state = LV_TXT_CMD_STATE_WAIT;
uint32_t i = line_start;
uint32_t i = 0;
uint32_t i_act = i;
uint32_t letter;
uint32_t letter_next;
if(new_line_start > 0) {
while(i < new_line_start) {
while(i + line_start < new_line_start) {
/* Get the current letter.*/
letter = lv_txt_encoded_next(txt, &i);
letter = lv_txt_encoded_next(bidi_txt, &i);
/*Get the next letter too for kerning*/
letter_next = lv_txt_encoded_next(&txt[i], NULL);
letter_next = lv_txt_encoded_next(&bidi_txt[i], NULL);
/*Handle the recolor command*/
if((flag & LV_TXT_FLAG_RECOLOR) != 0) {
if(lv_txt_is_cmd(&cmd_state, txt[i]) != false) {
if(lv_txt_is_cmd(&cmd_state, bidi_txt[i]) != false) {
continue; /*Skip the letter is it is part of a command*/
}
}
@ -729,7 +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;
}
@ -738,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);
}
/**
@ -799,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) {
@ -822,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;
@ -1004,8 +1062,11 @@ static bool lv_label_design(lv_obj_t * label, const lv_area_t * mask, lv_design_
/*Just for compatibility*/
lv_draw_label_hint_t * hint = NULL;
#endif
lv_draw_label(&coords, mask, style, opa_scale, ext->text, flag, &ext->offset,
lv_label_get_text_sel_start(label), lv_label_get_text_sel_end(label), hint, lv_obj_get_base_dir(label));
lv_draw_label_txt_sel_t sel;
sel.start = lv_label_get_text_sel_start(label);
sel.end = lv_label_get_text_sel_end(label);
lv_draw_label(&coords, mask, style, opa_scale, ext->text, flag, &ext->offset, &sel, hint, lv_obj_get_base_dir(label));
if(ext->long_mode == LV_LABEL_LONG_SROLL_CIRC) {
@ -1021,16 +1082,14 @@ static bool lv_label_design(lv_obj_t * label, const lv_area_t * mask, lv_design_
lv_font_get_glyph_width(style->text.font, ' ', ' ') * LV_LABEL_WAIT_CHAR_COUNT;
ofs.y = ext->offset.y;
lv_draw_label(&coords, mask, style, opa_scale, ext->text, flag, &ofs,
lv_label_get_text_sel_start(label), lv_label_get_text_sel_end(label), NULL, lv_obj_get_base_dir(label));
lv_draw_label(&coords, mask, style, opa_scale, ext->text, flag, &ofs, &sel, NULL, lv_obj_get_base_dir(label));
}
/*Draw the text again below the original to make an circular effect */
if(size.y > lv_obj_get_height(label)) {
ofs.x = ext->offset.x;
ofs.y = ext->offset.y + size.y + lv_font_get_line_height(style->text.font);
lv_draw_label(&coords, mask, style, opa_scale, ext->text, flag, &ofs,
lv_label_get_text_sel_start(label), lv_label_get_text_sel_end(label), NULL, lv_obj_get_base_dir(label));
lv_draw_label(&coords, mask, style, opa_scale, ext->text, flag, &ofs, &sel, NULL, lv_obj_get_base_dir(label));
}
}
}

View File

@ -33,7 +33,7 @@ extern "C" {
*********************/
#define LV_LABEL_DOT_NUM 3
#define LV_LABEL_POS_LAST 0xFFFF
#define LV_LABEL_TEXT_SEL_OFF 0xFFFF
#define LV_LABEL_TEXT_SEL_OFF LV_DRAW_LABEL_NO_TXT_SEL
LV_EXPORT_CONST_INT(LV_LABEL_DOT_NUM);
LV_EXPORT_CONST_INT(LV_LABEL_POS_LAST);

View File

@ -1,6 +1,7 @@
CSRCS += lv_arc.c
CSRCS += lv_bar.c
CSRCS += lv_cb.c
CSRCS += lv_cpicker.c
CSRCS += lv_ddlist.c
CSRCS += lv_kb.c
CSRCS += lv_line.c

View File

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

View File

@ -558,6 +558,9 @@ void lv_ta_set_placeholder_text(lv_obj_t * ta, const char * txt)
lv_label_set_text(ext->placeholder, txt);
/*Refresh the placeholder's align*/
lv_ta_set_text_align(ta, lv_label_get_align(ext->label));
placeholder_update(ta);
}
@ -773,12 +776,14 @@ void lv_ta_set_text_align(lv_obj_t * ta, lv_label_align_t align)
lv_obj_t * label = lv_ta_get_label(ta);
if(!ext->one_line) {
lv_label_set_align(label, align);
if(ext->placeholder) lv_label_set_align(ext->placeholder, align);
} else {
/*Normal left align. Just let the text expand*/
if(align == LV_LABEL_ALIGN_LEFT) {
lv_label_set_long_mode(label, LV_LABEL_LONG_EXPAND);
lv_page_set_scrl_fit2(ta, LV_FIT_TIGHT, LV_FIT_FLOOD);
lv_label_set_align(label, align);
if(ext->placeholder) lv_label_set_align(ext->placeholder, align);
}
/*Else use fix label width equal to the Text area width*/
@ -786,6 +791,7 @@ void lv_ta_set_text_align(lv_obj_t * ta, lv_label_align_t align)
lv_label_set_long_mode(label, LV_LABEL_LONG_CROP);
lv_page_set_scrl_fit2(ta, LV_FIT_FLOOD, LV_FIT_FLOOD);
lv_label_set_align(label, align);
if(ext->placeholder) lv_label_set_align(ext->placeholder, align);
lv_obj_set_width(label, lv_page_get_fit_width(ta));
}
@ -1131,8 +1137,8 @@ bool lv_ta_text_is_selected(const lv_obj_t * ta)
#if LV_LABEL_TEXT_SEL
lv_ta_ext_t * ext = lv_obj_get_ext_attr(ta);
if((lv_label_get_text_sel_start(ext->label) == LV_LABEL_TEXT_SEL_OFF ||
lv_label_get_text_sel_end(ext->label) == LV_LABEL_TEXT_SEL_OFF)) {
if((lv_label_get_text_sel_start(ext->label) == LV_DRAW_LABEL_NO_TXT_SEL ||
lv_label_get_text_sel_end(ext->label) == LV_DRAW_LABEL_NO_TXT_SEL)) {
return true;
} else {
return false;
@ -1203,10 +1209,10 @@ void lv_ta_clear_selection(lv_obj_t * ta)
#if LV_LABEL_TEXT_SEL
lv_ta_ext_t * ext = lv_obj_get_ext_attr(ta);
if(lv_label_get_text_sel_start(ext->label) != LV_LABEL_TEXT_SEL_OFF ||
lv_label_get_text_sel_end(ext->label) != LV_LABEL_TEXT_SEL_OFF) {
lv_label_set_text_sel_start(ext->label, LV_LABEL_TEXT_SEL_OFF);
lv_label_set_text_sel_end(ext->label, LV_LABEL_TEXT_SEL_OFF);
if(lv_label_get_text_sel_start(ext->label) != LV_DRAW_LABEL_NO_TXT_SEL ||
lv_label_get_text_sel_end(ext->label) != LV_DRAW_LABEL_NO_TXT_SEL) {
lv_label_set_text_sel_start(ext->label, LV_DRAW_LABEL_NO_TXT_SEL);
lv_label_set_text_sel_end(ext->label, LV_DRAW_LABEL_NO_TXT_SEL);
}
#else
(void)ta; /*Unused*/
@ -1385,8 +1391,7 @@ static bool lv_ta_scrollable_design(lv_obj_t * scrl, const lv_area_t * mask, lv_
cur_area.x1 += cur_style.body.padding.left;
cur_area.y1 += cur_style.body.padding.top;
lv_draw_label(&cur_area, mask, &cur_style, opa_scale, letter_buf, LV_TXT_FLAG_NONE, 0,
LV_LABEL_TEXT_SEL_OFF, LV_LABEL_TEXT_SEL_OFF, NULL, lv_obj_get_base_dir(ta));
lv_draw_label(&cur_area, mask, &cur_style, opa_scale, letter_buf, LV_TXT_FLAG_NONE, NULL, NULL, NULL, lv_obj_get_base_dir(ta));
} else if(ext->cursor.type == LV_CURSOR_OUTLINE) {
cur_style.body.opa = LV_OPA_TRANSP;
@ -1878,13 +1883,13 @@ static void update_cursor_position_on_click(lv_obj_t * ta, lv_signal_t sign, lv_
if(ext->text_sel_en) {
if(!ext->text_sel_in_prog && !click_outside_label && sign == LV_SIGNAL_PRESSED) {
/*Input device just went down. Store the selection start position*/
ext->tmp_sel_start = char_id_at_click;
ext->tmp_sel_end = LV_LABEL_TEXT_SEL_OFF;
ext->sel.start = char_id_at_click;
ext->sel.end = LV_LABEL_TEXT_SEL_OFF;
ext->text_sel_in_prog = 1;
lv_obj_set_drag(lv_page_get_scrl(ta), false);
} else if(ext->text_sel_in_prog && sign == LV_SIGNAL_PRESSING) {
/*Input device may be moving. Store the end position */
ext->tmp_sel_end = char_id_at_click;
ext->sel.end = char_id_at_click;
} else if(ext->text_sel_in_prog && (sign == LV_SIGNAL_PRESS_LOST || sign == LV_SIGNAL_RELEASED)) {
/*Input device is released. Check if anything was selected.*/
lv_obj_set_drag(lv_page_get_scrl(ta), true);
@ -1897,22 +1902,22 @@ static void update_cursor_position_on_click(lv_obj_t * ta, lv_signal_t sign, lv_
/*If the selected area has changed then update the real values and*/
/*Invalidate the text area.*/
if(ext->tmp_sel_start > ext->tmp_sel_end) {
if(ext_label->txt_sel_start != ext->tmp_sel_end || ext_label->txt_sel_end != ext->tmp_sel_start) {
ext_label->txt_sel_start = ext->tmp_sel_end;
ext_label->txt_sel_end = ext->tmp_sel_start;
if(ext->sel.start > ext->sel.end) {
if(ext_label->txt_sel_start != ext->sel.end || ext_label->txt_sel_end != ext->sel.start) {
ext_label->txt_sel_start = ext->sel.end;
ext_label->txt_sel_end = ext->sel.start;
lv_obj_invalidate(ta);
}
} else if(ext->tmp_sel_start < ext->tmp_sel_end) {
if(ext_label->txt_sel_start != ext->tmp_sel_start || ext_label->txt_sel_end != ext->tmp_sel_end) {
ext_label->txt_sel_start = ext->tmp_sel_start;
ext_label->txt_sel_end = ext->tmp_sel_end;
} else if(ext->sel.start < ext->sel.end) {
if(ext_label->txt_sel_start != ext->sel.start || ext_label->txt_sel_end != ext->sel.end) {
ext_label->txt_sel_start = ext->sel.start;
ext_label->txt_sel_end = ext->sel.end;
lv_obj_invalidate(ta);
}
} else {
if(ext_label->txt_sel_start != LV_LABEL_TEXT_SEL_OFF || ext_label->txt_sel_end != LV_LABEL_TEXT_SEL_OFF) {
ext_label->txt_sel_start = LV_LABEL_TEXT_SEL_OFF;
ext_label->txt_sel_end = LV_LABEL_TEXT_SEL_OFF;
if(ext_label->txt_sel_start != LV_DRAW_LABEL_NO_TXT_SEL || ext_label->txt_sel_end != LV_DRAW_LABEL_NO_TXT_SEL) {
ext_label->txt_sel_start = LV_DRAW_LABEL_NO_TXT_SEL;
ext_label->txt_sel_end = LV_DRAW_LABEL_NO_TXT_SEL;
lv_obj_invalidate(ta);
}
}

View File

@ -82,8 +82,7 @@ typedef struct
uint8_t click_pos : 1; /*1: Enable positioning the cursor by clicking the text area*/
} cursor;
#if LV_LABEL_TEXT_SEL
uint16_t tmp_sel_start; /*Temporary value*/
uint16_t tmp_sel_end; /*Temporary value*/
lv_draw_label_txt_sel_t sel; /*Temporary values for text selection*/
uint8_t text_sel_in_prog : 1; /*User is in process of selecting */
uint8_t text_sel_en : 1; /*Text can be selected on this text area*/
#endif

View File

@ -738,7 +738,7 @@ static bool lv_table_design(lv_obj_t * table, const lv_area_t * mask, lv_design_
label_mask_ok = lv_area_intersect(&label_mask, mask, &cell_area);
if(label_mask_ok) {
lv_draw_label(&txt_area, &label_mask, cell_style, opa_scale, ext->cell_data[cell] + 1,
txt_flags, NULL, -1, -1, NULL, lv_obj_get_base_dir(table));
txt_flags, NULL, NULL, NULL, lv_obj_get_base_dir(table));
}
/*Draw lines after '\n's*/
lv_point_t p1;