e_blur: add shadow layer 12/325612/2
authorhojoon-ryou <hojoon.ryou@samsung.com>
Wed, 11 Jun 2025 07:58:55 +0000 (16:58 +0900)
committerTizen Window System <tizen.windowsystem@gmail.com>
Thu, 12 Jun 2025 10:57:22 +0000 (10:57 +0000)
Change-Id: I1530a3750c1dc07749b5dd9157f1bb0e6a7f03c3

src/bin/server/e_blur.c
src/include/e_blur.h

index 9b7c1acc563dfdbc7f24f1500994c3317af90a65..1d362b3937f52b4a4f57ffcebc52a20e23e7710b 100644 (file)
@@ -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;
+}
index 7ef021e0e86bcc6d23657d3c284bf2e3b51973af..d94da318f631dcd0f535a983bc291102d877bf61 100644 (file)
@@ -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
 }