From 8d55a19666cd283e8180f887b24c40c942d50a2c Mon Sep 17 00:00:00 2001 From: hojoon-ryou Date: Wed, 11 Jun 2025 16:58:55 +0900 Subject: [PATCH] e_blur: add shadow layer Change-Id: I1530a3750c1dc07749b5dd9157f1bb0e6a7f03c3 --- src/bin/server/e_blur.c | 216 ++++++++++++++++++++++++++++++++++++---- src/include/e_blur.h | 16 +++ 2 files changed, 214 insertions(+), 18 deletions(-) diff --git a/src/bin/server/e_blur.c b/src/bin/server/e_blur.c index 9b7c1acc56..1d362b3937 100644 --- a/src/bin/server/e_blur.c +++ b/src/bin/server/e_blur.c @@ -43,6 +43,7 @@ struct _E_Blur_Manager struct { E_Blur_Dim_Config *dim_config; E_Blur_Stroke_Config *stroke_config; + E_Blur_Shadow_Config *shadow_config; } configs; }; @@ -86,6 +87,7 @@ struct _E_Blur_Rectangle E_View_Image *view_image; E_View_Rect *dim_rect; E_View_Image *stroke_image; + E_View_Image *shadow_image; E_View_Image *corner_radius_image; }; @@ -130,13 +132,15 @@ static Eina_Bool blur_trace = EINA_FALSE; static void _e_blur_ec_set(E_Blur *blur, E_Client *ec); static void _e_blur_behind_ec_set(E_Blur_Behind *blur, E_Client *ec); -static void _e_blur_rectangle_view_image_new(E_Blur_Rectangle *blur_rectangle, E_View_Tree *layer_tree, const char *name); +static void _e_blur_rectangle_view_image_new(E_Blur_Rectangle *blur_rectangle, E_View_Tree *view_tree, const char *name); static void _e_blur_rectangle_view_image_free(E_Blur_Rectangle *blur_rectangle); -static void _e_blur_rectangle_dim_rect_new(E_Blur_Rectangle *blur_rectangle, E_View_Tree *layer_tree, const char *name); +static void _e_blur_rectangle_dim_rect_new(E_Blur_Rectangle *blur_rectangle, E_View_Tree *view_tree, const char *name); static void _e_blur_rectangle_dim_rect_free(E_Blur_Rectangle *blur_rectangle); -static void _e_blur_rectangle_stroke_image_new(E_Blur_Rectangle *blur_rectangle, E_View_Tree *layer_tree, const char *name); +static void _e_blur_rectangle_stroke_image_new(E_Blur_Rectangle *blur_rectangle, E_View_Tree *view_tree, const char *name); static void _e_blur_rectangle_stroke_image_free(E_Blur_Rectangle *blur_rectangle); -static void _e_blur_rectangle_corner_radius_image_new(E_Blur_Rectangle *blur_rectangle, E_View_Tree *layer_tree, const char *name); +static void _e_blur_rectangle_shadow_image_new(E_Blur_Rectangle *blur_rectangle, E_View_Tree *view_tree, const char *name); +static void _e_blur_rectangle_shadow_image_free(E_Blur_Rectangle *blur_rectangle); +static void _e_blur_rectangle_corner_radius_image_new(E_Blur_Rectangle *blur_rectangle, E_View_Tree *view_tree, const char *name); static void _e_blur_rectangle_corner_radius_image_free(E_Blur_Rectangle *blur_rectangle); static void @@ -251,6 +255,9 @@ _e_blur_rectangle_show(E_Blur_Rectangle *blur_rectangle) if (blur_rectangle->stroke_image) e_view_show(e_view_image_view_get(blur_rectangle->stroke_image)); + if (blur_rectangle->shadow_image) + e_view_show(e_view_image_view_get(blur_rectangle->shadow_image)); + if (blur_rectangle->corner_radius_image) e_view_show(e_view_image_view_get(blur_rectangle->corner_radius_image)); } @@ -266,6 +273,9 @@ _e_blur_rectangle_hide(E_Blur_Rectangle *blur_rectangle) if (blur_rectangle->stroke_image) e_view_hide(e_view_image_view_get(blur_rectangle->stroke_image)); + if (blur_rectangle->shadow_image) + e_view_hide(e_view_image_view_get(blur_rectangle->shadow_image)); + if (blur_rectangle->corner_radius_image) e_view_hide(e_view_image_view_get(blur_rectangle->corner_radius_image)); } @@ -280,6 +290,7 @@ _e_blur_rectangle_free(E_Blur_Rectangle *blur_rectangle) _e_blur_rectangle_view_image_free(blur_rectangle); _e_blur_rectangle_dim_rect_free(blur_rectangle); _e_blur_rectangle_stroke_image_free(blur_rectangle); + _e_blur_rectangle_shadow_image_free(blur_rectangle); _e_blur_rectangle_corner_radius_image_free(blur_rectangle); if (blur_rectangle->listener.destroy.notify) @@ -364,6 +375,18 @@ _e_blur_rectangle_geometry_set(E_Blur_Rectangle *blur_rectangle, E_Client *ec) final_h + thickness * 2); } + if (blur_rectangle->shadow_image) + { + int offsetX = _blur_manager->configs.shadow_config->offsetX; + int offsetY = _blur_manager->configs.shadow_config->offsetY; + int radius = _blur_manager->configs.shadow_config->blur_radius; + e_view_image_geometry_set(blur_rectangle->shadow_image, + final_x + offsetX - radius, + final_y + offsetY - radius, + final_w + radius * 2, + final_h + radius * 2); + } + if (blur_rectangle->corner_radius_image) e_view_image_geometry_set(blur_rectangle->corner_radius_image, final_x, final_y, final_w, final_h); @@ -391,6 +414,19 @@ _e_blur_rectangle_filter_set(E_Blur_Rectangle *blur_rectangle) } } + if (blur_rectangle->shadow_image) + { + E_Blur_Shadow_Config *config = _blur_manager->configs.shadow_config; + int radius = config->blur_radius; + if (blur_rectangle->corner_radius_image) // works only rx == ry + snprintf(program, sizeof(program), "a = buffer{ 'rgba' } grow { %d, dst = a } blur { %d, src = a, color = color (%d, %d, %d, %d) }", + blur_rectangle->rx, radius, config->color.r, config->color.g, config->color.b, config->color.a); + else + snprintf(program, sizeof(program), "blur { %d, color = color (%d, %d, %d, %d) }", + radius, config->color.r, config->color.g, config->color.b, config->color.a); + e_view_image_gfx_filter_program_set(blur_rectangle->shadow_image, program, "shadow_blur"); + } + snprintf(program, sizeof(program), "blur (%d) padding_set (0)", blur_rectangle->blur->radius); @@ -541,6 +577,13 @@ _e_blur_cb_restack(struct wl_listener *listener, void *data) e_view_place_below(stroke_view, img_view); } + if (blur_rectangle->shadow_image) + { + E_View *shadow_view = e_view_image_view_get(blur_rectangle->shadow_image); + e_view_reparent(shadow_view, view_tree); + e_view_place_below(shadow_view, img_view); + } + if (blur_rectangle->corner_radius_image) { E_View *corner_img_view = e_view_image_view_get(blur_rectangle->corner_radius_image); @@ -644,14 +687,14 @@ _e_blur_rectangle_cb_ds_tizen_blur_rectangle_destroy(struct wl_listener *listene } static void -_e_blur_rectangle_view_image_new(E_Blur_Rectangle *blur_rectangle, E_View_Tree *layer_tree, const char *name) +_e_blur_rectangle_view_image_new(E_Blur_Rectangle *blur_rectangle, E_View_Tree *view_tree, const char *name) { E_View_Image *view_image = NULL; E_View *img_view = NULL; - EINA_SAFETY_ON_NULL_RETURN(layer_tree); + EINA_SAFETY_ON_NULL_RETURN(view_tree); - view_image = e_view_image_filled_create(layer_tree); + view_image = e_view_image_filled_create(view_tree); EINA_SAFETY_ON_NULL_RETURN(view_image); e_view_image_snapshot_set(view_image, true); @@ -672,20 +715,20 @@ _e_blur_rectangle_view_image_free(E_Blur_Rectangle *blur_rectangle) } static void -_e_blur_rectangle_dim_rect_new(E_Blur_Rectangle *blur_rectangle, E_View_Tree *layer_tree, const char *name) +_e_blur_rectangle_dim_rect_new(E_Blur_Rectangle *blur_rectangle, E_View_Tree *view_tree, const char *name) { E_View_Rect *dim_rect = NULL; E_View *dim_view = NULL; int dim_color[4]; - EINA_SAFETY_ON_NULL_RETURN(layer_tree); + EINA_SAFETY_ON_NULL_RETURN(view_tree); EINA_SAFETY_ON_NULL_RETURN(_blur_manager->configs.dim_config); dim_color[0] = _blur_manager->configs.dim_config->color.r; dim_color[1] = _blur_manager->configs.dim_config->color.g; dim_color[2] = _blur_manager->configs.dim_config->color.b; dim_color[3] = _blur_manager->configs.dim_config->color.a; - dim_rect = e_view_rect_create(layer_tree, 1, 1, dim_color); + dim_rect = e_view_rect_create(view_tree, 1, 1, dim_color); EINA_SAFETY_ON_NULL_RETURN(dim_rect); dim_view = e_view_rect_view_get(dim_rect); @@ -705,16 +748,16 @@ _e_blur_rectangle_dim_rect_free(E_Blur_Rectangle *blur_rectangle) } static void -_e_blur_rectangle_stroke_image_new(E_Blur_Rectangle *blur_rectangle, E_View_Tree *layer_tree, const char *name) +_e_blur_rectangle_stroke_image_new(E_Blur_Rectangle *blur_rectangle, E_View_Tree *view_tree, const char *name) { E_View_Image *stroke_image = NULL; E_View *stroke_view = NULL; unsigned int *pixels = NULL, A, R, G, B; - EINA_SAFETY_ON_NULL_RETURN(layer_tree); + EINA_SAFETY_ON_NULL_RETURN(view_tree); EINA_SAFETY_ON_NULL_RETURN(_blur_manager->configs.stroke_config); - stroke_image = e_view_image_filled_create(layer_tree); + stroke_image = e_view_image_filled_create(view_tree); EINA_SAFETY_ON_NULL_RETURN(stroke_image); stroke_view = e_view_image_view_get(stroke_image); @@ -749,15 +792,56 @@ _e_blur_rectangle_stroke_image_free(E_Blur_Rectangle *blur_rectangle) } static void -_e_blur_rectangle_corner_radius_image_new(E_Blur_Rectangle *blur_rectangle, E_View_Tree *layer_tree, const char *name) +_e_blur_rectangle_shadow_image_new(E_Blur_Rectangle *blur_rectangle, E_View_Tree *view_tree, const char *name) +{ + E_View_Image *shadow_image = NULL; + E_View *shadow_view = NULL; + unsigned int *pixels = NULL; + + EINA_SAFETY_ON_NULL_RETURN(view_tree); + EINA_SAFETY_ON_NULL_RETURN(_blur_manager->configs.shadow_config); + + shadow_image = e_view_image_filled_create(view_tree); + EINA_SAFETY_ON_NULL_RETURN(shadow_image); + shadow_view = e_view_image_view_get(shadow_image); + + e_view_image_size_set(shadow_image, 1, 1); + e_view_image_alpha_set(shadow_image, true); + pixels = e_view_image_data_get(shadow_image, true); + if (!pixels) + { + e_view_destroy(shadow_view); + return; + } + *pixels = 0xffffffff; + e_view_image_data_set(shadow_image, pixels); + e_view_image_data_update_add(shadow_image, 0, 0, 1, 1); + + e_view_name_set(shadow_view, name); + e_view_pass_events_set(shadow_view, true); + + blur_rectangle->shadow_image = shadow_image; +} + +static void +_e_blur_rectangle_shadow_image_free(E_Blur_Rectangle *blur_rectangle) +{ + EINA_SAFETY_ON_NULL_RETURN(blur_rectangle); + EINA_SAFETY_ON_NULL_RETURN(blur_rectangle->shadow_image); + e_view_destroy(e_view_image_view_get(blur_rectangle->shadow_image)); + blur_rectangle->shadow_image = NULL; +} + +static void +_e_blur_rectangle_corner_radius_image_new(E_Blur_Rectangle *blur_rectangle, E_View_Tree *view_tree, const char *name) { E_View_Image *corner_radius_image = NULL; E_View *corner_radius_view = NULL; unsigned int *pixels; - EINA_SAFETY_ON_NULL_RETURN(layer_tree); + EINA_SAFETY_ON_NULL_RETURN(view_tree); - corner_radius_image = e_view_image_filled_create(layer_tree); + corner_radius_image = e_view_image_filled_create(view_tree); EINA_SAFETY_ON_NULL_RETURN(corner_radius_image); corner_radius_view = e_view_image_view_get(corner_radius_image); @@ -792,7 +876,7 @@ _e_blur_cb_new_rectangle(struct wl_listener *listener, void *data) E_Blur *blur; E_Blur_Rectangle *blur_rectangle; struct ds_tizen_blur_rectangle *tizen_blur_rectangle = data; - E_View *dim_view = NULL, *img_view = NULL, *stroke_view = NULL, *corner_img_view = NULL; + E_View *dim_view = NULL, *img_view = NULL, *stroke_view = NULL, *shadow_view = NULL, *corner_img_view = NULL; E_View_Client *blur_view_client; E_View_Tree *blur_view_client_tree; E_Blur_Hook_Data hook_data; @@ -840,6 +924,13 @@ _e_blur_cb_new_rectangle(struct wl_listener *listener, void *data) stroke_view = e_view_image_view_get(blur_rectangle->stroke_image); } + if (_blur_manager->configs.shadow_config->enabled) + { + _e_blur_rectangle_shadow_image_new(blur_rectangle, blur_view_client_tree, "blur_shadow_obj"); + EINA_SAFETY_ON_NULL_GOTO(blur_rectangle->shadow_image, fail); + shadow_view = e_view_image_view_get(blur_rectangle->shadow_image); + } + if ((blur_rectangle->rx != 0) && (blur_rectangle->ry != 0)) { _e_blur_rectangle_corner_radius_image_new(blur_rectangle, blur_view_client_tree, "blur_corner_radius_image"); @@ -864,6 +955,8 @@ _e_blur_cb_new_rectangle(struct wl_listener *listener, void *data) e_view_place_above(dim_view, img_view); if (stroke_view) e_view_place_below(stroke_view, img_view); + if (shadow_view) + e_view_place_below(shadow_view, img_view); // show new E_Views if (e_view_client_visible_get(blur_view_client) && _e_blur_enabled_get(blur)) @@ -879,6 +972,7 @@ _e_blur_cb_new_rectangle(struct wl_listener *listener, void *data) return; fail: + if (shadow_view) _e_blur_rectangle_shadow_image_free(blur_rectangle); if (stroke_view) _e_blur_rectangle_stroke_image_free(blur_rectangle); if (dim_view) _e_blur_rectangle_dim_rect_free(blur_rectangle); if (img_view) _e_blur_rectangle_view_image_free(blur_rectangle); @@ -1315,6 +1409,17 @@ e_blur_manager_init(void) blur_manager->configs.stroke_config->color.a = 102; // #808080, 40%, premultiplied alpha blur_manager->configs.stroke_config->thickness = 2; // 2px + blur_manager->configs.shadow_config = E_NEW(E_Blur_Shadow_Config, 1); + EINA_SAFETY_ON_NULL_GOTO(blur_manager->configs.shadow_config, fail); + blur_manager->configs.shadow_config->enabled = EINA_FALSE; + blur_manager->configs.shadow_config->color.r = 0; + blur_manager->configs.shadow_config->color.g = 0; + blur_manager->configs.shadow_config->color.b = 0; + blur_manager->configs.shadow_config->color.a = 128; // #000000, 50%, premultiplied alpha + blur_manager->configs.shadow_config->blur_radius = 20; + blur_manager->configs.shadow_config->offsetX = 0; + blur_manager->configs.shadow_config->offsetY = 10; + blur_manager->tizen_blur_manager = ds_tizen_blur_manager_create(wl_disp); EINA_SAFETY_ON_NULL_GOTO(blur_manager->tizen_blur_manager, fail); @@ -1341,7 +1446,7 @@ e_blur_manager_init(void) return EINA_TRUE; fail: - + if (blur_manager->configs.shadow_config) free(blur_manager->configs.shadow_config); if (blur_manager->configs.stroke_config) free(blur_manager->configs.stroke_config); if (blur_manager->configs.dim_config) free(blur_manager->configs.dim_config); free(blur_manager); @@ -1640,3 +1745,78 @@ e_blur_stroke_config_get(E_Blur_Stroke_Config *stroke_config) *stroke_config = *_blur_manager->configs.stroke_config; } + +E_API Eina_Bool +e_blur_shadow_config_set(E_Blur_Shadow_Config *shadow_config) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(_blur_manager, EINA_FALSE); + EINA_SAFETY_ON_NULL_RETURN_VAL(_blur_manager->configs.shadow_config, EINA_FALSE); + + E_Blur_Shadow_Config *current_shadow_config = _blur_manager->configs.shadow_config; + Eina_Bool before_enabled = current_shadow_config->enabled; + Eina_Bool after_enabled = shadow_config->enabled; + E_View_Client *view_client; + E_View_Tree *view_client_tree; + E_Blur *blur; + E_Blur_Rectangle *blur_rectangle; + Eina_List *l, *ll; + unsigned int *pixels; + + current_shadow_config->enabled = shadow_config->enabled; + current_shadow_config->color.r = shadow_config->color.r; + current_shadow_config->color.g = shadow_config->color.g; + current_shadow_config->color.b = shadow_config->color.b; + current_shadow_config->color.a = shadow_config->color.a; + current_shadow_config->blur_radius = shadow_config->blur_radius; + current_shadow_config->offsetX = shadow_config->offsetX; + current_shadow_config->offsetY = shadow_config->offsetY; + + if (!before_enabled && !after_enabled) + return EINA_TRUE; + + EINA_LIST_FOREACH(_blur_manager->blurs, l, blur) + { + view_client = e_client_view_get(blur->ec); + if (!view_client) continue; + view_client_tree = e_view_parent_get(e_view_client_view_get(view_client)); + if (!view_client_tree) continue; + EINA_LIST_FOREACH(blur->blur_rectangles, ll, blur_rectangle) + { + if (after_enabled) + { + if (!blur_rectangle->shadow_image) + { + _e_blur_rectangle_shadow_image_new(blur_rectangle, view_client_tree, "blur_shadow_obj"); + EINA_SAFETY_ON_NULL_RETURN_VAL(blur_rectangle->shadow_image, EINA_FALSE); + e_view_place_below(e_view_image_view_get(blur_rectangle->shadow_image), + e_view_image_view_get(blur_rectangle->view_image)); + if (blur->enabled) _e_blur_rectangle_show(blur_rectangle); + } + pixels = e_view_image_data_get(blur_rectangle->shadow_image, true); + if (!pixels) + { + e_view_destroy(e_view_image_view_get(blur_rectangle->shadow_image)); + return EINA_FALSE; + } + *pixels = 0xffffffff; + e_view_image_data_set(blur_rectangle->shadow_image, pixels); + e_view_image_data_update_add(blur_rectangle->shadow_image, 0, 0, 1, 1); + _e_blur_rectangle_geometry_set(blur_rectangle, blur->ec); + _e_blur_rectangle_filter_set(blur_rectangle); + } + else if (before_enabled) + _e_blur_rectangle_shadow_image_free(blur_rectangle); + } + } + + return EINA_TRUE; +} + +E_API void +e_blur_shadow_config_get(E_Blur_Shadow_Config *shadow_config) +{ + EINA_SAFETY_ON_NULL_RETURN(shadow_config); + EINA_SAFETY_ON_NULL_RETURN(_blur_manager); + + *shadow_config = *_blur_manager->configs.shadow_config; +} diff --git a/src/include/e_blur.h b/src/include/e_blur.h index 7ef021e0e8..d94da318f6 100644 --- a/src/include/e_blur.h +++ b/src/include/e_blur.h @@ -9,6 +9,7 @@ extern "C" { typedef struct _E_Blur_Dim_Config E_Blur_Dim_Config; typedef struct _E_Blur_Stroke_Config E_Blur_Stroke_Config; +typedef struct _E_Blur_Shadow_Config E_Blur_Shadow_Config; struct _E_Blur_Dim_Config { @@ -33,10 +34,25 @@ struct _E_Blur_Stroke_Config int thickness; }; +struct _E_Blur_Shadow_Config +{ + Eina_Bool enabled; + struct { + unsigned char r; + unsigned char g; + unsigned char b; + unsigned char a; + } color; /* premultiplied alpha */ + int blur_radius; + int offsetX, offsetY; +}; + E_API Eina_Bool e_blur_dim_config_set(E_Blur_Dim_Config *dim_config); E_API void e_blur_dim_config_get(E_Blur_Dim_Config *dim_config); E_API Eina_Bool e_blur_stroke_config_set(E_Blur_Stroke_Config *stroke_config); E_API void e_blur_stroke_config_get(E_Blur_Stroke_Config *stroke_config); +E_API Eina_Bool e_blur_shadow_config_set(E_Blur_Shadow_Config *shadow_config); +E_API void e_blur_shadow_config_get(E_Blur_Shadow_Config *shadow_config); #ifdef __cplusplus } -- 2.34.1