e_blur: Use clip the object for corner radius of the blur rectangle 40/317140/1
authorChangyeon Lee <cyeon.lee@samsung.com>
Wed, 4 Sep 2024 09:39:58 +0000 (18:39 +0900)
committerTizen Window System <tizen.windowsystem@gmail.com>
Wed, 4 Sep 2024 10:56:20 +0000 (19:56 +0900)
applying corner radius to an image object and then setting a clip results
in better quality than applying a corner radius directly to a blur object.

Change-Id: Ibbf34b090a2b5acef12c860ee3325b6cb0b2b6e8

src/bin/server/e_blur.c

index 03400c5..dda62f8 100644 (file)
@@ -68,6 +68,7 @@ struct _E_Blur_Rectangle
    int rx, ry;
 
    Evas_Object *obj;
+   Evas_Object *corner_radius_obj;
 };
 
 struct _E_Blur_Behind
@@ -217,6 +218,9 @@ _e_blur_rectangle_free(E_Blur_Rectangle *blur_rectangle)
 
    evas_object_del(blur_rectangle->obj);
 
+   if (blur_rectangle->corner_radius_obj)
+     evas_object_del(blur_rectangle->corner_radius_obj);
+
    if (blur_rectangle->listener.destroy.notify)
      wl_list_remove(&blur_rectangle->listener.destroy.link);
 
@@ -265,6 +269,15 @@ _e_blur_rectangle_geometry_set(E_Blur_Rectangle *blur_rectangle, E_Client *ec)
                                  ec_y + blur_rectangle->y,
                                  (int)((double)blur_rectangle->w * scale_w),
                                  (int)((double)blur_rectangle->h * scale_h));
+
+        if (blur_rectangle->corner_radius_obj)
+          {
+             evas_object_geometry_set(blur_rectangle->corner_radius_obj,
+                                      ec_x + blur_rectangle->x,
+                                      ec_y + blur_rectangle->y,
+                                      (int)((double)blur_rectangle->w * scale_w),
+                                      (int)((double)blur_rectangle->h * scale_h));
+          }
      }
    else
      {
@@ -273,6 +286,15 @@ _e_blur_rectangle_geometry_set(E_Blur_Rectangle *blur_rectangle, E_Client *ec)
                                  evas_y + blur_rectangle->y,
                                  blur_rectangle->w,
                                  blur_rectangle->h);
+
+        if (blur_rectangle->corner_radius_obj)
+          {
+             evas_object_geometry_set(blur_rectangle->corner_radius_obj,
+                                      evas_x + blur_rectangle->x,
+                                      evas_y + blur_rectangle->y,
+                                      blur_rectangle->w,
+                                      blur_rectangle->h);
+          }
      }
 }
 
@@ -281,19 +303,17 @@ _e_blur_rectangle_filter_set(E_Blur_Rectangle *blur_rectangle)
 {
    char program[256];
 
-   if ((blur_rectangle->rx != 0) && (blur_rectangle->ry != 0))
-     {
-        snprintf(program, sizeof(program),
-                 "a = buffer { 'rgba' } blur { %d, dst = a } rounded_corner { src = a, rx = %d, ry = %d}",
-                 blur_rectangle->blur->radius, blur_rectangle->rx, blur_rectangle->ry);
-     }
-   else
+   if (blur_rectangle->corner_radius_obj)
      {
-        snprintf(program, sizeof(program),
-                 "blur (%d) padding_set (0)",
-                 blur_rectangle->blur->radius);
+        snprintf(program, sizeof(program), "rounded_corner { rx = %d, ry = %d}",
+                 blur_rectangle->rx, blur_rectangle->ry);
+
+        efl_gfx_filter_program_set(blur_rectangle->corner_radius_obj, program, "image_filter");
      }
 
+   snprintf(program, sizeof(program), "blur (%d) padding_set (0)",
+            blur_rectangle->blur->radius);
+
    efl_gfx_filter_program_set(blur_rectangle->obj, program, "image_filter");
 }
 
@@ -335,6 +355,8 @@ _e_blur_cb_ds_tizen_blur_commit(struct wl_listener *listener, void *data)
              _e_blur_rectangle_filter_set(blur_rectangle);
              if (!evas_object_visible_get(blur->ec->frame)) continue;
              evas_object_show(blur_rectangle->obj);
+             if (blur_rectangle->corner_radius_obj)
+               evas_object_show(blur_rectangle->corner_radius_obj);
           }
 
         _e_blur_enabled_set(blur, EINA_TRUE);
@@ -342,7 +364,11 @@ _e_blur_cb_ds_tizen_blur_commit(struct wl_listener *listener, void *data)
    else
      {
         EINA_LIST_FOREACH(blur->blur_rectangles, l, blur_rectangle)
-          evas_object_hide(blur_rectangle->obj);
+          {
+             evas_object_hide(blur_rectangle->obj);
+             if (blur_rectangle->corner_radius_obj)
+               evas_object_hide(blur_rectangle->corner_radius_obj);
+          }
 
         _e_blur_enabled_set(blur, EINA_FALSE);
      }
@@ -359,7 +385,11 @@ _e_blur_evas_cb_show(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_U
    if (!_e_blur_enabled_get(blur)) return;
 
    EINA_LIST_FOREACH(blur->blur_rectangles, l, blur_rectangle)
-     evas_object_show(blur_rectangle->obj);
+     {
+        evas_object_show(blur_rectangle->obj);
+        if (blur_rectangle->corner_radius_obj)
+          evas_object_show(blur_rectangle->corner_radius_obj);
+     }
 }
 
 static void
@@ -372,7 +402,11 @@ _e_blur_evas_cb_hide(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_U
    if (!(blur = data)) return;
 
    EINA_LIST_FOREACH(blur->blur_rectangles, l, blur_rectangle)
-     evas_object_hide(blur_rectangle->obj);
+     {
+        evas_object_hide(blur_rectangle->obj);
+        if (blur_rectangle->corner_radius_obj)
+          evas_object_hide(blur_rectangle->corner_radius_obj);
+     }
 }
 
 static void
@@ -417,6 +451,11 @@ _e_blur_evas_cb_restack(void *data, Evas *e EINA_UNUSED, Evas_Object *obj, void
      {
         evas_object_layer_set(blur_rectangle->obj, layer);
         evas_object_stack_below(blur_rectangle->obj, obj);
+        if (blur_rectangle->corner_radius_obj)
+          {
+             evas_object_layer_set(blur_rectangle->corner_radius_obj, layer);
+             evas_object_stack_above(blur_rectangle->corner_radius_obj, blur_rectangle->obj);
+          }
      }
 }
 
@@ -515,8 +554,9 @@ _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;
-   Evas_Object *obj;
+   Evas_Object *obj, *corner_radius_obj = NULL;
    E_Blur_Hook_Data hook_data;
+   unsigned int *pixels;
 
    blur = wl_container_of(listener, blur, listener.new_rectangle);
    EINA_SAFETY_ON_NULL_RETURN(blur);
@@ -526,7 +566,7 @@ _e_blur_cb_new_rectangle(struct wl_listener *listener, void *data)
    EINA_SAFETY_ON_NULL_RETURN(obj);
 
    blur_rectangle = E_NEW(E_Blur_Rectangle, 1);
-   EINA_SAFETY_ON_NULL_RETURN(blur_rectangle);
+   EINA_SAFETY_ON_NULL_GOTO(blur_rectangle, fail);
 
    ds_tizen_blur_rectangle_get_geometry(tizen_blur_rectangle,
                                         &blur_rectangle->x,
@@ -545,20 +585,53 @@ _e_blur_cb_new_rectangle(struct wl_listener *listener, void *data)
    blur_rectangle->obj = obj;
    evas_object_image_snapshot_set(blur_rectangle->obj, EINA_TRUE);
    evas_object_name_set(blur_rectangle->obj, "blur_obj");
+
+   if ((blur_rectangle->rx != 0) && (blur_rectangle->ry != 0))
+     {
+        corner_radius_obj = evas_object_image_filled_add(e_comp->evas);
+        EINA_SAFETY_ON_NULL_GOTO(corner_radius_obj, fail);
+
+        blur_rectangle->corner_radius_obj = corner_radius_obj;
+        evas_object_name_set(blur_rectangle->corner_radius_obj, "blur_corner_radius_obj");
+        evas_object_image_size_set(blur_rectangle->corner_radius_obj , 1, 1);
+        pixels = evas_object_image_data_get(blur_rectangle->corner_radius_obj, EINA_TRUE);
+        EINA_SAFETY_ON_NULL_GOTO(pixels, fail);
+        *pixels = 0xffffffff;
+        evas_object_image_data_set(blur_rectangle->corner_radius_obj, pixels);
+        evas_object_image_data_update_add(blur_rectangle->corner_radius_obj , 0, 0, 1, 1);
+        evas_object_clip_set(blur_rectangle->obj, blur_rectangle->corner_radius_obj);
+     }
+
    blur_rectangle->blur = blur;
    _e_blur_rectangle_add(blur, blur_rectangle);
    _e_blur_rectangle_filter_set(blur_rectangle);
    _e_blur_rectangle_geometry_set(blur_rectangle, blur->ec);
    evas_object_layer_set(blur_rectangle->obj, evas_object_layer_get(blur->ec->frame));
    evas_object_stack_below(blur_rectangle->obj, blur->ec->frame);
+   if (blur_rectangle->corner_radius_obj)
+     {
+        evas_object_layer_set(blur_rectangle->corner_radius_obj, evas_object_layer_get(blur->ec->frame));
+        evas_object_stack_above(blur_rectangle->corner_radius_obj, blur_rectangle->obj);
+     }
 
    if (evas_object_visible_get(blur->ec->frame) && _e_blur_enabled_get(blur))
-     evas_object_show(blur_rectangle->obj);
+     {
+        evas_object_show(blur_rectangle->obj);
+        if (blur_rectangle->corner_radius_obj)
+          evas_object_show(blur_rectangle->corner_radius_obj);
+     }
 
    ELOGF("E_BLUR", "E_Blur_Rectangle:%p Create", blur->ec, blur_rectangle);
 
    hook_data.blur_rectangle = blur_rectangle;
    _e_blur_hook_call(E_BLUR_HOOK_RECTANGLE_CREATE, &hook_data);
+
+   return;
+
+fail:
+   if (obj) evas_object_del(obj);
+   if (corner_radius_obj) evas_object_del(corner_radius_obj);
+   if (blur_rectangle) free(blur_rectangle);
 }
 
 static void