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 000000000..6c5a9b4c5 Binary files /dev/null and b/tests/ref_imgs/draw/draw_layer_bitmap_mask_not_masked.png differ diff --git a/tests/src/test_cases/draw/test_draw_layer.c b/tests/src/test_cases/draw/test_draw_layer.c index b1b1702ee..dff6ba70f 100644 --- a/tests/src/test_cases/draw/test_draw_layer.c +++ b/tests/src/test_cases/draw/test_draw_layer.c @@ -14,7 +14,7 @@ void tearDown(void) lv_obj_clean(lv_screen_active()); } -void test_draw_layer_bitmap_mask(void) +void test_draw_layer_bitmap_mask_from_variable(void) { LV_IMAGE_DECLARE(test_image_cogwheel_a8); @@ -31,7 +31,42 @@ void test_draw_layer_bitmap_mask(void) lv_obj_center(label); TEST_ASSERT_EQUAL_SCREENSHOT("draw/draw_layer_bitmap_mask.png"); - } +void test_draw_layer_bitmap_mask_from_image(void) +{ + lv_obj_t * obj = lv_obj_create(lv_screen_active()); + lv_obj_set_size(obj, 200, 200); + lv_obj_set_style_bg_color(obj, lv_color_hex3(0xf88), 0); + lv_obj_set_style_bitmap_mask_src(obj, "A:src/test_files/binimages/cogwheel.A8.bin", 0); + lv_obj_center(obj); + + lv_obj_t * label = lv_label_create(obj); + lv_obj_set_width(label, lv_pct(100)); + lv_label_set_text(label, + "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque suscipit risus nec pharetra pulvinar. In hac habitasse platea dictumst. Proin placerat congue massa eu luctus. Suspendisse risus nulla, consectetur eget odio ut, mollis sollicitudin magna. Suspendisse volutpat consequat laoreet. Aenean sodales suscipit leo, vitae pulvinar lorem pulvinar eu. Nullam molestie hendrerit est sit amet imperdiet."); + lv_obj_center(label); + + TEST_ASSERT_EQUAL_SCREENSHOT("draw/draw_layer_bitmap_mask.png"); +} + + +void test_draw_layer_bitmap_mask_from_image_not_found(void) +{ + lv_obj_t * obj = lv_obj_create(lv_screen_active()); + lv_obj_set_size(obj, 200, 200); + lv_obj_set_style_bg_color(obj, lv_color_hex3(0xf88), 0); + lv_obj_set_style_bitmap_mask_src(obj, "A:not/exisiting/file", 0); + lv_obj_center(obj); + + lv_obj_t * label = lv_label_create(obj); + lv_obj_set_width(label, lv_pct(100)); + lv_label_set_text(label, + "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque suscipit risus nec pharetra pulvinar. In hac habitasse platea dictumst. Proin placerat congue massa eu luctus. Suspendisse risus nulla, consectetur eget odio ut, mollis sollicitudin magna. Suspendisse volutpat consequat laoreet. Aenean sodales suscipit leo, vitae pulvinar lorem pulvinar eu. Nullam molestie hendrerit est sit amet imperdiet."); + lv_obj_center(label); + + TEST_ASSERT_EQUAL_SCREENSHOT("draw/draw_layer_bitmap_mask_not_masked.png"); +} + + #endif