Evas masking: Allow setting an image object as clipper

The render function is not yet implemented, but this
prepares the infra used to set an object other than
Rectangle as a clipper.

@feature
This commit is contained in:
Jean-Philippe Andre 2014-11-13 10:40:16 +09:00
parent a9630a77b6
commit 2a0201d571
4 changed files with 73 additions and 18 deletions

View File

@ -188,8 +188,33 @@ evas_object_mapped_clip_across_mark(Evas_Object *eo_obj, Evas_Object_Protected_D
#endif
}
static void
_evas_object_clip_mask_unset(Evas_Object_Protected_Data *obj)
{
if (!obj || !obj->mask->is_mask) return;
if (obj->clip.clipees) return;
/* this frees the clip surface. is this correct? */
EINA_COW_WRITE_BEGIN(evas_object_mask_cow, obj->mask, Evas_Object_Mask_Data, mask)
mask->is_mask = EINA_FALSE;
mask->redraw = EINA_FALSE;
mask->is_alpha = EINA_FALSE;
if (mask->surface)
{
obj->layer->evas->engine.func->image_map_surface_free
(obj->layer->evas->engine.data.output, mask->surface);
mask->surface = NULL;
}
mask->x = 0;
mask->y = 0;
mask->w = 0;
mask->h = 0;
EINA_COW_WRITE_END(evas_object_mask_cow, obj->mask, mask);
}
/* public functions */
extern const char *o_rect_type;
extern const char *o_image_type;
EOLIAN void
_evas_object_clip_set(Eo *eo_obj, Evas_Object_Protected_Data *obj, Evas_Object *eo_clip)
@ -242,10 +267,10 @@ _evas_object_clip_set(Eo *eo_obj, Evas_Object_Protected_Data *obj, Evas_Object *
}
if (evas_object_intercept_call_clip_set(eo_obj, obj, eo_clip)) return;
// illegal to set anything but a rect as a clip
if (clip->type != o_rect_type)
// illegal to set anything but a rect or an image as a clip
if (clip->type != o_rect_type && clip->type != o_image_type)
{
ERR("For now a clip on other object than a rectangle is disabled");
ERR("For now a clip on other object than a rectangle or an image is disabled");
return;
}
if (obj->is_smart)
@ -280,6 +305,7 @@ _evas_object_clip_set(Eo *eo_obj, Evas_Object_Protected_Data *obj, Evas_Object *
}
}
*/
_evas_object_clip_mask_unset(obj->cur->clipper);
}
evas_object_change(obj->cur->clipper->object, obj->cur->clipper);
evas_object_change(eo_obj, obj);
@ -290,6 +316,15 @@ _evas_object_clip_set(Eo *eo_obj, Evas_Object_Protected_Data *obj, Evas_Object *
}
EINA_COW_STATE_WRITE_END(obj, state_write, cur);
}
/* image object clipper */
if (clip->type == o_image_type)
{
EINA_COW_WRITE_BEGIN(evas_object_mask_cow, clip->mask, Evas_Object_Mask_Data, mask)
mask->is_mask = EINA_TRUE;
EINA_COW_WRITE_END(evas_object_mask_cow, clip->mask, mask);
}
/* clip me */
if ((!clip->clip.clipees) && (clip->cur->visible))
{
@ -326,13 +361,6 @@ _evas_object_clip_set(Eo *eo_obj, Evas_Object_Protected_Data *obj, Evas_Object *
evas_object_update_bounding_box(eo_clip, clip);
}
/* If it's NOT a rectangle set the mask bits too */
/* FIXME: Optmz ths chck */
if (clip->type != o_rect_type)
{
ERR("Not supported clipping to type '%s', just rectangles.",
clip->type);
}
evas_object_change(eo_clip, clip);
evas_object_change(eo_obj, obj);
evas_object_clip_dirty(eo_obj, obj);
@ -399,6 +427,7 @@ _evas_object_clip_unset(Eo *eo_obj, Evas_Object_Protected_Data *obj)
}
}
*/
_evas_object_clip_mask_unset(obj->cur->clipper);
}
evas_object_change(obj->cur->clipper->object, obj->cur->clipper);
}

View File

@ -29,6 +29,8 @@
/* private magic number for image objects */
static const char o_type[] = "image";
const char *o_image_type = o_type;
/* private struct for rectangle object internal data */
typedef struct _Evas_Object_Image Evas_Image_Data;
typedef struct _Evas_Object_Image_Load_Opts Evas_Object_Image_Load_Opts;

View File

@ -28,7 +28,7 @@ static const Evas_Object_Map_Data default_map = {
};
static const Evas_Object_Protected_State default_state = {
NULL, { 0, 0, 0, 0 },
{ { 0, 0, 0, 0, 0, 0, 0, 0, EINA_FALSE, EINA_FALSE } },
{ { 0, 0, 0, 0, 0, 0, 0, 0, NULL, EINA_FALSE, EINA_FALSE } },
{ 255, 255, 255, 255 },
1.0, 0, EVAS_RENDER_BLEND, EINA_FALSE, EINA_FALSE, EINA_FALSE, EINA_FALSE, EINA_FALSE, EINA_FALSE
};
@ -36,13 +36,16 @@ static const Evas_Object_Filter_Data default_filter = {
NULL, NULL, NULL, NULL, EINA_FALSE, EINA_FALSE
};
const void * const evas_object_filter_cow_default = &default_filter;
static const Evas_Object_Mask_Data default_mask = {
NULL, 0, 0, EINA_FALSE
};
Eina_Cow *evas_object_proxy_cow = NULL;
Eina_Cow *evas_object_map_cow = NULL;
Eina_Cow *evas_object_state_cow = NULL;
Eina_Cow *evas_object_3d_cow = NULL;
Eina_Cow *evas_object_filter_cow = NULL;
Eina_Cow *evas_object_mask_cow = NULL;
static Eina_Bool
_init_cow(void)
@ -52,24 +55,26 @@ _init_cow(void)
evas_object_proxy_cow = eina_cow_add("Evas Object Proxy", sizeof (Evas_Object_Proxy_Data), 8, &default_proxy, EINA_TRUE);
evas_object_map_cow = eina_cow_add("Evas Object Map", sizeof (Evas_Object_Map_Data), 8, &default_map, EINA_TRUE);
evas_object_state_cow = eina_cow_add("Evas Object State", sizeof (Evas_Object_Protected_State), 64, &default_state, EINA_FALSE);
evas_object_3d_cow = eina_cow_add("Evas Object 3D", sizeof (Evas_Object_3D_Data), 8, &default_proxy, EINA_TRUE);
evas_object_filter_cow = eina_cow_add("Evas Filter Data", sizeof (Evas_Object_Filter_Data), 8, &default_filter, EINA_TRUE);
evas_object_mask_cow = eina_cow_add("Evas Mask Data", sizeof (Evas_Object_Mask_Data), 8, &default_mask, EINA_TRUE);
if (!(evas_object_map_cow && evas_object_proxy_cow && evas_object_state_cow && evas_object_3d_cow && evas_object_filter_cow))
if (!(evas_object_map_cow && evas_object_proxy_cow && evas_object_state_cow &&
evas_object_3d_cow && evas_object_filter_cow && evas_object_mask_cow))
{
eina_cow_del(evas_object_proxy_cow);
eina_cow_del(evas_object_map_cow);
eina_cow_del(evas_object_state_cow);
eina_cow_del(evas_object_3d_cow);
eina_cow_del(evas_object_filter_cow);
eina_cow_del(evas_object_mask_cow);
evas_object_proxy_cow = NULL;
evas_object_map_cow = NULL;
evas_object_state_cow = NULL;
eina_cow_del(evas_object_3d_cow);
evas_object_3d_cow = NULL;
eina_cow_del(evas_object_filter_cow);
evas_object_filter_cow = NULL;
evas_object_mask_cow = NULL;
return EINA_FALSE;
}
@ -97,6 +102,7 @@ _evas_object_eo_base_constructor(Eo *eo_obj, Evas_Object_Protected_Data *obj)
obj->cur = eina_cow_alloc(evas_object_state_cow);
obj->prev = eina_cow_alloc(evas_object_state_cow);
obj->data_3d = eina_cow_alloc(evas_object_3d_cow);
obj->mask = eina_cow_alloc(evas_object_mask_cow);
}
void
@ -206,6 +212,7 @@ evas_object_free(Evas_Object *eo_obj, int clean_layer)
eina_cow_free(evas_object_state_cow, (const Eina_Cow_Data**) &obj->cur);
eina_cow_free(evas_object_state_cow, (const Eina_Cow_Data**) &obj->prev);
eina_cow_free(evas_object_3d_cow, (const Eina_Cow_Data**) &obj->data_3d);
eina_cow_free(evas_object_mask_cow, (const Eina_Cow_Data**) &obj->mask);
eo_data_unref(eo_obj, obj->private_data);
obj->private_data = NULL;
@ -509,6 +516,8 @@ evas_object_render_pre_effect_updates(Eina_Array *rects, Evas_Object *eo_obj, in
}
else
{
/* This is a clipper object: add regions that changed here,
* See above: EINA_LIST_FOREACH(clipper->clip.changes) */
evas_object_clip_changes_clean(eo_obj);
EINA_ARRAY_ITER_NEXT(rects, i, r, it)
obj->clip.changes = eina_list_append(obj->clip.changes, r);

View File

@ -48,6 +48,7 @@ typedef struct _Evas_Object_Proxy_Data Evas_Object_Proxy_Data;
typedef struct _Evas_Object_Map_Data Evas_Object_Map_Data;
typedef struct _Evas_Proxy_Render_Data Evas_Proxy_Render_Data;
typedef struct _Evas_Object_3D_Data Evas_Object_3D_Data;
typedef struct _Evas_Object_Mask_Data Evas_Object_Mask_Data;
typedef struct _Evas_Object_Protected_State Evas_Object_Protected_State;
typedef struct _Evas_Object_Protected_Data Evas_Object_Protected_Data;
@ -890,6 +891,16 @@ struct _Evas_Object_3D_Data
int w, h;
};
// Mask clipper information
struct _Evas_Object_Mask_Data
{
void *surface;
int x, y, w, h;
Eina_Bool is_mask : 1;
Eina_Bool redraw : 1;
Eina_Bool is_alpha : 1;
};
struct _Evas_Object_Protected_State
{
Evas_Object_Protected_Data *clipper;
@ -899,6 +910,7 @@ struct _Evas_Object_Protected_State
struct {
Evas_Coord x, y, w, h;
unsigned char r, g, b, a;
const Evas_Object_Protected_Data *mask, *prev_mask;
Eina_Bool visible : 1;
Eina_Bool dirty : 1;
} clip;
@ -957,6 +969,7 @@ struct _Evas_Object_Protected_Data
const Evas_Object_Proxy_Data *proxy;
const Evas_Object_Map_Data *map;
const Evas_Object_3D_Data *data_3d;
const Evas_Object_Mask_Data *mask;
// Pointer to the Evas_Object itself
Evas_Object *object;
@ -1714,6 +1727,7 @@ 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_mask_subrender(Evas_Public_Data *e, Evas_Object_Protected_Data *mask, Evas_Object_Protected_Data *prev_mask);
Eina_Bool evas_map_inside_get(const Evas_Map *m, Evas_Coord x, Evas_Coord y);
Eina_Bool evas_map_coords_get(const Evas_Map *m, Evas_Coord x, Evas_Coord y, Evas_Coord *mx, Evas_Coord *my, int grab);
@ -1746,6 +1760,7 @@ extern Eina_Cow *evas_object_image_state_cow;
extern Eina_Cow *evas_object_filter_cow;
// This should be replaced by something like "eina_cow_default_get()" maybe
extern const void * const evas_object_filter_cow_default;
extern Eina_Cow *evas_object_mask_cow;
# define EINA_COW_STATE_WRITE_BEGIN(Obj, Write, State) \
EINA_COW_WRITE_BEGIN(evas_object_state_cow, Obj->State, \