From 4e110a34bffe09abe4dd793f9ecf1cf3884ccf22 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Andre Date: Tue, 13 Dec 2016 17:41:49 +0900 Subject: [PATCH] evas: Add source_region property to proxy objects This will allow partially rendering a proxy in a smaller image, limited to the specified region. At the moment, this will allow apps to create proxies of very large objects and let them deal with the geometry & clipping. This is not directly solving the issues with adding a filter to textblock or the infinite page scrollers. @feature --- src/lib/evas/canvas/efl_canvas_proxy.c | 51 +++++++++++++++++++++++++++----- src/lib/evas/canvas/efl_canvas_proxy.eo | 25 +++++++++++++++- src/lib/evas/canvas/evas_image_private.h | 6 ++++ src/lib/evas/canvas/evas_object_image.c | 19 ++++++++++-- src/lib/evas/canvas/evas_render.c | 30 ++++++++++++++----- src/lib/evas/filters/evas_filter.c | 3 +- src/lib/evas/include/evas_private.h | 4 +-- 7 files changed, 115 insertions(+), 23 deletions(-) diff --git a/src/lib/evas/canvas/efl_canvas_proxy.c b/src/lib/evas/canvas/efl_canvas_proxy.c index 2e5af8d..2b18482 100644 --- a/src/lib/evas/canvas/efl_canvas_proxy.c +++ b/src/lib/evas/canvas/efl_canvas_proxy.c @@ -3,6 +3,18 @@ #define MY_CLASS EFL_CANVAS_PROXY_CLASS +EOLIAN static Efl_Object * +_efl_canvas_proxy_efl_object_constructor(Eo *eo_obj, Efl_Canvas_Proxy_Data *pd EINA_UNUSED) +{ + Evas_Image_Data *o; + + eo_obj = efl_constructor(efl_super(eo_obj, MY_CLASS)); + o = efl_data_scope_get(eo_obj, EFL_CANVAS_IMAGE_INTERNAL_CLASS); + if (o) o->efl_canvas_proxy = EINA_TRUE; + + return eo_obj; +} + Eina_Bool _evas_image_proxy_source_set(Eo *eo_obj, Evas_Object *eo_src) { @@ -57,7 +69,7 @@ _evas_image_proxy_source_set(Eo *eo_obj, Evas_Object *eo_src) } EOLIAN static Eina_Bool -_efl_canvas_proxy_source_set(Eo *eo_obj, void *_pd EINA_UNUSED, Evas_Object *eo_src) +_efl_canvas_proxy_source_set(Eo *eo_obj, Efl_Canvas_Proxy_Data *pd EINA_UNUSED, Evas_Object *eo_src) { return _evas_image_proxy_source_set(eo_obj, eo_src); } @@ -70,7 +82,7 @@ _evas_image_proxy_source_get(const Eo *eo_obj) } EOLIAN static Evas_Object * -_efl_canvas_proxy_source_get(Eo *eo_obj, void *_pd EINA_UNUSED) +_efl_canvas_proxy_source_get(Eo *eo_obj, Efl_Canvas_Proxy_Data *pd EINA_UNUSED) { return _evas_image_proxy_source_get(eo_obj); } @@ -94,7 +106,7 @@ _evas_image_proxy_source_clip_set(Eo *eo_obj, Eina_Bool source_clip) } EOLIAN static void -_efl_canvas_proxy_source_clip_set(Eo *eo_obj, void *_pd EINA_UNUSED, Eina_Bool source_clip) +_efl_canvas_proxy_source_clip_set(Eo *eo_obj, Efl_Canvas_Proxy_Data *pd EINA_UNUSED, Eina_Bool source_clip) { return _evas_image_proxy_source_clip_set(eo_obj, source_clip); } @@ -107,7 +119,7 @@ _evas_image_proxy_source_clip_get(const Eo *eo_obj) } EOLIAN static Eina_Bool -_efl_canvas_proxy_source_clip_get(Eo *eo_obj, void *_pd EINA_UNUSED) +_efl_canvas_proxy_source_clip_get(Eo *eo_obj, Efl_Canvas_Proxy_Data *pd EINA_UNUSED) { return _evas_image_proxy_source_clip_get(eo_obj); } @@ -131,7 +143,7 @@ _evas_image_proxy_source_events_set(Eo *eo_obj, Eina_Bool source_events) } EOLIAN static void -_efl_canvas_proxy_source_events_set(Eo *eo_obj, void *_pd EINA_UNUSED, Eina_Bool repeat) +_efl_canvas_proxy_source_events_set(Eo *eo_obj, Efl_Canvas_Proxy_Data *pd EINA_UNUSED, Eina_Bool repeat) { return _evas_image_proxy_source_events_set(eo_obj, repeat); } @@ -144,7 +156,7 @@ _evas_image_proxy_source_events_get(const Eo *eo_obj) } EOLIAN static Eina_Bool -_efl_canvas_proxy_source_events_get(Eo *eo_obj, void *_pd EINA_UNUSED) +_efl_canvas_proxy_source_events_get(Eo *eo_obj, Efl_Canvas_Proxy_Data *pd EINA_UNUSED) { return _evas_image_proxy_source_events_get(eo_obj); } @@ -260,7 +272,7 @@ _proxy_image_get(Evas_Image_Data *o) } EOLIAN static Eina_Bool -_efl_canvas_proxy_efl_gfx_buffer_buffer_map(Eo *eo_obj, void *_pd EINA_UNUSED, +_efl_canvas_proxy_efl_gfx_buffer_buffer_map(Eo *eo_obj, Efl_Canvas_Proxy_Data *pd EINA_UNUSED, Eina_Rw_Slice *slice, Efl_Gfx_Buffer_Access_Mode mode, int x, int y, int w, int h, @@ -329,7 +341,7 @@ end: } EOLIAN static Eina_Bool -_efl_canvas_proxy_efl_gfx_buffer_buffer_unmap(Eo *eo_obj, void *_pd EINA_UNUSED, +_efl_canvas_proxy_efl_gfx_buffer_buffer_unmap(Eo *eo_obj, Efl_Canvas_Proxy_Data *pd EINA_UNUSED, const Eina_Rw_Slice *slice) { Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS); @@ -344,6 +356,29 @@ _efl_canvas_proxy_efl_gfx_buffer_buffer_unmap(Eo *eo_obj, void *_pd EINA_UNUSED, return EINA_TRUE; } +EOLIAN static void +_efl_canvas_proxy_source_region_set(Eo *eo_obj, Efl_Canvas_Proxy_Data *pd, + int x, int y, int w, int h) +{ + Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS); + + pd->region.x = x; + pd->region.y = y; + pd->region.w = w; + pd->region.h = h; + evas_object_change(eo_obj, obj); +} + +EOLIAN static void +_efl_canvas_proxy_source_region_get(Eo *eo_obj EINA_UNUSED, Efl_Canvas_Proxy_Data *pd, + int *x, int *y, int *w, int *h) +{ + if (x) *x = pd->region.x; + if (y) *y = pd->region.y; + if (w) *w = pd->region.w; + if (h) *h = pd->region.h; +} + /* Some moron just set a proxy on a proxy. * Give them some pixels. A random color */ diff --git a/src/lib/evas/canvas/efl_canvas_proxy.eo b/src/lib/evas/canvas/efl_canvas_proxy.eo index b8048fb..d455520 100644 --- a/src/lib/evas/canvas/efl_canvas_proxy.eo +++ b/src/lib/evas/canvas/efl_canvas_proxy.eo @@ -6,7 +6,6 @@ class Efl.Canvas.Proxy (Efl.Canvas.Image.Internal, Efl.Gfx.Buffer) object attached to it. It can be used to apply some sort of image transformation to any object (eg. filters, map or zoom). ]] - data: null; methods { @property source { [[The source object for this proxy. @@ -70,8 +69,32 @@ class Efl.Canvas.Proxy (Efl.Canvas.Image.Internal, Efl.Gfx.Buffer) ($false) to its source.]] } } + @property source_region { + [[Region in the source object that should be used as source of pixels. + + If this property is enabled (ie. the region is not empty), then the + proxy will be an image object of the size of this region, and only + include the pixels from the source object starting at the relative + position $x,$y. + + The region ($x,$y,$w,$h) should fit inside the source object + relative geometry. Invalid values lead to undefined behaviour. + (0,0,0,0) can be used to reset the region to the entire object. + + @since 1.19 + ]] + values { + x: int; [[Relative X position inside the source object.]] + y: int; [[Relative Y position inside the source object.]] + w: int; [[Width of the region inside the source object, or 0 + for the entire object width.]] + h: int; [[Height of the region inside the source object, or 0 + for the entire object height.]] + } + } } implements { + Efl.Object.constructor; Efl.Gfx.Buffer.buffer_map; Efl.Gfx.Buffer.buffer_unmap; } diff --git a/src/lib/evas/canvas/evas_image_private.h b/src/lib/evas/canvas/evas_image_private.h index e22a862..fa2e63f 100644 --- a/src/lib/evas/canvas/evas_image_private.h +++ b/src/lib/evas/canvas/evas_image_private.h @@ -133,6 +133,7 @@ struct _Evas_Image_Data Eina_Bool direct_render : 1; Eina_Bool has_filter : 1; Eina_Bool buffer_data_set : 1; + Eina_Bool efl_canvas_proxy : 1; struct { Eina_Bool video_move : 1; @@ -143,6 +144,11 @@ struct _Evas_Image_Data Eina_Bool legacy_type : 1; }; +typedef struct _Efl_Canvas_Proxy_Data +{ + Eina_Rectangle region; +} Efl_Canvas_Proxy_Data; + /* shared functions between legacy and new eo classes */ void _evas_image_init_set(const Eina_File *f, const char *file, const char *key, Eo *eo_obj, Evas_Object_Protected_Data *obj, Evas_Image_Data *o, Evas_Image_Load_Opts *lo); void _evas_image_done_set(Eo *eo_obj, Evas_Object_Protected_Data *obj, Evas_Image_Data *o); diff --git a/src/lib/evas/canvas/evas_object_image.c b/src/lib/evas/canvas/evas_object_image.c index 110b9da..9fd263b 100644 --- a/src/lib/evas/canvas/evas_object_image.c +++ b/src/lib/evas/canvas/evas_object_image.c @@ -917,9 +917,10 @@ _efl_canvas_image_internal_efl_file_save(const Eo *eo_obj, Evas_Image_Data *o, c } else { + Eina_Rectangle region = { 0, 0, 0, 0 }; o->proxyrendering = EINA_TRUE; evas_render_proxy_subrender(obj->layer->evas->evas, o->cur->source, - (Eo *) eo_obj, obj, EINA_FALSE); + (Eo *) eo_obj, obj, region, EINA_FALSE); pixels = source->proxy->surface; imagew = source->proxy->w; imageh = source->proxy->h; @@ -1926,9 +1927,15 @@ _evas_image_render(Eo *eo_obj, Evas_Object_Protected_Data *obj, } else { + Eina_Rectangle region = { 0, 0, 0, 0 }; + if (o->efl_canvas_proxy) + { + Efl_Canvas_Proxy_Data *ppd = efl_data_scope_get(eo_obj, EFL_CANVAS_PROXY_CLASS); + region = ppd->region; + } o->proxyrendering = EINA_TRUE; evas_render_proxy_subrender(obj->layer->evas->evas, o->cur->source, - eo_obj, obj, EINA_FALSE); + eo_obj, obj, region, EINA_FALSE); pixels = source->proxy->surface; imagew = source->proxy->w; imageh = source->proxy->h; @@ -2955,9 +2962,15 @@ evas_object_image_is_inside(Evas_Object *eo_obj, } else { + Eina_Rectangle region = { 0, 0, 0, 0 }; + if (o->efl_canvas_proxy) + { + Efl_Canvas_Proxy_Data *ppd = efl_data_scope_get(eo_obj, EFL_CANVAS_PROXY_CLASS); + region = ppd->region; + } o->proxyrendering = EINA_TRUE; evas_render_proxy_subrender(obj->layer->evas->evas, o->cur->source, - eo_obj, obj, EINA_FALSE); + eo_obj, obj, region, EINA_FALSE); pixels = source->proxy->surface; imagew = source->proxy->w; imageh = source->proxy->h; diff --git a/src/lib/evas/canvas/evas_render.c b/src/lib/evas/canvas/evas_render.c index bded79b..66d82f4 100644 --- a/src/lib/evas/canvas/evas_render.c +++ b/src/lib/evas/canvas/evas_render.c @@ -2254,14 +2254,15 @@ evas_render_mapped(Evas_Public_Data *evas, Evas_Object *eo_obj, */ void evas_render_proxy_subrender(Evas *eo_e, Evas_Object *eo_source, Evas_Object *eo_proxy, - Evas_Object_Protected_Data *proxy_obj, Eina_Bool do_async) + Evas_Object_Protected_Data *proxy_obj, Eina_Rectangle region, + Eina_Bool do_async) { Evas_Public_Data *evas = efl_data_scope_get(eo_e, EVAS_CANVAS_CLASS); Evas_Object_Protected_Data *source; Eina_Bool source_clip = EINA_FALSE; int level = 1; void *ctx; - int w, h; + int x, y, w, h, W, H; #ifdef REND_DBG level = __RD_level; @@ -2271,10 +2272,22 @@ evas_render_proxy_subrender(Evas *eo_e, Evas_Object *eo_source, Evas_Object *eo_ eina_evlog("+proxy_subrender", eo_proxy, 0.0, NULL); source = efl_data_scope_get(eo_source, EFL_CANVAS_OBJECT_CLASS); - w = source->cur->geometry.w; - h = source->cur->geometry.h; - - RD(level, " proxy_subrender(source: %p, proxy: %p, %dx%d)\n", source, proxy_obj, w, h); + W = source->cur->geometry.w; + H = source->cur->geometry.h; + x = region.x; + y = region.y; + if(x >= W) x = W - 1; + if(x >= H) x = H - 1; + if(x < 0) x = 0; + if(y < 0) y = 0; + w = (region.w > 0) ? region.w : W; + h = (region.h > 0) ? region.h : H; + if((x + w) > W) w = W - x; + if((y + h) > H) h = H - y; + if(w < 0) w = 0; + if(h < 0) h = 0; + + RD(level, " proxy_subrender(source: %p, proxy: %p, region: %d,%d %dx%d)\n", eo_source, eo_proxy, x, y, w, h); EINA_COW_WRITE_BEGIN(evas_object_proxy_cow, source->proxy, Evas_Object_Proxy_Data, proxy_write) @@ -2318,6 +2331,7 @@ evas_render_proxy_subrender(Evas *eo_e, Evas_Object *eo_source, Evas_Object *eo_ .proxy_obj = proxy_obj, .eo_src = eo_source, .src_obj = source, + .region = (Eina_Rectangle) { x, y, w, h }, .source_clip = source_clip }; @@ -2326,8 +2340,8 @@ evas_render_proxy_subrender(Evas *eo_e, Evas_Object *eo_source, Evas_Object *eo_ ctx = ENFN->context_new(ENDT); evas_render_mapped(evas, eo_source, source, ctx, proxy_write->surface, - -source->cur->geometry.x, - -source->cur->geometry.y, + x - source->cur->geometry.x, + y - source->cur->geometry.y, level + 1, 0, 0, evas->output.w, evas->output.h, &proxy_render_data, level + 1, EINA_TRUE, do_async); ENFN->context_free(ENDT, ctx); diff --git a/src/lib/evas/filters/evas_filter.c b/src/lib/evas/filters/evas_filter.c index 63ab6a3..0f799a5 100644 --- a/src/lib/evas/filters/evas_filter.c +++ b/src/lib/evas/filters/evas_filter.c @@ -121,10 +121,11 @@ evas_filter_context_proxy_render_all(Evas_Filter_Context *ctx, Eo *eo_obj, } else { + Eina_Rectangle region = { 0, 0, 0, 0 }; XDBG("Source needs to be rendered: '%s' of type '%s' (%s)", fb->source_name, efl_class_name_get(efl_class_get(fb->source)), source->proxy->redraw ? "redraw" : "no surface"); - evas_render_proxy_subrender(ctx->evas->evas, fb->source, eo_obj, obj, do_async); + evas_render_proxy_subrender(ctx->evas->evas, fb->source, eo_obj, obj, region, do_async); } _filter_buffer_backing_free(fb); XDBG("Source #%d '%s' has dimensions %dx%d", fb->id, fb->source_name, fb->w, fb->h); diff --git a/src/lib/evas/include/evas_private.h b/src/lib/evas/include/evas_private.h index c038e75..8f8f63b 100644 --- a/src/lib/evas/include/evas_private.h +++ b/src/lib/evas/include/evas_private.h @@ -1924,6 +1924,7 @@ struct _Evas_Proxy_Render_Data Evas_Object_Protected_Data *src_obj; Evas_Object *eo_proxy; Evas_Object *eo_src; + Eina_Rectangle region; Eina_Bool source_clip : 1; }; @@ -1983,8 +1984,7 @@ Eina_Bool evas_render_mapped(Evas_Public_Data *e, Evas_Object *obj, int level, Eina_Bool use_mapped_ctx, Eina_Bool do_async); void evas_render_invalidate(Evas *e); void evas_render_object_recalc(Evas_Object *obj); -void evas_render_proxy_subrender(Evas *eo_e, Evas_Object *eo_source, Evas_Object *eo_proxy, - Evas_Object_Protected_Data *proxy_obj, Eina_Bool do_async); +void evas_render_proxy_subrender(Evas *eo_e, Evas_Object *eo_source, Evas_Object *eo_proxy, Evas_Object_Protected_Data *proxy_obj, Eina_Rectangle region, Eina_Bool do_async); void evas_render_mask_subrender(Evas_Public_Data *e, Evas_Object_Protected_Data *mask, Evas_Object_Protected_Data *prev_mask, int level); Eina_Bool evas_map_inside_get(const Evas_Map *m, Evas_Coord x, Evas_Coord y); -- 2.7.4