diff --git a/src/lv_core/lv_group.c b/src/lv_core/lv_group.c index c3324ebf3..7aca33fcc 100644 --- a/src/lv_core/lv_group.c +++ b/src/lv_core/lv_group.c @@ -20,6 +20,7 @@ /********************* * DEFINES *********************/ +#define LV_GROUP_NUM ((1 << LV_GROUP_ID_MAX) - 1) /********************** * TYPEDEFS @@ -39,6 +40,7 @@ static void obj_to_foreground(lv_obj_t * obj); /********************** * STATIC VARIABLES **********************/ +static lv_group_t groups[LV_GROUP_NUM]; /********************** * MACROS @@ -53,57 +55,19 @@ static void obj_to_foreground(lv_obj_t * obj); */ void lv_group_init(void) { - lv_ll_init(&LV_GC_ROOT(_lv_group_ll), sizeof(lv_group_t)); -} + memset(groups, 0x00, sizeof(groups)); -/** - * Create a new object group - * @return pointer to the new object group - */ -lv_group_t * lv_group_create(void) -{ - lv_group_t * group = lv_ll_ins_head(&LV_GC_ROOT(_lv_group_ll)); - LV_ASSERT_MEM(group); - if(group == NULL) return NULL; - lv_ll_init(&group->obj_ll, sizeof(lv_obj_t *)); - - group->obj_focus = NULL; - group->frozen = 0; - group->focus_cb = NULL; - group->click_focus = 1; - group->editing = 0; - group->refocus_policy = LV_GROUP_REFOCUS_POLICY_PREV; - group->wrap = 1; - -#if LV_USE_USER_DATA - memset(&group->user_data, 0, sizeof(lv_group_user_data_t)); -#endif - - return group; -} - -/** - * Delete a group object - * @param group pointer to a group - */ -void lv_group_del(lv_group_t * group) -{ - /*Defocus the the currently focused object*/ - if(group->obj_focus != NULL) { - (*group->obj_focus)->signal_cb(*group->obj_focus, LV_SIGNAL_DEFOCUS, NULL); - lv_obj_invalidate(*group->obj_focus); + uint8_t i; + for(i = 0; i < LV_GROUP_NUM; i++) { + lv_ll_init(&groups[i].obj_ll, sizeof(lv_obj_t *)); + groups[i].obj_focus = NULL; + groups[i].frozen = 0; + groups[i].focus_cb = NULL; + groups[i].click_focus = 1; + groups[i].editing = 0; + groups[i].refocus_policy = LV_GROUP_REFOCUS_POLICY_PREV; + groups[i].wrap = 1; } - - /*Remove the objects from the group*/ - lv_obj_t ** obj; - LV_LL_READ(group->obj_ll, obj) - { - (*obj)->group_p = NULL; - } - - lv_ll_clear(&(group->obj_ll)); - lv_ll_remove(&LV_GC_ROOT(_lv_group_ll), group); - lv_mem_free(group); } /** diff --git a/src/lv_core/lv_group.h b/src/lv_core/lv_group.h index 19a8b4802..1ebe2e768 100644 --- a/src/lv_core/lv_group.h +++ b/src/lv_core/lv_group.h @@ -56,10 +56,7 @@ typedef struct _lv_group_t lv_ll_t obj_ll; /**< Linked list to store the objects in the group */ lv_obj_t ** obj_focus; /**< The object in focus*/ - lv_group_style_mod_cb_t style_mod_cb; /**< A function to modifies the style of the focused object*/ - lv_group_style_mod_cb_t style_mod_edit_cb; /**< A function which modifies the style of the edited object*/ lv_group_focus_cb_t focus_cb; /**< A function to call when a new object is focused (optional)*/ - lv_style_t style_tmp; /**< Stores the modified style of the focused object */ #if LV_USE_USER_DATA lv_group_user_data_t user_data; #endif diff --git a/src/lv_core/lv_indev.c b/src/lv_core/lv_indev.c index 8bf050d5f..d1171e900 100644 --- a/src/lv_core/lv_indev.c +++ b/src/lv_core/lv_indev.c @@ -773,7 +773,7 @@ static void indev_proc_press(lv_indev_proc_t * proc) proc->types.pointer.drag_in_prog = 0; proc->types.pointer.drag_sum.x = 0; proc->types.pointer.drag_sum.y = 0; - proc->types.pointer.drag_dir = LV_DRAG_DIR_NONE; + proc->types.pointer.drag_dir = LV_DRAG_DIR_BOTH; proc->types.pointer.vect.x = 0; proc->types.pointer.vect.y = 0; @@ -1016,7 +1016,7 @@ static void indev_proc_reset_query_handler(lv_indev_t * indev) indev->proc.longpr_rep_timestamp = 0; indev->proc.types.pointer.drag_sum.x = 0; indev->proc.types.pointer.drag_sum.y = 0; - indev->proc.types.pointer.drag_dir = LV_DRAG_DIR_NONE; + indev->proc.types.pointer.drag_dir = LV_DRAG_DIR_BOTH; indev->proc.types.pointer.drag_throw_vect.x = 0; indev->proc.types.pointer.drag_throw_vect.y = 0; indev->proc.reset_query = 0; diff --git a/src/lv_core/lv_obj.c b/src/lv_core/lv_obj.c index e18ddd2ea..7a7e5d288 100644 --- a/src/lv_core/lv_obj.c +++ b/src/lv_core/lv_obj.c @@ -129,6 +129,11 @@ void lv_init(void) } #if LV_ENABLE_GC || !LV_MEM_CUSTOM + +/** + * Deinit the 'lv' library + * Currently only implemented when not using custom allocators, or GC is enabled. + */ void lv_deinit(void) { lv_gc_clear_roots(); @@ -256,8 +261,6 @@ lv_obj_t * lv_obj_create(lv_obj_t * parent, const lv_obj_t * copy) new_obj->base_dir = LV_BIDI_DIR_LTR; #endif - new_obj->reserved = 0; - new_obj->ext_attr = NULL; lv_style_dsc_init(&new_obj->style_dsc); @@ -1241,22 +1244,16 @@ void lv_obj_refresh_style(lv_obj_t * obj, uint8_t part) */ void lv_obj_report_style_mod(lv_style_t * style) { -// LV_ASSERT_STYLE(style); -// -// lv_disp_t * d = lv_disp_get_next(NULL); -// -// while(d) { -// lv_obj_t * i; -// LV_LL_READ(d->scr_ll, i) -// { -// if(i->style_p == style || style == NULL) { -// lv_obj_refresh_style(i); -// } -// -// report_style_mod_core(style, i); -// } -// d = lv_disp_get_next(d); -// } + lv_disp_t * d = lv_disp_get_next(NULL); + + while(d) { + lv_obj_t * i; + LV_LL_READ(d->scr_ll, i) + { + report_style_mod_core(style, i); + } + d = lv_disp_get_next(d); + } } /*----------------- @@ -2895,6 +2892,25 @@ void lv_obj_init_draw_label_dsc(lv_obj_t * obj, uint8_t part, lv_draw_label_dsc_ } } +void lv_obj_init_draw_img_dsc(lv_obj_t * obj, uint8_t part, lv_draw_img_dsc_t * draw_dsc) +{ + draw_dsc->angle = 0; + draw_dsc->zoom = LV_IMG_ZOOM_NONE; + draw_dsc->pivot.x = lv_area_get_width(&obj->coords) / 2; + draw_dsc->pivot.y = lv_area_get_height(&obj->coords) / 2; + draw_dsc->opa = lv_obj_get_style_opa(obj, part, LV_STYLE_IMAGE_OPA); + if(draw_dsc->opa <= LV_OPA_MIN) return; + lv_opa_t opa_scale = lv_obj_get_style_opa(obj, part, LV_STYLE_OPA_SCALE); + if(opa_scale < LV_OPA_MAX) { + draw_dsc->opa = (uint16_t)((uint16_t)draw_dsc->opa * opa_scale) >> 8; + } + if(draw_dsc->opa <= LV_OPA_MIN) return; + + draw_dsc->overlay_opa = lv_obj_get_style_opa(obj, part, LV_STYLE_OVERLAY_OPA); + draw_dsc->overlay_color = lv_obj_get_style_color(obj, part, LV_STYLE_OVERLAY_COLOR); + draw_dsc->blend_mode = lv_obj_get_style_value(obj, part, LV_STYLE_IMAGE_BLEND_MODE); +} + /** * Handle the drawing related tasks of the base objects. * @param obj pointer to an object @@ -3000,7 +3016,9 @@ static lv_res_t lv_obj_signal(lv_obj_t * obj, lv_signal_t sign, void * param) if(shadow > obj->ext_draw_pad) obj->ext_draw_pad = shadow; } else if(sign == LV_SIGNAL_STYLE_CHG) { lv_obj_refresh_ext_draw_pad(obj); - } else if(sign == LV_SIGNAL_FOCUS) { + } +#if LV_USE_GROUP + else if(sign == LV_SIGNAL_FOCUS) { if(lv_group_get_editing(lv_obj_get_group(obj))) { uint8_t state = LV_OBJ_STATE_FOCUS; state |= LV_OBJ_STATE_EDIT; @@ -3011,6 +3029,7 @@ static lv_res_t lv_obj_signal(lv_obj_t * obj, lv_signal_t sign, void * param) } else if(sign == LV_SIGNAL_DEFOCUS) { lv_obj_clear_state(obj, LV_OBJ_STATE_FOCUS | LV_OBJ_STATE_EDIT); } +#endif return res; } @@ -3037,21 +3056,40 @@ static void refresh_children_position(lv_obj_t * obj, lv_coord_t x_diff, lv_coor /** * Refresh the style of all children of an object. (Called recursively) - * @param style_p refresh objects only with this style_dsc. + * @param style refresh objects only with this style_dsc. * @param obj pointer to an object */ -static void report_style_mod_core(void * style_p, lv_obj_t * obj) +static void report_style_mod_core(void * style, lv_obj_t * obj) { -// lv_obj_t * i; -// LV_LL_READ(obj->child_ll, i) -// { -// if(i->style.local == style_p || style_p == NULL) { -// refresh_children_style(i); -// lv_obj_refresh_style(i); -// } -// -// report_style_mod_core(style_p, i); -// } + uint8_t part_sub; + for(part_sub = 0; part_sub != LV_OBJ_PART_ALL; part_sub++) { + lv_style_dsc_t * dsc = lv_obj_get_style(obj, part_sub); + if(dsc == NULL) break; + + if(&dsc->local == style) { + lv_obj_refresh_style(obj, part_sub); + /* Two local style can't have the same pointer + * so there won't be an other match*/ + return; + } + + uint8_t ci; + for(ci = 0; ci < dsc->class_cnt; ci++) { + lv_style_t * class = lv_style_dsc_get_class(dsc, ci); + if(class == style) { + lv_obj_refresh_style(obj, part_sub); + /*It's enough to handle once (if duplicated)*/ + break; + } + } + } + + lv_obj_t * child = lv_obj_get_child(obj, NULL); + while(child) { + report_style_mod_core(style, child); + child = lv_obj_get_child(obj, child); + } + } /** diff --git a/src/lv_core/lv_obj.h b/src/lv_core/lv_obj.h index ef06b4d1d..4afdb1c08 100644 --- a/src/lv_core/lv_obj.h +++ b/src/lv_core/lv_obj.h @@ -225,37 +225,37 @@ typedef struct _lv_obj_t void * ext_attr; /**< Object type specific extended data*/ lv_style_dsc_t style_dsc; -#if LV_USE_GROUP != 0 - void * group_p; /**< Pointer to the group of the object*/ -#endif #if LV_USE_EXT_CLICK_AREA == LV_EXT_CLICK_AREA_TINY uint8_t ext_click_pad_hor; /**< Extra click padding in horizontal direction */ uint8_t ext_click_pad_ver; /**< Extra click padding in vertical direction */ -#endif - -#if LV_USE_EXT_CLICK_AREA == LV_EXT_CLICK_AREA_FULL +#elif LV_USE_EXT_CLICK_AREA == LV_EXT_CLICK_AREA_FULL lv_area_t ext_click_pad; /**< Extra click padding area. */ #endif - /*Attributes and states*/ - uint8_t click : 1; /**< 1: Can be pressed by an input device*/ - uint8_t drag : 1; /**< 1: Enable the dragging*/ - uint8_t drag_throw : 1; /**< 1: Enable throwing with drag*/ - uint8_t drag_parent : 1; /**< 1: Parent will be dragged instead*/ - uint8_t hidden : 1; /**< 1: Object is hidden*/ - uint8_t top : 1; /**< 1: If the object or its children is clicked it goes to the foreground*/ - uint8_t parent_event : 1; /**< 1: Send the object's events to the parent too. */ - lv_drag_dir_t drag_dir : 3; /**< Which directions the object can be dragged in */ - lv_bidi_dir_t base_dir : 2; /**< Base direction of texts related to this object */ - uint8_t adv_hittest : 1; /**< 1: Use advanced hit-testing (slower) */ - uint8_t reserved : 2; /**< Reserved for future use*/ - uint8_t protect; /**< Automatically happening actions can be prevented. 'OR'ed values from - `lv_protect_t`*/ - uint8_t state; - lv_coord_t ext_draw_pad; /**< EXTtend the size in every direction for drawing. */ + /*Attributes and states*/ + uint8_t click :1; /**< 1: Can be pressed by an input device*/ + uint8_t drag :1; /**< 1: Enable the dragging*/ + uint8_t drag_throw :1; /**< 1: Enable throwing with drag*/ + uint8_t drag_parent :1; /**< 1: Parent will be dragged instead*/ + uint8_t hidden :1; /**< 1: Object is hidden*/ + uint8_t top :1; /**< 1: If the object or its children is clicked it goes to the foreground*/ + uint8_t parent_event :1; /**< 1: Send the object's events to the parent too. */ + uint8_t adv_hittest :1; /**< 1: Use advanced hit-testing (slower) */ + + lv_drag_dir_t drag_dir :2; /**< Which directions the object can be dragged in */ + lv_bidi_dir_t base_dir :2; /**< Base direction of texts related to this object */ + +#if LV_USE_GROUP != 0 + uint8_t group_id :LV_GROUP_ID_MAX; +#endif + + uint8_t protect; /**< Automatically happening actions can be prevented. + 'OR'ed values from `lv_protect_t`*/ + uint8_t state; + #if LV_USE_OBJ_REALIGN lv_realign_t realign; /**< Information about the last call to ::lv_obj_align. */ #endif @@ -298,7 +298,7 @@ void lv_init(void); /** * Deinit the 'lv' library - * Currently only implemented when not using custorm allocators, or GC is enabled. + * Currently only implemented when not using custom allocators, or GC is enabled. */ #if LV_ENABLE_GC || !LV_MEM_CUSTOM void lv_deinit(void); @@ -1075,6 +1075,7 @@ void lv_obj_init_draw_rect_dsc(lv_obj_t * obj, uint8_t type, lv_draw_rect_dsc_t void lv_obj_init_draw_label_dsc(lv_obj_t * obj, uint8_t type, lv_draw_label_dsc_t * draw_dsc); +void lv_obj_init_draw_img_dsc(lv_obj_t * obj, uint8_t part, lv_draw_img_dsc_t * draw_dsc); /********************** * MACROS **********************/ diff --git a/src/lv_core/lv_style.c b/src/lv_core/lv_style.c index d9cde92e0..fa8ff3d3a 100644 --- a/src/lv_core/lv_style.c +++ b/src/lv_core/lv_style.c @@ -61,7 +61,14 @@ void lv_style_init(lv_style_t * style) { style->map = NULL; style->size = 0; - style->used_groups = 0; +} + +void lv_style_copy(lv_style_t * style_dest, const lv_style_t * style_src) +{ + lv_style_init(style_dest); + style_dest->map = lv_mem_alloc(style_src->size); + memcpy(style_dest->map, style_src->map, style_src->size); + style_dest->size = style_src->size; } void lv_style_dsc_init(lv_style_dsc_t * style_dsc) @@ -142,17 +149,6 @@ void lv_style_reset(lv_style_t * style) lv_mem_free(style->map); style->map = NULL; style->size = 0; - style->used_groups = 0; -} - -/** - * Copy a style to an other - * @param dest pointer to the destination style - * @param src pointer to the source style - */ -void lv_style_copy(lv_style_t * dest, const lv_style_t * src) -{ - memcpy(dest, src, sizeof(lv_style_t)); } void lv_style_set_value(lv_style_t * style, lv_style_property_t prop, lv_style_value_t value) @@ -180,10 +176,6 @@ void lv_style_set_value(lv_style_t * style, lv_style_property_t prop, lv_style_v memcpy(style->map + style->size - (sizeof(lv_style_property_t) + sizeof(lv_style_value_t)), &prop, sizeof(lv_style_property_t)); memcpy(style->map + style->size - sizeof(lv_style_value_t), &value, sizeof(lv_style_value_t)); - - /*Set that group is used this style*/ - uint16_t group = (prop >> 4) & 0xF; - style->used_groups |= 1 << group; } void lv_style_set_color(lv_style_t * style, lv_style_property_t prop, lv_color_t color) @@ -211,10 +203,6 @@ void lv_style_set_color(lv_style_t * style, lv_style_property_t prop, lv_color_t memcpy(style->map + style->size - (sizeof(lv_style_property_t) + sizeof(lv_color_t)), &prop, sizeof(lv_style_property_t)); memcpy(style->map + style->size - sizeof(lv_color_t), &color, sizeof(lv_color_t)); - - /*Set that group is used this style*/ - uint16_t group = (prop >> 4) & 0xF; - style->used_groups |= 1 << group; } void lv_style_set_opa(lv_style_t * style, lv_style_property_t prop, lv_opa_t opa) @@ -242,10 +230,6 @@ void lv_style_set_opa(lv_style_t * style, lv_style_property_t prop, lv_opa_t opa memcpy(style->map + style->size - (sizeof(lv_style_property_t) + sizeof(lv_opa_t)), &prop, sizeof(lv_style_property_t)); memcpy(style->map + style->size - sizeof(lv_opa_t), &opa, sizeof(lv_opa_t)); - - /*Set that group is used this style*/ - uint16_t group = (prop >> 4) & 0xF; - style->used_groups |= 1 << group; } void lv_style_set_ptr(lv_style_t * style, lv_style_property_t prop, void * p) @@ -273,10 +257,6 @@ void lv_style_set_ptr(lv_style_t * style, lv_style_property_t prop, void * p) memcpy(style->map + style->size - (sizeof(lv_style_property_t) + sizeof(void *)), &prop, sizeof(lv_style_property_t)); memcpy(style->map + style->size - sizeof(void *), &p, sizeof(void *)); - - /*Set that group is used this style*/ - uint16_t group = (prop >> 4) & 0xF; - style->used_groups |= 1 << group; } @@ -361,59 +341,6 @@ int16_t lv_style_get_ptr(const lv_style_t * style, lv_style_property_t prop, voi } } -/** - * Mix two styles according to a given ratio - * @param start start style - * @param end end style - * @param res store the result style here - * @param ratio the ratio of mix [0..256]; 0: `start` style; 256: `end` style - */ -void lv_style_mix(const lv_style_t * start, const lv_style_t * end, lv_style_t * res, uint16_t ratio) -{ -// STYLE_ATTR_MIX(body.opa, ratio); -// STYLE_ATTR_MIX(body.radius, ratio); -// STYLE_ATTR_MIX(body.border.width, ratio); -// STYLE_ATTR_MIX(body.border.opa, ratio); -// STYLE_ATTR_MIX(body.shadow.width, ratio); -// STYLE_ATTR_MIX(body.shadow.offset.x, ratio); -// STYLE_ATTR_MIX(body.shadow.offset.y, ratio); -// STYLE_ATTR_MIX(body.shadow.spread, ratio); -// STYLE_ATTR_MIX(body.padding.left, ratio); -// STYLE_ATTR_MIX(body.padding.right, ratio); -// STYLE_ATTR_MIX(body.padding.top, ratio); -// STYLE_ATTR_MIX(body.padding.bottom, ratio); -// STYLE_ATTR_MIX(body.padding.inner, ratio); -// STYLE_ATTR_MIX(text.line_space, ratio); -// STYLE_ATTR_MIX(text.letter_space, ratio); -// STYLE_ATTR_MIX(text.opa, ratio); -// STYLE_ATTR_MIX(line.width, ratio); -// STYLE_ATTR_MIX(line.opa, ratio); -// STYLE_ATTR_MIX(image.intense, ratio); -// STYLE_ATTR_MIX(image.opa, ratio); -// -// lv_opa_t opa = ratio == STYLE_MIX_MAX ? LV_OPA_COVER : ratio; -// -// res->body.main_color = lv_color_mix(end->body.main_color, start->body.main_color, opa); -// res->body.grad_color = lv_color_mix(end->body.grad_color, start->body.grad_color, opa); -// res->body.border.color = lv_color_mix(end->body.border.color, start->body.border.color, opa); -// res->body.shadow.color = lv_color_mix(end->body.shadow.color, start->body.shadow.color, opa); -// res->text.color = lv_color_mix(end->text.color, start->text.color, opa); -// res->image.color = lv_color_mix(end->image.color, start->image.color, opa); -// res->line.color = lv_color_mix(end->line.color, start->line.color, opa); -// -// if(ratio < (STYLE_MIX_MAX >> 1)) { -// res->body.border.part = start->body.border.part; -// res->glass = start->glass; -// res->text.font = start->text.font; -// res->line.rounded = start->line.rounded; -// } else { -// res->body.border.part = end->body.border.part; -// res->glass = end->glass; -// res->text.font = end->text.font; -// res->line.rounded = end->line.rounded; -// } -} - #if LV_USE_ANIMATION void lv_style_anim_init(lv_anim_t * a) @@ -426,25 +353,25 @@ void lv_style_anim_init(lv_anim_t * a) a->ready_cb = style_animation_common_end_cb; lv_style_anim_dsc_t * dsc; + dsc = lv_mem_alloc(sizeof(lv_style_anim_dsc_t)); LV_ASSERT_MEM(dsc); if(dsc == NULL) return; dsc->ready_cb = NULL; dsc->style_anim = NULL; - lv_style_copy(&dsc->style_start, &lv_style_plain); - lv_style_copy(&dsc->style_end, &lv_style_plain); + lv_style_init(&dsc->style_start); + lv_style_init(&dsc->style_end); a->var = (void *)dsc; } void lv_style_anim_set_styles(lv_anim_t * a, lv_style_t * to_anim, const lv_style_t * start, const lv_style_t * end) { - lv_style_anim_dsc_t * dsc = a->var; dsc->style_anim = to_anim; - memcpy(&dsc->style_start, start, sizeof(lv_style_t)); - memcpy(&dsc->style_end, end, sizeof(lv_style_t)); - memcpy(dsc->style_anim, start, sizeof(lv_style_t)); + + lv_style_copy(&dsc->style_start, start); + lv_style_copy(&dsc->style_end, end); } #endif /********************** @@ -453,40 +380,15 @@ void lv_style_anim_set_styles(lv_anim_t * a, lv_style_t * to_anim, const lv_styl static inline int32_t get_property_index(const lv_style_t * style, lv_style_property_t prop) { - static uint32_t stat[256]; - - - static uint32_t s = 0; - - uint8_t id_to_find = prop & 0xFF; lv_style_attr_t attr; attr.full = (prop >> 8) & 0xFF; - stat[id_to_find]++; - -// if(s > 1000) { -// printf("\n\n"); -// s = 0; -// uint32_t i; -// for(i = 0; i < 256; i++) { -// if(stat[i] == 0) continue; -// printf("%02x;%d;\n", i, stat[i]); -// } -// } - int16_t weight = -1; int16_t id_guess = -1; - - uint16_t group = (id_to_find >> 4) & 0xF; - if((style->used_groups & (1 << group)) == 0) return id_guess; - size_t i = 0; while(i < style->size) { -// s++; - -// printf("style search:%d\n", s); lv_style_attr_t attr_act; attr_act.full = style->map[i + 1]; if(style->map[i] == id_to_find) { @@ -519,6 +421,7 @@ static inline int32_t get_property_index(const lv_style_t * style, lv_style_prop } #if LV_USE_ANIMATION + /** * Used by the style animations to set the values of a style according to start and end style. * @param dsc the 'animated variable' set by lv_style_anim_create() @@ -530,7 +433,77 @@ static void style_animator(lv_style_anim_dsc_t * dsc, lv_anim_value_t val) const lv_style_t * end = &dsc->style_end; lv_style_t * act = dsc->style_anim; - lv_style_mix(start, end, act, val); + size_t i = 0; + lv_style_property_t prop_act; + while(i < start->size) { + prop_act = start->map[i] + (start->map[i + 1] << 8); + + /*Value*/ + if((start->map[i] & 0xF) < LV_STYLE_ID_COLOR) { + lv_style_value_t v1; + memcpy(&v1, &start->map[i + sizeof(lv_style_property_t)], sizeof(lv_style_value_t)); + + int16_t res2; + lv_style_value_t v2; + res2 = lv_style_get_value(end, prop_act, &v2); + + if(res2 >= 0) { + lv_style_value_t vres = v1 + ((int32_t)((int32_t)(v2-v1) * val) >> 8); + lv_style_set_value(act, prop_act, vres); + } + + i+= sizeof(lv_style_value_t); + } + /*Color*/ + else if((start->map[i] & 0xF) < LV_STYLE_ID_OPA) { + lv_color_t color1; + memcpy(&color1, &start->map[i + sizeof(lv_style_property_t)], sizeof(lv_color_t)); + + int16_t res2; + lv_color_t color2; + res2 = lv_style_get_color(end, prop_act, &color2); + + if(res2 >= 0) { + lv_color_t color_res = val == 256 ? color2 : lv_color_mix(color2, color1, (lv_opa_t)val); + lv_style_set_color(act, prop_act, color_res); + } + + i+= sizeof(lv_color_t); + } + /*Opa*/ + else if((start->map[i] & 0xF) < LV_STYLE_ID_PTR) { + lv_opa_t opa1; + memcpy(&opa1, &start->map[i + sizeof(lv_style_property_t)], sizeof(lv_opa_t)); + + int16_t res2; + lv_opa_t opa2; + res2 = lv_style_get_opa(end, prop_act, &opa2); + + if(res2 >= 0) { + lv_opa_t opa_res = opa1 + ((uint16_t)((uint16_t)(opa2 - opa1) * val) >> 8); + lv_style_set_opa(act, prop_act, opa_res); + } + + i+= sizeof(lv_opa_t); + } + else { + void * p1; + memcpy(p1, &start->map[i + sizeof(lv_style_property_t)], sizeof(void *)); + + int16_t res2; + void * p2; + res2 = lv_style_get_ptr(end, prop_act, &p2); + + if(res2 >= 0) { + if(val > 128) lv_style_set_ptr(act, prop_act, p2); + else if(val > 128) lv_style_set_ptr(act, prop_act, p1); + } + + i+= sizeof(void*); + } + + i += sizeof(lv_style_property_t); + } lv_obj_report_style_mod(dsc->style_anim); } diff --git a/src/lv_core/lv_style.h b/src/lv_core/lv_style.h index 3cf7b91af..47aac1f1d 100644 --- a/src/lv_core/lv_style.h +++ b/src/lv_core/lv_style.h @@ -150,9 +150,7 @@ typedef uint16_t lv_style_state_t; typedef struct { uint8_t * map; - uint16_t used_groups; uint16_t size :9; - uint16_t reserved :7; }lv_style_t; typedef int16_t lv_style_value_t; @@ -229,10 +227,11 @@ typedef struct { /** Data structure for style animations. */ typedef struct { - lv_style_t style_start; /*Save not only pointers because can be same as 'style_anim' then it - will be modified too*/ + lv_style_t style_start; /* Save not only pointers because can be same as 'style_anim' and + then it would be modified too*/ lv_style_t style_end; lv_style_t * style_anim; + lv_style_property_t * prop_list; lv_anim_ready_cb_t ready_cb; } lv_style_anim_dsc_t; #endif diff --git a/src/lv_draw/lv_draw_img.c b/src/lv_draw/lv_draw_img.c index ea54acd8f..dffb1c104 100644 --- a/src/lv_draw/lv_draw_img.c +++ b/src/lv_draw/lv_draw_img.c @@ -25,12 +25,12 @@ /********************** * STATIC PROTOTYPES **********************/ -static lv_res_t lv_img_draw_core(const lv_area_t * coords, const lv_area_t * mask, const void * src, - const lv_style_t * style, uint16_t angle, lv_point_t * pivot, uint16_t zoom, bool antialaias, lv_opa_t opa_scale); +static lv_res_t lv_img_draw_core(const lv_area_t * coords, const lv_area_t * mask, lv_draw_img_dsc_t * draw_dsc, const void * src); -static void lv_draw_map(const lv_area_t * map_area, const lv_area_t * clip_area, const uint8_t * map_p, lv_opa_t opa, - bool chroma_key, bool alpha_byte, const lv_style_t * style, uint16_t angle, lv_point_t * pivot, uint16_t zoom, bool antialaias); +static void lv_draw_map(const lv_area_t * map_area, const lv_area_t * clip_area, const uint8_t * map_p, lv_draw_img_dsc_t * draw_dsc, + bool chroma_key, bool alpha_byte); +void show_error(const lv_area_t * coords, const lv_area_t * clip_area, const char * msg); /********************** * STATIC VARIABLES **********************/ @@ -43,6 +43,15 @@ static void lv_draw_map(const lv_area_t * map_area, const lv_area_t * clip_area, * GLOBAL FUNCTIONS **********************/ +void lv_draw_img_dsc_init(lv_draw_img_dsc_t * dsc) +{ + memset(dsc, 0x00, sizeof(lv_draw_img_dsc_t)); + dsc->opa = LV_OPA_COVER; + dsc->zoom = LV_IMG_ZOOM_NONE; + dsc->antialias = LV_ANTIALIAS; + +} + /** * Draw an image * @param coords the coordinates of the image @@ -54,25 +63,22 @@ static void lv_draw_map(const lv_area_t * map_area, const lv_area_t * clip_area, * @param antialias anti-alias transformations (rotate, zoom) or not * @param opa_scale scale down all opacities by the factor */ -void lv_draw_img(const lv_area_t * coords, const lv_area_t * mask, const void * src, const lv_style_t * style, - uint16_t angle, lv_point_t * center, uint16_t zoom, bool antialias, lv_opa_t opa_scale) +void lv_draw_img(const lv_area_t * coords, const lv_area_t * mask, const void * src, lv_draw_img_dsc_t * dsc) { -// if(src == NULL) { -// LV_LOG_WARN("Image draw: src is NULL"); -// lv_draw_rect(coords, mask, &lv_style_plain, LV_OPA_COVER); -// lv_draw_label(coords, mask, &lv_style_plain, LV_OPA_COVER, "No\ndata", LV_TXT_FLAG_NONE, NULL, NULL, NULL, LV_BIDI_DIR_LTR); -// return; -// } -// -// lv_res_t res; -// res = lv_img_draw_core(coords, mask, src, style, angle, center, zoom, antialias, opa_scale); -// -// if(res == LV_RES_INV) { -// LV_LOG_WARN("Image draw error"); -// lv_draw_rect(coords, mask, &lv_style_plain, LV_OPA_COVER); -// lv_draw_label(coords, mask, &lv_style_plain, LV_OPA_COVER, "No\ndata", LV_TXT_FLAG_NONE, NULL, NULL, NULL, LV_BIDI_DIR_LTR); -// return; -// } + if(src == NULL) { + LV_LOG_WARN("Image draw: src is NULL"); + show_error(coords, mask, "No\ndata"); + return; + } + + lv_res_t res; + res = lv_img_draw_core(coords, mask, src, dsc); + + if(res == LV_RES_INV) { + LV_LOG_WARN("Image draw error"); + show_error(coords, mask, "No\ndata"); + return; + } } /** @@ -191,127 +197,124 @@ lv_img_src_t lv_img_src_get_type(const void * src) * STATIC FUNCTIONS **********************/ -static lv_res_t lv_img_draw_core(const lv_area_t * coords, const lv_area_t * mask, const void * src, - const lv_style_t * style, uint16_t angle, lv_point_t * pivot, uint16_t zoom, bool antialias, lv_opa_t opa_scale) +static lv_res_t lv_img_draw_core(const lv_area_t * coords, const lv_area_t * mask, lv_draw_img_dsc_t * draw_dsc, const void * src) { -// lv_opa_t opa = -// opa_scale == LV_OPA_COVER ? style->image.opa : (uint16_t)((uint16_t)style->image.opa * opa_scale) >> 8; -// -// lv_img_cache_entry_t * cdsc = lv_img_cache_open(src, style); -// -// if(cdsc == NULL) return LV_RES_INV; -// -// bool chroma_keyed = lv_img_cf_is_chroma_keyed(cdsc->dec_dsc.header.cf); -// bool alpha_byte = lv_img_cf_has_alpha(cdsc->dec_dsc.header.cf); -// -// if(cdsc->dec_dsc.error_msg != NULL) { -// LV_LOG_WARN("Image draw error"); -// lv_draw_rect(coords, mask, &lv_style_plain, LV_OPA_COVER); -// lv_draw_label(coords, mask, &lv_style_plain, LV_OPA_COVER, cdsc->dec_dsc.error_msg, LV_TXT_FLAG_NONE, NULL, NULL, NULL, LV_BIDI_DIR_LTR); -// } -// /* The decoder open could open the image and gave the entire uncompressed image. -// * Just draw it!*/ -// else if(cdsc->dec_dsc.img_data) { -// lv_area_t map_area_rot; -// lv_area_copy(&map_area_rot, coords); -// if(angle || zoom != LV_IMG_ZOOM_NONE) { -// /*Get the exact area which is required to show the rotated image*/ -// lv_coord_t pivot_x = lv_area_get_width(coords) / 2 + coords->x1; -// lv_coord_t pivot_y = lv_area_get_height(coords) / 2 + coords->y1; -// -// if (pivot){ -// pivot_x = pivot->x + coords->x1; -// pivot_y = pivot->y + coords->y1; -// } -// lv_coord_t w = lv_area_get_width(coords); -// lv_coord_t w_zoom = (((w * zoom) >> 8) - w) / 2; -// lv_coord_t h = lv_area_get_height(coords); -// lv_coord_t h_zoom = (((h * zoom) >> 8) - h) / 2; -// -// lv_area_t norm; -// norm.x1 = coords->x1 - pivot_x - w_zoom; -// norm.y1 = coords->y1 - pivot_y - h_zoom; -// norm.x2 = coords->x2 - pivot_x + w_zoom; -// norm.y2 = coords->y2 - pivot_y + h_zoom; -// -// int16_t sinma = lv_trigo_sin(angle); -// int16_t cosma = lv_trigo_sin(angle + 90); -// -// lv_point_t lt; -// lv_point_t rt; -// lv_point_t lb; -// lv_point_t rb; -// lt.x = ((cosma * norm.x1 - sinma * norm.y1) >> (LV_TRIGO_SHIFT)) + pivot_x; -// lt.y = ((sinma * norm.x1 + cosma * norm.y1) >> (LV_TRIGO_SHIFT)) + pivot_y; -// -// rt.x = ((cosma * norm.x2 - sinma * norm.y1) >> (LV_TRIGO_SHIFT)) + pivot_x; -// rt.y = ((sinma * norm.x2 + cosma * norm.y1) >> (LV_TRIGO_SHIFT)) + pivot_y; -// -// lb.x = ((cosma * norm.x1 - sinma * norm.y2) >> (LV_TRIGO_SHIFT)) + pivot_x; -// lb.y = ((sinma * norm.x1 + cosma * norm.y2) >> (LV_TRIGO_SHIFT)) + pivot_y; -// -// rb.x = ((cosma * norm.x2 - sinma * norm.y2) >> (LV_TRIGO_SHIFT)) + pivot_x; -// rb.y = ((sinma * norm.x2 + cosma * norm.y2) >> (LV_TRIGO_SHIFT)) + pivot_y; -// -// map_area_rot.x1 = LV_MATH_MIN(LV_MATH_MIN(LV_MATH_MIN(lb.x, lt.x), rb.x), rt.x); -// map_area_rot.x2 = LV_MATH_MAX(LV_MATH_MAX(LV_MATH_MAX(lb.x, lt.x), rb.x), rt.x); -// map_area_rot.y1 = LV_MATH_MIN(LV_MATH_MIN(LV_MATH_MIN(lb.y, lt.y), rb.y), rt.y); -// map_area_rot.y2 = LV_MATH_MAX(LV_MATH_MAX(LV_MATH_MAX(lb.y, lt.y), rb.y), rt.y); -// } -// -// lv_area_t mask_com; /*Common area of mask and coords*/ -// bool union_ok; -// union_ok = lv_area_intersect(&mask_com, mask, &map_area_rot); -// if(union_ok == false) { -// return LV_RES_OK; /*Out of mask. There is nothing to draw so the image is drawn -// successfully.*/ -// } -// -// lv_draw_map(coords, &mask_com, cdsc->dec_dsc.img_data, opa, chroma_keyed, alpha_byte, style, angle, pivot, zoom, antialias); -// } -// /* The whole uncompressed image is not available. Try to read it line-by-line*/ -// else { -// lv_area_t mask_com; /*Common area of mask and coords*/ -// bool union_ok; -// union_ok = lv_area_intersect(&mask_com, mask, coords); -// if(union_ok == false) { -// return LV_RES_OK; /*Out of mask. There is nothing to draw so the image is drawn -// successfully.*/ -// } -// -// lv_coord_t width = lv_area_get_width(&mask_com); -// -// uint8_t * buf = lv_mem_buf_get(lv_area_get_width(&mask_com) * LV_IMG_PX_SIZE_ALPHA_BYTE); /*+1 because of the possible alpha byte*/ -// -// lv_area_t line; -// lv_area_copy(&line, &mask_com); -// lv_area_set_height(&line, 1); -// lv_coord_t x = mask_com.x1 - coords->x1; -// lv_coord_t y = mask_com.y1 - coords->y1; -// lv_coord_t row; -// lv_res_t read_res; -// for(row = mask_com.y1; row <= mask_com.y2; row++) { -// lv_area_t mask_line; -// union_ok = lv_area_intersect(&mask_line, mask, &line); -// if(union_ok == false) continue; -// -// read_res = lv_img_decoder_read_line(&cdsc->dec_dsc, x, y, width, buf); -// if(read_res != LV_RES_OK) { -// lv_img_decoder_close(&cdsc->dec_dsc); -// LV_LOG_WARN("Image draw can't read the line"); -// lv_mem_buf_release(buf); -// return LV_RES_INV; -// } -// -// -// lv_draw_map(&line, &mask_line, buf, opa, chroma_keyed, alpha_byte, style, 0, NULL, LV_IMG_ZOOM_NONE, false); -// line.y1++; -// line.y2++; -// y++; -// } -// lv_mem_buf_release(buf); -// } -// + if(draw_dsc->opa <= LV_OPA_MIN) return LV_RES_OK; + + lv_img_cache_entry_t * cdsc = lv_img_cache_open(src, draw_dsc->overlay_color); + + if(cdsc == NULL) return LV_RES_INV; + + bool chroma_keyed = lv_img_cf_is_chroma_keyed(cdsc->dec_dsc.header.cf); + bool alpha_byte = lv_img_cf_has_alpha(cdsc->dec_dsc.header.cf); + + if(cdsc->dec_dsc.error_msg != NULL) { + LV_LOG_WARN("Image draw error"); + + show_error(coords, mask, cdsc->dec_dsc.error_msg); + } + /* The decoder open could open the image and gave the entire uncompressed image. + * Just draw it!*/ + else if(cdsc->dec_dsc.img_data) { + lv_area_t map_area_rot; + lv_area_copy(&map_area_rot, coords); + if(draw_dsc->angle || draw_dsc->zoom != LV_IMG_ZOOM_NONE) { + /*Get the exact area which is required to show the rotated image*/ + lv_coord_t pivot_x = lv_area_get_width(coords) / 2 + coords->x1; + lv_coord_t pivot_y = lv_area_get_height(coords) / 2 + coords->y1; + + pivot_x = draw_dsc->pivot.x + coords->x1; + pivot_y = draw_dsc->pivot.y + coords->y1; + + lv_coord_t w = lv_area_get_width(coords); + lv_coord_t w_zoom = (((w * draw_dsc->zoom) >> 8) - w) / 2; + lv_coord_t h = lv_area_get_height(coords); + lv_coord_t h_zoom = (((h * draw_dsc->zoom) >> 8) - h) / 2; + + lv_area_t norm; + norm.x1 = coords->x1 - pivot_x - w_zoom; + norm.y1 = coords->y1 - pivot_y - h_zoom; + norm.x2 = coords->x2 - pivot_x + w_zoom; + norm.y2 = coords->y2 - pivot_y + h_zoom; + + int16_t sinma = lv_trigo_sin(draw_dsc->angle); + int16_t cosma = lv_trigo_sin(draw_dsc->angle + 90); + + lv_point_t lt; + lv_point_t rt; + lv_point_t lb; + lv_point_t rb; + lt.x = ((cosma * norm.x1 - sinma * norm.y1) >> (LV_TRIGO_SHIFT)) + pivot_x; + lt.y = ((sinma * norm.x1 + cosma * norm.y1) >> (LV_TRIGO_SHIFT)) + pivot_y; + + rt.x = ((cosma * norm.x2 - sinma * norm.y1) >> (LV_TRIGO_SHIFT)) + pivot_x; + rt.y = ((sinma * norm.x2 + cosma * norm.y1) >> (LV_TRIGO_SHIFT)) + pivot_y; + + lb.x = ((cosma * norm.x1 - sinma * norm.y2) >> (LV_TRIGO_SHIFT)) + pivot_x; + lb.y = ((sinma * norm.x1 + cosma * norm.y2) >> (LV_TRIGO_SHIFT)) + pivot_y; + + rb.x = ((cosma * norm.x2 - sinma * norm.y2) >> (LV_TRIGO_SHIFT)) + pivot_x; + rb.y = ((sinma * norm.x2 + cosma * norm.y2) >> (LV_TRIGO_SHIFT)) + pivot_y; + + map_area_rot.x1 = LV_MATH_MIN(LV_MATH_MIN(LV_MATH_MIN(lb.x, lt.x), rb.x), rt.x); + map_area_rot.x2 = LV_MATH_MAX(LV_MATH_MAX(LV_MATH_MAX(lb.x, lt.x), rb.x), rt.x); + map_area_rot.y1 = LV_MATH_MIN(LV_MATH_MIN(LV_MATH_MIN(lb.y, lt.y), rb.y), rt.y); + map_area_rot.y2 = LV_MATH_MAX(LV_MATH_MAX(LV_MATH_MAX(lb.y, lt.y), rb.y), rt.y); + } + + lv_area_t mask_com; /*Common area of mask and coords*/ + bool union_ok; + union_ok = lv_area_intersect(&mask_com, mask, &map_area_rot); + if(union_ok == false) { + return LV_RES_OK; /*Out of mask. There is nothing to draw so the image is drawn + successfully.*/ + } + + lv_draw_map(coords, &mask_com, cdsc->dec_dsc.img_data, draw_dsc, chroma_keyed, alpha_byte); + } + /* The whole uncompressed image is not available. Try to read it line-by-line*/ + else { + lv_area_t mask_com; /*Common area of mask and coords*/ + bool union_ok; + union_ok = lv_area_intersect(&mask_com, mask, coords); + if(union_ok == false) { + return LV_RES_OK; /*Out of mask. There is nothing to draw so the image is drawn + successfully.*/ + } + + lv_coord_t width = lv_area_get_width(&mask_com); + + uint8_t * buf = lv_mem_buf_get(lv_area_get_width(&mask_com) * LV_IMG_PX_SIZE_ALPHA_BYTE); /*+1 because of the possible alpha byte*/ + + lv_area_t line; + lv_area_copy(&line, &mask_com); + lv_area_set_height(&line, 1); + lv_coord_t x = mask_com.x1 - coords->x1; + lv_coord_t y = mask_com.y1 - coords->y1; + lv_coord_t row; + lv_res_t read_res; + for(row = mask_com.y1; row <= mask_com.y2; row++) { + lv_area_t mask_line; + union_ok = lv_area_intersect(&mask_line, mask, &line); + if(union_ok == false) continue; + + read_res = lv_img_decoder_read_line(&cdsc->dec_dsc, x, y, width, buf); + if(read_res != LV_RES_OK) { + lv_img_decoder_close(&cdsc->dec_dsc); + LV_LOG_WARN("Image draw can't read the line"); + lv_mem_buf_release(buf); + return LV_RES_INV; + } + + + lv_draw_map(&line, &mask_line, buf, draw_dsc, chroma_keyed, alpha_byte); + line.y1++; + line.y2++; + y++; + } + lv_mem_buf_release(buf); + } + return LV_RES_OK; } @@ -329,190 +332,194 @@ static lv_res_t lv_img_draw_core(const lv_area_t * coords, const lv_area_t * mas * @param zoom zoom factor * @param antialias anti-alias transformations (rotate, zoom) or not */ -static void lv_draw_map(const lv_area_t * map_area, const lv_area_t * clip_area, const uint8_t * map_p, lv_opa_t opa, - bool chroma_key, bool alpha_byte, const lv_style_t * style, uint16_t angle, lv_point_t * pivot, uint16_t zoom, bool antialaias) +static void lv_draw_map(const lv_area_t * map_area, const lv_area_t * clip_area, const uint8_t * map_p, lv_draw_img_dsc_t * draw_dsc, bool chroma_key, bool alpha_byte) { -// -// if(opa < LV_OPA_MIN) return; -// if(opa > LV_OPA_MAX) opa = LV_OPA_COVER; -// -// /* Use the clip area as draw area*/ -// lv_area_t draw_area; -// lv_area_copy(&draw_area, clip_area); -// -// lv_disp_t * disp = lv_refr_get_disp_refreshing(); -// lv_disp_buf_t * vdb = lv_disp_get_buf(disp); -// const lv_area_t * disp_area = &vdb->area; -// -// /* Now `draw_area` has absolute coordinates. -// * Make it relative to `disp_area` to simplify draw to `disp_buf`*/ -// draw_area.x1 -= disp_area->x1; -// draw_area.y1 -= disp_area->y1; -// draw_area.x2 -= disp_area->x1; -// draw_area.y2 -= disp_area->y1; -// -// uint8_t other_mask_cnt = lv_draw_mask_get_cnt(); -// -// /*The simplest case just copy the pixels into the VDB*/ -// if(other_mask_cnt == 0 && angle == 0 && zoom == LV_IMG_ZOOM_NONE && -// chroma_key == false && alpha_byte == false && -// opa == LV_OPA_COVER && style->image.intense == LV_OPA_TRANSP) { -// lv_blend_map(clip_area, map_area, (lv_color_t *)map_p, NULL, LV_DRAW_MASK_RES_FULL_COVER, LV_OPA_COVER, style->image.blend_mode); -// } -// /*In the other cases every pixel need to be checked one-by-one*/ -// else { -// /*The pixel size in byte is different if an alpha byte is added too*/ -// uint8_t px_size_byte = alpha_byte ? LV_IMG_PX_SIZE_ALPHA_BYTE : sizeof(lv_color_t); -// -// /*Build the image and a mask line-by-line*/ -// uint32_t mask_buf_size = lv_area_get_size(&draw_area) > LV_HOR_RES_MAX ? LV_HOR_RES_MAX : lv_area_get_size(&draw_area); -// lv_color_t * map2 = lv_mem_buf_get(mask_buf_size * sizeof(lv_color_t)); -// lv_opa_t * mask_buf = lv_mem_buf_get(mask_buf_size); -// -// /*Go to the first displayed pixel of the map*/ -// lv_coord_t map_w = lv_area_get_width(map_area); -// lv_coord_t map_h = lv_area_get_height(map_area); -// const uint8_t * map_buf_tmp = map_p; -// map_buf_tmp += map_w * (draw_area.y1 - (map_area->y1 - disp_area->y1)) * px_size_byte; -// map_buf_tmp += (draw_area.x1 - (map_area->x1 - disp_area->x1)) * px_size_byte; -// -// lv_color_t c; -// lv_color_t chroma_keyed_color = LV_COLOR_TRANSP; -// uint32_t px_i = 0; -// uint32_t px_i_start; -// -// const uint8_t * map_px; -// -// lv_area_t blend_area; -// blend_area.x1 = draw_area.x1 + disp_area->x1; -// blend_area.x2 = blend_area.x1 + lv_area_get_width(&draw_area) - 1; -// blend_area.y1 = disp_area->y1 + draw_area.y1; -// blend_area.y2 = blend_area.y1; -// -// /*Prepare the `mask_buf`if there are other masks*/ -// if(other_mask_cnt) { -// memset(mask_buf, 0xFF, mask_buf_size); -// } -// -// -// bool transform = angle != 0 || zoom != LV_IMG_ZOOM_NONE ? true : false; -// lv_img_transform_dsc_t trans_dsc; -// memset(&trans_dsc, 0, sizeof(lv_img_transform_dsc_t)); -// if(transform) { -// lv_img_cf_t cf = LV_IMG_CF_TRUE_COLOR; -// if(alpha_byte) cf = LV_IMG_CF_TRUE_COLOR_ALPHA; -// else if(chroma_key) cf = LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED; -// -// -// trans_dsc.cfg.angle = angle; -// trans_dsc.cfg.zoom = zoom; -// trans_dsc.cfg.src = map_p; -// trans_dsc.cfg.src_w = map_w; -// trans_dsc.cfg.src_h = map_h; -// trans_dsc.cfg.cf = cf; -// trans_dsc.cfg.pivot_x = map_w / 2; -// trans_dsc.cfg.pivot_y = map_h / 2; -// if (pivot){ -// trans_dsc.cfg.pivot_x = pivot->x; -// trans_dsc.cfg.pivot_y = pivot->y; -// } -// trans_dsc.cfg.color = style->image.color; -// trans_dsc.cfg.antialias = antialaias; -// -// lv_img_buf_transform_init(&trans_dsc); -// } -// -// lv_draw_mask_res_t mask_res; -// mask_res = (alpha_byte || chroma_key || angle) ? LV_DRAW_MASK_RES_CHANGED : LV_DRAW_MASK_RES_FULL_COVER; -// lv_coord_t x; -// lv_coord_t y; -// for(y = 0; y < lv_area_get_height(&draw_area); y++) { -// map_px = map_buf_tmp; -// px_i_start = px_i; -// -// for(x = 0; x < lv_area_get_width(&draw_area); x++, map_px += px_size_byte, px_i++) { -// -// if(transform == false) { -// if(alpha_byte) { -// lv_opa_t px_opa = map_px[LV_IMG_PX_SIZE_ALPHA_BYTE - 1]; -// mask_buf[px_i] = px_opa; -// if(px_opa < LV_OPA_MIN) continue; -// } else { -// mask_buf[px_i] = LV_OPA_COVER; -// } -// -//#if LV_COLOR_DEPTH == 8 -// c.full = map_px[0]; -//#elif LV_COLOR_DEPTH == 16 -// c.full = map_px[0] + (map_px[1] << 8); -//#elif LV_COLOR_DEPTH == 32 -// c.full = *((uint32_t*)map_px); -//#endif -// if (chroma_key) { -// if(c.full == chroma_keyed_color.full) { -// mask_buf[px_i] = LV_OPA_TRANSP; -// continue; -// } -// } -// } else { -// /*Rotate*/ -// bool ret; -// lv_coord_t rot_x = x + (disp_area->x1 + draw_area.x1) - map_area->x1; -// lv_coord_t rot_y = y + (disp_area->y1 + draw_area.y1) - map_area->y1; -// ret = lv_img_buf_transform(&trans_dsc, rot_x, rot_y); -// if(ret == false) { -// mask_buf[px_i] = LV_OPA_TRANSP; -// continue; -// } else { -// mask_buf[px_i] = trans_dsc.res.opa; -// c.full = trans_dsc.res.color.full; -// } -// } -// -// if(style->image.intense != 0) { -// c = lv_color_mix(style->image.color, c, style->image.intense); -// } -// -// map2[px_i].full = c.full; -// } -// -// /*Apply the masks if any*/ -// if(other_mask_cnt) { -// lv_draw_mask_res_t mask_res_sub; -// mask_res_sub = lv_draw_mask_apply(mask_buf + px_i_start, draw_area.x1 + vdb->area.x1, y + draw_area.y1 + vdb->area.y1, lv_area_get_width(&draw_area)); -// if(mask_res_sub == LV_DRAW_MASK_RES_FULL_TRANSP) { -// memset(mask_buf + px_i_start, 0x00, lv_area_get_width(&draw_area)); -// mask_res = LV_DRAW_MASK_RES_CHANGED; -// } else if(mask_res_sub == LV_DRAW_MASK_RES_CHANGED) { -// mask_res = LV_DRAW_MASK_RES_CHANGED; -// } -// } -// -// map_buf_tmp += map_w * px_size_byte; -// if(px_i + lv_area_get_width(&draw_area) < mask_buf_size) { -// blend_area.y2 ++; -// } else { -// lv_blend_map(clip_area, &blend_area, map2, mask_buf, mask_res, opa, style->image.blend_mode); -// -// blend_area.y1 = blend_area.y2 + 1; -// blend_area.y2 = blend_area.y1; -// -// px_i = 0; -// mask_res = (alpha_byte || chroma_key || angle) ? LV_DRAW_MASK_RES_CHANGED : LV_DRAW_MASK_RES_FULL_COVER; -// -// /*Prepare the `mask_buf`if there are other masks*/ -// if(other_mask_cnt) { -// memset(mask_buf, 0xFF, mask_buf_size); -// } -// } -// } -// /*Flush the last part*/ -// if(blend_area.y1 != blend_area.y2) { -// blend_area.y2--; -// lv_blend_map(clip_area, &blend_area, map2, mask_buf, mask_res, opa, style->image.blend_mode); -// } -// -// lv_mem_buf_release(mask_buf); -// lv_mem_buf_release(map2); -// } + /* Use the clip area as draw area*/ + lv_area_t draw_area; + lv_area_copy(&draw_area, clip_area); + + lv_disp_t * disp = lv_refr_get_disp_refreshing(); + lv_disp_buf_t * vdb = lv_disp_get_buf(disp); + const lv_area_t * disp_area = &vdb->area; + + /* Now `draw_area` has absolute coordinates. + * Make it relative to `disp_area` to simplify draw to `disp_buf`*/ + draw_area.x1 -= disp_area->x1; + draw_area.y1 -= disp_area->y1; + draw_area.x2 -= disp_area->x1; + draw_area.y2 -= disp_area->y1; + + uint8_t other_mask_cnt = lv_draw_mask_get_cnt(); + + /*The simplest case just copy the pixels into the VDB*/ + if(other_mask_cnt == 0 && draw_dsc->angle == 0 && draw_dsc->zoom == LV_IMG_ZOOM_NONE && + chroma_key == false && alpha_byte == false && + draw_dsc->opa == LV_OPA_COVER && draw_dsc->overlay_opa == LV_OPA_TRANSP) { + lv_blend_map(clip_area, map_area, (lv_color_t *)map_p, NULL, LV_DRAW_MASK_RES_FULL_COVER, LV_OPA_COVER, draw_dsc->blend_mode); + } + /*In the other cases every pixel need to be checked one-by-one*/ + else { + /*The pixel size in byte is different if an alpha byte is added too*/ + uint8_t px_size_byte = alpha_byte ? LV_IMG_PX_SIZE_ALPHA_BYTE : sizeof(lv_color_t); + + /*Build the image and a mask line-by-line*/ + uint32_t mask_buf_size = lv_area_get_size(&draw_area) > LV_HOR_RES_MAX ? LV_HOR_RES_MAX : lv_area_get_size(&draw_area); + lv_color_t * map2 = lv_mem_buf_get(mask_buf_size * sizeof(lv_color_t)); + lv_opa_t * mask_buf = lv_mem_buf_get(mask_buf_size); + + /*Go to the first displayed pixel of the map*/ + lv_coord_t map_w = lv_area_get_width(map_area); + lv_coord_t map_h = lv_area_get_height(map_area); + const uint8_t * map_buf_tmp = map_p; + map_buf_tmp += map_w * (draw_area.y1 - (map_area->y1 - disp_area->y1)) * px_size_byte; + map_buf_tmp += (draw_area.x1 - (map_area->x1 - disp_area->x1)) * px_size_byte; + + lv_color_t c; + lv_color_t chroma_keyed_color = LV_COLOR_TRANSP; + uint32_t px_i = 0; + uint32_t px_i_start; + + const uint8_t * map_px; + + lv_area_t blend_area; + blend_area.x1 = draw_area.x1 + disp_area->x1; + blend_area.x2 = blend_area.x1 + lv_area_get_width(&draw_area) - 1; + blend_area.y1 = disp_area->y1 + draw_area.y1; + blend_area.y2 = blend_area.y1; + + /*Prepare the `mask_buf`if there are other masks*/ + if(other_mask_cnt) { + memset(mask_buf, 0xFF, mask_buf_size); + } + + + bool transform = draw_dsc->angle != 0 || draw_dsc->zoom != LV_IMG_ZOOM_NONE ? true : false; + lv_img_transform_dsc_t trans_dsc; + memset(&trans_dsc, 0, sizeof(lv_img_transform_dsc_t)); + if(transform) { + lv_img_cf_t cf = LV_IMG_CF_TRUE_COLOR; + if(alpha_byte) cf = LV_IMG_CF_TRUE_COLOR_ALPHA; + else if(chroma_key) cf = LV_IMG_CF_TRUE_COLOR_CHROMA_KEYED; + + + trans_dsc.cfg.angle = draw_dsc->angle; + trans_dsc.cfg.zoom = draw_dsc->zoom; + trans_dsc.cfg.src = map_p; + trans_dsc.cfg.src_w = map_w; + trans_dsc.cfg.src_h = map_h; + trans_dsc.cfg.cf = cf; + trans_dsc.cfg.pivot_x = draw_dsc->pivot.x; + trans_dsc.cfg.pivot_y = draw_dsc->pivot.y; + trans_dsc.cfg.color = draw_dsc->overlay_color; + trans_dsc.cfg.antialias = draw_dsc->antialias; + + lv_img_buf_transform_init(&trans_dsc); + } + + lv_draw_mask_res_t mask_res; + mask_res = (alpha_byte || chroma_key || draw_dsc->angle) ? LV_DRAW_MASK_RES_CHANGED : LV_DRAW_MASK_RES_FULL_COVER; + lv_coord_t x; + lv_coord_t y; + for(y = 0; y < lv_area_get_height(&draw_area); y++) { + map_px = map_buf_tmp; + px_i_start = px_i; + + for(x = 0; x < lv_area_get_width(&draw_area); x++, map_px += px_size_byte, px_i++) { + + if(transform == false) { + if(alpha_byte) { + lv_opa_t px_opa = map_px[LV_IMG_PX_SIZE_ALPHA_BYTE - 1]; + mask_buf[px_i] = px_opa; + if(px_opa < LV_OPA_MIN) continue; + } else { + mask_buf[px_i] = LV_OPA_COVER; + } + +#if LV_COLOR_DEPTH == 8 + c.full = map_px[0]; +#elif LV_COLOR_DEPTH == 16 + c.full = map_px[0] + (map_px[1] << 8); +#elif LV_COLOR_DEPTH == 32 + c.full = *((uint32_t*)map_px); +#endif + if (chroma_key) { + if(c.full == chroma_keyed_color.full) { + mask_buf[px_i] = LV_OPA_TRANSP; + continue; + } + } + } else { + /*Rotate*/ + bool ret; + lv_coord_t rot_x = x + (disp_area->x1 + draw_area.x1) - map_area->x1; + lv_coord_t rot_y = y + (disp_area->y1 + draw_area.y1) - map_area->y1; + ret = lv_img_buf_transform(&trans_dsc, rot_x, rot_y); + if(ret == false) { + mask_buf[px_i] = LV_OPA_TRANSP; + continue; + } else { + mask_buf[px_i] = trans_dsc.res.opa; + c.full = trans_dsc.res.color.full; + } + } + + if(draw_dsc->overlay_opa != 0) { + c = lv_color_mix(draw_dsc->overlay_color, c, draw_dsc->overlay_opa); + } + + map2[px_i].full = c.full; + } + + /*Apply the masks if any*/ + if(other_mask_cnt) { + lv_draw_mask_res_t mask_res_sub; + mask_res_sub = lv_draw_mask_apply(mask_buf + px_i_start, draw_area.x1 + vdb->area.x1, y + draw_area.y1 + vdb->area.y1, lv_area_get_width(&draw_area)); + if(mask_res_sub == LV_DRAW_MASK_RES_FULL_TRANSP) { + memset(mask_buf + px_i_start, 0x00, lv_area_get_width(&draw_area)); + mask_res = LV_DRAW_MASK_RES_CHANGED; + } else if(mask_res_sub == LV_DRAW_MASK_RES_CHANGED) { + mask_res = LV_DRAW_MASK_RES_CHANGED; + } + } + + map_buf_tmp += map_w * px_size_byte; + if(px_i + lv_area_get_width(&draw_area) < mask_buf_size) { + blend_area.y2 ++; + } else { + lv_blend_map(clip_area, &blend_area, map2, mask_buf, mask_res, draw_dsc->opa, draw_dsc->blend_mode); + + blend_area.y1 = blend_area.y2 + 1; + blend_area.y2 = blend_area.y1; + + px_i = 0; + mask_res = (alpha_byte || chroma_key || draw_dsc->angle) ? LV_DRAW_MASK_RES_CHANGED : LV_DRAW_MASK_RES_FULL_COVER; + + /*Prepare the `mask_buf`if there are other masks*/ + if(other_mask_cnt) { + memset(mask_buf, 0xFF, mask_buf_size); + } + } + } + /*Flush the last part*/ + if(blend_area.y1 != blend_area.y2) { + blend_area.y2--; + lv_blend_map(clip_area, &blend_area, map2, mask_buf, mask_res, draw_dsc->opa, draw_dsc->blend_mode); + } + + lv_mem_buf_release(mask_buf); + lv_mem_buf_release(map2); + } } + +void show_error(const lv_area_t * coords, const lv_area_t * clip_area, const char * msg) +{ + lv_draw_rect_dsc_t rect_dsc; + lv_draw_rect_dsc_init(&rect_dsc); + rect_dsc.bg_color = LV_COLOR_WHITE; + lv_draw_rect(coords, clip_area, &rect_dsc); + + lv_draw_label_dsc_t label_dsc; + lv_draw_label_dsc_init(&label_dsc); + lv_draw_label(coords, clip_area, &label_dsc, msg, NULL); +} + diff --git a/src/lv_draw/lv_draw_img.h b/src/lv_draw/lv_draw_img.h index 47d15132e..fc6a24d05 100644 --- a/src/lv_draw/lv_draw_img.h +++ b/src/lv_draw/lv_draw_img.h @@ -29,11 +29,26 @@ extern "C" { * TYPEDEFS **********************/ +typedef struct { + lv_opa_t opa; + + uint16_t angle; + lv_point_t pivot; + uint16_t zoom; + + lv_opa_t overlay_opa; + lv_color_t overlay_color; + + lv_blend_mode_t blend_mode; + + uint8_t antialias :1; +} lv_draw_img_dsc_t; /********************** * GLOBAL PROTOTYPES **********************/ +void lv_draw_img_dsc_init(lv_draw_img_dsc_t * dsc); /** * Draw an image * @param coords the coordinates of the image @@ -45,8 +60,7 @@ extern "C" { * @param antialias anti-alias transformations (rotate, zoom) or not * @param opa_scale scale down all opacities by the factor */ -void lv_draw_img(const lv_area_t * coords, const lv_area_t * mask, const void * src, const lv_style_t * style, - uint16_t angle, lv_point_t * center, uint16_t zoom, bool antialaias, lv_opa_t opa_scale); +void lv_draw_img(const lv_area_t * coords, const lv_area_t * mask, const void * src, lv_draw_img_dsc_t * dsc); /** * Get the type of an image source diff --git a/src/lv_hal/lv_hal_indev.h b/src/lv_hal/lv_hal_indev.h index 38b9b5214..b7f752d23 100644 --- a/src/lv_hal/lv_hal_indev.h +++ b/src/lv_hal/lv_hal_indev.h @@ -52,11 +52,10 @@ typedef uint8_t lv_indev_state_t; enum { - LV_DRAG_DIR_NONE = 0x0, /**< Both directions are disabled */ - LV_DRAG_DIR_HOR = 0x1, /**< Object can be dragged horizontally. */ - LV_DRAG_DIR_VER = 0x2, /**< Object can be dragged vertically. */ - LV_DRAG_DIR_BOTH = 0x3, /**< Object can be dragged in all directions. */ - LV_DRAG_DIR_ONE = 0x4, /**< Object can be dragged only one direction (the first move). */ + LV_DRAG_DIR_HOR = 0x0, /**< Object can be dragged horizontally. */ + LV_DRAG_DIR_VER = 0x1, /**< Object can be dragged vertically. */ + LV_DRAG_DIR_BOTH = 0x2, /**< Object can be dragged in all directions. */ + LV_DRAG_DIR_ONE = 0x3, /**< Object can be dragged only one direction (the first move). */ }; typedef uint8_t lv_drag_dir_t; diff --git a/src/lv_objx/lv_bar.c b/src/lv_objx/lv_bar.c index 7afdc9ec8..0281c455c 100644 --- a/src/lv_objx/lv_bar.c +++ b/src/lv_objx/lv_bar.c @@ -34,11 +34,10 @@ **********************/ static lv_design_res_t lv_bar_design(lv_obj_t * bar, const lv_area_t * clip_area, lv_design_mode_t mode); static lv_res_t lv_bar_signal(lv_obj_t * bar, lv_signal_t sign, void * param); +static lv_style_dsc_t * lv_bar_get_style(lv_obj_t * bar, uint8_t part); - -static void draw_bg(lv_obj_t * bar, const lv_area_t * clip_area, lv_design_mode_t mode, lv_opa_t opa); -static void draw_indic(lv_obj_t * bar, const lv_area_t * clip_area, lv_design_mode_t mode, lv_opa_t opa); - +static void draw_bg(lv_obj_t * bar, const lv_area_t * clip_area); +static void draw_indic(lv_obj_t * bar, const lv_area_t * clip_area); #if LV_USE_ANIMATION static void lv_bar_set_value_with_anim(lv_obj_t * bar, int16_t new_value, int16_t *value_ptr, lv_bar_anim_t *anim_info, lv_anim_enable_t en); @@ -97,24 +96,21 @@ lv_obj_t * lv_bar_create(lv_obj_t * par, const lv_obj_t * copy) lv_bar_init_anim(new_bar, &ext->start_value_anim); #endif ext->type = LV_BAR_TYPE_NORMAL; - ext->style_indic = &lv_style_pretty_color; + lv_style_dsc_init(&ext->style_indic); lv_obj_set_signal_cb(new_bar, lv_bar_signal); lv_obj_set_design_cb(new_bar, lv_bar_design); + /*Init the new bar object*/ if(copy == NULL) { lv_obj_set_click(new_bar, false); lv_obj_set_size(new_bar, LV_DPI * 2, LV_DPI / 4); lv_bar_set_value(new_bar, ext->cur_value, false); - lv_theme_t * th = lv_theme_get_current(); - if(th) { - lv_bar_set_style(new_bar, LV_BAR_STYLE_BG, th->style.bar.bg); - lv_bar_set_style(new_bar, LV_BAR_STYLE_INDIC, th->style.bar.indic); - } else { - lv_obj_set_style(new_bar, &lv_style_pretty); - } + _ot(new_bar, LV_BAR_PART_BG, BAR); + _ot(new_bar, LV_BAR_PART_INDIC, BAR_INDIC); + } else { lv_bar_ext_t * ext_copy = lv_obj_get_ext_attr(copy); ext->min_value = ext_copy->min_value; @@ -124,7 +120,7 @@ lv_obj_t * lv_bar_create(lv_obj_t * par, const lv_obj_t * copy) ext->style_indic = ext_copy->style_indic; ext->type = ext_copy->type; /*Refresh the style with new signal function*/ - lv_obj_refresh_style(new_bar); + lv_obj_refresh_style(new_bar, LV_OBJ_PART_ALL); lv_bar_set_value(new_bar, ext->cur_value, false); } @@ -254,27 +250,6 @@ void lv_bar_set_anim_time(lv_obj_t * bar, uint16_t anim_time) #endif } -/** - * Set a style of a bar - * @param bar pointer to a bar object - * @param type which style should be set - * @param style pointer to a style - */ -void lv_bar_set_style(lv_obj_t * bar, lv_bar_style_t type, const lv_style_t * style) -{ - LV_ASSERT_OBJ(bar, LV_OBJX_NAME); - - lv_bar_ext_t * ext = lv_obj_get_ext_attr(bar); - - switch(type) { - case LV_BAR_STYLE_BG: lv_obj_set_style(bar, style); break; - case LV_BAR_STYLE_INDIC: - ext->style_indic = style; - lv_obj_refresh_ext_draw_pad(bar); - break; - } -} - /*===================== * Getter functions *====================*/ @@ -374,27 +349,6 @@ uint16_t lv_bar_get_anim_time(const lv_obj_t * bar) #endif } -/** - * Get a style of a bar - * @param bar pointer to a bar object - * @param type which style should be get - * @return style pointer to a style - */ -const lv_style_t * lv_bar_get_style(const lv_obj_t * bar, lv_bar_style_t type) -{ - LV_ASSERT_OBJ(bar, LV_OBJX_NAME); - - const lv_style_t * style = NULL; - lv_bar_ext_t * ext = lv_obj_get_ext_attr(bar); - - switch(type) { - case LV_BAR_STYLE_BG: style = lv_obj_get_style(bar); break; - case LV_BAR_STYLE_INDIC: style = ext->style_indic; break; - default: style = NULL; break; - } - - return style; -} /********************** * STATIC FUNCTIONS @@ -416,22 +370,8 @@ static lv_design_res_t lv_bar_design(lv_obj_t * bar, const lv_area_t * clip_area /*Return false if the object is not covers the mask area*/ return ancestor_design_f(bar, clip_area, mode); } else if(mode == LV_DESIGN_DRAW_MAIN) { - lv_opa_t opa_scale = lv_obj_get_opa_scale(bar); - - draw_bg(bar, clip_area, mode, opa_scale); - draw_indic(bar, clip_area, mode, opa_scale); - -#if LV_USE_GROUP - /*Draw the border*/ - if(lv_obj_is_focused(bar)) { - const lv_style_t * style_bg = lv_bar_get_style(bar, LV_BAR_STYLE_BG); - lv_style_t style_tmp; - lv_style_copy(&style_tmp, style_bg); - style_tmp.body.opa = LV_OPA_TRANSP; - style_tmp.body.shadow.width = 0; - lv_draw_rect(&bar->coords, clip_area, &style_tmp, opa_scale); - } -#endif + draw_bg(bar, clip_area); + draw_indic(bar, clip_area); } else if(mode == LV_DESIGN_DRAW_POST) { @@ -439,32 +379,18 @@ static lv_design_res_t lv_bar_design(lv_obj_t * bar, const lv_area_t * clip_area return LV_DESIGN_RES_OK; } -static void draw_bg(lv_obj_t * bar, const lv_area_t * clip_area, lv_design_mode_t mode, lv_opa_t opa) +static void draw_bg(lv_obj_t * bar, const lv_area_t * clip_area) { + /*Simply draw the background*/ + lv_draw_rect_dsc_t draw_dsc; + lv_draw_rect_dsc_init(&draw_dsc); + lv_obj_init_draw_rect_dsc(bar, LV_BAR_PART_BG, &draw_dsc); + lv_draw_rect(&bar->coords, clip_area, &draw_dsc); - const lv_style_t * style_bg = lv_bar_get_style(bar, LV_BAR_STYLE_BG); -#if LV_USE_GROUP == 0 - /*Simply draw the background*/ - lv_draw_rect(&bar->coords, clip_area, style_bg, opa); -#else - /* Draw the borders later if the bar is focused. - * At value = 100% the indicator can cover to whole background and the focused style won't - * be visible*/ - if(lv_obj_is_focused(bar)) { - lv_style_t style_tmp; - lv_style_copy(&style_tmp, style_bg); - style_tmp.body.border.width = 0; - lv_draw_rect(&bar->coords, clip_area, &style_tmp, opa); - } else { - lv_draw_rect(&bar->coords, clip_area, style_bg, opa); - } -#endif } -static void draw_indic(lv_obj_t * bar, const lv_area_t * clip_area, lv_design_mode_t mode, lv_opa_t opa) +static void draw_indic(lv_obj_t * bar, const lv_area_t * clip_area) { - (void) mode; /*Unused*/ - lv_bar_ext_t * ext = lv_obj_get_ext_attr(bar); lv_coord_t objw = lv_obj_get_width(bar); @@ -484,15 +410,17 @@ static void draw_indic(lv_obj_t * bar, const lv_area_t * clip_area, lv_design_mo #endif /*Calculate the indicator area*/ - lv_area_copy(&ext->indic_area, &bar->coords); - const lv_style_t * style_indic = lv_bar_get_style(bar, LV_BAR_STYLE_INDIC); - const lv_style_t * style_bg = lv_bar_get_style(bar, LV_BAR_STYLE_BG); + lv_style_value_t bg_left = lv_obj_get_style_value(bar, LV_BAR_PART_BG, LV_STYLE_PAD_LEFT); + lv_style_value_t bg_right = lv_obj_get_style_value(bar, LV_BAR_PART_BG, LV_STYLE_PAD_RIGHT); + lv_style_value_t bg_top = lv_obj_get_style_value(bar, LV_BAR_PART_BG, LV_STYLE_PAD_TOP); + lv_style_value_t bg_bottom = lv_obj_get_style_value(bar, LV_BAR_PART_BG, LV_STYLE_PAD_BOTTOM); /*Respect padding and minimum width/height too*/ - ext->indic_area.x1 += style_indic->body.padding.left; - ext->indic_area.x2 -= style_indic->body.padding.right; - ext->indic_area.y1 += style_indic->body.padding.top; - ext->indic_area.y2 -= style_indic->body.padding.bottom; + lv_area_copy(&ext->indic_area, &bar->coords); + ext->indic_area.x1 += bg_left; + ext->indic_area.x2 -= bg_right; + ext->indic_area.y1 += bg_top; + ext->indic_area.y2 -= bg_bottom; if(hor && lv_area_get_height(&ext->indic_area) < LV_BAR_SIZE_MIN) { ext->indic_area.y1 = bar->coords.y1 + (objh / 2) - (LV_BAR_SIZE_MIN / 2); @@ -570,46 +498,59 @@ static void draw_indic(lv_obj_t * bar, const lv_area_t * clip_area, lv_design_mo /*Do not draw a zero length indicator*/ if(!sym && indic_length == 0) return; - lv_style_t style_indic_tmp; - lv_style_copy(&style_indic_tmp, style_indic); - uint16_t bg_radius = style_bg->body.radius; + uint16_t bg_radius = lv_obj_get_style_value(bar, LV_BAR_PART_BG, LV_STYLE_RADIUS); lv_coord_t short_side = LV_MATH_MIN(objw, objh); if(bg_radius > short_side >> 1) bg_radius = short_side >> 1; - /*Draw only the shadow*/ + + lv_draw_rect_dsc_t draw_indic_dsc; + lv_draw_rect_dsc_init(&draw_indic_dsc); + lv_obj_init_draw_rect_dsc(bar, LV_BAR_PART_INDIC, &draw_indic_dsc); + + /* Draw only the shadow if the indicator is long enough. + * The radius of the bg and the indicator can make a strange shape where + * it'd be very difficult to draw shadow. */ if((hor && lv_area_get_width(&ext->indic_area) > bg_radius * 2) || (!hor && lv_area_get_height(&ext->indic_area) > bg_radius * 2)) { - style_indic_tmp.body.opa = LV_OPA_TRANSP; - style_indic_tmp.body.border.width = 0; - lv_draw_rect(&ext->indic_area, clip_area, &style_indic_tmp, opa); + lv_opa_t bg_opa = draw_indic_dsc.bg_opa; + lv_opa_t border_opa = draw_indic_dsc.border_opa; + draw_indic_dsc.bg_opa = LV_OPA_TRANSP; + draw_indic_dsc.border_opa = LV_OPA_TRANSP; + lv_draw_rect(&ext->indic_area, clip_area, &draw_indic_dsc); + draw_indic_dsc.bg_opa = bg_opa; + draw_indic_dsc.border_opa = border_opa; } - lv_draw_mask_radius_param_t mask_bg_param; - lv_draw_mask_radius_init(&mask_bg_param, &bar->coords, style_bg->body.radius, false); + lv_draw_mask_radius_init(&mask_bg_param, &bar->coords, bg_radius, false); int16_t mask_bg_id = lv_draw_mask_add(&mask_bg_param, NULL); /*Draw_only the background*/ - style_indic_tmp.body.shadow.width = 0; - style_indic_tmp.body.opa = style_indic->body.opa; + lv_opa_t shadow_opa = draw_indic_dsc.shadow_opa; + lv_opa_t border_opa = draw_indic_dsc.border_opa; + draw_indic_dsc.border_opa = LV_OPA_TRANSP; + draw_indic_dsc.shadow_opa = LV_OPA_TRANSP; /*Get the max possible indicator area. The gradient should be applied on this*/ lv_area_t mask_indic_max_area; lv_area_copy(&mask_indic_max_area, &bar->coords); - mask_indic_max_area.x1 += style_indic->body.padding.left; - mask_indic_max_area.y1 += style_indic->body.padding.top; - mask_indic_max_area.x2 -= style_indic->body.padding.right; - mask_indic_max_area.y2 -= style_indic->body.padding.bottom; + mask_indic_max_area.x1 += bg_left; + mask_indic_max_area.y1 += bg_top; + mask_indic_max_area.x2 -= bg_right; + mask_indic_max_area.y2 -= bg_bottom; /*Create a mask to the current indicator area to see only this part from the whole gradient.*/ lv_draw_mask_radius_param_t mask_indic_param; - lv_draw_mask_radius_init(&mask_indic_param, &ext->indic_area, style_indic->body.radius, false); + lv_draw_mask_radius_init(&mask_indic_param, &ext->indic_area, draw_indic_dsc.radius, false); int16_t mask_indic_id = lv_draw_mask_add(&mask_indic_param, NULL); - lv_draw_rect(&mask_indic_max_area, clip_area, &style_indic_tmp, opa); + + lv_draw_rect(&mask_indic_max_area, clip_area, &draw_indic_dsc); + draw_indic_dsc.border_opa = border_opa; + draw_indic_dsc.shadow_opa = shadow_opa; /*Draw the border*/ - style_indic_tmp.body.border.width = style_indic->body.border.width; - style_indic_tmp.body.opa = LV_OPA_TRANSP; - lv_draw_rect(&ext->indic_area, clip_area, &style_indic_tmp, opa); + draw_indic_dsc.bg_opa = LV_OPA_TRANSP; + draw_indic_dsc.shadow_opa = LV_OPA_TRANSP; + lv_draw_rect(&ext->indic_area, clip_area, &draw_indic_dsc); lv_draw_mask_remove_id(mask_indic_id); lv_draw_mask_remove_id(mask_bg_id); @@ -627,25 +568,40 @@ static lv_res_t lv_bar_signal(lv_obj_t * bar, lv_signal_t sign, void * param) { lv_res_t res; + if(sign == LV_SIGNAL_GET_STYLE) { + uint8_t ** type_p = param; + lv_style_dsc_t ** style_dsc_p = param; + *style_dsc_p = lv_bar_get_style(bar, **type_p); + return LV_RES_OK; + } + /* Include the ancient signal function */ res = ancestor_signal(bar, sign, param); if(res != LV_RES_OK) return res; if(sign == LV_SIGNAL_GET_TYPE) return lv_obj_handle_get_type_signal(param, LV_OBJX_NAME); if(sign == LV_SIGNAL_REFR_EXT_DRAW_PAD) { - const lv_style_t * style_indic = lv_bar_get_style(bar, LV_BAR_STYLE_INDIC); - const lv_style_t * style_bg = lv_bar_get_style(bar, LV_BAR_STYLE_BG); + lv_style_value_t bg_sh_width = lv_obj_get_style_value(bar, LV_BAR_PART_BG, LV_STYLE_SHADOW_WIDTH); + lv_style_value_t bg_sh_spread = lv_obj_get_style_value(bar, LV_BAR_PART_BG, LV_STYLE_SHADOW_SPREAD); + lv_style_value_t bg_sh_ofs_x = lv_obj_get_style_value(bar, LV_BAR_PART_BG, LV_STYLE_SHADOW_OFFSET_X); + lv_style_value_t bg_sh_ofs_y = lv_obj_get_style_value(bar, LV_BAR_PART_BG, LV_STYLE_SHADOW_OFFSET_Y); - lv_coord_t bg_size = style_bg->body.shadow.width + style_bg->body.shadow.spread; - bg_size += LV_MATH_MAX(LV_MATH_ABS(style_bg->body.shadow.offset.x), LV_MATH_ABS(style_bg->body.shadow.offset.y)); + lv_coord_t bg_size = bg_sh_width + bg_sh_spread; + bg_size += LV_MATH_MAX(LV_MATH_ABS(bg_sh_ofs_x), LV_MATH_ABS(bg_sh_ofs_y)); - lv_coord_t indic_size = style_indic->body.shadow.width + style_indic->body.shadow.spread; - indic_size += LV_MATH_MAX(LV_MATH_ABS(style_indic->body.shadow.offset.x), LV_MATH_ABS(style_indic->body.shadow.offset.y)); + + lv_style_value_t indic_sh_width = lv_obj_get_style_value(bar, LV_BAR_PART_INDIC, LV_STYLE_SHADOW_WIDTH); + lv_style_value_t indic_sh_spread = lv_obj_get_style_value(bar, LV_BAR_PART_INDIC, LV_STYLE_SHADOW_SPREAD); + lv_style_value_t indic_sh_ofs_x = lv_obj_get_style_value(bar, LV_BAR_PART_INDIC, LV_STYLE_SHADOW_OFFSET_X); + lv_style_value_t indic_sh_ofs_y = lv_obj_get_style_value(bar, LV_BAR_PART_INDIC, LV_STYLE_SHADOW_OFFSET_Y); + + + lv_coord_t indic_size = indic_sh_width + indic_sh_spread; + indic_size += LV_MATH_MAX(LV_MATH_ABS(indic_sh_ofs_x), LV_MATH_ABS(indic_sh_ofs_y)); bar->ext_draw_pad = LV_MATH_MAX(bar->ext_draw_pad, bg_size); bar->ext_draw_pad = LV_MATH_MAX(bar->ext_draw_pad, indic_size); - if(style_indic->body.shadow.width > bar->ext_draw_pad) bar->ext_draw_pad = style_indic->body.shadow.width; } if(sign == LV_SIGNAL_CLEANUP) { @@ -659,6 +615,27 @@ static lv_res_t lv_bar_signal(lv_obj_t * bar, lv_signal_t sign, void * param) return res; } +static lv_style_dsc_t * lv_bar_get_style(lv_obj_t * bar, uint8_t part) +{ + LV_ASSERT_OBJ(bar, LV_OBJX_NAME); + + lv_bar_ext_t * ext = lv_obj_get_ext_attr(bar); + lv_style_dsc_t * style_dsc_p; + + switch(part) { + case LV_BAR_PART_BG: + style_dsc_p = &bar->style_dsc; + break; + case LV_BAR_PART_INDIC: + style_dsc_p = &ext->style_indic; + break; + default: + style_dsc_p = NULL; + } + + return style_dsc_p; +} + #if LV_USE_ANIMATION static void lv_bar_anim(lv_bar_anim_t * var, lv_anim_value_t value) { diff --git a/src/lv_objx/lv_bar.h b/src/lv_objx/lv_bar.h index d0b02e2c0..79dfeb9af 100644 --- a/src/lv_objx/lv_bar.h +++ b/src/lv_objx/lv_bar.h @@ -65,15 +65,15 @@ typedef struct lv_bar_anim_t start_value_anim; #endif uint8_t type : 2; /*Type of bar*/ - const lv_style_t * style_indic; /*Style of the indicator*/ + lv_style_dsc_t style_indic; /*Style of the indicator*/ } lv_bar_ext_t; -/** Bar styles. */ +/** Bar parts */ enum { - LV_BAR_STYLE_BG, /** Bar background style. */ - LV_BAR_STYLE_INDIC, /** Bar fill area style. */ + LV_BAR_PART_BG, /** Bar background style. */ + LV_BAR_PART_INDIC, /** Bar fill area style. */ }; -typedef uint8_t lv_bar_style_t; +typedef uint8_t lv_bar_part_t; /********************** * GLOBAL PROTOTYPES @@ -129,14 +129,6 @@ void lv_bar_set_type(lv_obj_t * bar, lv_bar_type_t type); */ void lv_bar_set_anim_time(lv_obj_t * bar, uint16_t anim_time); -/** - * Set a style of a bar - * @param bar pointer to a bar object - * @param type which style should be set - * @param style pointer to a style - */ -void lv_bar_set_style(lv_obj_t * bar, lv_bar_style_t type, const lv_style_t * style); - /*===================== * Getter functions *====================*/ @@ -183,14 +175,6 @@ lv_bar_type_t lv_bar_get_type(lv_obj_t * bar); */ uint16_t lv_bar_get_anim_time(const lv_obj_t * bar); -/** - * Get a style of a bar - * @param bar pointer to a bar object - * @param type which style should be get - * @return style pointer to a style - */ -const lv_style_t * lv_bar_get_style(const lv_obj_t * bar, lv_bar_style_t type); - /********************** * MACROS **********************/ diff --git a/src/lv_objx/lv_btnm.c b/src/lv_objx/lv_btnm.c index aa4114f03..1bbde50b0 100644 --- a/src/lv_objx/lv_btnm.c +++ b/src/lv_objx/lv_btnm.c @@ -30,7 +30,7 @@ **********************/ static lv_res_t lv_btnm_signal(lv_obj_t * btnm, lv_signal_t sign, void * param); static lv_design_res_t lv_btnm_design(lv_obj_t * btnm, const lv_area_t * clip_area, lv_design_mode_t mode); -static lv_style_dsc_t * lv_btnm_get_style(lv_obj_t * btnm, uint8_t type); +static lv_style_dsc_t * lv_btnm_get_style(lv_obj_t * btnm, uint8_t part); static uint8_t get_button_width(lv_btnm_ctrl_t ctrl_bits); static bool button_is_hidden(lv_btnm_ctrl_t ctrl_bits); @@ -953,7 +953,7 @@ static lv_res_t lv_btnm_signal(lv_obj_t * btnm, lv_signal_t sign, void * param) return res; } -static lv_style_dsc_t * lv_btnm_get_style(lv_obj_t * btnm, uint8_t type) +static lv_style_dsc_t * lv_btnm_get_style(lv_obj_t * btnm, uint8_t part) { LV_ASSERT_OBJ(btnm, LV_OBJX_NAME); @@ -961,7 +961,7 @@ static lv_style_dsc_t * lv_btnm_get_style(lv_obj_t * btnm, uint8_t type) lv_style_dsc_t * style_dsc_p; - switch(type) { + switch(part) { case LV_BTNM_PART_MAIN: style_dsc_p = &btnm->style_dsc; break; diff --git a/src/lv_objx/lv_page.c b/src/lv_objx/lv_page.c index 8cc2b39c7..4aaf38ff0 100644 --- a/src/lv_objx/lv_page.c +++ b/src/lv_objx/lv_page.c @@ -372,36 +372,6 @@ lv_coord_t lv_page_get_fit_height(lv_obj_t * page) return lv_obj_get_height(page) - bg_top - bg_bottom - scrl_top - scrl_bottom; } - -static lv_style_dsc_t * lv_page_get_style(lv_obj_t * page, uint8_t type) -{ - LV_ASSERT_OBJ(page, LV_OBJX_NAME); - - lv_page_ext_t * ext = lv_obj_get_ext_attr(page); - lv_style_dsc_t * style_dsc_p; - - switch(type) { - case LV_PAGE_PART_BG: - style_dsc_p = &page->style_dsc; - break; - case LV_PAGE_PART_SCRL: - style_dsc_p = lv_obj_get_style(ext->scrl, LV_CONT_PART_MAIN); - break; - case LV_PAGE_PART_SCRL_BAR: - style_dsc_p = &ext->sb.style; - break; -#if LV_USE_ANIMATION - case LV_PAGE_STYLE_EDGE_FLASH: - style_dsc_p = &ext->edge_flash.style; - break; -#endif - default: - style_dsc_p = NULL; - } - - return style_dsc_p; -} - /*===================== * Other functions *====================*/ @@ -757,20 +727,21 @@ static lv_design_res_t lv_page_design(lv_obj_t * page, const lv_area_t * clip_ar if(ext->edge_flash.left_ip || ext->edge_flash.right_ip || ext->edge_flash.top_ip || ext->edge_flash.bottom_ip) { - lv_style_t flash_style; - lv_style_copy(&flash_style, ext->edge_flash.style); - flash_style.body.radius = LV_RADIUS_CIRCLE; - uint32_t opa = (flash_style.body.opa * ext->edge_flash.state) / LV_PAGE_END_FLASH_SIZE; - flash_style.body.opa = opa; - lv_draw_rect(&flash_area, clip_area, &flash_style, lv_obj_get_opa_scale(page)); + lv_draw_rect_dsc_t edge_draw_dsc; + lv_draw_rect_dsc_init(&edge_draw_dsc); + lv_obj_init_draw_rect_dsc(page, LV_PAGE_PART_EDGE_FLASH, &edge_draw_dsc); + edge_draw_dsc.radius = LV_RADIUS_CIRCLE; + uint32_t opa = (edge_draw_dsc.bg_opa * ext->edge_flash.state) / LV_PAGE_END_FLASH_SIZE; + edge_draw_dsc.bg_opa = opa; + lv_draw_rect(&flash_area, clip_area, &edge_draw_dsc); } } - if(style->body.corner_mask) { +#endif + if(lv_obj_get_style_value(page, LV_PAGE_PART_BG, LV_STYLE_BG_CLIP_CORNER)) { void * param = lv_draw_mask_remove_custom(page + 8); lv_mem_buf_release(param); } -#endif } return LV_DESIGN_RES_OK; @@ -1093,6 +1064,37 @@ static void scrl_def_event_cb(lv_obj_t * scrl, lv_event_t event) /*clang-format on*/ } + +static lv_style_dsc_t * lv_page_get_style(lv_obj_t * page, uint8_t type) +{ + LV_ASSERT_OBJ(page, LV_OBJX_NAME); + + lv_page_ext_t * ext = lv_obj_get_ext_attr(page); + lv_style_dsc_t * style_dsc_p; + + switch(type) { + case LV_PAGE_PART_BG: + style_dsc_p = &page->style_dsc; + break; + case LV_PAGE_PART_SCRL: + style_dsc_p = lv_obj_get_style(ext->scrl, LV_CONT_PART_MAIN); + break; + case LV_PAGE_PART_SCRL_BAR: + style_dsc_p = &ext->sb.style; + break; +#if LV_USE_ANIMATION + case LV_PAGE_PART_EDGE_FLASH: + style_dsc_p = &ext->edge_flash.style; + break; +#endif + default: + style_dsc_p = NULL; + } + + return style_dsc_p; +} + + /** * Refresh the position and size of the scroll bars. * @param page pointer to a page object diff --git a/src/lv_objx/lv_slider.c b/src/lv_objx/lv_slider.c index 1b5343969..51cb80e57 100644 --- a/src/lv_objx/lv_slider.c +++ b/src/lv_objx/lv_slider.c @@ -32,6 +32,7 @@ **********************/ static lv_design_res_t lv_slider_design(lv_obj_t * slider, const lv_area_t * clip_area, lv_design_mode_t mode); static lv_res_t lv_slider_signal(lv_obj_t * slider, lv_signal_t sign, void * param); +static lv_style_dsc_t * lv_slider_get_style(lv_obj_t * slider, uint8_t part); static void lv_slider_position_knob(lv_obj_t * slider, lv_area_t * knob_area, lv_coord_t knob_size, bool hor); static void lv_slider_draw_knob(lv_obj_t * slider, const lv_area_t * knob_area, const lv_area_t * clip_area); @@ -76,7 +77,7 @@ lv_obj_t * lv_slider_create(lv_obj_t * par, const lv_obj_t * copy) } /*Initialize the allocated 'ext' */ - ext->style_knob = &lv_style_pretty; + lv_style_dsc_init(&ext->style_knob); ext->value_to_set = NULL; ext->dragging = false; ext->img_knob = NULL; @@ -90,22 +91,11 @@ lv_obj_t * lv_slider_create(lv_obj_t * par, const lv_obj_t * copy) lv_obj_set_click(new_slider, true); lv_obj_set_protect(new_slider, LV_PROTECT_PRESS_LOST); - /*Set the default styles*/ - lv_theme_t * th = lv_theme_get_current(); - if(th) { - lv_slider_set_style(new_slider, LV_SLIDER_STYLE_BG, th->style.slider.bg); - lv_slider_set_style(new_slider, LV_SLIDER_STYLE_INDIC, th->style.slider.indic); - lv_slider_set_style(new_slider, LV_SLIDER_STYLE_KNOB, th->style.slider.knob); - } else { - lv_slider_set_style(new_slider, LV_SLIDER_STYLE_KNOB, ext->style_knob); - } + _ot(new_slider, LV_SLIDER_PART_KNOB, SLIDER_KNOB); } /*Copy an existing slider*/ else { - lv_slider_ext_t * copy_ext = lv_obj_get_ext_attr(copy); - ext->style_knob = copy_ext->style_knob; - /*Refresh the style with new signal function*/ - lv_obj_refresh_style(new_slider); +// lv_slider_ext_t * copy_ext = lv_obj_get_ext_attr(copy); } LV_LOG_INFO("slider created"); @@ -134,29 +124,6 @@ void lv_slider_set_knob_img(lv_obj_t * slider, const void * img_src) lv_obj_invalidate(slider); } -/** - * Set a style of a slider - * @param slider pointer to a slider object - * @param type which style should be set - * @param style pointer to a style - */ -void lv_slider_set_style(lv_obj_t * slider, lv_slider_style_t type, const lv_style_t * style) -{ - LV_ASSERT_OBJ(slider, LV_OBJX_NAME); - - lv_slider_ext_t * ext = lv_obj_get_ext_attr(slider); - - switch(type) { - case LV_SLIDER_STYLE_BG: lv_bar_set_style(slider, LV_BAR_STYLE_BG, style); break; - case LV_SLIDER_STYLE_INDIC: lv_bar_set_style(slider, LV_BAR_STYLE_INDIC, style); break; - case LV_SLIDER_STYLE_KNOB: - ext->style_knob = style; - lv_obj_refresh_ext_draw_pad(slider); - lv_obj_invalidate(slider); - break; - } -} - /*===================== * Getter functions *====================*/ @@ -199,29 +166,6 @@ const void * lv_slider_get_knob_img(lv_obj_t * slider, const void * img_src) return ext->img_knob; } -/** - * Get a style of a slider - * @param slider pointer to a slider object - * @param type which style should be get - * @return style pointer to a style - */ -const lv_style_t * lv_slider_get_style(const lv_obj_t * slider, lv_slider_style_t type) -{ - LV_ASSERT_OBJ(slider, LV_OBJX_NAME); - - const lv_style_t * style = NULL; - lv_slider_ext_t * ext = lv_obj_get_ext_attr(slider); - - switch(type) { - case LV_SLIDER_STYLE_BG: style = lv_bar_get_style(slider, LV_BAR_STYLE_BG); break; - case LV_SLIDER_STYLE_INDIC: style = lv_bar_get_style(slider, LV_BAR_STYLE_INDIC); break; - case LV_SLIDER_STYLE_KNOB: style = ext->style_knob; break; - default: style = NULL; break; - } - - return style; -} - /********************** * STATIC FUNCTIONS **********************/ @@ -321,6 +265,13 @@ static lv_res_t lv_slider_signal(lv_obj_t * slider, lv_signal_t sign, void * par { lv_res_t res; + if(sign == LV_SIGNAL_GET_STYLE) { + uint8_t ** type_p = param; + lv_style_dsc_t ** style_dsc_p = param; + *style_dsc_p = lv_slider_get_style(slider, **type_p); + return LV_RES_OK; + } + /* Include the ancient signal function */ res = ancestor_signal(slider, sign, param); if(res != LV_RES_OK) return res; @@ -357,18 +308,23 @@ static lv_res_t lv_slider_signal(lv_obj_t * slider, lv_signal_t sign, void * par lv_coord_t w = lv_obj_get_width(slider); lv_coord_t h = lv_obj_get_height(slider); - const lv_style_t * indic_style = lv_slider_get_style(slider, LV_SLIDER_STYLE_INDIC); + + lv_style_value_t bg_left = lv_obj_get_style_value(slider, LV_SLIDER_PART_BG, LV_STYLE_PAD_LEFT); + lv_style_value_t bg_right = lv_obj_get_style_value(slider, LV_SLIDER_PART_BG, LV_STYLE_PAD_RIGHT); + lv_style_value_t bg_top = lv_obj_get_style_value(slider, LV_SLIDER_PART_BG, LV_STYLE_PAD_TOP); + lv_style_value_t bg_bottom = lv_obj_get_style_value(slider, LV_SLIDER_PART_BG, LV_STYLE_PAD_BOTTOM); + int32_t range = ext->bar.max_value - ext->bar.min_value; int16_t new_value = 0, real_max_value = ext->bar.max_value, real_min_value = ext->bar.min_value; if(w >= h) { - lv_coord_t indic_w = w - indic_style->body.padding.left - indic_style->body.padding.right; - new_value = p.x - (slider->coords.x1 + indic_style->body.padding.left); /*Make the point relative to the indicator*/ + lv_coord_t indic_w = w - bg_left - bg_right; + new_value = p.x - (slider->coords.x1 + bg_left); /*Make the point relative to the indicator*/ new_value = (new_value * range) / indic_w; new_value += ext->bar.min_value; } else { - lv_coord_t indic_h = h - indic_style->body.padding.bottom - indic_style->body.padding.top; - new_value = p.y - (slider->coords.y2 + indic_style->body.padding.bottom); /*Make the point relative to the indicator*/ + lv_coord_t indic_h = h - bg_bottom - bg_top; + new_value = p.y - (slider->coords.y2 + bg_bottom); /*Make the point relative to the indicator*/ new_value = (-new_value * range) / indic_h; new_value += ext->bar.min_value; @@ -412,18 +368,22 @@ static lv_res_t lv_slider_signal(lv_obj_t * slider, lv_signal_t sign, void * par slider->signal_cb(slider, LV_SIGNAL_REFR_EXT_DRAW_PAD, NULL); } } else if(sign == LV_SIGNAL_REFR_EXT_DRAW_PAD) { - const lv_style_t * bg_style = lv_slider_get_style(slider, LV_SLIDER_STYLE_BG); - const lv_style_t * indic_style = lv_slider_get_style(slider, LV_SLIDER_STYLE_INDIC); - const lv_style_t * knob_style = lv_slider_get_style(slider, LV_SLIDER_STYLE_KNOB); + lv_style_value_t knob_left = lv_obj_get_style_value(slider, LV_SLIDER_PART_KNOB, LV_STYLE_PAD_LEFT); + lv_style_value_t knob_right = lv_obj_get_style_value(slider, LV_SLIDER_PART_KNOB, LV_STYLE_PAD_RIGHT); + lv_style_value_t knob_top = lv_obj_get_style_value(slider, LV_SLIDER_PART_KNOB, LV_STYLE_PAD_TOP); + lv_style_value_t knob_bottom = lv_obj_get_style_value(slider, LV_SLIDER_PART_KNOB, LV_STYLE_PAD_BOTTOM); /* The smaller size is the knob diameter*/ lv_coord_t knob_size = LV_MATH_MIN(lv_obj_get_width(slider), lv_obj_get_height(slider)) >> 1; - knob_size += LV_MATH_MAX( - LV_MATH_MAX(knob_style->body.padding.left, knob_style->body.padding.right), - LV_MATH_MAX(knob_style->body.padding.bottom,knob_style->body.padding.top)); + knob_size += LV_MATH_MAX(LV_MATH_MAX(knob_left, knob_right), LV_MATH_MAX(knob_bottom,knob_top)); - knob_size += knob_style->body.shadow.width + knob_style->body.shadow.spread; - knob_size += LV_MATH_MAX(LV_MATH_ABS(knob_style->body.shadow.offset.x), LV_MATH_ABS(knob_style->body.shadow.offset.y)); + lv_style_value_t knob_sh_width = lv_obj_get_style_value(slider, LV_SLIDER_PART_KNOB, LV_STYLE_SHADOW_WIDTH); + lv_style_value_t knob_sh_spread = lv_obj_get_style_value(slider, LV_SLIDER_PART_KNOB, LV_STYLE_SHADOW_SPREAD); + lv_style_value_t knob_sh_ox = lv_obj_get_style_value(slider, LV_SLIDER_PART_KNOB, LV_STYLE_SHADOW_OFFSET_X); + lv_style_value_t knob_sh_oy = lv_obj_get_style_value(slider, LV_SLIDER_PART_KNOB, LV_STYLE_SHADOW_OFFSET_Y); + + knob_size += knob_sh_width + knob_sh_spread; + knob_size += LV_MATH_MAX(LV_MATH_ABS(knob_sh_ox), LV_MATH_ABS(knob_sh_oy)); if(ext->img_knob) { lv_img_header_t info; @@ -437,12 +397,21 @@ static lv_res_t lv_slider_signal(lv_obj_t * slider, lv_signal_t sign, void * par } } + lv_style_value_t bg_sh_width = lv_obj_get_style_value(slider, LV_SLIDER_PART_BG, LV_STYLE_SHADOW_WIDTH); + lv_style_value_t bg_sh_spread = lv_obj_get_style_value(slider, LV_SLIDER_PART_BG, LV_STYLE_SHADOW_SPREAD); + lv_style_value_t bg_sh_ox = lv_obj_get_style_value(slider, LV_SLIDER_PART_BG, LV_STYLE_SHADOW_OFFSET_X); + lv_style_value_t bg_sh_oy = lv_obj_get_style_value(slider, LV_SLIDER_PART_BG, LV_STYLE_SHADOW_OFFSET_Y); - lv_coord_t bg_size = bg_style->body.shadow.width + bg_style->body.shadow.spread; - bg_size += LV_MATH_MAX(LV_MATH_ABS(bg_style->body.shadow.offset.x), LV_MATH_ABS(bg_style->body.shadow.offset.y)); + lv_coord_t bg_size = bg_sh_width + bg_sh_spread; + bg_size += LV_MATH_MAX(LV_MATH_ABS(bg_sh_ox), LV_MATH_ABS(bg_sh_oy)); - lv_coord_t indic_size = indic_style->body.shadow.width + indic_style->body.shadow.spread; - indic_size += LV_MATH_MAX(LV_MATH_ABS(indic_style->body.shadow.offset.x), LV_MATH_ABS(indic_style->body.shadow.offset.y)); + lv_style_value_t indic_sh_width = lv_obj_get_style_value(slider, LV_SLIDER_PART_INDIC, LV_STYLE_SHADOW_WIDTH); + lv_style_value_t indic_sh_spread = lv_obj_get_style_value(slider, LV_SLIDER_PART_INDIC, LV_STYLE_SHADOW_SPREAD); + lv_style_value_t indic_sh_ox = lv_obj_get_style_value(slider, LV_SLIDER_PART_INDIC, LV_STYLE_SHADOW_OFFSET_X); + lv_style_value_t indic_sh_oy = lv_obj_get_style_value(slider, LV_SLIDER_PART_INDIC, LV_STYLE_SHADOW_OFFSET_Y); + + lv_coord_t indic_size = indic_sh_width + indic_sh_spread; + indic_size += LV_MATH_MAX(LV_MATH_ABS(indic_sh_ox), LV_MATH_ABS(indic_sh_oy)); slider->ext_draw_pad = LV_MATH_MAX(slider->ext_draw_pad, knob_size); slider->ext_draw_pad = LV_MATH_MAX(slider->ext_draw_pad, indic_size); @@ -468,9 +437,33 @@ static lv_res_t lv_slider_signal(lv_obj_t * slider, lv_signal_t sign, void * par return res; } + +static lv_style_dsc_t * lv_slider_get_style(lv_obj_t * slider, uint8_t part) +{ + LV_ASSERT_OBJ(slider, LV_OBJX_NAME); + + lv_slider_ext_t * ext = lv_obj_get_ext_attr(slider); + lv_style_dsc_t * style_dsc_p; + + switch(part) { + case LV_SLIDER_PART_BG: + style_dsc_p = &slider->style_dsc; + break; + case LV_SLIDER_PART_INDIC: + style_dsc_p = &ext->bar.style_indic; + break; + case LV_SLIDER_PART_KNOB: + style_dsc_p = &ext->style_knob; + break; + default: + style_dsc_p = NULL; + } + + return style_dsc_p; +} + static void lv_slider_position_knob(lv_obj_t * slider, lv_area_t * knob_area, lv_coord_t knob_size, bool hor) { - const lv_style_t * style_knob = lv_slider_get_style(slider, LV_SLIDER_STYLE_KNOB); if(hor) { knob_area->x1 -= (knob_size >> 1); @@ -484,19 +477,27 @@ static void lv_slider_position_knob(lv_obj_t * slider, lv_area_t * knob_area, lv knob_area->x2 = slider->coords.x2; } + lv_style_value_t knob_left = lv_obj_get_style_value(slider, LV_SLIDER_PART_KNOB, LV_STYLE_PAD_LEFT); + lv_style_value_t knob_right = lv_obj_get_style_value(slider, LV_SLIDER_PART_KNOB, LV_STYLE_PAD_RIGHT); + lv_style_value_t knob_top = lv_obj_get_style_value(slider, LV_SLIDER_PART_KNOB, LV_STYLE_PAD_TOP); + lv_style_value_t knob_bottom = lv_obj_get_style_value(slider, LV_SLIDER_PART_KNOB, LV_STYLE_PAD_BOTTOM); + /*Apply the paddings on the knob area*/ - knob_area->x1 -= style_knob->body.padding.left; - knob_area->x2 += style_knob->body.padding.right; - knob_area->y1 -= style_knob->body.padding.top; - knob_area->y2 += style_knob->body.padding.bottom; + knob_area->x1 -= knob_left; + knob_area->x2 += knob_right; + knob_area->y1 -= knob_top; + knob_area->y2 += knob_bottom; } -static void lv_slider_draw_knob(lv_obj_t * slider, const lv_area_t * knob_area, const lv_area_t * clip_area) { +static void lv_slider_draw_knob(lv_obj_t * slider, const lv_area_t * knob_area, const lv_area_t * clip_area) +{ lv_slider_ext_t * ext = lv_obj_get_ext_attr(slider); - const lv_style_t * style_knob = lv_slider_get_style(slider, LV_SLIDER_STYLE_KNOB); - lv_opa_t opa_scale = lv_obj_get_opa_scale(slider); - lv_draw_rect(knob_area, clip_area, style_knob, opa_scale); + lv_draw_rect_dsc_t knob_rect_dsc; + lv_draw_rect_dsc_init(&knob_rect_dsc); + lv_obj_init_draw_rect_dsc(slider, LV_SLIDER_PART_KNOB, &knob_rect_dsc); + + lv_draw_rect(knob_area, clip_area, &knob_rect_dsc); if(ext->img_knob) { lv_res_t res; @@ -511,7 +512,10 @@ static void lv_slider_draw_knob(lv_obj_t * slider, const lv_area_t * knob_area, a.x2 = info.w - 1 + x_ofs; a.y2 = info.h - 1 + y_ofs; - lv_draw_img(&a, clip_area, ext->img_knob, style_knob, 0, NULL, LV_IMG_ZOOM_NONE, false, opa_scale); + lv_draw_img_dsc_t knob_img_dsc; + lv_draw_img_dsc_init(&knob_img_dsc); + lv_obj_init_draw_img_dsc(slider, LV_SLIDER_PART_KNOB, &knob_img_dsc); + lv_draw_img(&a, clip_area, ext->img_knob, &knob_img_dsc); } else { LV_LOG_WARN("lv_slider_design: can't get knob image info") } diff --git a/src/lv_objx/lv_slider.h b/src/lv_objx/lv_slider.h index a8e634442..4edb350e8 100644 --- a/src/lv_objx/lv_slider.h +++ b/src/lv_objx/lv_slider.h @@ -44,7 +44,7 @@ typedef struct { lv_bar_ext_t bar; /*Ext. of ancestor*/ /*New data for this type */ - const lv_style_t * style_knob; /*Style of the knob*/ + lv_style_dsc_t style_knob; /*Style of the knob*/ lv_area_t left_knob_area; lv_area_t right_knob_area; int16_t *value_to_set; /* Which bar value to set */ @@ -54,9 +54,9 @@ typedef struct /** Built-in styles of slider*/ enum { - LV_SLIDER_STYLE_BG, /** Slider background style. */ - LV_SLIDER_STYLE_INDIC, /** Slider indicator (filled area) style. */ - LV_SLIDER_STYLE_KNOB, /** Slider knob style. */ + LV_SLIDER_PART_BG, /** Slider background style. */ + LV_SLIDER_PART_INDIC, /** Slider indicator (filled area) style. */ + LV_SLIDER_PART_KNOB, /** Slider knob style. */ }; typedef uint8_t lv_slider_style_t; @@ -143,14 +143,6 @@ static inline void lv_slider_set_type(lv_obj_t * slider, lv_slider_type_t type) lv_bar_set_type(slider, LV_BAR_TYPE_CUSTOM); } -/** - * Set a style of a slider - * @param slider pointer to a slider object - * @param type which style should be set - * @param style pointer to a style - */ -void lv_slider_set_style(lv_obj_t * slider, lv_slider_style_t type, const lv_style_t * style); - /*===================== * Getter functions *====================*/ @@ -232,14 +224,6 @@ static inline lv_slider_type_t lv_slider_get_type(lv_obj_t * slider) return LV_SLIDER_TYPE_NORMAL; } -/** - * Get a style of a slider - * @param slider pointer to a slider object - * @param type which style should be get - * @return style pointer to a style - */ -const lv_style_t * lv_slider_get_style(const lv_obj_t * slider, lv_slider_style_t type); - /********************** * MACROS **********************/ diff --git a/src/lv_objx/lv_sw.c b/src/lv_objx/lv_sw.c index 4427cc2a6..d67766bc1 100644 --- a/src/lv_objx/lv_sw.c +++ b/src/lv_objx/lv_sw.c @@ -33,14 +33,14 @@ /********************** * STATIC PROTOTYPES **********************/ -static lv_design_res_t lv_sw_design(lv_obj_t * slider, const lv_area_t * clip_area, lv_design_mode_t mode); static lv_res_t lv_sw_signal(lv_obj_t * sw, lv_signal_t sign, void * param); +static lv_style_dsc_t * lv_sw_get_style(lv_obj_t * sw, uint8_t part); +static lv_style_dsc_t * lv_sw_get_style(lv_obj_t * sw, uint8_t part); /********************** * STATIC VARIABLES **********************/ static lv_signal_cb_t ancestor_signal; -static lv_design_cb_t ancestor_design; /********************** * MACROS @@ -61,13 +61,12 @@ lv_obj_t * lv_sw_create(lv_obj_t * par, const lv_obj_t * copy) LV_LOG_TRACE("switch create started"); /*Create the ancestor of switch*/ - lv_obj_t * new_sw = lv_bar_create(par, copy); + lv_obj_t * new_sw = lv_slider_create(par, copy); LV_ASSERT_MEM(new_sw); if(new_sw == NULL) return NULL; if(ancestor_signal == NULL) ancestor_signal = lv_obj_get_signal_cb(new_sw); - if(ancestor_design == NULL) ancestor_design = lv_obj_get_design_cb(new_sw); /*Allocate the switch type specific extended data*/ lv_sw_ext_t * ext = lv_obj_allocate_ext_attr(new_sw, sizeof(lv_sw_ext_t)); @@ -79,42 +78,28 @@ lv_obj_t * lv_sw_create(lv_obj_t * par, const lv_obj_t * copy) /*Initialize the allocated 'ext' */ ext->changed = 0; - ext->style_knob_off = &lv_style_pretty; - ext->style_knob_on = &lv_style_pretty; - ext->img_knob_off = NULL; - ext->img_knob_on = NULL; /*The signal and design functions are not copied so set them here*/ lv_obj_set_signal_cb(new_sw, lv_sw_signal); - lv_obj_set_design_cb(new_sw, lv_sw_design); /*Init the new switch switch*/ if(copy == NULL) { lv_obj_set_click(new_sw, true); lv_obj_set_protect(new_sw, LV_PROTECT_PRESS_LOST); lv_obj_set_size(new_sw, 2 * LV_DPI / 3, LV_DPI / 3); - lv_bar_set_range(new_sw, 0, LV_SW_MAX_VALUE); + lv_slider_set_range(new_sw, 0, 1); + + _ot(new_sw, LV_SW_PART_KNOB, SW_KNOB); - /*Set the default styles*/ - lv_theme_t * th = lv_theme_get_current(); - if(th) { - lv_sw_set_style(new_sw, LV_SW_STYLE_BG, th->style.sw.bg); - lv_sw_set_style(new_sw, LV_SW_STYLE_INDIC, th->style.sw.indic); - lv_sw_set_style(new_sw, LV_SW_STYLE_KNOB_OFF, th->style.sw.knob_off); - lv_sw_set_style(new_sw, LV_SW_STYLE_KNOB_ON, th->style.sw.knob_on); - } else { - /*Let the slider' style*/ - } } /*Copy an existing switch*/ else { - lv_sw_ext_t * copy_ext = lv_obj_get_ext_attr(copy); - ext->style_knob_off = copy_ext->style_knob_off; - ext->style_knob_on = copy_ext->style_knob_on; +// lv_sw_ext_t * copy_ext = lv_obj_get_ext_attr(copy); +// ext->style_knob_off = copy_ext->style_knob_off; +// ext->style_knob_on = copy_ext->style_knob_on; } /*Refresh the style with new signal function*/ - lv_obj_refresh_style(new_sw); LV_LOG_INFO("switch created"); @@ -139,8 +124,8 @@ void lv_sw_on(lv_obj_t * sw, lv_anim_enable_t anim) #endif lv_sw_ext_t * ext = lv_obj_get_ext_attr(sw); ext->state = 1; - lv_bar_set_value(sw, LV_SW_MAX_VALUE, anim); - lv_obj_invalidate(sw); + lv_slider_set_value(sw, 1, anim); + lv_obj_set_state(sw, LV_OBJ_STATE_CHECKED); } /** @@ -158,7 +143,7 @@ void lv_sw_off(lv_obj_t * sw, lv_anim_enable_t anim) lv_sw_ext_t * ext = lv_obj_get_ext_attr(sw); ext->state = 0; lv_bar_set_value(sw, 0, anim); - lv_obj_invalidate(sw); + lv_obj_clear_state(sw, LV_OBJ_STATE_CHECKED); } /** @@ -184,210 +169,14 @@ bool lv_sw_toggle(lv_obj_t * sw, lv_anim_enable_t anim) return !state; } -/** - * Set an image to display on the knob of the switch when it's in OFF state - * @param sw pointer to a switch object - * @param img_src pointer to an `lv_img_dsc_t` variable or a path to an image - * (not an `lv_img` object) - */ -void lv_sw_set_knob_off_img(lv_obj_t * sw, const void * img_src) -{ - LV_ASSERT_OBJ(sw, LV_OBJX_NAME); - - lv_sw_ext_t * ext = lv_obj_get_ext_attr(sw); - - ext->img_knob_off = img_src; - lv_obj_refresh_ext_draw_pad(sw); - lv_obj_invalidate(sw); -} - -/** - * Set an image to display on the knob of the switch when it's in ON state - * @param sw pointer to a switch object - * @param img_src pointer to an `lv_img_dsc_t` variable or a path to an image - * (not an `lv_img` object) - */ -void lv_sw_set_knob_on_img(lv_obj_t * sw, const void * img_src) -{ - LV_ASSERT_OBJ(sw, LV_OBJX_NAME); - - lv_sw_ext_t * ext = lv_obj_get_ext_attr(sw); - - ext->img_knob_on = img_src; - lv_obj_refresh_ext_draw_pad(sw); - lv_obj_invalidate(sw); -} - -/** - * Set a style of a switch - * @param sw pointer to a switch object - * @param type which style should be set - * @param style pointer to a style - */ -void lv_sw_set_style(lv_obj_t * sw, lv_sw_style_t type, const lv_style_t * style) -{ - LV_ASSERT_OBJ(sw, LV_OBJX_NAME); - - lv_sw_ext_t * ext = lv_obj_get_ext_attr(sw); - - switch(type) { - case LV_SW_STYLE_BG: lv_bar_set_style(sw, LV_BAR_STYLE_BG, style); break; - case LV_SW_STYLE_INDIC: lv_bar_set_style(sw, LV_BAR_STYLE_INDIC, style); break; - case LV_SW_STYLE_KNOB_OFF: - ext->style_knob_off = style; - lv_obj_refresh_ext_draw_pad(sw); - lv_obj_invalidate(sw); - break; - case LV_SW_STYLE_KNOB_ON: - ext->style_knob_on = style; - lv_obj_refresh_ext_draw_pad(sw); - lv_obj_invalidate(sw); - break; - } -} - /*===================== * Getter functions *====================*/ -/** - * Get an image to display on the knob of the switch when it's in OFF state - * @param sw pointer to a switch object - * @return the image source: pointer to an `lv_img_dsc_t` variable or a path to an image - * (not an `lv_img` object) - */ -const void * lv_slider_get_knob_off_img(lv_obj_t * sw, const void * img_src) -{ - LV_ASSERT_OBJ(sw, LV_OBJX_NAME); - - lv_sw_ext_t * ext = lv_obj_get_ext_attr(sw); - - return ext->img_knob_off; -} - -/** - * Get an image to display on the knob of the switch when it's in ON state - * @param sw pointer to a switch object - * @return the image source: pointer to an `lv_img_dsc_t` variable or a path to an image - * (not an `lv_img` object) - */ -const void * lv_slider_get_knob_on_img(lv_obj_t * sw, const void * img_src) -{ - LV_ASSERT_OBJ(sw, LV_OBJX_NAME); - - lv_sw_ext_t * ext = lv_obj_get_ext_attr(sw); - - return ext->img_knob_on; -} - -/** - * Get a style of a switch - * @param sw pointer to a switch object - * @param type which style should be get - * @return style pointer to a style - */ -const lv_style_t * lv_sw_get_style(const lv_obj_t * sw, lv_sw_style_t type) -{ - LV_ASSERT_OBJ(sw, LV_OBJX_NAME); - - const lv_style_t * style = NULL; - lv_sw_ext_t * ext = lv_obj_get_ext_attr(sw); - - switch(type) { - case LV_SW_STYLE_BG: style = lv_bar_get_style(sw, LV_BAR_STYLE_BG); break; - case LV_SW_STYLE_INDIC: style = lv_bar_get_style(sw, LV_BAR_STYLE_INDIC); break; - case LV_SW_STYLE_KNOB_OFF: style = ext->style_knob_off; break; - case LV_SW_STYLE_KNOB_ON: style = ext->style_knob_on; break; - default: style = NULL; break; - } - - return style; -} - /********************** * STATIC FUNCTIONS **********************/ -/** - * Handle the drawing related tasks of the sliders - * @param sw pointer to an object - * @param clip_area the object will be drawn only in this area - * @param mode LV_DESIGN_COVER_CHK: only check if the object fully covers the 'mask_p' area - * (return 'true' if yes) - * LV_DESIGN_DRAW: draw the object (always return 'true') - * LV_DESIGN_DRAW_POST: drawing after every children are drawn - * @param return an element of `lv_design_res_t` - */ -static lv_design_res_t lv_sw_design(lv_obj_t * sw, const lv_area_t * clip_area, lv_design_mode_t mode) -{ - /*Return false if the object is not covers the mask_p area*/ - if(mode == LV_DESIGN_COVER_CHK) { - return LV_DESIGN_RES_NOT_COVER; - } - /*Draw the object*/ - else if(mode == LV_DESIGN_DRAW_MAIN) { - /*The ancestor design function will draw the background and the indicator. - * It also sets ext->bar.indic_area*/ - ancestor_design(sw, clip_area, mode); - - lv_sw_ext_t * ext = lv_obj_get_ext_attr(sw); - lv_opa_t opa_scale = lv_obj_get_opa_scale(sw); - const lv_style_t * style_knob = lv_sw_get_style(sw, ext->state ? - LV_SW_STYLE_KNOB_ON : LV_SW_STYLE_KNOB_OFF); - - const lv_style_t * style_indic = lv_sw_get_style(sw, LV_SW_STYLE_INDIC); - - lv_coord_t objw = lv_obj_get_width(sw); - lv_coord_t objh = lv_obj_get_height(sw); - lv_coord_t indic_maxw = objw - style_indic->body.padding.left - style_indic->body.padding.right; - lv_coord_t knob_size = objh; - - lv_coord_t indic_p = (lv_area_get_width(&ext->bar.indic_area) * 256) / (indic_maxw); - lv_area_t knob_area; - knob_area.x2 = ext->bar.indic_area.x2; - knob_area.x2 += (knob_size * (256 - indic_p)) >> 8; - if(knob_area.x2 < sw->coords.x1 + knob_size) knob_area.x2 = sw->coords.x1 + knob_size; - knob_area.x1 = knob_area.x2 - knob_size; - knob_area.y1 = sw->coords.y1; - knob_area.y2 = sw->coords.y2; - - knob_area.x1 -= style_knob->body.padding.left; - knob_area.x2 += style_knob->body.padding.right; - knob_area.y1 -= style_knob->body.padding.top; - knob_area.y2 += style_knob->body.padding.bottom; - - lv_draw_rect(&knob_area, clip_area, style_knob, opa_scale); - - const void * img = ext->state ? ext->img_knob_on : ext->img_knob_off; - - if(img) { - lv_res_t res; - lv_img_header_t info; - res = lv_img_decoder_get_info(img, &info); - if(res == LV_RES_OK) { - lv_coord_t x_ofs = knob_area.x1 + (lv_area_get_width(&knob_area) - info.w) / 2; - lv_coord_t y_ofs = knob_area.y1 + (lv_area_get_height(&knob_area) - info.h) / 2; - lv_area_t a; - a.x1 = x_ofs; - a.y1 = y_ofs; - a.x2 = info.w - 1 + x_ofs; - a.y2 = info.h - 1 + y_ofs; - - lv_draw_img(&a, clip_area, img, style_knob, 0, NULL, LV_IMG_ZOOM_NONE, false, opa_scale); - } else { - LV_LOG_WARN("lv_slider_design: can't get knob image info") - } - } - } - /*Post draw when the children are drawn*/ - else if(mode == LV_DESIGN_DRAW_POST) { - return ancestor_design(sw, clip_area, mode); - } - - return LV_DESIGN_RES_OK; -} - - /** * Signal function of the switch * @param sw pointer to a switch object @@ -398,6 +187,14 @@ static lv_design_res_t lv_sw_design(lv_obj_t * sw, const lv_area_t * clip_area, static lv_res_t lv_sw_signal(lv_obj_t * sw, lv_signal_t sign, void * param) { lv_res_t res; + + if(sign == LV_SIGNAL_GET_STYLE) { + uint8_t ** type_p = param; + lv_style_dsc_t ** style_dsc_p = param; + *style_dsc_p = lv_sw_get_style(sw, **type_p); + return LV_RES_OK; + } + if(sign == LV_SIGNAL_GET_TYPE) { res = ancestor_signal(sw, sign, param); if(res != LV_RES_OK) return res; @@ -421,148 +218,37 @@ static lv_res_t lv_sw_signal(lv_obj_t * sw, lv_signal_t sign, void * param) lv_indev_get_point(indev, &p); ext->start_x = p.x; } - ext->slided = 0; ext->changed = 0; } else if(sign == LV_SIGNAL_PRESSING) { - /*See if the switch was slid (moved at least a little)*/ - lv_indev_t * indev = lv_indev_get_act(); - lv_point_t p; - if(indev) { - lv_indev_get_point(indev, &p); - if(LV_MATH_ABS(p.x - ext->start_x) > indev->driver.drag_limit) ext->slided = 1; - - /*If slid set the value accordingly*/ - if(ext->slided) { - lv_coord_t w = lv_obj_get_width(sw); - const lv_style_t * indic_style = lv_sw_get_style(sw, LV_SW_STYLE_INDIC); - int16_t new_val = 0; - - lv_coord_t indic_w = w - indic_style->body.padding.left - indic_style->body.padding.right; - int32_t range = ext->bar.max_value - ext->bar.min_value; - new_val = p.x - (sw->coords.x1 + indic_style->body.padding.left); /*Make the point relative to the indicator*/ - new_val = (new_val * range) / indic_w; - new_val += ext->bar.min_value; - - if(new_val < ext->bar.min_value) new_val = ext->bar.min_value; - else if(new_val > ext->bar.max_value) new_val = ext->bar.max_value; - - /*If explicitly changed (by slide) don't need to be toggled on release*/ - int16_t threshold = LV_SW_MAX_VALUE / 2; - if((new_val < threshold && ext->bar.cur_value > threshold) || - (new_val > threshold && ext->bar.cur_value < threshold)) { - ext->changed = 1; - } - - if(new_val != ext->bar.cur_value) { - ext->bar.cur_value = new_val; - lv_obj_invalidate(sw); - } - } - } + if(ext->state != ext->slider.bar.cur_value) ext->changed = 1; } else if(sign == LV_SIGNAL_PRESS_LOST) { if(lv_sw_get_state(sw)) lv_sw_on(sw, LV_ANIM_ON); else lv_sw_off(sw, LV_ANIM_ON); } else if(sign == LV_SIGNAL_RELEASED) { /*If not dragged then toggle the switch*/ if(ext->changed == 0) { - int32_t state; if(lv_sw_get_state(sw)) { lv_sw_off(sw, LV_ANIM_ON); - state = 0; } else { lv_sw_on(sw, LV_ANIM_ON); - state = 1; } - - res = lv_event_send(sw, LV_EVENT_VALUE_CHANGED, &state); - if(res != LV_RES_OK) return res; } /*If the switch was dragged then calculate the new state based on the current position*/ else { - int16_t v = lv_bar_get_value(sw); - int32_t state; - if(v > LV_SW_MAX_VALUE / 2) { - lv_sw_on(sw, LV_ANIM_ON); - state = 1; - } else { - lv_sw_off(sw, LV_ANIM_ON); - state = 0; - } - res = lv_event_send(sw, LV_EVENT_VALUE_CHANGED, &state); - if(res != LV_RES_OK) return res; + if(ext->slider.bar.cur_value != 0) lv_sw_on(sw, LV_ANIM_ON); + else lv_sw_off(sw, LV_ANIM_ON); } + + res = lv_event_send(sw, LV_EVENT_VALUE_CHANGED, NULL); + if(res != LV_RES_OK) return res; + } else if(sign == LV_SIGNAL_CONTROL) { char c = *((char *)param); - uint32_t state; - if(c == LV_KEY_RIGHT || c == LV_KEY_UP) { - lv_bar_set_value(sw, LV_SW_MAX_VALUE, LV_ANIM_ON); - state = 1; - res = lv_event_send(sw, LV_EVENT_VALUE_CHANGED, &state); - if(res != LV_RES_OK) return res; - } else if(c == LV_KEY_LEFT || c == LV_KEY_DOWN) { - lv_bar_set_value(sw, 0, LV_ANIM_ON); - state = 0; - res = lv_event_send(sw, LV_EVENT_VALUE_CHANGED, &state); - if(res != LV_RES_OK) return res; - } - } - else if(sign == LV_SIGNAL_REFR_EXT_DRAW_PAD) { - const lv_style_t * bg_style = lv_sw_get_style(sw, LV_SW_STYLE_BG); - const lv_style_t * indic_style = lv_sw_get_style(sw, LV_SW_STYLE_INDIC); - const lv_style_t * knob_on_style = lv_sw_get_style(sw, LV_SW_STYLE_KNOB_OFF); - const lv_style_t * knob_off_style = lv_sw_get_style(sw, LV_SW_STYLE_KNOB_ON); - /* The smaller size is the knob diameter*/ - lv_coord_t knob_on_size = LV_MATH_MIN(lv_obj_get_width(sw), lv_obj_get_height(sw)) >> 1; - knob_on_size += LV_MATH_MAX( - LV_MATH_MAX(knob_on_style->body.padding.left, knob_on_style->body.padding.right), - LV_MATH_MAX(knob_on_style->body.padding.bottom, knob_on_style->body.padding.top)); - - knob_on_size += knob_on_style->body.shadow.width + knob_on_style->body.shadow.spread; - knob_on_size += LV_MATH_MAX(LV_MATH_ABS(knob_on_style->body.shadow.offset.x), LV_MATH_ABS(knob_on_style->body.shadow.offset.y)); - - if(ext->img_knob_on) { - lv_img_header_t info; - lv_res_t res; - res = lv_img_decoder_get_info(ext->img_knob_on, &info); - if(res == LV_RES_OK) { - knob_on_size = LV_MATH_MAX(knob_on_size, info.w / 2); - knob_on_size = LV_MATH_MAX(knob_on_size, info.h / 2); - } else { - LV_LOG_WARN("slider signal (LV_SIGNAL_REFR_EXT_DRAW_PAD): can't get knob image info") - } - } - - lv_coord_t knob_off_size = LV_MATH_MIN(lv_obj_get_width(sw), lv_obj_get_height(sw)) >> 1; - knob_off_size += LV_MATH_MAX( - LV_MATH_MAX(knob_off_style->body.padding.left, knob_off_style->body.padding.right), - LV_MATH_MAX(knob_off_style->body.padding.bottom, knob_off_style->body.padding.top)); - - knob_off_size += knob_off_style->body.shadow.width + knob_off_style->body.shadow.spread; - knob_off_size += LV_MATH_MAX(LV_MATH_ABS(knob_off_style->body.shadow.offset.x), LV_MATH_ABS(knob_off_style->body.shadow.offset.y)); - - if(ext->img_knob_off) { - lv_img_header_t info; - lv_res_t res; - res = lv_img_decoder_get_info(ext->img_knob_off, &info); - if(res == LV_RES_OK) { - knob_off_size = LV_MATH_MAX(knob_off_size, info.w / 2); - knob_off_size = LV_MATH_MAX(knob_off_size, info.h / 2); - } else { - LV_LOG_WARN("slider signal (LV_SIGNAL_REFR_EXT_DRAW_PAD): can't get knob image info") - } - } - - lv_coord_t bg_size = bg_style->body.shadow.width + bg_style->body.shadow.spread; - bg_size += LV_MATH_MAX(LV_MATH_ABS(bg_style->body.shadow.offset.x), LV_MATH_ABS(bg_style->body.shadow.offset.y)); - - lv_coord_t indic_size = indic_style->body.shadow.width + indic_style->body.shadow.spread; - indic_size += LV_MATH_MAX(LV_MATH_ABS(indic_style->body.shadow.offset.x), LV_MATH_ABS(indic_style->body.shadow.offset.y)); - - sw->ext_draw_pad = LV_MATH_MAX(sw->ext_draw_pad, knob_on_size); - sw->ext_draw_pad = LV_MATH_MAX(sw->ext_draw_pad, knob_off_size); - sw->ext_draw_pad = LV_MATH_MAX(sw->ext_draw_pad, bg_size); - sw->ext_draw_pad = LV_MATH_MAX(sw->ext_draw_pad, indic_size); + if(c == LV_KEY_RIGHT || c == LV_KEY_UP) lv_sw_on(sw, LV_ANIM_ON); + else if(c == LV_KEY_LEFT || c == LV_KEY_DOWN) lv_sw_off(sw, LV_ANIM_ON); + res = lv_event_send(sw, LV_EVENT_VALUE_CHANGED, NULL); + if(res != LV_RES_OK) return res; } else if(sign == LV_SIGNAL_GET_EDITABLE) { bool * editable = (bool *)param; @@ -572,4 +258,27 @@ static lv_res_t lv_sw_signal(lv_obj_t * sw, lv_signal_t sign, void * param) return res; } +static lv_style_dsc_t * lv_sw_get_style(lv_obj_t * sw, uint8_t part) +{ + LV_ASSERT_OBJ(sw, LV_OBJX_NAME); + + lv_sw_ext_t * ext = lv_obj_get_ext_attr(sw); + lv_style_dsc_t * style_dsc_p; + + switch(part) { + case LV_SW_PART_BG: + style_dsc_p = &sw->style_dsc; + break; + case LV_SW_PART_INDIC: + style_dsc_p = &ext->slider.bar.style_indic; + break; + case LV_SW_PART_KNOB: + style_dsc_p = &ext->slider.style_knob; + break; + default: + style_dsc_p = NULL; + } + + return style_dsc_p; +} #endif diff --git a/src/lv_objx/lv_sw.h b/src/lv_objx/lv_sw.h index 480ff4ed3..d5e9372ab 100644 --- a/src/lv_objx/lv_sw.h +++ b/src/lv_objx/lv_sw.h @@ -23,12 +23,11 @@ extern "C" { #endif #include "../lv_core/lv_obj.h" -#include "lv_bar.h" +#include "lv_slider.h" /********************* * DEFINES *********************/ -#define LV_SW_MAX_VALUE 100 /********************** * TYPEDEFS @@ -36,28 +35,23 @@ extern "C" { /*Data of switch*/ typedef struct { - lv_bar_ext_t bar; /*Ext. of ancestor*/ + lv_slider_ext_t slider; /*Ext. of ancestor*/ /*New data for this type */ - const lv_style_t * style_knob_off; /**< Style of the knob when the switch is OFF*/ - const lv_style_t * style_knob_on; /**< Style of the knob when the switch is ON (NULL to use the same as OFF)*/ - const void * img_knob_off; /**< Image to display when the switch is OFF*/ - const void * img_knob_on; /**< Image to display when the switch is ON*/ lv_coord_t start_x; uint8_t changed :1; /*Indicates the switch state explicitly changed by drag*/ - uint8_t slided :1; uint8_t state :1; /*The current state*/ } lv_sw_ext_t; /** - * Switch styles. + * Switch parts. */ enum { - LV_SW_STYLE_BG, /**< Switch background. */ - LV_SW_STYLE_INDIC, /**< Switch fill area. */ - LV_SW_STYLE_KNOB_OFF, /**< Switch knob (when off). */ - LV_SW_STYLE_KNOB_ON, /**< Switch knob (when on). */ + LV_SW_PART_BG, /**< Switch background. */ + LV_SW_PART_INDIC, /**< Switch fill area. */ + LV_SW_PART_KNOB, /**< Switch knob (when off). */ }; -typedef uint8_t lv_sw_style_t; + +typedef uint8_t lv_sw_part_t; /********************** * GLOBAL PROTOTYPES @@ -98,12 +92,12 @@ void lv_sw_off(lv_obj_t * sw, lv_anim_enable_t anim); bool lv_sw_toggle(lv_obj_t * sw, lv_anim_enable_t anim); /** - * Set an image to display on the knob of the switch when it's in OFF state + * Set an image to display on the knob of the switch. * @param sw pointer to a switch object * @param img_src pointer to an `lv_img_dsc_t` variable or a path to an image * (not an `lv_img` object) */ -void lv_sw_set_knob_off_img(lv_obj_t * sw, const void * img_src); +void lv_sw_set_knob_img(lv_obj_t * sw, const void * img_src); /** * Set an image to display on the knob of the switch when it's in ON state @@ -123,14 +117,6 @@ static inline void lv_sw_set_anim_time(lv_obj_t * sw, uint16_t anim_time) { lv_bar_set_anim_time(sw, anim_time); } -/** - * Set a style of a switch - * @param sw pointer to a switch object - * @param type which style should be set - * @param style pointer to a style - */ -void lv_sw_set_style(lv_obj_t * sw, lv_sw_style_t type, const lv_style_t * style); - /*===================== * Getter functions @@ -171,16 +157,6 @@ static inline uint16_t lv_sw_get_anim_time(const lv_obj_t * sw) return lv_bar_get_anim_time(sw); } -/** - * Get a style of a switch - * @param sw pointer to a switch object - * @param type which style should be get - * @return style pointer to a style - */ -const lv_style_t * lv_sw_get_style(const lv_obj_t * sw, lv_sw_style_t type); - - - /********************** * MACROS **********************/ diff --git a/src/lv_themes/lv_theme.h b/src/lv_themes/lv_theme.h index 6e43990ef..c0dbc9ef8 100644 --- a/src/lv_themes/lv_theme.h +++ b/src/lv_themes/lv_theme.h @@ -53,10 +53,20 @@ typedef enum { LV_THEME_LABEL_TITLE, LV_THEME_LABEL_HINT, - LV_THEME_BTNM, LV_THEME_BTNM_BTN, + LV_THEME_BAR, + LV_THEME_BAR_INDIC, + + LV_THEME_SLIDER, + LV_THEME_SLIDER_INDIC, + LV_THEME_SLIDER_KNOB, + + LV_THEME_SW, + LV_THEME_SW_INDIC, + LV_THEME_SW_KNOB, + }lv_theme_style_t; typedef struct { diff --git a/src/lv_themes/lv_theme_alien.c b/src/lv_themes/lv_theme_alien.c index f50639410..b84eb2aec 100644 --- a/src/lv_themes/lv_theme_alien.c +++ b/src/lv_themes/lv_theme_alien.c @@ -30,18 +30,16 @@ static lv_theme_t theme; static lv_style_t scr; static lv_style_t transp; -static lv_style_t def; -static lv_style_t bg; static lv_style_t panel; /*General fancy background (e.g. to chart or ta)*/ -static lv_style_t sb; static lv_style_t btn; +static lv_style_t sb; #if LV_USE_BAR -static lv_style_t bar_bg, bar_indic; +static lv_style_t bar_indic; #endif #if LV_USE_SLIDER -static lv_style_t slider_knob; +static lv_style_t knob; #endif #if LV_USE_LMETER @@ -52,10 +50,6 @@ static lv_style_t lmeter_bg; static lv_style_t ddlist_bg, ddlist_sel; #endif -#if LV_USE_BTNM -static lv_style_t btnm_bg, btnm_rel, btnm_pr, btnm_trel, btnm_ina; -#endif - /********************** * MACROS **********************/ @@ -67,10 +61,9 @@ static lv_style_t btnm_bg, btnm_rel, btnm_pr, btnm_trel, btnm_ina; static void basic_init(void) { lv_style_init(&scr); - lv_style_set_color(&scr, LV_STYLE_BG_COLOR, LV_COLOR_MAKE(0xF0, 0x90, 0x20)); + lv_style_set_color(&scr, LV_STYLE_BG_COLOR, LV_COLOR_MAKE(0x20, 0x20, 0x20)); lv_style_set_color(&scr, LV_STYLE_TEXT_COLOR , LV_COLOR_WHITE); - lv_style_init(&transp); lv_style_set_value(&transp, LV_STYLE_BG_OPA, LV_OPA_TRANSP); lv_style_set_value(&transp, LV_STYLE_BORDER_WIDTH, 0); @@ -209,36 +202,12 @@ static void label_init(void) static void bar_init(void) { #if LV_USE_BAR - lv_style_copy(&bar_bg, &def); - bar_bg.body.opa = LV_OPA_30; - bar_bg.body.radius = LV_RADIUS_CIRCLE; - bar_bg.body.main_color = LV_COLOR_WHITE; - bar_bg.body.grad_color = LV_COLOR_SILVER; - bar_bg.body.border.width = 2; - bar_bg.body.border.color = LV_COLOR_SILVER; - bar_bg.body.border.opa = LV_OPA_20; - bar_bg.body.padding.left = 0; - bar_bg.body.padding.right = 0; - bar_bg.body.padding.top = LV_DPI / 10; - bar_bg.body.padding.bottom = LV_DPI / 10; - bar_bg.body.padding.inner = 0; - - lv_style_copy(&bar_indic, &def); - bar_indic.body.radius = LV_RADIUS_CIRCLE; - bar_indic.body.border.width = 2; - bar_indic.body.border.color = LV_COLOR_SILVER; - bar_indic.body.border.opa = LV_OPA_70; - bar_indic.body.padding.left = 0; - bar_indic.body.padding.right = 0; - bar_indic.body.padding.top = 0; - bar_indic.body.padding.bottom = 0; - bar_indic.body.shadow.width = LV_DPI / 20; - bar_indic.body.shadow.color = lv_color_hsv_to_rgb(_hue, 20, 90); - bar_indic.body.main_color = lv_color_hsv_to_rgb(_hue, 40, 80); - bar_indic.body.grad_color = lv_color_hsv_to_rgb(_hue, 40, 80); - - theme.style.bar.bg = &bar_bg; - theme.style.bar.indic = &bar_indic; + lv_style_init(&bar_indic); + lv_style_set_color(&bar_indic, LV_STYLE_BG_COLOR, LV_COLOR_BLUE); + lv_style_set_value(&bar_indic, LV_STYLE_PAD_TOP, LV_DPI/20); + lv_style_set_value(&bar_indic, LV_STYLE_PAD_BOTTOM, LV_DPI/20); + lv_style_set_value(&bar_indic, LV_STYLE_PAD_LEFT, LV_DPI/20); + lv_style_set_value(&bar_indic, LV_STYLE_PAD_RIGHT, LV_DPI/20); #endif } @@ -292,54 +261,20 @@ static void led_init(void) static void slider_init(void) { #if LV_USE_SLIDER != 0 - lv_style_copy(&slider_knob, &def); - slider_knob.body.opa = LV_OPA_60; - slider_knob.body.radius = LV_RADIUS_CIRCLE; - slider_knob.body.main_color = LV_COLOR_WHITE; - slider_knob.body.grad_color = LV_COLOR_SILVER; - slider_knob.body.border.width = 1; - slider_knob.body.border.color = LV_COLOR_GRAY; - slider_knob.body.border.opa = LV_OPA_50; - slider_knob.body.padding.left = LV_DPI/25; - slider_knob.body.padding.right = LV_DPI/25; - slider_knob.body.padding.top = LV_DPI/25; - slider_knob.body.padding.bottom = LV_DPI/25; + lv_style_init(&knob); + lv_style_set_color(&knob, LV_STYLE_BG_COLOR, LV_COLOR_RED); + lv_style_set_value(&knob, LV_STYLE_PAD_TOP, LV_DPI/20); + lv_style_set_value(&knob, LV_STYLE_PAD_BOTTOM, LV_DPI/20); + lv_style_set_value(&knob, LV_STYLE_PAD_LEFT, LV_DPI/20); + lv_style_set_value(&knob, LV_STYLE_PAD_RIGHT, LV_DPI/20); - theme.style.slider.bg = &bar_bg; - theme.style.slider.indic = &bar_indic; - theme.style.slider.knob = &slider_knob; #endif } static void sw_init(void) { #if LV_USE_SW != 0 - static lv_style_t sw_bg, sw_indic, sw_knob; - lv_style_copy(&sw_bg, &bar_bg); - sw_bg.body.opa = LV_OPA_COVER; - sw_bg.body.padding.left = -2; - sw_bg.body.padding.right = -2; - sw_bg.body.padding.top = -2; - sw_bg.body.padding.bottom = -2; - sw_bg.body.main_color = lv_color_hex3(0x666); - sw_bg.body.grad_color = lv_color_hex3(0x999); - sw_bg.body.border.width = 2; - sw_bg.body.border.opa = LV_OPA_50; - lv_style_copy(&sw_indic, &bar_indic); - sw_indic.body.shadow.width = LV_DPI / 20; - sw_indic.body.padding.left = 0; - sw_indic.body.padding.right = 0; - sw_indic.body.padding.top = 0; - sw_indic.body.padding.bottom = 0; - - lv_style_copy(&sw_knob, &slider_knob); - sw_knob.body.opa = LV_OPA_80; - - theme.style.sw.bg = &sw_bg; - theme.style.sw.indic = &sw_indic; - theme.style.sw.knob_off = &sw_knob; - theme.style.sw.knob_on = &sw_knob; #endif } @@ -879,10 +814,22 @@ lv_style_t * lv_theme_alien_get_style(lv_theme_style_t name) return &transp; case LV_THEME_PANEL: return &panel; + case LV_THEME_BTN: + return &btn; case LV_THEME_BTNM: return &panel; case LV_THEME_BTNM_BTN: return &btn; + case LV_THEME_BAR: + return &panel; + case LV_THEME_BAR_INDIC: + return &bar_indic; + case LV_THEME_SLIDER: + return &panel; + case LV_THEME_SLIDER_INDIC: + return &bar_indic; + case LV_THEME_SLIDER_KNOB: + return &knob; } return NULL;