diff --git a/src/core/lv_obj.c b/src/core/lv_obj.c index 767e51db4c..738f2984c5 100644 --- a/src/core/lv_obj.c +++ b/src/core/lv_obj.c @@ -518,11 +518,14 @@ static void lv_obj_draw(lv_event_t * e) #if LV_DRAW_COMPLEX if(lv_obj_get_style_clip_corner(obj, LV_PART_MAIN)) { - lv_draw_mask_radius_param_t * mp = lv_mem_buf_get(sizeof(lv_draw_mask_radius_param_t)); + /*If the radius is 0 the parent's coordinates will clip anyway*/ lv_coord_t r = lv_obj_get_style_radius(obj, LV_PART_MAIN); - lv_draw_mask_radius_init(mp, &obj->coords, r, false); - /*Add the mask and use `obj+8` as custom id. Don't use `obj` directly because it might be used by the user*/ - lv_draw_mask_add(mp, obj + 8); + if(r != 0) { + lv_draw_mask_radius_param_t * mp = lv_mem_buf_get(sizeof(lv_draw_mask_radius_param_t)); + lv_draw_mask_radius_init(mp, &obj->coords, r, false); + /*Add the mask and use `obj+8` as custom id. Don't use `obj` directly because it might be used by the user*/ + lv_draw_mask_add(mp, obj + 8); + } } #endif } @@ -533,8 +536,10 @@ static void lv_obj_draw(lv_event_t * e) #if LV_DRAW_COMPLEX if(lv_obj_get_style_clip_corner(obj, LV_PART_MAIN)) { lv_draw_mask_radius_param_t * param = lv_draw_mask_remove_custom(obj + 8); - lv_draw_mask_free_param(param); - lv_mem_buf_release(param); + if(param) { + lv_draw_mask_free_param(param); + lv_mem_buf_release(param); + } } #endif @@ -556,7 +561,6 @@ static void lv_obj_draw(lv_event_t * e) coords.y1 -= h; coords.y2 += h; - lv_obj_draw_part_dsc_t part_dsc; lv_obj_draw_dsc_init(&part_dsc, clip_area); part_dsc.class_p = MY_CLASS; diff --git a/src/draw/lv_draw_img.c b/src/draw/lv_draw_img.c index ec5799e578..593c0ecb1a 100644 --- a/src/draw/lv_draw_img.c +++ b/src/draw/lv_draw_img.c @@ -353,10 +353,10 @@ LV_ATTRIBUTE_FAST_MEM static void lv_draw_map(const lv_area_t * map_area, const draw_area.x2 -= disp_area->x1; draw_area.y2 -= disp_area->y1; - uint8_t other_mask_cnt = lv_draw_mask_get_cnt(); + bool mask_any = lv_draw_mask_is_any(map_area); /*The simplest case just copy the pixels into the draw_buf*/ - if(other_mask_cnt == 0 && draw_dsc->angle == 0 && draw_dsc->zoom == LV_IMG_ZOOM_NONE && + if(!mask_any && draw_dsc->angle == 0 && draw_dsc->zoom == LV_IMG_ZOOM_NONE && chroma_key == false && alpha_byte == false && draw_dsc->recolor_opa == LV_OPA_TRANSP) { _lv_blend_map(clip_area, map_area, (lv_color_t *)map_p, NULL, LV_DRAW_MASK_RES_FULL_COVER, draw_dsc->opa, draw_dsc->blend_mode); @@ -364,14 +364,14 @@ LV_ATTRIBUTE_FAST_MEM static void lv_draw_map(const lv_area_t * map_area, const #if LV_USE_GPU_NXP_PXP /*Simple case without masking and transformations*/ - else if(other_mask_cnt == 0 && draw_dsc->angle == 0 && draw_dsc->zoom == LV_IMG_ZOOM_NONE && alpha_byte == false && + else if(!mask_any && draw_dsc->angle == 0 && draw_dsc->zoom == LV_IMG_ZOOM_NONE && alpha_byte == false && chroma_key == true && draw_dsc->recolor_opa == LV_OPA_TRANSP) { /*copy with color keying (+ alpha)*/ lv_gpu_nxp_pxp_enable_color_key(); _lv_blend_map(clip_area, map_area, (lv_color_t *)map_p, NULL, LV_DRAW_MASK_RES_FULL_COVER, draw_dsc->opa, draw_dsc->blend_mode); lv_gpu_nxp_pxp_disable_color_key(); } - else if(other_mask_cnt == 0 && draw_dsc->angle == 0 && draw_dsc->zoom == LV_IMG_ZOOM_NONE && alpha_byte == false && + else if(!mask_any && draw_dsc->angle == 0 && draw_dsc->zoom == LV_IMG_ZOOM_NONE && alpha_byte == false && chroma_key == false && draw_dsc->recolor_opa != LV_OPA_TRANSP) { /*copy with recolor (+ alpha)*/ lv_gpu_nxp_pxp_enable_recolor(draw_dsc->recolor, draw_dsc->recolor_opa); _lv_blend_map(clip_area, map_area, (lv_color_t *)map_p, NULL, LV_DRAW_MASK_RES_FULL_COVER, draw_dsc->opa, @@ -408,7 +408,7 @@ LV_ATTRIBUTE_FAST_MEM static void lv_draw_map(const lv_area_t * map_area, const bool transform = draw_dsc->angle != 0 || draw_dsc->zoom != LV_IMG_ZOOM_NONE ? true : false; /*Simple ARGB image. Handle it as special case because it's very common*/ - if(other_mask_cnt == 0 && !transform && !chroma_key && draw_dsc->recolor_opa == LV_OPA_TRANSP && alpha_byte) { + if(!mask_any && !transform && !chroma_key && draw_dsc->recolor_opa == LV_OPA_TRANSP && alpha_byte) { #if LV_USE_GPU_STM32_DMA2D && LV_COLOR_DEPTH == 32 /*Blend ARGB images directly*/ if(lv_area_get_size(&draw_area) > 240) { @@ -509,7 +509,7 @@ LV_ATTRIBUTE_FAST_MEM static void lv_draw_map(const lv_area_t * map_area, const draw_dsc->zoom != LV_IMG_ZOOM_NONE) ? LV_DRAW_MASK_RES_CHANGED : LV_DRAW_MASK_RES_FULL_COVER; /*Prepare the `mask_buf`if there are other masks*/ - if(other_mask_cnt) { + if(mask_any) { lv_memset_ff(mask_buf, mask_buf_size); } @@ -589,7 +589,7 @@ LV_ATTRIBUTE_FAST_MEM static void lv_draw_map(const lv_area_t * map_area, const } #if LV_DRAW_COMPLEX /*Apply the masks if any*/ - if(other_mask_cnt) { + if(mask_any) { lv_draw_mask_res_t mask_res_sub; mask_res_sub = lv_draw_mask_apply(mask_buf + px_i_start, draw_area.x1 + draw_buf->area.x1, y + draw_area.y1 + draw_buf->area.y1, lv_area_get_width(&draw_area)); @@ -619,7 +619,7 @@ LV_ATTRIBUTE_FAST_MEM static void lv_draw_map(const lv_area_t * map_area, const draw_dsc->zoom != LV_IMG_ZOOM_NONE) ? LV_DRAW_MASK_RES_CHANGED : LV_DRAW_MASK_RES_FULL_COVER; /*Prepare the `mask_buf`if there are other masks*/ - if(other_mask_cnt) { + if(mask_any) { lv_memset_ff(mask_buf, mask_buf_size); } } diff --git a/src/draw/lv_draw_label.c b/src/draw/lv_draw_label.c index c915dd864d..73dea7dea4 100644 --- a/src/draw/lv_draw_label.c +++ b/src/draw/lv_draw_label.c @@ -539,7 +539,7 @@ LV_ATTRIBUTE_FAST_MEM static void draw_letter_normal(lv_coord_t pos_x, lv_coord_ fill_area.y1 = row_start + pos_y; fill_area.y2 = fill_area.y1; #if LV_DRAW_COMPLEX - uint8_t other_mask_cnt = lv_draw_mask_get_cnt(); + bool mask_any = lv_draw_mask_is_any(&fill_area); #endif uint32_t col_bit_max = 8 - bpp; @@ -577,7 +577,7 @@ LV_ATTRIBUTE_FAST_MEM static void draw_letter_normal(lv_coord_t pos_x, lv_coord_ #if LV_DRAW_COMPLEX /*Apply masks if any*/ - if(other_mask_cnt) { + if(mask_any) { lv_draw_mask_res_t mask_res = lv_draw_mask_apply(mask_buf + mask_p_start, fill_area.x1, fill_area.y2, lv_area_get_width(&fill_area)); if(mask_res == LV_DRAW_MASK_RES_TRANSP) { @@ -695,8 +695,7 @@ static void draw_letter_subpx(lv_coord_t pos_x, lv_coord_t pos_y, lv_font_glyph_ /*If the letter is partially out of mask the move there on draw_buf*/ disp_buf_buf_tmp += (row_start * disp_buf_width) + col_start / 3; - uint8_t other_mask_cnt = lv_draw_mask_get_cnt(); - + bool mask_any = lv_draw_mask_is_any(&map_area); uint8_t font_rgb[3]; #if LV_COLOR_16_SWAP == 0 @@ -784,7 +783,7 @@ static void draw_letter_subpx(lv_coord_t pos_x, lv_coord_t pos_y, lv_font_glyph_ } /*Apply masks if any*/ - if(other_mask_cnt) { + if(mask_any) { lv_draw_mask_res_t mask_res = lv_draw_mask_apply(mask_buf + mask_p_start, map_area.x1, map_area.y2, lv_area_get_width(&map_area)); if(mask_res == LV_DRAW_MASK_RES_TRANSP) { diff --git a/src/draw/lv_draw_line.c b/src/draw/lv_draw_line.c index 50150d1a95..a0eb4c1737 100644 --- a/src/draw/lv_draw_line.c +++ b/src/draw/lv_draw_line.c @@ -127,11 +127,7 @@ LV_ATTRIBUTE_FAST_MEM static void draw_line_hor(const lv_point_t * point1, const int32_t w_half0 = w >> 1; int32_t w_half1 = w_half0 + (w & 0x1); /*Compensate rounding error*/ - bool dashed = dsc->dash_gap && dsc->dash_width ? true : false; - bool simple_mode = true; - if(lv_draw_mask_get_cnt()) simple_mode = false; - else if(dashed) simple_mode = false; lv_area_t draw_area; draw_area.x1 = LV_MIN(point1->x, point2->x); @@ -139,6 +135,11 @@ LV_ATTRIBUTE_FAST_MEM static void draw_line_hor(const lv_point_t * point1, const draw_area.y1 = point1->y - w_half1; draw_area.y2 = point1->y + w_half0; + bool dashed = dsc->dash_gap && dsc->dash_width ? true : false; + bool simple_mode = true; + if(lv_draw_mask_is_any(&draw_area)) simple_mode = false; + else if(dashed) simple_mode = false; + /*If there is no mask then simply draw a rectangle*/ if(simple_mode) { _lv_blend_fill(clip, &draw_area, @@ -227,18 +228,17 @@ LV_ATTRIBUTE_FAST_MEM static void draw_line_ver(const lv_point_t * point1, const int32_t w_half0 = w >> 1; int32_t w_half1 = w_half0 + (w & 0x1); /*Compensate rounding error*/ - bool dashed = dsc->dash_gap && dsc->dash_width ? true : false; - - bool simple_mode = true; - if(lv_draw_mask_get_cnt()) simple_mode = false; - else if(dashed) simple_mode = false; - lv_area_t draw_area; draw_area.x1 = point1->x - w_half1; draw_area.x2 = point1->x + w_half0; draw_area.y1 = LV_MIN(point1->y, point2->y); draw_area.y2 = LV_MAX(point1->y, point2->y) - 1; + bool dashed = dsc->dash_gap && dsc->dash_width ? true : false; + bool simple_mode = true; + if(lv_draw_mask_is_any(&draw_area)) simple_mode = false; + else if(dashed) simple_mode = false; + /*If there is no mask then simply draw a rectangle*/ if(simple_mode) { _lv_blend_fill(clip, &draw_area, diff --git a/src/draw/lv_draw_mask.c b/src/draw/lv_draw_mask.c index 800c37a004..d638ea6ccf 100644 --- a/src/draw/lv_draw_mask.c +++ b/src/draw/lv_draw_mask.c @@ -211,9 +211,29 @@ LV_ATTRIBUTE_FAST_MEM uint8_t lv_draw_mask_get_cnt(void) return cnt; } -bool lv_draw_mask_is_any(void) +bool lv_draw_mask_is_any(const lv_area_t * a) { - return LV_GC_ROOT(_lv_draw_mask_list[0]).param ? true : false; + if(a == NULL) return LV_GC_ROOT(_lv_draw_mask_list[0]).param ? true : false; + + uint8_t i; + for(i = 0; i < _LV_MASK_MAX_NUM; i++) { + _lv_draw_mask_common_dsc_t * comm_param = LV_GC_ROOT(_lv_draw_mask_list[i]).param; + if(comm_param == NULL) continue; + if(comm_param->type == LV_DRAW_MASK_TYPE_RADIUS) { + lv_draw_mask_radius_param_t * radius_param = LV_GC_ROOT(_lv_draw_mask_list[i]).param; + if(radius_param->cfg.outer) { + if(!_lv_area_is_out(a, &radius_param->cfg.rect, radius_param->cfg.radius)) return true; + } + else { + if(!_lv_area_is_in(a, &radius_param->cfg.rect, radius_param->cfg.radius)) return true; + } + } else { + return true; + } + } + + return false; + } /** diff --git a/src/draw/lv_draw_mask.h b/src/draw/lv_draw_mask.h index 4cf36f04f2..c55c50a5df 100644 --- a/src/draw/lv_draw_mask.h +++ b/src/draw/lv_draw_mask.h @@ -55,11 +55,14 @@ typedef _lv_draw_mask_saved_t _lv_draw_mask_saved_arr_t[_LV_MASK_MAX_NUM]; #if LV_DRAW_COMPLEX == 0 -static inline uint8_t lv_draw_mask_get_cnt(void) { +static inline uint8_t lv_draw_mask_get_cnt(void) +{ return 0; } -static inline bool lv_draw_mask_is_any(void) { +static inline bool lv_draw_mask_is_any(const lv_area_t * a) +{ + LV_UNUSED(a); return false; } @@ -277,9 +280,10 @@ LV_ATTRIBUTE_FAST_MEM uint8_t lv_draw_mask_get_cnt(void); /** * Check is there is any added draw mask + * @param a an area to test for affecting masks. * @return true: there is t least 1 draw mask; false: there are no draw masks */ -bool lv_draw_mask_is_any(void); +bool lv_draw_mask_is_any(const lv_area_t * a); //! @endcond diff --git a/src/draw/lv_draw_rect.c b/src/draw/lv_draw_rect.c index aa4d8fe0aa..fe2e581d92 100644 --- a/src/draw/lv_draw_rect.c +++ b/src/draw/lv_draw_rect.c @@ -136,7 +136,7 @@ LV_ATTRIBUTE_FAST_MEM static void draw_bg(const lv_area_t * coords, const lv_are lv_grad_dir_t grad_dir = dsc->bg_grad_dir; if(dsc->bg_color.full == dsc->bg_grad_color.full) grad_dir = LV_GRAD_DIR_NONE; - bool mask_any = lv_draw_mask_is_any(); + bool mask_any = lv_draw_mask_is_any(&coords_bg); /*Most simple case: just a plain rectangle*/ if(!mask_any && dsc->radius == 0 && (grad_dir == LV_GRAD_DIR_NONE)) { @@ -497,7 +497,7 @@ LV_ATTRIBUTE_FAST_MEM static void draw_shadow(const lv_area_t * coords, const lv /*Skip a lot of masking if the background will cover the shadow that would be masked out*/ - bool mask_any = lv_draw_mask_is_any(); + bool mask_any = lv_draw_mask_is_any(&shadow_area); bool simple = true; if(mask_any || dsc->bg_opa < LV_OPA_COVER) simple = false; @@ -1083,7 +1083,7 @@ void draw_border_generic(const lv_area_t * clip_area, const lv_area_t * outer_ar if(!_lv_area_intersect(&draw_area, outer_area, clip_area)) return; int32_t draw_area_w = lv_area_get_width(&draw_area); - bool mask_any = lv_draw_mask_is_any(); + bool mask_any = lv_draw_mask_is_any(outer_area); /*Create a mask if there is a radius*/ lv_opa_t * mask_buf = lv_mem_buf_get(draw_area_w);