diff --git a/CHANGELOG.md b/CHANGELOG.md index a19141b109..04a973b948 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,13 +1,25 @@ # Changelog +## v7.11.0 (Planned for 19.02.2021) + +### New features +- Add better screen orientation management with software rotation support +- Decide text animation's direction based on base_dir (when using LV_USE_BIDI) + +### Bugfixes +- fix(gauge) fix needle invalidation +- fix(bar) correct symmetric handling for vertical sliders + ## v7.10.1 (Planned for 16.02.2021) ### Bugfixes - fix(draw) overlap outline with background to prevent aliasing artifacts - fix(indev) clear the indev's `act_obj` in `lv_indev_reset` - fix(text) fix out of bounds read in `_lv_txt_get_width` +- fix(list) scroll list when button is focused using LV_KEY_NEXT/PREV - fix(text) improve Arabic contextual analysis by adding hyphen processing and proper handling of lam-alef sequence - fix(delete) delete animation after the children are deleted +- fix(gauge) consider paddigns for needle images ## v7.10.0 diff --git a/CMakeLists.txt b/CMakeLists.txt index 4f9d825706..0a65216f60 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -60,5 +60,8 @@ zephyr_library_sources(${SOURCES}) endif() # CONFIG_LVGL else() -message(FATAL_ERROR "Unknown platform.") + +file(GLOB_RECURSE SOURCES src/*.c) +add_library(lvgl STATIC ${SOURCES}) + endif() diff --git a/Kconfig b/Kconfig index 1d97cadaa6..0e48abbb93 100644 --- a/Kconfig +++ b/Kconfig @@ -1,4 +1,4 @@ -# Kconfig file for LVGL v7.10.1 +# Kconfig file for LVGL v7.11.0 menu "LVGL configuration" diff --git a/component.mk b/component.mk index 0c8dbc5344..5d07eb7ef4 100644 --- a/component.mk +++ b/component.mk @@ -1,8 +1,23 @@ # ESP-IDF component file for make based commands -ifdef $(IDF_VER) - COMPONENT_SRCDIRS := . -COMPONENT_ADD_INCLUDEDIRS := . +COMPONENT_SRCDIRS += src +COMPONENT_SRCDIRS += src/lv_core +COMPONENT_SRCDIRS += src/lv_draw +COMPONENT_SRCDIRS += src/lv_font +COMPONENT_SRCDIRS += src/lv_gpu +COMPONENT_SRCDIRS += src/lv_hal +COMPONENT_SRCDIRS += src/lv_misc +COMPONENT_SRCDIRS += src/lv_themes +COMPONENT_SRCDIRS += src/lv_widgets -endif +COMPONENT_ADD_INCLUDEDIRS := . +COMPONENT_ADD_INCLUDEDIRS += src +COMPONENT_ADD_INCLUDEDIRS += src/lv_core +COMPONENT_ADD_INCLUDEDIRS += src/lv_draw +COMPONENT_ADD_INCLUDEDIRS += src/lv_font +COMPONENT_ADD_INCLUDEDIRS += src/lv_gpu +COMPONENT_ADD_INCLUDEDIRS += src/lv_hal +COMPONENT_ADD_INCLUDEDIRS += src/lv_misc +COMPONENT_ADD_INCLUDEDIRS += src/lv_themes +COMPONENT_ADD_INCLUDEDIRS += src/lv_widgets diff --git a/examples/porting/lv_port_disp_template.c b/examples/porting/lv_port_disp_template.c index a4f95fab40..20ce22ae88 100644 --- a/examples/porting/lv_port_disp_template.c +++ b/examples/porting/lv_port_disp_template.c @@ -82,13 +82,13 @@ void lv_port_disp_init(void) /* Example for 2) */ static lv_disp_buf_t draw_buf_dsc_2; static lv_color_t draw_buf_2_1[LV_HOR_RES_MAX * 10]; /*A buffer for 10 rows*/ - static lv_color_t draw_buf_2_1[LV_HOR_RES_MAX * 10]; /*An other buffer for 10 rows*/ - lv_disp_buf_init(&draw_buf_dsc_2, draw_buf_2_1, draw_buf_2_1, LV_HOR_RES_MAX * 10); /*Initialize the display buffer*/ + static lv_color_t draw_buf_2_2[LV_HOR_RES_MAX * 10]; /*An other buffer for 10 rows*/ + lv_disp_buf_init(&draw_buf_dsc_2, draw_buf_2_1, draw_buf_2_2, LV_HOR_RES_MAX * 10); /*Initialize the display buffer*/ /* Example for 3) */ static lv_disp_buf_t draw_buf_dsc_3; static lv_color_t draw_buf_3_1[LV_HOR_RES_MAX * LV_VER_RES_MAX]; /*A screen sized buffer*/ - static lv_color_t draw_buf_3_1[LV_HOR_RES_MAX * LV_VER_RES_MAX]; /*An other screen sized buffer*/ + static lv_color_t draw_buf_3_2[LV_HOR_RES_MAX * LV_VER_RES_MAX]; /*An other screen sized buffer*/ lv_disp_buf_init(&draw_buf_dsc_3, draw_buf_3_1, draw_buf_3_2, LV_HOR_RES_MAX * LV_VER_RES_MAX); /*Initialize the display buffer*/ /*----------------------------------- diff --git a/lv_conf_template.h b/lv_conf_template.h index 8832320be2..ebcab297fe 100644 --- a/lv_conf_template.h +++ b/lv_conf_template.h @@ -1,6 +1,6 @@ /** * @file lv_conf.h - * Configuration file for v7.10.1 + * Configuration file for v7.11.0 */ /* @@ -69,6 +69,9 @@ /* Type of coordinates. Should be `int16_t` (or `int32_t` for extreme cases) */ typedef int16_t lv_coord_t; +/* Maximum buffer size to allocate for rotation. Only used if software rotation is enabled. */ +#define LV_DISP_ROT_MAX_BUF (10U * 1024U) + /*========================= Memory manager settings *=========================*/ diff --git a/lvgl.h b/lvgl.h index 0c4670eeaa..4aa1d7e2b9 100644 --- a/lvgl.h +++ b/lvgl.h @@ -14,8 +14,8 @@ extern "C" { * CURRENT VERSION OF LVGL ***************************/ #define LVGL_VERSION_MAJOR 7 -#define LVGL_VERSION_MINOR 10 -#define LVGL_VERSION_PATCH 1 +#define LVGL_VERSION_MINOR 11 +#define LVGL_VERSION_PATCH 0 #define LVGL_VERSION_INFO "" /********************* diff --git a/src/lv_conf_internal.h b/src/lv_conf_internal.h index 152ec8f21d..e3ccef339f 100644 --- a/src/lv_conf_internal.h +++ b/src/lv_conf_internal.h @@ -170,6 +170,15 @@ /* Type of coordinates. Should be `int16_t` (or `int32_t` for extreme cases) */ +/* Maximum buffer size to allocate for rotation. Only used if software rotation is enabled. */ +#ifndef LV_DISP_ROT_MAX_BUF +# ifdef CONFIG_LV_DISP_ROT_MAX_BUF +# define LV_DISP_ROT_MAX_BUF CONFIG_LV_DISP_ROT_MAX_BUF +# else +# define LV_DISP_ROT_MAX_BUF (10U * 1024U) +# endif +#endif + /*========================= Memory manager settings *=========================*/ diff --git a/src/lv_core/lv_indev.c b/src/lv_core/lv_indev.c index e2b5698e5f..a58ea3937f 100644 --- a/src/lv_core/lv_indev.c +++ b/src/lv_core/lv_indev.c @@ -413,6 +413,16 @@ lv_task_t * lv_indev_get_read_task(lv_disp_t * indev) */ static void indev_pointer_proc(lv_indev_t * i, lv_indev_data_t * data) { + lv_disp_t * disp = i->driver.disp; + if(disp->driver.rotated == LV_DISP_ROT_180 || disp->driver.rotated == LV_DISP_ROT_270) { + data->point.x = disp->driver.hor_res - data->point.x - 1; + data->point.y = disp->driver.ver_res - data->point.y - 1; + } + if(disp->driver.rotated == LV_DISP_ROT_90 || disp->driver.rotated == LV_DISP_ROT_270) { + lv_coord_t tmp = data->point.y; + data->point.y = data->point.x; + data->point.x = disp->driver.ver_res - tmp - 1; + } /*Move the cursor if set and moved*/ if(i->cursor != NULL && (i->proc.types.pointer.last_point.x != data->point.x || i->proc.types.pointer.last_point.y != data->point.y)) { diff --git a/src/lv_core/lv_obj.c b/src/lv_core/lv_obj.c index 556bd0060d..cc3a0045b7 100644 --- a/src/lv_core/lv_obj.c +++ b/src/lv_core/lv_obj.c @@ -3474,6 +3474,7 @@ void lv_obj_init_draw_rect_dsc(lv_obj_t * obj, uint8_t part, lv_draw_rect_dsc_t if(opa_scale < LV_OPA_MAX) { draw_dsc->bg_opa = (uint16_t)((uint16_t)draw_dsc->bg_opa * opa_scale) >> 8; draw_dsc->border_opa = (uint16_t)((uint16_t)draw_dsc->border_opa * opa_scale) >> 8; + draw_dsc->outline_opa = (uint16_t)((uint16_t)draw_dsc->outline_opa * opa_scale) >> 8; draw_dsc->shadow_opa = (uint16_t)((uint16_t)draw_dsc->shadow_opa * opa_scale) >> 8; draw_dsc->pattern_opa = (uint16_t)((uint16_t)draw_dsc->pattern_opa * opa_scale) >> 8; draw_dsc->value_opa = (uint16_t)((uint16_t)draw_dsc->value_opa * opa_scale) >> 8; diff --git a/src/lv_core/lv_refr.c b/src/lv_core/lv_refr.c index a84a3d9174..8199f4eacc 100644 --- a/src/lv_core/lv_refr.c +++ b/src/lv_core/lv_refr.c @@ -741,12 +741,182 @@ static void lv_refr_obj(lv_obj_t * obj, const lv_area_t * mask_ori_p) } } +static void lv_refr_vdb_rotate_180(lv_disp_drv_t * drv, lv_area_t * area, lv_color_t * color_p) +{ + lv_coord_t area_w = lv_area_get_width(area); + lv_coord_t area_h = lv_area_get_height(area); + uint32_t total = area_w * area_h; + /* Swap the beginning and end values */ + lv_color_t tmp; + uint32_t i = total - 1, j = 0; + while(i > j) { + tmp = color_p[i]; + color_p[i] = color_p[j]; + color_p[j] = tmp; + i--; + j++; + } + lv_coord_t tmp_coord; + tmp_coord = area->y2; + area->y2 = drv->ver_res - area->y1 - 1; + area->y1 = drv->ver_res - tmp_coord - 1; + tmp_coord = area->x2; + area->x2 = drv->hor_res - area->x1 - 1; + area->x1 = drv->hor_res - tmp_coord - 1; +} + +static LV_ATTRIBUTE_FAST_MEM void lv_refr_vdb_rotate_90(bool invert_i, lv_coord_t area_w, lv_coord_t area_h, + lv_color_t * orig_color_p, lv_color_t * rot_buf) +{ + + uint32_t invert = (area_w * area_h) - 1; + uint32_t initial_i = ((area_w - 1) * area_h); + for(lv_coord_t y = 0; y < area_h; y++) { + uint32_t i = initial_i + y; + if(invert_i) + i = invert - i; + for(lv_coord_t x = 0; x < area_w; x++) { + rot_buf[i] = *(orig_color_p++); + if(invert_i) + i += area_h; + else + i -= area_h; + } + } +} + +/** + * Helper function for lv_refr_vdb_rotate_90_sqr. Given a list of four numbers, rotate the entire list to the left. + */ +static inline void lv_vdb_rotate4(lv_color_t * a, lv_color_t * b, lv_color_t * c, lv_color_t * d) +{ + lv_color_t tmp; + tmp = *a; + *a = *b; + *b = *c; + *c = *d; + *d = tmp; +} + +/** + * Rotate a square image 90/270 degrees in place. + * @note inspired by https://stackoverflow.com/a/43694906 + */ +static void lv_refr_vdb_rotate_90_sqr(bool is_270, lv_coord_t w, lv_color_t * color_p) +{ + for(lv_coord_t i = 0; i < w / 2; i++) { + for(lv_coord_t j = 0; j < (w + 1) / 2; j++) { + lv_coord_t inv_i = (w - 1) - i; + lv_coord_t inv_j = (w - 1) - j; + if(is_270) { + lv_vdb_rotate4( + &color_p[i * w + j], + &color_p[inv_j * w + i], + &color_p[inv_i * w + inv_j], + &color_p[j * w + inv_i] + ); + } + else { + lv_vdb_rotate4( + &color_p[i * w + j], + &color_p[j * w + inv_i], + &color_p[inv_i * w + inv_j], + &color_p[inv_j * w + i] + ); + } + + } + } +} + +/** + * Rotate the VDB to the display's native orientation. + */ +static void lv_refr_vdb_rotate(lv_area_t * area, lv_color_t * color_p) +{ + lv_disp_drv_t * drv = &disp_refr->driver; + if(lv_disp_is_true_double_buf(disp_refr) && drv->sw_rotate) { + LV_LOG_ERROR("cannot rotate a true double-buffered display!"); + return; + } + if(drv->rotated == LV_DISP_ROT_180) { + lv_refr_vdb_rotate_180(drv, area, color_p); + drv->flush_cb(drv, area, color_p); + } + else if(drv->rotated == LV_DISP_ROT_90 || drv->rotated == LV_DISP_ROT_270) { + /*Allocate a temporary buffer to store rotated image */ + lv_color_t * rot_buf = NULL; + lv_disp_buf_t * vdb = lv_disp_get_buf(disp_refr); + lv_coord_t area_w = lv_area_get_width(area); + lv_coord_t area_h = lv_area_get_height(area); + /*Determine the maximum number of rows that can be rotated at a time*/ + lv_coord_t max_row = LV_MATH_MIN((lv_coord_t)((LV_DISP_ROT_MAX_BUF / sizeof(lv_color_t)) / area_w), area_h); + lv_coord_t init_y_off; + init_y_off = area->y1; + if(drv->rotated == LV_DISP_ROT_90) { + area->y2 = drv->ver_res - area->x1 - 1; + area->y1 = area->y2 - area_w + 1; + } + else { + area->y1 = area->x1; + area->y2 = area->y1 + area_w - 1; + } + vdb->flushing = 0; + /*Rotate the screen in chunks, flushing after each one*/ + lv_coord_t row = 0; + while(row < area_h) { + lv_coord_t height = LV_MATH_MIN(max_row, area_h - row); + vdb->flushing = 1; + if((row == 0) && (area_h >= area_w)) { + /*Rotate the initial area as a square*/ + height = area_w; + lv_refr_vdb_rotate_90_sqr(drv->rotated == LV_DISP_ROT_270, area_w, color_p); + if(drv->rotated == LV_DISP_ROT_90) { + area->x1 = init_y_off; + area->x2 = init_y_off + area_w - 1; + } + else { + area->x2 = drv->hor_res - 1 - init_y_off; + area->x1 = area->x2 - area_w + 1; + } + } + else { + /*Rotate other areas using a maximum buffer size*/ + if(rot_buf == NULL) + rot_buf = _lv_mem_buf_get(LV_DISP_ROT_MAX_BUF); + lv_refr_vdb_rotate_90(drv->rotated == LV_DISP_ROT_270, area_w, height, color_p, rot_buf); + + if(drv->rotated == LV_DISP_ROT_90) { + area->x1 = init_y_off + row; + area->x2 = init_y_off + row + height - 1; + } + else { + area->x2 = drv->hor_res - 1 - init_y_off - row; + area->x1 = area->x2 - height + 1; + } + } + /*Flush the completed area to the display*/ + drv->flush_cb(drv, area, rot_buf == NULL ? color_p : rot_buf); + /*FIXME: Rotation forces legacy behavior where rendering and flushing are done serially*/ + while(vdb->flushing) { + if(drv->wait_cb) drv->wait_cb(drv); + } + color_p += area_w * height; + row += height; + } + /*Free the allocated buffer at the end if necessary*/ + if(rot_buf != NULL) + _lv_mem_buf_release(rot_buf); + } +} + /** * Flush the content of the VDB */ static void lv_refr_vdb_flush(void) { lv_disp_buf_t * vdb = lv_disp_get_buf(disp_refr); + lv_color_t * color_p = vdb->buf_act; /*In double buffered mode wait until the other buffer is flushed before flushing the current * one*/ @@ -765,8 +935,15 @@ static void lv_refr_vdb_flush(void) lv_disp_t * disp = _lv_refr_get_disp_refreshing(); if(disp->driver.gpu_wait_cb) disp->driver.gpu_wait_cb(&disp->driver); - if(disp->driver.flush_cb) disp->driver.flush_cb(&disp->driver, &vdb->area, vdb->buf_act); - + if(disp->driver.flush_cb) { + /*Rotate the buffer to the display's native orientation if necessary*/ + if(disp->driver.rotated != LV_DISP_ROT_NONE && disp->driver.sw_rotate) { + lv_refr_vdb_rotate(&vdb->area, vdb->buf_act); + } + else { + disp->driver.flush_cb(&disp->driver, &vdb->area, color_p); + } + } if(vdb->buf1 && vdb->buf2) { if(vdb->buf_act == vdb->buf1) vdb->buf_act = vdb->buf2; diff --git a/src/lv_core/lv_style.c b/src/lv_core/lv_style.c index 9f5e09d596..387b4da885 100644 --- a/src/lv_core/lv_style.c +++ b/src/lv_core/lv_style.c @@ -6,26 +6,12 @@ /********************* * INCLUDES *********************/ -#include "lv_obj.h" +#include "lv_style.h" #include "../lv_misc/lv_mem.h" -#include "../lv_misc/lv_anim.h" /********************* * DEFINES *********************/ -#define STYLE_MIX_MAX 256 -#define STYLE_MIX_SHIFT 8 /*log2(STYLE_MIX_MAX)*/ - -#define VAL_PROP(v1, v2, r) v1 + (((v2 - v1) * r) >> STYLE_MIX_SHIFT) -#define STYLE_ATTR_MIX(attr, r) \ - if(start->attr != end->attr) { \ - res->attr = VAL_PROP(start->attr, end->attr, r); \ - } else { \ - res->attr = start->attr; \ - } - -#define LV_STYLE_PROP_TO_ID(prop) (prop & 0xFF); -#define LV_STYLE_PROP_GET_TYPE(prop) ((prop >> 8) & 0xFF); /********************** * TYPEDEFS @@ -36,7 +22,7 @@ **********************/ LV_ATTRIBUTE_FAST_MEM static inline int32_t get_property_index(const lv_style_t * style, lv_style_property_t prop); static lv_style_t * get_alloc_local_style(lv_style_list_t * list); -static inline void style_resize(lv_style_t * style, size_t sz); +static inline bool style_resize(lv_style_t * style, size_t sz); static inline lv_style_property_t get_style_prop(const lv_style_t * style, size_t idx); static inline uint8_t get_style_prop_id(const lv_style_t * style, size_t idx); static inline uint8_t get_style_prop_attr(const lv_style_t * style, size_t idx); @@ -78,16 +64,14 @@ void lv_style_init(lv_style_t * style) */ void lv_style_copy(lv_style_t * style_dest, const lv_style_t * style_src) { - if(style_src == NULL) return; - LV_ASSERT_STYLE(style_dest); - LV_ASSERT_STYLE(style_src); - - if(style_src->map == NULL) return; uint16_t size = _lv_style_get_mem_size(style_src); + if(size == 0) return; + style_dest->map = lv_mem_alloc(size); - _lv_memcpy(style_dest->map, style_src->map, size); + if(style_dest->map) + _lv_memcpy(style_dest->map, style_src->map, size); } /** @@ -99,9 +83,6 @@ void lv_style_copy(lv_style_t * style_dest, const lv_style_t * style_src) */ bool lv_style_remove_prop(lv_style_t * style, lv_style_property_t prop) { - if(style == NULL) return false; - LV_ASSERT_STYLE(style); - int32_t id = get_property_index(style, prop); /*The property exists but not sure it's state is the same*/ if(id >= 0) { @@ -154,35 +135,44 @@ void lv_style_list_copy(lv_style_list_t * list_dest, const lv_style_list_t * lis _lv_style_list_reset(list_dest); - if(list_src->style_list == NULL) return; + if(list_src == NULL || list_src->style_list == NULL) return; /*Copy the styles but skip the transitions*/ if(list_src->has_local == 0) { if(list_src->has_trans) { list_dest->style_list = lv_mem_alloc((list_src->style_cnt - 1) * sizeof(lv_style_t *)); - _lv_memcpy(list_dest->style_list, list_src->style_list + 1, (list_src->style_cnt - 1) * sizeof(lv_style_t *)); - list_dest->style_cnt = list_src->style_cnt - 1; + if(list_dest->style_list) { + _lv_memcpy(list_dest->style_list, list_src->style_list + 1, (list_src->style_cnt - 1) * sizeof(lv_style_t *)); + list_dest->style_cnt = list_src->style_cnt - 1; + } } else { list_dest->style_list = lv_mem_alloc(list_src->style_cnt * sizeof(lv_style_t *)); - _lv_memcpy(list_dest->style_list, list_src->style_list, list_src->style_cnt * sizeof(lv_style_t *)); - list_dest->style_cnt = list_src->style_cnt; + if(list_dest->style_list) { + _lv_memcpy(list_dest->style_list, list_src->style_list, list_src->style_cnt * sizeof(lv_style_t *)); + list_dest->style_cnt = list_src->style_cnt; + } } } else { if(list_src->has_trans) { list_dest->style_list = lv_mem_alloc((list_src->style_cnt - 2) * sizeof(lv_style_t *)); - _lv_memcpy(list_dest->style_list, list_src->style_list + 2, (list_src->style_cnt - 2) * sizeof(lv_style_t *)); - list_dest->style_cnt = list_src->style_cnt - 2; + if(list_dest->style_list) { + _lv_memcpy(list_dest->style_list, list_src->style_list + 2, (list_src->style_cnt - 2) * sizeof(lv_style_t *)); + list_dest->style_cnt = list_src->style_cnt - 2; + } } else { list_dest->style_list = lv_mem_alloc((list_src->style_cnt - 1) * sizeof(lv_style_t *)); - _lv_memcpy(list_dest->style_list, list_src->style_list + 1, (list_src->style_cnt - 1) * sizeof(lv_style_t *)); - list_dest->style_cnt = list_src->style_cnt - 1; + if(list_dest->style_list) { + _lv_memcpy(list_dest->style_list, list_src->style_list + 1, (list_src->style_cnt - 1) * sizeof(lv_style_t *)); + list_dest->style_cnt = list_src->style_cnt - 1; + } } lv_style_t * local_style = get_alloc_local_style(list_dest); - lv_style_copy(local_style, get_alloc_local_style((lv_style_list_t *)list_src)); + if(local_style) + lv_style_copy(local_style, get_alloc_local_style((lv_style_list_t *)list_src)); } } @@ -203,12 +193,12 @@ void _lv_style_list_add_style(lv_style_list_t * list, lv_style_t * style) /*Remove the style first if already exists*/ _lv_style_list_remove_style(list, style); - lv_style_t ** new_classes; - if(list->style_cnt == 0) new_classes = lv_mem_alloc(sizeof(lv_style_t *)); - else new_classes = lv_mem_realloc(list->style_list, sizeof(lv_style_t *) * (list->style_cnt + 1)); - LV_ASSERT_MEM(new_classes); - if(new_classes == NULL) { - LV_LOG_WARN("lv_style_list_add_style: couldn't add the class"); + lv_style_t ** new_styles; + if(list->style_cnt == 0) new_styles = lv_mem_alloc(sizeof(lv_style_t *)); + else new_styles = lv_mem_realloc(list->style_list, sizeof(lv_style_t *) * (list->style_cnt + 1)); + LV_ASSERT_MEM(new_styles); + if(new_styles == NULL) { + LV_LOG_WARN("lv_style_list_add_style: couldn't add the style"); return; } @@ -218,12 +208,12 @@ void _lv_style_list_add_style(lv_style_list_t * list, lv_style_t * style) if(list->has_trans) first_style++; if(list->has_local) first_style++; for(i = list->style_cnt; i > first_style; i--) { - new_classes[i] = new_classes[i - 1]; + new_styles[i] = new_styles[i - 1]; } - new_classes[first_style] = style; + new_styles[first_style] = style; list->style_cnt++; - list->style_list = new_classes; + list->style_list = new_styles; } /** @@ -257,24 +247,22 @@ void _lv_style_list_remove_style(lv_style_list_t * list, lv_style_t * style) return; } - lv_style_t ** new_classes = lv_mem_alloc(sizeof(lv_style_t *) * (list->style_cnt - 1)); - LV_ASSERT_MEM(new_classes); - if(new_classes == NULL) { - LV_LOG_WARN("lv_style_list_remove_style: couldn't reallocate class list"); + lv_style_t ** new_styles = lv_mem_alloc(sizeof(lv_style_t *) * (list->style_cnt - 1)); + LV_ASSERT_MEM(new_styles); + if(new_styles == NULL) { + LV_LOG_WARN("lv_style_list_remove_style: couldn't reallocate style list"); return; } uint8_t j; for(i = 0, j = 0; i < list->style_cnt; i++) { if(list->style_list[i] == style) continue; - new_classes[j] = list->style_list[i]; - j++; - + new_styles[j++] = list->style_list[i]; } lv_mem_free(list->style_list); list->style_cnt--; - list->style_list = new_classes; + list->style_list = new_styles; } /** @@ -334,7 +322,7 @@ uint16_t _lv_style_get_mem_size(const lv_style_t * style) { LV_ASSERT_STYLE(style); - if(style->map == NULL) return 0; + if(style == NULL || style->map == NULL) return 0; size_t i = 0; uint8_t prop_id; @@ -357,8 +345,6 @@ uint16_t _lv_style_get_mem_size(const lv_style_t * style) */ void _lv_style_set_int(lv_style_t * style, lv_style_property_t prop, lv_style_int_t value) { - LV_ASSERT_STYLE(style); - int32_t id = get_property_index(style, prop); /*The property already exists but not sure it's state is the same*/ if(id >= 0) { @@ -375,16 +361,15 @@ void _lv_style_set_int(lv_style_t * style, lv_style_property_t prop, lv_style_in } /*Add new property if not exists yet*/ - uint8_t new_prop_size = (sizeof(lv_style_property_t) + sizeof(lv_style_int_t)); + uint8_t new_prop_size = sizeof(lv_style_property_t) + sizeof(lv_style_int_t); lv_style_property_t end_mark = _LV_STYLE_CLOSING_PROP; uint8_t end_mark_size = sizeof(end_mark); uint16_t size = _lv_style_get_mem_size(style); if(size == 0) size += end_mark_size; - size += sizeof(lv_style_property_t) + sizeof(lv_style_int_t); - style_resize(style, size); - LV_ASSERT_MEM(style->map); - if(style == NULL) return; + + size += new_prop_size; + if(!style_resize(style, size)) return; _lv_memcpy_small(style->map + size - new_prop_size - end_mark_size, &prop, sizeof(lv_style_property_t)); _lv_memcpy_small(style->map + size - sizeof(lv_style_int_t) - end_mark_size, &value, sizeof(lv_style_int_t)); @@ -403,8 +388,6 @@ void _lv_style_set_int(lv_style_t * style, lv_style_property_t prop, lv_style_in */ void _lv_style_set_color(lv_style_t * style, lv_style_property_t prop, lv_color_t color) { - LV_ASSERT_STYLE(style); - int32_t id = get_property_index(style, prop); /*The property already exists but not sure it's state is the same*/ if(id >= 0) { @@ -421,17 +404,15 @@ void _lv_style_set_color(lv_style_t * style, lv_style_property_t prop, lv_color_ } /*Add new property if not exists yet*/ - uint8_t new_prop_size = (sizeof(lv_style_property_t) + sizeof(lv_color_t)); + uint8_t new_prop_size = sizeof(lv_style_property_t) + sizeof(lv_color_t); lv_style_property_t end_mark = _LV_STYLE_CLOSING_PROP; uint8_t end_mark_size = sizeof(end_mark); uint16_t size = _lv_style_get_mem_size(style); if(size == 0) size += end_mark_size; - size += sizeof(lv_style_property_t) + sizeof(lv_color_t); - style_resize(style, size); - LV_ASSERT_MEM(style->map); - if(style == NULL) return; + size += new_prop_size; + if(!style_resize(style, size)) return; _lv_memcpy_small(style->map + size - new_prop_size - end_mark_size, &prop, sizeof(lv_style_property_t)); _lv_memcpy_small(style->map + size - sizeof(lv_color_t) - end_mark_size, &color, sizeof(lv_color_t)); @@ -450,8 +431,6 @@ void _lv_style_set_color(lv_style_t * style, lv_style_property_t prop, lv_color_ */ void _lv_style_set_opa(lv_style_t * style, lv_style_property_t prop, lv_opa_t opa) { - LV_ASSERT_STYLE(style); - int32_t id = get_property_index(style, prop); /*The property already exists but not sure it's state is the same*/ if(id >= 0) { @@ -468,17 +447,15 @@ void _lv_style_set_opa(lv_style_t * style, lv_style_property_t prop, lv_opa_t op } /*Add new property if not exists yet*/ - uint8_t new_prop_size = (sizeof(lv_style_property_t) + sizeof(lv_opa_t)); + uint8_t new_prop_size = sizeof(lv_style_property_t) + sizeof(lv_opa_t); lv_style_property_t end_mark = _LV_STYLE_CLOSING_PROP; uint8_t end_mark_size = sizeof(end_mark); uint16_t size = _lv_style_get_mem_size(style); if(size == 0) size += end_mark_size; - size += sizeof(lv_style_property_t) + sizeof(lv_opa_t); - style_resize(style, size); - LV_ASSERT_MEM(style->map); - if(style == NULL) return; + size += new_prop_size; + if(!style_resize(style, size)) return; _lv_memcpy_small(style->map + size - new_prop_size - end_mark_size, &prop, sizeof(lv_style_property_t)); _lv_memcpy_small(style->map + size - sizeof(lv_opa_t) - end_mark_size, &opa, sizeof(lv_opa_t)); @@ -497,8 +474,6 @@ void _lv_style_set_opa(lv_style_t * style, lv_style_property_t prop, lv_opa_t op */ void _lv_style_set_ptr(lv_style_t * style, lv_style_property_t prop, const void * p) { - LV_ASSERT_STYLE(style); - int32_t id = get_property_index(style, prop); /*The property already exists but not sure it's state is the same*/ if(id >= 0) { @@ -515,17 +490,15 @@ void _lv_style_set_ptr(lv_style_t * style, lv_style_property_t prop, const void } /*Add new property if not exists yet*/ - uint8_t new_prop_size = (sizeof(lv_style_property_t) + sizeof(const void *)); + uint8_t new_prop_size = sizeof(lv_style_property_t) + sizeof(const void *); lv_style_property_t end_mark = _LV_STYLE_CLOSING_PROP; uint8_t end_mark_size = sizeof(end_mark); uint16_t size = _lv_style_get_mem_size(style); if(size == 0) size += end_mark_size; - size += sizeof(lv_style_property_t) + sizeof(const void *); - style_resize(style, size); - LV_ASSERT_MEM(style->map); - if(style == NULL) return; + size += new_prop_size; + if(!style_resize(style, size)) return; _lv_memcpy_small(style->map + size - new_prop_size - end_mark_size, &prop, sizeof(lv_style_property_t)); _lv_memcpy_small(style->map + size - sizeof(const void *) - end_mark_size, &p, sizeof(const void *)); @@ -533,7 +506,7 @@ void _lv_style_set_ptr(lv_style_t * style, lv_style_property_t prop, const void } /** - * Get the a property from a style. + * Get an integer typed property from a style. * Take into account the style state and return the property which matches the best. * @param style pointer to a style where to search * @param prop the property, might contain ORed style states too @@ -542,14 +515,8 @@ void _lv_style_set_ptr(lv_style_t * style, lv_style_property_t prop, const void * Higher number is means better fit * -1 if the not found (`res` will be undefined) */ -int16_t _lv_style_get_int(const lv_style_t * style, lv_style_property_t prop, void * v_res) +int16_t _lv_style_get_int(const lv_style_t * style, lv_style_property_t prop, lv_style_int_t * res) { - lv_style_int_t * res = (lv_style_int_t *)v_res; - LV_ASSERT_STYLE(style); - - if(style == NULL) return -1; - if(style->map == NULL) return -1; - int32_t id = get_property_index(style, prop); if(id < 0) { return -1; @@ -559,10 +526,7 @@ int16_t _lv_style_get_int(const lv_style_t * style, lv_style_property_t prop, vo lv_style_attr_t attr_act; attr_act = get_style_prop_attr(style, id); - lv_style_attr_t attr_goal; - attr_goal = (prop >> 8) & 0xFF; - - return LV_STYLE_ATTR_GET_STATE(attr_act) & LV_STYLE_ATTR_GET_STATE(attr_goal); + return LV_STYLE_ATTR_GET_STATE(attr_act); } } @@ -579,14 +543,8 @@ int16_t _lv_style_get_int(const lv_style_t * style, lv_style_property_t prop, vo * For example: `lv_style_get_border_opa()` * @note for performance reasons it's not checked if the property really has opacity type */ -int16_t _lv_style_get_opa(const lv_style_t * style, lv_style_property_t prop, void * v_res) +int16_t _lv_style_get_opa(const lv_style_t * style, lv_style_property_t prop, lv_opa_t * res) { - lv_opa_t * res = (lv_opa_t *)v_res; - LV_ASSERT_STYLE(style); - - if(style == NULL) return -1; - if(style->map == NULL) return -1; - int32_t id = get_property_index(style, prop); if(id < 0) { return -1; @@ -596,10 +554,7 @@ int16_t _lv_style_get_opa(const lv_style_t * style, lv_style_property_t prop, vo lv_style_attr_t attr_act; attr_act = get_style_prop_attr(style, id); - lv_style_attr_t attr_goal; - attr_goal = (prop >> 8) & 0xFF; - - return LV_STYLE_ATTR_GET_STATE(attr_act) & LV_STYLE_ATTR_GET_STATE(attr_goal); + return LV_STYLE_ATTR_GET_STATE(attr_act); } } @@ -616,11 +571,8 @@ int16_t _lv_style_get_opa(const lv_style_t * style, lv_style_property_t prop, vo * For example: `lv_style_get_border_color()` * @note for performance reasons it's not checked if the property really has color type */ -int16_t _lv_style_get_color(const lv_style_t * style, lv_style_property_t prop, void * v_res) +int16_t _lv_style_get_color(const lv_style_t * style, lv_style_property_t prop, lv_color_t * res) { - lv_color_t * res = (lv_color_t *)v_res; - if(style == NULL) return -1; - if(style->map == NULL) return -1; int32_t id = get_property_index(style, prop); if(id < 0) { return -1; @@ -630,10 +582,7 @@ int16_t _lv_style_get_color(const lv_style_t * style, lv_style_property_t prop, lv_style_attr_t attr_act; attr_act = get_style_prop_attr(style, id); - lv_style_attr_t attr_goal; - attr_goal = (prop >> 8) & 0xFF; - - return LV_STYLE_ATTR_GET_STATE(attr_act) & LV_STYLE_ATTR_GET_STATE(attr_goal); + return LV_STYLE_ATTR_GET_STATE(attr_act); } } @@ -650,12 +599,8 @@ int16_t _lv_style_get_color(const lv_style_t * style, lv_style_property_t prop, * For example: `lv_style_get_text_font()` * @note for performance reasons it's not checked if the property really has pointer type */ -int16_t _lv_style_get_ptr(const lv_style_t * style, lv_style_property_t prop, void * v_res) +int16_t _lv_style_get_ptr(const lv_style_t * style, lv_style_property_t prop, const void ** res) { - const void ** res = (const void **)v_res; - if(style == NULL) return -1; - if(style->map == NULL) return -1; - int32_t id = get_property_index(style, prop); if(id < 0) { return -1; @@ -665,10 +610,7 @@ int16_t _lv_style_get_ptr(const lv_style_t * style, lv_style_property_t prop, vo lv_style_attr_t attr_act; attr_act = get_style_prop_attr(style, id); - lv_style_attr_t attr_goal; - attr_goal = (prop >> 8) & 0xFF; - - return LV_STYLE_ATTR_GET_STATE(attr_act) & LV_STYLE_ATTR_GET_STATE(attr_goal); + return LV_STYLE_ATTR_GET_STATE(attr_act); } } @@ -822,9 +764,8 @@ lv_res_t _lv_style_list_get_int(lv_style_list_t * list, lv_style_property_t prop int16_t ci; for(ci = 0; ci < list->style_cnt; ci++) { - /* changed class to _class to allow compilation as c++ */ - lv_style_t * _class = lv_style_list_get_style(list, ci); - int16_t weight_act = _lv_style_get_int(_class, prop, &value_act); + lv_style_t * style = lv_style_list_get_style(list, ci); + int16_t weight_act = _lv_style_get_int(style, prop, &value_act); /*On perfect match return the value immediately*/ if(weight_act == weight_goal) { @@ -844,7 +785,6 @@ lv_res_t _lv_style_list_get_int(lv_style_list_t * list, lv_style_property_t prop if(weight >= 0) return LV_RES_OK; else return LV_RES_INV; - } /** @@ -876,8 +816,8 @@ lv_res_t _lv_style_list_get_color(lv_style_list_t * list, lv_style_property_t pr int16_t ci; for(ci = 0; ci < list->style_cnt; ci++) { - lv_style_t * _class = lv_style_list_get_style(list, ci); - int16_t weight_act = _lv_style_get_color(_class, prop, &value_act); + lv_style_t * style = lv_style_list_get_style(list, ci); + int16_t weight_act = _lv_style_get_color(style, prop, &value_act); /*On perfect match return the value immediately*/ if(weight_act == weight_goal) { *res = value_act; @@ -926,8 +866,8 @@ lv_res_t _lv_style_list_get_opa(lv_style_list_t * list, lv_style_property_t prop int16_t ci; for(ci = 0; ci < list->style_cnt; ci++) { - lv_style_t * _class = lv_style_list_get_style(list, ci); - int16_t weight_act = _lv_style_get_opa(_class, prop, &value_act); + lv_style_t * style = lv_style_list_get_style(list, ci); + int16_t weight_act = _lv_style_get_opa(style, prop, &value_act); /*On perfect match return the value immediately*/ if(weight_act == weight_goal) { *res = value_act; @@ -976,8 +916,8 @@ lv_res_t _lv_style_list_get_ptr(lv_style_list_t * list, lv_style_property_t prop int16_t ci; for(ci = 0; ci < list->style_cnt; ci++) { - lv_style_t * _class = lv_style_list_get_style(list, ci); - int16_t weight_act = _lv_style_get_ptr(_class, prop, &value_act); + lv_style_t * style = lv_style_list_get_style(list, ci); + int16_t weight_act = _lv_style_get_ptr(style, prop, &value_act); /*On perfect match return the value immediately*/ if(weight_act == weight_goal) { *res = value_act; @@ -1052,6 +992,7 @@ LV_ATTRIBUTE_FAST_MEM static inline int32_t get_property_index(const lv_style_t { LV_ASSERT_STYLE(style); + if(style == NULL) return -1; if(style->map == NULL) return -1; uint8_t id_to_find = prop & 0xFF; @@ -1092,7 +1033,7 @@ LV_ATTRIBUTE_FAST_MEM static inline int32_t get_property_index(const lv_style_t } /** - * Get he local style from a style list. Allocate it if not exists yet. + * Get the local style from a style list. Allocate it if not exists yet. * @param list pointer to a style list * @return pointer to the local style */ @@ -1122,9 +1063,12 @@ static lv_style_t * get_alloc_local_style(lv_style_list_t * list) * @param style pointer to the style to be resized. * @param size new size */ -static inline void style_resize(lv_style_t * style, size_t sz) +static inline bool style_resize(lv_style_t * style, size_t sz) { - style->map = lv_mem_realloc(style->map, sz); + uint8_t * new_map = lv_mem_realloc(style->map, sz); + if(sz && new_map == NULL) return false; + style->map = new_map; + return true; } /** @@ -1136,9 +1080,7 @@ static inline void style_resize(lv_style_t * style, size_t sz) static inline lv_style_property_t get_style_prop(const lv_style_t * style, size_t idx) { lv_style_property_t prop; - uint8_t * prop_p = (uint8_t *)∝ - prop_p[0] = style->map[idx]; - prop_p[1] = style->map[idx + 1]; + _lv_memcpy_small(&prop, &style->map[idx], sizeof(lv_style_property_t)); return prop; } @@ -1167,8 +1109,7 @@ static inline uint8_t get_style_prop_attr(const lv_style_t * style, size_t idx) /** * Get property size. * @param prop_id property id. - * @param idx index of the style in style->map - * @return attribute of property in style->map + idx + * @return size of property */ static inline size_t get_prop_size(uint8_t prop_id) { diff --git a/src/lv_core/lv_style.h b/src/lv_core/lv_style.h index 1ff7b3b4db..3ac80eb37a 100644 --- a/src/lv_core/lv_style.h +++ b/src/lv_core/lv_style.h @@ -100,7 +100,7 @@ enum { LV_STYLE_PROP_INIT(LV_STYLE_TRANSFORM_HEIGHT, 0x0, LV_STYLE_ID_VALUE + 5, LV_STYLE_ATTR_NONE), LV_STYLE_PROP_INIT(LV_STYLE_TRANSFORM_ANGLE, 0x0, LV_STYLE_ID_VALUE + 6, LV_STYLE_ATTR_NONE), LV_STYLE_PROP_INIT(LV_STYLE_TRANSFORM_ZOOM, 0x0, LV_STYLE_ID_VALUE + 7, LV_STYLE_ATTR_NONE), - LV_STYLE_PROP_INIT(LV_STYLE_OPA_SCALE, 0x0, LV_STYLE_ID_OPA + 0, LV_STYLE_ATTR_INHERIT), + LV_STYLE_PROP_INIT(LV_STYLE_OPA_SCALE, 0x0, LV_STYLE_ID_OPA + 0, LV_STYLE_ATTR_INHERIT), LV_STYLE_PROP_INIT(LV_STYLE_PAD_TOP, 0x1, LV_STYLE_ID_VALUE + 0, LV_STYLE_ATTR_NONE), LV_STYLE_PROP_INIT(LV_STYLE_PAD_BOTTOM, 0x1, LV_STYLE_ID_VALUE + 1, LV_STYLE_ATTR_NONE), @@ -127,11 +127,11 @@ enum { LV_STYLE_PROP_INIT(LV_STYLE_BORDER_COLOR, 0x3, LV_STYLE_ID_COLOR + 0, LV_STYLE_ATTR_NONE), LV_STYLE_PROP_INIT(LV_STYLE_BORDER_OPA, 0x3, LV_STYLE_ID_OPA + 0, LV_STYLE_ATTR_NONE), - LV_STYLE_PROP_INIT(LV_STYLE_OUTLINE_WIDTH, 0x4, LV_STYLE_ID_VALUE + 0, LV_STYLE_ATTR_NONE), - LV_STYLE_PROP_INIT(LV_STYLE_OUTLINE_PAD, 0x4, LV_STYLE_ID_VALUE + 1, LV_STYLE_ATTR_NONE), - LV_STYLE_PROP_INIT(LV_STYLE_OUTLINE_BLEND_MODE, 0x4, LV_STYLE_ID_VALUE + 2, LV_STYLE_ATTR_NONE), - LV_STYLE_PROP_INIT(LV_STYLE_OUTLINE_COLOR, 0x4, LV_STYLE_ID_COLOR + 0, LV_STYLE_ATTR_NONE), - LV_STYLE_PROP_INIT(LV_STYLE_OUTLINE_OPA, 0x4, LV_STYLE_ID_OPA + 0, LV_STYLE_ATTR_NONE), + LV_STYLE_PROP_INIT(LV_STYLE_OUTLINE_WIDTH, 0x4, LV_STYLE_ID_VALUE + 0, LV_STYLE_ATTR_NONE), + LV_STYLE_PROP_INIT(LV_STYLE_OUTLINE_PAD, 0x4, LV_STYLE_ID_VALUE + 1, LV_STYLE_ATTR_NONE), + LV_STYLE_PROP_INIT(LV_STYLE_OUTLINE_BLEND_MODE, 0x4, LV_STYLE_ID_VALUE + 2, LV_STYLE_ATTR_NONE), + LV_STYLE_PROP_INIT(LV_STYLE_OUTLINE_COLOR, 0x4, LV_STYLE_ID_COLOR + 0, LV_STYLE_ATTR_NONE), + LV_STYLE_PROP_INIT(LV_STYLE_OUTLINE_OPA, 0x4, LV_STYLE_ID_OPA + 0, LV_STYLE_ATTR_NONE), LV_STYLE_PROP_INIT(LV_STYLE_SHADOW_WIDTH, 0x5, LV_STYLE_ID_VALUE + 0, LV_STYLE_ATTR_NONE), LV_STYLE_PROP_INIT(LV_STYLE_SHADOW_OFS_X, 0x5, LV_STYLE_ID_VALUE + 1, LV_STYLE_ATTR_NONE), @@ -141,33 +141,33 @@ enum { LV_STYLE_PROP_INIT(LV_STYLE_SHADOW_COLOR, 0x5, LV_STYLE_ID_COLOR + 0, LV_STYLE_ATTR_NONE), LV_STYLE_PROP_INIT(LV_STYLE_SHADOW_OPA, 0x5, LV_STYLE_ID_OPA + 0, LV_STYLE_ATTR_NONE), - LV_STYLE_PROP_INIT(LV_STYLE_PATTERN_BLEND_MODE, 0x6, LV_STYLE_ID_VALUE + 0, LV_STYLE_ATTR_NONE), - LV_STYLE_PROP_INIT(LV_STYLE_PATTERN_REPEAT, 0x6, LV_STYLE_ID_VALUE + 1, LV_STYLE_ATTR_NONE), - LV_STYLE_PROP_INIT(LV_STYLE_PATTERN_RECOLOR, 0x6, LV_STYLE_ID_COLOR + 0, LV_STYLE_ATTR_NONE), - LV_STYLE_PROP_INIT(LV_STYLE_PATTERN_OPA, 0x6, LV_STYLE_ID_OPA + 0, LV_STYLE_ATTR_NONE), - LV_STYLE_PROP_INIT(LV_STYLE_PATTERN_RECOLOR_OPA, 0x6, LV_STYLE_ID_OPA + 1, LV_STYLE_ATTR_NONE), - LV_STYLE_PROP_INIT(LV_STYLE_PATTERN_IMAGE, 0x6, LV_STYLE_ID_PTR + 0, LV_STYLE_ATTR_NONE), + LV_STYLE_PROP_INIT(LV_STYLE_PATTERN_BLEND_MODE, 0x6, LV_STYLE_ID_VALUE + 0, LV_STYLE_ATTR_NONE), + LV_STYLE_PROP_INIT(LV_STYLE_PATTERN_REPEAT, 0x6, LV_STYLE_ID_VALUE + 1, LV_STYLE_ATTR_NONE), + LV_STYLE_PROP_INIT(LV_STYLE_PATTERN_RECOLOR, 0x6, LV_STYLE_ID_COLOR + 0, LV_STYLE_ATTR_NONE), + LV_STYLE_PROP_INIT(LV_STYLE_PATTERN_OPA, 0x6, LV_STYLE_ID_OPA + 0, LV_STYLE_ATTR_NONE), + LV_STYLE_PROP_INIT(LV_STYLE_PATTERN_RECOLOR_OPA, 0x6, LV_STYLE_ID_OPA + 1, LV_STYLE_ATTR_NONE), + LV_STYLE_PROP_INIT(LV_STYLE_PATTERN_IMAGE, 0x6, LV_STYLE_ID_PTR + 0, LV_STYLE_ATTR_NONE), - LV_STYLE_PROP_INIT(LV_STYLE_VALUE_LETTER_SPACE, 0x7, LV_STYLE_ID_VALUE + 0, LV_STYLE_ATTR_NONE), - LV_STYLE_PROP_INIT(LV_STYLE_VALUE_LINE_SPACE, 0x7, LV_STYLE_ID_VALUE + 1, LV_STYLE_ATTR_NONE), - LV_STYLE_PROP_INIT(LV_STYLE_VALUE_BLEND_MODE, 0x7, LV_STYLE_ID_VALUE + 2, LV_STYLE_ATTR_NONE), - LV_STYLE_PROP_INIT(LV_STYLE_VALUE_OFS_X, 0x7, LV_STYLE_ID_VALUE + 3, LV_STYLE_ATTR_NONE), - LV_STYLE_PROP_INIT(LV_STYLE_VALUE_OFS_Y, 0x7, LV_STYLE_ID_VALUE + 4, LV_STYLE_ATTR_NONE), - LV_STYLE_PROP_INIT(LV_STYLE_VALUE_ALIGN, 0x7, LV_STYLE_ID_VALUE + 5, LV_STYLE_ATTR_NONE), - LV_STYLE_PROP_INIT(LV_STYLE_VALUE_COLOR, 0x7, LV_STYLE_ID_COLOR + 0, LV_STYLE_ATTR_NONE), - LV_STYLE_PROP_INIT(LV_STYLE_VALUE_OPA, 0x7, LV_STYLE_ID_OPA + 0, LV_STYLE_ATTR_NONE), - LV_STYLE_PROP_INIT(LV_STYLE_VALUE_FONT, 0x7, LV_STYLE_ID_PTR + 0, LV_STYLE_ATTR_NONE), - LV_STYLE_PROP_INIT(LV_STYLE_VALUE_STR, 0x7, LV_STYLE_ID_PTR + 1, LV_STYLE_ATTR_NONE), + LV_STYLE_PROP_INIT(LV_STYLE_VALUE_LETTER_SPACE, 0x7, LV_STYLE_ID_VALUE + 0, LV_STYLE_ATTR_NONE), + LV_STYLE_PROP_INIT(LV_STYLE_VALUE_LINE_SPACE, 0x7, LV_STYLE_ID_VALUE + 1, LV_STYLE_ATTR_NONE), + LV_STYLE_PROP_INIT(LV_STYLE_VALUE_BLEND_MODE, 0x7, LV_STYLE_ID_VALUE + 2, LV_STYLE_ATTR_NONE), + LV_STYLE_PROP_INIT(LV_STYLE_VALUE_OFS_X, 0x7, LV_STYLE_ID_VALUE + 3, LV_STYLE_ATTR_NONE), + LV_STYLE_PROP_INIT(LV_STYLE_VALUE_OFS_Y, 0x7, LV_STYLE_ID_VALUE + 4, LV_STYLE_ATTR_NONE), + LV_STYLE_PROP_INIT(LV_STYLE_VALUE_ALIGN, 0x7, LV_STYLE_ID_VALUE + 5, LV_STYLE_ATTR_NONE), + LV_STYLE_PROP_INIT(LV_STYLE_VALUE_COLOR, 0x7, LV_STYLE_ID_COLOR + 0, LV_STYLE_ATTR_NONE), + LV_STYLE_PROP_INIT(LV_STYLE_VALUE_OPA, 0x7, LV_STYLE_ID_OPA + 0, LV_STYLE_ATTR_NONE), + LV_STYLE_PROP_INIT(LV_STYLE_VALUE_FONT, 0x7, LV_STYLE_ID_PTR + 0, LV_STYLE_ATTR_NONE), + LV_STYLE_PROP_INIT(LV_STYLE_VALUE_STR, 0x7, LV_STYLE_ID_PTR + 1, LV_STYLE_ATTR_NONE), - LV_STYLE_PROP_INIT(LV_STYLE_TEXT_LETTER_SPACE, 0x8, LV_STYLE_ID_VALUE + 0, LV_STYLE_ATTR_INHERIT), - LV_STYLE_PROP_INIT(LV_STYLE_TEXT_LINE_SPACE, 0x8, LV_STYLE_ID_VALUE + 1, LV_STYLE_ATTR_INHERIT), - LV_STYLE_PROP_INIT(LV_STYLE_TEXT_DECOR, 0x8, LV_STYLE_ID_VALUE + 2, LV_STYLE_ATTR_INHERIT), - LV_STYLE_PROP_INIT(LV_STYLE_TEXT_BLEND_MODE, 0x8, LV_STYLE_ID_VALUE + 3, LV_STYLE_ATTR_INHERIT), - LV_STYLE_PROP_INIT(LV_STYLE_TEXT_COLOR, 0x8, LV_STYLE_ID_COLOR + 0, LV_STYLE_ATTR_INHERIT), - LV_STYLE_PROP_INIT(LV_STYLE_TEXT_SEL_COLOR, 0x8, LV_STYLE_ID_COLOR + 1, LV_STYLE_ATTR_INHERIT), - LV_STYLE_PROP_INIT(LV_STYLE_TEXT_SEL_BG_COLOR, 0x8, LV_STYLE_ID_COLOR + 2, LV_STYLE_ATTR_INHERIT), - LV_STYLE_PROP_INIT(LV_STYLE_TEXT_OPA, 0x8, LV_STYLE_ID_OPA + 0, LV_STYLE_ATTR_INHERIT), - LV_STYLE_PROP_INIT(LV_STYLE_TEXT_FONT, 0x8, LV_STYLE_ID_PTR + 0, LV_STYLE_ATTR_INHERIT), + LV_STYLE_PROP_INIT(LV_STYLE_TEXT_LETTER_SPACE, 0x8, LV_STYLE_ID_VALUE + 0, LV_STYLE_ATTR_INHERIT), + LV_STYLE_PROP_INIT(LV_STYLE_TEXT_LINE_SPACE, 0x8, LV_STYLE_ID_VALUE + 1, LV_STYLE_ATTR_INHERIT), + LV_STYLE_PROP_INIT(LV_STYLE_TEXT_DECOR, 0x8, LV_STYLE_ID_VALUE + 2, LV_STYLE_ATTR_INHERIT), + LV_STYLE_PROP_INIT(LV_STYLE_TEXT_BLEND_MODE, 0x8, LV_STYLE_ID_VALUE + 3, LV_STYLE_ATTR_INHERIT), + LV_STYLE_PROP_INIT(LV_STYLE_TEXT_COLOR, 0x8, LV_STYLE_ID_COLOR + 0, LV_STYLE_ATTR_INHERIT), + LV_STYLE_PROP_INIT(LV_STYLE_TEXT_SEL_COLOR, 0x8, LV_STYLE_ID_COLOR + 1, LV_STYLE_ATTR_INHERIT), + LV_STYLE_PROP_INIT(LV_STYLE_TEXT_SEL_BG_COLOR, 0x8, LV_STYLE_ID_COLOR + 2, LV_STYLE_ATTR_INHERIT), + LV_STYLE_PROP_INIT(LV_STYLE_TEXT_OPA, 0x8, LV_STYLE_ID_OPA + 0, LV_STYLE_ATTR_INHERIT), + LV_STYLE_PROP_INIT(LV_STYLE_TEXT_FONT, 0x8, LV_STYLE_ID_PTR + 0, LV_STYLE_ATTR_INHERIT), LV_STYLE_PROP_INIT(LV_STYLE_LINE_WIDTH, 0x9, LV_STYLE_ID_VALUE + 0, LV_STYLE_ATTR_NONE), LV_STYLE_PROP_INIT(LV_STYLE_LINE_BLEND_MODE, 0x9, LV_STYLE_ID_VALUE + 1, LV_STYLE_ATTR_NONE), @@ -190,7 +190,7 @@ enum { LV_STYLE_PROP_INIT(LV_STYLE_TRANSITION_PROP_4, 0xB, LV_STYLE_ID_VALUE + 5, LV_STYLE_ATTR_NONE), LV_STYLE_PROP_INIT(LV_STYLE_TRANSITION_PROP_5, 0xB, LV_STYLE_ID_VALUE + 6, LV_STYLE_ATTR_NONE), LV_STYLE_PROP_INIT(LV_STYLE_TRANSITION_PROP_6, 0xB, LV_STYLE_ID_VALUE + 7, LV_STYLE_ATTR_NONE), - LV_STYLE_PROP_INIT(LV_STYLE_TRANSITION_PATH, 0xB, LV_STYLE_ID_PTR + 0, LV_STYLE_ATTR_NONE), + LV_STYLE_PROP_INIT(LV_STYLE_TRANSITION_PATH, 0xB, LV_STYLE_ID_PTR + 0, LV_STYLE_ATTR_NONE), LV_STYLE_PROP_INIT(LV_STYLE_SCALE_WIDTH, 0xC, LV_STYLE_ID_VALUE + 0, LV_STYLE_ATTR_NONE), LV_STYLE_PROP_INIT(LV_STYLE_SCALE_BORDER_WIDTH, 0xC, LV_STYLE_ID_VALUE + 1, LV_STYLE_ATTR_NONE), @@ -231,9 +231,9 @@ typedef struct { uint32_t ignore_cache : 1; /*1: Ignore cache while getting value of properties*/ uint32_t radius_zero : 1; - uint32_t opa_scale_cover : 1; - uint32_t clip_corner_off : 1; - uint32_t transform_all_zero : 1; + uint32_t opa_scale_cover : 1; + uint32_t clip_corner_off : 1; + uint32_t transform_all_zero : 1; uint32_t pad_all_zero : 1; uint32_t margin_all_zero : 1; uint32_t blend_mode_all_normal : 1; @@ -405,7 +405,7 @@ void _lv_style_set_ptr(lv_style_t * style, lv_style_property_t prop, const void * For example: `lv_style_get_border_width()` * @note for performance reasons it's not checked if the property really has integer type */ -int16_t _lv_style_get_int(const lv_style_t * style, lv_style_property_t prop, void * res); +int16_t _lv_style_get_int(const lv_style_t * style, lv_style_property_t prop, lv_style_int_t * res); /** * Get a color typed property from a style. @@ -420,7 +420,7 @@ int16_t _lv_style_get_int(const lv_style_t * style, lv_style_property_t prop, vo * For example: `lv_style_get_border_color()` * @note for performance reasons it's not checked if the property really has color type */ -int16_t _lv_style_get_color(const lv_style_t * style, lv_style_property_t prop, void * res); +int16_t _lv_style_get_color(const lv_style_t * style, lv_style_property_t prop, lv_color_t * res); /** * Get an opacity typed property from a style. @@ -435,7 +435,7 @@ int16_t _lv_style_get_color(const lv_style_t * style, lv_style_property_t prop, * For example: `lv_style_get_border_opa()` * @note for performance reasons it's not checked if the property really has opacity type */ -int16_t _lv_style_get_opa(const lv_style_t * style, lv_style_property_t prop, void * res); +int16_t _lv_style_get_opa(const lv_style_t * style, lv_style_property_t prop, lv_opa_t * res); /** * Get a pointer typed property from a style. @@ -450,7 +450,7 @@ int16_t _lv_style_get_opa(const lv_style_t * style, lv_style_property_t prop, vo * For example: `lv_style_get_text_font()` * @note for performance reasons it's not checked if the property really has pointer type */ -int16_t _lv_style_get_ptr(const lv_style_t * style, lv_style_property_t prop, void * res); +int16_t _lv_style_get_ptr(const lv_style_t * style, lv_style_property_t prop, const void ** res); /** * Get the local style of a style list @@ -461,7 +461,7 @@ lv_style_t * lv_style_list_get_local_style(lv_style_list_t * list); /** * Get the transition style of a style list - * @param list pointer to a style list where the local property should be set + * @param list pointer to a style list where the transition property should be set * @return pointer to the transition style if exists else `NULL`. */ lv_style_t * _lv_style_list_get_transition_style(lv_style_list_t * list); @@ -574,7 +574,7 @@ bool lv_debug_check_style(const lv_style_t * style); /** * Check whether a style list is valid (initialized correctly) - * @param style pointer to a style + * @param list pointer to a style list * @return true: valid */ bool lv_debug_check_style_list(const lv_style_list_t * list); @@ -596,7 +596,7 @@ bool lv_debug_check_style_list(const lv_style_list_t * list); * lv_style_init(&my_style); * lv_style_copy(&my_style, &style_to_copy); */ -#define LV_STYLE_CREATE(name, copy_p) static lv_style_t name; lv_style_init(&name); lv_style_copy(&name, copy_p); +#define LV_STYLE_CREATE(name, copy_p) static lv_style_t name; lv_style_init(&name); lv_style_copy(&name, copy_p) #if LV_USE_DEBUG diff --git a/src/lv_draw/lv_draw_img.h b/src/lv_draw/lv_draw_img.h index a9c699092b..53c8f444b4 100644 --- a/src/lv_draw/lv_draw_img.h +++ b/src/lv_draw/lv_draw_img.h @@ -15,6 +15,7 @@ extern "C" { *********************/ #include "lv_img_decoder.h" #include "lv_img_buf.h" +#include "../lv_core/lv_style.h" /********************* * DEFINES diff --git a/src/lv_draw/lv_draw_rect.c b/src/lv_draw/lv_draw_rect.c index 430216bb8c..de5e8843d8 100644 --- a/src/lv_draw/lv_draw_rect.c +++ b/src/lv_draw/lv_draw_rect.c @@ -716,6 +716,9 @@ LV_ATTRIBUTE_FAST_MEM static void draw_shadow(const lv_area_t * coords, const lv has_com = _lv_area_intersect(&ca, &a, clip); if(has_com && _lv_area_is_in(&a, &bg_coords, r_bg) == false) { + /*Avoid overlap in the middle with large radius*/ + if(ca.x1 <= w_half) ca.x1 = w_half + 1; + if(simple_mode) ca.x1 = LV_MATH_MAX(ca.x1, coords->x2); /*Draw horizontal lines*/ lv_coord_t w = lv_area_get_width(&ca); @@ -841,6 +844,9 @@ LV_ATTRIBUTE_FAST_MEM static void draw_shadow(const lv_area_t * coords, const lv has_com = _lv_area_intersect(&ca, &a, clip); if(has_com && _lv_area_is_in(&a, &bg_coords, r_bg) == false) { + /*Avoid overlap in the middle with large radius*/ + if(ca.x2 > w_half) ca.x2 = w_half; + if(simple_mode) ca.x2 = LV_MATH_MIN(coords->x1, ca.x2); /*Draw vertical lines*/ lv_coord_t w = lv_area_get_width(&ca); @@ -879,6 +885,9 @@ LV_ATTRIBUTE_FAST_MEM static void draw_shadow(const lv_area_t * coords, const lv has_com = _lv_area_intersect(&ca, &a, clip); if(has_com && _lv_area_is_in(&a, &bg_coords, r_bg) == false) { + /*Avoid overlap in the middle with large radius*/ + if(ca.y2 > h_half) ca.y2 = h_half; + if(simple_mode) ca.y2 = LV_MATH_MIN(ca.y2, coords->y1); /*Draw horizontal lines*/ lv_coord_t w = lv_area_get_width(&ca); @@ -920,6 +929,9 @@ LV_ATTRIBUTE_FAST_MEM static void draw_shadow(const lv_area_t * coords, const lv has_com = _lv_area_intersect(&ca, &a, clip); if(has_com && _lv_area_is_in(&a, &bg_coords, r_bg) == false) { + /*Avoid overlap in the middle with large radius*/ + if(ca.y1 <= h_half) ca.y1 = h_half + 1; + if(simple_mode) ca.y1 = LV_MATH_MAX(ca.y1, coords->y2); /*Draw horizontal lines*/ lv_coord_t w = lv_area_get_width(&ca); diff --git a/src/lv_draw/lv_img_cache.c b/src/lv_draw/lv_img_cache.c index f5dc99d3c6..364fdebf56 100644 --- a/src/lv_draw/lv_img_cache.c +++ b/src/lv_draw/lv_img_cache.c @@ -33,6 +33,10 @@ /********************** * STATIC PROTOTYPES **********************/ +#if LV_IMG_CACHE_DEF_SIZE + static bool lv_img_cache_match(const void * src1, const void * src2); +#endif + #if LV_IMG_CACHE_DEF_SIZE == 0 static lv_img_cache_entry_t cache_temp; #endif @@ -82,16 +86,8 @@ lv_img_cache_entry_t * _lv_img_cache_open(const void * src, lv_color_t color) } for(i = 0; i < entry_cnt; i++) { - bool match = false; - lv_img_src_t src_type = lv_img_src_get_type(cache[i].dec_dsc.src); - if(src_type == LV_IMG_SRC_VARIABLE) { - if(cache[i].dec_dsc.src == src && cache[i].dec_dsc.color.full == color.full) match = true; - } - else if(src_type == LV_IMG_SRC_FILE) { - if(strcmp(cache[i].dec_dsc.src, src) == 0) match = true; - } - - if(match) { + if(color.full == cache[i].dec_dsc.color.full && + lv_img_cache_match(src, cache[i].dec_dsc.src)) { /* If opened increment its life. * Image difficult to open should live longer to keep avoid frequent their recaching. * Therefore increase `life` with `time_to_open`*/ @@ -122,19 +118,14 @@ lv_img_cache_entry_t * _lv_img_cache_open(const void * src, lv_color_t color) else { LV_LOG_INFO("image draw: cache miss, cached to an empty entry"); } - #else cached_src = &cache_temp; #endif /*Open the image and measure the time to open*/ - uint32_t t_start; - t_start = lv_tick_get(); - cached_src->dec_dsc.time_to_open = 0; - lv_res_t open_res = lv_img_decoder_open(&cached_src->dec_dsc, src, color); + uint32_t t_start = lv_tick_get(); + lv_res_t open_res = lv_img_decoder_open(&cached_src->dec_dsc, src, color); if(open_res == LV_RES_INV) { LV_LOG_WARN("Image draw cannot open the image resource"); - lv_img_decoder_close(&cached_src->dec_dsc); - _lv_memset_00(&cached_src->dec_dsc, sizeof(lv_img_decoder_dsc_t)); _lv_memset_00(cached_src, sizeof(lv_img_cache_entry_t)); cached_src->life = INT32_MIN; /*Make the empty entry very "weak" to force its use */ return NULL; @@ -180,11 +171,7 @@ void lv_img_cache_set_size(uint16_t new_entry_cnt) entry_cnt = new_entry_cnt; /*Clean the cache*/ - uint16_t i; - for(i = 0; i < entry_cnt; i++) { - _lv_memset_00(&LV_GC_ROOT(_lv_img_cache_array)[i].dec_dsc, sizeof(lv_img_decoder_dsc_t)); - _lv_memset_00(&LV_GC_ROOT(_lv_img_cache_array)[i], sizeof(lv_img_cache_entry_t)); - } + _lv_memset_00(LV_GC_ROOT(_lv_img_cache_array), entry_cnt * sizeof(lv_img_cache_entry_t)); #endif } @@ -200,12 +187,11 @@ void lv_img_cache_invalidate_src(const void * src) uint16_t i; for(i = 0; i < entry_cnt; i++) { - if(cache[i].dec_dsc.src == src || src == NULL) { + if(src == NULL || lv_img_cache_match(src, cache[i].dec_dsc.src)) { if(cache[i].dec_dsc.src != NULL) { lv_img_decoder_close(&cache[i].dec_dsc); } - _lv_memset_00(&cache[i].dec_dsc, sizeof(lv_img_decoder_dsc_t)); _lv_memset_00(&cache[i], sizeof(lv_img_cache_entry_t)); } } @@ -215,3 +201,17 @@ void lv_img_cache_invalidate_src(const void * src) /********************** * STATIC FUNCTIONS **********************/ + +#if LV_IMG_CACHE_DEF_SIZE +static bool lv_img_cache_match(const void * src1, const void * src2) +{ + lv_img_src_t src_type = lv_img_src_get_type(src1); + if(src_type == LV_IMG_SRC_VARIABLE) + return src1 == src2; + if(src_type != LV_IMG_SRC_FILE) + return false; + if(lv_img_src_get_type(src2) != LV_IMG_SRC_FILE) + return false; + return strcmp(src1, src2) == 0; +} +#endif diff --git a/src/lv_draw/lv_img_cache.h b/src/lv_draw/lv_img_cache.h index 6106aff901..f8f8fc483e 100644 --- a/src/lv_draw/lv_img_cache.h +++ b/src/lv_draw/lv_img_cache.h @@ -31,7 +31,7 @@ extern "C" { typedef struct { lv_img_decoder_dsc_t dec_dsc; /**< Image information */ - /** Count the cache entries's life. Add `time_tio_open` to `life` when the entry is used. + /** Count the cache entries's life. Add `time_to_open` to `life` when the entry is used. * Decrement all lifes by one every in every ::lv_img_cache_open. * If life == 0 the entry can be reused */ int32_t life; diff --git a/src/lv_draw/lv_img_decoder.c b/src/lv_draw/lv_img_decoder.c index 190edb252f..2a6aeb1bd7 100644 --- a/src/lv_draw/lv_img_decoder.c +++ b/src/lv_draw/lv_img_decoder.c @@ -10,7 +10,6 @@ #include "../lv_misc/lv_debug.h" #include "../lv_draw/lv_draw_img.h" #include "../lv_misc/lv_ll.h" -#include "../lv_misc/lv_color.h" #include "../lv_misc/lv_gc.h" /********************* @@ -24,7 +23,7 @@ **********************/ typedef struct { #if LV_USE_FILESYSTEM - lv_fs_file_t * f; + lv_fs_file_t f; #endif lv_color_t * palette; lv_opa_t * opa; @@ -63,9 +62,9 @@ void _lv_img_decoder_init(void) /*Create a decoder for the built in color format*/ decoder = lv_img_decoder_create(); + LV_ASSERT_MEM(decoder); if(decoder == NULL) { LV_LOG_WARN("lv_img_decoder_init: out of memory"); - LV_ASSERT_MEM(decoder); return; } @@ -84,15 +83,11 @@ void _lv_img_decoder_init(void) */ lv_res_t lv_img_decoder_get_info(const char * src, lv_img_header_t * header) { - header->always_zero = 0; - header->h = 0; - header->w = 0; - header->cf = LV_IMG_CF_UNKNOWN; + _lv_memset_00(header, sizeof(lv_img_header_t)); lv_res_t res = LV_RES_INV; lv_img_decoder_t * d; _LV_LL_READ(LV_GC_ROOT(_lv_img_defoder_ll), d) { - res = LV_RES_INV; if(d->info_cb) { res = d->info_cb(d, src, header); if(res == LV_RES_OK) break; @@ -116,39 +111,53 @@ lv_res_t lv_img_decoder_get_info(const char * src, lv_img_header_t * header) */ lv_res_t lv_img_decoder_open(lv_img_decoder_dsc_t * dsc, const void * src, lv_color_t color) { - dsc->color = color; - dsc->src_type = lv_img_src_get_type(src); - dsc->user_data = NULL; + _lv_memset_00(dsc, sizeof(lv_img_decoder_dsc_t)); + + dsc->color = color; + dsc->src_type = lv_img_src_get_type(src); if(dsc->src_type == LV_IMG_SRC_FILE) { size_t fnlen = strlen(src); dsc->src = lv_mem_alloc(fnlen + 1); + LV_ASSERT_MEM(dsc->src); + if(dsc->src == NULL) { + LV_LOG_WARN("lv_img_decoder_open: out of memory"); + return LV_RES_INV; + } strcpy((char *)dsc->src, src); } else { - dsc->src = src; + dsc->src = src; } lv_res_t res = LV_RES_INV; lv_img_decoder_t * d; _LV_LL_READ(LV_GC_ROOT(_lv_img_defoder_ll), d) { - /*Info an Open callbacks are required*/ + /*Info and Open callbacks are required*/ if(d->info_cb == NULL || d->open_cb == NULL) continue; res = d->info_cb(d, src, &dsc->header); if(res != LV_RES_OK) continue; - dsc->error_msg = NULL; - dsc->img_data = NULL; - dsc->decoder = d; - + dsc->decoder = d; res = d->open_cb(d, dsc); /*Opened successfully. It is a good decoder to for this image source*/ - if(res == LV_RES_OK) break; + if(res == LV_RES_OK) return res; + + /*Prepare for the next loop*/ + _lv_memset_00(&dsc->header, sizeof(lv_img_header_t)); + + dsc->error_msg = NULL; + dsc->img_data = NULL; + dsc->user_data = NULL; + dsc->time_to_open = 0; } + if(dsc->src_type == LV_IMG_SRC_FILE) + lv_mem_free(dsc->src); + return res; } @@ -273,6 +282,9 @@ lv_res_t lv_img_decoder_built_in_info(lv_img_decoder_t * decoder, const void * s } #if LV_USE_FILESYSTEM else if(src_type == LV_IMG_SRC_FILE) { + /*Support only "*.bin" files*/ + if(strcmp(lv_fs_get_ext(src), "bin")) return LV_RES_INV; + lv_fs_file_t file; lv_fs_res_t res; uint32_t rn; @@ -287,7 +299,6 @@ lv_res_t lv_img_decoder_built_in_info(lv_img_decoder_t * decoder, const void * s } if(header->cf < CF_BUILT_IN_FIRST || header->cf > CF_BUILT_IN_LAST) return LV_RES_INV; - } #endif else if(src_type == LV_IMG_SRC_SYMBOL) { @@ -309,7 +320,7 @@ lv_res_t lv_img_decoder_built_in_info(lv_img_decoder_t * decoder, const void * s /** * Open a built in image * @param decoder the decoder where this function belongs - * @param dsc pointer to decoder descriptor. `src`, `style` are already initialized in it. + * @param dsc pointer to decoder descriptor. `src`, `color` are already initialized in it. * @return LV_RES_OK: the info is successfully stored in `header`; LV_RES_INV: unknown format or other error. */ lv_res_t lv_img_decoder_built_in_open(lv_img_decoder_t * decoder, lv_img_decoder_dsc_t * dsc) @@ -317,7 +328,6 @@ lv_res_t lv_img_decoder_built_in_open(lv_img_decoder_t * decoder, lv_img_decoder /*Open the file if it's a file*/ if(dsc->src_type == LV_IMG_SRC_FILE) { #if LV_USE_FILESYSTEM - /*Support only "*.bin" files*/ if(strcmp(lv_fs_get_ext(dsc->src), "bin")) return LV_RES_INV; @@ -334,22 +344,14 @@ lv_res_t lv_img_decoder_built_in_open(lv_img_decoder_t * decoder, lv_img_decoder LV_ASSERT_MEM(dsc->user_data); if(dsc->user_data == NULL) { LV_LOG_ERROR("img_decoder_built_in_open: out of memory"); + lv_fs_close(&f); return LV_RES_INV; } _lv_memset_00(dsc->user_data, sizeof(lv_img_decoder_built_in_data_t)); } lv_img_decoder_built_in_data_t * user_data = dsc->user_data; - user_data->f = lv_mem_alloc(sizeof(f)); - LV_ASSERT_MEM(user_data->f); - if(user_data->f == NULL) { - LV_LOG_ERROR("img_decoder_built_in_open: out of memory"); - lv_img_decoder_built_in_close(decoder, dsc); - return LV_RES_INV; - } - - _lv_memcpy_small(user_data->f, &f, sizeof(f)); - + _lv_memcpy_small(&user_data->f, &f, sizeof(f)); #else LV_LOG_WARN("Image built-in decoder cannot read file because LV_USE_FILESYSTEM = 0"); return LV_RES_INV; @@ -373,14 +375,12 @@ lv_res_t lv_img_decoder_built_in_open(lv_img_decoder_t * decoder, lv_img_decoder } else { /*If it's a file it need to be read line by line later*/ - dsc->img_data = NULL; return LV_RES_OK; } } /*Process indexed images. Build a palette*/ else if(cf == LV_IMG_CF_INDEXED_1BIT || cf == LV_IMG_CF_INDEXED_2BIT || cf == LV_IMG_CF_INDEXED_4BIT || cf == LV_IMG_CF_INDEXED_8BIT) { - #if LV_IMG_CF_INDEXED uint8_t px_size = lv_img_cf_get_px_size(cf); uint32_t palette_size = 1 << px_size; @@ -391,7 +391,6 @@ lv_res_t lv_img_decoder_built_in_open(lv_img_decoder_t * decoder, lv_img_decoder LV_ASSERT_MEM(dsc->user_data); if(dsc->user_data == NULL) { LV_LOG_ERROR("img_decoder_built_in_open: out of memory"); - lv_img_decoder_built_in_close(decoder, dsc); return LV_RES_INV; } _lv_memset_00(dsc->user_data, sizeof(lv_img_decoder_built_in_data_t)); @@ -411,11 +410,11 @@ lv_res_t lv_img_decoder_built_in_open(lv_img_decoder_t * decoder, lv_img_decoder if(dsc->src_type == LV_IMG_SRC_FILE) { /*Read the palette from file*/ #if LV_USE_FILESYSTEM - lv_fs_seek(user_data->f, 4); /*Skip the header*/ + lv_fs_seek(&user_data->f, 4); /*Skip the header*/ lv_color32_t cur_color; uint32_t i; for(i = 0; i < palette_size; i++) { - lv_fs_read(user_data->f, &cur_color, sizeof(lv_color32_t), NULL); + lv_fs_read(&user_data->f, &cur_color, sizeof(lv_color32_t), NULL); user_data->palette[i] = lv_color_make(cur_color.ch.red, cur_color.ch.green, cur_color.ch.blue); user_data->opa[i] = cur_color.ch.alpha; } @@ -435,10 +434,10 @@ lv_res_t lv_img_decoder_built_in_open(lv_img_decoder_t * decoder, lv_img_decoder } } - dsc->img_data = NULL; return LV_RES_OK; #else LV_LOG_WARN("Indexed (palette) images are not enabled in lv_conf.h. See LV_IMG_CF_INDEXED"); + lv_img_decoder_built_in_close(decoder, dsc); return LV_RES_INV; #endif } @@ -446,10 +445,10 @@ lv_res_t lv_img_decoder_built_in_open(lv_img_decoder_t * decoder, lv_img_decoder else if(cf == LV_IMG_CF_ALPHA_1BIT || cf == LV_IMG_CF_ALPHA_2BIT || cf == LV_IMG_CF_ALPHA_4BIT || cf == LV_IMG_CF_ALPHA_8BIT) { #if LV_IMG_CF_ALPHA - dsc->img_data = NULL; return LV_RES_OK; /*Nothing to process*/ #else LV_LOG_WARN("Alpha indexed images are not enabled in lv_conf.h. See LV_IMG_CF_ALPHA"); + lv_img_decoder_built_in_close(decoder, dsc); return LV_RES_INV; #endif } @@ -491,7 +490,6 @@ lv_res_t lv_img_decoder_built_in_read_line(lv_img_decoder_t * decoder, lv_img_de } else if(dsc->header.cf == LV_IMG_CF_ALPHA_1BIT || dsc->header.cf == LV_IMG_CF_ALPHA_2BIT || dsc->header.cf == LV_IMG_CF_ALPHA_4BIT || dsc->header.cf == LV_IMG_CF_ALPHA_8BIT) { - res = lv_img_decoder_built_in_line_alpha(dsc, x, y, len, buf); } else if(dsc->header.cf == LV_IMG_CF_INDEXED_1BIT || dsc->header.cf == LV_IMG_CF_INDEXED_2BIT || @@ -518,16 +516,13 @@ void lv_img_decoder_built_in_close(lv_img_decoder_t * decoder, lv_img_decoder_ds lv_img_decoder_built_in_data_t * user_data = dsc->user_data; if(user_data) { #if LV_USE_FILESYSTEM - if(user_data->f) { - lv_fs_close(user_data->f); - lv_mem_free(user_data->f); - } + if(dsc->src_type == LV_IMG_SRC_FILE) + lv_fs_close(&user_data->f); #endif if(user_data->palette) lv_mem_free(user_data->palette); if(user_data->opa) lv_mem_free(user_data->opa); lv_mem_free(user_data); - dsc->user_data = NULL; } } @@ -546,14 +541,14 @@ static lv_res_t lv_img_decoder_built_in_line_true_color(lv_img_decoder_dsc_t * d uint32_t pos = ((y * dsc->header.w + x) * px_size) >> 3; pos += 4; /*Skip the header*/ - res = lv_fs_seek(user_data->f, pos); + res = lv_fs_seek(&user_data->f, pos); if(res != LV_FS_RES_OK) { LV_LOG_WARN("Built-in image decoder seek failed"); return LV_RES_INV; } uint32_t btr = len * (px_size >> 3); uint32_t br = 0; - res = lv_fs_read(user_data->f, buf, btr, &br); + res = lv_fs_read(&user_data->f, buf, btr, &br); if(res != LV_FS_RES_OK || btr != br) { LV_LOG_WARN("Built-in image decoder read failed"); return LV_RES_INV; @@ -574,7 +569,6 @@ static lv_res_t lv_img_decoder_built_in_line_true_color(lv_img_decoder_dsc_t * d static lv_res_t lv_img_decoder_built_in_line_alpha(lv_img_decoder_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_coord_t len, uint8_t * buf) { - #if LV_IMG_CF_ALPHA const lv_opa_t alpha1_opa_table[2] = {0, 255}; /*Opacity mapping with bpp = 1 (Just for compatibility)*/ const lv_opa_t alpha2_opa_table[4] = {0, 85, 170, 255}; /*Opacity mapping with bpp = 2*/ @@ -608,24 +602,21 @@ static lv_res_t lv_img_decoder_built_in_line_alpha(lv_img_decoder_dsc_t * dsc, l int8_t pos = 0; switch(dsc->header.cf) { case LV_IMG_CF_ALPHA_1BIT: - w = (dsc->header.w >> 3); /*E.g. w = 20 -> w = 2 + 1*/ - if(dsc->header.w & 0x7) w++; + w = (dsc->header.w + 7) >> 3; /*E.g. w = 20 -> w = 2 + 1*/ ofs += w * y + (x >> 3); /*First pixel*/ - pos = 7 - (x & 0x7); + pos = 7 - (x & 0x7); opa_table = alpha1_opa_table; break; case LV_IMG_CF_ALPHA_2BIT: - w = (dsc->header.w >> 2); /*E.g. w = 13 -> w = 3 + 1 (bytes)*/ - if(dsc->header.w & 0x3) w++; + w = (dsc->header.w + 3) >> 2; /*E.g. w = 13 -> w = 3 + 1 (bytes)*/ ofs += w * y + (x >> 2); /*First pixel*/ - pos = 6 - ((x & 0x3) * 2); + pos = 6 - (x & 0x3) * 2; opa_table = alpha2_opa_table; break; case LV_IMG_CF_ALPHA_4BIT: - w = (dsc->header.w >> 1); /*E.g. w = 13 -> w = 6 + 1 (bytes)*/ - if(dsc->header.w & 0x1) w++; + w = (dsc->header.w + 1) >> 1; /*E.g. w = 13 -> w = 6 + 1 (bytes)*/ ofs += w * y + (x >> 1); /*First pixel*/ - pos = 4 - ((x & 0x1) * 4); + pos = 4 - (x & 0x1) * 4; opa_table = alpha4_opa_table; break; case LV_IMG_CF_ALPHA_8BIT: @@ -638,6 +629,7 @@ static lv_res_t lv_img_decoder_built_in_line_alpha(lv_img_decoder_dsc_t * dsc, l #if LV_USE_FILESYSTEM lv_img_decoder_built_in_data_t * user_data = dsc->user_data; uint8_t * fs_buf = _lv_mem_buf_get(w); + if(fs_buf == NULL) return LV_RES_INV; #endif const uint8_t * data_tmp = NULL; @@ -648,8 +640,8 @@ static lv_res_t lv_img_decoder_built_in_line_alpha(lv_img_decoder_dsc_t * dsc, l } else { #if LV_USE_FILESYSTEM - lv_fs_seek(user_data->f, ofs + 4); /*+4 to skip the header*/ - lv_fs_read(user_data->f, fs_buf, w, NULL); + lv_fs_seek(&user_data->f, ofs + 4); /*+4 to skip the header*/ + lv_fs_read(&user_data->f, fs_buf, w, NULL); data_tmp = fs_buf; #else LV_LOG_WARN("Image built-in alpha line reader can't read file because LV_USE_FILESYSTEM = 0"); @@ -659,7 +651,7 @@ static lv_res_t lv_img_decoder_built_in_line_alpha(lv_img_decoder_dsc_t * dsc, l } for(i = 0; i < len; i++) { - uint8_t val_act = (*data_tmp & (mask << pos)) >> pos; + uint8_t val_act = (*data_tmp >> pos) & mask; buf[i * LV_IMG_PX_SIZE_ALPHA_BYTE + LV_IMG_PX_SIZE_ALPHA_BYTE - 1] = dsc->header.cf == LV_IMG_CF_ALPHA_8BIT ? val_act : opa_table[val_act]; @@ -674,7 +666,6 @@ static lv_res_t lv_img_decoder_built_in_line_alpha(lv_img_decoder_dsc_t * dsc, l _lv_mem_buf_release(fs_buf); #endif return LV_RES_OK; - #else LV_LOG_WARN("Image built-in alpha line reader failed because LV_IMG_CF_ALPHA is 0 in lv_conf.h"); return LV_RES_INV; @@ -684,7 +675,6 @@ static lv_res_t lv_img_decoder_built_in_line_alpha(lv_img_decoder_dsc_t * dsc, l static lv_res_t lv_img_decoder_built_in_line_indexed(lv_img_decoder_dsc_t * dsc, lv_coord_t x, lv_coord_t y, lv_coord_t len, uint8_t * buf) { - #if LV_IMG_CF_INDEXED uint8_t px_size = lv_img_cf_get_px_size(dsc->header.cf); uint16_t mask = (1 << px_size) - 1; /*E.g. px_size = 2; mask = 0x03*/ @@ -694,25 +684,22 @@ static lv_res_t lv_img_decoder_built_in_line_indexed(lv_img_decoder_dsc_t * dsc, uint32_t ofs = 0; switch(dsc->header.cf) { case LV_IMG_CF_INDEXED_1BIT: - w = (dsc->header.w >> 3); /*E.g. w = 20 -> w = 2 + 1*/ - if(dsc->header.w & 0x7) w++; + w = (dsc->header.w + 7) >> 3; /*E.g. w = 20 -> w = 2 + 1*/ ofs += w * y + (x >> 3); /*First pixel*/ ofs += 8; /*Skip the palette*/ pos = 7 - (x & 0x7); break; case LV_IMG_CF_INDEXED_2BIT: - w = (dsc->header.w >> 2); /*E.g. w = 13 -> w = 3 + 1 (bytes)*/ - if(dsc->header.w & 0x3) w++; + w = (dsc->header.w + 3) >> 2; /*E.g. w = 13 -> w = 3 + 1 (bytes)*/ ofs += w * y + (x >> 2); /*First pixel*/ ofs += 16; /*Skip the palette*/ - pos = 6 - ((x & 0x3) * 2); + pos = 6 - (x & 0x3) * 2; break; case LV_IMG_CF_INDEXED_4BIT: - w = (dsc->header.w >> 1); /*E.g. w = 13 -> w = 6 + 1 (bytes)*/ - if(dsc->header.w & 0x1) w++; + w = (dsc->header.w + 1) >> 1; /*E.g. w = 13 -> w = 6 + 1 (bytes)*/ ofs += w * y + (x >> 1); /*First pixel*/ ofs += 64; /*Skip the palette*/ - pos = 4 - ((x & 0x1) * 4); + pos = 4 - (x & 0x1) * 4; break; case LV_IMG_CF_INDEXED_8BIT: w = dsc->header.w; /*E.g. x = 7 -> w = 7 (bytes)*/ @@ -726,6 +713,7 @@ static lv_res_t lv_img_decoder_built_in_line_indexed(lv_img_decoder_dsc_t * dsc, #if LV_USE_FILESYSTEM uint8_t * fs_buf = _lv_mem_buf_get(w); + if(fs_buf == NULL) return LV_RES_INV; #endif const uint8_t * data_tmp = NULL; if(dsc->src_type == LV_IMG_SRC_VARIABLE) { @@ -734,8 +722,8 @@ static lv_res_t lv_img_decoder_built_in_line_indexed(lv_img_decoder_dsc_t * dsc, } else { #if LV_USE_FILESYSTEM - lv_fs_seek(user_data->f, ofs + 4); /*+4 to skip the header*/ - lv_fs_read(user_data->f, fs_buf, w, NULL); + lv_fs_seek(&user_data->f, ofs + 4); /*+4 to skip the header*/ + lv_fs_read(&user_data->f, fs_buf, w, NULL); data_tmp = fs_buf; #else LV_LOG_WARN("Image built-in indexed line reader can't read file because LV_USE_FILESYSTEM = 0"); @@ -746,7 +734,7 @@ static lv_res_t lv_img_decoder_built_in_line_indexed(lv_img_decoder_dsc_t * dsc, lv_coord_t i; for(i = 0; i < len; i++) { - uint8_t val_act = (*data_tmp & (mask << pos)) >> pos; + uint8_t val_act = (*data_tmp >> pos) & mask; lv_color_t color = user_data->palette[val_act]; #if LV_COLOR_DEPTH == 8 || LV_COLOR_DEPTH == 1 diff --git a/src/lv_draw/lv_img_decoder.h b/src/lv_draw/lv_img_decoder.h index 5ea93ae5ea..8bcef4bf1f 100644 --- a/src/lv_draw/lv_img_decoder.h +++ b/src/lv_draw/lv_img_decoder.h @@ -20,7 +20,7 @@ extern "C" { #include "../lv_misc/lv_fs.h" #include "../lv_misc/lv_types.h" #include "../lv_misc/lv_area.h" -#include "../lv_core/lv_style.h" +#include "../lv_misc/lv_color.h" /********************* * DEFINES @@ -59,7 +59,7 @@ typedef lv_res_t (*lv_img_decoder_info_f_t)(struct _lv_img_decoder * decoder, co /** * Open an image for decoding. Prepare it as it is required to read it later * @param decoder pointer to the decoder the function associated with - * @param dsc pointer to decoder descriptor. `src`, `style` are already initialized in it. + * @param dsc pointer to decoder descriptor. `src`, `color` are already initialized in it. */ typedef lv_res_t (*lv_img_decoder_open_f_t)(struct _lv_img_decoder * decoder, struct _lv_img_decoder_dsc * dsc); diff --git a/src/lv_hal/lv_hal_disp.c b/src/lv_hal/lv_hal_disp.c index 007fdc3678..bd31f3e316 100644 --- a/src/lv_hal/lv_hal_disp.c +++ b/src/lv_hal/lv_hal_disp.c @@ -58,7 +58,8 @@ void lv_disp_drv_init(lv_disp_drv_t * driver) driver->hor_res = LV_HOR_RES_MAX; driver->ver_res = LV_VER_RES_MAX; driver->buffer = NULL; - driver->rotated = 0; + driver->rotated = LV_DISP_ROT_NONE; + driver->sw_rotate = 0; driver->color_chroma_key = LV_COLOR_TRANSP; driver->dpi = LV_DPI; @@ -178,12 +179,25 @@ lv_disp_t * lv_disp_drv_register(lv_disp_drv_t * driver) */ void lv_disp_drv_update(lv_disp_t * disp, lv_disp_drv_t * new_drv) { - memcpy(&disp->driver, new_drv, sizeof(lv_disp_drv_t)); + if(new_drv != &disp->driver) + memcpy(&disp->driver, new_drv, sizeof(lv_disp_drv_t)); lv_obj_t * scr; _LV_LL_READ(disp->scr_ll, scr) { lv_obj_set_size(scr, lv_disp_get_hor_res(disp), lv_disp_get_ver_res(disp)); } + + /* + * This method is usually called upon orientation change, thus the screen is now a + * different size. + * The object invalidated its previous area. That area is now out of the screen area + * so we reset all invalidated areas and invalidate the active screen's new area only. + */ + _lv_memset_00(disp->inv_areas, sizeof(disp->inv_areas)); + _lv_memset_00(disp->inv_area_joined, sizeof(disp->inv_area_joined)); + disp->inv_p = 0; + if(disp->act_scr != NULL) + lv_obj_invalidate(disp->act_scr); } /** @@ -240,8 +254,15 @@ lv_coord_t lv_disp_get_hor_res(lv_disp_t * disp) if(disp == NULL) return LV_HOR_RES_MAX; - else - return disp->driver.rotated == 0 ? disp->driver.hor_res : disp->driver.ver_res; + else { + switch(disp->driver.rotated) { + case LV_DISP_ROT_90: + case LV_DISP_ROT_270: + return disp->driver.ver_res; + default: + return disp->driver.hor_res; + } + } } /** @@ -255,8 +276,15 @@ lv_coord_t lv_disp_get_ver_res(lv_disp_t * disp) if(disp == NULL) return LV_VER_RES_MAX; - else - return disp->driver.rotated == 0 ? disp->driver.ver_res : disp->driver.hor_res; + else { + switch(disp->driver.rotated) { + case LV_DISP_ROT_90: + case LV_DISP_ROT_270: + return disp->driver.hor_res; + default: + return disp->driver.ver_res; + } + } } /** @@ -416,6 +444,31 @@ bool lv_disp_is_true_double_buf(lv_disp_t * disp) } } +/** + * Set the rotation of this display. + * @param disp pointer to a display (NULL to use the default display) + * @param rotation rotation angle + */ +void lv_disp_set_rotation(lv_disp_t * disp, lv_disp_rot_t rotation) +{ + if(disp == NULL) disp = lv_disp_get_default(); + + disp->driver.rotated = rotation; + lv_disp_drv_update(disp, &disp->driver); +} + +/** + * Get the current rotation of this display. + * @param disp pointer to a display (NULL to use the default display) + * @return rotation angle + */ +lv_disp_rot_t lv_disp_get_rotation(lv_disp_t * disp) +{ + if(disp == NULL) disp = lv_disp_get_default(); + + return disp->driver.rotated; +} + /********************** * STATIC FUNCTIONS **********************/ diff --git a/src/lv_hal/lv_hal_disp.h b/src/lv_hal/lv_hal_disp.h index 5eba4e2664..874b3dbb05 100644 --- a/src/lv_hal/lv_hal_disp.h +++ b/src/lv_hal/lv_hal_disp.h @@ -60,6 +60,14 @@ typedef struct { volatile uint32_t last_part : 1; /*1: the last part of the current area is being rendered*/ } lv_disp_buf_t; + +typedef enum { + LV_DISP_ROT_NONE = 0, + LV_DISP_ROT_90, + LV_DISP_ROT_180, + LV_DISP_ROT_270 +} lv_disp_rot_t; + /** * Display Driver structure to be registered by HAL */ @@ -75,7 +83,8 @@ typedef struct _disp_drv_t { #if LV_ANTIALIAS uint32_t antialiasing : 1; /**< 1: antialiasing is enabled on this display. */ #endif - uint32_t rotated : 1; /**< 1: turn the display by 90 degree. @warning Does not update coordinates for you!*/ + uint32_t rotated : 2; + uint32_t sw_rotate : 1; /**< 1: use software rotation (slower) */ #if LV_COLOR_SCREEN_TRANSP /**Handle if the screen doesn't have a solid (opa == LV_OPA_COVER) background. @@ -281,6 +290,20 @@ lv_coord_t lv_disp_get_dpi(lv_disp_t * disp); */ lv_disp_size_t lv_disp_get_size_category(lv_disp_t * disp); +/** + * Set the rotation of this display. + * @param disp pointer to a display (NULL to use the default display) + * @param rotation rotation angle + */ +void lv_disp_set_rotation(lv_disp_t * disp, lv_disp_rot_t rotation); + +/** + * Get the current rotation of this display. + * @param disp pointer to a display (NULL to use the default display) + * @return rotation angle + */ +lv_disp_rot_t lv_disp_get_rotation(lv_disp_t * disp); + //! @cond Doxygen_Suppress /** diff --git a/src/lv_misc/lv_anim.c b/src/lv_misc/lv_anim.c index 4b01b80516..ccbe5af150 100644 --- a/src/lv_misc/lv_anim.c +++ b/src/lv_misc/lv_anim.c @@ -1,5 +1,5 @@ /** - * @file anim.c + * @file lv_anim.c * */ @@ -33,13 +33,14 @@ **********************/ static void anim_task(lv_task_t * param); static void anim_mark_list_change(void); -static bool anim_ready_handler(lv_anim_t * a); +static void anim_ready_handler(lv_anim_t * a); /********************** * STATIC VARIABLES **********************/ static uint32_t last_task_run; static bool anim_list_changed; +static bool anim_run_round; static lv_task_t * _lv_anim_task; const lv_anim_path_t lv_anim_path_def = {.cb = lv_anim_path_linear}; @@ -57,7 +58,6 @@ const lv_anim_path_t lv_anim_path_def = {.cb = lv_anim_path_linear}; void _lv_anim_core_init(void) { _lv_ll_init(&LV_GC_ROOT(_lv_anim_ll), sizeof(lv_anim_t)); - last_task_run = lv_tick_get(); _lv_anim_task = lv_task_create(anim_task, LV_DISP_DEF_REFR_PERIOD, LV_ANIM_TASK_PRIO, NULL); anim_mark_list_change(); /*Turn off the animation task*/ anim_list_changed = false; /*The list has not actually changed*/ @@ -93,7 +93,7 @@ void lv_anim_start(lv_anim_t * a) /*If the list is empty the anim task was suspended and it's last run measure is invalid*/ if(_lv_ll_is_empty(&LV_GC_ROOT(_lv_anim_ll))) { - last_task_run = lv_tick_get() - 1; + last_task_run = lv_tick_get(); } /*Add the new animation to the animation linked list*/ @@ -103,6 +103,7 @@ void lv_anim_start(lv_anim_t * a) /*Initialize the animation descriptor*/ a->time_orig = a->time; + a->run_round = anim_run_round; _lv_memcpy(new_anim, a, sizeof(lv_anim_t)); /*Set the start value*/ @@ -148,6 +149,15 @@ bool lv_anim_del(void * var, lv_anim_exec_xcb_t exec_cb) return del; } +/** + * Delete all the animations animation + */ +void lv_anim_del_all(void) +{ + _lv_ll_clear(&LV_GC_ROOT(_lv_anim_ll)); + anim_mark_list_change(); +} + /** * Get the animation of a variable and its `exec_cb`. * @param var pointer to variable @@ -187,12 +197,10 @@ uint16_t lv_anim_count_running(void) * @param end end value of the animation * @return the required time [ms] for the animation with the given parameters */ -uint16_t lv_anim_speed_to_time(uint16_t speed, lv_anim_value_t start, lv_anim_value_t end) +uint32_t lv_anim_speed_to_time(uint32_t speed, lv_anim_value_t start, lv_anim_value_t end) { - int32_t d = LV_MATH_ABS((int32_t)start - end); - uint32_t time = (int32_t)((int32_t)(d * 1000) / speed); - - if(time > UINT16_MAX) time = UINT16_MAX; + uint32_t d = LV_MATH_ABS(start - end); + uint32_t time = (d * 1000) / speed; if(time == 0) { time++; @@ -222,22 +230,16 @@ lv_anim_value_t lv_anim_path_linear(const lv_anim_path_t * path, const lv_anim_t LV_UNUSED(path); /*Calculate the current step*/ - uint32_t step; - if(a->time == a->act_time) { - step = LV_ANIM_RESOLUTION; /*Use the last value if the time fully elapsed*/ - } - else { - step = ((int32_t)a->act_time * LV_ANIM_RESOLUTION) / a->time; - } + int32_t step = _lv_map(a->act_time, 0, a->time, 0, LV_ANIM_RESOLUTION); /* Get the new value which will be proportional to `step` * and the `start` and `end` values*/ int32_t new_value; - new_value = (int32_t)step * (a->end - a->start); + new_value = step * (a->end - a->start); new_value = new_value >> LV_ANIM_RES_SHIFT; new_value += a->start; - return (lv_anim_value_t)new_value; + return new_value; } /** @@ -250,20 +252,16 @@ lv_anim_value_t lv_anim_path_ease_in(const lv_anim_path_t * path, const lv_anim_ LV_UNUSED(path); /*Calculate the current step*/ - uint32_t t; - if(a->time == a->act_time) - t = 1024; - else - t = (uint32_t)((uint32_t)a->act_time * 1024) / a->time; + uint32_t t = _lv_map(a->act_time, 0, a->time, 0, 1024); int32_t step = _lv_bezier3(t, 0, 1, 1, 1024); int32_t new_value; - new_value = (int32_t)step * (a->end - a->start); + new_value = step * (a->end - a->start); new_value = new_value >> 10; new_value += a->start; - return (lv_anim_value_t)new_value; + return new_value; } /** @@ -277,20 +275,15 @@ lv_anim_value_t lv_anim_path_ease_out(const lv_anim_path_t * path, const lv_anim /*Calculate the current step*/ - uint32_t t; - if(a->time == a->act_time) - t = 1024; - else - t = (uint32_t)((uint32_t)a->act_time * 1024) / a->time; - + uint32_t t = _lv_map(a->act_time, 0, a->time, 0, 1024); int32_t step = _lv_bezier3(t, 0, 1023, 1023, 1024); int32_t new_value; - new_value = (int32_t)step * (a->end - a->start); + new_value = step * (a->end - a->start); new_value = new_value >> 10; new_value += a->start; - return (lv_anim_value_t)new_value; + return new_value; } /** @@ -304,20 +297,15 @@ lv_anim_value_t lv_anim_path_ease_in_out(const lv_anim_path_t * path, const lv_a /*Calculate the current step*/ - uint32_t t; - if(a->time == a->act_time) - t = 1024; - else - t = (uint32_t)((uint32_t)a->act_time * 1024) / a->time; - + uint32_t t = _lv_map(a->act_time, 0, a->time, 0, 1024); int32_t step = _lv_bezier3(t, 0, 100, 924, 1024); int32_t new_value; - new_value = (int32_t)step * (a->end - a->start); + new_value = step * (a->end - a->start); new_value = new_value >> 10; new_value += a->start; - return (lv_anim_value_t)new_value; + return new_value; } /** @@ -331,20 +319,15 @@ lv_anim_value_t lv_anim_path_overshoot(const lv_anim_path_t * path, const lv_ani /*Calculate the current step*/ - uint32_t t; - if(a->time == a->act_time) - t = 1024; - else - t = (uint32_t)((uint32_t)a->act_time * 1024) / a->time; - + uint32_t t = _lv_map(a->act_time, 0, a->time, 0, 1024); int32_t step = _lv_bezier3(t, 0, 1000, 1300, 1024); int32_t new_value; - new_value = (int32_t)step * (a->end - a->start); + new_value = step * (a->end - a->start); new_value = new_value >> 10; new_value += a->start; - return (lv_anim_value_t)new_value; + return new_value; } /** @@ -357,12 +340,8 @@ lv_anim_value_t lv_anim_path_bounce(const lv_anim_path_t * path, const lv_anim_t LV_UNUSED(path); /*Calculate the current step*/ - int32_t t; - if(a->time == a->act_time) - t = 1024; - else - t = (uint32_t)((uint32_t)a->act_time * 1024) / a->time; + uint32_t t = _lv_map(a->act_time, 0, a->time, 0, 1024); int32_t diff = (a->end - a->start); /*3 bounces has 5 parts: 3 down and 2 up. One part is t / 5 long*/ @@ -399,16 +378,16 @@ lv_anim_value_t lv_anim_path_bounce(const lv_anim_path_t * path, const lv_anim_t } if(t > 1024) t = 1024; - if(t < 0) t = 0; + int32_t step = _lv_bezier3(t, 1024, 800, 500, 0); int32_t new_value; - new_value = (int32_t)step * diff; + new_value = step * diff; new_value = new_value >> 10; new_value = a->end - new_value; - return (lv_anim_value_t)new_value; + return new_value; } /** @@ -439,14 +418,12 @@ static void anim_task(lv_task_t * param) { (void)param; - lv_anim_t * a; - _LV_LL_READ(LV_GC_ROOT(_lv_anim_ll), a) { - a->has_run = 0; - } - uint32_t elaps = lv_tick_elaps(last_task_run); - a = _lv_ll_get_head(&LV_GC_ROOT(_lv_anim_ll)); + /*Flip the run round*/ + anim_run_round = anim_run_round ? false : true; + + lv_anim_t * a = _lv_ll_get_head(&LV_GC_ROOT(_lv_anim_ll)); while(a != NULL) { /*It can be set by `lv_anim_del()` typically in `end_cb`. If set then an animation delete @@ -455,8 +432,8 @@ static void anim_task(lv_task_t * param) */ anim_list_changed = false; - if(!a->has_run) { - a->has_run = 1; /*The list readying might be reset so need to know which anim has run already*/ + if(a->run_round != anim_run_round) { + a->run_round = anim_run_round; /*The list readying might be reset so need to know which anim has run already*/ /*The animation will run now for the first time. Call `start_cb`*/ int32_t new_act_time = a->act_time + elaps; @@ -499,9 +476,8 @@ static void anim_task(lv_task_t * param) * Called when an animation is ready to do the necessary thinks * e.g. repeat, play back, delete etc. * @param a pointer to an animation descriptor - * @return true: animation delete occurred and the `LV_GC_ROOT(_lv_anim_ll)` has changed - * */ -static bool anim_ready_handler(lv_anim_t * a) + */ +static void anim_ready_handler(lv_anim_t * a) { /*In the end of a forward anim decrement repeat cnt.*/ if(a->playback_now == 0 && a->repeat_cnt > 0 && a->repeat_cnt != LV_ANIM_REPEAT_INFINITE) { @@ -544,8 +520,6 @@ static bool anim_ready_handler(lv_anim_t * a) a->time = a->playback_now == 0 ? a->time_orig : a->playback_time; } } - - return anim_list_changed; } static void anim_mark_list_change(void) { diff --git a/src/lv_misc/lv_anim.h b/src/lv_misc/lv_anim.h index 54baf59696..8d07057f4f 100644 --- a/src/lv_misc/lv_anim.h +++ b/src/lv_misc/lv_anim.h @@ -1,10 +1,10 @@ /** - * @file anim.h + * @file lv_anim.h * */ -#ifndef ANIM_H -#define ANIM_H +#ifndef LV_ANIM_H +#define LV_ANIM_H #ifdef __cplusplus extern "C" { @@ -74,28 +74,28 @@ typedef void (*lv_anim_start_cb_t)(struct _lv_anim_t *); /** Describes an animation*/ typedef struct _lv_anim_t { void * var; /**var = var; + a->var = var; } /** @@ -146,7 +146,7 @@ static inline void lv_anim_set_exec_cb(lv_anim_t * a, lv_anim_exec_xcb_t exec_cb */ static inline void lv_anim_set_time(lv_anim_t * a, uint32_t duration) { - a->time = duration; + a->time = duration; } /** @@ -169,7 +169,7 @@ static inline void lv_anim_set_values(lv_anim_t * a, lv_anim_value_t start, lv_a { a->start = start; a->current = start; - a->end = end; + a->end = end; } /** @@ -190,8 +190,8 @@ static inline void lv_anim_set_custom_exec_cb(lv_anim_t * a, lv_anim_custom_exec /** * Set the path (curve) of the animation. * @param a pointer to an initialized `lv_anim_t` variable - * @param path_cb a function the get the current value of the animation. - * The built in functions starts with `lv_anim_path_...` + * @param path a function the get the current value of the animation. + * The built in functions starts with `lv_anim_path_...` */ static inline void lv_anim_set_path(lv_anim_t * a, const lv_anim_path_t * path) { @@ -223,7 +223,7 @@ static inline void lv_anim_set_ready_cb(lv_anim_t * a, lv_anim_ready_cb_t ready_ * @param a pointer to an initialized `lv_anim_t` variable * @param time the duration of the playback animation in in milliseconds. 0: disable playback */ -static inline void lv_anim_set_playback_time(lv_anim_t * a, uint16_t time) +static inline void lv_anim_set_playback_time(lv_anim_t * a, uint32_t time) { a->playback_time = time; } @@ -233,7 +233,7 @@ static inline void lv_anim_set_playback_time(lv_anim_t * a, uint16_t time) * @param a pointer to an initialized `lv_anim_t` variable * @param delay delay in milliseconds before starting the playback animation. */ -static inline void lv_anim_set_playback_delay(lv_anim_t * a, uint16_t delay) +static inline void lv_anim_set_playback_delay(lv_anim_t * a, uint32_t delay) { a->playback_delay = delay; } @@ -245,7 +245,7 @@ static inline void lv_anim_set_playback_delay(lv_anim_t * a, uint16_t delay) */ static inline void lv_anim_set_repeat_count(lv_anim_t * a, uint16_t cnt) { - a->repeat_cnt = cnt; + a->repeat_cnt = cnt; } /** @@ -253,7 +253,7 @@ static inline void lv_anim_set_repeat_count(lv_anim_t * a, uint16_t cnt) * @param a pointer to an initialized `lv_anim_t` variable * @param delay delay in milliseconds before repeating the animation. */ -static inline void lv_anim_set_repeat_delay(lv_anim_t * a, uint16_t delay) +static inline void lv_anim_set_repeat_delay(lv_anim_t * a, uint32_t delay) { a->repeat_delay = delay; } @@ -298,7 +298,7 @@ static inline void lv_anim_path_set_user_data(lv_anim_path_t * path, void * user * @param a pointer to an initialized `lv_anim_t` variable * @return delay before the animation in milliseconds */ -static inline int32_t lv_anim_get_delay(lv_anim_t * a) +static inline uint32_t lv_anim_get_delay(lv_anim_t * a) { return -a->act_time; } @@ -312,6 +312,11 @@ static inline int32_t lv_anim_get_delay(lv_anim_t * a) */ bool lv_anim_del(void * var, lv_anim_exec_xcb_t exec_cb); +/** + * Delete all the animations animation + */ +void lv_anim_del_all(void); + /** * Get the animation of a variable and its `exec_cb`. * @param var pointer to variable @@ -350,7 +355,7 @@ uint16_t lv_anim_count_running(void); * @param end end value of the animation * @return the required time [ms] for the animation with the given parameters */ -uint16_t lv_anim_speed_to_time(uint16_t speed, lv_anim_value_t start, lv_anim_value_t end); +uint32_t lv_anim_speed_to_time(uint32_t speed, lv_anim_value_t start, lv_anim_value_t end); /** * Manually refresh the state of the animations. diff --git a/src/lv_misc/lv_math.c b/src/lv_misc/lv_math.c index 45b82cd50e..2ce7c4e3df 100644 --- a/src/lv_misc/lv_math.c +++ b/src/lv_misc/lv_math.c @@ -240,8 +240,8 @@ int64_t _lv_pow(int64_t base, int8_t exp) */ int32_t _lv_map(int32_t x, int32_t min_in, int32_t max_in, int32_t min_out, int32_t max_out) { - if(x <= min_in) return min_out; if(x >= max_in) return max_out; + if(x <= min_in) return min_out; /* The equation should be: * ((x - min_in) / delta in) * delta_out + min_out diff --git a/src/lv_misc/lv_mem.c b/src/lv_misc/lv_mem.c index 7a7f9e8c89..805bbfe5d7 100644 --- a/src/lv_misc/lv_mem.c +++ b/src/lv_misc/lv_mem.c @@ -10,6 +10,7 @@ #include "lv_mem.h" #include "lv_math.h" #include "lv_gc.h" +#include "lv_debug.h" #include #if LV_MEM_CUSTOM != 0 diff --git a/src/lv_misc/lv_txt.c b/src/lv_misc/lv_txt.c index e240485b30..201abaebd8 100644 --- a/src/lv_misc/lv_txt.c +++ b/src/lv_misc/lv_txt.c @@ -724,7 +724,7 @@ static uint32_t lv_txt_utf8_get_byte_id(const char * txt, uint32_t utf8_id) { uint32_t i; uint32_t byte_cnt = 0; - for(i = 0; i < utf8_id; i++) { + for(i = 0; i < utf8_id && txt[byte_cnt] != '\0'; i++) { uint8_t c_size = _lv_txt_encoded_size(&txt[byte_cnt]); byte_cnt += c_size > 0 ? c_size : 1; } diff --git a/src/lv_widgets/lv_bar.c b/src/lv_widgets/lv_bar.c index 1b18b54c29..0e1723dbca 100644 --- a/src/lv_widgets/lv_bar.c +++ b/src/lv_widgets/lv_bar.c @@ -419,8 +419,8 @@ static void draw_bg(lv_obj_t * bar, const lv_area_t * clip_area) /*value will be drawn later*/ draw_dsc.value_opa = LV_OPA_TRANSP; lv_obj_init_draw_rect_dsc(bar, LV_BAR_PART_BG, &draw_dsc); - lv_draw_rect(&bar->coords, clip_area, &draw_dsc); + lv_draw_rect(&bar->coords, clip_area, &draw_dsc); } static void draw_indic(lv_obj_t * bar, const lv_area_t * clip_area) @@ -531,17 +531,35 @@ static void draw_indic(lv_obj_t * bar, const lv_area_t * clip_area) *axis1 += anim_start_value_x; } else { - *axis1 = *axis2 - anim_cur_value_x; + *axis1 = *axis2 - anim_cur_value_x + 1; *axis2 -= anim_start_value_x; } if(sym) { - lv_coord_t zero; - zero = *axis1 + (-ext->min_value * anim_length) / range; - if(*axis2 > zero) - *axis1 = zero; + lv_coord_t zero, shift; + shift = (-ext->min_value * anim_length) / range; + if(hor) { + zero = *axis1 + shift; + if(*axis2 > zero) + *axis1 = zero; + else { + *axis1 = *axis2; + *axis2 = zero; + } + } else { - *axis1 = *axis2; - *axis2 = zero; + zero = *axis2 - shift + 1; + if(*axis1 > zero) + *axis2 = zero; + else { + *axis2 = *axis1; + *axis1 = zero; + } + if(*axis2 < *axis1) { + /* swap */ + zero = *axis1; + *axis1 = *axis2; + *axis2 = zero; + } } } @@ -576,11 +594,16 @@ static void draw_indic(lv_obj_t * bar, const lv_area_t * clip_area) draw_indic_dsc.border_opa = border_opa; draw_indic_dsc.value_opa = value_opa; draw_indic_dsc.pattern_image = pattern_src; - } lv_draw_mask_radius_param_t mask_bg_param; - lv_draw_mask_radius_init(&mask_bg_param, &bar->coords, bg_radius, false); + lv_area_t bg_mask_area; + bg_mask_area.x1 = bar->coords.x1 + bg_left; + bg_mask_area.x2 = bar->coords.x2 - bg_right; + bg_mask_area.y1 = bar->coords.y1 + bg_top; + bg_mask_area.y2 = bar->coords.y2 - bg_bottom; + + lv_draw_mask_radius_init(&mask_bg_param, &bg_mask_area, bg_radius, false); int16_t mask_bg_id = lv_draw_mask_add(&mask_bg_param, NULL); /*Draw_only the background and the pattern*/ @@ -665,6 +688,16 @@ static lv_res_t lv_bar_signal(lv_obj_t * bar, lv_signal_t sign, void * param) /*Bg size is handled by lv_obj*/ bar->ext_draw_pad = LV_MATH_MAX(bar->ext_draw_pad, indic_size); + /*Calculate the indicator area*/ + lv_style_int_t bg_left = lv_obj_get_style_pad_left(bar, LV_BAR_PART_BG); + lv_style_int_t bg_right = lv_obj_get_style_pad_right(bar, LV_BAR_PART_BG); + lv_style_int_t bg_top = lv_obj_get_style_pad_top(bar, LV_BAR_PART_BG); + lv_style_int_t bg_bottom = lv_obj_get_style_pad_bottom(bar, LV_BAR_PART_BG); + + lv_coord_t pad = LV_MATH_MIN4(bg_left, bg_right, bg_top, bg_bottom); + if(pad < 0) { + bar->ext_draw_pad = LV_MATH_MAX(bar->ext_draw_pad, -pad); + } } if(sign == LV_SIGNAL_CLEANUP) { lv_obj_clean_style_list(bar, LV_BAR_PART_INDIC); diff --git a/src/lv_widgets/lv_gauge.c b/src/lv_widgets/lv_gauge.c index 0aafc5fcd9..bba5266aed 100644 --- a/src/lv_widgets/lv_gauge.c +++ b/src/lv_widgets/lv_gauge.c @@ -197,9 +197,13 @@ void lv_gauge_set_value(lv_obj_t * gauge, uint8_t needle_id, int32_t value) int32_t old_value = ext->values[needle_id]; ext->values[needle_id] = value; - lv_coord_t r = lv_obj_get_width(gauge) / 2; - lv_coord_t x_ofs = gauge->coords.x1 + r; - lv_coord_t y_ofs = gauge->coords.y1 + r; + lv_style_int_t pad = lv_obj_get_style_pad_inner(gauge, LV_GAUGE_PART_NEEDLE); + lv_style_int_t left = lv_obj_get_style_pad_left(gauge, LV_GAUGE_PART_MAIN); + lv_style_int_t right = lv_obj_get_style_pad_right(gauge, LV_GAUGE_PART_MAIN); + lv_style_int_t top = lv_obj_get_style_pad_top(gauge, LV_GAUGE_PART_MAIN); + lv_coord_t r = (lv_obj_get_width(gauge) - left - right) / 2 - pad; + lv_coord_t x_ofs = gauge->coords.x1 + r + left + pad; + lv_coord_t y_ofs = gauge->coords.y1 + r + top + pad; uint16_t angle = lv_linemeter_get_scale_angle(gauge); int16_t angle_ofs = 90 + (360 - angle) / 2 + lv_gauge_get_angle_offset(gauge); lv_point_t p_mid; @@ -240,6 +244,33 @@ void lv_gauge_set_value(lv_obj_t * gauge, uint8_t needle_id, int32_t value) a.y2 = LV_MATH_MAX(p_mid.y, p_end.y) + needle_w; lv_obj_invalidate_area(gauge, &a); + /*The image might have long "end" on the opposite side ant it also needs to be invalidated*/ + if(ext->needle_img) { + needle_angle = (old_value - min) * angle / (max - min) + angle_ofs; + needle_angle += 180; + r = LV_MATH_MAX(ext->needle_img_pivot.x, ext->needle_img_pivot.y); + + p_end.y = (_lv_trigo_sin(needle_angle) * r) / LV_TRIGO_SIN_MAX + y_ofs; + p_end.x = (_lv_trigo_sin(needle_angle + 90) * r) / LV_TRIGO_SIN_MAX + x_ofs; + + a.x1 = LV_MATH_MIN(p_mid.x, p_end.x) - needle_w; + a.y1 = LV_MATH_MIN(p_mid.y, p_end.y) - needle_w; + a.x2 = LV_MATH_MAX(p_mid.x, p_end.x) + needle_w; + a.y2 = LV_MATH_MAX(p_mid.y, p_end.y) + needle_w; + lv_obj_invalidate_area(gauge, &a); + + needle_angle = (value - min) * angle / (max - min) + angle_ofs; + needle_angle += 180; + p_end.y = (_lv_trigo_sin(needle_angle) * r) / LV_TRIGO_SIN_MAX + y_ofs; + p_end.x = (_lv_trigo_sin(needle_angle + 90) * r) / LV_TRIGO_SIN_MAX + x_ofs; + + a.x1 = LV_MATH_MIN(p_mid.x, p_end.x) - needle_w; + a.y1 = LV_MATH_MIN(p_mid.y, p_end.y) - needle_w; + a.x2 = LV_MATH_MAX(p_mid.x, p_end.x) + needle_w; + a.y2 = LV_MATH_MAX(p_mid.y, p_end.y) + needle_w; + lv_obj_invalidate_area(gauge, &a); + } + } /** @@ -611,8 +642,8 @@ static void lv_gauge_draw_needle(lv_obj_t * gauge, const lv_area_t * clip_area) lv_img_decoder_get_info(ext->needle_img, &info); lv_area_t a; - a.x1 = gauge->coords.x1 + lv_area_get_width(&gauge->coords) / 2 - ext->needle_img_pivot.x; - a.y1 = gauge->coords.y1 + lv_area_get_height(&gauge->coords) / 2 - ext->needle_img_pivot.y; + a.x1 = x_ofs - ext->needle_img_pivot.x; + a.y1 = y_ofs - ext->needle_img_pivot.y; a.x2 = a.x1 + info.w - 1; a.y2 = a.y1 + info.h - 1; img_dsc.pivot.x = ext->needle_img_pivot.x; diff --git a/src/lv_widgets/lv_label.c b/src/lv_widgets/lv_label.c index 112143b88e..8c0a6c4b04 100644 --- a/src/lv_widgets/lv_label.c +++ b/src/lv_widgets/lv_label.c @@ -1,4 +1,4 @@ -/** +/** * @file lv_label.c * */ @@ -1034,7 +1034,26 @@ void lv_label_refr_text(lv_obj_t * label) bool hor_anim = false; if(size.x > lv_area_get_width(&txt_coords)) { +#if LV_USE_BIDI + lv_anim_value_t start, end; + lv_bidi_dir_t base_dir = lv_obj_get_base_dir(label); + + if(base_dir == LV_BIDI_DIR_AUTO) + base_dir = _lv_bidi_detect_base_dir(ext->text); + + if(base_dir == LV_BIDI_DIR_RTL) { + start = lv_area_get_width(&txt_coords) - size.x; + end = 0; + } + else { + start = 0; + end = lv_area_get_width(&txt_coords) - size.x; + } + + lv_anim_set_values(&a, start, end); +#else lv_anim_set_values(&a, 0, lv_area_get_width(&txt_coords) - size.x); +#endif lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t)lv_label_set_offset_x); lv_anim_set_time(&a, lv_anim_speed_to_time(ext->anim_speed, a.start, a.end)); lv_anim_set_playback_time(&a, a.time); @@ -1113,7 +1132,27 @@ void lv_label_refr_text(lv_obj_t * label) bool hor_anim = false; if(size.x > lv_area_get_width(&txt_coords)) { +#if LV_USE_BIDI + lv_anim_value_t start, end; + lv_bidi_dir_t base_dir = lv_obj_get_base_dir(label); + + if(base_dir == LV_BIDI_DIR_AUTO) + base_dir = _lv_bidi_detect_base_dir(ext->text); + + if(base_dir == LV_BIDI_DIR_RTL) { + start = -size.x - lv_font_get_glyph_width(font, ' ', ' ') * LV_LABEL_WAIT_CHAR_COUNT; + end = 0; + } + else { + start = 0; + end = -size.x - lv_font_get_glyph_width(font, ' ', ' ') * LV_LABEL_WAIT_CHAR_COUNT; + } + + lv_anim_set_values(&a, start, end); +#else lv_anim_set_values(&a, 0, -size.x - lv_font_get_glyph_width(font, ' ', ' ') * LV_LABEL_WAIT_CHAR_COUNT); +#endif + lv_anim_set_exec_cb(&a, (lv_anim_exec_xcb_t)lv_label_set_offset_x); lv_anim_set_time(&a, lv_anim_speed_to_time(ext->anim_speed, a.start, a.end)); @@ -1382,14 +1421,6 @@ static lv_res_t lv_label_signal(lv_obj_t * label, lv_signal_t sign, void * param if(ext->static_txt == 0) lv_label_set_text(label, NULL); #endif } - else if(sign == LV_SIGNAL_GET_TYPE) { - lv_obj_type_t * buf = param; - uint8_t i; - for(i = 0; i < LV_MAX_ANCESTOR_NUM - 1; i++) { /*Find the last set data*/ - if(buf->type[i] == NULL) break; - } - buf->type[i] = "lv_label"; - } return res; } diff --git a/src/lv_widgets/lv_label.h b/src/lv_widgets/lv_label.h index c4e4a02369..df7336763d 100644 --- a/src/lv_widgets/lv_label.h +++ b/src/lv_widgets/lv_label.h @@ -155,7 +155,7 @@ void lv_label_set_long_mode(lv_obj_t * label, lv_label_long_mode_t long_mode); /** * Set the align of the label (left or center) * @param label pointer to a label object - * @param align 'LV_LABEL_ALIGN_LEFT' or 'LV_LABEL_ALIGN_LEFT' + * @param align LV_LABEL_ALIGN_LEFT/RIGHT/CENTER */ void lv_label_set_align(lv_obj_t * label, lv_label_align_t align); @@ -207,7 +207,7 @@ lv_label_long_mode_t lv_label_get_long_mode(const lv_obj_t * label); /** * Get the align attribute * @param label pointer to a label object - * @return LV_LABEL_ALIGN_LEFT or LV_LABEL_ALIGN_CENTER + * @return LV_LABEL_ALIGN_LEFT/RIGHT/CENTER */ lv_label_align_t lv_label_get_align(const lv_obj_t * label); diff --git a/src/lv_widgets/lv_led.c b/src/lv_widgets/lv_led.c index dea778d7d7..1a16529a48 100644 --- a/src/lv_widgets/lv_led.c +++ b/src/lv_widgets/lv_led.c @@ -237,14 +237,7 @@ static lv_res_t lv_led_signal(lv_obj_t * led, lv_signal_t sign, void * param) res = ancestor_signal(led, sign, param); if(res != LV_RES_OK) return res; - if(sign == LV_SIGNAL_GET_TYPE) { - lv_obj_type_t * buf = param; - uint8_t i; - for(i = 0; i < LV_MAX_ANCESTOR_NUM - 1; i++) { /*Find the last set data*/ - if(buf->type[i] == NULL) break; - } - buf->type[i] = "lv_led"; - } + if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, LV_OBJX_NAME); return res; } diff --git a/src/lv_widgets/lv_list.c b/src/lv_widgets/lv_list.c index a80c454aba..8eff86ed78 100644 --- a/src/lv_widgets/lv_list.c +++ b/src/lv_widgets/lv_list.c @@ -293,7 +293,6 @@ void lv_list_focus_btn(lv_obj_t * list, lv_obj_t * btn) * It will be restored when the list is focused again.*/ if(btn) ext->last_sel_btn = btn; #endif - /*Focus the new button*/ ext->act_sel_btn = btn; @@ -741,7 +740,6 @@ static lv_res_t lv_list_signal(lv_obj_t * list, lv_signal_t sign, void * param) #endif } else if(sign == LV_SIGNAL_CONTROL) { - #if LV_USE_GROUP char c = *((char *)param); if(c == LV_KEY_RIGHT || c == LV_KEY_DOWN) { @@ -835,6 +833,12 @@ static lv_res_t lv_list_btn_signal(lv_obj_t * btn, lv_signal_t sign, void * para if(ext->last_sel_btn == btn) ext->last_sel_btn = NULL; #endif } + else if(sign == LV_SIGNAL_FOCUS) { +#if LV_USE_GROUP + lv_obj_t * list = lv_obj_get_parent(lv_obj_get_parent(btn)); + lv_list_focus_btn(list, btn); +#endif + } return res; } diff --git a/src/lv_widgets/lv_spinbox.c b/src/lv_widgets/lv_spinbox.c index ebeddcc354..10a16142d1 100644 --- a/src/lv_widgets/lv_spinbox.c +++ b/src/lv_widgets/lv_spinbox.c @@ -399,14 +399,6 @@ static lv_res_t lv_spinbox_signal(lv_obj_t * spinbox, lv_signal_t sign, void * p if(sign == LV_SIGNAL_CLEANUP) { /*Nothing to cleanup. (No dynamically allocated memory in 'ext')*/ } - else if(sign == LV_SIGNAL_GET_TYPE) { - lv_obj_type_t * buf = param; - uint8_t i; - for(i = 0; i < LV_MAX_ANCESTOR_NUM - 1; i++) { /*Find the last set data*/ - if(buf->type[i] == NULL) break; - } - buf->type[i] = "lv_spinbox"; - } else if(sign == LV_SIGNAL_RELEASED) { /*If released with an ENCODER then move to the next digit*/ lv_spinbox_ext_t * ext = lv_obj_get_ext_attr(spinbox);