jpeg pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=1336b2d9e05f2c6fafe109af49ea56739fe77fe3

commit 1336b2d9e05f2c6fafe109af49ea56739fe77fe3
Author: Jean-Philippe Andre <jp.an...@samsung.com>
Date:   Fri Mar 17 11:24:10 2017 +0900

    evas filters: Expand snapshot regions by blur radius
    
    When using a snapshot object we have access to exactly all
    the pixels below it inside the snapshot surface. So, in order
    to produce a nice blur, it is necessary to expand this snapshot
    and then clip it otherwise the edges will look a bit ugly.
    
    Unfortunately, there are still places where blurs didn't look
    so good, as objects below an opaque region would never get
    rendered into the snapshot object. So the edges, inside a
    snapshot object, around an opaque region would have blur
    artifacts.
    
    This fixes that by shrinking the cutout regions by the radius
    of the filter. Eg for blur this is the blur radius.
    
    The test case in elm_test can exhibit this fix very clearly:
    a red glow would be visible around the opaque rectangle, but with
    these changes we instead see the blurry edges of the objects
    below the rectangle.
---
 src/bin/elementary/test_evas_snapshot.c |  2 +-
 src/lib/evas/canvas/evas_filter_mixin.c | 18 ++++++++++
 src/lib/evas/canvas/evas_render.c       | 58 +++++++++++++++++----------------
 src/lib/evas/include/evas_private.h     |  1 +
 4 files changed, 50 insertions(+), 29 deletions(-)

diff --git a/src/bin/elementary/test_evas_snapshot.c 
b/src/bin/elementary/test_evas_snapshot.c
index 26d76b4..d2e8786 100644
--- a/src/bin/elementary/test_evas_snapshot.c
+++ b/src/bin/elementary/test_evas_snapshot.c
@@ -20,7 +20,7 @@ static const int rnd[] = {
 
 static const char *filter =
       "padding_set {0}"
-      "fill { color = '#0123' }"
+      "fill { color = 'red' }"
       "blur { 5 }"
       "print ('Evaluating filter: ' .. input.width .. 'x' .. input.height)"
       ;
diff --git a/src/lib/evas/canvas/evas_filter_mixin.c 
b/src/lib/evas/canvas/evas_filter_mixin.c
index a0d3b3e..636451d 100644
--- a/src/lib/evas/canvas/evas_filter_mixin.c
+++ b/src/lib/evas/canvas/evas_filter_mixin.c
@@ -741,4 +741,22 @@ 
_evas_filter_obscured_region_set(Evas_Object_Protected_Data *obj,
    FCOW_END(fcow, pd);
 }
 
+void
+_evas_filter_radius_get(Evas_Object_Protected_Data *obj, int *l, int *r, int 
*t, int *b)
+{
+   Evas_Filter_Padding pad = {};
+   Evas_Filter_Data *pd;
+
+   pd = efl_data_scope_get(obj->object, MY_CLASS);
+   if (!pd->data || !pd->data->chain) goto end;
+
+   evas_filter_program_padding_get(pd->data->chain, NULL, &pad);
+
+end:
+   if (l) *l = pad.l;
+   if (r) *r = pad.r;
+   if (t) *t = pad.t;
+   if (b) *b = pad.b;
+}
+
 #include "canvas/efl_canvas_filter_internal.eo.c"
diff --git a/src/lib/evas/canvas/evas_render.c 
b/src/lib/evas/canvas/evas_render.c
index e464026..61d8fd2 100644
--- a/src/lib/evas/canvas/evas_render.c
+++ b/src/lib/evas/canvas/evas_render.c
@@ -88,6 +88,7 @@ rend_dbg(const char *txt)
 #else
 #define RD(xxx, args...)
 #define IFRD(ifcase, xxx, args...)
+#define RDNAME(xxx) ""
 #endif
 
 #define OBJ_ARRAY_PUSH(array, obj) eina_array_push(array, obj)
@@ -2612,13 +2613,15 @@ end:
 }
 
 static void
-_evas_render_cutout_add(Evas_Public_Data *evas, void *context, 
Evas_Object_Protected_Data *obj, int off_x, int off_y)
+_evas_render_cutout_add(Evas_Public_Data *evas, void *context,
+                        Evas_Object_Protected_Data *obj, int off_x, int off_y,
+                        int cutout_margin)
 {
+   Evas_Coord cox = 0, coy = 0, cow = 0, coh = 0;
+
    if (evas_object_is_source_invisible(obj->object, obj)) return;
    if (evas_object_is_opaque(obj->object, obj))
      {
-        Evas_Coord cox, coy, cow, coh;
-
         cox = obj->cur->cache.clip.x;
         coy = obj->cur->cache.clip.y;
         cow = obj->cur->cache.clip.w;
@@ -2642,28 +2645,22 @@ _evas_render_cutout_add(Evas_Public_Data *evas, void 
*context, Evas_Object_Prote
                   oo = oo->cur->clipper;
                }
           }
-        ENFN->context_cutout_add(ENDT, context, cox + off_x, coy + off_y, cow, 
coh);
      }
-   else
+   else if (obj->func->get_opaque_rect)
      {
-        if (obj->func->get_opaque_rect)
-          {
-             Evas_Coord obx, oby, obw, obh;
-
-             obj->func->get_opaque_rect(obj->object, obj, obj->private_data, 
&obx, &oby, &obw, &obh);
-             if ((obw > 0) && (obh > 0))
-               {
-                  obx += off_x;
-                  oby += off_y;
-                  RECTS_CLIP_TO_RECT(obx, oby, obw, obh,
-                                     obj->cur->cache.clip.x + off_x,
-                                     obj->cur->cache.clip.y + off_y,
-                                     obj->cur->cache.clip.w,
-                                     obj->cur->cache.clip.h);
-                  ENFN->context_cutout_add(ENDT, context, obx, oby, obw, obh);
-               }
-          }
+        obj->func->get_opaque_rect(obj->object, obj, obj->private_data, &cox, 
&coy, &cow, &coh);
+        if ((cow <= 0) || (coh <= 0)) return;
+        RECTS_CLIP_TO_RECT(cox, coy, cow, coh,
+                           obj->cur->cache.clip.x, obj->cur->cache.clip.y,
+                           obj->cur->cache.clip.w, obj->cur->cache.clip.h);
      }
+   else return;
+   cox += cutout_margin + off_x;
+   coy += cutout_margin + off_y;
+   cow -= 2 * cutout_margin;
+   coh -= 2 * cutout_margin;
+   if ((cow <= 0) || (coh <= 0)) return;
+   ENFN->context_cutout_add(ENDT, context, cox, coy, cow, coh);
 }
 
 void
@@ -2821,7 +2818,7 @@ evas_render_updates_internal_loop(Evas *eo_e, 
Evas_Public_Data *evas,
                                   Evas_Object_Protected_Data *top,
                                   int ux, int uy, int uw, int uh,
                                   int cx, int cy, int cw, int ch,
-                                  int fx, int fy,
+                                  int fx, int fy, int cutout_margin,
                                   Eina_Bool alpha,
                                   Eina_Bool do_async,
                                   unsigned int *offset, int level)
@@ -2854,7 +2851,7 @@ evas_render_updates_internal_loop(Evas *eo_e, 
Evas_Public_Data *evas,
 
              /* reset the background of the area if needed (using cutout and 
engine alpha flag to help) */
              if (alpha)
-               _evas_render_cutout_add(evas, context, obj, off_x + fx, off_y + 
fy);
+               _evas_render_cutout_add(evas, context, obj, off_x + fx, off_y + 
fy, cutout_margin);
           }
      }
    if (alpha)
@@ -2966,7 +2963,7 @@ evas_render_updates_internal_loop(Evas *eo_e, 
Evas_Public_Data *evas,
                             ux, uy, uw, uh)
                           )
 #endif
-                         _evas_render_cutout_add(evas, context, obj2, off_x + 
fx, off_y + fy);
+                         _evas_render_cutout_add(evas, context, obj2, off_x + 
fx, off_y + fy, cutout_margin);
                     }
 #endif
                   ENFN->context_cutout_target(ENDT, context,
@@ -3263,8 +3260,9 @@ evas_render_updates_internal(Evas *eo_e,
                   if (eina_rectangle_intersection(&ur, &output) &&
                       _snapshot_needs_redraw(evas, obj, &opaque))
                     {
-                       void *pseudo_canvas;
+                       int cutout_margin, fpl = 0, fpr = 0, fpt = 0, fpb = 0;
                        unsigned int restore_offset = offset;
+                       void *pseudo_canvas;
 
                        EINA_RECTANGLE_SET(&cr,
                                           ur.x - output.x, ur.y - output.y,
@@ -3273,6 +3271,10 @@ evas_render_updates_internal(Evas *eo_e,
                        pseudo_canvas = _evas_object_image_surface_get(obj, 
EINA_TRUE);
 
                        // TODO: List of canvas regions that need redraw
+                       // Get required margin for filters (eg. blur radius)
+                       _evas_filter_radius_get(obj, &fpl, &fpr, &fpt, &fpb);
+                       cutout_margin = MAX(MAX(MAX(fpl, fpr), fpt), fpb);
+
                        // Add obscure region (make it a list?)
                        _evas_filter_obscured_region_set(obj, opaque);
 
@@ -3282,7 +3284,7 @@ evas_render_updates_internal(Evas *eo_e,
                                                                        obj,
                                                                        ur.x, 
ur.y, ur.w, ur.h,
                                                                        cr.x, 
cr.y, cr.w, cr.h,
-                                                                       fx, fy, 
alpha,
+                                                                       fx, fy, 
cutout_margin, alpha,
                                                                        
do_async,
                                                                        
&offset, 1);
                        ENFN->context_free(ENDT, ctx);
@@ -3319,7 +3321,7 @@ evas_render_updates_internal(Evas *eo_e,
                                                              ctx, NULL,
                                                              ux, uy, uw, uh,
                                                              cx, cy, cw, ch,
-                                                             fx, fy, alpha,
+                                                             fx, fy, 0, alpha,
                                                              do_async,
                                                              &offset, 0);
              ENFN->context_free(ENDT, ctx);
diff --git a/src/lib/evas/include/evas_private.h 
b/src/lib/evas/include/evas_private.h
index 7034da4..cd56838 100644
--- a/src/lib/evas/include/evas_private.h
+++ b/src/lib/evas/include/evas_private.h
@@ -2035,6 +2035,7 @@ void *efl_input_hold_legacy_info_fill(Efl_Input_Hold 
*evt, Evas_Event_Flags **pf
 Eina_Bool evas_vg_loader_svg(Evas_Object *vg, const Eina_File *f, const char 
*key EINA_UNUSED);
 
 void *_evas_object_image_surface_get(Evas_Object_Protected_Data *obj, 
Eina_Bool create);
+void _evas_filter_radius_get(Evas_Object_Protected_Data *obj, int *l, int *r, 
int *t, int *b);
 void _evas_filter_obscured_region_set(Evas_Object_Protected_Data *obj, const 
Eina_Rectangle rect);
 Eina_Bool _evas_image_proxy_source_clip_get(const Eo *eo_obj);
 

-- 


Reply via email to