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
This commit is contained in:
Jean-Philippe Andre 2016-12-13 17:41:49 +09:00
parent 0ca1d0eef2
commit 4e110a34bf
7 changed files with 114 additions and 22 deletions

View File

@ -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
*/

View File

@ -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;
}

View File

@ -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);

View File

@ -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;

View File

@ -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;
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, %dx%d)\n", source, proxy_obj, w, h);
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);

View File

@ -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);

View File

@ -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);