diff options
author | Laurent Ghigonis <laurent@p1sec.com> | 2013-02-27 19:44:58 +0100 |
---|---|---|
committer | Laurent Ghigonis <laurent@p1sec.com> | 2013-02-27 19:44:58 +0100 |
commit | d21bb7f6b5df682c2b41ad47a63c1dc6da0bcce2 (patch) | |
tree | bd0a2c7597f909b813e0d5ce011b59644edb4c99 /egraph | |
parent | add authors and license (diff) | |
parent | lockup ++ (diff) | |
download | glouglou-d21bb7f6b5df682c2b41ad47a63c1dc6da0bcce2.tar.xz glouglou-d21bb7f6b5df682c2b41ad47a63c1dc6da0bcce2.zip |
Merge egraph repository in glouglou repository
Diffstat (limited to 'egraph')
-rw-r--r-- | egraph/AUTHORS | 1 | ||||
-rw-r--r-- | egraph/COPYING | 15 | ||||
-rw-r--r-- | egraph/Egraph.h | 233 | ||||
-rw-r--r-- | egraph/Makefile | 38 | ||||
-rw-r--r-- | egraph/README | 47 | ||||
-rw-r--r-- | egraph/data/blob.png | bin | 0 -> 3649 bytes | |||
-rw-r--r-- | egraph/data/edge.png | bin | 0 -> 372 bytes | |||
-rw-r--r-- | egraph/data/edge.xcf | bin | 0 -> 8278 bytes | |||
-rw-r--r-- | egraph/data/vertice.png | bin | 0 -> 4488 bytes | |||
-rw-r--r-- | egraph/doc/TODO.txt | 118 | ||||
-rw-r--r-- | egraph/doc/bug_lockup_evas.txt | 646 | ||||
-rw-r--r-- | egraph/doc/egraph.xoj | bin | 0 -> 105411 bytes | |||
-rw-r--r-- | egraph/doc/internals.txt | 89 | ||||
-rw-r--r-- | egraph/egraph.c | 1275 | ||||
-rw-r--r-- | egraph/egraph.edc | 250 | ||||
-rw-r--r-- | egraph/examples/Makefile | 12 | ||||
-rw-r--r-- | egraph/examples/demoapp.c | 371 | ||||
-rw-r--r-- | egraph/examples/simplegraph.c | 59 | ||||
-rwxr-xr-x | egraph/retest.sh | 9 | ||||
-rw-r--r-- | egraph/tests/Makefile | 32 | ||||
-rw-r--r-- | egraph/tests/README.txt | 4 | ||||
-rw-r--r-- | egraph/tests/creategraph.c | 37 |
22 files changed, 3236 insertions, 0 deletions
diff --git a/egraph/AUTHORS b/egraph/AUTHORS new file mode 100644 index 0000000..4e42cdc --- /dev/null +++ b/egraph/AUTHORS @@ -0,0 +1 @@ +Laurent Ghigonis <laurent@p1sec.com> diff --git a/egraph/COPYING b/egraph/COPYING new file mode 100644 index 0000000..bae178d --- /dev/null +++ b/egraph/COPYING @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2012 Laurent Ghigonis <laurent@p1sec.com> + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ diff --git a/egraph/Egraph.h b/egraph/Egraph.h new file mode 100644 index 0000000..553d5cd --- /dev/null +++ b/egraph/Egraph.h @@ -0,0 +1,233 @@ +#include <Eina.h> +#include <Evas.h> +#include <Ecore.h> +#include <igraph/igraph.h> + +#define EGRAPH_VERTICES_MAX 16384 /* cannot be more that u_int32_t */ +#define EGRAPH_VERTICE_NAME_MAXLEN 60 + +typedef struct Egraph Egraph; +typedef struct Egraph_Edge Egraph_Edge; +typedef struct Egraph_Vertice Egraph_Vertice; + +typedef enum { + EGRAPH_LAYOUT_GRAPHOPT = 0, + EGRAPH_LAYOUT_KAMADAKAWAI = 1, + EGRAPH_LAYOUT_FRUCHTERMANREINGOLD = 2, +} Egraph_Layout; +#define EGRAPH_LAYOUT_DEFAULT EGRAPH_LAYOUT_GRAPHOPT +#define EGRAPH_LAYOUTING_IMPROVEMENTS 5 + +struct Egraph { + Evas_Object_Smart_Clipped_Data __clipped_data; + Evas_Object *obj; + Evas_Object *split_vertice_edge; + Evas *evas; + int graph_directed; + int display_vertices; + int display_names; + int display_edges; + int use_animations; + int do_improvements; + char *theme_path; + int theme_edges; + Egraph_Layout layout; + struct { + Ecore_Thread *thread; + int running; + int todo; + int changes_diff; + int improvement; /* special pass to improve the graph layout */ + } layouting; + Eina_Hash *vertices; + int vertices_count; + u_int32_t vertices_freeids[EGRAPH_VERTICES_MAX]; + int vertice_max_w; + int vertice_max_h; + Eina_List *edges; + igraph_t graph; + int graph_vcount; + igraph_matrix_t coords; + igraph_t graph2; // XXX remove use of graph here, see _repos() + int graph2_vcount; + igraph_vector_t graph2_wmin, graph2_wmax, graph2_hmin, graph2_hmax; + int graph_wmin, graph_wmax, graph_hmin, graph_hmax; + igraph_matrix_t coords2; +}; + +struct Egraph_Vertice { + u_int32_t id; + char *name; + char *type; + u_int status : 1; + Evas_Object *o; + Eina_List *edges; + Eina_List *blobs_incoming; + void *data; + u_int is_group : 1; + Eina_List *group_vertices; /* used if the vertice is a group */ + u_int new : 1; + u_int v2_new : 1; + u_int v2_del : 1; + u_int v3_new : 1; + u_int v3_del : 1; +}; + +struct Egraph_Edge { + Egraph_Vertice *a; + Egraph_Vertice *b; + char *type; + Evas_Object *o; + u_int o_usetheme : 1; + void *data; + u_int new : 1; + u_int v2_new : 1; + u_int v2_del : 1; + u_int v3_new : 1; + u_int v3_del : 1; +}; + +/** + * Creates Egraph Evas_Object + */ +Evas_Object *egraph_new(Evas *evas, int directed); + +/** + * Remove all nodes and edges + */ +void egraph_clear(Evas_Object *obj); + +/** + * Configure egraph to use an edje theme + */ +void egraph_theme_file_set(Evas_Object *obj, char *path); + +/** + * Sets if egraph should theme the edges + */ +void egraph_theme_edges_set(Evas_Object *obj, int set); + +/** + * Sets the layout of Egraph + */ +void egraph_layout_set(Evas_Object *obj, Egraph_Layout layout); + +/** + * Configure if Egraph should display vertices + */ +void egraph_display_vertices_set(Evas_Object *obj, int set); + +/** + * Configure if Egraph should display vertices names + */ +void egraph_display_names_set(Evas_Object *obj, int set); + +/** + * Configure if Egraph should display edges + */ +void egraph_display_edges_set(Evas_Object *obj, int set); + +/** + * Configure if Egraph should use animations + */ +void egraph_use_animations_set(Evas_Object *obj, int set); + +/** + * Configure if Egraph should do improvements after a graph change + */ +void egraph_do_improvements_set(Evas_Object *obj, int set); + +/** + * Adds an edge between existing vertices + * + * @param obj The Egraph object + * @param a First vertice + * @param b Second vertice + * @param data The pointer to attach + * @return The new Egraph_Egde object + */ +Egraph_Edge *egraph_edge_add(Evas_Object *obj, + Egraph_Vertice *a, Egraph_Vertice *b, void *data); + +/** + * Delete an edge + * + * Hint: This does not delete vertices + */ +void egraph_edge_del(Evas_Object *obj, Egraph_Edge *e); + +/** + * Sets the type of an edge, to make it appear differently in the graph, + * depending on theme + */ +void egraph_edge_type_set(Evas_Object *obj, + Egraph_Edge *e, const char *type); +/** + * Finds if an edge exists between 2 vertices + */ +Egraph_Edge *egraph_edge_find(Evas_Object *obj, + Egraph_Vertice *a, Egraph_Vertice *b); + +/** + * Add a vertice to the graph + * + * @param obj The Egraph object + * @param name The name of the vertice to be displayed. If NULL, no name is + * displayed + * @param data The pointer to attach + */ +Egraph_Vertice *egraph_vertice_add(Evas_Object *obj, + const char *name, void *data); + +/** + * Delete a vertice + * + * Hint: Also deletes all the edges attached to it + * + * @param obj The Egraph object + * @todo add user callback where edges are deleted + */ +void egraph_vertice_del(Evas_Object *obj, Egraph_Vertice *v); + +/** + * Update the name of a vertice + */ +void egraph_vertice_rename(Evas_Object *obj, Egraph_Vertice *v, + const char *name); + +/** + * Sets the type of a vertice, to make it appear differently in the graph, + * depending on theme + */ +void +egraph_vertice_type_set(Evas_Object *obj, Egraph_Vertice *v, const char *type); + + /** + * Send a blob from vertice to vertice + * + * A blob is a visual object that will move quickly from the first node to the + * second node. + */ +void egraph_vertice_send_blob(Evas_Object *obj, + Egraph_Vertice *a, Egraph_Vertice *b, + int size, u_int32_t color); + +/** + * Add a group of vertices, for later attaching nodes to it. + * + * The group is represented by an Egraph_Vertice with special properties. + */ +Egraph_Vertice *egraph_group_add(Evas_Object *obj, + const char *name, void *data); + +/** + * Attach a vertice to a group + */ +int egraph_group_vertice_attach(Evas_Object *obj, + Egraph_Vertice *group, Egraph_Vertice *v); + +/** + * Detach a vertice from a group + */ +void egraph_group_vertice_detach(Evas_Object *obj, + Egraph_Vertice *group, Egraph_Vertice *v); diff --git a/egraph/Makefile b/egraph/Makefile new file mode 100644 index 0000000..3aa6042 --- /dev/null +++ b/egraph/Makefile @@ -0,0 +1,38 @@ +# CFLAGS += -Werror -Wall -O2 -fPIC -shared -g +CFLAGS += -Werror -Wall -fPIC -shared -g +CFLAGS += $(shell pkg-config --libs --cflags edje) +CFLAGS += $(shell pkg-config --libs --cflags efx) +CFLAGS += $(shell pkg-config --libs --cflags igraph) + +PREFIX=/usr/local +INCLUDEDIR=$(PREFIX)/include +SHAREDIR=$(PREFIX)/share/egraph +LIBDIR=$(PREFIX)/lib + +SOURCES = egraph.c +HEADERS = Egraph.h +EDC = egraph.edc +EDJ = $(EDC:.edc=.edj) +OBJECTS = $(SOURCES:.c=.o) +LIBNAME = libegraph +TARGET = ${LIBNAME}.so + +all: $(TARGET) $(EDJ) + +$(TARGET): $(OBJECTS) + $(CC) $(CFLAGS) -o $(TARGET) $(OBJECTS) + +$(EDJ): + edje_cc $(EDC) $(EDJ) + +install: + @echo "installation of $(LIBNAME)" + mkdir -p $(LIBDIR) + mkdir -p $(INCLUDEDIR) + mkdir -p $(SHAREDIR) + install -m 0644 $(TARGET) $(LIBDIR) + install -m 0644 $(HEADERS) $(INCLUDEDIR) + install -m 0644 $(EDJ) $(SHAREDIR) + +clean: + rm -f $(TARGET) $(OBJECTS) $(EDJ) diff --git a/egraph/README b/egraph/README new file mode 100644 index 0000000..dc4be18 --- /dev/null +++ b/egraph/README @@ -0,0 +1,47 @@ +egraph - library for rendring dynamic graphs in evas + +Requirements +============ + +* Enlightenment Foundation Libraries +http://www.enlightenment.org + * eina + * evas + * ecore + * efx + +* igraph v0.6 +http://igraph.sourceforge.net/index.html + * for Ubuntu: v0.6 is *not* available in ubuntu packages +You can download it here : +http://sourceforge.net/projects/igraph/files/C%20library/0.6/igraph-0.6.tar.gz/download + * for Archlinux: yaourt -S igraph + +Installation +============ + +make +sudo make install + +You can run the demoapp in examples : +make -C examples +./examples/demoapp + +You can use OpenGL rendering : +ELM_ENGINE=opengl_x11 ./examples/demoapp + +Thanks +====== + +Thanks to ntamas (http://sixdegrees.hu/) for her advices on igraph. +Thanks to cedric for tech advices on evas / edje. +Thanks to vtorri for tech advices on evas / edje. +Thanks to zmike for tech advices on efx. +Thanks to raster for tech advices on evas / elementary. +Thanks to ludivina for graphical advices. + +History +======= + +Egraph was developped for the Glouglou Network Map (gg_map), a tool for +live computer network visualisation based on the Glouglou framework. diff --git a/egraph/data/blob.png b/egraph/data/blob.png Binary files differnew file mode 100644 index 0000000..96e4aff --- /dev/null +++ b/egraph/data/blob.png diff --git a/egraph/data/edge.png b/egraph/data/edge.png Binary files differnew file mode 100644 index 0000000..f6bbfc4 --- /dev/null +++ b/egraph/data/edge.png diff --git a/egraph/data/edge.xcf b/egraph/data/edge.xcf Binary files differnew file mode 100644 index 0000000..9481336 --- /dev/null +++ b/egraph/data/edge.xcf diff --git a/egraph/data/vertice.png b/egraph/data/vertice.png Binary files differnew file mode 100644 index 0000000..54c556b --- /dev/null +++ b/egraph/data/vertice.png diff --git a/egraph/doc/TODO.txt b/egraph/doc/TODO.txt new file mode 100644 index 0000000..beed508 --- /dev/null +++ b/egraph/doc/TODO.txt @@ -0,0 +1,118 @@ +CURRENT +======= + +vertice / vertice_text visibility will be broken +need to implement it in the edje object and send signals + +* BUG: show nodes labels does not show old nodes labels +reproduce: do not show labels, add edges, show label, add edges + +* BUG: layer stacking is wrong, edges end up on top of nodes, despite +eg->split_vertice_edge + +* BUG: vertices / vertices text fight for being on top. use evas layers ? +add 500 edges to reproduce, and watch the nodes + +TODO +==== + +* missing function declaration for static _color_int_to_rgb() +* reorder static funcs + +* BUG: sometimes when you add nodes during layouting, the graph is broken +a new edge attaches to the wrong new vertice +it seems to be always the same node numbers that gets this wrong edge + +* BUG: EGRAPH_LAYOUT_FRUCHTERMANREINGOLD is broken when adding many edges + +* zoom +10:16 < glouglou> i want to implement zooming with mouse scroll, do you have some ideas about that ? +10:16 < zmike> that should be trivial +10:16 < zmike> just hook mouse wheel and use efx_zoom +10:18 < glouglou> does efx_zoom resize the objects ? +10:18 < glouglou> all the graph is one evas smart object +10:18 < zmike> it does not resize, it just maps +10:18 < glouglou> that clips everything +10:18 < zmike> it should work, you can see the elm test is working, and that uses smart objects +10:18 < glouglou> yeah i want to update the coordinates i guess, not really "zoom" +10:19 < zmike> hm there's no efx_scale yet, but you could use efx_resize I would think +10:19 < glouglou> i would prefer to resize / update the coords +10:19 < glouglou> scale yes, that would be it +10:19 < glouglou> ok +10:19 < zmike> just calculate the size you want and use efx_resize +10:20 < zmike> it will animate the resizing + +* blobs +05:17 < glouglou> cedric: t'as vu dans ma demo les packets qui vont d'une node a l'autre quand les nodes bougent et ben les paquets arrivent a l'ancien endroit +05:17 < glouglou> j'ai regarde un peu dans efx mais j'ai pas trouve de bon moyen +05:18 < glouglou> il faudrait que les paquets ne puissent pas sortir de l'edge (le trait) entre les 2 nodes +05:18 < glouglou> si tu as une idee ... +05:22 -!- Munto [~frugal@2a01:e35:139d:91e0:221:85ff:fee1:5c3c] has quit [Read error: Connection reset by peer] +05:33 -!- sharinganex [~sharingan@233.208.85.79.rev.sfr.net] has joined #e.fr +06:22 <@cedric> glouglou: oui, swallow un smart objet +06:22 <@cedric> qui n'a qu'une seule tache faire bouger des paquets de haut en bas et de bas en haut +06:22 <@cedric> parcontre ca a un probleme, la taille des objets de tes paquets est limite par la taille de ton objet edje parent +06:40 < glouglou> cedric: mais un smart object dans un edje object qui est ensuite mappe, juste pour faire un trait, ca va etre un peu lourd non ? +06:40 < glouglou> et complexe +06:40 < glouglou> mais c'est vrai que ca resous mon probleme +06:41 <@cedric> bah, de toute facon, tu vas avoir une surface cree pour mettre ton edje dans ta map +06:41 <@cedric> dc ca reviendra au meme voir tu fairas l'economie d'une surface +06:49 < glouglou> cedric: donc quand tu swallow un evas smart object dans un edje object, les coordonnes pour le smart object sont relatifs a la part swallow ? +06:50 < glouglou> genre si je fais un geometry_get dans mon smart obj, le 0x0 sera en fait en haut a gauche de ma part swallow edje ? +06:52 <@cedric> oui +06:52 < glouglou> mais c'est magnifique +06:52 < glouglou> et splendide a fois +06:53 < glouglou> merci :D + +TODO LATER +========== + +* find a better storage type for vertices +quick access O(1) -> table +possibility to foreach and remove at the same time + +* possible future API: no edges no vertices for the user + +struct Egraph_Vertice { + const char *name; + int vertice_id; + Evas_Object *o; + void *data; +} +egraph_vertice_add(Egraph *eg, const char *name, void *data); +egraph_edge_add(Egraph *eg, + const char *a, const char *b, void *data); + +* speed: draw directly to a surface and map to evas via invisible polygons +see elementary/src/bin/test_gesture_layer3.c +04:45 < glouglou> i would like to draw directly in a surface and then give it to evas, but i want in the future to have user interaction with the nodes of my + graph, like click click reaction, so i guess i cannot escape from creating one evas object for each node and edge +04:46 <@raster> trick: +04:47 <@raster> u can just create invisible rects +04:47 < glouglou> (i can imagine crazy mapping of the clicks on my surface that triggers evas callbacks, but i'm not that crazy) +04:47 <@raster> and overlay them on your image +04:47 <@raster> use them for event stuff +04:47 < glouglou> lol +04:47 <@raster> or polygons tyoo +04:47 <@raster> thats about the only use of polygons +04:47 <@raster> as u can do exact inside/outside poly checks for events +04:48 < glouglou> i think you are talking about the crazy things i don't want to do :p +04:48 <@raster> one of the elm demos does this +04:48 <@raster> for soming/rotating with little photos +04:48 <@raster> multitouch test stuff + +* speed: from Thanatermesis : +the Core library (https://github.com/acaudwell/Core) +renders to OpenGL directly +used by : +http://code.google.com/p/logstalgia/ +https://github.com/acaudwell/Gource (http://code.google.com/p/gource/) + +OLD +=== + +* speed: evas_object_rectangles +04:40 <@raster> they add clipoouts +04:41 <@raster> make them just a bit translucent +04:41 <@raster> and it'll be faster + diff --git a/egraph/doc/bug_lockup_evas.txt b/egraph/doc/bug_lockup_evas.txt new file mode 100644 index 0000000..4f194c5 --- /dev/null +++ b/egraph/doc/bug_lockup_evas.txt @@ -0,0 +1,646 @@ +=============================================================================== +This bug is a lockup of evas during rendering in my efl app. +App freeze and takes 100% CPU. Below are backtraces when gdb was running and +I interrupt it with Ctrl-C. + +At the time of crash, around 300objects total : +elementary interface + ~100 edje + ~100 evas_object_line + +This crash is not predictible from what I see, sometimes it goes fine for a long +time. +It seem to crash more when using more edje objects. + +svn info +Revision: 79909 + +uname -a +Linux balboa 3.6.7-1-ARCH #1 SMP PREEMPT Sun Nov 18 10:11:22 CET 2012 x86_64 GNU/Linux + +=============================================================================== +2012-12-09_18-10 + +ELM_ENGINE=opengl_x11 gdb ./examples/demoapp +run + +// use the app, and it locks up during an animation (app takes 100% CPU) +// Ctrl-C + +(gdb) bt +#0 0x00007ffff7233fe6 in _calc_intra_outer_rect_area (outer=<synthetic pointer>, intra=<synthetic pointer>, a=..., b=...) at lib/evas/common/evas_tiler.c:468 +#1 rect_list_add_split_fuzzy (node=0x1967160, rects=0xdf91a8, accepted_error=<optimized out>) at lib/evas/common/evas_tiler.c:652 +#2 rect_list_add_split_fuzzy_and_merge (node=0x1967160, rects=0xdf91a8, split_accepted_error=<optimized out>, merge_accepted_error=<optimized out>) + at lib/evas/common/evas_tiler.c:849 +#3 _add_redraw (h=16, w=24, y=200, x=882, rects=0xdf91a8) at lib/evas/common/evas_tiler.c:956 +#4 evas_common_tilebuf_add_redraw (tb=0xdf9170, x=882, y=200, w=24, h=16) at lib/evas/common/evas_tiler.c:986 +#5 0x00007ffff71b2af2 in evas_object_render_pre_effect_updates (rects=0x68ad48, eo_obj=<optimized out>, is_v=1, was_v=<optimized out>) + at lib/evas/canvas/evas_object_main.c:343 +#6 0x00007ffff71f1bfc in _evas_render_phase1_direct (render_objects=0x1498d30, active_objects=0x68ab50, e=<optimized out>, restack_objects=<optimized out>, + delete_objects=<optimized out>) at lib/evas/canvas/evas_render.c:231 +#7 evas_render_updates_internal (eo_e=0x68aac0, make_updates=make_updates@entry=1 '\001', do_draw=do_draw@entry=1 '\001') at lib/evas/canvas/evas_render.c:1357 +#8 0x00007ffff71f3cd7 in _canvas_render_updates (eo_e=<optimized out>, _pd=<optimized out>, list=<optimized out>) at lib/evas/canvas/evas_render.c:1795 +#9 0x00007ffff6acba35 in _eo_op_internal (obj=0x68aac0, op_type=EO_OP_TYPE_REGULAR, op=402, p_list=0x7fffffffe1b8) at lib/eo/eo.c:363 +#10 0x00007ffff6acd6cd in _eo_dov_internal (p_list=0x7fffffffe1b8, op_type=EO_OP_TYPE_REGULAR, obj=0x68aac0) at lib/eo/eo.c:403 +#11 eo_do_internal (obj=0x68aac0, op_type=op_type@entry=EO_OP_TYPE_REGULAR) at lib/eo/eo.c:434 +#12 0x00007ffff71f3c5f in evas_render_updates (eo_e=<optimized out>) at lib/evas/canvas/evas_render.c:1779 +#13 0x00007fffe73da43a in _ecore_evas_x_render (ee=0x6892f0) at modules/ecore_evas/engines/x/ecore_evas_x.c:447 +#14 0x00007ffff68ba7f1 in _ecore_evas_idle_enter (data=<optimized out>) at lib/ecore_evas/ecore_evas.c:59 +#15 0x00007ffff6f3c019 in _ecore_call_task_cb (data=<optimized out>, func=<optimized out>) at lib/ecore/ecore_private.h:300 +#16 _ecore_idle_enterer_call () at lib/ecore/ecore_idle_enterer.c:235 +#17 0x00007ffff6f3e47b in _ecore_main_loop_iterate_internal (once_only=once_only@entry=0) at lib/ecore/ecore_main.c:1866 +#18 0x00007ffff6f3eb27 in ecore_main_loop_begin () at lib/ecore/ecore_main.c:964 +#19 0x00000000004027bf in elm_main (argc=1, argv=0x7fffffffe568) at demoapp.c:248 +#20 0x0000000000402804 in main (argc=1, argv=0x7fffffffe568) at demoapp.c:255 + +=============================================================================== + +=============================================================================== +2012-12-10_15-48 + +ELM_ENGINE=opengl_x11 gdb ./examples/demoapp +run + +// use the app, and it locks up during an animation (app takes 100% CPU) +// Ctrl-C + +^C +Program received signal SIGINT, Interrupt. +0x00007ffff7233fd3 in rect_list_add_split_fuzzy (node=0x1ce6300, rects=0x9c49b8, accepted_error=<optimized out>) at lib/evas/common/evas_tiler.c:650 +650 current = ((rect_node_t *)cur_node)->rect; +(gdb) bt +#0 0x00007ffff7233fd3 in rect_list_add_split_fuzzy (node=0x1ce6300, rects=0x9c49b8, accepted_error=<optimized out>) at lib/evas/common/evas_tiler.c:650 +#1 rect_list_add_split_fuzzy_and_merge (node=0x1ce6300, rects=0x9c49b8, split_accepted_error=<optimized out>, merge_accepted_error=<optimized out>) + at lib/evas/common/evas_tiler.c:849 +#2 _add_redraw (h=7, w=34, y=254, x=698, rects=0x9c49b8) at lib/evas/common/evas_tiler.c:956 +#3 evas_common_tilebuf_add_redraw (tb=0x9c4980, x=698, y=254, w=34, h=7) at lib/evas/common/evas_tiler.c:986 +#4 0x00007ffff71b2af2 in evas_object_render_pre_effect_updates (rects=0x68bed8, eo_obj=<optimized out>, is_v=1, was_v=<optimized out>) + at lib/evas/canvas/evas_object_main.c:343 +#5 0x00007ffff71f1bfc in _evas_render_phase1_direct (render_objects=0x139e3a0, active_objects=0x68bce0, e=<optimized out>, restack_objects=<optimized out>, + delete_objects=<optimized out>) at lib/evas/canvas/evas_render.c:231 +#6 evas_render_updates_internal (eo_e=0x68bc50, make_updates=make_updates@entry=1 '\001', do_draw=do_draw@entry=1 '\001') at lib/evas/canvas/evas_render.c:1357 +#7 0x00007ffff71f3cd7 in _canvas_render_updates (eo_e=<optimized out>, _pd=<optimized out>, list=<optimized out>) at lib/evas/canvas/evas_render.c:1795 +#8 0x00007ffff6acba35 in _eo_op_internal (obj=0x68bc50, op_type=EO_OP_TYPE_REGULAR, op=402, p_list=0x7fffffffe158) at lib/eo/eo.c:363 +#9 0x00007ffff6acd6cd in _eo_dov_internal (p_list=0x7fffffffe158, op_type=EO_OP_TYPE_REGULAR, obj=0x68bc50) at lib/eo/eo.c:403 +#10 eo_do_internal (obj=0x68bc50, op_type=op_type@entry=EO_OP_TYPE_REGULAR) at lib/eo/eo.c:434 +#11 0x00007ffff71f3c5f in evas_render_updates (eo_e=<optimized out>) at lib/evas/canvas/evas_render.c:1779 +#12 0x00007fffe73d943a in _ecore_evas_x_render (ee=0x68a480) at modules/ecore_evas/engines/x/ecore_evas_x.c:447 +#13 0x00007ffff68ba7f1 in _ecore_evas_idle_enter (data=<optimized out>) at lib/ecore_evas/ecore_evas.c:59 +#14 0x00007ffff6f3c019 in _ecore_call_task_cb (data=<optimized out>, func=<optimized out>) at lib/ecore/ecore_private.h:300 +#15 _ecore_idle_enterer_call () at lib/ecore/ecore_idle_enterer.c:235 +#16 0x00007ffff6f3e47b in _ecore_main_loop_iterate_internal (once_only=once_only@entry=0) at lib/ecore/ecore_main.c:1866 +#17 0x00007ffff6f3eb27 in ecore_main_loop_begin () at lib/ecore/ecore_main.c:964 +#18 0x00000000004028de in elm_main (argc=1, argv=0x7fffffffe508) at demoapp.c:284 +#19 0x0000000000402923 in main (argc=1, argv=0x7fffffffe508) at demoapp.c:291 + +=============================================================================== +2012-12-10_23-49 + +Lockup without opengl ! +I was using software rendering. + +gdb ./examples/demoapp +run + +// use the app, and it locks up during an animation (app takes 100% CPU) +// Ctrl-C + +^C +Program received signal SIGINT, Interrupt. +_calc_intra_outer_rect_area (outer=<synthetic pointer>, intra=<synthetic pointer>, a=..., b=...) at lib/evas/common/evas_tiler.c:524 +524 intra->area = intra->width * intra->height; +(gdb) bt +#0 _calc_intra_outer_rect_area (outer=<synthetic pointer>, intra=<synthetic pointer>, a=..., b=...) at lib/evas/common/evas_tiler.c:524 +#1 rect_list_add_split_fuzzy (node=0xb54050, rects=0x6927f8, accepted_error=<optimized out>) at lib/evas/common/evas_tiler.c:652 +#2 rect_list_add_split_fuzzy_and_merge (node=0xb54050, rects=0x6927f8, split_accepted_error=<optimized out>, merge_accepted_error=<optimized out>) + at lib/evas/common/evas_tiler.c:849 +#3 _add_redraw (h=72, w=348, y=429, x=296, rects=0x6927f8) at lib/evas/common/evas_tiler.c:956 +#4 evas_common_tilebuf_add_redraw (tb=0x6927c0, x=296, y=429, w=348, h=72) at lib/evas/common/evas_tiler.c:986 +#5 0x00007ffff71b2af2 in evas_object_render_pre_effect_updates (rects=rects@entry=0x689ac8, eo_obj=eo_obj@entry=0x8d2360, is_v=is_v@entry=1, was_v=was_v@entry= + 1) at lib/evas/canvas/evas_object_main.c:343 +#6 0x00007ffff71ab60d in evas_object_image_render_pre (eo_obj=0x8d2360, obj=0x8d23f0) at lib/evas/canvas/evas_object_image.c:3768 +#7 0x00007ffff71f1668 in evas_render_updates_internal (eo_e=0x689840, make_updates=make_updates@entry=1 '\001', do_draw=do_draw@entry=1 '\001') + at lib/evas/canvas/evas_render.c:1365 +#8 0x00007ffff71f3cd7 in _canvas_render_updates (eo_e=<optimized out>, _pd=<optimized out>, list=<optimized out>) at lib/evas/canvas/evas_render.c:1795 +#9 0x00007ffff6acba35 in _eo_op_internal (obj=0x689840, op_type=EO_OP_TYPE_REGULAR, op=402, p_list=0x7fffffffe168) at lib/eo/eo.c:363 +#10 0x00007ffff6acd6cd in _eo_dov_internal (p_list=0x7fffffffe168, op_type=EO_OP_TYPE_REGULAR, obj=0x689840) at lib/eo/eo.c:403 +#11 eo_do_internal (obj=0x689840, op_type=op_type@entry=EO_OP_TYPE_REGULAR) at lib/eo/eo.c:434 +#12 0x00007ffff71f3c5f in evas_render_updates (eo_e=<optimized out>) at lib/evas/canvas/evas_render.c:1779 +#13 0x00007fffe73d943a in _ecore_evas_x_render (ee=0x6880c0) at modules/ecore_evas/engines/x/ecore_evas_x.c:447 +#14 0x00007ffff68ba7f1 in _ecore_evas_idle_enter (data=<optimized out>) at lib/ecore_evas/ecore_evas.c:59 +#15 0x00007ffff6f3c019 in _ecore_call_task_cb (data=<optimized out>, func=<optimized out>) at lib/ecore/ecore_private.h:300 +#16 _ecore_idle_enterer_call () at lib/ecore/ecore_idle_enterer.c:235 +#17 0x00007ffff6f3e47b in _ecore_main_loop_iterate_internal (once_only=once_only@entry=0) at lib/ecore/ecore_main.c:1866 +#18 0x00007ffff6f3eb27 in ecore_main_loop_begin () at lib/ecore/ecore_main.c:964 +#19 0x00000000004028de in elm_main (argc=1, argv=0x7fffffffe518) at demoapp.c:284 +#20 0x0000000000402923 in main (argc=1, argv=0x7fffffffe518) at demoapp.c:291 + +=============================================================================== +2012-12-10_23-58 + +// Same scenario + +^C +Program received signal SIGINT, Interrupt. +rect_list_add_split_fuzzy (node=0xfe0150, rects=0x6927f8, accepted_error=<optimized out>) at lib/evas/common/evas_tiler.c:653 +653 area = current.area + r.area - intra.area; +(gdb) bt +#0 rect_list_add_split_fuzzy (node=0xfe0150, rects=0x6927f8, accepted_error=<optimized out>) at lib/evas/common/evas_tiler.c:653 +#1 rect_list_add_split_fuzzy_and_merge (node=0xfe0150, rects=0x6927f8, split_accepted_error=<optimized out>, merge_accepted_error=<optimized out>) + at lib/evas/common/evas_tiler.c:849 +#2 _add_redraw (h=63, w=85, y=314, x=493, rects=0x6927f8) at lib/evas/common/evas_tiler.c:956 +#3 evas_common_tilebuf_add_redraw (tb=0x6927c0, x=493, y=314, w=85, h=63) at lib/evas/common/evas_tiler.c:986 +#4 0x00007ffff71b2b9d in evas_object_render_pre_effect_updates (rects=0x689ac8, eo_obj=<optimized out>, is_v=1, was_v=<optimized out>) + at lib/evas/canvas/evas_object_main.c:356 +#5 0x00007ffff71f1bfc in _evas_render_phase1_direct (render_objects=0x1b79f50, active_objects=0x6898d0, e=<optimized out>, restack_objects=<optimized out>, + delete_objects=<optimized out>) at lib/evas/canvas/evas_render.c:231 +#6 evas_render_updates_internal (eo_e=0x689840, make_updates=make_updates@entry=1 '\001', do_draw=do_draw@entry=1 '\001') at lib/evas/canvas/evas_render.c:1357 +#7 0x00007ffff71f3cd7 in _canvas_render_updates (eo_e=<optimized out>, _pd=<optimized out>, list=<optimized out>) at lib/evas/canvas/evas_render.c:1795 +#8 0x00007ffff6acba35 in _eo_op_internal (obj=0x689840, op_type=EO_OP_TYPE_REGULAR, op=402, p_list=0x7fffffffe168) at lib/eo/eo.c:363 +#9 0x00007ffff6acd6cd in _eo_dov_internal (p_list=0x7fffffffe168, op_type=EO_OP_TYPE_REGULAR, obj=0x689840) at lib/eo/eo.c:403 +#10 eo_do_internal (obj=0x689840, op_type=op_type@entry=EO_OP_TYPE_REGULAR) at lib/eo/eo.c:434 +#11 0x00007ffff71f3c5f in evas_render_updates (eo_e=<optimized out>) at lib/evas/canvas/evas_render.c:1779 +#12 0x00007fffe73d943a in _ecore_evas_x_render (ee=0x6880c0) at modules/ecore_evas/engines/x/ecore_evas_x.c:447 +#13 0x00007ffff68ba7f1 in _ecore_evas_idle_enter (data=<optimized out>) at lib/ecore_evas/ecore_evas.c:59 +#14 0x00007ffff6f3c019 in _ecore_call_task_cb (data=<optimized out>, func=<optimized out>) at lib/ecore/ecore_private.h:300 +#15 _ecore_idle_enterer_call () at lib/ecore/ecore_idle_enterer.c:235 +#16 0x00007ffff6f3e47b in _ecore_main_loop_iterate_internal (once_only=once_only@entry=0) at lib/ecore/ecore_main.c:1866 +#17 0x00007ffff6f3eb27 in ecore_main_loop_begin () at lib/ecore/ecore_main.c:964 +#18 0x00000000004028de in elm_main (argc=1, argv=0x7fffffffe518) at demoapp.c:284 +#19 0x0000000000402923 in main (argc=1, argv=0x7fffffffe518) at demoapp.c:291 + +=============================================================================== +2012-12-11_00-34 + +// Same scenario + +^C +Program received signal SIGINT, Interrupt. +rect_list_add_split_fuzzy (node=0xb54370, rects=0x6927f8, accepted_error=<optimized out>) at lib/evas/common/evas_tiler.c:702 +702 else if (intra.area <= accepted_error) +(gdb) bt +#0 rect_list_add_split_fuzzy (node=0xb54370, rects=0x6927f8, accepted_error=<optimized out>) at lib/evas/common/evas_tiler.c:702 +#1 rect_list_add_split_fuzzy_and_merge (node=0xb54370, rects=0x6927f8, split_accepted_error=<optimized out>, merge_accepted_error=<optimized out>) + at lib/evas/common/evas_tiler.c:849 +#2 _add_redraw (h=39, w=49, y=156, x=486, rects=0x6927f8) at lib/evas/common/evas_tiler.c:956 +#3 evas_common_tilebuf_add_redraw (tb=0x6927c0, x=486, y=156, w=49, h=39) at lib/evas/common/evas_tiler.c:986 +#4 0x00007ffff71b2af2 in evas_object_render_pre_effect_updates (rects=0x689ac8, eo_obj=<optimized out>, is_v=1, was_v=<optimized out>) + at lib/evas/canvas/evas_object_main.c:343 +#5 0x00007ffff71f1bfc in _evas_render_phase1_direct (render_objects=0x1671880, active_objects=0x6898d0, e=<optimized out>, restack_objects=<optimized out>, + delete_objects=<optimized out>) at lib/evas/canvas/evas_render.c:231 +#6 evas_render_updates_internal (eo_e=0x689840, make_updates=make_updates@entry=1 '\001', do_draw=do_draw@entry=1 '\001') at lib/evas/canvas/evas_render.c:1357 +#7 0x00007ffff71f3cd7 in _canvas_render_updates (eo_e=<optimized out>, _pd=<optimized out>, list=<optimized out>) at lib/evas/canvas/evas_render.c:1795 +#8 0x00007ffff6acba35 in _eo_op_internal (obj=0x689840, op_type=EO_OP_TYPE_REGULAR, op=402, p_list=0x7fffffffe168) at lib/eo/eo.c:363 +#9 0x00007ffff6acd6cd in _eo_dov_internal (p_list=0x7fffffffe168, op_type=EO_OP_TYPE_REGULAR, obj=0x689840) at lib/eo/eo.c:403 +#10 eo_do_internal (obj=0x689840, op_type=op_type@entry=EO_OP_TYPE_REGULAR) at lib/eo/eo.c:434 +#11 0x00007ffff71f3c5f in evas_render_updates (eo_e=<optimized out>) at lib/evas/canvas/evas_render.c:1779 +#12 0x00007fffe73d943a in _ecore_evas_x_render (ee=0x6880c0) at modules/ecore_evas/engines/x/ecore_evas_x.c:447 +#13 0x00007ffff68ba7f1 in _ecore_evas_idle_enter (data=<optimized out>) at lib/ecore_evas/ecore_evas.c:59 +#14 0x00007ffff6f3c019 in _ecore_call_task_cb (data=<optimized out>, func=<optimized out>) at lib/ecore/ecore_private.h:300 +#15 _ecore_idle_enterer_call () at lib/ecore/ecore_idle_enterer.c:235 +#16 0x00007ffff6f3e47b in _ecore_main_loop_iterate_internal (once_only=once_only@entry=0) at lib/ecore/ecore_main.c:1866 +#17 0x00007ffff6f3eb27 in ecore_main_loop_begin () at lib/ecore/ecore_main.c:964 +#18 0x00000000004028de in elm_main (argc=1, argv=0x7fffffffe518) at demoapp.c:284 +#19 0x0000000000402923 in main (argc=1, argv=0x7fffffffe518) at demoapp.c:291 + +=============================================================================== +2012-12-11_05-39 + +Without any evas_object_line + +^C +Program received signal SIGINT, Interrupt. +rect_list_add_split_fuzzy (node=0xcf4c20, rects=0x692788, accepted_error=<optimized out>) at lib/evas/common/evas_tiler.c:650 +650 current = ((rect_node_t *)cur_node)->rect; +(gdb) bt +#0 rect_list_add_split_fuzzy (node=0xcf4c20, rects=0x692788, accepted_error=<optimized out>) at lib/evas/common/evas_tiler.c:650 +#1 rect_list_add_split_fuzzy_and_merge (node=0xcf4c20, rects=0x692788, split_accepted_error=<optimized out>, merge_accepted_error=<optimized out>) + at lib/evas/common/evas_tiler.c:849 +#2 _add_redraw (h=16, w=1047, y=240, x=263, rects=0x692788) at lib/evas/common/evas_tiler.c:956 +#3 evas_common_tilebuf_add_redraw (tb=0x692750, x=263, y=240, w=1047, h=16) at lib/evas/common/evas_tiler.c:986 +#4 0x00007ffff71b2af2 in evas_object_render_pre_effect_updates (rects=rects@entry=0x689a58, eo_obj=eo_obj@entry=0x1100690, is_v=is_v@entry=1, + was_v=was_v@entry=1) at lib/evas/canvas/evas_object_main.c:343 +#5 0x00007ffff71ab60d in evas_object_image_render_pre (eo_obj=0x1100690, obj=0x1100720) at lib/evas/canvas/evas_object_image.c:3768 +#6 0x00007ffff71f1bfc in _evas_render_phase1_direct (render_objects=0x1100690, active_objects=0x689860, e=<optimized out>, restack_objects=<optimized out>, + delete_objects=<optimized out>) at lib/evas/canvas/evas_render.c:231 +#7 evas_render_updates_internal (eo_e=0x6897d0, make_updates=make_updates@entry=1 '\001', do_draw=do_draw@entry=1 '\001') at lib/evas/canvas/evas_render.c:1357 +#8 0x00007ffff71f3cd7 in _canvas_render_updates (eo_e=<optimized out>, _pd=<optimized out>, list=<optimized out>) at lib/evas/canvas/evas_render.c:1795 +#9 0x00007ffff6acba35 in _eo_op_internal (obj=0x6897d0, op_type=EO_OP_TYPE_REGULAR, op=402, p_list=0x7fffffffe1d8) at lib/eo/eo.c:363 +#10 0x00007ffff6acd6cd in _eo_dov_internal (p_list=0x7fffffffe1d8, op_type=EO_OP_TYPE_REGULAR, obj=0x6897d0) at lib/eo/eo.c:403 +#11 eo_do_internal (obj=0x6897d0, op_type=op_type@entry=EO_OP_TYPE_REGULAR) at lib/eo/eo.c:434 +#12 0x00007ffff71f3c5f in evas_render_updates (eo_e=<optimized out>) at lib/evas/canvas/evas_render.c:1779 +#13 0x00007fffe73d743a in _ecore_evas_x_render (ee=0x688050) at modules/ecore_evas/engines/x/ecore_evas_x.c:447 +#14 0x00007ffff68ba7f1 in _ecore_evas_idle_enter (data=<optimized out>) at lib/ecore_evas/ecore_evas.c:59 +#15 0x00007ffff6f3c019 in _ecore_call_task_cb (data=<optimized out>, func=<optimized out>) at lib/ecore/ecore_private.h:300 +#16 _ecore_idle_enterer_call () at lib/ecore/ecore_idle_enterer.c:235 +#17 0x00007ffff6f3e47b in _ecore_main_loop_iterate_internal (once_only=once_only@entry=0) at lib/ecore/ecore_main.c:1866 +#18 0x00007ffff6f3eb27 in ecore_main_loop_begin () at lib/ecore/ecore_main.c:964 +#19 0x00000000004028ce in elm_main (argc=1, argv=0x7fffffffe588) at demoapp.c:284 +#20 0x0000000000402913 in main (argc=1, argv=0x7fffffffe588) at demoapp.c:291 + +=============================================================================== +2012-12-11_05-42 + +with 500 nodes = 1500 objects, no evas_object_line, but 500 evas_map + +^C +Program received signal SIGINT, Interrupt. +_calc_intra_outer_rect_area (outer=<synthetic pointer>, intra=<synthetic pointer>, a=..., b=...) at lib/evas/common/evas_tiler.c:498 +498 if (a.top < b.top) +(gdb) bt +#0 _calc_intra_outer_rect_area (outer=<synthetic pointer>, intra=<synthetic pointer>, a=..., b=...) at lib/evas/common/evas_tiler.c:498 +#1 rect_list_add_split_fuzzy (node=0x1acbb00, rects=0x93f238, accepted_error=<optimized out>) at lib/evas/common/evas_tiler.c:652 +#2 rect_list_add_split_fuzzy_and_merge (node=0x1acbb00, rects=0x93f238, split_accepted_error=<optimized out>, merge_accepted_error=<optimized out>) + at lib/evas/common/evas_tiler.c:849 +#3 _add_redraw (h=52, w=371, y=437, x=826, rects=0x93f238) at lib/evas/common/evas_tiler.c:956 +#4 evas_common_tilebuf_add_redraw (tb=0x93f200, x=826, y=437, w=371, h=52) at lib/evas/common/evas_tiler.c:986 +#5 0x00007ffff71ed67f in _evas_render_prev_cur_clip_cache_add (obj=obj@entry=0x1c752b0, e=0x68bc90, e=0x68bc90) at lib/evas/canvas/evas_render.c:158 +#6 0x00007ffff71ee940 in _evas_render_phase1_object_process (e=e@entry=0x68bc90, eo_obj=0x1c75220, active_objects=active_objects@entry=0x68bda8, + restack_objects=restack_objects@entry=0x68bdc8, delete_objects=delete_objects@entry=0x68bd88, render_objects=render_objects@entry=0x68bde8, restack=0, + redraw_all=redraw_all@entry=0x7fffffffe0ec, mapped_parent=mapped_parent@entry=0 '\000') at lib/evas/canvas/evas_render.c:355 +#7 0x00007ffff71eeaf6 in _evas_render_phase1_object_process (e=e@entry=0x68bc90, eo_obj=<optimized out>, active_objects=active_objects@entry=0x68bda8, + restack_objects=restack_objects@entry=0x68bdc8, delete_objects=delete_objects@entry=0x68bd88, render_objects=render_objects@entry=0x68bde8, restack=0, + redraw_all=redraw_all@entry=0x7fffffffe0ec, mapped_parent=mapped_parent@entry=0 '\000') at lib/evas/canvas/evas_render.c:413 +#8 0x00007ffff71eeaf6 in _evas_render_phase1_object_process (e=e@entry=0x68bc90, eo_obj=<optimized out>, active_objects=active_objects@entry=0x68bda8, + restack_objects=restack_objects@entry=0x68bdc8, delete_objects=delete_objects@entry=0x68bd88, render_objects=render_objects@entry=0x68bde8, restack=0, + redraw_all=redraw_all@entry=0x7fffffffe0ec, mapped_parent=mapped_parent@entry=0 '\000') at lib/evas/canvas/evas_render.c:413 +#9 0x00007ffff71eeaf6 in _evas_render_phase1_object_process (e=e@entry=0x68bc90, eo_obj=<optimized out>, active_objects=active_objects@entry=0x68bda8, + restack_objects=restack_objects@entry=0x68bdc8, delete_objects=delete_objects@entry=0x68bd88, render_objects=render_objects@entry=0x68bde8, restack=0, + redraw_all=redraw_all@entry=0x7fffffffe0ec, mapped_parent=mapped_parent@entry=0 '\000') at lib/evas/canvas/evas_render.c:413 +#10 0x00007ffff71eeaf6 in _evas_render_phase1_object_process (e=e@entry=0x68bc90, eo_obj=<optimized out>, active_objects=active_objects@entry=0x68bda8, + restack_objects=restack_objects@entry=0x68bdc8, delete_objects=delete_objects@entry=0x68bd88, render_objects=render_objects@entry=0x68bde8, restack=0, + redraw_all=redraw_all@entry=0x7fffffffe0ec, mapped_parent=mapped_parent@entry=0 '\000') at lib/evas/canvas/evas_render.c:413 +#11 0x00007ffff71eeaf6 in _evas_render_phase1_object_process (e=e@entry=0x68bc90, eo_obj=<optimized out>, active_objects=active_objects@entry=0x68bda8, + restack_objects=restack_objects@entry=0x68bdc8, delete_objects=delete_objects@entry=0x68bd88, render_objects=render_objects@entry=0x68bde8, + restack=restack@entry=0, redraw_all=redraw_all@entry=0x7fffffffe0ec, mapped_parent=mapped_parent@entry=0 '\000') at lib/evas/canvas/evas_render.c:413 +#12 0x00007ffff71f0f29 in _evas_render_phase1_process (redraw_all=0x7fffffffe0dc, render_objects=0x68bde8, delete_objects=0x68bd88, restack_objects=0x68bdc8, + active_objects=0x68bda8, e=0x68bc90) at lib/evas/canvas/evas_render.c:557 +#13 evas_render_updates_internal (eo_e=0x68bc00, make_updates=make_updates@entry=1 '\001', do_draw=do_draw@entry=1 '\001') at lib/evas/canvas/evas_render.c:1337 +#14 0x00007ffff71f3cd7 in _canvas_render_updates (eo_e=<optimized out>, _pd=<optimized out>, list=<optimized out>) at lib/evas/canvas/evas_render.c:1795 +#15 0x00007ffff6acba35 in _eo_op_internal (obj=0x68bc00, op_type=EO_OP_TYPE_REGULAR, op=402, p_list=0x7fffffffe1b8) at lib/eo/eo.c:363 +#16 0x00007ffff6acd6cd in _eo_dov_internal (p_list=0x7fffffffe1b8, op_type=EO_OP_TYPE_REGULAR, obj=0x68bc00) at lib/eo/eo.c:403 +#17 eo_do_internal (obj=0x68bc00, op_type=op_type@entry=EO_OP_TYPE_REGULAR) at lib/eo/eo.c:434 +#18 0x00007ffff71f3c5f in evas_render_updates (eo_e=<optimized out>) at lib/evas/canvas/evas_render.c:1779 +#19 0x00007fffe73d743a in _ecore_evas_x_render (ee=0x68a430) at modules/ecore_evas/engines/x/ecore_evas_x.c:447 +#20 0x00007ffff68ba7f1 in _ecore_evas_idle_enter (data=<optimized out>) at lib/ecore_evas/ecore_evas.c:59 +#21 0x00007ffff6f3c019 in _ecore_call_task_cb (data=<optimized out>, func=<optimized out>) at lib/ecore/ecore_private.h:300 +#22 _ecore_idle_enterer_call () at lib/ecore/ecore_idle_enterer.c:235 +#23 0x00007ffff6f3e47b in _ecore_main_loop_iterate_internal (once_only=once_only@entry=0) at lib/ecore/ecore_main.c:1866 +#24 0x00007ffff6f3eb27 in ecore_main_loop_begin () at lib/ecore/ecore_main.c:964 +#25 0x00000000004028ce in elm_main (argc=1, argv=0x7fffffffe568) at demoapp.c:284 +#26 0x0000000000402913 in main (argc=1, argv=0x7fffffffe568) at demoapp.c:291 + + +=============================================================================== +2012-12-13_06-32 + + +(gdb) bt +#0 0x00007ffff53ddff7 in _calc_intra_outer_rect_area ( + outer=<synthetic pointer>, intra=<synthetic pointer>, a=..., b=...) + at lib/evas/common/evas_tiler.c:479 +#1 rect_list_add_split_fuzzy (node=0x8ed9c0, rects=0x691668, + accepted_error=<optimized out>) at lib/evas/common/evas_tiler.c:652 +#2 rect_list_add_split_fuzzy_and_merge (node=0x8ed9c0, rects=0x691668, + split_accepted_error=<optimized out>, merge_accepted_error=<optimized out>) + at lib/evas/common/evas_tiler.c:849 +#3 _add_redraw (h=115, w=327, y=203, x=504, rects=0x691668) + at lib/evas/common/evas_tiler.c:956 +#4 evas_common_tilebuf_add_redraw (tb=0x691630, x=504, y=203, w=327, h=115) + at lib/evas/common/evas_tiler.c:986 +#5 0x00007ffff535cb9d in evas_object_render_pre_effect_updates (rects= + 0x688938, eo_obj=<optimized out>, is_v=1, was_v=<optimized out>) + at lib/evas/canvas/evas_object_main.c:356 +#6 0x00007ffff539bbfc in _evas_render_phase1_direct (render_objects=0x9baa60, + active_objects=0x688740, e=<optimized out>, + restack_objects=<optimized out>, delete_objects=<optimized out>) + at lib/evas/canvas/evas_render.c:231 +#7 evas_render_updates_internal (eo_e=0x6886b0, + make_updates=make_updates@entry=1 '\001', do_draw=do_draw@entry=1 '\001') + at lib/evas/canvas/evas_render.c:1357 +#8 0x00007ffff539dcd7 in _canvas_render_updates (eo_e=<optimized out>, + _pd=<optimized out>, list=<optimized out>) + at lib/evas/canvas/evas_render.c:1795 +#9 0x00007ffff706fa35 in _eo_op_internal (obj=0x6886b0, op_type= + EO_OP_TYPE_REGULAR, op=402, p_list=0x7fffffffe228) at lib/eo/eo.c:363 +#10 0x00007ffff70716cd in _eo_dov_internal (p_list=0x7fffffffe228, op_type= + EO_OP_TYPE_REGULAR, obj=0x6886b0) at lib/eo/eo.c:403 +#11 eo_do_internal (obj=0x6886b0, op_type=op_type@entry=EO_OP_TYPE_REGULAR) + at lib/eo/eo.c:434 +#12 0x00007ffff539dc5f in evas_render_updates (eo_e=<optimized out>) + at lib/evas/canvas/evas_render.c:1779 +#13 0x00007fffe6f7a43a in _ecore_evas_x_render (ee=0x686f30) + at modules/ecore_evas/engines/x/ecore_evas_x.c:447 +#14 0x00007ffff6e5e7f1 in _ecore_evas_idle_enter (data=<optimized out>) + at lib/ecore_evas/ecore_evas.c:59 +#15 0x00007ffff50e6019 in _ecore_call_task_cb (data=<optimized out>, + func=<optimized out>) at lib/ecore/ecore_private.h:300 +#16 _ecore_idle_enterer_call () at lib/ecore/ecore_idle_enterer.c:235 +#17 0x00007ffff50e862d in _ecore_main_loop_iterate_internal ( + once_only=once_only@entry=0) at lib/ecore/ecore_main.c:1841 +#18 0x00007ffff50e8b27 in ecore_main_loop_begin () at lib/ecore/ecore_main.c:964 +#19 0x000000000040230e in elm_main (argc=1, argv=0x7fffffffe5b8) at gg_map.c:269 +#20 0x0000000000402359 in main (argc=1, argv=0x7fffffffe5b8) at gg_map.c:276 + + +=============================================================================== +2012-12-13_06-42 + +^C +Program received signal SIGINT, Interrupt. +rect_list_add_split_fuzzy (node=0x884d70, rects=0x691668, + accepted_error=<optimized out>) at lib/evas/common/evas_tiler.c:653 +653 area = current.area + r.area - intra.area; + +(gdb) bt +#0 rect_list_add_split_fuzzy (node=0x884d70, rects=0x691668, + accepted_error=<optimized out>) at lib/evas/common/evas_tiler.c:653 +#1 rect_list_add_split_fuzzy_and_merge (node=0x884d70, rects=0x691668, + split_accepted_error=<optimized out>, merge_accepted_error=<optimized out>) + at lib/evas/common/evas_tiler.c:849 +#2 _add_redraw (h=12, w=542, y=356, x=118, rects=0x691668) + at lib/evas/common/evas_tiler.c:956 +#3 evas_common_tilebuf_add_redraw (tb=tb@entry=0x691630, x=118, y=356, w=542, + h=12) at lib/evas/common/evas_tiler.c:986 +#4 0x00007fffe6d672ac in _merge_rects (tb=0x691630, r1=<optimized out>, r2= + 0x0, r3=0x0) at modules/evas/engines/software_x11/evas_engine.c:713 +#5 0x00007fffe6d6759b in eng_output_redraws_next_update_get (data=0x691c00, x= + 0x7fffffffe13c, y=0x7fffffffe140, w=0x7fffffffe144, h=0x7fffffffe148, + cx=<optimized out>, cy=0x7fffffffe150, cw=0x7fffffffe154, ch= + 0x7fffffffe158) at modules/evas/engines/software_x11/evas_engine.c:821 +#6 0x00007ffff539bf4f in evas_render_updates_internal (eo_e=0x6886b0, + make_updates=make_updates@entry=1 '\001', do_draw=do_draw@entry=1 '\001') + at lib/evas/canvas/evas_render.c:1533 +#7 0x00007ffff539dcd7 in _canvas_render_updates (eo_e=<optimized out>, + _pd=<optimized out>, list=<optimized out>) + at lib/evas/canvas/evas_render.c:1795 +#8 0x00007ffff706fa35 in _eo_op_internal (obj=0x6886b0, op_type= + EO_OP_TYPE_REGULAR, op=402, p_list=0x7fffffffe228) at lib/eo/eo.c:363 +#9 0x00007ffff70716cd in _eo_dov_internal (p_list=0x7fffffffe228, op_type= + EO_OP_TYPE_REGULAR, obj=0x6886b0) at lib/eo/eo.c:403 +#10 eo_do_internal (obj=0x6886b0, op_type=op_type@entry=EO_OP_TYPE_REGULAR) + at lib/eo/eo.c:434 +#11 0x00007ffff539dc5f in evas_render_updates (eo_e=<optimized out>) + at lib/evas/canvas/evas_render.c:1779 +#12 0x00007fffe6f7a43a in _ecore_evas_x_render (ee=0x686f30) + at modules/ecore_evas/engines/x/ecore_evas_x.c:447 +#13 0x00007ffff6e5e7f1 in _ecore_evas_idle_enter (data=<optimized out>) + at lib/ecore_evas/ecore_evas.c:59 +#14 0x00007ffff50e6019 in _ecore_call_task_cb (data=<optimized out>, + func=<optimized out>) at lib/ecore/ecore_private.h:300 +#15 _ecore_idle_enterer_call () at lib/ecore/ecore_idle_enterer.c:235 +#16 0x00007ffff50e847b in _ecore_main_loop_iterate_internal ( + once_only=once_only@entry=0) at lib/ecore/ecore_main.c:1866 +#17 0x00007ffff50e8b27 in ecore_main_loop_begin () + at lib/ecore/ecore_main.c:964 +#18 0x000000000040230e in elm_main (argc=1, argv=0x7fffffffe5b8) + at gg_map.c:269 +#19 0x0000000000402359 in main (argc=1, argv=0x7fffffffe5b8) at gg_map.c:276 + +=============================================================================== +2012-12-13_15-32 + +^C 0x7fffe6d61700 (LWP 21696)] +[Thread 0x7fffe6d61700 (LWP 21696) exited] +[New Thread 0x7fffe6d61700 (LWP 21697)] +[Thread 0x7fffe6d61700 (LWP 21697) exited] +[New Thread 0x7fffe6d61700 (LWP 21711)] +[Thread 0x7fffe6d61700 (LWP 21711) exited] +[New Thread 0x7fffe6d61700 (LWP 21712)] +[Thread 0x7fffe6d61700 (LWP 21712) exited] + +Program received signal SIGINT, Interrupt. +rect_list_add_split_fuzzy (node=0xa977b0, rects=0x691668, + accepted_error=<optimized out>) at lib/evas/common/evas_tiler.c:680 +680 else if ((outer.area - area) <= accepted_error) + + +(gdb) bt +#0 rect_list_add_split_fuzzy (node=0xa977b0, rects=0x691668, + accepted_error=<optimized out>) at lib/evas/common/evas_tiler.c:680 +#1 rect_list_add_split_fuzzy_and_merge (node=0xa977b0, rects=0x691668, + split_accepted_error=<optimized out>, merge_accepted_error=<optimized out>) + at lib/evas/common/evas_tiler.c:849 +#2 _add_redraw (h=6, w=126, y=110, x=463, rects=0x691668) + at lib/evas/common/evas_tiler.c:956 +#3 evas_common_tilebuf_add_redraw (tb=0x691630, x=463, y=110, w=126, h=6) + at lib/evas/common/evas_tiler.c:986 +#4 0x00007ffff535cb9d in evas_object_render_pre_effect_updates ( + rects=rects@entry=0x688938, eo_obj=eo_obj@entry=0xa83500, is_v=is_v@entry= + 1, was_v=was_v@entry=1) at lib/evas/canvas/evas_object_main.c:356 +#5 0x00007ffff535560d in evas_object_image_render_pre (eo_obj=0xa83500, obj= + 0xa83590) at lib/evas/canvas/evas_object_image.c:3768 +#6 0x00007ffff539bbfc in _evas_render_phase1_direct (render_objects=0xa83500, + active_objects=0x688740, e=<optimized out>, + restack_objects=<optimized out>, delete_objects=<optimized out>) + at lib/evas/canvas/evas_render.c:231 +#7 evas_render_updates_internal (eo_e=0x6886b0, + make_updates=make_updates@entry=1 '\001', do_draw=do_draw@entry=1 '\001') + at lib/evas/canvas/evas_render.c:1357 +#8 0x00007ffff539dcd7 in _canvas_render_updates (eo_e=<optimized out>, + _pd=<optimized out>, list=<optimized out>) + at lib/evas/canvas/evas_render.c:1795 +#9 0x00007ffff706fa35 in _eo_op_internal (obj=0x6886b0, op_type= + EO_OP_TYPE_REGULAR, op=402, p_list=0x7fffffffe228) at lib/eo/eo.c:363 +#10 0x00007ffff70716cd in _eo_dov_internal (p_list=0x7fffffffe228, op_type= + EO_OP_TYPE_REGULAR, obj=0x6886b0) at lib/eo/eo.c:403 +#11 eo_do_internal (obj=0x6886b0, op_type=op_type@entry=EO_OP_TYPE_REGULAR) + at lib/eo/eo.c:434 +#12 0x00007ffff539dc5f in evas_render_updates (eo_e=<optimized out>) + at lib/evas/canvas/evas_render.c:1779 +#13 0x00007fffe6f7943a in _ecore_evas_x_render (ee=0x686f30) + at modules/ecore_evas/engines/x/ecore_evas_x.c:447 +#14 0x00007ffff6e5e7f1 in _ecore_evas_idle_enter (data=<optimized out>) + at lib/ecore_evas/ecore_evas.c:59 +#15 0x00007ffff50e6019 in _ecore_call_task_cb (data=<optimized out>, + func=<optimized out>) at lib/ecore/ecore_private.h:300 +#16 _ecore_idle_enterer_call () at lib/ecore/ecore_idle_enterer.c:235 +#17 0x00007ffff50e847b in _ecore_main_loop_iterate_internal ( + once_only=once_only@entry=0) at lib/ecore/ecore_main.c:1866 +#18 0x00007ffff50e8b27 in ecore_main_loop_begin () + at lib/ecore/ecore_main.c:964 +#19 0x00000000004022f1 in elm_main (argc=1, argv=0x7fffffffe5b8) + at gg_map.c:273 +#20 0x000000000040233c in main (argc=1, argv=0x7fffffffe5b8) at gg_map.c:280 +(gdb) + + +=============================================================================== +2012-12-13_17-19 + + +rect_list_add_split_fuzzy (node=0xb07d60, rects=0x692668, [0/1873] + accepted_error=<optimized out>) at lib/evas/common/evas_tiler.c:653 +653 area = current.area + r.area - intra.area; +(gdb) bt +#0 rect_list_add_split_fuzzy (node=0xb07d60, rects=0x692668, + accepted_error=<optimized out>) at lib/evas/common/evas_tiler.c:653 +#1 rect_list_add_split_fuzzy_and_merge (node=0xb07d60, rects=0x692668, + split_accepted_error=<optimized out>, merge_accepted_error=<optimized out>) + at lib/evas/common/evas_tiler.c:849 +#2 _add_redraw (h=30, w=79, y=539, x=665, rects=0x692668) + at lib/evas/common/evas_tiler.c:956 +#3 evas_common_tilebuf_add_redraw (tb=0x692630, x=665, y=539, w=79, h=30) + at lib/evas/common/evas_tiler.c:986 +#4 0x00007ffff539bd1c in _evas_render_phase1_direct (render_objects=0xb61c40, + active_objects=0x689740, e=<optimized out>, + restack_objects=<optimized out>, delete_objects=<optimized out>) + at lib/evas/canvas/evas_render.c:257 +#5 evas_render_updates_internal (eo_e=0x6896b0, + make_updates=make_updates@entry=1 '\001', do_draw=do_draw@entry=1 '\001') + at lib/evas/canvas/evas_render.c:1357 +#6 0x00007ffff539dcd7 in _canvas_render_updates (eo_e=<optimized out>, + _pd=<optimized out>, list=<optimized out>) + at lib/evas/canvas/evas_render.c:1795 +#7 0x00007ffff706fa35 in _eo_op_internal (obj=0x6896b0, op_type= + EO_OP_TYPE_REGULAR, op=402, p_list=0x7fffffffe228) at lib/eo/eo.c:363 +#8 0x00007ffff70716cd in _eo_dov_internal (p_list=0x7fffffffe228, op_type= + EO_OP_TYPE_REGULAR, obj=0x6896b0) at lib/eo/eo.c:403 +#9 eo_do_internal (obj=0x6896b0, op_type=op_type@entry=EO_OP_TYPE_REGULAR) + at lib/eo/eo.c:434 +#10 0x00007ffff539dc5f in evas_render_updates (eo_e=<optimized out>) + at lib/evas/canvas/evas_render.c:1779 +#11 0x00007fffe6f7943a in _ecore_evas_x_render (ee=0x687f30) + at modules/ecore_evas/engines/x/ecore_evas_x.c:447 +#12 0x00007ffff6e5e7f1 in _ecore_evas_idle_enter (data=<optimized out>) + at lib/ecore_evas/ecore_evas.c:59 +#13 0x00007ffff50e6019 in _ecore_call_task_cb (data=<optimized out>, + func=<optimized out>) at lib/ecore/ecore_private.h:300 +#14 _ecore_idle_enterer_call () at lib/ecore/ecore_idle_enterer.c:235 +#15 0x00007ffff50e847b in _ecore_main_loop_iterate_internal ( + once_only=once_only@entry=0) at lib/ecore/ecore_main.c:1866 +#16 0x00007ffff50e8b27 in ecore_main_loop_begin () at lib/ecore/ecore_main.c:964 +#17 0x00000000004025d9 in elm_main (argc=1, argv=0x7fffffffe5b8) at gg_map.c:324 +#18 0x0000000000402624 in main (argc=1, argv=0x7fffffffe5b8) at gg_map.c:331 + +=============================================================================== +2012-12-16_04-22 + +This bug is a lockup of evas during rendering in my efl app. +App freeze and takes 100% CPU. Below are backtraces when gdb was running and +I interrupt it with Ctrl-C. + +At the time of crash, around 300objects total : +elementary interface + ~100 edje + 100 edje mapped with evas_map + ~100 evas_object_text + +This crash is not predictible from what I see, sometimes it goes fine for a long +time. +It seem to crash more when using more edje objects. + +happened AFTER raster's fix +------------------------------------------------------------------------ +r81039 | raster | 2012-12-16 03:01:11 +0100 (Sun, 16 Dec 2012) | 5 lines +small change - dont let update rect list for image object become a +runaway endless list if evas doenst come around and render (pick it +up) any time soon - limit to 512 update rects. + + +^C +Program received signal SIGINT, Interrupt. +0x00007ffff53ddc54 in _calc_intra_outer_rect_area (outer=<synthetic pointer>, + intra=<synthetic pointer>, a=..., b=...) at lib/evas/common/evas_tiler.c:530 +530 outer->height = max_bottom - min_top; +(gdb) bt +#0 0x00007ffff53ddc54 in _calc_intra_outer_rect_area ( + outer=<synthetic pointer>, intra=<synthetic pointer>, a=..., b=...) + at lib/evas/common/evas_tiler.c:530 +#1 rect_list_add_split_fuzzy (node=0x9d27c0, rects=0x6942b8, + accepted_error=<optimized out>) at lib/evas/common/evas_tiler.c:652 +#2 rect_list_add_split_fuzzy_and_merge (node=0x9d27c0, rects=0x6942b8, + split_accepted_error=<optimized out>, merge_accepted_error=<optimized out>) + at lib/evas/common/evas_tiler.c:849 +#3 _add_redraw (h=76, w=276, y=453, x=990, rects=0x6942b8) + at lib/evas/common/evas_tiler.c:956 +#4 evas_common_tilebuf_add_redraw (tb=0x694280, x=990, y=453, w=276, h=76) + at lib/evas/common/evas_tiler.c:986 +#5 0x00007ffff539736f in _evas_render_prev_cur_clip_cache_add (obj=obj@entry= + 0xbee890, e=0x68b390, e=0x68b390) at lib/evas/canvas/evas_render.c:158 +#6 0x00007ffff539ba0c in _evas_render_phase1_direct (render_objects=0xbee800, + active_objects=0x68b390, e=<optimized out>, + restack_objects=<optimized out>, delete_objects=<optimized out>) + at lib/evas/canvas/evas_render.c:257 +#7 evas_render_updates_internal (eo_e=0x68b300, + make_updates=make_updates@entry=1 '\001', do_draw=do_draw@entry=1 '\001') + at lib/evas/canvas/evas_render.c:1357 +#8 0x00007ffff539d9c7 in _canvas_render_updates (eo_e=<optimized out>, + _pd=<optimized out>, list=<optimized out>) + at lib/evas/canvas/evas_render.c:1795 +#9 0x00007ffff706fa45 in _eo_op_internal (obj=0x68b300, op_type= + EO_OP_TYPE_REGULAR, op=402, p_list=0x7fffffffe1f8) at lib/eo/eo.c:363 +#10 0x00007ffff70716dd in _eo_dov_internal (p_list=0x7fffffffe1f8, op_type= + EO_OP_TYPE_REGULAR, obj=0x68b300) at lib/eo/eo.c:403 +#11 eo_do_internal (obj=0x68b300, op_type=op_type@entry=EO_OP_TYPE_REGULAR) + at lib/eo/eo.c:434 +#12 0x00007ffff539d94f in evas_render_updates (eo_e=<optimized out>) + at lib/evas/canvas/evas_render.c:1779 +#13 0x00007fffe6f7743a in _ecore_evas_x_render (ee=0x689b80) + at modules/ecore_evas/engines/x/ecore_evas_x.c:447 +#14 0x00007ffff6e5e841 in _ecore_evas_idle_enter (data=<optimized out>) + at lib/ecore_evas/ecore_evas.c:59 +#15 0x00007ffff50e5059 in _ecore_call_task_cb (data=<optimized out>, + func=<optimized out>) at lib/ecore/ecore_private.h:300 +#16 _ecore_idle_enterer_call () at lib/ecore/ecore_idle_enterer.c:235 +#17 0x00007ffff50e74bb in _ecore_main_loop_iterate_internal ( + once_only=once_only@entry=0) at lib/ecore/ecore_main.c:1866 +#18 0x00007ffff50e7b67 in ecore_main_loop_begin () at lib/ecore/ecore_main.c:964 +#19 0x00000000004035b0 in elm_main (argc=1, argv=0x7fffffffe5b8) at gg_map.c:461 +---Type <return> to continue, or q <return> to quit--- +#20 0x00000000004035fb in main (argc=1, argv=0x7fffffffe5b8) at gg_map.c:468 + +=============================================================================== +2012-12-16_18-16 + + +^C +Program received signal SIGINT, Interrupt. +0x00007ffff53ddd20 in _calc_intra_outer_rect_area (outer=<synthetic pointer>, + intra=<synthetic pointer>, a=..., b=...) + at lib/evas/common/evas_tiler.c:509 +509 if (a.bottom < b.bottom) +(gdb) bt +#0 0x00007ffff53ddd20 in _calc_intra_outer_rect_area ( + outer=<synthetic pointer>, intra=<synthetic pointer>, a=..., b=...) + at lib/evas/common/evas_tiler.c:509 +#1 rect_list_add_split_fuzzy (node=0x16b03d0, rects=0x692668, + accepted_error=<optimized out>) at lib/evas/common/evas_tiler.c:652 +#2 rect_list_add_split_fuzzy_and_merge (node=0x16b03d0, rects=0x692668, + split_accepted_error=<optimized out>, merge_accepted_error=<optimized out>) + at lib/evas/common/evas_tiler.c:849 +#3 _add_redraw (h=31, w=323, y=264, x=696, rects=0x692668) + at lib/evas/common/evas_tiler.c:956 +#4 evas_common_tilebuf_add_redraw (tb=0x692630, x=696, y=264, w=323, h=31) + at lib/evas/common/evas_tiler.c:986 +#5 0x00007ffff539736f in _evas_render_prev_cur_clip_cache_add (obj=obj@entry= + 0x36cef40, e=0x689740, e=0x689740) at lib/evas/canvas/evas_render.c:158 +#6 0x00007ffff539ba0c in _evas_render_phase1_direct (render_objects= + 0x36ceeb0, active_objects=0x689740, e=<optimized out>, + restack_objects=<optimized out>, delete_objects=<optimized out>) + at lib/evas/canvas/evas_render.c:257 +#7 evas_render_updates_internal (eo_e=0x6896b0, + make_updates=make_updates@entry=1 '\001', do_draw=do_draw@entry=1 '\001') + at lib/evas/canvas/evas_render.c:1357 +#8 0x00007ffff539d9c7 in _canvas_render_updates (eo_e=<optimized out>, + _pd=<optimized out>, list=<optimized out>) + at lib/evas/canvas/evas_render.c:1795 +#9 0x00007ffff706fa45 in _eo_op_internal (obj=0x6896b0, op_type= + EO_OP_TYPE_REGULAR, op=402, p_list=0x7fffffffe1f8) at lib/eo/eo.c:363 +#10 0x00007ffff70716dd in _eo_dov_internal (p_list=0x7fffffffe1f8, op_type= + EO_OP_TYPE_REGULAR, obj=0x6896b0) at lib/eo/eo.c:403 +#11 eo_do_internal (obj=0x6896b0, op_type=op_type@entry=EO_OP_TYPE_REGULAR) + at lib/eo/eo.c:434 +#12 0x00007ffff539d94f in evas_render_updates (eo_e=<optimized out>) + at lib/evas/canvas/evas_render.c:1779 +#13 0x00007fffe6f7743a in _ecore_evas_x_render (ee=0x687f30) + at modules/ecore_evas/engines/x/ecore_evas_x.c:447 +#14 0x00007ffff6e5e841 in _ecore_evas_idle_enter (data=<optimized out>) + at lib/ecore_evas/ecore_evas.c:59 +#15 0x00007ffff50e5059 in _ecore_call_task_cb (data=<optimized out>, + func=<optimized out>) at lib/ecore/ecore_private.h:300 +#16 _ecore_idle_enterer_call () at lib/ecore/ecore_idle_enterer.c:235 +#17 0x00007ffff50e766d in _ecore_main_loop_iterate_internal ( + once_only=once_only@entry=0) at lib/ecore/ecore_main.c:1841 +#18 0x00007ffff50e7b67 in ecore_main_loop_begin () + at lib/ecore/ecore_main.c:964 +#19 0x00000000004031c1 in elm_main (argc=1, argv=0x7fffffffe5b8) + at gg_map.c:447 +#20 0x000000000040320c in main (argc=1, argv=0x7fffffffe5b8) at gg_map.c:454 + + diff --git a/egraph/doc/egraph.xoj b/egraph/doc/egraph.xoj Binary files differnew file mode 100644 index 0000000..59ca038 --- /dev/null +++ b/egraph/doc/egraph.xoj diff --git a/egraph/doc/internals.txt b/egraph/doc/internals.txt new file mode 100644 index 0000000..7a8b34d --- /dev/null +++ b/egraph/doc/internals.txt @@ -0,0 +1,89 @@ +Internals +========= + +=== algo to handle threaded graph layouting correctly === + +###### GENERAL ALGO +_layouting_start(graph-2, coords-2); + +_add/del(structs-3); +_repositionning(graph, structs, coords); + +_layouting_end(coords-2); + +_v2_updtate(structs-2, graph-2, coords-2); + _v2_structs/graph_update(structs-2, graph); + -> structs, graph // real add/del + _coords_copy(coords-2); + -> coords + +_repositionning(graph, structs, coords); + +_v3_update(structs-3); + _v3_structs/graph_update(structs-3, graph-2); + -> structs-2, graph-2 + +###### TIMELINE VERTICE ADD +egraph_vertice_add(); + id = freeids[vertices_count]; + v = vertices[id]; + v->id = id; + vertices_count++; + v->v3-new = 1; + +_v3_update(); + v->v2-new = v->v3-new; + v->v3-new = 0; + _v2_add() + v->graph2_vid = graph2_vcount; + graph2_vcount++; + igraph_add_vertices(graph2); + +_layouting_start(); + // end up in coords2 + +_layouting_end(); +_coords_copy(); + // end up in coords + +_v2_update(); + _add() + v->v2-new = 0; + v->graph_vid = graph_vcount; + graph_vcount++; + igraph_add_vertices(graph); + evas_object + +// in structs, graph, coords + +###### TIMELINE VERTICE DEL +egraph_vertice_del(); + v->v3-del = 1; + +_v3_update(); + v->v2-del = v->v3-del; + v->v3-del = 0; + _v2_del() + igraph_delete_vertices(v->graph2_vid); + graph2_vcount--; + +_layouting_start(); + // not in coords2 + +_layouting_end(); +_coords_copy(); + // not in coords + +_v2_update(); + _del(); + igraph_delete_vertices(v->graph_vid); + graph_vcount--; + freeids[vertices_count] = v->id; + vertices_count--; + free(v); + +// removed from structs, graph, coords + +###### TIMELINE VERTICE DEL + + diff --git a/egraph/egraph.c b/egraph/egraph.c new file mode 100644 index 0000000..bffcebf --- /dev/null +++ b/egraph/egraph.c @@ -0,0 +1,1275 @@ +#include <err.h> +#include <Efx.h> +#include <Edje.h> + +#include "Egraph.h" + +#define DEBUG 0 + +#define TYPE_MAXLEN 30 + +static void _smart_add(Evas_Object *obj); +static void _smart_del(Evas_Object *obj); +static void _smart_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y); +static void _smart_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h); +static void _edge_v2_add(Egraph *eg, Egraph_Edge *e); +static void _edge_add(Egraph *eg, Egraph_Edge *e); +static void _edge_signal(Egraph *eg, Egraph_Edge *e, const char *signal); +static void _edge_v2_del(Egraph *eg, Egraph_Edge *e); +static void _edge_del(Egraph *eg, Egraph_Edge *e); +static void _vertice_v2_add(Egraph *eg, Egraph_Vertice *v); +static void _vertice_add(Egraph *eg, Egraph_Vertice *v); +static void _vertice_v2_del(Egraph *eg, Egraph_Vertice *v); +static void _vertice_del(Egraph *eg, Egraph_Vertice *v); +static void _vertice_update_status(Egraph *eg, Egraph_Vertice *v); +static void _vertice_signal(Egraph *eg, Egraph_Vertice *v, const char *signal); +static void _vertice_geometry_update(Egraph *eg, Egraph_Vertice *v); +static void _v2_update(Egraph *eg); +static void _v3_update(Egraph *eg); +static void _coords2_copy(Egraph *eg); +static void _cb_blob_arrived(void *data, Efx_Map_Data *e, Evas_Object *obj); +static void _blob_send(Evas_Object *blob, + Egraph_Vertice *v, Evas_Coord x, Evas_Coord y); +static void _layouting_schedule(Egraph *eg); +static Eina_Bool _cb_layouting_start(void *data); +static void _cb_layouting_run(void *data, Ecore_Thread *thread); +static void _cb_layouting_end(void *data, Ecore_Thread *thread); +static void _cb_layouting_cancel(void *data, Ecore_Thread *thread); +static int _igraph_query_vid(igraph_t *g, int g_len, int id); +static void _cb_vertice_move(void *data, + Evas *evas, Evas_Object *obj, void *event_info); +static void _reposition(Egraph *eg, int no_animation); +static void _matrix_minmax_2v(const igraph_matrix_t *m, int row_count, + float *c1min, float *c1max, + float *c2min, float *c2max); +static Evas_Object *_edje_obj_new(Egraph *eg, const char *group); +static Evas_Object *_edje_obj_set(Egraph *eg, Evas_Object *o, const char *group); + +static const Evas_Smart_Cb_Description _smart_callbacks[] = {{NULL, NULL}}; +#define EGRAPH_DATA_GET(o, ptr) \ + Egraph * ptr = evas_object_smart_data_get(o) +/* defines _egraph_parent_sc and _egraph_smart_class_new */ +EVAS_SMART_SUBCLASS_NEW("Egraph", _egraph, + Evas_Smart_Class, Evas_Smart_Class, + evas_object_smart_clipped_class_get, _smart_callbacks); + +static void +_egraph_smart_set_user(Evas_Smart_Class *sc) +{ + /* specializing these two */ + sc->add = _smart_add; + sc->del = _smart_del; + sc->move = _smart_move; + /* clipped smart object has no hook on resizes or calculations */ + sc->resize = _smart_resize; +} + +static void +_smart_add(Evas_Object *obj) +{ + EVAS_SMART_DATA_ALLOC(obj, Egraph); + + priv->evas = evas_object_evas_get(obj); + + _egraph_parent_sc->add(obj); +} + +static void +_smart_del(Evas_Object *obj) +{ + EGRAPH_DATA_GET(obj, eg); + + igraph_destroy(&eg->graph); + if (eg->layouting.running == 2) + ecore_thread_cancel(eg->layouting.thread); + + _egraph_parent_sc->del(obj); +} + +static void +_smart_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y) +{ + EGRAPH_DATA_GET(obj, eg); + + _reposition(eg, 1); + + _egraph_parent_sc->move(obj, x, y); +} + +static void +_smart_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h) +{ + EGRAPH_DATA_GET(obj, eg); + + _reposition(eg, 1); +} + +Evas_Object * +egraph_new(Evas *evas, int directed) +{ + Evas_Object *obj = NULL; + Evas_Object *rect; + Egraph *eg; + int i; + + EINA_SAFETY_ON_NULL_RETURN_VAL(evas, NULL); + + efx_init(); + eina_log_domain_level_set("efx", EINA_LOG_LEVEL_WARN); + + obj = evas_object_smart_add(evas, _egraph_smart_class_new()); + eg = evas_object_smart_data_get(obj); + if (!eg) goto err; + eg->obj = obj; + rect = evas_object_rectangle_add(eg->evas); + evas_object_color_set(rect, 0, 0, 0, 0); + evas_object_smart_member_add(rect, obj); + eg->split_vertice_edge = rect; + + eg->graph_directed = directed; + eg->display_vertices = 1; + eg->display_names = 1; + eg->display_edges = 1; + eg->use_animations = 1; + eg->do_improvements = 1; + egraph_theme_file_set(obj, NULL); + eg->theme_edges = 1; + eg->layout = EGRAPH_LAYOUT_DEFAULT; + + /* needed for igraph attribute handling */ + igraph_i_set_attribute_table(&igraph_cattribute_table); + + eg->vertices = eina_hash_int32_new(NULL); + for (i=0; i<EGRAPH_VERTICES_MAX-1; i++) + eg->vertices_freeids[i] = i; + if (igraph_empty(&eg->graph, 0, directed)) + goto err; + if (igraph_empty(&eg->graph2, 0, directed)) + goto err; + igraph_matrix_init(&eg->coords, 0, 2); + igraph_matrix_init(&eg->coords2, 0, 2); + eg->graph_wmin = 0; + eg->graph_wmax = 200; + eg->graph_hmin = 0; + eg->graph_hmax = 200; + eg->vertice_max_w = 0; + eg->vertice_max_h = 0; + + return obj; + +err: + if (obj) + evas_object_del(obj); + return NULL; +} + +void +egraph_clear(Evas_Object *obj) +{ + EGRAPH_DATA_GET(obj, eg); + Eina_Iterator *it; + Egraph_Vertice *v; + void *data; + + it = eina_hash_iterator_tuple_new(eg->vertices); + while (eina_iterator_next(it, &data)) { + Eina_Hash_Tuple *t = data; + v = t->data; + egraph_vertice_del(obj, v); + } +} + +void +egraph_theme_file_set(Evas_Object *obj, char *path) +{ + EGRAPH_DATA_GET(obj, eg); + + if (eg->theme_path) + free(eg->theme_path); + + if (!path) { + char buf[256]; + + snprintf(buf, sizeof(buf), + "%s/egraph.edj", + "/usr/local/share/egraph"); /* XXX use eina_prefix */ + path = buf; + } + eg->theme_path = strndup(path, 256); +} + +void +egraph_theme_edges_set(Evas_Object *obj, int set) +{ + EGRAPH_DATA_GET(obj, eg); + + eg->theme_edges = set; +} + +void +egraph_layout_set(Evas_Object *obj, Egraph_Layout layout) +{ + EGRAPH_DATA_GET(obj, eg); + + eg->layout = layout; + _layouting_schedule(eg); +} + +void +egraph_display_vertices_set(Evas_Object *obj, int set) +{ + EGRAPH_DATA_GET(obj, eg); + Eina_Iterator *it; + Egraph_Vertice *v; + void *data; + + eg->display_vertices = set; + + it = eina_hash_iterator_tuple_new(eg->vertices); + while (eina_iterator_next(it, &data)) { + Eina_Hash_Tuple *t = data; + v = t->data; + if (v->o) { + if (set == 0) + evas_object_hide(v->o); + else + evas_object_show(v->o); + } + } + + _reposition(eg, 0); +} + +void +egraph_display_names_set(Evas_Object *obj, int set) +{ + EGRAPH_DATA_GET(obj, eg); + Eina_Iterator *it; + Egraph_Vertice *v; + void *data; + + eg->display_names = set; + + it = eina_hash_iterator_tuple_new(eg->vertices); + while (eina_iterator_next(it, &data)) { + Eina_Hash_Tuple *t = data; + v = t->data; + egraph_vertice_rename(obj, v, set ? v->name : NULL); + } +} + +void +egraph_display_edges_set(Evas_Object *obj, int set) +{ + EGRAPH_DATA_GET(obj, eg); + Eina_List *l; + Egraph_Edge *e; + + eg->display_edges = set; + + EINA_LIST_FOREACH(eg->edges, l, e) { + if (e->o) { + if (set == 0) + evas_object_hide(e->o); + else + evas_object_show(e->o); + } + } +} + +void +egraph_use_animations_set(Evas_Object *obj, int set) +{ + EGRAPH_DATA_GET(obj, eg); + + eg->use_animations = set; +} + +void +egraph_do_improvements_set(Evas_Object *obj, int set) +{ + EGRAPH_DATA_GET(obj, eg); + + eg->do_improvements = set; +} + +Egraph_Edge * +egraph_edge_add(Evas_Object *obj, Egraph_Vertice *a, Egraph_Vertice *b, + void *data) +{ + EGRAPH_DATA_GET(obj, eg); + Egraph_Edge *e; + + e = calloc(1, sizeof(Egraph_Edge)); + if (!e) + err(1, "egraph_edge_add: cannot calloc"); + e->v3_new = 1; + e->a = a; + e->b = b; + e->data = data; + eg->edges = eina_list_append(eg->edges, e); + if (DEBUG) + printf("egraph_edge_add %d %d\n", e->a->id, e->b->id); + + egraph_edge_type_set(obj, e, "edge_normal"); + + _layouting_schedule(eg); + return e; +} + +static void +_edge_v2_add(Egraph *eg, Egraph_Edge *e) +{ + int a_pos, b_pos; + + if (DEBUG) + printf("_edge_v2_add %d %d\n", e->a->id, e->b->id); + + e->v2_new = 1; + e->v3_new = 0; + + a_pos = _igraph_query_vid(&eg->graph2, eg->graph2_vcount, e->a->id); + b_pos = _igraph_query_vid(&eg->graph2, eg->graph2_vcount, e->b->id); + igraph_add_edge(&eg->graph2, a_pos, b_pos); +} + +static void +_edge_add(Egraph *eg, Egraph_Edge *e) +{ + Evas_Object *eobj = NULL; + int a_pos, b_pos; + + e->new = 1; + e->v2_new = 0; + + a_pos = _igraph_query_vid(&eg->graph, eg->graph_vcount, e->a->id); + b_pos = _igraph_query_vid(&eg->graph, eg->graph_vcount, e->b->id); + igraph_add_edge(&eg->graph, a_pos, b_pos); + + if (eg->theme_edges) { + eobj = _edje_obj_new(eg, e->type); + if (eobj) { + e->o_usetheme = 1; + evas_object_resize(eobj, eg->vertice_max_w, eg->vertice_max_h); // XXX rm + } + } + if (!eobj) { + eobj = evas_object_line_add(eg->evas); + evas_object_color_set(eobj, 255, 0, 0, 255); + } + evas_object_smart_member_add(eobj, eg->obj); + evas_object_stack_below(eobj, eg->split_vertice_edge); + e->o = eobj; + _edge_signal(eg, e, "become_active"); + + e->a->edges = eina_list_append(e->a->edges, e); + e->b->edges = eina_list_append(e->b->edges, e); + _vertice_update_status(eg, e->a); + _vertice_update_status(eg, e->b); +} + +void +egraph_edge_type_set(Evas_Object *obj, Egraph_Edge *e, const char *type) +{ + EGRAPH_DATA_GET(obj, eg); + + if (e->type) + free(e->type); + + e->type = strndup(type, TYPE_MAXLEN); + if (eg->theme_edges && e->o) { + _edje_obj_set(eg, e->o, type); + } +} + +static void +_edge_signal(Egraph *eg, Egraph_Edge *e, const char *signal) +{ + if (eg->theme_edges && e->o); + edje_object_signal_emit(e->o, signal, ""); +} + +void +egraph_edge_del(Evas_Object *obj, Egraph_Edge *e) +{ + EGRAPH_DATA_GET(obj, eg); + + // XXX DEBUG find mem corrupt, del already del edge + if (!egraph_edge_find(obj, e->a, e->b)) + printf("XXX DEBUG: egraph_edge_del on unknown edge !!!\n"); + if (DEBUG) + printf("egraph_edge_del: %d %d\n", e->a->id, e->b->id); + + e->v3_del = 1; + _layouting_schedule(eg); +} + +static void +_edge_v2_del(Egraph *eg, Egraph_Edge *e) +{ + igraph_es_t es; + int a_pos, b_pos; + + if (e->v2_del == 1) + return; + + if (DEBUG) + printf("_edge_v2_del %d %d\n", e->a->id, e->b->id); + + e->v2_del = 1; + e->v3_del = 0; + + if (!e->v3_new) { + a_pos = _igraph_query_vid(&eg->graph2, eg->graph2_vcount, e->a->id); + b_pos = _igraph_query_vid(&eg->graph2, eg->graph2_vcount, e->b->id); + igraph_es_pairs_small(&es, eg->graph_directed, a_pos, b_pos, -1); + igraph_delete_edges(&eg->graph2, es); + } +} + +static void +_edge_del(Egraph *eg, Egraph_Edge *e) +{ + igraph_es_t es; + int a_pos, b_pos; + + if (!e->v3_new && !e->v2_new) { + a_pos = _igraph_query_vid(&eg->graph, eg->graph_vcount, e->a->id); + b_pos = _igraph_query_vid(&eg->graph, eg->graph_vcount, e->b->id); + igraph_es_pairs_small(&es, eg->graph_directed, a_pos, b_pos, -1); + igraph_delete_edges(&eg->graph, es); + + e->a->edges = eina_list_remove(e->a->edges, e); + e->b->edges = eina_list_remove(e->b->edges, e); + _vertice_update_status(eg, e->a); + _vertice_update_status(eg, e->b); + + evas_object_del(e->o); + } + eg->edges = eina_list_remove(eg->edges, e); + free(e); +} + +Egraph_Edge * +egraph_edge_find(Evas_Object *obj, Egraph_Vertice *a, Egraph_Vertice *b) +{ + EGRAPH_DATA_GET(obj, eg); + Egraph_Edge *e; + Eina_List *l; + + EINA_LIST_FOREACH(eg->edges, l, e) + if (!(e->v3_del || e->v2_del) && + ((e->a == a && e->b == b) || + (e->a == b && e->b == a))) + return e; + return NULL; +} + +Egraph_Vertice * +egraph_vertice_add(Evas_Object *obj, const char *name, void *data) +{ + EGRAPH_DATA_GET(obj, eg); + Egraph_Vertice *v; + u_int32_t id; + + if (eg->vertices_count == EGRAPH_VERTICES_MAX) { + printf("egraph error: maximum number of vertices reached !\n"); + return NULL; + } + v = calloc(1, sizeof(Egraph_Vertice)); + if (!v) + err(1, "egraph_vertice_add: cannot calloc"); + id = eg->vertices_freeids[eg->vertices_count]; + v->id = id; + eina_hash_add(eg->vertices, &id, v); + eg->vertices_count++; + v->v3_new = 1; + if (DEBUG) + printf("egraph_vertice_add %d\n", id); + + if (name) + v->name = strndup(name, EGRAPH_VERTICE_NAME_MAXLEN); + egraph_vertice_type_set(obj, v, "vertice_normal"); + + v->data = data; + + _layouting_schedule(eg); + return v; +} + +static void +_vertice_v2_add(Egraph *eg, Egraph_Vertice *v) +{ + v->v2_new = 1; + v->v3_new = 0; + + igraph_add_vertices(&eg->graph2, 1, 0); + SETVAN(&eg->graph2, "id", eg->graph2_vcount, v->id); + eg->graph2_vcount++; +} + +static void +_vertice_add(Egraph *eg, Egraph_Vertice *v) +{ + Evas_Object *vobj = NULL; + + v->new = 1; + v->v2_new = 0; + + vobj = _edje_obj_new(eg, v->type); + if (!vobj) { + printf("egraph: could not load theme for vertice !"); + v->v2_new = 1; + v->new = 0; + _vertice_v2_del(eg, v); + return; + } + evas_object_smart_member_add(vobj, eg->obj); + evas_object_stack_above(vobj, eg->split_vertice_edge); + evas_object_event_callback_add(vobj, EVAS_CALLBACK_MOVE, _cb_vertice_move, v); + v->o = vobj; + _vertice_geometry_update(eg, v); + + igraph_add_vertices(&eg->graph, 1, 0); + SETVAN(&eg->graph, "id", eg->graph_vcount, v->id); + eg->graph_vcount++; + + if (v->name) + egraph_vertice_rename(eg->obj, v, v->name); +} + +void +egraph_vertice_del(Evas_Object *obj, Egraph_Vertice *v) +{ + EGRAPH_DATA_GET(obj, eg); + Egraph_Edge *e; + Eina_List *l; + + v->v3_del = 1; + + EINA_LIST_FOREACH(eg->edges, l, e) + if (e->a == v || e->b == v) + egraph_edge_del(obj, e); + + _layouting_schedule(eg); +} + +static void +_vertice_v2_del(Egraph *eg, Egraph_Vertice *v) +{ + Egraph_Edge *e; + Eina_List *l; + int pos; + + if (v->v2_del == 1) + return; + + v->v2_del = 1; + v->v3_del = 0; + + if (DEBUG) + printf("_vertice_v2_del %d\n", v->id); + EINA_LIST_FOREACH(eg->edges, l, e) + if (e->a == v || e->b == v) + _edge_v2_del(eg, e); + + if (!v->v3_new) { + pos = _igraph_query_vid(&eg->graph2, eg->graph2_vcount, v->id); + igraph_delete_vertices(&eg->graph2, igraph_vss_1(pos)); + eg->graph2_vcount--; + } +} + +static void +_vertice_del(Egraph *eg, Egraph_Vertice *v) +{ + Egraph_Edge *e; + Eina_List *l, *lprev; + Evas_Object *blob; + int pos; + + if (!v->v3_new && !v->v2_new) { + EINA_LIST_FOREACH_SAFE(eg->edges, l, lprev, e) + if (e->a == v || e->b == v) + _edge_del(eg, e); + eina_list_free(v->edges); + + pos = _igraph_query_vid(&eg->graph, eg->graph_vcount, v->id); + igraph_delete_vertices(&eg->graph, igraph_vss_1(pos)); + eg->graph_vcount--; + + EINA_LIST_FOREACH(v->blobs_incoming, l, blob) + evas_object_del(blob); + eina_list_free(v->blobs_incoming); + + evas_object_del(v->o); + } + + eina_hash_del(eg->vertices, &v->id, NULL); + eg->vertices_count--; + eg->vertices_freeids[eg->vertices_count] = v->id; + + free(v); +} + +void +egraph_vertice_type_set(Evas_Object *obj, Egraph_Vertice *v, const char *type) +{ + EGRAPH_DATA_GET(obj, eg); + + if (v->type) + free(v->type); + + v->type = strndup(type, TYPE_MAXLEN); + if (v->o) + _edje_obj_set(eg, v->o, type); +} + +static void +_vertice_update_status(Egraph *eg, Egraph_Vertice *v) +{ + Eina_List *l; + Egraph_Edge *e; + int status = 0; + + if (v->is_group && (eina_list_count(v->edges) >= 1)) { + status = 1; /* we are a group with childs */ + } else { + EINA_LIST_FOREACH(v->edges, l, e) { + if ((v == e->a && !e->b->is_group) || + (v == e->b && !e->a->is_group)) { + status = 1; /* we are connected to at least on other non group node */ + break; + } + } + } + + if (status != v->status) { + if (status) + _vertice_signal(eg, v, "become_active"); + else + _vertice_signal(eg, v, "become_inactive"); + v->status = status; + } +} + +static void +_vertice_signal(Egraph *eg, Egraph_Vertice *v, const char *signal) +{ + if (v->o) + edje_object_signal_emit(v->o, signal, ""); +} + +void +egraph_vertice_rename(Evas_Object *obj, Egraph_Vertice *v, const char *name) +{ + EGRAPH_DATA_GET(obj, eg); + + if (eg->display_names == 0) + return; + + if (name) { + if (v->name != name) { + if (v->name) + free(v->name); + v->name = strndup(name, EGRAPH_VERTICE_NAME_MAXLEN); + } + } + if (v->o) { + if (v->name) + edje_object_part_text_set(v->o, "label", v->name); + else + edje_object_part_text_set(v->o, "label", ""); + _vertice_geometry_update(eg, v); + } +} + +static void +_vertice_geometry_update(Egraph *eg, Egraph_Vertice *v) +{ + int w, h; + + edje_object_size_min_calc(v->o, &w, &h); + if (DEBUG) + printf("_vertice_geometry_update: %d %d\n", w, h); + evas_object_resize(v->o, w, h); + if (w > eg->vertice_max_w) + eg->vertice_max_w = w; + if (h > eg->vertice_max_h) + eg->vertice_max_h = h; + if (DEBUG) + printf("_vertice_geometry_update: end %d %d\n", + eg->vertice_max_w, eg->vertice_max_h); +} + +void +_color_int_to_rgb(u_int32_t color, int *r, int *g , int *b) +{ + *r = (color & 0xFF000000) >> 24; + *g = (color & 0x00FF0000) >> 16; + *b = (color & 0x0000FF00) >> 8; +} + +void +egraph_vertice_send_blob(Evas_Object *obj, + Egraph_Vertice *a, Egraph_Vertice *b, + int size, u_int32_t color) +{ + EGRAPH_DATA_GET(obj, eg); + Evas_Object *blob; + int ax, ay, aw, ah, bx, by, bw, bh; + int cr, cg, cb; + + if (!a->o || !b->o) + return; + evas_object_geometry_get(a->o, &ax, &ay, &aw, &ah); + evas_object_geometry_get(b->o, &bx, &by, &bw, &bh); + _color_int_to_rgb(color, &cr, &cg, &cb); + + blob = _edje_obj_new(eg, "blob"); + if (!blob) + blob = evas_object_rectangle_add(eg->evas); + evas_object_color_set(blob, cr, cg, cb, 255); + evas_object_smart_member_add(blob, eg->obj); + evas_object_stack_above(blob, eg->split_vertice_edge); + evas_object_move(blob, ax, ay); + evas_object_resize(blob, size, size); + evas_object_show(blob); + b->blobs_incoming = eina_list_append(b->blobs_incoming, blob); + _blob_send(blob, b, bx, by); +} + +static void +_cb_blob_arrived(void *data, Efx_Map_Data *e, Evas_Object *obj) +{ + Egraph_Vertice *v; + + v = data; + v->blobs_incoming = eina_list_remove(v->blobs_incoming, obj); + evas_object_del(obj); +} + +static void +_blob_send(Evas_Object *blob, Egraph_Vertice *v, Evas_Coord x, Evas_Coord y) +{ + if (DEBUG) + printf("blob_send %d %d\n", x, y); + efx_move(blob, EFX_EFFECT_SPEED_SINUSOIDAL, + &(Evas_Point){ x, y }, 0.6, _cb_blob_arrived, v); +} + +static void +_layouting_schedule(Egraph *eg) +{ + if (eg->layouting.running > 0) { + eg->layouting.todo = 1; + return; + } + + eg->layouting.running = 1; + ecore_timer_add(0.0, _cb_layouting_start, eg); /* delayed start */ +} + +static void +_v2_update(Egraph *eg) +{ + Eina_List *l, *lprev, *todel, *toadd; + Eina_Iterator *it; + Egraph_Vertice *v; + Egraph_Edge *e; + void *data; + + /* update graph and structs based on v2_add / v2_del */ + it = eina_hash_iterator_tuple_new(eg->vertices); + todel = NULL; toadd = NULL; + while (eina_iterator_next(it, &data)) { + Eina_Hash_Tuple *t = data; + v = t->data; + if (v->v2_del) + todel = eina_list_append(todel, v); + else if (v->v2_new) + toadd = eina_list_append(toadd, v); + } + eina_iterator_free(it); + EINA_LIST_FOREACH(todel, l, v) + _vertice_del(eg, v); + EINA_LIST_FOREACH(toadd, l, v) + _vertice_add(eg, v); + todel = eina_list_free(todel); + toadd = eina_list_free(toadd); + EINA_LIST_FOREACH_SAFE(eg->edges, l, lprev, e) { + if (e->v2_del) + _edge_del(eg, e); + else if (e->v2_new) + _edge_add(eg, e); + } +} + +static void +_v3_update(Egraph *eg) +{ + Eina_List *l, *lprev; + Eina_Iterator *it; + Egraph_Vertice *v; + Egraph_Edge *e; + void *data; + float ranx, rany; + int changes_count = 0; + int changes_diff = 0; + int i, id; + + if (DEBUG) + printf("_v3_update\n"); + /* update graph2 and structs based on v3_add / v3_del */ + it = eina_hash_iterator_tuple_new(eg->vertices); + while (eina_iterator_next(it, &data)) { + Eina_Hash_Tuple *t = data; + v = t->data; + if (v->v3_del) { + _vertice_v2_del(eg, v); changes_diff--; changes_count++; + } else if (v->v3_new) { + _vertice_v2_add(eg, v); changes_diff++; changes_count++; + } + } + eina_iterator_free(it); + if (DEBUG) + printf("_v3_update edges\n"); + EINA_LIST_FOREACH_SAFE(eg->edges, l, lprev, e) { + if (e->v3_del) { + _edge_v2_del(eg, e); changes_count++; + } else if (e->v3_new) { + _edge_v2_add(eg, e); changes_count++; + } + } + + /* set correct coords2 size */ + if (changes_diff > 0) { + for (i=0; i<changes_diff; i++) { + id = (eg->graph2_vcount - changes_diff) + i; + igraph_matrix_add_rows(&eg->coords2, 1); + ranx = eg->graph_wmin + fmod((float)random() / 1000, (float)((eg->graph_wmax + 1) - eg->graph_wmin)); + rany = eg->graph_hmin + fmod((float)random() / 1000, (float)((eg->graph_hmax + 1) - eg->graph_hmin)); + if (DEBUG) + printf("ranx %6.3f rany %6.3f\n", ranx, rany); + igraph_matrix_set(&eg->coords2, id, 0, ranx); + igraph_matrix_set(&eg->coords2, id, 1, rany); + } + } else if (changes_diff < 0) { + changes_diff = -changes_diff; + for (i=0; i<changes_diff; i++) { + id = (eg->graph2_vcount + changes_diff) - i; + igraph_matrix_remove_row(&eg->coords2, 0); + } + } + + if (eg->layout == EGRAPH_LAYOUT_FRUCHTERMANREINGOLD) { + /* set minimum and maximum for each node */ + /* XXX do that in layouting thread ? */ + if (DEBUG) + printf("g wmin %d wmax %d hmin %d hmax %d\n", + eg->graph_wmin, eg->graph_wmax, eg->graph_hmin, eg->graph_hmax); + igraph_vector_init(&eg->graph2_wmin, eg->graph2_vcount); + igraph_vector_init(&eg->graph2_wmax, eg->graph2_vcount); + igraph_vector_init(&eg->graph2_hmin, eg->graph2_vcount); + igraph_vector_init(&eg->graph2_hmax, eg->graph2_vcount); + igraph_vector_fill(&eg->graph2_wmin, eg->graph_wmin); + igraph_vector_fill(&eg->graph2_wmax, eg->graph_wmax); + igraph_vector_fill(&eg->graph2_hmin, eg->graph_hmin); + igraph_vector_fill(&eg->graph2_hmax, eg->graph_hmax); + } + + eg->layouting.changes_diff = changes_diff; +} + +static Eina_Bool +_cb_layouting_start(void *data) +{ + Egraph *eg; + + eg = data; + + eg->layouting.todo = 0; + + _v3_update(eg); + + eg->layouting.running = 2; + eg->layouting.thread = ecore_thread_run(_cb_layouting_run, _cb_layouting_end, + _cb_layouting_cancel, eg); + + return EINA_FALSE; /* no repeat */ +} + +void +_cb_layouting_run(void *data, Ecore_Thread *thread) +{ + Egraph *eg; + int niter; + + eg = data; + + if (DEBUG) + printf("[-] _cb_layouting_run begin (%d)\n", eg->layout); + + switch(eg->layout) { + case EGRAPH_LAYOUT_KAMADAKAWAI: + if (eg->layouting.improvement) { + niter = 300; + } else { + if (eg->layouting.changes_diff == 0) + niter = 1000; + else + niter = 1000 * eg->layouting.changes_diff; + if (niter > 2000) + niter = 2000; + } + /* http://igraph.sourceforge.net/doc/html/ch18s01.html#igraph_layout_kamada_kawai + * int igraph_layout_kamada_kawai(const igraph_t *g, igraph_matrix_t *res, + * igraph_integer_t niter, igraph_real_t sigma, + * igraph_real_t initemp, igraph_real_t coolexp, + * igraph_real_t kkconst, igraph_bool_t use_seed, + * const igraph_vector_t *minx, + * const igraph_vector_t *maxx, + * const igraph_vector_t *miny, + * const igraph_vector_t *maxy); + * Defaults : + * igraph_layout_kamada_kawai(&eg->graph2, &eg->coords2, + * 1000, eg->vertices_count / 4, 10, 0.99, + * eg->vertices_count ^ 2, 1, + * NULL, NULL, NULL, NULL); + */ + igraph_layout_kamada_kawai(&eg->graph2, &eg->coords2, + niter, eg->graph2_vcount, 10, 0.99, + eg->vertices_count ^ 2, 1, + NULL, NULL, NULL, NULL); + break; + + case EGRAPH_LAYOUT_GRAPHOPT: + if (eg->layouting.improvement) { + niter = 300; + } else { + if (eg->layouting.changes_diff == 0) + niter = 100; + else + niter = 50 * eg->layouting.changes_diff; + if (niter > 500) + niter = 500; + } + /* http://igraph.sourceforge.net/doc/html/ch18s01.html#igraph_layout_graphopt + * int igraph_layout_graphopt(const igraph_t *g, igraph_matrix_t *res, + * igraph_integer_t niter, + * igraph_real_t node_charge, igraph_real_t node_mass, + * igraph_real_t spring_length, + * igraph_real_t spring_constant, + * igraph_real_t max_sa_movement, + * igraph_bool_t use_seed); + * Defaults : + * igraph_layout_graphopt(&eg->graph2, &eg->coords2, + * 1000, 0.001, 30, 0, 1, 5, 0); + */ + igraph_layout_graphopt(&eg->graph2, &eg->coords2, + niter, 0.003, 10, 10, 1, 5, 1); + break; + + case EGRAPH_LAYOUT_FRUCHTERMANREINGOLD: + niter = 1000; + /* http://igraph.sourceforge.net/doc/html/ch18s01.html#igraph_layout_fruchterman_reingold + * int igraph_layout_fruchterman_reingold(const igraph_t *graph, igraph_matrix_t *res, + * igraph_integer_t niter, igraph_real_t maxdelta, + * igraph_real_t area, igraph_real_t coolexp, + * igraph_real_t repulserad, igraph_bool_t use_seed, + * const igraph_vector_t *weight, + * const igraph_vector_t *minx, + * const igraph_vector_t *maxx, + * const igraph_vector_t *miny, + * const igraph_vector_t *maxy); + * Defaults: + * igraph_layout_fruchterman_reingold(&eg->graph2, &eg->coords2, + * 500, eg->graph2_vcount, + * sqrt(eg->graph2_vcount) * sqrt(eg->graph2_vcount), 1.5, + * eg->graph2_vcount, 0, + * NULL, NULL, NULL, NULL, NULL); + */ + igraph_layout_fruchterman_reingold(&eg->graph2, &eg->coords2, + niter, 0.05, + sqrt(eg->graph2_vcount), 1.5, + sqrt(eg->graph2_vcount) * eg->graph2_vcount, 1, + NULL, NULL, NULL, NULL, NULL); + //&eg->graph2_wmin, &eg->graph2_wmax, + //&eg->graph2_hmin, &eg->graph2_hmax); + break; + } + if (DEBUG) + printf("[-] _cb_layouting_run end\n"); +} + +static void +_coords2_copy(Egraph *eg) +{ + igraph_matrix_copy(&eg->coords, &eg->coords2); +} + +void +_cb_layouting_end(void *data, Ecore_Thread *thread) +{ + Egraph *eg; + + eg = data; + _v2_update(eg); + _coords2_copy(eg); + _reposition(eg, 0); + eg->layouting.running = 0; + if (eg->layouting.todo) { + eg->layouting.todo = 0; + eg->layouting.improvement = 0; + _layouting_schedule(eg); + } else { + if (eg->do_improvements) { + if (eg->layouting.improvement < EGRAPH_LAYOUTING_IMPROVEMENTS) { + eg->layouting.improvement++; + _layouting_schedule(eg); + } else { + eg->layouting.improvement = 0; + } + } + } +} + +void +_cb_layouting_cancel(void *data, Ecore_Thread *thread) +{ + Egraph *eg; + + eg = data; + eg->layouting.running = 0; + eg->layouting.todo = 0; + /* we are not in a clean state now, but it happends on exit only */ +} + +/* XXX slow ! possible to do edge/vertice delete on repositionning ? */ +static int +_igraph_query_vid(igraph_t *g, int g_len, int id) +{ + int i; + + for (i=0; i<g_len; i++) { + if (VAN(g, "id", i) == id) + return i; + } + printf("egraph: WARNING: _igraph_query_id %d not found !\n", id); + return -1; +} + +/* Apply vertice move to it's edges */ +static void +_cb_vertice_move(void *data, Evas *evas, Evas_Object *obj, void *event_info) +{ + EGRAPH_DATA_GET(evas_object_smart_parent_get(obj), eg); + Egraph_Vertice *v; + Egraph_Edge *e; + Evas_Map *m; + Eina_List *l; + int x, y, w, h; + int ax, ay, bx, by, aw, ah, bw, bh; + int p0x, p0y, p1x, p1y, p2x, p2y, p3x, p3y; + float a; + + v = data; + evas_object_geometry_get(v->o, &x, &y, &w, &h); + + EINA_LIST_FOREACH(v->edges, l, e) { + if (e->new) { + if (eg->display_edges) + evas_object_show(e->o); + e->new = 0; + } + if (e->o_usetheme) { + /* XXX we map the edges once per node = 2 times ... */ + evas_object_move(e->o, x, y); + m = evas_map_new(4); + evas_map_smooth_set(m, 1); + evas_map_util_points_populate_from_object(m, e->o); + evas_object_geometry_get(e->a->o, &ax, &ay, &aw, &ah); + evas_object_geometry_get(e->b->o, &bx, &by, &bw, &bh); + ax = ax + aw / 2; ay = ay + ah / 2; + bx = bx + bw / 2; by = by + bh / 2; + aw = aw / 2; ah = ah / 2; + bw = bw / 2; bh = bh / 2; + /* rotate edge endpoints */ + a = atan2(by - ay, bx - ax); +#define ROTX(x, h, a) (-sin(a)*h + x) +#define ROTY(y, h, a) (cos(a)*h + y) + p0x = ROTX(ax, ah, a); p0y = ROTY(ay, ah, a); + p1x = ROTX(ax, -ah, a); p1y = ROTY(ay, -ah, a); + p2x = ROTX(bx, bh, a); p2y = ROTY(by, bh, a); + p3x = ROTX(bx, -bh, a); p3y = ROTY(by, -bh, a); + /* set edge endpoints */ + evas_map_point_coord_set(m, 0, p2x, p2y, 0); + evas_map_point_coord_set(m, 1, p0x, p0y, 0); + evas_map_point_coord_set(m, 2, p1x, p1y, 0); + evas_map_point_coord_set(m, 3, p3x, p3y, 0); + evas_object_map_set(e->o, m); + evas_object_map_enable_set(e->o, EINA_TRUE); // XXX do at init + evas_map_free(m); + } else { + evas_object_line_xy_get(e->o, &ax, &ay, &bx, &by); + if (e->a == v) { + ax = x + w/2; + ay = y + h/2; + } else { + bx = x + w/2; + by = y + h/2; + } + evas_object_line_xy_set(e->o, ax, ay, bx, by); + } + } +} + +static void +_reposition(Egraph *eg, int no_animation) +{ + Egraph_Vertice *v; + u_int32_t id; + float gw_min, gw_max, gh_min, gh_max, factor_w, factor_h; + float x, y; + int obj_x, obj_y, obj_w, obj_h; + int vcur; + + if (DEBUG) + printf("[-] _reposition\n"); + if (eg->graph_vcount == 0) + return; + + evas_object_geometry_get(eg->obj, &obj_x, &obj_y, &obj_w, &obj_h); + _matrix_minmax_2v(&eg->coords, eg->graph_vcount, + &gw_min, &gw_max, &gh_min, &gh_max); + eg->graph_wmin = gw_min; + eg->graph_wmax = gw_max; + eg->graph_hmin = gh_min; + eg->graph_hmax = gh_max; + + if (DEBUG) + printf("gw_min %6.3f gw_max %6.3f gh_min %6.3f gh_max %6.3f\n", + gw_min, gw_max, gh_min, gh_max); + if (gw_max == gw_min) + factor_w = 1; + else + factor_w = (obj_w - eg->vertice_max_w) / (gw_max - gw_min); + if (gh_max == gh_min) + factor_h = 1; + else + factor_h = (obj_h - eg->vertice_max_h) / (gh_max - gh_min); + if (DEBUG) + printf("factor_w %6.3f factor_h %6.3f\n", factor_w, factor_h); + + for (vcur=0; vcur<eg->graph_vcount; vcur++) { + id = VAN(&eg->graph, "id", vcur); + + x = MATRIX(eg->coords, vcur, 0); + y = MATRIX(eg->coords, vcur, 1); + if (DEBUG) + printf("%d: %6.3f %6.3f id %d\n", vcur, x, y, id); + x = obj_x + ((x - gw_min) * factor_w); + y = obj_y + ((y - gh_min) * factor_h); + if (DEBUG) + printf(" inobj: %6.3f %6.3f\n", x, y); + + v = eina_hash_find(eg->vertices, &id); + if (eg->use_animations && !no_animation) { + efx_move(v->o, EFX_EFFECT_SPEED_DECELERATE, + &(Evas_Point){ x, y }, 0.5, NULL, NULL); + } + else + evas_object_move(v->o, x, y); + /* XXX fix blob repositionning + Evas_Object *blob; + Eina_List *l; + EINA_LIST_FOREACH(v->blobs_incoming, l, blob) + _blob_send(blob, v, x, y); + */ + if (v->new) { + evas_object_show(v->o); + v->new = 0; + } + } +} + +/** + * Compute minimum and maximum of a matrices of 2 colum vectors + * + * @note igraph is crazy in the coconut + */ +static void +_matrix_minmax_2v(const igraph_matrix_t *m, int row_count, + float *c1min, float *c1max, float *c2min, float *c2max) +{ + float val; + int row; + + *c1min=MATRIX(*m, 0, 0); *c1max=MATRIX(*m, 0, 0); + *c2min=MATRIX(*m, 0, 1); *c2max=MATRIX(*m, 0, 1); + + for (row=1; row<row_count; row++) { + val = MATRIX(*m, row, 0); + if (val < *c1min) *c1min = val; + else if (val > *c1max) *c1max = val; + val = MATRIX(*m, row, 1); + if (val < *c2min) *c2min = val; + else if (val > *c2max) *c2max = val; + } +} + +static Evas_Object * +_edje_obj_new(Egraph *eg, const char *group) +{ + Evas_Object *obj; + + obj = edje_object_add(eg->evas); + return _edje_obj_set(eg, obj, group); +} + +static Evas_Object * +_edje_obj_set(Egraph *eg, Evas_Object *obj, const char *group) +{ + if (!obj || !edje_object_file_set(obj, eg->theme_path, group)) { + int err = edje_object_load_error_get(obj); + const char *errmsg = edje_load_error_str(err); + if (DEBUG) + fprintf(stderr, "Could not load the edje file - reason:%s\n", errmsg); + return NULL; + } + return obj; +} + +Egraph_Vertice * +egraph_group_add(Evas_Object *obj, const char *name, void *data) +{ + Egraph_Vertice *g; + + g = egraph_vertice_add(obj, name, data); + g->is_group = 1; + egraph_vertice_type_set(obj, g, "vertice_group"); + return g; +} + +int +egraph_group_vertice_attach(Evas_Object *obj, + Egraph_Vertice *group, Egraph_Vertice *v) +{ + Egraph_Edge *e; + + group->group_vertices = eina_list_append(group->group_vertices, v); + e = egraph_edge_add(obj, group, v, NULL); + egraph_edge_type_set(obj, e, "edge_group"); + return 1; +} + +void +egraph_group_vertice_detach(Evas_Object *obj, + Egraph_Vertice *group, Egraph_Vertice *v) +{ + Egraph_Edge *e; + + group->group_vertices = eina_list_remove(group->group_vertices, v); + e = egraph_edge_find(obj, group, v); + egraph_edge_del(obj, e); +} diff --git a/egraph/egraph.edc b/egraph/egraph.edc new file mode 100644 index 0000000..399442a --- /dev/null +++ b/egraph/egraph.edc @@ -0,0 +1,250 @@ +collections { + group { + name: "vertice_normal"; + max: 700 700; + min: 700 700; + images { + image: "data/vertice.png" COMP; + } + parts { + part { + name: "image"; + type: IMAGE; + description { + state: "default" 0.0; + max: 15 15; + min: 15 15; + image{ + normal: "data/vertice.png"; + } + rel1.relative: 0.0 0.0; + rel2.relative: 1.0 1.0; + color: 255 255 255 100; + } + description { + state: "active" 1.0; + inherit: "default" 0.0; + color: 255 255 255 255; + } + } + part { + name: "label"; + type: TEXT; + description { + state: "default" 0.0; + max: 50 8; + fixed: 1 1; + color: 200 255 0 50; /* yellow low */ + text { + font: "vera"; + size: 10; + min: 1 1; + } + rel1.to: "image"; + rel1.relative: 0.5 1.0; + rel2.to: "image"; + rel2.relative: 0.5 1.0; + rel2.offset: 0 8; + } + description { + state: "active" 1.0; + inherit: "default" 0.0; + color: 200 255 0 255; /* yellow visible */ + } + } + } + programs { + program { + name: "state_active"; + signal: "become_active"; + source: ""; + action: STATE_SET "active" 0.0; + target: "image"; + target: "label"; + transition: DECELERATE 0.5; + } + program { + name: "state_inactive"; + signal: "become_inactive"; + source: ""; + action: STATE_SET "default" 0.0; + target: "image"; + target: "label"; + transition: DECELERATE 0.5; + } + } + } + group { + name: "vertice_group"; + max: 700 700; + min: 700 700; + images { + image: "data/vertice.png" COMP; + } + parts { + part { + name: "image"; + type: IMAGE; + description { + state: "default" 0.0; + max: 15 15; + min: 15 15; + image{ + normal: "data/vertice.png"; + } + rel1.relative: 0.0 0.0; + rel2.relative: 1.0 1.0; + color: 160 120 40 70; + } + description { + state: "active" 1.0; + inherit: "default" 0.0; + color: 160 120 40 170; + } + } + part { + name: "label"; + type: TEXT; + description { + state: "default" 0.0; + max: 50 8; + fixed: 1 1; + color: 160 120 40 70; /* yellow low */ + text { + font: "vera"; + size: 10; + min: 1 1; + } + rel1.to: "image"; + rel1.relative: 0.5 1.0; + rel2.to: "image"; + rel2.relative: 0.5 1.0; + rel2.offset: 0 8; + } + description { + state: "active" 1.0; + inherit: "default" 0.0; + color: 160 120 40 170; /* yellow visible */ + } + } + } + programs { + program { + name: "state_active"; + signal: "become_active"; + action: STATE_SET "active" 0.0; + target: "image"; + transition: DECELERATE 0.5; + } + program { + name: "state_inactive"; + signal: "become_inactive"; + action: STATE_SET "default" 0.0; + target: "image"; + transition: DECELERATE 0.5; + } + } + } + group { + name: "edge_normal"; + max: 700 700; + min: 700 700; + images { + image: "data/edge.png" COMP; + } + parts { + part { + name: "image"; + type: IMAGE; + description { + state: "default" 0.0; + max: 50 10; + min: 50 10; + image{ + normal: "data/edge.png"; + } + rel1.relative: 0.0 0.0; + rel2.relative: 1.0 1.0; + color: 255 255 255 50; + } + description { + state: "active" 1.0; + inherit: "default" 0.0; + color: 255 255 255 255; + } + } + } + programs { + program { + name: "state_active"; + signal: "become_active"; + action: STATE_SET "active" 0.0; + target: "image"; + transition: DECELERATE 0.5; + } + } + } + group { + name: "edge_group"; + max: 700 700; + min: 700 700; + images { + image: "data/edge.png" COMP; + } + parts { + part { + name: "image"; + type: IMAGE; + description { + state: "default" 0.0; + max: 50 10; + min: 50 10; + image{ + normal: "data/edge.png"; + } + rel1.relative: 0.0 0.0; + rel2.relative: 1.0 1.0; + color: 255 120 40 70; + } + description { + state: "active" 1.0; + inherit: "default" 0.0; + color: 255 120 40 170; + } + } + } + programs { + program { + name: "state_active"; + signal: "become_active"; + action: STATE_SET "active" 0.0; + target: "image"; + transition: DECELERATE 0.5; + } + } + } + group { + name: "blob"; + max: 700 700; + min: 700 700; + images { + image: "data/blob.png" COMP; + } + parts { + part { + name: "image"; + type: IMAGE; + description { + state: "default" 0.0; + max: 50 50; + min: 3 3; + image{ + normal: "data/blob.png"; + } + rel1.relative: 0.0 0.0; + rel2.relative: 1.0 1.0; + } + } + } + } +} diff --git a/egraph/examples/Makefile b/egraph/examples/Makefile new file mode 100644 index 0000000..9ac573e --- /dev/null +++ b/egraph/examples/Makefile @@ -0,0 +1,12 @@ +CFLAGS += -Wall -g +CFLAGS += $(shell pkg-config --libs --cflags elementary) +CFLAGS += -L../ -legraph -lecore_evas + +SOURCES = $(shell echo *.c) +OBJECTS = $(SOURCES:.c=.o) +TARGETS = $(SOURCES:.c=) + +all: $(TARGETS) + +clean: + rm -f $(TARGETS) $(OBJECTS) diff --git a/egraph/examples/demoapp.c b/egraph/examples/demoapp.c new file mode 100644 index 0000000..4e64363 --- /dev/null +++ b/egraph/examples/demoapp.c @@ -0,0 +1,371 @@ +#include <err.h> + +#include <Elementary.h> +#include <Egraph.h> + +Evas_Object *_mainwin; +Evas_Object *_egraph; +Eina_List *_vertice_list = NULL; +Eina_List *_group_list = NULL; + +static void +_cb_add_edge(void *data, Evas_Object *obj, void *event_info) +{ + Egraph_Vertice *a, *b; + int ran, count; + char buf[64]; + + if (!_egraph) + return; + + count = eina_list_count(_vertice_list); + if (count == 0) { + a = egraph_vertice_add(_egraph, "first", NULL); + _vertice_list = eina_list_append(_vertice_list, a); + } else { + ran = random() % count; + a = eina_list_nth(_vertice_list, ran); + } + b = egraph_vertice_add(_egraph, NULL, NULL); + snprintf(buf, sizeof(buf), "%d", b->id); + egraph_vertice_rename(_egraph, b, buf); + _vertice_list = eina_list_append(_vertice_list, b); + + egraph_edge_add(_egraph, a, b, NULL); +} + +static void +_cb_add_50edges(void *data, Evas_Object *obj, void *event_info) +{ + int i; + + if (!_egraph) + return; + + for (i=0; i<50; i++) + _cb_add_edge(data, obj, event_info); +} + +static void +_cb_add_500edges(void *data, Evas_Object *obj, void *event_info) +{ + int i; + + if (!_egraph) + return; + + for (i=0; i<500; i++) + _cb_add_edge(data, obj, event_info); +} + +static void +_cb_del_edges(void *data, Evas_Object *obj, void *event_info) +{ + Eina_List *l; + Egraph_Vertice *v; + + if (!_egraph) + return; + + egraph_clear(_egraph); + _vertice_list = eina_list_free(_vertice_list); + _group_list = eina_list_free(_group_list); +} + +static void +_cb_add_node(void *data, Evas_Object *obj, void *event_info) +{ + Egraph_Vertice *v; + char buf[64]; + + if (!_egraph) + return; + + v = egraph_vertice_add(_egraph, NULL, NULL); + snprintf(buf, sizeof(buf), "%d", v->id); + egraph_vertice_rename(_egraph, v, buf); + _vertice_list = eina_list_append(_vertice_list, v); +} + +static void +_cb_send_100blobs(void *data, Evas_Object *obj, void *event_info) +{ + Egraph_Vertice *a, *b; + int count, ran, i; + + count = eina_list_count(_vertice_list); + if (!count) + return; + + for (i=0; i<100; i++) { + ran = random() % count; + a = eina_list_nth(_vertice_list, ran); + ran = random() % count; + b = eina_list_nth(_vertice_list, ran); + egraph_vertice_send_blob(_egraph, a, b, 5, 0xFF000000); + } +} + +static void +_cb_add_10n_group(void *data, Evas_Object *obj, void *event_info) +{ + Egraph_Vertice *group, *v; + char buf[64]; + int i; + + if (!_egraph) + return; + + group = egraph_group_add(_egraph, NULL, NULL); + snprintf(buf, sizeof(buf), "%d-group", group->id); + egraph_vertice_rename(_egraph, group, buf); + _group_list = eina_list_append(_group_list, group); + for (i=0; i<10; i++) { + v = egraph_vertice_add(_egraph, NULL, NULL); + snprintf(buf, sizeof(buf), "%d-child(%d)", v->id, group->id); + egraph_vertice_rename(_egraph, v, buf); + egraph_group_vertice_attach(_egraph, group, v); + _vertice_list = eina_list_append(_vertice_list, v); + } +} + + +static void +_cb_show_nodes(void *data, Evas_Object *obj, void *event_info) +{ + egraph_display_vertices_set(_egraph, elm_check_state_get(obj)); +} + +static void +_cb_show_labels(void *data, Evas_Object *obj, void *event_info) +{ + if (!_egraph) + return; + + egraph_display_names_set(_egraph, elm_check_state_get(obj)); +} + +static void +_cb_show_edges(void *data, Evas_Object *obj, void *event_info) +{ + if (!_egraph) + return; + + egraph_display_edges_set(_egraph, elm_check_state_get(obj)); +} + +static void +_cb_use_animations(void *data, Evas_Object *obj, void *event_info) +{ + if (!_egraph) + return; + + egraph_use_animations_set(_egraph, elm_check_state_get(obj)); +} + +static void +_cb_do_improvements(void *data, Evas_Object *obj, void *event_info) +{ + if (!_egraph) + return; + + egraph_do_improvements_set(_egraph, elm_check_state_get(obj)); +} + +static void +_cb_use_theme_e(void *data, Evas_Object *obj, void *event_info) +{ + if (!_egraph) + return; + + egraph_theme_edges_set(_egraph, elm_check_state_get(obj)); +} + +static void +_cb_layout_changed(void *data, Evas_Object *obj, void *event_info) +{ + Elm_Object_Item *it; + char *selected; + int layout; + + if (!_egraph) + return; + + it = event_info; + selected = elm_object_item_text_get(it); + layout = EGRAPH_LAYOUT_DEFAULT; + if (!strcmp(selected, "Kamada K.")) + layout = EGRAPH_LAYOUT_KAMADAKAWAI; + else if (!strcmp(selected, "GraphOpt")) + layout = EGRAPH_LAYOUT_GRAPHOPT; + else if (!strcmp(selected, "Fruchterman R.")) + layout = EGRAPH_LAYOUT_FRUCHTERMANREINGOLD; + + egraph_layout_set(_egraph, layout); +} + +static void +_cb_on_done(void *data, Evas_Object *obj, void *event_info) +{ + elm_exit(); +} + +EAPI_MAIN int +elm_main(int argc, char **argv) +{ + Evas_Object *win, *bg, *egraph, *panes; + Evas_Object *bx, *tb, *tb_it, *ck, *sc, *seg_it, *lb; + Evas *evas; + int retval = -1; + + win = elm_win_add(NULL, "panes", ELM_WIN_BASIC); + evas = evas_object_evas_get(win); + elm_win_title_set(win, "Egraph demo app"); + evas_object_smart_callback_add(win, "delete,request", _cb_on_done, NULL); + + bg = elm_bg_add(win); + elm_win_resize_object_add(win, bg); + evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_color_set(bg, 0, 0, 0, 255); + evas_object_show(bg); + + bx = elm_box_add(win); + elm_box_horizontal_set(bx, EINA_TRUE); + evas_object_size_hint_weight_set(bx, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + elm_win_resize_object_add(win, bx); + evas_object_show(bx); + + tb = elm_toolbar_add(win); + elm_toolbar_homogeneous_set(tb, EINA_FALSE); + elm_toolbar_horizontal_set(tb, EINA_FALSE); + elm_toolbar_shrink_mode_set(tb, ELM_TOOLBAR_SHRINK_EXPAND); + elm_toolbar_select_mode_set(tb, ELM_OBJECT_SELECT_MODE_ALWAYS); + elm_toolbar_transverse_expanded_set(tb, EINA_TRUE); + elm_object_style_set(tb, "item_centered"); + evas_object_size_hint_weight_set(tb, 0.0, EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(tb, EVAS_HINT_FILL, EVAS_HINT_FILL); + elm_box_pack_end(bx, tb); + evas_object_show(tb); + elm_toolbar_item_append(tb, "object-rotate-right", "Add 1 edge", + _cb_add_edge, NULL); + elm_toolbar_item_append(tb, "object-rotate-right", "Add 50 edges", + _cb_add_50edges, NULL); + elm_toolbar_item_append(tb, "object-rotate-right", "Add 500 edges", + _cb_add_500edges, NULL); + elm_toolbar_item_append(tb, "object-rotate-right", "Add 1 node alone", + _cb_add_node, NULL); + elm_toolbar_item_append(tb, "edit-delete", "Delete all", + _cb_del_edges, NULL); + elm_toolbar_item_append(tb, "object-rotate-right", "Send 100 blobs", + _cb_send_100blobs, NULL); + elm_toolbar_item_append(tb, "object-rotate-right", "Add a 10n group", + _cb_add_10n_group, NULL); + elm_toolbar_item_separator_set(elm_toolbar_item_append(tb, NULL, NULL, NULL, NULL), EINA_FALSE); + lb = elm_label_add(win); + elm_object_text_set(lb, "<b>Layout</b>"); + evas_object_size_hint_weight_set(lb, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(lb, EVAS_HINT_FILL, EVAS_HINT_FILL); + tb_it = elm_toolbar_item_append(tb, NULL, NULL, NULL, NULL); + elm_object_item_part_content_set(tb_it, "object", lb); + sc = elm_segment_control_add(win); + //evas_object_size_hint_weight_set(sc, em->weight.w, em->weight.h); + //evas_object_size_hint_align_set(sc, em->align.x, em->align.y); + seg_it = elm_segment_control_item_add(sc, NULL, "GraphOpt"); + elm_segment_control_item_selected_set(seg_it, EINA_TRUE); + seg_it = elm_segment_control_item_add(sc, NULL, "Kamada K."); + elm_segment_control_item_selected_set(seg_it, EINA_FALSE); + seg_it = elm_segment_control_item_add(sc, NULL, "Fruchterman R."); + elm_segment_control_item_selected_set(seg_it, EINA_FALSE); + evas_object_smart_callback_add(sc, "changed", _cb_layout_changed, NULL); + evas_object_show(sc); + tb_it = elm_toolbar_item_append(tb, NULL, NULL, NULL, NULL); + elm_object_item_part_content_set(tb_it, "object", sc); + //elm_toolbar_item_separator_set(elm_toolbar_item_append(tb, NULL, NULL, NULL, NULL), EINA_FALSE); + ck = elm_check_add(win); + elm_object_text_set(ck, "Show Node"); + elm_check_state_set(ck, EINA_TRUE); + evas_object_show(ck); + evas_object_smart_callback_add(ck, "changed", _cb_show_nodes, NULL); + tb_it = elm_toolbar_item_append(tb, NULL, NULL, NULL, NULL); + elm_object_item_part_content_set(tb_it, "object", ck); + ck = elm_check_add(win); + elm_object_text_set(ck, "Show Label"); + elm_check_state_set(ck, EINA_TRUE); + evas_object_show(ck); + evas_object_smart_callback_add(ck, "changed", _cb_show_labels, NULL); + tb_it = elm_toolbar_item_append(tb, NULL, NULL, NULL, NULL); + elm_object_item_part_content_set(tb_it, "object", ck); + ck = elm_check_add(win); + elm_object_text_set(ck, "Show Edges"); + elm_check_state_set(ck, EINA_TRUE); + evas_object_show(ck); + evas_object_smart_callback_add(ck, "changed", _cb_show_edges, NULL); + tb_it = elm_toolbar_item_append(tb, NULL, NULL, NULL, NULL); + elm_object_item_part_content_set(tb_it, "object", ck); + ck = elm_check_add(win); + elm_object_text_set(ck, "Use animations"); + elm_check_state_set(ck, EINA_TRUE); + evas_object_show(ck); + evas_object_smart_callback_add(ck, "changed", _cb_use_animations, NULL); + tb_it = elm_toolbar_item_append(tb, NULL, NULL, NULL, NULL); + elm_object_item_part_content_set(tb_it, "object", ck); + ck = elm_check_add(win); + elm_object_text_set(ck, "Do improvements"); + elm_check_state_set(ck, EINA_TRUE); + evas_object_show(ck); + evas_object_smart_callback_add(ck, "changed", _cb_do_improvements, NULL); + tb_it = elm_toolbar_item_append(tb, NULL, NULL, NULL, NULL); + elm_object_item_part_content_set(tb_it, "object", ck); + ck = elm_check_add(win); + elm_object_text_set(ck, "Use theme for edges"); + elm_check_state_set(ck, EINA_TRUE); + evas_object_show(ck); + evas_object_smart_callback_add(ck, "changed", _cb_use_theme_e, NULL); + tb_it = elm_toolbar_item_append(tb, NULL, NULL, NULL, NULL); + elm_object_item_part_content_set(tb_it, "object", ck); + //elm_toolbar_item_separator_set(elm_toolbar_item_append(tb, NULL, NULL, NULL, NULL), EINA_FALSE); + elm_toolbar_item_append(tb, "exit", "Quit", + _cb_on_done, NULL); + + panes = elm_panes_add(win); + evas_object_size_hint_weight_set(panes, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(panes, EVAS_HINT_FILL, EVAS_HINT_FILL); + elm_panes_content_right_size_set(panes, 0.0); + elm_box_pack_end(bx, panes); + evas_object_show(panes); + + egraph = egraph_new(evas, 1); + if (!egraph) + goto quit; + evas_object_size_hint_weight_set(egraph, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); + evas_object_size_hint_align_set(egraph, EVAS_HINT_FILL, EVAS_HINT_FILL); + evas_object_show(egraph); + elm_object_part_content_set(panes, "left", egraph); + + lb = elm_label_add(win); + elm_object_style_set(lb, "marker"); + evas_object_color_set(lb, 255, 255, 255, 255); + elm_object_text_set(lb, + "Demo application for Egraph<br/>" + "<br/>" + "Enjoy !<br/>"); + evas_object_show(lb); + elm_object_part_content_set(panes, "right", lb); + + evas_object_resize(win, 150, 150); // XXX workaround elm sizing issue + evas_object_show(win); + evas_object_resize(win, 950, 715); + evas_object_show(win); + _egraph = egraph; + _mainwin = win; + + _cb_add_50edges(NULL, NULL, NULL); + + elm_run(); + retval = 0; + +quit: + elm_shutdown(); + return retval; +} +ELM_MAIN() diff --git a/egraph/examples/simplegraph.c b/egraph/examples/simplegraph.c new file mode 100644 index 0000000..43e6d59 --- /dev/null +++ b/egraph/examples/simplegraph.c @@ -0,0 +1,59 @@ +#include <Ecore.h> +#include <Ecore_Evas.h> +#include <stdio.h> +#include <errno.h> + +#include "../Egraph.h" + +Evas_Object *_egraph_obj = NULL; + +static void +_on_destroy(Ecore_Evas *ee) +{ + ecore_main_loop_quit(); +} + +static void +_canvas_resize_cb(Ecore_Evas *ee) +{ + int w, h; + + printf("_canvas_resize_cb\n"); + ecore_evas_geometry_get(ee, NULL, NULL, &w, &h); + evas_object_resize(_egraph_obj, w, h); +} + +int +main(void) +{ + Ecore_Evas *ee; + Evas *evas; + Egraph_Vertice *a, *b; + Egraph_Edge *e; + + if (!ecore_evas_init()) + return EXIT_FAILURE; + ee = ecore_evas_new(NULL, 10, 10, 100, 100, NULL); + if (!ee) + return -1; + ecore_evas_callback_destroy_set(ee, _on_destroy); + ecore_evas_callback_resize_set(ee, _canvas_resize_cb); + ecore_evas_show(ee); + evas = ecore_evas_get(ee); + + _egraph_obj = egraph_new(evas, 1); + evas_object_resize(_egraph_obj, 100, 100); + evas_object_show(_egraph_obj); + + a = egraph_vertice_add(_egraph_obj, "a", NULL); + b = egraph_vertice_add(_egraph_obj, "b", NULL); + e = egraph_edge_add(_egraph_obj, a, b, NULL); + + ecore_main_loop_begin(); + + evas_object_del(_egraph_obj); + ecore_evas_free(ee); + ecore_evas_shutdown(); + + return (!_egraph_obj); +} diff --git a/egraph/retest.sh b/egraph/retest.sh new file mode 100755 index 0000000..c778fa1 --- /dev/null +++ b/egraph/retest.sh @@ -0,0 +1,9 @@ +#!/bin/sh + +make clean && \ + make && \ + sudo make install && \ + make -C tests/ clean && \ + make -C tests/ run && \ + make -C examples clean && \ + make -C examples diff --git a/egraph/tests/Makefile b/egraph/tests/Makefile new file mode 100644 index 0000000..8b70170 --- /dev/null +++ b/egraph/tests/Makefile @@ -0,0 +1,32 @@ +CFLAGS += -Wall -g +CFLAGS += $(shell pkg-config --libs --cflags igraph) +CFLAGS += $(shell pkg-config --libs --cflags efx) +CFLAGS += -L../ -legraph -lecore_evas + +SOURCES = $(shell echo *.c) +OBJECTS = $(SOURCES:.c=.o) +TARGETS = $(SOURCES:.c=) + +all: $(TARGETS) + +run: $(TARGETS) + @count=0 ;\ + errors=0 ;\ + for test in $(TARGETS); do \ + echo =============================================================================== ;\ + echo $$test ;\ + LD_LIBRARY_PATH=$$LD_LIBRARY_PATH:../ ./$$test ;\ + if [ $$? -eq 0 ]; then \ + echo OK ;\ + else \ + echo FAILED ;\ + errors=$$(($$errors + 1)) ;\ + fi ;\ + count=$$(($$count + 1)) ;\ + done ;\ + echo =============================================================================== ;\ + echo "$$count tests executed, $$errors errors" ;\ + exit $$errors + +clean: + rm -f $(TARGETS) $(OBJECTS) diff --git a/egraph/tests/README.txt b/egraph/tests/README.txt new file mode 100644 index 0000000..9a25111 --- /dev/null +++ b/egraph/tests/README.txt @@ -0,0 +1,4 @@ +egraph library unit tests + +do "make run" to execute them +returns the number of tests that failed diff --git a/egraph/tests/creategraph.c b/egraph/tests/creategraph.c new file mode 100644 index 0000000..d27e3d5 --- /dev/null +++ b/egraph/tests/creategraph.c @@ -0,0 +1,37 @@ +#include <Ecore.h> +#include <Ecore_Evas.h> +#include <stdio.h> +#include <errno.h> + +#include "../Egraph.h" + +int +main(void) +{ + Ecore_Evas *ee; + Evas *evas; + Evas_Object *obj = NULL; + Egraph_Vertice *a, *b; + Egraph_Edge *e; + + if (!ecore_evas_init()) + return EXIT_FAILURE; + ee = ecore_evas_new(NULL, 10, 10, 100, 100, NULL); + if (!ee) + return -1; + ecore_evas_show(ee); + evas = ecore_evas_get(ee); + + obj = egraph_new(evas, 1); + + a = egraph_vertice_add(obj, "a", NULL); + b = egraph_vertice_add(obj, NULL, NULL); + e = egraph_edge_add(obj, a, b, NULL); + egraph_vertice_del(obj, a); + + evas_object_del(obj); + ecore_evas_free(ee); + ecore_evas_shutdown(); + + return (!obj); +} |