forked from enlightenment/efl
evas: and for this nice international hollyday let me introduce a dynamic bounding box for smart object.
This make it possible to use the object tree to reduce the number of object, we need to explore to know what is under a specific position. First used by propagation event code. That code is now 4 times faster, enjoy ! As a side cost evas_object_move goes from 925 to 980 valgrind cycle on my computer, so not something you will notice. NOTE: if you notice any breakage regarding event propagation, map, cats, minor or major, please report to me ! I hope I didn't loose my mojo, with such a scary change, I have a big chance to get it back ! SVN revision: 70564
This commit is contained in:
parent
4bac402899
commit
0f424acb6e
|
@ -721,3 +721,7 @@
|
||||||
|
|
||||||
* Add missing files in the tarballs.
|
* Add missing files in the tarballs.
|
||||||
|
|
||||||
|
2012-05-01 Cedric Bail
|
||||||
|
|
||||||
|
* Compute limited bounding box for Smart object.
|
||||||
|
* Use bounding box to reduce the number of object explored during event propagation.
|
||||||
|
|
|
@ -5,6 +5,7 @@ Changes since Evas 1.2.0:
|
||||||
|
|
||||||
Improvements:
|
Improvements:
|
||||||
* Lock less font rendering.
|
* Lock less font rendering.
|
||||||
|
* Reduce cost of propagating event by limiting the object we explore by using a bouncing box.
|
||||||
|
|
||||||
Fixes:
|
Fixes:
|
||||||
* Add missing files in the tarball.
|
* Add missing files in the tarball.
|
||||||
|
|
|
@ -219,7 +219,12 @@ evas_object_clip_set(Evas_Object *obj, Evas_Object *clip)
|
||||||
}
|
}
|
||||||
obj->cur.clipper = clip;
|
obj->cur.clipper = clip;
|
||||||
clip->clip.clipees = eina_list_append(clip->clip.clipees, obj);
|
clip->clip.clipees = eina_list_append(clip->clip.clipees, obj);
|
||||||
if (clip->clip.clipees) clip->cur.have_clipees = 1;
|
if (clip->clip.clipees)
|
||||||
|
{
|
||||||
|
clip->cur.have_clipees = 1;
|
||||||
|
if (clip->changed)
|
||||||
|
evas_object_update_bounding_box(clip);
|
||||||
|
}
|
||||||
|
|
||||||
/* If it's NOT a rectangle set the mask bits too */
|
/* If it's NOT a rectangle set the mask bits too */
|
||||||
/* FIXME: Optmz ths chck */
|
/* FIXME: Optmz ths chck */
|
||||||
|
|
|
@ -73,6 +73,11 @@ _evas_event_object_list_raw_in_get(Evas *e, Eina_List *in,
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if (obj->child_has_map ||
|
||||||
|
(obj->cur.bounding_box.x <= x &&
|
||||||
|
obj->cur.bounding_box.x + obj->cur.bounding_box.w >= x &&
|
||||||
|
obj->cur.bounding_box.y <= y &&
|
||||||
|
obj->cur.bounding_box.y + obj->cur.bounding_box.h >= y))
|
||||||
in = _evas_event_object_list_in_get
|
in = _evas_event_object_list_in_get
|
||||||
(e, in, evas_object_smart_members_get_direct(obj),
|
(e, in, evas_object_smart_members_get_direct(obj),
|
||||||
stop, x, y, &norep);
|
stop, x, y, &norep);
|
||||||
|
|
|
@ -365,9 +365,27 @@ evas_map_inside_get(const Evas_Map *m, Evas_Coord x, Evas_Coord y)
|
||||||
return evas_map_coords_get(m, x, y, NULL, NULL, 0);
|
return evas_map_coords_get(m, x, y, NULL, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_evas_object_map_parent_check(Evas_Object *parent)
|
||||||
|
{
|
||||||
|
const Eina_Inlist *list;
|
||||||
|
const Evas_Object *o;
|
||||||
|
|
||||||
|
if (!parent) return EINA_FALSE;
|
||||||
|
|
||||||
|
list = evas_object_smart_members_get_direct(parent->smart.parent);
|
||||||
|
EINA_INLIST_FOREACH(list, o)
|
||||||
|
if (o->cur.usemap) break ;
|
||||||
|
if (o) return EINA_FALSE; /* Still some child have a map enable */
|
||||||
|
parent->child_has_map = EINA_FALSE;
|
||||||
|
_evas_object_map_parent_check(parent->smart.parent);
|
||||||
|
return EINA_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
EAPI void
|
EAPI void
|
||||||
evas_object_map_enable_set(Evas_Object *obj, Eina_Bool enabled)
|
evas_object_map_enable_set(Evas_Object *obj, Eina_Bool enabled)
|
||||||
{
|
{
|
||||||
|
Evas_Object *parents;
|
||||||
MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
|
MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
|
||||||
return;
|
return;
|
||||||
MAGIC_CHECK_END();
|
MAGIC_CHECK_END();
|
||||||
|
@ -406,6 +424,17 @@ evas_object_map_enable_set(Evas_Object *obj, Eina_Bool enabled)
|
||||||
evas_object_change(obj);
|
evas_object_change(obj);
|
||||||
if (!obj->changed_pchange) obj->changed_pchange = pchange;
|
if (!obj->changed_pchange) obj->changed_pchange = pchange;
|
||||||
obj->changed_map = EINA_TRUE;
|
obj->changed_map = EINA_TRUE;
|
||||||
|
|
||||||
|
if (enabled)
|
||||||
|
{
|
||||||
|
for (parents = obj->smart.parent; parents; parents = parents->smart.parent)
|
||||||
|
parents->child_has_map = EINA_TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (_evas_object_map_parent_check(obj->smart.parent))
|
||||||
|
evas_object_update_bounding_box(obj);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EAPI Eina_Bool
|
EAPI Eina_Bool
|
||||||
|
|
|
@ -449,6 +449,169 @@ evas_object_del(Evas_Object *obj)
|
||||||
evas_object_change(obj);
|
evas_object_change(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
evas_object_update_bounding_box(Evas_Object *obj)
|
||||||
|
{
|
||||||
|
Eina_Bool propagate = EINA_FALSE;
|
||||||
|
Evas_Coord x, y, w, h;
|
||||||
|
Evas_Coord px, py, pw, ph;
|
||||||
|
Eina_Bool clip;
|
||||||
|
|
||||||
|
if (!obj->smart.parent) return ;
|
||||||
|
if (obj->child_has_map) return ; /* Disable bounding box computation for this object and its parent */
|
||||||
|
/* We could also remove object that are not visible from the bounding box, use the clipping information
|
||||||
|
to reduce the bounding of the object they are clipping, but for the moment this will do it's jobs */
|
||||||
|
clip = !!obj->clip.clipees;
|
||||||
|
|
||||||
|
if (obj->smart.smart)
|
||||||
|
{
|
||||||
|
x = obj->cur.bounding_box.x;
|
||||||
|
y = obj->cur.bounding_box.y;
|
||||||
|
w = obj->cur.bounding_box.w;
|
||||||
|
h = obj->cur.bounding_box.h;
|
||||||
|
px = obj->prev.bounding_box.x;
|
||||||
|
py = obj->prev.bounding_box.y;
|
||||||
|
pw = obj->prev.bounding_box.w;
|
||||||
|
ph = obj->prev.bounding_box.h;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x = obj->cur.geometry.x;
|
||||||
|
y = obj->cur.geometry.y;
|
||||||
|
w = obj->cur.geometry.w;
|
||||||
|
h = obj->cur.geometry.h;
|
||||||
|
px = obj->prev.geometry.x;
|
||||||
|
py = obj->prev.geometry.y;
|
||||||
|
pw = obj->prev.geometry.w;
|
||||||
|
ph = obj->prev.geometry.h;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update left limit */
|
||||||
|
if (!clip && x < obj->smart.parent->cur.bounding_box.x)
|
||||||
|
{
|
||||||
|
obj->smart.parent->cur.bounding_box.w += obj->smart.parent->cur.bounding_box.x - x;
|
||||||
|
obj->smart.parent->cur.bounding_box.x = x;
|
||||||
|
propagate = EINA_TRUE;
|
||||||
|
}
|
||||||
|
else if ((px == obj->smart.parent->cur.bounding_box.x && x > obj->smart.parent->cur.bounding_box.x)
|
||||||
|
|| (clip && x == obj->smart.parent->cur.bounding_box.x))
|
||||||
|
{
|
||||||
|
const Eina_Inlist *list;
|
||||||
|
const Evas_Object *o;
|
||||||
|
Evas_Coord minx = clip ? obj->layer->evas->output.w : x;
|
||||||
|
|
||||||
|
list = evas_object_smart_members_get_direct(obj->smart.parent);
|
||||||
|
EINA_INLIST_FOREACH(list, o)
|
||||||
|
{
|
||||||
|
Evas_Coord tx = o->smart.smart ? o->cur.bounding_box.x : o->cur.geometry.x;
|
||||||
|
|
||||||
|
if (!o->clip.clipees && tx < minx) minx = tx;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (minx != obj->smart.parent->cur.bounding_box.x)
|
||||||
|
{
|
||||||
|
obj->smart.parent->cur.bounding_box.w += obj->smart.parent->cur.bounding_box.x - minx;
|
||||||
|
obj->smart.parent->cur.bounding_box.x = minx;
|
||||||
|
propagate = EINA_TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update top limit */
|
||||||
|
if (y < obj->smart.parent->cur.bounding_box.y)
|
||||||
|
{
|
||||||
|
obj->smart.parent->cur.bounding_box.h += obj->smart.parent->cur.bounding_box.x - x;
|
||||||
|
obj->smart.parent->cur.bounding_box.y = y;
|
||||||
|
propagate = EINA_TRUE;
|
||||||
|
}
|
||||||
|
else if ((py == obj->smart.parent->cur.bounding_box.y && y > obj->smart.parent->cur.bounding_box.y)
|
||||||
|
|| (clip && y == obj->smart.parent->cur.bounding_box.y))
|
||||||
|
{
|
||||||
|
const Eina_Inlist *list;
|
||||||
|
const Evas_Object *o;
|
||||||
|
Evas_Coord miny = clip ? obj->layer->evas->output.h : y;
|
||||||
|
|
||||||
|
list = evas_object_smart_members_get_direct(obj->smart.parent);
|
||||||
|
EINA_INLIST_FOREACH(list, o)
|
||||||
|
{
|
||||||
|
Evas_Coord ty = o->smart.smart ? o->cur.bounding_box.y : o->cur.geometry.y;
|
||||||
|
|
||||||
|
if (!o->clip.clipees && ty < miny) miny = ty;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (miny != obj->smart.parent->cur.bounding_box.y)
|
||||||
|
{
|
||||||
|
obj->smart.parent->cur.bounding_box.h += obj->smart.parent->cur.bounding_box.y - miny;
|
||||||
|
obj->smart.parent->cur.bounding_box.y = miny;
|
||||||
|
propagate = EINA_TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update right limit */
|
||||||
|
if (x + w > obj->smart.parent->cur.bounding_box.x + obj->smart.parent->cur.bounding_box.w)
|
||||||
|
{
|
||||||
|
obj->smart.parent->cur.bounding_box.w = x + w - obj->smart.parent->cur.bounding_box.x;
|
||||||
|
propagate = EINA_TRUE;
|
||||||
|
}
|
||||||
|
else if ((px + pw == obj->smart.parent->cur.bounding_box.x + obj->smart.parent->cur.bounding_box.w &&
|
||||||
|
x + w < obj->smart.parent->cur.bounding_box.x + obj->smart.parent->cur.bounding_box.w)
|
||||||
|
|| (clip && x + w == obj->smart.parent->cur.bounding_box.x + obj->smart.parent->cur.bounding_box.w))
|
||||||
|
{
|
||||||
|
const Eina_Inlist *list;
|
||||||
|
const Evas_Object *o;
|
||||||
|
Evas_Coord maxw = clip ? 0 : x + w;
|
||||||
|
|
||||||
|
list = evas_object_smart_members_get_direct(obj->smart.parent);
|
||||||
|
EINA_INLIST_FOREACH(list, o)
|
||||||
|
{
|
||||||
|
Evas_Coord tw = o->smart.smart
|
||||||
|
? o->cur.bounding_box.x + o->cur.bounding_box.w
|
||||||
|
: o->cur.geometry.x + o->cur.geometry.w;
|
||||||
|
|
||||||
|
if (!o->clip.clipees && tw > maxw) maxw = tw;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (maxw != obj->smart.parent->cur.bounding_box.x + obj->smart.parent->cur.bounding_box.w)
|
||||||
|
{
|
||||||
|
obj->smart.parent->cur.bounding_box.w = maxw - obj->smart.parent->cur.bounding_box.x;
|
||||||
|
propagate = EINA_TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update bottom limit */
|
||||||
|
if (y + h > obj->smart.parent->cur.bounding_box.y + obj->smart.parent->cur.bounding_box.h)
|
||||||
|
{
|
||||||
|
obj->smart.parent->cur.bounding_box.h = y + h - obj->smart.parent->cur.bounding_box.y;
|
||||||
|
propagate = EINA_TRUE;
|
||||||
|
}
|
||||||
|
else if ((py + ph == obj->smart.parent->cur.bounding_box.y + obj->smart.parent->cur.bounding_box.h &&
|
||||||
|
y + h < obj->smart.parent->cur.bounding_box.y + obj->smart.parent->cur.bounding_box.h) ||
|
||||||
|
(clip && y + h == obj->smart.parent->cur.bounding_box.y + obj->smart.parent->cur.bounding_box.h))
|
||||||
|
{
|
||||||
|
const Eina_Inlist *list;
|
||||||
|
const Evas_Object *o;
|
||||||
|
Evas_Coord maxh = clip ? 0 : y + h;
|
||||||
|
|
||||||
|
list = evas_object_smart_members_get_direct(obj->smart.parent);
|
||||||
|
EINA_INLIST_FOREACH(list, o)
|
||||||
|
{
|
||||||
|
Evas_Coord th = o->smart.smart
|
||||||
|
? o->cur.bounding_box.y + o->cur.bounding_box.h
|
||||||
|
: o->cur.geometry.y + o->cur.geometry.h;
|
||||||
|
|
||||||
|
if (!o->clip.clipees && th > maxh) maxh = th;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (maxh != obj->smart.parent->cur.bounding_box.y + obj->smart.parent->cur.bounding_box.h)
|
||||||
|
{
|
||||||
|
obj->smart.parent->cur.bounding_box.h = maxh - obj->smart.parent->cur.bounding_box.y;
|
||||||
|
propagate = EINA_TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (propagate)
|
||||||
|
evas_object_update_bounding_box(obj->smart.parent);
|
||||||
|
}
|
||||||
|
|
||||||
EAPI void
|
EAPI void
|
||||||
evas_object_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
|
evas_object_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
|
||||||
{
|
{
|
||||||
|
@ -505,6 +668,8 @@ evas_object_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
|
||||||
obj->cur.geometry.x = nx;
|
obj->cur.geometry.x = nx;
|
||||||
obj->cur.geometry.y = ny;
|
obj->cur.geometry.y = ny;
|
||||||
|
|
||||||
|
evas_object_update_bounding_box(obj);
|
||||||
|
|
||||||
//// obj->cur.cache.geometry.validity = 0;
|
//// obj->cur.cache.geometry.validity = 0;
|
||||||
obj->changed_move = EINA_TRUE;
|
obj->changed_move = EINA_TRUE;
|
||||||
evas_object_change(obj);
|
evas_object_change(obj);
|
||||||
|
@ -590,6 +755,8 @@ evas_object_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h)
|
||||||
obj->cur.geometry.w = nw;
|
obj->cur.geometry.w = nw;
|
||||||
obj->cur.geometry.h = nh;
|
obj->cur.geometry.h = nh;
|
||||||
|
|
||||||
|
evas_object_update_bounding_box(obj);
|
||||||
|
|
||||||
//// obj->cur.cache.geometry.validity = 0;
|
//// obj->cur.cache.geometry.validity = 0;
|
||||||
evas_object_change(obj);
|
evas_object_change(obj);
|
||||||
evas_object_clip_dirty(obj);
|
evas_object_clip_dirty(obj);
|
||||||
|
|
|
@ -509,6 +509,7 @@ struct _Evas_Object
|
||||||
Evas_Object *map_parent;
|
Evas_Object *map_parent;
|
||||||
double scale;
|
double scale;
|
||||||
Evas_Coord_Rectangle geometry;
|
Evas_Coord_Rectangle geometry;
|
||||||
|
Evas_Coord_Rectangle bounding_box;
|
||||||
struct {
|
struct {
|
||||||
struct {
|
struct {
|
||||||
Evas_Coord x, y, w, h;
|
Evas_Coord x, y, w, h;
|
||||||
|
@ -620,6 +621,7 @@ struct _Evas_Object
|
||||||
Eina_Bool del_ref : 1;
|
Eina_Bool del_ref : 1;
|
||||||
|
|
||||||
Eina_Bool is_frame : 1;
|
Eina_Bool is_frame : 1;
|
||||||
|
Eina_Bool child_has_map : 1;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _Evas_Func_Node
|
struct _Evas_Func_Node
|
||||||
|
@ -889,6 +891,7 @@ extern "C" {
|
||||||
|
|
||||||
Evas_Object *evas_object_new(Evas *e);
|
Evas_Object *evas_object_new(Evas *e);
|
||||||
void evas_object_free(Evas_Object *obj, int clean_layer);
|
void evas_object_free(Evas_Object *obj, int clean_layer);
|
||||||
|
void evas_object_update_bounding_box(Evas_Object *obj);
|
||||||
void evas_object_inject(Evas_Object *obj, Evas *e);
|
void evas_object_inject(Evas_Object *obj, Evas *e);
|
||||||
void evas_object_release(Evas_Object *obj, int clean_layer);
|
void evas_object_release(Evas_Object *obj, int clean_layer);
|
||||||
void evas_object_change(Evas_Object *obj);
|
void evas_object_change(Evas_Object *obj);
|
||||||
|
|
Loading…
Reference in New Issue