From bcb8dbb736ed4904a57da67740a74208875d4461 Mon Sep 17 00:00:00 2001 From: Gabor Kiss-Vamosi Date: Tue, 26 Mar 2024 10:28:09 +0100 Subject: [PATCH] feat(mask): add support for image file bitmap masks (#5911) --- scripts/style_api_gen.py | 2 +- src/core/lv_obj_style_gen.c | 5 ++- src/core/lv_obj_style_gen.h | 27 +++++++----- src/draw/sw/lv_draw_sw_img.c | 38 ++++++++++++----- src/misc/lv_style_gen.c | 2 +- src/misc/lv_style_gen.h | 2 +- .../draw_layer_bitmap_mask_not_masked.png | Bin 0 -> 15888 bytes tests/src/test_cases/draw/test_draw_layer.c | 39 +++++++++++++++++- 8 files changed, 87 insertions(+), 28 deletions(-) create mode 100644 tests/ref_imgs/draw/draw_layer_bitmap_mask_not_masked.png diff --git a/scripts/style_api_gen.py b/scripts/style_api_gen.py index fdf11a83f..91688a88f 100755 --- a/scripts/style_api_gen.py +++ b/scripts/style_api_gen.py @@ -390,7 +390,7 @@ props = [ 'dsc': "Set the base direction of the object. The possible values are `LV_BIDI_DIR_LTR/RTL/AUTO`."}, {'name': 'BITMAP_MASK_SRC', - 'style_type': 'ptr', 'var_type': 'const lv_image_dsc_t *', 'default':'`NULL`', 'inherited': 0, 'layout': 0, 'ext_draw': 0, + 'style_type': 'ptr', 'var_type': 'const void *', 'default':'`NULL`', 'inherited': 0, 'layout': 0, 'ext_draw': 0, 'dsc': "If set a layer will be created for the widget and the layer will be masked with this A8 bitmap mask."}, {'name': 'ROTARY_SENSITIVITY', diff --git a/src/core/lv_obj_style_gen.c b/src/core/lv_obj_style_gen.c index f9b21e807..22862ae01 100644 --- a/src/core/lv_obj_style_gen.c +++ b/src/core/lv_obj_style_gen.c @@ -690,7 +690,8 @@ void lv_obj_set_style_opa_layered(lv_obj_t * obj, lv_opa_t value, lv_style_selec lv_obj_set_local_style_prop(obj, LV_STYLE_OPA_LAYERED, v, selector); } -void lv_obj_set_style_color_filter_dsc(lv_obj_t * obj, const lv_color_filter_dsc_t * value, lv_style_selector_t selector) +void lv_obj_set_style_color_filter_dsc(lv_obj_t * obj, const lv_color_filter_dsc_t * value, + lv_style_selector_t selector) { lv_style_value_t v = { .ptr = value @@ -754,7 +755,7 @@ void lv_obj_set_style_base_dir(lv_obj_t * obj, lv_base_dir_t value, lv_style_sel lv_obj_set_local_style_prop(obj, LV_STYLE_BASE_DIR, v, selector); } -void lv_obj_set_style_bitmap_mask_src(lv_obj_t * obj, const lv_image_dsc_t * value, lv_style_selector_t selector) +void lv_obj_set_style_bitmap_mask_src(lv_obj_t * obj, const void * value, lv_style_selector_t selector) { lv_style_value_t v = { .ptr = value diff --git a/src/core/lv_obj_style_gen.h b/src/core/lv_obj_style_gen.h index c3bd10761..663e4046b 100644 --- a/src/core/lv_obj_style_gen.h +++ b/src/core/lv_obj_style_gen.h @@ -230,7 +230,8 @@ static inline lv_color_t lv_obj_get_style_bg_grad_color(const lv_obj_t * obj, ui static inline lv_color_t lv_obj_get_style_bg_grad_color_filtered(const lv_obj_t * obj, uint32_t part) { - lv_style_value_t v = _lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, LV_STYLE_BG_GRAD_COLOR)); + lv_style_value_t v = _lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, + LV_STYLE_BG_GRAD_COLOR)); return v.color; } @@ -290,7 +291,8 @@ static inline lv_color_t lv_obj_get_style_bg_image_recolor(const lv_obj_t * obj, static inline lv_color_t lv_obj_get_style_bg_image_recolor_filtered(const lv_obj_t * obj, uint32_t part) { - lv_style_value_t v = _lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, LV_STYLE_BG_IMAGE_RECOLOR)); + lv_style_value_t v = _lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, + LV_STYLE_BG_IMAGE_RECOLOR)); return v.color; } @@ -314,7 +316,8 @@ static inline lv_color_t lv_obj_get_style_border_color(const lv_obj_t * obj, uin static inline lv_color_t lv_obj_get_style_border_color_filtered(const lv_obj_t * obj, uint32_t part) { - lv_style_value_t v = _lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, LV_STYLE_BORDER_COLOR)); + lv_style_value_t v = _lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, + LV_STYLE_BORDER_COLOR)); return v.color; } @@ -356,7 +359,8 @@ static inline lv_color_t lv_obj_get_style_outline_color(const lv_obj_t * obj, ui static inline lv_color_t lv_obj_get_style_outline_color_filtered(const lv_obj_t * obj, uint32_t part) { - lv_style_value_t v = _lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, LV_STYLE_OUTLINE_COLOR)); + lv_style_value_t v = _lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, + LV_STYLE_OUTLINE_COLOR)); return v.color; } @@ -404,7 +408,8 @@ static inline lv_color_t lv_obj_get_style_shadow_color(const lv_obj_t * obj, uin static inline lv_color_t lv_obj_get_style_shadow_color_filtered(const lv_obj_t * obj, uint32_t part) { - lv_style_value_t v = _lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, LV_STYLE_SHADOW_COLOR)); + lv_style_value_t v = _lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, + LV_STYLE_SHADOW_COLOR)); return v.color; } @@ -428,7 +433,8 @@ static inline lv_color_t lv_obj_get_style_image_recolor(const lv_obj_t * obj, ui static inline lv_color_t lv_obj_get_style_image_recolor_filtered(const lv_obj_t * obj, uint32_t part) { - lv_style_value_t v = _lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, LV_STYLE_IMAGE_RECOLOR)); + lv_style_value_t v = _lv_obj_style_apply_color_filter(obj, part, lv_obj_get_style_prop(obj, part, + LV_STYLE_IMAGE_RECOLOR)); return v.color; } @@ -636,10 +642,10 @@ static inline lv_base_dir_t lv_obj_get_style_base_dir(const lv_obj_t * obj, uint return (lv_base_dir_t)v.num; } -static inline const lv_image_dsc_t * lv_obj_get_style_bitmap_mask_src(const lv_obj_t * obj, uint32_t part) +static inline const void * lv_obj_get_style_bitmap_mask_src(const lv_obj_t * obj, uint32_t part) { lv_style_value_t v = lv_obj_get_style_prop(obj, part, LV_STYLE_BITMAP_MASK_SRC); - return (const lv_image_dsc_t *)v.ptr; + return (const void *)v.ptr; } static inline uint32_t lv_obj_get_style_rotary_sensitivity(const lv_obj_t * obj, uint32_t part) @@ -829,7 +835,8 @@ void lv_obj_set_style_radius(lv_obj_t * obj, int32_t value, lv_style_selector_t void lv_obj_set_style_clip_corner(lv_obj_t * obj, bool value, lv_style_selector_t selector); void lv_obj_set_style_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector); void lv_obj_set_style_opa_layered(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector); -void lv_obj_set_style_color_filter_dsc(lv_obj_t * obj, const lv_color_filter_dsc_t * value, lv_style_selector_t selector); +void lv_obj_set_style_color_filter_dsc(lv_obj_t * obj, const lv_color_filter_dsc_t * value, + lv_style_selector_t selector); void lv_obj_set_style_color_filter_opa(lv_obj_t * obj, lv_opa_t value, lv_style_selector_t selector); void lv_obj_set_style_anim(lv_obj_t * obj, const lv_anim_t * value, lv_style_selector_t selector); void lv_obj_set_style_anim_duration(lv_obj_t * obj, uint32_t value, lv_style_selector_t selector); @@ -837,7 +844,7 @@ void lv_obj_set_style_transition(lv_obj_t * obj, const lv_style_transition_dsc_t void lv_obj_set_style_blend_mode(lv_obj_t * obj, lv_blend_mode_t value, lv_style_selector_t selector); void lv_obj_set_style_layout(lv_obj_t * obj, uint16_t value, lv_style_selector_t selector); void lv_obj_set_style_base_dir(lv_obj_t * obj, lv_base_dir_t value, lv_style_selector_t selector); -void lv_obj_set_style_bitmap_mask_src(lv_obj_t * obj, const lv_image_dsc_t * value, lv_style_selector_t selector); +void lv_obj_set_style_bitmap_mask_src(lv_obj_t * obj, const void * value, lv_style_selector_t selector); void lv_obj_set_style_rotary_sensitivity(lv_obj_t * obj, uint32_t value, lv_style_selector_t selector); #if LV_USE_FLEX void lv_obj_set_style_flex_flow(lv_obj_t * obj, lv_flex_flow_t value, lv_style_selector_t selector); diff --git a/src/draw/sw/lv_draw_sw_img.c b/src/draw/sw/lv_draw_sw_img.c index 2f6dcf34a..167cdeddc 100644 --- a/src/draw/sw/lv_draw_sw_img.c +++ b/src/draw/sw/lv_draw_sw_img.c @@ -236,22 +236,38 @@ static void img_draw_core(lv_draw_unit_t * draw_unit, const lv_draw_image_dsc_t } /*Handle masked RGB565, RGB888, XRGB888, or ARGB8888 images*/ else if(!transformed && masked && draw_dsc->recolor_opa <= LV_OPA_MIN) { + lv_image_decoder_dsc_t mask_decoder_dsc; + lv_area_t mask_area; + lv_result_t decoder_res = lv_image_decoder_open(&mask_decoder_dsc, draw_dsc->bitmap_mask_src, NULL); + if(decoder_res == LV_RESULT_OK && mask_decoder_dsc.decoded) { + if(mask_decoder_dsc.decoded->header.cf == LV_COLOR_FORMAT_A8) { + const lv_draw_buf_t * mask_img = mask_decoder_dsc.decoded; + blend_dsc.mask_buf = mask_img->data; + blend_dsc.mask_stride = mask_img->header.stride; + + const lv_area_t * original_area; + if(lv_area_get_width(&draw_dsc->original_area) < 0) original_area = img_coords; + else original_area = &draw_dsc->original_area; + lv_area_set(&mask_area, 0, 0, mask_img->header.w - 1, mask_img->header.h - 1); + lv_area_align(original_area, &mask_area, LV_ALIGN_CENTER, 0, 0); + blend_dsc.mask_area = &mask_area; + blend_dsc.mask_res = LV_DRAW_SW_MASK_RES_CHANGED; + } + else { + LV_LOG_WARN("The mask image doesn'thave A8 format. Drawing the image without mask."); + } + } + else { + LV_LOG_WARN("Couldn't decode the mask image. Drawing the image without mask."); + } + blend_dsc.src_area = img_coords; blend_dsc.src_buf = src_buf; blend_dsc.blend_area = img_coords; blend_dsc.src_color_format = cf; - blend_dsc.mask_buf = draw_dsc->bitmap_mask_src->data; - blend_dsc.mask_stride = draw_dsc->bitmap_mask_src->header.stride; - - const lv_area_t * original_area; - if(lv_area_get_width(&draw_dsc->original_area) < 0) original_area = img_coords; - else original_area = &draw_dsc->original_area; - - lv_area_t a = {0, 0, draw_dsc->bitmap_mask_src->header.w - 1, draw_dsc->bitmap_mask_src->header.h - 1}; - lv_area_align(original_area, &a, LV_ALIGN_CENTER, 0, 0); - blend_dsc.mask_area = &a; - blend_dsc.mask_res = LV_DRAW_SW_MASK_RES_CHANGED; lv_draw_sw_blend(draw_unit, &blend_dsc); + + if(decoder_res == LV_RESULT_OK) lv_image_decoder_close(&mask_decoder_dsc); } /* check whether it is possible to accelerate the operation in synchronouse mode */ else if(LV_RESULT_INVALID == LV_DRAW_SW_IMAGE(transformed, /* whether require transform */ diff --git a/src/misc/lv_style_gen.c b/src/misc/lv_style_gen.c index 297087534..3abeffea7 100644 --- a/src/misc/lv_style_gen.c +++ b/src/misc/lv_style_gen.c @@ -940,7 +940,7 @@ void lv_style_set_base_dir(lv_style_t * style, lv_base_dir_t value) const lv_style_prop_t _lv_style_const_prop_id_BASE_DIR = LV_STYLE_BASE_DIR; -void lv_style_set_bitmap_mask_src(lv_style_t * style, const lv_image_dsc_t * value) +void lv_style_set_bitmap_mask_src(lv_style_t * style, const void * value) { lv_style_value_t v = { .ptr = value diff --git a/src/misc/lv_style_gen.h b/src/misc/lv_style_gen.h index 7aed6b7e9..5bd9833ed 100644 --- a/src/misc/lv_style_gen.h +++ b/src/misc/lv_style_gen.h @@ -200,7 +200,7 @@ void lv_style_set_layout(lv_style_t * style, uint16_t value); LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_LAYOUT; void lv_style_set_base_dir(lv_style_t * style, lv_base_dir_t value); LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_BASE_DIR; -void lv_style_set_bitmap_mask_src(lv_style_t * style, const lv_image_dsc_t * value); +void lv_style_set_bitmap_mask_src(lv_style_t * style, const void * value); LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_BITMAP_MASK_SRC; void lv_style_set_rotary_sensitivity(lv_style_t * style, uint32_t value); LV_ATTRIBUTE_EXTERN_DATA extern const lv_style_prop_t _lv_style_const_prop_id_ROTARY_SENSITIVITY; diff --git a/tests/ref_imgs/draw/draw_layer_bitmap_mask_not_masked.png b/tests/ref_imgs/draw/draw_layer_bitmap_mask_not_masked.png new file mode 100644 index 0000000000000000000000000000000000000000..6c5a9b4c5b8be985aa58b487be4f0c600b71cfee GIT binary patch literal 15888 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