aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVincent Torri <vincent.torri@gmail.com>2012-11-14 20:12:53 +0000
committerVincent Torri <vincent.torri@gmail.com>2012-11-14 20:12:53 +0000
commit80910393d6c88f55a8d02813a05481b298a6ef71 (patch)
treec55d60a98628be19a7336ef20a120e8ed78c7f54
parentephysics: change quaternion API to avoid many free calls (diff)
downloadefl-80910393d6c88f55a8d02813a05481b298a6ef71.tar.gz
merge: add evas tests and examples
SVN revision: 79300
-rw-r--r--Makefile.am1
-rw-r--r--configure.ac2
-rw-r--r--src/Makefile.am4
-rw-r--r--src/examples/Makefile.am4
-rw-r--r--src/examples/eet/Makefile.am7
-rw-r--r--src/examples/eina/Makefile.am6
-rw-r--r--src/examples/eo/Makefile.am18
-rw-r--r--src/examples/evas/Makefile.ambin0 -> 3911 bytes
-rw-r--r--src/examples/evas/aspect.edc17
-rw-r--r--src/examples/evas/cube1.pngbin0 -> 183167 bytes
-rw-r--r--src/examples/evas/enlightenment.pngbin0 -> 17541 bytes
-rw-r--r--src/examples/evas/evas-aspect-hints.c249
-rw-r--r--src/examples/evas/evas-box.c382
-rw-r--r--src/examples/evas/evas-buffer-simple.c228
-rw-r--r--src/examples/evas/evas-events.c413
-rw-r--r--src/examples/evas/evas-hints.c378
-rw-r--r--src/examples/evas/evas-images.c353
-rw-r--r--src/examples/evas/evas-images2.c311
-rw-r--r--src/examples/evas/evas-images3.c196
-rw-r--r--src/examples/evas/evas-init-shutdown.c56
-rw-r--r--src/examples/evas/evas-map-utils.c321
-rw-r--r--src/examples/evas/evas-object-manipulation.c235
-rw-r--r--src/examples/evas/evas-smart-interface.c790
-rw-r--r--src/examples/evas/evas-smart-object.c756
-rw-r--r--src/examples/evas/evas-stacking.c329
-rw-r--r--src/examples/evas/evas-table.c120
-rw-r--r--src/examples/evas/evas-text.c411
-rw-r--r--src/examples/evas/im1.pngbin0 -> 467518 bytes
-rw-r--r--src/examples/evas/red.png (renamed from legacy/ecore/src/examples/red.png)bin225 -> 225 bytes
-rw-r--r--src/tests/Makefile.am2
-rw-r--r--src/tests/evas/Makefile.am27
-rw-r--r--src/tests/evas/evas_suite.c (renamed from legacy/edje/src/tests/edje_suite.c)25
-rw-r--r--src/tests/evas/evas_suite.h12
-rw-r--r--src/tests/evas/evas_test_callbacks.c135
-rw-r--r--src/tests/evas/evas_test_init.c19
-rw-r--r--src/tests/evas/evas_test_text.c493
-rw-r--r--src/tests/evas/evas_test_textblock.c2219
-rw-r--r--src/tests/evas/evas_tests_helpers.h40
38 files changed, 8530 insertions, 29 deletions
diff --git a/Makefile.am b/Makefile.am
index 45dd848e97..37bab29d29 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -168,6 +168,7 @@ if EFL_ENABLE_COVERAGE
endif
@./src/tests/eet/eet_suite$(EXEEXT)
@./src/tests/eo/eo_suite$(EXEEXT)
+ @./src/tests/evas/evas_suite$(EXEEXT)
if EFL_ENABLE_COVERAGE
@$(MAKE) $(AM_MAKEFLAGS) lcov-report
endif
diff --git a/configure.ac b/configure.ac
index b9af029886..cc0a3e06f4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1827,11 +1827,13 @@ src/examples/Makefile
src/examples/eina/Makefile
src/examples/eet/Makefile
src/examples/eo/Makefile
+src/examples/evas/Makefile
src/lib/eina/eina_config.h
src/tests/Makefile
src/tests/eina/Makefile
src/tests/eet/Makefile
src/tests/eo/Makefile
+src/tests/evas/Makefile
spec/efl.spec
pc/evil.pc
pc/eina.pc
diff --git a/src/Makefile.am b/src/Makefile.am
index 72212a721d..bc4f1d27a8 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -21,11 +21,11 @@ include Makefile_Embryo.am
.PHONY: benchmark examples
benchmark:
- @$(MAKE) $(AM_MAKEFLAGS) -C lib
+ @$(MAKE) $(AM_MAKEFLAGS)
@$(MAKE) $(AM_MAKEFLAGS) -C benchmarks benchmark
examples:
- @make -C lib
+ @make
@$(MAKE) $(AM_MAKEFLAGS) -C examples examples
install-examples:
diff --git a/src/examples/Makefile.am b/src/examples/Makefile.am
index 9b095d82c2..831c727267 100644
--- a/src/examples/Makefile.am
+++ b/src/examples/Makefile.am
@@ -1,13 +1,15 @@
MAINTAINERCLEANFILES = Makefile.in
-SUBDIRS = eina eo eet
+SUBDIRS = eina eo eet evas
examples:
@$(MAKE) $(AM_MAKEFLAGS) -C eina examples
@$(MAKE) $(AM_MAKEFLAGS) -C eo examples
@$(MAKE) $(AM_MAKEFLAGS) -C eet examples
+ @$(MAKE) $(AM_MAKEFLAGS) -C evas examples
install-examples:
@$(MAKE) $(AM_MAKEFLAGS) -C eina install-examples
@$(MAKE) $(AM_MAKEFLAGS) -C eo install-examples
@$(MAKE) $(AM_MAKEFLAGS) -C eet install-examples
+ @$(MAKE) $(AM_MAKEFLAGS) -C evas install-examples
diff --git a/src/examples/eet/Makefile.am b/src/examples/eet/Makefile.am
index 121f237116..17756bae59 100644
--- a/src/examples/eet/Makefile.am
+++ b/src/examples/eet/Makefile.am
@@ -1,4 +1,5 @@
MAINTAINERCLEANFILES = Makefile.in
+
AM_CPPFLAGS = \
-I$(top_srcdir)/src/lib/eina \
-I$(top_srcdir)/src/lib/eet \
@@ -44,10 +45,10 @@ clean-local:
rm -f $(EXTRA_PROGRAMS)
install-examples:
- mkdir -p $(pkgdatadir)/examples/eet
- $(install_sh_DATA) -c $(SRCS) $(pkgdatadir)/examples/eet
+ mkdir -p $(datadir)/eet/examples
+ $(install_sh_DATA) -c $(SRCS) $(datadir)/eet/examples
uninstall-local:
for f in $(SRCS) ; do \
- rm -f $(pkgdatadir)/examples/eet/$$f ; \
+ rm -f $(datadir)/eet/examples/$$f ; \
done
diff --git a/src/examples/eina/Makefile.am b/src/examples/eina/Makefile.am
index 97671a4296..0af0a55124 100644
--- a/src/examples/eina/Makefile.am
+++ b/src/examples/eina/Makefile.am
@@ -112,12 +112,12 @@ clean-local:
rm -f $(EXTRA_PROGRAMS)
install-examples:
- mkdir -p $(pkgdatadir)/examples/eina
- $(install_sh_DATA) -c $(SRCS) $(pkgdatadir)/examples/eina
+ mkdir -p $(datadir)/eina/examples
+ $(install_sh_DATA) -c $(SRCS) $(datadir)/eina/examples
uninstall-local:
for f in $(SRCS) ; do \
- rm -f $(pkgdatadir)/examples/eina/$$f ; \
+ rm -f $(datadir)/eina/examples/$$f ; \
done
EXTRA_DIST = addr_book.txt chat.xml
diff --git a/src/examples/eo/Makefile.am b/src/examples/eo/Makefile.am
index 924138c41e..ede96e0e7b 100644
--- a/src/examples/eo/Makefile.am
+++ b/src/examples/eo/Makefile.am
@@ -67,20 +67,20 @@ clean-local:
rm -f $(EXTRA_PROGRAMS)
install-examples:
- mkdir -p $(pkgdatadir)/examples/eo/isa
- $(install_sh_DATA) -c $(eo_isa_SOURCES) $(pkgdatadir)/examples/eo/isa
- mkdir -p $(pkgdatadir)/examples/eo/evas
- $(install_sh_DATA) -c $(evas_SOURCES) $(pkgdatadir)/examples/eo/evas
- mkdir -p $(pkgdatadir)/examples/eo/simple
- $(install_sh_DATA) -c $(simple_SOURCES) $(pkgdatadir)/examples/eo/simple
+ mkdir -p $(datadir)/eo/examples/isa
+ $(install_sh_DATA) -c $(eo_isa_SOURCES) $(datadir)/eo/examples/isa
+ mkdir -p $(datadir)/eo/examples/evas
+ $(install_sh_DATA) -c $(evas_SOURCES) $(datadir)/eo/examples/evas
+ mkdir -p $(datadir)/eo/examples/simple
+ $(install_sh_DATA) -c $(simple_SOURCES) $(datadir)/eo/examples/simple
uninstall-local:
for f in $(eo_isa_SOURCES) ; do \
- rm -f $(pkgdatadir)/examples/eo/isa/$$f ; \
+ rm -f $(datadir)/eo/examples/isa/$$f ; \
done
for f in $(evas_SOURCES) ; do \
- rm -f $(pkgdatadir)/examples/eo/evas/$$f ; \
+ rm -f $(datadir)/eo/examples/evas/$$f ; \
done
for f in $(simple_SOURCES) ; do \
- rm -f $(pkgdatadir)/examples/eo/simple/$$f ; \
+ rm -f $(datadir)/eo/examples/simple/$$f ; \
done
diff --git a/src/examples/evas/Makefile.am b/src/examples/evas/Makefile.am
new file mode 100644
index 0000000000..5da4518b4c
--- /dev/null
+++ b/src/examples/evas/Makefile.am
Binary files differ
diff --git a/src/examples/evas/aspect.edc b/src/examples/evas/aspect.edc
new file mode 100644
index 0000000000..b8bfb313e0
--- /dev/null
+++ b/src/examples/evas/aspect.edc
@@ -0,0 +1,17 @@
+collections {
+ group {
+ name: "main";
+ parts {
+ part {
+ name: "content";
+ mouse_events: 0;
+ type: SWALLOW;
+ description {
+ state: "default" 0.0;
+ visible: 1;
+ }
+ }
+ }
+ }
+}
+
diff --git a/src/examples/evas/cube1.png b/src/examples/evas/cube1.png
new file mode 100644
index 0000000000..c2f4fda6b3
--- /dev/null
+++ b/src/examples/evas/cube1.png
Binary files differ
diff --git a/src/examples/evas/enlightenment.png b/src/examples/evas/enlightenment.png
new file mode 100644
index 0000000000..aeb836bc98
--- /dev/null
+++ b/src/examples/evas/enlightenment.png
Binary files differ
diff --git a/src/examples/evas/evas-aspect-hints.c b/src/examples/evas/evas-aspect-hints.c
new file mode 100644
index 0000000000..de8ed50178
--- /dev/null
+++ b/src/examples/evas/evas-aspect-hints.c
@@ -0,0 +1,249 @@
+/**
+ * Simple Evas example illustrating aspect control hints on objects.
+ *
+ * You'll need at least one engine built for it (excluding the buffer
+ * one) and the png image loader also built. See stdout/stderr for
+ * output.
+ *
+ * You'll also need @b Edje for this one, as it has the only smart
+ * object implementing aspect control for children.
+ *
+ * @verbatim
+ * gcc -o evas-events evas-events.c `pkg-config --libs --cflags ecore-evas edje`
+ * @endverbatim
+ */
+
+#ifdef HAVE_CONFIG_H
+
+#include "config.h"
+#endif
+
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <Edje.h>
+#include <stdio.h>
+#include <errno.h>
+
+#define WIDTH 320
+#define HEIGHT 480
+
+static const char *border_img_path = PACKAGE_EXAMPLES_DIR "/red.png";
+static const char *edje_file_path = PACKAGE_EXAMPLES_DIR "/aspect.edj";
+
+struct test_data
+{
+ Ecore_Evas *ee;
+ Evas *canvas;
+ Evas_Object *bg, *rect, *container, *border;
+};
+
+static struct test_data d = {0};
+
+/* here just to keep our example's window size and background image's
+ * size in synchrony */
+static void
+_canvas_resize_cb(Ecore_Evas *ee)
+{
+ int w, h;
+
+ ecore_evas_geometry_get(ee, NULL, NULL, &w, &h);
+ evas_object_resize(d.bg, w, h);
+}
+
+static const char *
+_get_aspect_name(Evas_Aspect_Control aspect)
+{
+ switch (aspect)
+ {
+ case 0:
+ return "NONE";
+
+ case 1:
+ return "NEITHER";
+
+ case 2:
+ return "HORIZONTAL";
+
+ case 3:
+ return "VERTICAL";
+
+ case 4:
+ return "BOTH";
+
+ default:
+ return "INVALID";
+ }
+}
+
+static void
+_on_keydown(void *data __UNUSED__,
+ Evas *evas __UNUSED__,
+ Evas_Object *o,
+ void *einfo)
+{
+ const Evas_Modifier *mods;
+ Evas_Event_Key_Down *ev = einfo;
+
+ mods = evas_key_modifier_get(evas_object_evas_get(o));
+
+ if (evas_key_modifier_is_set(mods, "Shift") &&
+ strcmp(ev->keyname, "h") == 0) /* print help */
+ {
+ fprintf(stdout, "commands are:\n"
+ "\tc - cycle aspect control on object\n"
+ "\th - change horizontal aspect component\n"
+ "\tv - change vertical aspect component\n"
+ "\ts - print current object's status\n"
+ "\tH - print help\n");
+ return;
+ }
+
+ if (strcmp(ev->keyname, "s") == 0) /* get aspect status of the obj */
+ {
+ Evas_Coord w, h;
+ Evas_Aspect_Control aspect;
+
+ evas_object_size_hint_aspect_get(d.rect, &aspect, &w, &h);
+
+ fprintf(stdout, "Object has aspect %s, with horizontal compontent %d"
+ " and vertical compontent %d\n",
+ _get_aspect_name(aspect), w, h);
+
+ return;
+ }
+
+ if (strcmp(ev->keyname, "c") == 0) /* cycle aspect control on obj */
+ {
+ Evas_Coord w, h;
+ Evas_Aspect_Control aspect;
+
+ evas_object_size_hint_aspect_get(d.rect, &aspect, &w, &h);
+
+ aspect = (aspect + 1) % 5;
+
+ evas_object_size_hint_aspect_set(d.rect, aspect, w, h);
+
+ fprintf(stdout, "Changing aspect control to %s\n",
+ _get_aspect_name(aspect));
+
+ return;
+ }
+
+ if (strcmp(ev->keyname, "h") == 0) /* change horizontal aspect component */
+ {
+ Evas_Coord w, h;
+ Evas_Aspect_Control aspect;
+
+ evas_object_size_hint_aspect_get(d.rect, &aspect, &w, &h);
+
+ w = (w + 1) % 3;
+
+ evas_object_size_hint_aspect_set(d.rect, aspect, w, h);
+
+ fprintf(stdout, "Changing horizontal aspect component to %d\n", w);
+
+ return;
+ }
+
+ if (strcmp(ev->keyname, "v") == 0) /* change vertical aspect component */
+ {
+ Evas_Coord w, h;
+ Evas_Aspect_Control aspect;
+
+ evas_object_size_hint_aspect_get(d.rect, &aspect, &w, &h);
+
+ h = (h + 1) % 3;
+
+ evas_object_size_hint_aspect_set(d.rect, aspect, w, h);
+
+ fprintf(stdout, "Changing vertical aspect component to %d\n", h);
+
+ return;
+ }
+}
+
+int
+main(void)
+{
+ Eina_Bool ret;
+
+ if (!ecore_evas_init())
+ return EXIT_FAILURE;
+
+ if (!edje_init())
+ return EXIT_FAILURE;
+
+ /* this will give you a window with an Evas canvas under the first
+ * engine available */
+ d.ee = ecore_evas_new(NULL, 10, 10, WIDTH, HEIGHT, NULL);
+ if (!d.ee)
+ goto error;
+
+ ecore_evas_callback_resize_set(d.ee, _canvas_resize_cb);
+ ecore_evas_show(d.ee);
+
+ /* the canvas pointer, de facto */
+ d.canvas = ecore_evas_get(d.ee);
+
+ d.bg = evas_object_rectangle_add(d.canvas);
+ evas_object_color_set(d.bg, 255, 255, 255, 255); /* white bg */
+ evas_object_move(d.bg, 0, 0); /* at canvas' origin */
+ evas_object_resize(d.bg, WIDTH, HEIGHT); /* covers full canvas */
+ evas_object_show(d.bg);
+
+ evas_object_focus_set(d.bg, EINA_TRUE);
+ evas_object_event_callback_add(
+ d.bg, EVAS_CALLBACK_KEY_DOWN, _on_keydown, NULL);
+
+ d.container = edje_object_add(d.canvas);
+ ret = edje_object_file_set(d.container, edje_file_path, "main");
+ if (!ret)
+ {
+ Edje_Load_Error err = edje_object_load_error_get(d.container);
+ const char *msg = edje_load_error_str(err);
+ fprintf(stderr, "could not load 'main' from %s: %s",
+ edje_file_path, msg);
+
+ goto panic;
+ }
+
+ evas_object_move(d.container, (WIDTH / 4), (HEIGHT / 4));
+ evas_object_resize(d.container, (WIDTH / 2), (HEIGHT / 2));
+ evas_object_show(d.container);
+
+ d.rect = evas_object_rectangle_add(d.canvas);
+ evas_object_color_set(d.rect, 0, 0, 255, 255);
+ evas_object_size_hint_aspect_set(d.rect, EVAS_ASPECT_CONTROL_NONE, 1, 1);
+ evas_object_show(d.rect);
+
+ edje_object_part_swallow(d.container, "content", d.rect);
+ evas_object_smart_changed(d.container);
+
+ /* this is a border around the edje object, container of the
+ * rectangle we are going to experiment with (change its aspect
+ * hints). this way you can see how their sizes relate */
+ d.border = evas_object_image_filled_add(d.canvas);
+ evas_object_image_file_set(d.border, border_img_path, NULL);
+ evas_object_image_border_set(d.border, 3, 3, 3, 3);
+ evas_object_image_border_center_fill_set(d.border, EVAS_BORDER_FILL_NONE);
+ evas_object_move(d.border, (WIDTH / 4) - 3, (HEIGHT / 4) - 3);
+ evas_object_resize(d.border, (WIDTH / 2) + 6, (HEIGHT / 2) + 6);
+ evas_object_show(d.border);
+
+ ecore_main_loop_begin();
+
+ ecore_evas_free(d.ee);
+ ecore_evas_shutdown();
+ edje_shutdown();
+ return 0;
+
+error:
+ fprintf(stderr, "you got to have at least one evas engine built and linked"
+ " up to ecore-evas for this example to run properly.\n");
+panic:
+ ecore_evas_free(d.ee);
+ ecore_evas_shutdown();
+ edje_shutdown();
+
+ return -1;
+}
diff --git a/src/examples/evas/evas-box.c b/src/examples/evas/evas-box.c
new file mode 100644
index 0000000000..ec795355fc
--- /dev/null
+++ b/src/examples/evas/evas-box.c
@@ -0,0 +1,382 @@
+/**
+ * Simple Evas example illustrating a custom Evas box object
+ *
+ * You'll need at least one engine built for it (excluding the buffer
+ * one). See stdout/stderr for output.
+ *
+ * @verbatim
+ * gcc -o evas-box evas-box.c `pkg-config --libs --cflags evas ecore ecore-evas eina`
+ * @endverbatim
+ */
+
+#ifdef HAVE_CONFIG_H
+
+#include "config.h"
+#else
+#define PACKAGE_EXAMPLES_DIR "."
+#define __UNUSED__
+#endif
+
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#define WIDTH (640)
+#define HEIGHT (480)
+
+static const char *border_img_path = PACKAGE_EXAMPLES_DIR "/red.png";
+
+static const char *commands = \
+ "commands are:\n"
+ "\ta - change the box's alignment values\n"
+ "\tp - change the box's padding values\n"
+ "\t1 - change the box's layout to horizontal\n"
+ "\t2 - change the box's layout to vertical\n"
+ "\t3 - change the box's layout to horizontal homogeneous\n"
+ "\t4 - change the box's layout to vertical homogeneous\n"
+ "\t5 - change the box's layout to horizontal maximum size homogeneous\n"
+ "\t6 - change the box's layout to vertical maximum size homogeneous\n"
+ "\t7 - change the box's layout to horizontal flow\n"
+ "\t8 - change the box's layout to vertical flow\n"
+ "\t9 - change the box's layout to stack\n"
+ "\t0 - change the box's layout to a custom-made one\n"
+ "\tCtrl + NUMBER - insert a new child object at that position in the box\n"
+ "\tShift + NUMBER - remove the child object at that position in the box\n"
+ "\th - print help\n";
+
+struct exemple_data
+{
+ Ecore_Evas *ee;
+ Evas *evas;
+ Evas_Object *bg, *box, *border;
+};
+
+static struct exemple_data d;
+
+static void /* custom 'diagonal' layout */
+_custom_layout(Evas_Object *o,
+ Evas_Object_Box_Data *p,
+ void *data __UNUSED__)
+{
+ int x, y, w, h;
+ int xx, yy, ww, hh;
+ int count;
+ Eina_List *l;
+ Evas_Object_Box_Option *opt;
+
+ evas_object_geometry_get(o, &x, &y, &w, &h);
+ count = eina_list_count(p->children);
+ ww = w / (count ? : 1);
+ hh = h / (count ? : 1);
+ if (ww < 1) ww = 1;
+ if (hh < 1) hh = 1;
+
+ xx = x;
+ yy = y;
+ EINA_LIST_FOREACH(p->children, l, opt)
+ {
+ evas_object_move(opt->obj, xx, yy);
+ xx += ww;
+ yy += hh;
+ }
+}
+
+static Evas_Object * /* new rectangle to be put in the box */
+_new_rectangle_add(Evas *e)
+{
+ Evas_Object *o;
+
+ o = evas_object_rectangle_add(e);
+ evas_object_resize(o, 10, 10);
+ evas_object_color_set(o, 0, 255, 0, 255);
+ evas_object_show(o);
+
+ return o;
+}
+
+/* use the following commands to interact with this example - 'h' is
+ * the key for help */
+static void
+_on_keydown(void *data __UNUSED__,
+ Evas *evas __UNUSED__,
+ Evas_Object *o __UNUSED__,
+ void *einfo)
+{
+ Evas_Event_Key_Down *ev = einfo;
+ const Evas_Modifier *mods = evas_key_modifier_get(evas);
+
+ if (strcmp(ev->keyname, "h") == 0) /* print help */
+ {
+ fprintf(stdout, commands);
+ return;
+ }
+
+ if (evas_key_modifier_is_set(mods, "Shift"))
+ {
+ int pos;
+ Eina_Bool ret;
+ Evas_Object *obj;
+ Eina_List *children;
+
+ pos = atoi(ev->keyname);
+ children = evas_object_box_children_get(d.box);
+
+ obj = eina_list_nth(children, pos);
+ if (!obj) goto list_free;
+
+ ret = evas_object_box_remove_at(d.box, pos);
+ if (ret) evas_object_del(obj);
+
+list_free:
+ eina_list_free(children);
+ return;
+ }
+
+ if (evas_key_modifier_is_set(mods, "Control"))
+ {
+ Evas_Object *o;
+ int pos;
+ pos = atoi(ev->keyname);
+ o = _new_rectangle_add(d.evas);
+ if (!evas_object_box_insert_at(d.box, o, pos))
+ evas_object_box_append(d.box, o);
+ return;
+ }
+
+ if (strcmp(ev->keyname, "a") == 0)
+ {
+ double h, v;
+
+ evas_object_box_align_get(d.box, &h, &v);
+
+ if (h == 0.5)
+ h = v = 1.0;
+ else if (h == 1.0)
+ h = v = -1.0;
+ else if (h == -1.0)
+ h = v = 0.0;
+ else if (h == 0.0)
+ h = v = 0.5;
+
+ evas_object_box_align_set(d.box, h, v);
+
+ fprintf(stdout, "Applying new alignment values (%.1f, %.1f)"
+ " on the box\n", h, v);
+ return;
+ }
+
+ if (strcmp(ev->keyname, "p") == 0)
+ {
+ int h, v;
+
+ evas_object_box_padding_get(d.box, &h, &v);
+
+ if (h == 0)
+ h = v = 50;
+ else
+ h = v = 0;
+
+ evas_object_box_padding_set(d.box, h, v);
+
+ fprintf(stdout, "Applying new padding values (%d, %d)"
+ " on the box\n", h, v);
+ return;
+ }
+
+ if (strcmp(ev->keyname, "1") == 0)
+ {
+ evas_object_box_layout_set(
+ d.box, evas_object_box_layout_horizontal, NULL, NULL);
+
+ fprintf(stdout, "Applying '%s' layout on the box\n", "horizontal");
+ return;
+ }
+
+ if (strcmp(ev->keyname, "2") == 0)
+ {
+ evas_object_box_layout_set(
+ d.box, evas_object_box_layout_vertical, NULL, NULL);
+
+ fprintf(stdout, "Applying '%s' layout on the box\n", "vertical");
+ return;
+ }
+
+ if (strcmp(ev->keyname, "3") == 0)
+ {
+ evas_object_box_layout_set(
+ d.box, evas_object_box_layout_homogeneous_horizontal, NULL,
+ NULL);
+
+ fprintf(stdout, "Applying '%s' layout on the box\n",
+ "horizontal homogeneous");
+ return;
+ }
+
+ if (strcmp(ev->keyname, "4") == 0)
+ {
+ evas_object_box_layout_set(
+ d.box, evas_object_box_layout_homogeneous_vertical, NULL, NULL);
+
+ fprintf(stdout, "Applying '%s' layout on the box\n",
+ "vertical homogeneous");
+ return;
+ }
+
+ if (strcmp(ev->keyname, "5") == 0)
+ {
+ evas_object_box_layout_set(
+ d.box, evas_object_box_layout_homogeneous_max_size_horizontal,
+ NULL, NULL);
+
+ fprintf(stdout, "Applying '%s' layout on the box\n",
+ "horizontal maximum size homogeneous");
+ return;
+ }
+
+ if (strcmp(ev->keyname, "6") == 0)
+ {
+ evas_object_box_layout_set(
+ d.box, evas_object_box_layout_homogeneous_max_size_vertical,
+ NULL, NULL);
+
+ fprintf(stdout, "Applying '%s' layout on the box\n",
+ "vertical maximum size homogeneous");
+ return;
+ }
+
+ if (strcmp(ev->keyname, "7") == 0)
+ {
+ evas_object_box_layout_set(
+ d.box, evas_object_box_layout_flow_horizontal, NULL, NULL);
+
+ fprintf(stdout, "Applying '%s' layout on the box\n", "horizontal flow");
+ return;
+ }
+
+ if (strcmp(ev->keyname, "8") == 0)
+ {
+ evas_object_box_layout_set(
+ d.box, evas_object_box_layout_flow_vertical, NULL, NULL);
+
+ fprintf(stdout, "Applying '%s' layout on the box\n", "vertical flow");
+ return;
+ }
+
+ if (strcmp(ev->keyname, "9") == 0)
+ {
+ evas_object_box_layout_set(
+ d.box, evas_object_box_layout_stack, NULL, NULL);
+
+ fprintf(stdout, "Applying '%s' layout on the box\n", "stack");
+ return;
+ }
+
+ if (strcmp(ev->keyname, "0") == 0)
+ {
+ evas_object_box_layout_set(d.box, _custom_layout, NULL, NULL);
+
+ fprintf(stdout, "Applying '%s' layout on the box\n", "CUSTOM");
+ return;
+ }
+}
+
+static void
+_on_delete(Ecore_Evas *ee __UNUSED__)
+{
+ ecore_main_loop_quit();
+}
+
+static void /* adjust canvas' contents on resizes */
+_canvas_resize_cb(Ecore_Evas *ee)
+{
+ int w, h;
+
+ ecore_evas_geometry_get(ee, NULL, NULL, &w, &h);
+
+ evas_object_resize(d.bg, w, h);
+
+ evas_object_move(d.box, (w / 4), (h / 4));
+ evas_object_resize(d.box, (w / 2), (h / 2));
+
+ evas_object_move(d.border, (w / 4) - 2, (h / 4) - 2);
+ evas_object_resize(d.border, (w / 2) + 4, (h / 2) + 4);
+}
+
+int
+main(void)
+{
+ Evas_Object *last, *o;
+ int i;
+
+ srand(time(NULL));
+
+ if (!ecore_evas_init())
+ return EXIT_FAILURE;
+
+ /* this will give you a window with an Evas canvas under the first
+ * engine available */
+ d.ee = ecore_evas_new(NULL, 0, 0, WIDTH, HEIGHT, NULL);
+ if (!d.ee)
+ goto panic;
+
+ ecore_evas_callback_delete_request_set(d.ee, _on_delete);
+ ecore_evas_callback_resize_set(d.ee, _canvas_resize_cb);
+ ecore_evas_show(d.ee);
+
+ d.evas = ecore_evas_get(d.ee);
+
+ d.bg = evas_object_rectangle_add(d.evas);
+ evas_object_color_set(d.bg, 255, 255, 255, 255); /* white bg */
+ evas_object_show(d.bg);
+
+ evas_object_focus_set(d.bg, EINA_TRUE);
+ evas_object_event_callback_add(
+ d.bg, EVAS_CALLBACK_KEY_DOWN, _on_keydown, NULL);
+
+ d.box = evas_object_box_add(d.evas);
+ evas_object_show(d.box);
+
+ for (i = 1; i <= 5; i++)
+ {
+ o = last = evas_object_rectangle_add(d.evas);
+ evas_object_size_hint_min_set(o, 50, 50);
+ evas_object_color_set(
+ o, rand() % 256, rand() % 256, rand() % 256, 255);
+ evas_object_show(o);
+
+ if (!evas_object_box_append(d.box, o))
+ {
+ fprintf(stderr, "Error appending child object on the box!\n");
+ goto error;
+ }
+ }
+
+ /* this is a border around the box, container of the rectangles we
+ * are going to experiment with. this way you can see how the
+ * container relates to the children */
+ d.border = evas_object_image_filled_add(d.evas);
+ evas_object_image_file_set(d.border, border_img_path, NULL);
+ evas_object_image_border_set(d.border, 2, 2, 2, 2);
+ evas_object_image_border_center_fill_set(d.border, EVAS_BORDER_FILL_NONE);
+ evas_object_show(d.border);
+
+ fprintf(stdout, commands);
+
+ _canvas_resize_cb(d.ee);
+ ecore_main_loop_begin();
+ ecore_evas_shutdown();
+ return 0;
+
+error:
+ ecore_evas_shutdown();
+ return -1;
+
+panic:
+ fprintf(stderr, "You got to have at least one evas engine built and linked"
+ " up to ecore-evas for this example to run properly.\n");
+ return -2;
+}
+
diff --git a/src/examples/evas/evas-buffer-simple.c b/src/examples/evas/evas-buffer-simple.c
new file mode 100644
index 0000000000..6676ef10b0
--- /dev/null
+++ b/src/examples/evas/evas-buffer-simple.c
@@ -0,0 +1,228 @@
+/**
+ * Simple Evas example using the Buffer engine.
+ *
+ * You must have Evas compiled with the buffer engine, and have the
+ * evas-software-buffer pkg-config files installed.
+ *
+ * Compile with:
+ *
+ * @verbatim
+ * gcc -o evas-buffer-simple evas-buffer-simple.c `pkg-config --libs --cflags evas evas-software-buffer`
+ * @endverbatim
+ *
+ */
+#include <Evas.h>
+#include <Evas_Engine_Buffer.h>
+#include <stdio.h>
+#include <errno.h>
+
+#define WIDTH (320)
+#define HEIGHT (240)
+
+/*
+ * create_canvas(), destroy_canvas() and draw_scene() are support functions.
+ *
+ * They are only required to use raw Evas, but for real world usage,
+ * it is recommended to use ecore and its ecore-evas submodule, that
+ * provide convenience canvas creators, integration with main loop and
+ * automatic render of updates (draw_scene()) when system goes back to
+ * main loop.
+ */
+static Evas *create_canvas(int width, int height);
+static void destroy_canvas(Evas *canvas);
+static void draw_scene(Evas *canvas);
+
+// support function to save scene as PPM image
+static void save_scene(Evas *canvas, const char *dest);
+
+int main(void)
+{
+ Evas *canvas;
+ Evas_Object *bg, *r1, *r2, *r3;
+
+ evas_init();
+
+ // create your canvas
+ // NOTE: consider using ecore_evas_buffer_new() instead!
+ canvas = create_canvas(WIDTH, HEIGHT);
+ if (!canvas)
+ return -1;
+
+ bg = evas_object_rectangle_add(canvas);
+ evas_object_color_set(bg, 255, 255, 255, 255); // white bg
+ evas_object_move(bg, 0, 0); // at origin
+ evas_object_resize(bg, WIDTH, HEIGHT); // covers full canvas
+ evas_object_show(bg);
+
+ puts("initial scene, with just background:");
+ draw_scene(canvas);
+
+ r1 = evas_object_rectangle_add(canvas);
+ evas_object_color_set(r1, 255, 0, 0, 255); // 100% opaque red
+ evas_object_move(r1, 10, 10);
+ evas_object_resize(r1, 100, 100);
+ evas_object_show(r1);
+
+ // pay attention to transparency! Evas color values are pre-multiplied by
+ // alpha, so 50% opaque green is:
+ // non-premul: r=0, g=255, b=0 a=128 (50% alpha)
+ // premul:
+ // r_premul = r * a / 255 = 0 * 128 / 255 = 0
+ // g_premul = g * a / 255 = 255 * 128 / 255 = 128
+ // b_premul = b * a / 255 = 0 * 128 / 255 = 0
+ //
+ // this 50% green is over a red background, so it will show in the
+ // final output as yellow (green + red = yellow)
+ r2 = evas_object_rectangle_add(canvas);
+ evas_object_color_set(r2, 0, 128, 0, 128); // 50% opaque green
+ evas_object_move(r2, 10, 10);
+ evas_object_resize(r2, 50, 50);
+ evas_object_show(r2);
+
+ r3 = evas_object_rectangle_add(canvas);
+ evas_object_color_set(r3, 0, 128, 0, 255); // 100% opaque dark green
+ evas_object_move(r3, 60, 60);
+ evas_object_resize(r3, 50, 50);
+ evas_object_show(r3);
+
+ puts("final scene (note updates):");
+ draw_scene(canvas);
+ save_scene(canvas, "/tmp/evas-buffer-simple-render.ppm");
+
+ // NOTE: use ecore_evas_buffer_new() and here ecore_evas_free()
+ destroy_canvas(canvas);
+
+ evas_shutdown();
+
+ return 0;
+}
+
+static Evas *create_canvas(int width, int height)
+{
+ Evas *canvas;
+ Evas_Engine_Info_Buffer *einfo;
+ int method;
+ void *pixels;
+
+ method = evas_render_method_lookup("buffer");
+ if (method <= 0)
+ {
+ fputs("ERROR: evas was not compiled with 'buffer' engine!\n", stderr);
+ return NULL;
+ }
+
+ canvas = evas_new();
+ if (!canvas)
+ {
+ fputs("ERROR: could not instantiate new evas canvas.\n", stderr);
+ return NULL;
+ }
+
+ evas_output_method_set(canvas, method);
+ evas_output_size_set(canvas, width, height);
+ evas_output_viewport_set(canvas, 0, 0, width, height);
+
+ einfo = (Evas_Engine_Info_Buffer *)evas_engine_info_get(canvas);
+ if (!einfo)
+ {
+ fputs("ERROR: could not get evas engine info!\n", stderr);
+ evas_free(canvas);
+ return NULL;
+ }
+
+ // ARGB32 is sizeof(int), that is 4 bytes, per pixel
+ pixels = malloc(width * height * sizeof(int));
+ if (!pixels)
+ {
+ fputs("ERROR: could not allocate canvas pixels!\n", stderr);
+ evas_free(canvas);
+ return NULL;
+ }
+
+ einfo->info.depth_type = EVAS_ENGINE_BUFFER_DEPTH_ARGB32;
+ einfo->info.dest_buffer = pixels;
+ einfo->info.dest_buffer_row_bytes = width * sizeof(int);
+ einfo->info.use_color_key = 0;
+ einfo->info.alpha_threshold = 0;
+ einfo->info.func.new_update_region = NULL;
+ einfo->info.func.free_update_region = NULL;
+ evas_engine_info_set(canvas, (Evas_Engine_Info *)einfo);
+
+ return canvas;
+}
+
+static void destroy_canvas(Evas *canvas)
+{
+ Evas_Engine_Info_Buffer *einfo;
+
+ einfo = (Evas_Engine_Info_Buffer *)evas_engine_info_get(canvas);
+ if (!einfo)
+ {
+ fputs("ERROR: could not get evas engine info!\n", stderr);
+ evas_free(canvas);
+ return;
+ }
+
+ free(einfo->info.dest_buffer);
+ evas_free(canvas);
+}
+
+static void draw_scene(Evas *canvas)
+{
+ Eina_List *updates, *n;
+ Eina_Rectangle *update;
+
+ // render and get the updated rectangles:
+ updates = evas_render_updates(canvas);
+
+ // informative only here, just print the updated areas:
+ EINA_LIST_FOREACH(updates, n, update)
+ printf("UPDATED REGION: pos: %3d, %3d size: %3dx%3d\n",
+ update->x, update->y, update->w, update->h);
+
+ // free list of updates
+ evas_render_updates_free(updates);
+}
+
+static void save_scene(Evas *canvas, const char *dest)
+{
+ Evas_Engine_Info_Buffer *einfo;
+ const unsigned int *pixels, *pixels_end;
+ int width, height;
+ FILE *f;
+
+ einfo = (Evas_Engine_Info_Buffer *)evas_engine_info_get(canvas);
+ if (!einfo)
+ {
+ fputs("ERROR: could not get evas engine info!\n", stderr);
+ return;
+ }
+ evas_output_size_get(canvas, &width, &height);
+
+ f = fopen(dest, "wb+");
+ if (!f)
+ {
+ fprintf(stderr, "ERROR: could not open for writing '%s': %s\n",
+ dest, strerror(errno));
+ return;
+ }
+
+ pixels = einfo->info.dest_buffer;
+ pixels_end = pixels + (width * height);
+
+ // PPM P6 format is dead simple to write:
+ fprintf(f, "P6\n%d %d\n255\n", width, height);
+ for (; pixels < pixels_end; pixels++)
+ {
+ int r, g, b;
+
+ r = ((*pixels) & 0xff0000) >> 16;
+ g = ((*pixels) & 0x00ff00) >> 8;
+ b = (*pixels) & 0x0000ff;
+
+ fprintf(f, "%c%c%c", r, g, b);
+ }
+
+ fclose(f);
+ printf("saved scene as '%s'\n", dest);
+}
diff --git a/src/examples/evas/evas-events.c b/src/examples/evas/evas-events.c
new file mode 100644
index 0000000000..28b22ed7e5
--- /dev/null
+++ b/src/examples/evas/evas-events.c
@@ -0,0 +1,413 @@
+/**
+ * Simple Evas example illustrating how to interact with canvas' (and
+ * its objects') events and other canvas operations.
+ *
+ * You'll need at least one engine built for it (excluding the buffer
+ * one) and the png image loader also built. See stdout/stderr for
+ * output.
+ *
+ * @verbatim
+ * gcc -o evas-events evas-events.c `pkg-config --libs --cflags evas ecore ecore-evas`
+ * @endverbatim
+ */
+
+#ifdef HAVE_CONFIG_H
+
+#include "config.h"
+#else
+
+#define PACKAGE_EXAMPLES_DIR "."
+#define __UNUSED__
+
+#endif
+
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <stdio.h>
+#include <errno.h>
+
+#define WIDTH (320)
+#define HEIGHT (240)
+
+static const char *img_path = PACKAGE_EXAMPLES_DIR "/enlightenment.png";
+
+static const char *commands = \
+ "commands are:\n"
+ "\ta - toggle animation timer\n"
+ "\tc - cycle between focus and key grabs for key input\n"
+ "\td - delete canvas callbacks\n"
+ "\tf - freeze input for 3 seconds\n"
+ "\tp - toggle precise point collision detection on image\n"
+ "\tControl + o - add an obscured rectangle\n"
+ "\th - print help\n";
+
+struct test_data
+{
+ Ecore_Evas *ee;
+ Evas *canvas;
+ Evas_Object *img, *bg;
+ Ecore_Timer *resize_timer, *freeze_timer;
+ Eina_Bool obscured, focus;
+};
+
+static struct test_data d = {0};
+
+/* here to keep our example's window size and background image's
+ * size in synchrony */
+static void
+_canvas_resize_cb(Ecore_Evas *ee)
+{
+ int w, h;
+
+ ecore_evas_geometry_get(ee, NULL, NULL, &w, &h);
+ evas_object_resize(d.bg, w, h);
+}
+
+/* called when our rectangle gets focus */
+static void
+_object_focus_in_cb(void *data __UNUSED__,
+ Evas *e,
+ void *event_info)
+{
+ fprintf(stdout, "An object got focused: %s\n",
+ evas_object_name_get(event_info));
+
+ fprintf(stdout, "Let's recheck it: %s\n",
+ evas_object_name_get(evas_focus_get(e)));
+
+ fprintf(stdout, "And again: %s\n", evas_object_focus_get(event_info) ?
+ "OK!" : "Oops, something is bad.");
+}
+
+/* render flush callback */
+static void
+_render_flush_cb(void *data __UNUSED__,
+ Evas *e __UNUSED__,
+ void *event_info __UNUSED__)
+{
+ fprintf(stdout, "Canvas is about to flush its rendering pipeline!\n");
+}
+
+/* put some action in the canvas */
+static Eina_Bool
+_resize_cb(void *data __UNUSED__)
+{
+ int w, h, cw, ch;
+
+ evas_object_geometry_get(d.img, NULL, NULL, &w, &h);
+ ecore_evas_geometry_get(d.ee, NULL, NULL, &cw, &ch);
+
+ if (w < cw)
+ evas_object_resize(d.img, cw, ch);
+ else
+ evas_object_resize(d.img, cw / 2, ch / 2);
+
+ return EINA_TRUE; /* re-issue the timer */
+}
+
+/* let's have our events back */
+static Eina_Bool
+_thaw_cb(void *data __UNUSED__)
+{
+ fprintf(stdout, "Canvas was frozen %d times, now thawing.\n",
+ evas_event_freeze_get(d.canvas));
+ evas_event_thaw(d.canvas);
+ return EINA_FALSE; /* do not re-issue the timer */
+}
+
+/* mouse enters the object's area */
+static void
+_on_mouse_in(void *data __UNUSED__,
+ Evas *evas __UNUSED__,
+ Evas_Object *o __UNUSED__,
+ void *einfo __UNUSED__)
+{
+ fprintf(stdout, "Enlightenment logo has had the mouse in.\n");
+}
+
+static void
+_on_mouse_out(void *data __UNUSED__,
+ Evas *evas __UNUSED__,
+ Evas_Object *o __UNUSED__,
+ void *einfo __UNUSED__)
+{
+ fprintf(stdout, "Enlightenment logo has had the mouse out.\n");
+} /* mouse exits the object's area */
+
+/* examine the keys pressed */
+static void
+_on_keydown(void *data __UNUSED__,
+ Evas *evas,
+ Evas_Object *o __UNUSED__,
+ void *einfo)
+{
+ const Evas_Modifier *mods;
+ Evas_Event_Key_Down *ev = einfo;
+
+ fprintf(stdout, "We've got key input: %s\n", ev->keyname);
+ fprintf(stdout, "It actually came from %s\n", d.focus ?
+ "focus" : "key grab");
+
+ if (strcmp(ev->keyname, "h") == 0) /* print help */
+ {
+ fprintf(stdout, commands);
+ return;
+ }
+
+ if (strcmp(ev->keyname, "a") == 0) /* toggle animation timer */
+ {
+ if (d.resize_timer != NULL)
+ {
+ fprintf(stdout, "Stopping animation timer\n");
+ ecore_timer_del(d.resize_timer);
+ d.resize_timer = NULL;
+ }
+ else
+ {
+ fprintf(stdout, "Re-issuing animation timer\n");
+ d.resize_timer = ecore_timer_add(2, _resize_cb, NULL);
+ }
+ return;
+ }
+
+ if (strcmp(ev->keyname, "c") == 0) /* cycle between focus and key
+ * grabs for key input */
+ {
+ Eina_Bool ret;
+ Evas_Modifier_Mask mask =
+ evas_key_modifier_mask_get(d.canvas, "Control");
+
+ fprintf(stdout, "Switching to %s for key input\n", d.focus ?
+ "key grabs" : "focus");
+
+ if (d.focus)
+ {
+ evas_object_focus_set(d.bg, EINA_FALSE);
+ fprintf(stdout, "Focused object is now %s\n",
+ evas_focus_get(d.canvas) ?
+ "still valid! Something went wrong." : "none.");
+
+ ret = evas_object_key_grab(d.bg, "a", 0, 0, EINA_TRUE);
+ if (!ret)
+ {
+ fprintf(stdout, "Something went wrong with key grabs.\n");
+ goto c_end;
+ }
+ ret = evas_object_key_grab(d.bg, "c", 0, 0, EINA_TRUE);
+ if (!ret)
+ {
+ fprintf(stdout, "Something went wrong with key grabs.\n");
+ goto c_end;
+ }
+ ret = evas_object_key_grab(d.bg, "d", 0, 0, EINA_TRUE);
+ if (!ret)
+ {
+ fprintf(stdout, "Something went wrong with key grabs.\n");
+ goto c_end;
+ }
+ ret = evas_object_key_grab(d.bg, "f", 0, 0, EINA_TRUE);
+ if (!ret)
+ {
+ fprintf(stdout, "Something went wrong with key grabs.\n");
+ goto c_end;
+ }
+ ret = evas_object_key_grab(d.bg, "p", 0, 0, EINA_TRUE);
+ if (!ret)
+ {
+ fprintf(stdout, "Something went wrong with key grabs.\n");
+ goto c_end;
+ }
+ ret = evas_object_key_grab(d.bg, "o", mask, 0, EINA_TRUE);
+ if (!ret)
+ {
+ fprintf(stdout, "Something went wrong with key grabs.\n");
+ goto c_end;
+ }
+ ret = evas_object_key_grab(d.bg, "h", 0, 0, EINA_TRUE);
+ if (!ret)
+ {
+ fprintf(stdout, "Something went wrong with key grabs.\n");
+ goto c_end;
+ }
+ }
+ else /* got here by key grabs */
+ {
+ evas_object_key_ungrab(d.bg, "a", 0, 0);
+ evas_object_key_ungrab(d.bg, "c", 0, 0);
+ evas_object_key_ungrab(d.bg, "d", 0, 0);
+ evas_object_key_ungrab(d.bg, "f", 0, 0);
+ evas_object_key_ungrab(d.bg, "p", 0, 0);
+ evas_object_key_ungrab(d.bg, "o", mask, 0);
+ evas_object_key_ungrab(d.bg, "h", 0, 0);
+
+ evas_object_focus_set(d.bg, EINA_TRUE);
+ }
+
+c_end:
+ d.focus = !d.focus;
+
+ return;
+ }
+
+ if (strcmp(ev->keyname, "d") == 0) /* delete canvas' callbacks */
+ {
+ fprintf(stdout, "Deleting canvas event callbacks\n");
+ evas_event_callback_del_full(evas, EVAS_CALLBACK_RENDER_FLUSH_PRE,
+ _render_flush_cb, NULL);
+ evas_event_callback_del_full(
+ evas, EVAS_CALLBACK_CANVAS_OBJECT_FOCUS_IN,
+ _object_focus_in_cb, NULL);
+ return;
+ }
+
+ if (strcmp(ev->keyname, "f") == 0) /* freeze input for 3 seconds */
+ {
+ fprintf(stdout, "Freezing input for 3 seconds\n");
+ evas_event_freeze(evas);
+ d.freeze_timer = ecore_timer_add(3, _thaw_cb, NULL);
+ return;
+ }
+
+ if (strcmp(ev->keyname, "p") == 0) /* toggle precise point
+ * collision detection */
+ {
+ Eina_Bool precise = evas_object_precise_is_inside_get(d.img);
+
+ fprintf(stdout, "Toggling precise point collision detection %s on"
+ " Enlightenment logo\n", precise ? "off" : "on");
+ evas_object_precise_is_inside_set(d.img, !precise);
+
+ return;
+ }
+
+ mods = evas_key_modifier_get(evas);
+ if (evas_key_modifier_is_set(mods, "Control") &&
+ (strcmp(ev->keyname, "o") == 0)) /* add an obscured
+ * rectangle to the middle
+ * of the canvas */
+ {
+ fprintf(stdout, "Toggling obscured rectangle on canvas\n");
+ if (!d.obscured)
+ {
+ int w, h;
+ evas_output_viewport_get(evas, NULL, NULL, &w, &h);
+ evas_obscured_rectangle_add(evas, w / 4, h / 4, w / 2, h / 2);
+ }
+ else
+ {
+ int w, h;
+ Eina_Rectangle *rect;
+ Eina_List *updates, *l;
+
+ evas_output_viewport_get(evas, NULL, NULL, &w, &h);
+ evas_obscured_clear(evas);
+
+ /* we have to flag a damage region here because
+ * evas_obscured_clear() doesn't change the canvas'
+ * state. we'd have to wait for an animation step, for
+ * example, to get the result, without it */
+ evas_damage_rectangle_add(evas, 0, 0, w, h);
+
+ updates = evas_render_updates(evas);
+
+ EINA_LIST_FOREACH(updates, l, rect)
+ {
+ fprintf(stdout, "Rectangle (%d, %d, %d, %d) on canvas got a"
+ " rendering update.\n", rect->x, rect->y,
+ rect->w,
+ rect->h);
+ }
+ evas_render_updates_free(updates);
+ }
+ d.obscured = !d.obscured;
+ } /* end of obscured region command */
+}
+
+int
+main(void)
+{
+ int err;
+
+ if (!ecore_evas_init())
+ return EXIT_FAILURE;
+
+ /* this will give you a window with an Evas canvas under the first
+ * engine available */
+ d.ee = ecore_evas_new(NULL, 10, 10, WIDTH, HEIGHT, NULL);
+ if (!d.ee)
+ goto error;
+
+ ecore_evas_callback_resize_set(d.ee, _canvas_resize_cb);
+ ecore_evas_show(d.ee);
+
+ /* the canvas pointer, de facto */
+ d.canvas = ecore_evas_get(d.ee);
+
+ evas_event_callback_add(d.canvas, EVAS_CALLBACK_RENDER_FLUSH_PRE,
+ _render_flush_cb, NULL);
+ if (evas_alloc_error() != EVAS_ALLOC_ERROR_NONE)
+ {
+ fprintf(stderr, "ERROR: Callback registering failed! Aborting.\n");
+ goto panic;
+ }
+
+ evas_event_callback_add(d.canvas, EVAS_CALLBACK_CANVAS_OBJECT_FOCUS_IN,
+ _object_focus_in_cb, NULL);
+ if (evas_alloc_error() != EVAS_ALLOC_ERROR_NONE)
+ {
+ fprintf(stderr, "ERROR: Callback registering failed! Aborting.\n");
+ goto panic;
+ } /* two canvas event callbacks */
+
+ d.bg = evas_object_rectangle_add(d.canvas);
+ evas_object_name_set(d.bg, "our dear rectangle");
+ evas_object_color_set(d.bg, 255, 255, 255, 255); /* white bg */
+ evas_object_move(d.bg, 0, 0); /* at canvas' origin */
+ evas_object_resize(d.bg, WIDTH, HEIGHT); /* covers full canvas */
+ evas_object_show(d.bg);
+
+ evas_object_focus_set(d.bg, EINA_TRUE); /* so we get input events */
+ d.focus = EINA_TRUE;
+
+ evas_object_event_callback_add(
+ d.bg, EVAS_CALLBACK_KEY_DOWN, _on_keydown, NULL);
+ if (evas_alloc_error() != EVAS_ALLOC_ERROR_NONE)
+ {
+ fprintf(stderr, "ERROR: Callback registering failed! Aborting.\n");
+ goto panic;
+ }
+
+ d.img = evas_object_image_filled_add(d.canvas);
+ evas_object_image_file_set(d.img, img_path, NULL);
+ err = evas_object_image_load_error_get(d.img);
+ if (err != EVAS_LOAD_ERROR_NONE)
+ {
+ goto panic;
+ }
+ else
+ {
+ evas_object_move(d.img, 0, 0);
+ evas_object_resize(d.img, WIDTH, HEIGHT);
+ evas_object_show(d.img);
+ evas_object_event_callback_add(
+ d.img, EVAS_CALLBACK_MOUSE_IN, _on_mouse_in, NULL);
+ evas_object_event_callback_add(
+ d.img, EVAS_CALLBACK_MOUSE_OUT, _on_mouse_out, NULL);
+ }
+
+ d.resize_timer = ecore_timer_add(2, _resize_cb, NULL);
+
+ fprintf(stdout, commands);
+ ecore_main_loop_begin();
+
+ ecore_evas_free(d.ee);
+ ecore_evas_shutdown();
+ return 0;
+
+error:
+ fprintf(stderr, "you got to have at least one evas engine built and linked"
+ " up to ecore-evas for this example to run properly.\n");
+panic:
+ ecore_evas_shutdown();
+ return -1;
+}
diff --git a/src/examples/evas/evas-hints.c b/src/examples/evas/evas-hints.c
new file mode 100644
index 0000000000..78c09ba4ab
--- /dev/null
+++ b/src/examples/evas/evas-hints.c
@@ -0,0 +1,378 @@
+/**
+ * Simple Evas example illustrating <b>alignment, minimum size, maximum
+ * size, padding and weight</b> hints on objects.
+ *
+ * To exemplify those hints, whe use the Evas box object, one of the
+ * managers using size hints to layout its children.
+ *
+ * You'll need at least one engine built for it (excluding the buffer
+ * one) and the png image loader also built. See stdout/stderr for
+ * output.
+ *
+ * @verbatim
+ * gcc -o evas-events evas-events.c `pkg-config --libs --cflags ecore-evas`
+ * @endverbatim
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#else
+#define __UNUSED__
+#endif
+
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#define WIDTH 320
+#define HEIGHT 480
+#define PACKAGE_EXAMPLES_DIR "."
+
+static const char commands[] = \
+ "commands are:\n"
+ "\tShift + a - change alignment hints on top rectangle\n"
+ "\tShift + m - change min. size hint on top rectangle\n"
+ "\tShift + n - change max. size hint on top rectangle\n"
+ "\tShift + p - change padding hints on top rectangle\n"
+ "\tShift + w - change weight hints on top rectangle\n\n"
+ "\tControl + a - change alignment hints on bottom rectangle\n"
+ "\tControl + m - change min. size hint on bottom rectangle\n"
+ "\tControl + n - change max. size hint on bottom rectangle\n"
+ "\tControl + p - change padding hints on bottom rectangle\n"
+ "\tControl + w - change weight hints on bottom rectangle\n\n"
+ "\ts - print current hints information\n"
+ "\th - print help\n";
+
+static const char *border_img_path = PACKAGE_EXAMPLES_DIR "/red.png";
+
+struct coord_tuple
+{
+ Evas_Coord w, h;
+};
+
+struct weight_tuple
+{
+ double x, y;
+};
+
+struct padding_tuple
+{
+ Evas_Coord l, r, t, b;
+};
+
+struct rect_data
+{
+ struct coord_tuple *min_ptr;
+ struct coord_tuple min[4];
+
+ struct coord_tuple *max_ptr;
+ struct coord_tuple max[4];
+
+ struct weight_tuple *align_ptr;
+ struct weight_tuple align[3];
+
+ struct weight_tuple *weight_ptr;
+ struct weight_tuple weight[3];
+
+ struct padding_tuple *padding_ptr;
+ struct padding_tuple padding[3];
+};
+
+struct test_data
+{
+ Ecore_Evas *ee;
+ Evas *canvas;
+ struct rect_data t_data, b_data;
+ Evas_Object *bg, *box, *t_rect, *b_rect, *border;
+};
+
+static struct test_data d = {0};
+
+/* here just to keep our example's window size and background image's
+ * size in synchrony */
+static void
+_canvas_resize_cb(Ecore_Evas *ee)
+{
+ int w, h;
+
+ ecore_evas_geometry_get(ee, NULL, NULL, &w, &h);
+ evas_object_resize(d.bg, w, h);
+
+ evas_object_move(d.box, (w / 4), (h / 4));
+ evas_object_resize(d.box, (w / 2), (h / 2));
+
+ evas_object_move(d.border, (w / 4) - 3, (h / 4) - 3);
+ evas_object_resize(d.border, (w / 2) + 6, (h / 2) + 6);
+}
+
+static void
+_print_rect_stats(Evas_Object *rect)
+{
+ Evas_Coord w, h, l, r, t, b;
+ double x, y;
+
+ evas_object_size_hint_align_get(rect, &x, &y);
+ fprintf(stdout, "\talign hints: h(%f), v(%f)\n", x, y);
+
+ evas_object_size_hint_min_get(rect, &w, &h);
+ fprintf(stdout, "\tmin. size hints: h(%d), v(%d)\n", w, h);
+
+ evas_object_size_hint_max_get(rect, &w, &h);
+ fprintf(stdout, "\tmax. size hints: h(%d), v(%d)\n", w, h);
+
+ evas_object_size_hint_padding_get(rect, &l, &r, &t, &b);
+ fprintf(stdout, "\tpadding hints: l(%d), r(%d), t(%d), b(%d)\n",
+ l, r, t, b);
+
+ evas_object_size_hint_weight_get(rect, &x, &y);
+ fprintf(stdout, "\tweight hints: h(%f), v(%f)\n", x, y);
+}
+
+/* use the following commands to interact with this example - 'h' is
+ * the key for help */
+static void
+_on_keydown(void *data __UNUSED__,
+ Evas *evas __UNUSED__,
+ Evas_Object *o __UNUSED__,
+ void *einfo)
+{
+ Evas_Event_Key_Down *ev = einfo;
+ struct rect_data *r_data = NULL;
+ const Evas_Modifier *mods;
+ Evas_Object *rect = NULL;
+ const char *name = NULL;
+
+ mods = evas_key_modifier_get(evas);
+ if (evas_key_modifier_is_set(mods, "Shift"))
+ {
+ rect = d.t_rect;
+ r_data = &d.t_data;
+ name = "top";
+ }
+ else if (evas_key_modifier_is_set(mods, "Control"))
+ {
+ rect = d.b_rect;
+ r_data = &d.b_data;
+ name = "bottom";
+ }
+ else if (strcmp(ev->keyname, "h") == 0) /* print help */
+ {
+ fprintf(stdout, commands);
+ return;
+ }
+ else if (strcmp(ev->keyname, "s") == 0) /* get aspect status of the
+ * rectangles WRT size
+ * hints */
+ {
+ fprintf(stdout, "Top rectangle:\n");
+ _print_rect_stats(d.t_rect);
+
+ fprintf(stdout, "\nBottom rectangle:\n");
+ _print_rect_stats(d.b_rect);
+
+ return;
+ }
+
+ if (!rect) return;
+
+ if (strcmp(ev->keyname, "a") == 0) /* alignment hints */
+ {
+ (r_data->align_ptr)++;
+
+ if ((unsigned)
+ (((void *)(r_data->align_ptr)) - ((void *)(r_data->align))) >=
+ sizeof(r_data->align))
+ r_data->align_ptr = r_data->align;
+
+ evas_object_size_hint_align_set(
+ rect, r_data->align_ptr->x, r_data->align_ptr->y);
+
+ fprintf(stdout, "Changing align hints for %s rect. to (%f, %f)\n",
+ name, r_data->align_ptr->x, r_data->align_ptr->y);
+ return;
+ }
+
+ if (strcmp(ev->keyname, "m") == 0) /* min. size hints */
+ {
+ (r_data->min_ptr)++;
+
+ if ((unsigned)
+ (((void *)(r_data->min_ptr)) - ((void *)(r_data->min))) >=
+ sizeof(r_data->min))
+ r_data->min_ptr = r_data->min;
+
+ evas_object_size_hint_min_set(
+ rect, r_data->min_ptr->w, r_data->min_ptr->h);
+
+ fprintf(stdout, "Changing min. size hints for %s rect. to (%d, %d)\n",
+ name, r_data->min_ptr->w, r_data->min_ptr->h);
+ return;
+ }
+
+ if (strcmp(ev->keyname, "n") == 0) /* max. size hints */
+ {
+ (r_data->max_ptr)++;
+
+ if ((unsigned)
+ (((void *)(r_data->max_ptr)) - ((void *)(r_data->max))) >=
+ sizeof(r_data->max))
+ r_data->max_ptr = r_data->max;
+
+ evas_object_size_hint_max_set(
+ rect, r_data->max_ptr->w, r_data->max_ptr->h);
+
+ fprintf(stdout, "Changing max. size hints for %s rect. to (%d, %d)\n",
+ name, r_data->max_ptr->w, r_data->max_ptr->h);
+ return;
+ }
+
+ if (strcmp(ev->keyname, "p") == 0) /* padding size hints */
+ {
+ (r_data->padding_ptr)++;
+
+ if ((unsigned)
+ (((void *)(r_data->padding_ptr)) - ((void *)(r_data->padding))) >=
+ sizeof(r_data->padding))
+ r_data->padding_ptr = r_data->padding;
+
+ evas_object_size_hint_padding_set(
+ rect, r_data->padding_ptr->l, r_data->padding_ptr->r,
+ r_data->padding_ptr->t, r_data->padding_ptr->b);
+
+ fprintf(stdout, "Changing padding size hints for %s rect."
+ " to (%d, %d, %d, %d)\n",
+ name, r_data->padding_ptr->l, r_data->padding_ptr->r,
+ r_data->padding_ptr->t, r_data->padding_ptr->b);
+ return;
+ }
+
+ /* experiment with weights here. keep in mind that, for the box
+ * object, only if all the children have non zero weights this hint
+ * will have an effect */
+ if (strcmp(ev->keyname, "w") == 0) /* weight hints */
+ {
+ (r_data->weight_ptr)++;
+
+ if ((unsigned)
+ (((void *)(r_data->weight_ptr)) - ((void *)(r_data->weight))) >=
+ sizeof(r_data->weight))
+ r_data->weight_ptr = r_data->weight;
+
+ evas_object_size_hint_weight_set(
+ rect, r_data->weight_ptr->x, r_data->weight_ptr->y);
+
+ fprintf(stdout, "Changing weight hints for %s rect. to (%f, %f)\n",
+ name, r_data->weight_ptr->x, r_data->weight_ptr->y);
+ return;
+ }
+}
+
+static void
+_on_destroy(Ecore_Evas *ee __UNUSED__)
+{
+ ecore_main_loop_quit();
+}
+
+int
+main(void)
+{
+ if (!ecore_evas_init())
+ return EXIT_FAILURE;
+
+ /* init values one is going to cycle through while running this
+ * example */
+ struct rect_data init_data = \
+ {
+ .min = {{0, 0}, {30, 30}, {100, 70}, {200, 200}},
+ .max = {{0, 0}, {100, 100}, {100, 70}, {300, 300}},
+ .align = {{0.0, 0.0}, {0.5, 0.5}, {1.0, 0.5}},
+ .weight = {{0.0, 0.0}, {3, 6}, {10, 100}},
+ .padding = {{0, 0, 0, 0}, {3, 6, 9, 12}, {10, 20, 0, 30}}
+ };
+
+ d.t_data = init_data;
+
+ d.t_data.min_ptr = d.t_data.min + 1;
+ d.t_data.max_ptr = d.t_data.max + 1;
+ d.t_data.align_ptr = d.t_data.align;
+ d.t_data.weight_ptr = d.t_data.weight;
+ d.t_data.padding_ptr = d.t_data.padding;
+
+ d.b_data = init_data;
+
+ d.b_data.min_ptr = d.b_data.min + 1;
+ d.b_data.max_ptr = d.b_data.max + 1;
+ d.b_data.align_ptr = d.b_data.align;
+ d.b_data.weight_ptr = d.b_data.weight;
+ d.b_data.padding_ptr = d.b_data.padding;
+
+ /* this will give you a window with an Evas canvas under the first
+ * engine available */
+ d.ee = ecore_evas_new(NULL, 0, 0, WIDTH, HEIGHT, NULL);
+ if (!d.ee)
+ goto error;
+
+ ecore_evas_callback_destroy_set(d.ee, _on_destroy);
+ ecore_evas_callback_resize_set(d.ee, _canvas_resize_cb);
+ ecore_evas_show(d.ee);
+
+ /* the canvas pointer, de facto */
+ d.canvas = ecore_evas_get(d.ee);
+
+ d.bg = evas_object_rectangle_add(d.canvas);
+ evas_object_color_set(d.bg, 255, 255, 255, 255); /* white bg */
+ evas_object_move(d.bg, 0, 0); /* at canvas' origin */
+ evas_object_resize(d.bg, WIDTH, HEIGHT); /* covers full canvas */
+ evas_object_show(d.bg);
+
+ evas_object_focus_set(d.bg, EINA_TRUE);
+ evas_object_event_callback_add(
+ d.bg, EVAS_CALLBACK_KEY_DOWN, _on_keydown, NULL);
+
+ /* Evas box with vertical layout */
+ d.box = evas_object_box_add(d.canvas);
+ evas_object_box_layout_set(
+ d.box, evas_object_box_layout_vertical, NULL, NULL);
+ evas_object_show(d.box);
+
+ /* this is a border around the box, container of the rectangles we
+ * are going to experiment with (changing some size hints). this
+ * way you can see how the container relates to the children */
+ d.border = evas_object_image_filled_add(d.canvas);
+ evas_object_image_file_set(d.border, border_img_path, NULL);
+ evas_object_image_border_set(d.border, 3, 3, 3, 3);
+ evas_object_image_border_center_fill_set(d.border, EVAS_BORDER_FILL_NONE);
+ evas_object_show(d.border);
+
+ d.t_rect = evas_object_rectangle_add(d.canvas);
+ evas_object_color_set(d.t_rect, 0, 0, 255, 255);
+
+ evas_object_size_hint_min_set(
+ d.t_rect, d.t_data.min_ptr->w, d.t_data.min_ptr->h);
+ evas_object_show(d.t_rect);
+ evas_object_box_append(d.box, d.t_rect);
+
+ d.b_rect = evas_object_rectangle_add(d.canvas);
+ evas_object_color_set(d.b_rect, 0, 255, 0, 255);
+
+ evas_object_size_hint_min_set(
+ d.b_rect, d.b_data.min_ptr->w, d.b_data.min_ptr->h);
+ evas_object_show(d.b_rect);
+ evas_object_box_append(d.box, d.b_rect);
+
+ _canvas_resize_cb(d.ee);
+
+ fprintf(stdout, commands);
+ ecore_main_loop_begin();
+ ecore_evas_shutdown();
+ return 0;
+
+error:
+ fprintf(stderr, "You got to have at least one evas engine built and linked"
+ " up to ecore-evas for this example to run properly.\n");
+ return -1;
+}
+
diff --git a/src/examples/evas/evas-images.c b/src/examples/evas/evas-images.c
new file mode 100644
index 0000000000..a8cf3c41fa
--- /dev/null
+++ b/src/examples/evas/evas-images.c
@@ -0,0 +1,353 @@
+/**
+ * Simple Evas example illustrating some image objects functions
+ *
+ * You'll need at least one engine built for it (excluding the buffer
+ * one) and the png image loader also built. See stdout/stderr for
+ * output.
+ *
+ * @verbatim
+ * gcc -o evas-images evas-images.c `pkg-config --libs --cflags evas ecore ecore-evas`
+ * @endverbatim
+ */
+
+#ifdef HAVE_CONFIG_H
+
+#include "config.h"
+#else
+
+#define PACKAGE_EXAMPLES_DIR "."
+#define __UNUSED__
+
+#endif
+
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <stdio.h>
+#include <errno.h>
+
+#define WIDTH (320)
+#define HEIGHT (240)
+
+static const char *border_img_path = PACKAGE_EXAMPLES_DIR "/red.png";
+static const char *valid_path = PACKAGE_EXAMPLES_DIR "/enlightenment.png";
+static const char *bogus_path = "/tmp/non-existent-220986.png";
+static const char *commands = \
+ "commands are:\n"
+ "\tx - change image's x fill coordinate\n"
+ "\ty - change image's y fill coordinate\n"
+ "\tw - change image's w fill size\n"
+ "\te - change image's h fill size\n"
+ "\tf - toggle image filled property (overrides fill)\n"
+ "\ta - toggle image's alpha channel usage\n"
+ "\tm - toggle border's smooth scaling\n"
+ "\tt - change border's thickness\n"
+ "\tb - change border's center region aspect\n"
+ "\tc - change border's scaling factor\n"
+ "\ts - print image's fill property status\n"
+ "\th - print help\n";
+
+struct test_data
+{
+ Ecore_Evas *ee;
+ Evas *evas;
+ Evas_Object *img1, *img2, *bg, *border;
+};
+
+static struct test_data d = {0};
+
+static void
+_on_destroy(Ecore_Evas *ee __UNUSED__)
+{
+ ecore_main_loop_quit();
+}
+
+/* here just to keep our example's window size and background image's
+ * size in synchrony */
+static void
+_canvas_resize_cb(Ecore_Evas *ee)
+{
+ int w, h;
+
+ ecore_evas_geometry_get(ee, NULL, NULL, &w, &h);
+ evas_object_resize(d.bg, w, h);
+}
+
+static const char *
+_border_fill_mode_to_str(Evas_Border_Fill_Mode mode)
+{
+ switch (mode)
+ {
+ case EVAS_BORDER_FILL_NONE:
+ return "none";
+
+ case EVAS_BORDER_FILL_DEFAULT:
+ return "default";
+
+ case EVAS_BORDER_FILL_SOLID:
+ return "solid";
+
+ default:
+ return "invalid";
+ }
+}
+
+static void
+_on_keydown(void *data __UNUSED__,
+ Evas *evas __UNUSED__,
+ Evas_Object *o __UNUSED__,
+ void *einfo)
+{
+ Evas_Event_Key_Down *ev = einfo;
+
+ if (strcmp(ev->keyname, "h") == 0) /* print help */
+ {
+ fprintf(stdout, commands);
+ return;
+ }
+
+ if (strcmp(ev->keyname, "m") == 0) /* toggle border image's smooth scaling */
+ {
+ Eina_Bool smooth_scale = evas_object_image_smooth_scale_get(d.border);
+
+ evas_object_image_smooth_scale_set(d.border, !smooth_scale);
+
+ fprintf(stdout, "Image's border is now %s smooth scaling\n",
+ smooth_scale ? "without" : "with");
+
+ return;
+ }
+
+ if (strcmp(ev->keyname, "t") == 0) /* change border's thickness */
+ {
+ int l, r, t, b;
+
+ evas_object_image_border_get(d.border, &l, &r, &t, &b);
+
+ l = (l + 3) % 9;
+ r = (r + 3) % 9;
+ t = (t + 3) % 9;
+ b = (b + 3) % 9;
+
+ evas_object_image_border_set(d.border, l, r, t, b);
+
+ fprintf(stdout, "Image's border thickness is now %d\n", l);
+
+ return;
+ }
+
+ if (strcmp(ev->keyname, "c") == 0) /* change border's scaling factor */
+ {
+ double scale = evas_object_image_border_scale_get(d.border);
+
+ scale *= 2;
+ if (scale > 4.0) scale = 1.0;
+
+ evas_object_image_border_scale_set(d.border, scale);
+
+ fprintf(stdout, "Image's border scaling factor is now %f\n", scale);
+
+ return;
+ }
+
+ if (strcmp(ev->keyname, "b") == 0) /* change border's center
+ * region's aspect */
+ {
+ Eina_Bool fill = \
+ evas_object_image_border_center_fill_get(d.border);
+
+ fill = (fill + 1) % 3;
+
+ evas_object_image_border_center_fill_set(d.border, fill);
+
+ fprintf(stdout, "Image's border center region aspect is now \"%s\"\n",
+ _border_fill_mode_to_str(fill));
+
+ return;
+ }
+
+ if (strcmp(ev->keyname, "a") == 0) /* toggle alpha channel usage */
+ {
+ Eina_Bool alpha = evas_object_image_alpha_get(d.img1);
+
+ evas_object_image_alpha_set(d.img1, !alpha);
+
+ fprintf(stdout, "Image's alpha channel is now %s\n",
+ alpha ? "off" : "on");
+
+ return;
+ }
+
+ if (strcmp(ev->keyname, "f") == 0) /* toggle filled property */
+ {
+ Eina_Bool filled = evas_object_image_filled_get(d.img1);
+
+ evas_object_image_filled_set(d.img1, !filled);
+
+ fprintf(stdout, "Image's x filled property is now %s\n",
+ filled ? "off" : "on");
+
+ return;
+ }
+
+ if (strcmp(ev->keyname, "x") == 0) /* change x fill coordinate */
+ {
+ Evas_Coord x, y, w, h;
+
+ evas_object_image_fill_get(d.img1, &x, &y, &w, &h);
+ x = (x + 20) % (WIDTH / 2);
+ evas_object_image_fill_set(d.img1, x, y, w, h);
+
+ fprintf(stdout, "Image's x fill coordinate changed to %d\n", x);
+
+ return;
+ }
+
+ if (strcmp(ev->keyname, "y") == 0) /* change y fill coordinate */
+ {
+ Evas_Coord x, y, w, h;
+
+ evas_object_image_fill_get(d.img1, &x, &y, &w, &h);
+ y = (y + 20) % (HEIGHT / 2);
+ evas_object_image_fill_set(d.img1, x, y, w, h);
+
+ fprintf(stdout, "Image's y fill coordinate changed to %d\n", y);
+
+ return;
+ }
+
+ if (strcmp(ev->keyname, "w") == 0) /* change w fill size */
+ {
+ Evas_Coord x, y, w, h;
+
+ evas_object_image_fill_get(d.img1, &x, &y, &w, &h);
+ if (w == (WIDTH / 4)) w = (WIDTH / 2);
+ else if (w == WIDTH / 2) w = WIDTH;
+ else w = (WIDTH / 4);
+ evas_object_image_fill_set(d.img1, x, y, w, h);
+
+ fprintf(stdout, "Image's w fill size changed to %d\n", w);
+
+ return;
+ }
+
+ if (strcmp(ev->keyname, "e") == 0) /* change h fill size */
+ {
+ Evas_Coord x, y, w, h;
+
+ evas_object_image_fill_get(d.img1, &x, &y, &w, &h);
+ if (h == (HEIGHT / 4)) h = (HEIGHT / 2);
+ else if (h == HEIGHT / 2) h = HEIGHT;
+ else h = (HEIGHT / 4);
+ evas_object_image_fill_set(d.img1, x, y, w, h);
+
+ fprintf(stdout, "Image's h fill size changed to %d\n", h);
+
+ return;
+ }
+
+ if (strcmp(ev->keyname, "s") == 0) /* status */
+ {
+ Evas_Coord x, y, w, h;
+
+ evas_object_image_fill_get(d.img1, &x, &y, &w, &h);
+
+ fprintf(stdout, "Image has fill properties set to: %d, %d, %d, %d\n",
+ x, y, w, h);
+
+ return;
+ }
+}
+
+int
+main(void)
+{
+ int err;
+
+ if (!ecore_evas_init())
+ return EXIT_FAILURE;
+
+ /* this will give you a window with an Evas canvas under the first
+ * engine available */
+ d.ee = ecore_evas_new(NULL, 10, 10, WIDTH, HEIGHT, NULL);
+ if (!d.ee)
+ goto error;
+
+ ecore_evas_callback_destroy_set(d.ee, _on_destroy);
+ ecore_evas_callback_resize_set(d.ee, _canvas_resize_cb);
+ ecore_evas_show(d.ee);
+
+ /* the canvas pointer, de facto */
+ d.evas = ecore_evas_get(d.ee);
+
+ d.bg = evas_object_rectangle_add(d.evas);
+ evas_object_color_set(d.bg, 255, 255, 255, 255); /* white bg */
+ evas_object_move(d.bg, 0, 0); /* at canvas' origin */
+ evas_object_resize(d.bg, WIDTH, HEIGHT); /* covers full canvas */
+ evas_object_show(d.bg);
+
+ d.img1 = evas_object_image_add(d.evas);
+ evas_object_image_file_set(d.img1, valid_path, NULL);
+ err = evas_object_image_load_error_get(d.img1);
+ if (err != EVAS_LOAD_ERROR_NONE)
+ {
+ fprintf(stderr, "could not load image '%s'. error string is \"%s\"\n",
+ valid_path, evas_load_error_str(err));
+ }
+ else
+ {
+ fprintf(stdout,
+ "loaded image '%s' with succes! error string is \"%s\"\n",
+ valid_path, evas_load_error_str(err));
+
+ evas_object_move(d.img1, 3, 3);
+ evas_object_image_fill_set(d.img1, 0, 0, WIDTH / 2, HEIGHT / 2);
+ evas_object_resize(d.img1, WIDTH / 2, HEIGHT / 2);
+ evas_object_show(d.img1);
+
+ evas_object_focus_set(d.bg, EINA_TRUE);
+ evas_object_event_callback_add(
+ d.bg, EVAS_CALLBACK_KEY_DOWN, _on_keydown, NULL);
+ }
+
+ /* this is a border around the image above, here just to emphasize
+ * its geometry */
+ d.border = evas_object_image_filled_add(d.evas);
+ evas_object_image_file_set(d.border, border_img_path, NULL);
+ evas_object_image_border_set(d.border, 3, 3, 3, 3);
+ evas_object_image_border_center_fill_set(d.border, EVAS_BORDER_FILL_NONE);
+
+ evas_object_move(d.border, 0, 0);
+ evas_object_resize(d.border, (WIDTH / 2) + 6, (HEIGHT / 2) + 6);
+ evas_object_show(d.border);
+
+ /* image loading will fail for this one -- unless one cheats and
+ * puts a valid image on that path */
+ d.img2 = evas_object_image_add(d.evas);
+ evas_object_image_file_set(d.img2, bogus_path, NULL);
+ err = evas_object_image_load_error_get(d.img2);
+ if (err != EVAS_LOAD_ERROR_NONE)
+ {
+ fprintf(stderr, "could not load image '%s': error string is \"%s\"\n",
+ bogus_path, evas_load_error_str(err));
+ }
+ else
+ {
+ evas_object_move(d.img2, WIDTH / 2, HEIGHT / 2);
+ evas_object_image_fill_set(d.img2, 0, 0, WIDTH / 2, HEIGHT / 2);
+ evas_object_resize(d.img2, WIDTH / 2, HEIGHT / 2);
+ evas_object_show(d.img2);
+ }
+
+ fprintf(stdout, commands);
+ ecore_main_loop_begin();
+
+ ecore_evas_free(d.ee);
+ ecore_evas_shutdown();
+ return 0;
+
+error:
+ fprintf(stderr, "you got to have at least one evas engine built and linked"
+ " up to ecore-evas for this example to run properly.\n");
+ ecore_evas_shutdown();
+ return -1;
+}
diff --git a/src/examples/evas/evas-images2.c b/src/examples/evas/evas-images2.c
new file mode 100644
index 0000000000..64f4c9fc43
--- /dev/null
+++ b/src/examples/evas/evas-images2.c
@@ -0,0 +1,311 @@
+/**
+ * Simple Evas example illustrating some image objects functions
+ *
+ * You'll need at least one engine built for it (excluding the buffer
+ * one) and the png image loader/saver also built. See stdout/stderr
+ * for output.
+ *
+ * @verbatim
+ * gcc -o evas-images2 evas-images2.c `pkg-config --libs --cflags evas ecore ecore-evas`
+ * @endverbatim
+ */
+
+#ifdef HAVE_CONFIG_H
+
+#include "config.h"
+#else
+
+#define PACKAGE_EXAMPLES_DIR "."
+#define __UNUSED__
+
+#endif
+
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <stdio.h>
+#include <errno.h>
+
+#define WIDTH (320)
+#define HEIGHT (240)
+
+static const char *img_path = PACKAGE_EXAMPLES_DIR "/enlightenment.png";
+static const char *commands = \
+ "commands are:\n"
+ "\tp - change proxy image's source\n"
+ "\ts - print noise image's stride value\n"
+ "\ta - save noise image to disk (/tmp dir)\n"
+ "\tv - change source visibility\n"
+ "\te - enable/disable source events\n"
+ "\th - print help\n";
+
+const char *file_path = "/tmp/evas-images2-example.png";
+const char *quality_str = "quality=100";
+
+struct test_data
+{
+ Ecore_Evas *ee;
+ Evas *evas;
+ Evas_Object *logo, *noise_img, *proxy_img, *bg;
+};
+
+static struct test_data d = {0};
+
+static void
+_mouse_down(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj,
+ void *event_info)
+{
+ Evas_Event_Mouse_Down *ev = event_info;
+ printf("Mouse Down - obj(%p), coords(%d %d)\n", obj, ev->canvas.x,
+ ev->canvas.y);
+}
+
+static void
+_mouse_move(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj,
+ void *event_info)
+{
+ Evas_Event_Mouse_Move *ev = event_info;
+ printf("Mouse Move - obj(%p), coords(%d %d)\n", obj, ev->cur.canvas.x,
+ ev->cur.canvas.y);
+}
+
+static void
+_mouse_up(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj,
+ void *event_info)
+{
+ Evas_Event_Mouse_Up *ev = event_info;
+ printf("Mouse Up - obj(%p), coords(%d %d)\n", obj, ev->canvas.x,
+ ev->canvas.y);
+}
+
+static void
+_multi_down(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj,
+ void *event_info)
+{
+ Evas_Event_Multi_Down *ev = event_info;
+ printf("Multi Down - obj(%p), coords(%d %d)\n", obj, ev->canvas.x,
+ ev->canvas.y);
+}
+
+static void
+_multi_move(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj,
+ void *event_info)
+{
+ Evas_Event_Multi_Move *ev = event_info;
+ printf("Multi Move - obj(%p), coords(%d %d)\n", obj, ev->cur.canvas.x,
+ ev->cur.canvas.y);
+}
+
+static void
+_multi_up(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj,
+ void *event_info)
+{
+ Evas_Event_Multi_Up *ev = event_info;
+ printf("Multi Up - obj(%p), coords(%d %d)\n", obj, ev->canvas.x,
+ ev->canvas.y);
+}
+
+static void
+_mouse_in(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj,
+ void *event_info)
+{
+ Evas_Event_Mouse_In *ev = event_info;
+ printf("Mouse In - obj(%p), coords(%d %d)\n", obj, ev->canvas.x,
+ ev->canvas.y);
+}
+
+static void
+_mouse_out(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj,
+ void *event_info)
+{
+ Evas_Event_Mouse_Out *ev = event_info;
+ printf("Mouse Out - obj(%p), coords(%d %d)\n", obj, ev->canvas.x,
+ ev->canvas.y);
+}
+
+static void
+_hold(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj,
+ void *event_info)
+{
+ Evas_Event_Hold *ev = event_info;
+ printf("Hold - obj(%p), hold(%d)\n", obj, ev->hold);
+}
+
+static void
+_on_preloaded(void *data __UNUSED__,
+ Evas *e __UNUSED__,
+ Evas_Object *obj __UNUSED__,
+ void *event_info __UNUSED__)
+{
+ fprintf(stdout, "Image has been pre-loaded!\n");
+}
+
+static void
+_on_destroy(Ecore_Evas *ee __UNUSED__)
+{
+ ecore_main_loop_quit();
+}
+
+/* here just to keep our example's window size and background image's
+ * size in synchrony */
+static void
+_canvas_resize_cb(Ecore_Evas *ee)
+{
+ int w, h;
+
+ ecore_evas_geometry_get(ee, NULL, NULL, &w, &h);
+ evas_object_resize(d.bg, w, h);
+}
+
+static void
+_on_keydown(void *data __UNUSED__,
+ Evas *evas __UNUSED__,
+ Evas_Object *o __UNUSED__,
+ void *einfo)
+{
+ Evas_Event_Key_Down *ev = einfo;
+
+ if (strcmp(ev->keyname, "h") == 0) /* print help */
+ {
+ fprintf(stdout, commands);
+ return;
+ }
+
+ if (strcmp(ev->keyname, "s") == 0) /* print proxy image' stride value */
+ {
+ int stride = evas_object_image_stride_get(d.noise_img);
+
+ fprintf(stdout, "Image has row stride value of %d, which accounts"
+ " for %d pixels\n", stride, stride / 4);
+
+ return;
+ }
+
+ if (strcmp(ev->keyname, "p") == 0) /* change proxy's source */
+ {
+ Evas_Object *source = evas_object_image_source_get(d.proxy_img);
+
+ if (source == d.logo) source = d.noise_img;
+ else source = d.logo;
+
+ evas_object_image_source_set(d.proxy_img, source);
+
+ fprintf(stdout, "Proxy image's source changed\n");
+
+ return;
+ }
+
+ if (strcmp(ev->keyname, "a") == 0) /* save noise image to disk */
+ {
+ if (!evas_object_image_save(d.noise_img, file_path, NULL, quality_str))
+ fprintf(stderr, "Cannot save image to '%s' (flags '%s')\n",
+ file_path, quality_str);
+ else
+ fprintf(stdout, "Image saved to '%s' (flags '%s'), check it out with "
+ "an image viewer\n", file_path, quality_str);
+
+ return;
+ }
+
+ if (strcmp(ev->keyname, "v") == 0) /* change source visibility */
+ {
+ Eina_Bool src_visible =
+ evas_object_image_source_visible_get(d.proxy_img);
+ evas_object_image_source_visible_set(d.proxy_img, !src_visible);
+ return;
+ }
+
+ if (strcmp(ev->keyname, "e") == 0) /* change source events */
+ {
+ Eina_Bool src_events = evas_object_image_source_events_get(d.proxy_img);
+ evas_object_image_source_events_set(d.proxy_img, !src_events);
+ return;
+ }
+}
+
+int
+main(void)
+{
+ unsigned int i;
+ unsigned int pixels[(WIDTH / 4) * (HEIGHT / 4)];
+
+ srand(time(NULL));
+
+ if (!ecore_evas_init())
+ return EXIT_FAILURE;
+
+ /* this will give you a window with an Evas canvas under the first
+ * engine available */
+ d.ee = ecore_evas_new(NULL, 10, 10, WIDTH, HEIGHT, NULL);
+ if (!d.ee)
+ goto error;
+
+ ecore_evas_callback_destroy_set(d.ee, _on_destroy);
+ ecore_evas_callback_resize_set(d.ee, _canvas_resize_cb);
+ ecore_evas_show(d.ee);
+
+ /* the canvas pointer, de facto */
+ d.evas = ecore_evas_get(d.ee);
+
+ d.bg = evas_object_rectangle_add(d.evas);
+ evas_object_color_set(d.bg, 255, 255, 255, 255); /* white bg */
+ evas_object_move(d.bg, 0, 0); /* at canvas' origin */
+ evas_object_resize(d.bg, WIDTH, HEIGHT); /* covers full canvas */
+ evas_object_show(d.bg);
+
+ evas_object_focus_set(d.bg, EINA_TRUE);
+ evas_object_event_callback_add(
+ d.bg, EVAS_CALLBACK_KEY_DOWN, _on_keydown, NULL);
+
+ d.logo = evas_object_image_filled_add(d.evas);
+
+ evas_object_event_callback_add(
+ d.logo, EVAS_CALLBACK_IMAGE_PRELOADED, _on_preloaded, NULL);
+ evas_object_image_preload(d.logo, EINA_TRUE);
+
+ evas_object_image_file_set(d.logo, img_path, NULL);
+ evas_object_resize(d.logo, WIDTH / 2, HEIGHT / 2);
+ evas_object_event_callback_add(d.logo, EVAS_CALLBACK_MOUSE_DOWN, _mouse_down, 0);
+ evas_object_event_callback_add(d.logo, EVAS_CALLBACK_MOUSE_MOVE, _mouse_move, 0);
+ evas_object_event_callback_add(d.logo, EVAS_CALLBACK_MOUSE_UP, _mouse_up, 0);
+ evas_object_event_callback_add(d.logo, EVAS_CALLBACK_MOUSE_IN, _mouse_in, 0);
+ evas_object_event_callback_add(d.logo, EVAS_CALLBACK_MOUSE_OUT, _mouse_out, 0);
+ evas_object_event_callback_add(d.logo, EVAS_CALLBACK_MULTI_DOWN, _multi_down, 0);
+ evas_object_event_callback_add(d.logo, EVAS_CALLBACK_MULTI_UP, _multi_up, 0);
+ evas_object_event_callback_add(d.logo, EVAS_CALLBACK_MULTI_MOVE, _multi_move, 0);
+ evas_object_event_callback_add(d.logo, EVAS_CALLBACK_HOLD, _hold, 0);
+
+ evas_object_show(d.logo);
+
+ /* creating noise image */
+ for (i = 0; i < sizeof(pixels) / sizeof(pixels[0]); i++)
+ pixels[i] = rand();
+
+ d.noise_img = evas_object_image_add(d.evas);
+ evas_object_image_size_set(d.noise_img, WIDTH / 4, HEIGHT / 4);
+ evas_object_image_data_set(d.noise_img, pixels);
+ evas_object_image_filled_set(d.noise_img, EINA_TRUE);
+ evas_object_move(d.noise_img, (WIDTH * 3) / 4, 0);
+ evas_object_resize(d.noise_img, WIDTH / 4, HEIGHT / 4);
+ evas_object_show(d.noise_img);
+ fprintf(stdout, "Creating noise image with size %d, %d\n",
+ WIDTH / 4, HEIGHT / 4);
+
+ d.proxy_img = evas_object_image_filled_add(d.evas);
+ evas_object_image_source_set(d.proxy_img, d.logo);
+ evas_object_move(d.proxy_img, WIDTH / 4, HEIGHT / 2);
+ evas_object_resize(d.proxy_img, WIDTH / 2, HEIGHT / 2);
+ evas_object_show(d.proxy_img);
+
+ fprintf(stdout, commands);
+ ecore_main_loop_begin();
+
+ ecore_evas_free(d.ee);
+ ecore_evas_shutdown();
+ return 0;
+
+error:
+ fprintf(stderr, "you got to have at least one evas engine built and linked"
+ " up to ecore-evas for this example to run properly.\n");
+ ecore_evas_shutdown();
+ return -1;
+}
diff --git a/src/examples/evas/evas-images3.c b/src/examples/evas/evas-images3.c
new file mode 100644
index 0000000000..5d627b0a37
--- /dev/null
+++ b/src/examples/evas/evas-images3.c
@@ -0,0 +1,196 @@
+/**
+ * Simple Evas example illustrating some image objects functions
+ *
+ * You'll need at least one engine built for it (excluding the buffer
+ * one) and the png image loader/saver also built. See stdout/stderr
+ * for output.
+ *
+ * @verbatim
+ * gcc -o evas-images2 evas-images2.c `pkg-config --libs --cflags evas ecore ecore-evas`
+ * @endverbatim
+ */
+
+#ifdef HAVE_CONFIG_H
+
+#include "config.h"
+#else
+
+#define PACKAGE_EXAMPLES_DIR "."
+#define __UNUSED__
+
+#endif
+
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <stdio.h>
+#include <errno.h>
+
+#define WIDTH (320)
+#define HEIGHT (240)
+
+static const char *img_path = PACKAGE_EXAMPLES_DIR "/enlightenment.png";
+static const char *commands = \
+ "commands are:\n"
+ "\tw - write new pixel data to image\n"
+ "\ti - print image info\n"
+ "\ta - save noise image to disk (/tmp dir)\n"
+ "\th - print help\n";
+
+const char *file_path = "/tmp/evas-images2-example.png";
+const char *quality_str = "quality=100";
+
+struct test_data
+{
+ Ecore_Evas *ee;
+ Evas *evas;
+ Evas_Object *bg;
+ Evas_Object *logo, *logo1;
+};
+
+static struct test_data d = {0};
+
+static void
+_on_destroy(Ecore_Evas *ee __UNUSED__)
+{
+ ecore_main_loop_quit();
+}
+
+/* here just to keep our example's window size and background image's
+ * size in synchrony */
+static void
+_canvas_resize_cb(Ecore_Evas *ee)
+{
+ int w, h;
+
+ ecore_evas_geometry_get(ee, NULL, NULL, &w, &h);
+ evas_object_resize(d.bg, w, h);
+ evas_object_resize(d.logo, w / 2, h);
+ evas_object_move(d.logo1, w / 2, 0);
+ evas_object_resize(d.logo1, w / 2, h);
+}
+
+static void
+_on_keydown(void *data __UNUSED__,
+ Evas *evas __UNUSED__,
+ Evas_Object *o __UNUSED__,
+ void *einfo)
+{
+ Evas_Event_Key_Down *ev = einfo;
+
+ if (strcmp(ev->keyname, "h") == 0) /* print help */
+ {
+ fprintf(stdout, commands);
+ return;
+ }
+
+ if (strcmp(ev->keyname, "i") == 0) /* change proxy's source */
+ {
+ int stride = evas_object_image_stride_get(d.logo);
+ int w, h;
+
+ evas_object_image_size_get(d.logo, &w, &h);
+
+ printf("image size: %dx%d; stride: %d\n", w, h, stride);
+
+ return;
+ }
+
+ if (strcmp(ev->keyname, "w") == 0) /* save noise image to disk */
+ {
+ int i;
+ char *pixels = evas_object_image_data_get(d.logo, EINA_FALSE);
+ char *bufpixels;
+ int w, h;
+ int stride;
+ Eina_Bool equal = EINA_TRUE;
+
+ evas_object_image_size_get(d.logo, &w, &h);
+ stride = evas_object_image_stride_get(d.logo);
+
+ bufpixels = malloc(sizeof(char) * stride * h);
+ memcpy(bufpixels, pixels, sizeof(char) * stride * h);
+
+ pixels = evas_object_image_data_get(d.logo, EINA_TRUE);
+
+ for (i = 0; i < (stride * h); i++)
+ {
+ if (bufpixels[i] != pixels[i])
+ {
+ equal = EINA_FALSE;
+ break;
+ }
+ }
+
+ free(bufpixels);
+
+ if (!equal)
+ printf("write pixels different from readonly pixels.\n");
+
+ for (i = ((stride * h) / 4) ; i < ((stride * h) / 2) ; i++)
+ {
+ pixels[i] = 0;
+ }
+
+ // evas_object_image_data_set(d.logo, pixels);
+ evas_object_image_data_update_add(d.logo, 0, 0, w, h);
+ return;
+ }
+}
+
+int
+main(void)
+{
+ // unsigned int i;
+ // unsigned int pixels[(WIDTH / 4) * (HEIGHT / 4)];
+
+ if (!ecore_evas_init())
+ return EXIT_FAILURE;
+
+ /* this will give you a window with an Evas canvas under the first
+ * engine available */
+ d.ee = ecore_evas_new(NULL, 10, 10, WIDTH, HEIGHT, NULL);
+ if (!d.ee)
+ goto error;
+
+ ecore_evas_callback_destroy_set(d.ee, _on_destroy);
+ ecore_evas_callback_resize_set(d.ee, _canvas_resize_cb);
+ ecore_evas_show(d.ee);
+
+ /* the canvas pointer, de facto */
+ d.evas = ecore_evas_get(d.ee);
+
+ d.bg = evas_object_rectangle_add(d.evas);
+ evas_object_color_set(d.bg, 255, 255, 255, 255); /* white bg */
+ evas_object_move(d.bg, 0, 0); /* at canvas' origin */
+ evas_object_resize(d.bg, WIDTH, HEIGHT); /* covers full canvas */
+ evas_object_show(d.bg);
+
+ evas_object_focus_set(d.bg, EINA_TRUE);
+ evas_object_event_callback_add(
+ d.bg, EVAS_CALLBACK_KEY_DOWN, _on_keydown, NULL);
+
+ d.logo = evas_object_image_filled_add(d.evas);
+
+ evas_object_image_file_set(d.logo, img_path, NULL);
+ evas_object_resize(d.logo, WIDTH / 2, HEIGHT);
+ evas_object_show(d.logo);
+
+ d.logo1 = evas_object_image_filled_add(d.evas);
+ evas_object_image_file_set(d.logo1, img_path, NULL);
+ evas_object_resize(d.logo1, WIDTH / 2, HEIGHT);
+ evas_object_move(d.logo1, WIDTH / 2, 0);
+ evas_object_show(d.logo1);
+
+ fprintf(stdout, commands);
+ ecore_main_loop_begin();
+
+ ecore_evas_free(d.ee);
+ ecore_evas_shutdown();
+ return 0;
+
+error:
+ fprintf(stderr, "you got to have at least one evas engine built and linked"
+ " up to ecore-evas for this example to run properly.\n");
+ ecore_evas_shutdown();
+ return -1;
+}
diff --git a/src/examples/evas/evas-init-shutdown.c b/src/examples/evas/evas-init-shutdown.c
new file mode 100644
index 0000000000..a7508d8685
--- /dev/null
+++ b/src/examples/evas/evas-init-shutdown.c
@@ -0,0 +1,56 @@
+/**
+ * Simple example illustrating usage of evas_init() and
+ * evas_shutdown(). Usually one would instantiate a canvas to have
+ * something useful out of Evas. For an example of this kind, see the
+ * @ref Example_Evas_Buffer_Simple.
+ *
+ * Here, we are just listing the engine Evas was compiled with support
+ * to.
+ *
+ * @verbatim
+ * gcc -o evas-init-shutdown evas-init-shutdown.c `pkg-config --libs \
+ * --cflags evas`
+ * @endverbatim
+ *
+ */
+
+#include <Evas.h>
+#include <stdio.h>
+#include <errno.h>
+
+/*
+ * Simple example illustrating usage of evas_init() and
+ * evas_shutdown(). Usually one would instantiate a canvas to have
+ * something useful out of Evas. For an example of this kind, see the
+ * evas-buffer-simple.c, which requires the buffer engine module
+ * compiled in Evas.
+ *
+ * Here, we are just listing the engine Evas was compiled with support
+ * to.
+ */
+
+int
+main(void)
+{
+ Eina_List *engine_list, *l;
+ char *engine_name;
+
+ evas_init();
+
+ engine_list = evas_render_method_list();
+ if (!engine_list)
+ {
+ fprintf(stderr, "ERROR: Evas supports no engines! Exit.\n");
+ exit(-1);
+ }
+
+ printf("Available Evas Engines:\n");
+ EINA_LIST_FOREACH(engine_list, l, engine_name)
+ printf("%s\n", engine_name);
+
+ evas_render_method_list_free(engine_list);
+
+ evas_shutdown();
+ return 0;
+ }
+
diff --git a/src/examples/evas/evas-map-utils.c b/src/examples/evas/evas-map-utils.c
new file mode 100644
index 0000000000..2d15882f53
--- /dev/null
+++ b/src/examples/evas/evas-map-utils.c
@@ -0,0 +1,321 @@
+/*
+ * gcc -o evas-map-utils evas-map-utils.c `pkg-config --cflags --libs evas ecore ecore-evas`
+ */
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#else
+#define __UNUSED__
+#endif
+
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+
+#define WIDTH 480
+#define HEIGHT 480
+
+typedef struct
+{
+ Ecore_Evas *ee;
+ Evas *canvas;
+ struct {
+ int r, g, b, a;
+ } colors[6];
+ int colors_index;
+ int frame;
+ Eina_Bool alpha : 1;
+ Eina_Bool smooth : 1;
+ Eina_Bool backface_culling : 1;
+ Eina_Bool apply_perspective : 1;
+ Eina_Bool apply_lighting : 1;
+} App_Data;
+
+static const char *help_string =
+ "Valid commands:\n"
+ "\ta - toggle alpha for maps\n"
+ "\ts - toggle smooth for maps\n"
+ "\tc - switch map color\n"
+ "\tb - toggle backface culling\n"
+ "\tp - toggle perspective\n"
+ "\tl - toggle lighting\n"
+ "\th - prints this help\n";
+
+static Eina_Bool
+_anim_cb(void *data)
+{
+ App_Data *ad = data;
+ Evas_Map *m;
+ const Evas_Map *old_map;
+ Evas_Object *o;
+ int r, g, b, a;
+ int win_w, win_h, img_w, img_h;
+ Evas_Coord x, y, w, h;
+
+ evas_output_size_get(ad->canvas, &win_w, &win_h);
+
+ m = evas_map_new(4);
+ evas_map_smooth_set(m, ad->smooth);
+ evas_map_alpha_set(m, ad->alpha);
+
+ r = ad->colors[ad->colors_index].r;
+ g = ad->colors[ad->colors_index].g;
+ b = ad->colors[ad->colors_index].b;
+ a = ad->colors[ad->colors_index].a;
+ evas_map_util_points_color_set(m, r, g, b, a);
+
+ o = evas_object_name_find(ad->canvas, "obj1");
+ evas_object_geometry_get(o, &x, &y, &w, &h);
+
+ evas_map_util_points_populate_from_object(m, o);
+ evas_map_util_rotate(m, 3 * ad->frame, x + (w / 2), y + (h / 2));
+ evas_object_map_set(o, m);
+ evas_object_map_enable_set(o, EINA_TRUE);
+
+ o = evas_object_name_find(ad->canvas, "obj2");
+ evas_object_geometry_get(o, &x, &y, &w, &h);
+ evas_object_image_size_get(o, &img_w, &img_h);
+
+ evas_map_util_points_populate_from_object_full(m, o, 100);
+ evas_map_point_image_uv_set(m, 0, 0, 0);
+ evas_map_point_image_uv_set(m, 1, img_w, 0);
+ evas_map_point_image_uv_set(m, 2, img_w, img_h);
+ evas_map_point_image_uv_set(m, 3, 0, img_h);
+ evas_map_util_3d_rotate(m, ad->frame * 6, ad->frame * 6, ad->frame * 6,
+ x + (w / 3), y + 10, 0);
+ if (ad->apply_lighting)
+ evas_map_util_3d_lighting(m, win_w / 2, win_h / 2, -100,
+ 255, 255, 255, 0, 0, 0);
+ evas_object_map_set(o, m);
+ evas_object_map_enable_set(o, EINA_TRUE);
+
+ o = evas_object_name_find(ad->canvas, "obj3");
+ evas_object_geometry_get(o, &x, &y, &w, &h);
+ evas_object_image_size_get(o, &img_w, &img_h);
+
+ evas_map_util_points_populate_from_geometry(m, x, y + (h / 2), w, h, -20);
+ evas_map_point_image_uv_set(m, 0, 0, 0);
+ evas_map_point_image_uv_set(m, 1, img_w, 0);
+ evas_map_point_image_uv_set(m, 2, img_w, img_h);
+ evas_map_point_image_uv_set(m, 3, 0, img_h);
+ evas_map_util_3d_rotate(m, 20, ad->frame * 6, 0,
+ x + (w / 2), y + (w / 2), w / 2);
+
+ if (ad->apply_perspective)
+ evas_map_util_3d_perspective(m, x + (w / 2), y + (h / 2), 0, 256);
+ if (ad->apply_lighting)
+ {
+ Evas_Coord mx, my;
+ evas_pointer_canvas_xy_get(ad->canvas, &mx, &my);
+ evas_map_util_3d_lighting(m, mx, my, -256,
+ 255, 255, 255, 0, 0, 0);
+ }
+ if (ad->backface_culling)
+ {
+ if (evas_map_util_clockwise_get(m))
+ evas_object_show(o);
+ else
+ evas_object_hide(o);
+ }
+ else
+ evas_object_show(o);
+ evas_object_map_set(o, m);
+ evas_object_map_enable_set(o, EINA_TRUE);
+
+ evas_map_free(m);
+
+ o = evas_object_name_find(ad->canvas, "obj4");
+ evas_object_geometry_get(o, &x, &y, &w, &h);
+ evas_object_image_size_get(evas_object_image_source_get(o), &img_w, &img_h);
+
+ m = evas_map_new(4);
+ evas_map_point_coord_set(m, 0, x, y + h, 0);
+ evas_map_point_coord_set(m, 1, x + w, y + h, 0);
+ evas_map_point_coord_set(m, 2, win_w - 10, win_h - 30, 0);
+ evas_map_point_coord_set(m, 3, (win_w / 2) + 10, win_h - 30, 0);
+ evas_map_point_image_uv_set(m, 0, 0, img_h);
+ evas_map_point_image_uv_set(m, 1, img_w, img_h);
+ evas_map_point_image_uv_set(m, 2, img_w, 2 * (img_h / 3));
+ evas_map_point_image_uv_set(m, 3, 0, 2 * (img_h / 3));
+ evas_map_point_color_set(m, 0, 200, 200, 200, 150);
+ evas_map_point_color_set(m, 1, 200, 200, 200, 150);
+ evas_map_point_color_set(m, 2, 0, 0, 0, 0);
+ evas_map_point_color_set(m, 3, 0, 0, 0, 0);
+ evas_object_map_set(o, m);
+ evas_object_map_enable_set(o, EINA_TRUE);
+
+ evas_map_free(m);
+
+ ad->frame = (ad->frame + 1) % 60;
+
+ return EINA_TRUE;
+}
+
+static void
+_on_keydown(void *data, Evas *e, Evas_Object *o, void *event)
+{
+ App_Data *ad = data;
+ Evas_Event_Key_Down *ev = event;
+ const Evas_Modifier *mods;
+
+ mods = evas_key_modifier_get(ad->canvas);
+ switch (ev->keyname[0])
+ {
+ case 'a':
+ ad->alpha = !ad->alpha;
+ break;
+ case 's':
+ ad->smooth = !ad->smooth;
+ break;
+ case 'c':
+ ad->colors_index = (ad->colors_index + 1) % 6;
+ break;
+ case 'b':
+ ad->backface_culling = !ad->backface_culling;
+ break;
+ case 'p':
+ ad->apply_perspective = !ad->apply_perspective;
+ break;
+ case 'l':
+ ad->apply_lighting = !ad->apply_lighting;
+ break;
+ case 'h':
+ puts(help_string);
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+_objs_fit(Evas *e)
+{
+ Evas_Object *o;
+ int w, h;
+
+ evas_output_size_get(e, &w, &h);
+ w /= 2;
+ h /= 2;
+
+ o = evas_object_name_find(e, "obj1");
+ evas_object_move(o, w / 4, h / 4);
+ evas_object_resize(o, w / 2, h / 2);
+
+ o = evas_object_name_find(e, "obj2");
+ evas_object_move(o, 5 * w / 4, h / 4);
+ evas_object_resize(o, w / 2, h / 2);
+
+ o = evas_object_name_find(e, "obj3");
+ evas_object_move(o, w / 4, 5 * h / 4);
+ evas_object_resize(o, w / 2, h / 2);
+
+ o = evas_object_name_find(e, "obj4_source");
+ evas_object_move(o, 5 * w / 4, 5 * h / 4);
+ evas_object_resize(o, w / 2, h / 2);
+
+ o = evas_object_name_find(e, "obj4");
+ evas_object_move(o, 5 * w / 4, 5 * h / 4);
+ evas_object_resize(o, w / 2, h / 2);
+}
+
+static void
+_on_resize(void *data __UNUSED__, Evas *e, Evas_Object *o __UNUSED__, void *event __UNUSED__)
+{
+ _objs_fit(e);
+}
+
+static void
+_on_free(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *o __UNUSED__, void *event __UNUSED__)
+{
+ ecore_main_loop_quit();
+}
+
+int
+main(void)
+{
+ Evas_Object *bg, *o, *osrc;
+ static App_Data d = {
+ .ee = NULL,
+ .canvas = NULL,
+ .colors = {
+ { 255, 255, 255, 255 },
+ { 128, 128, 0, 128 },
+ { 255, 0, 0, 255 },
+ { 64, 128, 255, 255 },
+ { 11, 23, 58, 132 },
+ { 0, 0, 0, 255 }
+ },
+ .colors_index = 0,
+ .frame = 0,
+ .alpha = EINA_FALSE,
+ .smooth = EINA_FALSE,
+ .backface_culling = EINA_FALSE,
+ .apply_perspective = EINA_TRUE,
+ .apply_lighting = EINA_TRUE
+ };
+
+ if (!ecore_evas_init())
+ return EXIT_FAILURE;
+
+ d.ee = ecore_evas_new(NULL, 0, 0, WIDTH, HEIGHT, NULL);
+ if (!d.ee)
+ goto error;
+
+ d.canvas = ecore_evas_get(d.ee);
+
+ bg = evas_object_image_filled_add(d.canvas);
+ evas_object_image_file_set(bg, "cube1.png", NULL);
+ ecore_evas_object_associate(d.ee, bg, 0);
+ evas_object_focus_set(bg, EINA_TRUE);
+ evas_object_move(bg, 0, 0);
+ evas_object_resize(bg, WIDTH, HEIGHT);
+ evas_object_show(bg);
+
+ o = evas_object_rectangle_add(d.canvas);
+ evas_object_name_set(o, "obj1");
+ evas_object_color_set(o, 128, 0, 200, 200);
+ evas_object_show(o);
+
+ o = evas_object_image_filled_add(d.canvas);
+ evas_object_name_set(o, "obj2");
+ evas_object_image_file_set(o, "enlightenment.png", NULL);
+ evas_object_show(o);
+
+ o = evas_object_image_filled_add(d.canvas);
+ evas_object_name_set(o, "obj3");
+ evas_object_image_file_set(o, "enlightenment.png", NULL);
+ evas_object_show(o);
+
+ osrc = evas_object_image_filled_add(d.canvas);
+ evas_object_image_file_set(osrc, "im1.png", NULL);
+ evas_object_name_set(osrc, "obj4_source");
+ evas_object_show(osrc);
+
+ o = evas_object_image_filled_add(d.canvas);
+ evas_object_image_source_set(o, osrc);
+ evas_object_name_set(o, "obj4");
+ evas_object_show(o);
+
+ _objs_fit(d.canvas);
+
+ evas_object_event_callback_add(bg, EVAS_CALLBACK_KEY_DOWN, _on_keydown, &d);
+ evas_object_event_callback_add(bg, EVAS_CALLBACK_RESIZE, _on_resize, NULL);
+ evas_object_event_callback_add(bg, EVAS_CALLBACK_FREE, _on_free, NULL);
+
+ ecore_animator_add(_anim_cb, &d);
+
+ ecore_main_loop_begin();
+
+ ecore_evas_shutdown();
+ return 0;
+
+error:
+ fprintf(stderr, "you got to have at least one evas engine built and linked"
+ " up to ecore-evas for this example to run properly.\n");
+panic:
+ ecore_evas_shutdown();
+ return -1;
+}
diff --git a/src/examples/evas/evas-object-manipulation.c b/src/examples/evas/evas-object-manipulation.c
new file mode 100644
index 0000000000..e9c94427c6
--- /dev/null
+++ b/src/examples/evas/evas-object-manipulation.c
@@ -0,0 +1,235 @@
+/**
+ * Simple Evas example illustrating basic objects manipulation.
+ *
+ * You'll need at least one engine built for it (excluding the buffer
+ * one) and the png image loader also built. See stdout/stderr for
+ * output.
+ *
+ * @verbatim
+ * gcc -o evas-object-manipulation evas-object-manipulation.c `pkg-config --libs --cflags ecore evas ecore-evas`
+ * @endverbatim
+ */
+
+#ifdef HAVE_CONFIG_H
+
+#include "config.h"
+#else
+
+#define PACKAGE_EXAMPLES_DIR "."
+#define __UNUSED__
+
+#endif
+
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <stdio.h>
+#include <errno.h>
+
+#define WIDTH (320)
+#define HEIGHT (240)
+
+static const char *img_path = PACKAGE_EXAMPLES_DIR "/enlightenment.png";
+static const char *border_img_path = PACKAGE_EXAMPLES_DIR "/red.png";
+
+struct test_data
+{
+ Ecore_Evas *ee;
+ Evas *canvas;
+ Evas_Object *img, *bg, *clipper, *clipper_border, *text;
+};
+
+static struct test_data d = {0};
+
+/* here just to keep our example's window size and background image's
+ * size in synchrony */
+static void
+_canvas_resize_cb(Ecore_Evas *ee)
+{
+ int w, h;
+
+ ecore_evas_geometry_get(ee, NULL, NULL, &w, &h);
+ evas_object_resize(d.bg, w, h);
+}
+
+static void
+_on_keydown(void *data __UNUSED__,
+ Evas *evas __UNUSED__,
+ Evas_Object *o __UNUSED__,
+ void *einfo)
+{
+ Evas_Event_Key_Down *ev = einfo;
+
+ if (strcmp(ev->keyname, "h") == 0) /* print help */
+ {
+ fprintf(stdout, "commands are:\n"
+ "\to - change clipper's opacity\n"
+ "\tr - toggle clipper's color between red and white\n"
+ "\tc - toggle clipper's clipping function\n"
+ "\tv - toggle clipper's visibility\n");
+ return;
+ }
+
+ if (strcmp(ev->keyname, "o") == 0) /* change clipper's opacity */
+ {
+ int alpha, r, g, b;
+
+ evas_object_color_get(d.clipper, &r, &g, &b, &alpha);
+ alpha -= 20;
+ if (alpha < 0)
+ alpha = 255;
+
+ evas_object_color_set(d.clipper, r, g, b, alpha);
+
+ fprintf(stdout, "Changing clipper's opacity: %d%%\n",
+ (int)((alpha / 255.0) * 100));
+ return;
+ }
+
+ if (strcmp(ev->keyname, "r") == 0) /* toggle clipper's color
+ * between red and white */
+ {
+ int alpha, r, g, b;
+
+ fprintf(stdout, "Changing clipper's color to");
+
+ evas_object_color_get(d.clipper, &r, &g, &b, &alpha);
+ if (g > 0)
+ {
+ fprintf(stdout, "red\n");
+ g = b = 0;
+ }
+ else
+ {
+ fprintf(stdout, "white\n");
+ g = b = 255;
+ }
+
+ evas_object_color_set(d.clipper, r, g, b, alpha);
+ return;
+ }
+
+ if (strcmp(ev->keyname, "c") == 0) /* toggle clipper's clipping function */
+ {
+ fprintf(stdout, "Toggling clipping ");
+
+ if (evas_object_clip_get(d.img) == d.clipper)
+ {
+ evas_object_clip_unset(d.img);
+ fprintf(stdout, "off\n");
+ }
+ else
+ {
+ evas_object_clip_set(d.img, d.clipper);
+ fprintf(stdout, "on\n");
+ }
+ return;
+ }
+
+ if (strcmp(ev->keyname, "v") == 0) /* toggle clipper's visibility */
+ {
+ fprintf(stdout, "Clipper is now ");
+
+ if (evas_object_visible_get(d.clipper))
+ {
+ evas_object_hide(d.clipper);
+ fprintf(stdout, "hidden\n");
+ }
+ else
+ {
+ evas_object_show(d.clipper);
+ fprintf(stdout, "visible\n");
+ }
+ return;
+ }
+}
+
+int
+main(void)
+{
+ int err;
+
+ if (!ecore_evas_init())
+ return EXIT_FAILURE;
+
+ /* this will give you a window with an Evas canvas under the first
+ * engine available */
+ d.ee = ecore_evas_new(NULL, 10, 10, WIDTH, HEIGHT, NULL);
+ if (!d.ee)
+ goto error;
+
+ ecore_evas_callback_resize_set(d.ee, _canvas_resize_cb);
+ ecore_evas_show(d.ee);
+
+ /* the canvas pointer, de facto */
+ d.canvas = ecore_evas_get(d.ee);
+
+ d.bg = evas_object_rectangle_add(d.canvas);
+ evas_object_name_set(d.bg, "background rectangle");
+ evas_object_color_set(d.bg, 255, 255, 255, 255); /* white bg */
+ evas_object_move(d.bg, 0, 0); /* at canvas' origin */
+ evas_object_resize(d.bg, WIDTH, HEIGHT); /* covers full canvas */
+ evas_object_show(d.bg);
+
+ evas_object_focus_set(d.bg, EINA_TRUE);
+ evas_object_event_callback_add(
+ d.bg, EVAS_CALLBACK_KEY_DOWN, _on_keydown, NULL);
+
+ d.img = evas_object_image_filled_add(d.canvas);
+ evas_object_image_file_set(d.img, img_path, NULL);
+ err = evas_object_image_load_error_get(d.img);
+ if (err != EVAS_LOAD_ERROR_NONE)
+ {
+ goto panic;
+ }
+ else
+ {
+ evas_object_move(d.img, 0, 0);
+ evas_object_resize(d.img, WIDTH, HEIGHT);
+ evas_object_show(d.img);
+
+ fprintf(stdout, "Image object added, type is: %s\n",
+ evas_object_type_get(d.img));
+ }
+
+ /* border on the image's clipper, here just to emphasize its position */
+ d.clipper_border = evas_object_image_filled_add(d.canvas);
+ evas_object_image_file_set(d.clipper_border, border_img_path, NULL);
+ err = evas_object_image_load_error_get(d.clipper_border);
+ if (err != EVAS_LOAD_ERROR_NONE)
+ {
+ goto panic;
+ }
+ else
+ {
+ evas_object_image_border_set(d.clipper_border, 3, 3, 3, 3);
+ evas_object_image_border_center_fill_set(
+ d.clipper_border, EVAS_BORDER_FILL_NONE);
+ evas_object_move(d.clipper_border, (WIDTH / 4) - 3, (HEIGHT / 4) - 3);
+ evas_object_resize(
+ d.clipper_border, (WIDTH / 2) + 6, (HEIGHT / 2) + 6);
+ evas_object_show(d.clipper_border);
+ }
+
+ /* solid white clipper (note that it's the default color for a
+ * rectangle) - it won't change clippees' colors, then (multiplying
+ * by 255) */
+ d.clipper = evas_object_rectangle_add(d.canvas);
+ evas_object_move(d.clipper, WIDTH / 4, HEIGHT / 4);
+ evas_object_resize(d.clipper, WIDTH / 2, HEIGHT / 2);
+ evas_object_clip_set(d.img, d.clipper);
+ evas_object_show(d.clipper);
+
+ ecore_main_loop_begin();
+
+ ecore_evas_free(d.ee);
+ ecore_evas_shutdown();
+ return 0;
+
+error:
+ fprintf(stderr, "you got to have at least one evas engine built and linked"
+ " up to ecore-evas for this example to run properly.\n");
+panic:
+ ecore_evas_free(d.ee);
+ ecore_evas_shutdown();
+ return -1;
+}
diff --git a/src/examples/evas/evas-smart-interface.c b/src/examples/evas/evas-smart-interface.c
new file mode 100644
index 0000000000..97b9a9e6a6
--- /dev/null
+++ b/src/examples/evas/evas-smart-interface.c
@@ -0,0 +1,790 @@
+/**
+ * Simple Evas example illustrating Evas smart interfaces
+ *
+ * You'll need at least one engine built for it (excluding the buffer
+ * one). See stdout/stderr for output.
+ *
+ * @verbatim
+ * gcc -o evas-smart-interface evas-smart-interface.c `pkg-config --libs --cflags evas ecore ecore-evas`
+ * @endverbatim
+ */
+
+#ifdef HAVE_CONFIG_H
+
+#include "config.h"
+#else
+
+#define PACKAGE_EXAMPLES_DIR "."
+#define __UNUSED__
+
+#endif
+
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <stdio.h>
+#include <errno.h>
+
+#define WIDTH (320)
+#define HEIGHT (240)
+
+static const char *commands = \
+ "commands are:\n"
+ "\tl - insert child rectangle on the left\n"
+ "\tr - insert child rectangle on the right\n"
+ "\tw - remove and delete all members from the smart object\n"
+ "\tright arrow - move smart object to the right\n"
+ "\tleft arrow - move smart object to the left\n"
+ "\tup arrow - move smart object up\n"
+ "\tdown arrow - move smart object down\n"
+ "\td - decrease smart object's size\n"
+ "\ti - increase smart object's size\n"
+ "\tc - change smart object's clipper color\n"
+ "\th - print help\n"
+ "\tq - quit\n"
+;
+
+#define WHITE {255, 255, 255, 255}
+#define RED {255, 0, 0, 255}
+#define GREEN {0, 255, 0, 255}
+#define BLUE {0, 0, 255, 255}
+
+struct test_data
+{
+ Ecore_Evas *ee;
+ Evas *evas;
+ Evas_Object *smt, *bg, *clipper, *rects[2];
+};
+
+struct color_tuple
+{
+ int r, g, b, a;
+} clipper_colors[4] = {WHITE, RED, GREEN, BLUE};
+int cur_color = 0;
+
+static const char *
+_index_to_color(int i)
+{
+ switch (i)
+ {
+ case 0:
+ return "WHITE (default)";
+
+ case 1:
+ return "RED";
+
+ case 2:
+ return "GREEN";
+
+ case 3:
+ return "BLUE";
+
+ default:
+ return "other";
+ }
+}
+
+static struct test_data d = {0};
+static const char *border_img_path = PACKAGE_EXAMPLES_DIR "/red.png";
+
+#define _evas_smart_example_type "Evas_Smart_Example"
+
+static const char iface1_data[] = "iface1_data";
+static const char IFACE1_NAME[] = "iface1";
+
+static Eina_Bool _iface1_add(Evas_Object *);
+static void _iface1_del(Evas_Object *);
+static void _iface1_custom_fn(Evas_Object *);
+
+typedef struct _Evas_Smart_Example_Interface Evas_Smart_Example_Interface;
+struct _Evas_Smart_Example_Interface
+{
+ Evas_Smart_Interface base;
+ void (*example_func)(Evas_Object *obj);
+};
+
+static Evas_Smart_Example_Interface iface1;
+
+static Eina_Bool
+_iface1_add(Evas_Object *obj)
+{
+ printf("iface1's add()!\n");
+
+ return EINA_TRUE;
+}
+
+static void
+_iface1_del(Evas_Object *obj)
+{
+ printf("iface1's del()! Data is %s\n",
+ (char *)evas_object_smart_interface_data_get
+ (obj, (Evas_Smart_Interface *)&iface1));
+}
+
+static void
+_iface1_custom_fn(Evas_Object *obj)
+{
+ printf("iface1's custom_fn()!\n");
+}
+
+static const Evas_Smart_Interface *_smart_interfaces[] =
+{
+ (Evas_Smart_Interface *)&iface1, NULL
+};
+
+#define EVT_CHILDREN_NUMBER_CHANGED "children,changed"
+
+static const Evas_Smart_Cb_Description _smart_callbacks[] =
+{
+ {EVT_CHILDREN_NUMBER_CHANGED, "i"},
+ {NULL, NULL}
+};
+
+typedef struct _Evas_Smart_Example_Data Evas_Smart_Example_Data;
+/*
+ * This structure augments clipped smart object's instance data,
+ * providing extra members required by our example smart object's
+ * implementation.
+ */
+struct _Evas_Smart_Example_Data
+{
+ Evas_Object_Smart_Clipped_Data base;
+ Evas_Object *children[2], *border;
+ int child_count;
+};
+
+#define EVAS_SMART_EXAMPLE_DATA_GET(o, ptr) \
+ Evas_Smart_Example_Data * ptr = evas_object_smart_data_get(o)
+
+#define EVAS_SMART_EXAMPLE_DATA_GET_OR_RETURN(o, ptr) \
+ EVAS_SMART_EXAMPLE_DATA_GET(o, ptr); \
+ if (!ptr) \
+ { \
+ fprintf(stderr, "No widget data for object %p (%s)!", \
+ o, evas_object_type_get(o)); \
+ fflush(stderr); \
+ abort(); \
+ return; \
+ }
+
+#define EVAS_SMART_EXAMPLE_DATA_GET_OR_RETURN_VAL(o, ptr, val) \
+ EVAS_SMART_EXAMPLE_DATA_GET(o, ptr); \
+ if (!ptr) \
+ { \
+ fprintf(stderr, "No widget data for object %p (%s)!", \
+ o, evas_object_type_get(o)); \
+ fflush(stderr); \
+ abort(); \
+ return val; \
+ }
+
+EVAS_SMART_SUBCLASS_IFACE_NEW
+ (_evas_smart_example_type, _evas_smart_example, Evas_Smart_Class,
+ Evas_Smart_Class, evas_object_smart_clipped_class_get, _smart_callbacks,
+ _smart_interfaces);
+
+static void
+_on_destroy(Ecore_Evas *ee __UNUSED__)
+{
+ ecore_main_loop_quit();
+}
+
+/* here just to keep our example's window size and background image's
+ * size in synchrony */
+static void
+_canvas_resize_cb(Ecore_Evas *ee)
+{
+ int w, h;
+
+ ecore_evas_geometry_get(ee, NULL, NULL, &w, &h);
+ evas_object_resize(d.bg, w, h);
+}
+
+static void
+_on_child_del(void *data,
+ Evas *evas __UNUSED__,
+ Evas_Object *o,
+ void *einfo __UNUSED__)
+{
+ Evas_Object *example_smart = data;
+ long idx;
+
+ EVAS_SMART_EXAMPLE_DATA_GET(example_smart, priv);
+
+ idx = (long)evas_object_data_get(o, "index");
+ idx--;
+
+ priv->children[idx] = NULL;
+
+ evas_object_smart_member_del(o);
+ evas_object_smart_changed(example_smart);
+}
+
+static void
+_evas_smart_example_child_callbacks_unregister(Evas_Object *obj)
+{
+ evas_object_data_set(obj, "index", NULL);
+ evas_object_event_callback_del(obj, EVAS_CALLBACK_FREE, _on_child_del);
+}
+
+static void
+_evas_smart_example_child_callbacks_register(Evas_Object *o,
+ Evas_Object *child,
+ long idx)
+{
+ evas_object_event_callback_add(child, EVAS_CALLBACK_FREE, _on_child_del, o);
+ evas_object_data_set(child, "index", (void *)(++idx));
+}
+
+/* create and setup a new example smart object's internals */
+static void
+_evas_smart_example_smart_add(Evas_Object *o)
+{
+ EVAS_SMART_DATA_ALLOC(o, Evas_Smart_Example_Data);
+
+ /* this is a border around the smart object's area, delimiting it */
+ priv->border = evas_object_image_filled_add(evas_object_evas_get(o));
+ evas_object_image_file_set(priv->border, border_img_path, NULL);
+ evas_object_image_border_set(priv->border, 3, 3, 3, 3);
+ evas_object_image_border_center_fill_set(
+ priv->border, EVAS_BORDER_FILL_NONE);
+ evas_object_smart_member_add(priv->border, o);
+
+ _evas_smart_example_parent_sc->add(o);
+}
+
+static void
+_evas_smart_example_smart_del(Evas_Object *o)
+{
+ EVAS_SMART_EXAMPLE_DATA_GET(o, priv);
+
+ if (priv->children[0])
+ {
+ _evas_smart_example_child_callbacks_unregister(priv->children[0]);
+ priv->children[0] = NULL;
+ }
+
+ if (priv->children[1])
+ {
+ _evas_smart_example_child_callbacks_unregister(priv->children[1]);
+ priv->children[1] = NULL;
+ }
+
+ _evas_smart_example_parent_sc->del(o);
+}
+
+static void
+_evas_smart_example_smart_show(Evas_Object *o)
+{
+ EVAS_SMART_EXAMPLE_DATA_GET(o, priv);
+
+ if (priv->children[0]) evas_object_show(priv->children[0]);
+ if (priv->children[1]) evas_object_show(priv->children[1]);
+ evas_object_show(priv->border);
+
+ _evas_smart_example_parent_sc->show(o);
+}
+
+static void
+_evas_smart_example_smart_hide(Evas_Object *o)
+{
+ EVAS_SMART_EXAMPLE_DATA_GET(o, priv);
+
+ if (priv->children[0]) evas_object_hide(priv->children[0]);
+ if (priv->children[1]) evas_object_hide(priv->children[1]);
+ evas_object_hide(priv->border);
+
+ _evas_smart_example_parent_sc->hide(o);
+}
+
+static void
+_evas_smart_example_smart_resize(Evas_Object *o,
+ Evas_Coord w,
+ Evas_Coord h)
+{
+ Evas_Coord ow, oh;
+ evas_object_geometry_get(o, NULL, NULL, &ow, &oh);
+ if ((ow == w) && (oh == h)) return;
+
+ /* this will trigger recalculation */
+ evas_object_smart_changed(o);
+}
+
+/* act on child objects' properties, before rendering */
+static void
+_evas_smart_example_smart_calculate(Evas_Object *o)
+{
+ Evas_Coord x, y, w, h;
+
+ EVAS_SMART_EXAMPLE_DATA_GET_OR_RETURN(o, priv);
+ evas_object_geometry_get(o, &x, &y, &w, &h);
+
+ evas_object_resize(priv->border, w, h);
+ evas_object_move(priv->border, x, y);
+
+ if (priv->children[0])
+ {
+ evas_object_move(priv->children[0], x + 3, y + 3);
+ evas_object_resize(priv->children[0], (w / 2) - 3, (h / 2) - 3);
+ }
+
+ if (priv->children[1])
+ {
+ evas_object_move(priv->children[1], x + (w / 2), y + (h / 2));
+ evas_object_resize(priv->children[1], (w / 2) - 3, (h / 2) - 3);
+ }
+}
+
+/* setting our smart interface */
+static void
+_evas_smart_example_smart_set_user(Evas_Smart_Class *sc)
+{
+ /* specializing these two */
+ sc->add = _evas_smart_example_smart_add;
+ sc->del = _evas_smart_example_smart_del;
+ sc->show = _evas_smart_example_smart_show;
+ sc->hide = _evas_smart_example_smart_hide;
+
+ /* clipped smart object has no hook on resizes or calculations */
+ sc->resize = _evas_smart_example_smart_resize;
+ sc->calculate = _evas_smart_example_smart_calculate;
+}
+
+/* BEGINS example smart object's own interface */
+
+/* add a new example smart object to a canvas */
+Evas_Object *
+evas_smart_example_add(Evas *evas)
+{
+ return evas_object_smart_add(evas, _evas_smart_example_smart_class_new());
+}
+
+static void
+_evas_smart_example_remove_do(Evas_Smart_Example_Data *priv,
+ Evas_Object *child,
+ int idx)
+{
+ priv->children[idx] = NULL;
+ priv->child_count--;
+ _evas_smart_example_child_callbacks_unregister(child);
+ evas_object_smart_member_del(child);
+}
+
+/* remove a child element, return its pointer (or NULL on errors) */
+Evas_Object *
+evas_smart_example_remove(Evas_Object *o,
+ Evas_Object *child)
+{
+ long idx;
+
+ EVAS_SMART_EXAMPLE_DATA_GET_OR_RETURN_VAL(o, priv, NULL);
+
+ if (priv->children[0] != child && priv->children[1] != child)
+ {
+ fprintf(stderr, "You are trying to remove something not belonging to"
+ " the example smart object!\n");
+ return NULL;
+ }
+
+ idx = (long)evas_object_data_get(child, "index");
+ idx--;
+
+ _evas_smart_example_remove_do(priv, child, idx);
+
+ evas_object_smart_callback_call(
+ o, EVT_CHILDREN_NUMBER_CHANGED, (void *)(long)priv->child_count);
+ evas_object_smart_changed(o);
+
+ return child;
+}
+
+/* set to return any previous object set to the left position of the
+ * smart object or NULL, if any (or on errors) */
+Evas_Object *
+evas_smart_example_set_left(Evas_Object *o,
+ Evas_Object *child)
+{
+ Evas_Object *ret = NULL;
+
+ EVAS_SMART_EXAMPLE_DATA_GET_OR_RETURN_VAL(o, priv, NULL);
+ if (!child)
+ return NULL;
+
+ if (priv->children[1] == child)
+ {
+ fprintf(stderr, "You mustn't place a child on both slots of"
+ " the example smart object!\n");
+ return NULL;
+ }
+
+ if (priv->children[0])
+ {
+ if (priv->children[0] != child)
+ {
+ ret = priv->children[0];
+ _evas_smart_example_remove_do(priv, priv->children[0], 0);
+ }
+ else return child;
+ }
+
+ priv->children[0] = child;
+ _evas_smart_example_child_callbacks_register(o, child, 0);
+ evas_object_smart_member_add(child, o);
+ evas_object_smart_changed(o);
+
+ priv->child_count++;
+ if (!ret)
+ {
+ evas_object_smart_callback_call(
+ o, EVT_CHILDREN_NUMBER_CHANGED, (void *)(long)priv->child_count);
+ }
+
+ return ret;
+}
+
+/* set to return any previous object set to the right position of the
+ * smart object or NULL, if any (or on errors) */
+Evas_Object *
+evas_smart_example_set_right(Evas_Object *o,
+ Evas_Object *child)
+{
+ Evas_Object *ret = NULL;
+
+ EVAS_SMART_EXAMPLE_DATA_GET_OR_RETURN_VAL(o, priv, NULL);
+ if (!child)
+ return NULL;
+
+ if (priv->children[0] == child)
+ {
+ fprintf(stderr, "You mustn't place a child on both slots of"
+ " the example smart object!\n");
+ return NULL;
+ }
+
+ if (priv->children[1])
+ {
+ if (priv->children[1] != child)
+ {
+ ret = priv->children[1];
+ _evas_smart_example_remove_do(priv, priv->children[1], 1);
+ }
+ else return child;
+ }
+
+ priv->children[1] = child;
+ _evas_smart_example_child_callbacks_register(o, child, 1);
+ evas_object_smart_member_add(child, o);
+ evas_object_smart_changed(o);
+
+ priv->child_count++;
+ if (!ret)
+ {
+ evas_object_smart_callback_call(
+ o, EVT_CHILDREN_NUMBER_CHANGED, (void *)(long)priv->child_count);
+ }
+
+ return ret;
+}
+
+/* END OF example smart object's own interface */
+
+static void
+_on_keydown(void *data __UNUSED__,
+ Evas *evas __UNUSED__,
+ Evas_Object *o __UNUSED__,
+ void *einfo)
+{
+ Evas_Event_Key_Down *ev = einfo;
+
+ if (strcmp(ev->keyname, "q") == 0) /* print help */
+ {
+ _on_destroy(NULL);
+ return;
+ }
+
+ if (strcmp(ev->keyname, "h") == 0) /* print help */
+ {
+ fprintf(stdout, commands);
+ return;
+ }
+
+ if (strcmp(ev->keyname, "w") == 0) /* clear out smart object (WRT
+ * members) */
+ {
+ if (d.rects[0])
+ {
+ evas_smart_example_remove(d.smt, d.rects[0]);
+ evas_object_del(d.rects[0]);
+ }
+ if (d.rects[1])
+ {
+ evas_smart_example_remove(d.smt, d.rects[1]);
+ evas_object_del(d.rects[1]);
+ }
+
+ memset(d.rects, 0, sizeof(d.rects));
+
+ fprintf(stdout, "Deleting all members of the smart object.\n");
+
+ return;
+ }
+
+ if (strcmp(ev->keyname, "l") == 0) /* insert random colored
+ * rectangle on the left */
+ {
+ Evas_Object *rect = evas_object_rectangle_add(d.evas), *prev;
+ evas_object_color_set(
+ rect, rand() % 255, rand() % 255, rand() % 255, 255);
+ evas_object_show(rect);
+
+ prev = evas_smart_example_set_left(d.smt, rect);
+ d.rects[0] = rect;
+
+ fprintf(stdout, "Setting smart object's left spot with a new"
+ " rectangle.\n");
+ fprintf(stdout, "Checking its new smart object parent: %s\n",
+ evas_object_smart_parent_get(rect) == d.smt ? "OK!" :
+ "Failure!");
+ if (prev)
+ {
+ int r, g, b;
+
+ evas_object_color_get(prev, &r, &g, &b, NULL);
+ fprintf(stdout, "Deleting previous left child,"
+ " which had colors (%d, %d, %d)\n", r, g, b);
+ evas_object_del(prev);
+ }
+
+ return;
+ }
+
+ if (strcmp(ev->keyname, "r") == 0) /* insert random colored
+ * rectangle on the right */
+ {
+ Evas_Object *rect = evas_object_rectangle_add(d.evas), *prev;
+ evas_object_color_set(
+ rect, rand() % 255, rand() % 255, rand() % 255, 255);
+ evas_object_show(rect);
+
+ prev = evas_smart_example_set_right(d.smt, rect);
+ d.rects[1] = rect;
+
+ fprintf(stdout, "Setting smart object's right spot with a new"
+ " rectangle.\n");
+ fprintf(stdout, "Checking its new smart object parent: %s\n",
+ evas_object_smart_parent_get(rect) == d.smt ? "OK!" :
+ "Failure!");
+ if (prev)
+ {
+ int r, g, b;
+
+ evas_object_color_get(prev, &r, &g, &b, NULL);
+ fprintf(stdout, "Deleting previous right child,"
+ " which had colors (%d, %d, %d)\n", r, g, b);
+ evas_object_del(prev);
+ }
+
+ return;
+ }
+
+ /* move smart object along the canvas */
+ if (strcmp(ev->keyname, "Right") == 0 || strcmp(ev->keyname, "Left") == 0 ||
+ strcmp(ev->keyname, "Up") == 0 || strcmp(ev->keyname, "Down") == 0)
+ {
+ Evas_Coord x, y;
+
+ evas_object_geometry_get(d.smt, &x, &y, NULL, NULL);
+
+ switch (ev->keyname[0])
+ {
+ case 'R':
+ x += 20;
+ break;
+
+ case 'L':
+ x -= 20;
+ break;
+
+ case 'U':
+ y -= 20;
+ break;
+
+ case 'D':
+ y += 20;
+ break;
+ }
+
+ evas_object_move(d.smt, x, y);
+
+ return;
+ }
+
+ /* increase smart object's size */
+ if (strcmp(ev->keyname, "i") == 0)
+ {
+ Evas_Coord w, h;
+
+ evas_object_geometry_get(d.smt, NULL, NULL, &w, &h);
+
+ w *= 1.1;
+ h *= 1.1;
+
+ evas_object_resize(d.smt, w, h);
+
+ return;
+ }
+
+ /* decrease smart object's size */
+ if (strcmp(ev->keyname, "d") == 0)
+ {
+ Evas_Coord w, h;
+
+ evas_object_geometry_get(d.smt, NULL, NULL, &w, &h);
+
+ w *= 0.9;
+ h *= 0.9;
+
+ evas_object_resize(d.smt, w, h);
+
+ return;
+ }
+
+ /* change smart object's clipper color */
+ if (strcmp(ev->keyname, "c") == 0)
+ {
+ cur_color = (cur_color + 1) % 4;
+
+ evas_object_color_set(
+ d.clipper, clipper_colors[cur_color].r, clipper_colors[cur_color].g,
+ clipper_colors[cur_color].b, clipper_colors[cur_color].a);
+
+ fprintf(stderr, "Changing clipper's color to %s\n",
+ _index_to_color(cur_color));
+
+ return;
+ }
+}
+
+static void
+/* callback on number of member objects changed */
+_on_example_smart_object_child_num_change(void *data __UNUSED__,
+ Evas_Object *obj __UNUSED__,
+ void *event_info)
+{
+ fprintf(stdout, "Number of child members on our example smart"
+ " object changed to %lu\n", (long)event_info);
+}
+
+int
+main(void)
+{
+ const Evas_Smart_Cb_Description **descriptions;
+ Evas_Smart_Example_Interface *iface;
+ unsigned int count;
+ Eina_Bool ret;
+
+ srand(time(NULL));
+
+ if (!ecore_evas_init())
+ return EXIT_FAILURE;
+
+ /* this will give you a window with an Evas canvas under the first
+ * engine available */
+ d.ee = ecore_evas_new(NULL, 10, 10, WIDTH, HEIGHT, NULL);
+ if (!d.ee)
+ goto error;
+
+ ecore_evas_callback_destroy_set(d.ee, _on_destroy);
+ ecore_evas_callback_resize_set(d.ee, _canvas_resize_cb);
+ ecore_evas_show(d.ee);
+
+ /* the canvas pointer, de facto */
+ d.evas = ecore_evas_get(d.ee);
+
+ d.bg = evas_object_rectangle_add(d.evas);
+ evas_object_color_set(d.bg, 255, 255, 255, 255);
+ evas_object_move(d.bg, 0, 0);
+ evas_object_resize(d.bg, WIDTH, HEIGHT);
+ evas_object_show(d.bg);
+
+ iface = (Evas_Smart_Example_Interface *)&iface1;
+ iface->base.name = IFACE1_NAME;
+ iface->base.private_size = sizeof(iface1_data);
+ iface->base.add = _iface1_add;
+ iface->base.del = _iface1_del;
+ iface->example_func = _iface1_custom_fn;
+
+ d.smt = evas_smart_example_add(d.evas);
+
+ evas_object_move(d.smt, WIDTH / 4, HEIGHT / 4);
+ evas_object_resize(d.smt, WIDTH / 2, HEIGHT / 2);
+ evas_object_show(d.smt);
+
+ ret = evas_object_smart_type_check(d.smt, _evas_smart_example_type);
+ fprintf(stdout, "Adding smart object of type \"%s\" to the canvas: %s.\n",
+ _evas_smart_example_type, ret ? "success" : "failure");
+
+ d.clipper = evas_object_smart_clipped_clipper_get(d.smt);
+ fprintf(stdout, "Checking if clipped smart object's clipper is a "
+ "\"static\" one: %s\n", evas_object_static_clip_get(
+ d.clipper) ? "yes" : "no");
+
+ evas_object_color_set(
+ d.clipper, clipper_colors[cur_color].r, clipper_colors[cur_color].g,
+ clipper_colors[cur_color].b, clipper_colors[cur_color].a);
+
+ evas_object_smart_callbacks_descriptions_get(
+ d.smt, &descriptions, &count, NULL, NULL);
+
+ for (; *descriptions; descriptions++)
+ {
+ fprintf(stdout, "We've found a smart callback on the smart object!"
+ "\n\tname: %s\n\ttype: %s\n", (*descriptions)->name,
+ (*descriptions)->type);
+
+ if (strcmp((*descriptions)->type, "i")) continue;
+ /* we know we don't have other types of smart callbacks
+ * here, just playing with it */
+
+ /* for now, we know the only one callback is the one
+ * reporting number of member objects changed on the
+ * example smart object */
+ evas_object_smart_callback_add(
+ d.smt, (*descriptions)->name,
+ _on_example_smart_object_child_num_change, NULL);
+ }
+
+ evas_object_focus_set(d.bg, EINA_TRUE);
+ evas_object_event_callback_add(
+ d.bg, EVAS_CALLBACK_KEY_DOWN, _on_keydown, NULL);
+
+ iface = (Evas_Smart_Example_Interface *)evas_object_smart_interface_get
+ (d.smt, IFACE1_NAME);
+ if (iface)
+ {
+ char *data;
+
+ fprintf(stdout, "We've found a smart interface on the smart object!"
+ "\n\tname: %s\n", iface->base.name);
+
+ fprintf(stdout, "Setting its interface data...\n");
+ data = evas_object_smart_interface_data_get
+ (d.smt, (Evas_Smart_Interface *)iface);
+ memcpy(data, iface1_data, sizeof(iface1_data));
+
+ fprintf(stdout, "Calling an interface's function...\n");
+ iface->example_func(d.smt);
+ }
+
+ fprintf(stdout, commands);
+ ecore_main_loop_begin();
+
+ ecore_evas_free(d.ee);
+ ecore_evas_shutdown();
+ return 0;
+
+error:
+ fprintf(stderr, "you got to have at least one evas engine built and linked"
+ " up to ecore-evas for this example to run properly.\n");
+ ecore_evas_shutdown();
+ return -1;
+}
diff --git a/src/examples/evas/evas-smart-object.c b/src/examples/evas/evas-smart-object.c
new file mode 100644
index 0000000000..8b65981390
--- /dev/null
+++ b/src/examples/evas/evas-smart-object.c
@@ -0,0 +1,756 @@
+/**
+ * Simple Evas example illustrating a custom Evas smart object
+ *
+ * You'll need at least one engine built for it (excluding the buffer
+ * one). See stdout/stderr for output.
+ *
+ * @verbatim
+ * gcc -o evas-smart-object evas-smart-object.c `pkg-config --libs --cflags evas ecore ecore-evas`
+ * @endverbatim
+ */
+
+#ifdef HAVE_CONFIG_H
+
+#include "config.h"
+#else
+
+#define PACKAGE_EXAMPLES_DIR "."
+#define __UNUSED__
+
+#endif
+
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <stdio.h>
+#include <errno.h>
+
+#define WIDTH (320)
+#define HEIGHT (240)
+
+static const char *commands = \
+ "commands are:\n"
+ "\tl - insert child rectangle on the left\n"
+ "\tr - insert child rectangle on the right\n"
+ "\tw - remove and delete all members from the smart object\n"
+ "\tright arrow - move smart object to the right\n"
+ "\tleft arrow - move smart object to the left\n"
+ "\tup arrow - move smart object up\n"
+ "\tdown arrow - move smart object down\n"
+ "\td - decrease smart object's size\n"
+ "\ti - increase smart object's size\n"
+ "\tc - change smart object's clipper color\n"
+ "\t. - rotate object to the right\n"
+ "\t, - rotate object to the left\n"
+ "\th - print help\n"
+ "\tq - quit\n"
+;
+
+#define WHITE {255, 255, 255, 255}
+#define RED {255, 0, 0, 255}
+#define GREEN {0, 255, 0, 255}
+#define BLUE {0, 0, 255, 255}
+
+struct test_data
+{
+ Ecore_Evas *ee;
+ Evas *evas;
+ Evas_Object *smt, *bg, *clipper, *rects[2];
+};
+
+struct color_tuple
+{
+ int r, g, b, a;
+} clipper_colors[4] = {WHITE, RED, GREEN, BLUE};
+int cur_color = 0;
+int cur_angle = 0;
+
+static const char *
+_index_to_color(int i)
+{
+ switch (i)
+ {
+ case 0:
+ return "WHITE (default)";
+
+ case 1:
+ return "RED";
+
+ case 2:
+ return "GREEN";
+
+ case 3:
+ return "BLUE";
+
+ default:
+ return "other";
+ }
+}
+
+static struct test_data d = {0};
+static const char *border_img_path = PACKAGE_EXAMPLES_DIR "/red.png";
+
+#define _evas_smart_example_type "Evas_Smart_Example"
+#define EVT_CHILDREN_NUMBER_CHANGED "children,changed"
+
+static const Evas_Smart_Cb_Description _smart_callbacks[] =
+{
+ {EVT_CHILDREN_NUMBER_CHANGED, "i"},
+ {NULL, NULL}
+};
+
+typedef struct _Evas_Smart_Example_Data Evas_Smart_Example_Data;
+/*
+ * This structure augments clipped smart object's instance data,
+ * providing extra members required by our example smart object's
+ * implementation.
+ */
+struct _Evas_Smart_Example_Data
+{
+ Evas_Object_Smart_Clipped_Data base;
+ Evas_Object *children[2], *border;
+ int child_count;
+};
+
+#define EVAS_SMART_EXAMPLE_DATA_GET(o, ptr) \
+ Evas_Smart_Example_Data * ptr = evas_object_smart_data_get(o)
+
+#define EVAS_SMART_EXAMPLE_DATA_GET_OR_RETURN(o, ptr) \
+ EVAS_SMART_EXAMPLE_DATA_GET(o, ptr); \
+ if (!ptr) \
+ { \
+ fprintf(stderr, "No widget data for object %p (%s)!", \
+ o, evas_object_type_get(o)); \
+ fflush(stderr); \
+ abort(); \
+ return; \
+ }
+
+#define EVAS_SMART_EXAMPLE_DATA_GET_OR_RETURN_VAL(o, ptr, val) \
+ EVAS_SMART_EXAMPLE_DATA_GET(o, ptr); \
+ if (!ptr) \
+ { \
+ fprintf(stderr, "No widget data for object %p (%s)!", \
+ o, evas_object_type_get(o)); \
+ fflush(stderr); \
+ abort(); \
+ return val; \
+ }
+
+EVAS_SMART_SUBCLASS_NEW(_evas_smart_example_type, _evas_smart_example,
+ Evas_Smart_Class, Evas_Smart_Class,
+ evas_object_smart_clipped_class_get, _smart_callbacks);
+
+static void
+_on_destroy(Ecore_Evas *ee __UNUSED__)
+{
+ ecore_main_loop_quit();
+}
+
+/* here just to keep our example's window size and background image's
+ * size in synchrony */
+static void
+_canvas_resize_cb(Ecore_Evas *ee)
+{
+ int w, h;
+
+ ecore_evas_geometry_get(ee, NULL, NULL, &w, &h);
+ evas_object_resize(d.bg, w, h);
+}
+
+static void
+_on_child_del(void *data,
+ Evas *evas __UNUSED__,
+ Evas_Object *o,
+ void *einfo __UNUSED__)
+{
+ Evas_Object *example_smart = data;
+ long idx;
+
+ EVAS_SMART_EXAMPLE_DATA_GET(example_smart, priv);
+
+ idx = (long)evas_object_data_get(o, "index");
+ idx--;
+
+ priv->children[idx] = NULL;
+
+ evas_object_smart_member_del(o);
+ evas_object_smart_changed(example_smart);
+}
+
+static void
+_evas_smart_example_child_callbacks_unregister(Evas_Object *obj)
+{
+ evas_object_data_set(obj, "index", NULL);
+ evas_object_event_callback_del(obj, EVAS_CALLBACK_FREE, _on_child_del);
+}
+
+static void
+_evas_smart_example_child_callbacks_register(Evas_Object *o,
+ Evas_Object *child,
+ long idx)
+{
+ evas_object_event_callback_add(child, EVAS_CALLBACK_FREE, _on_child_del, o);
+ evas_object_data_set(child, "index", (void *)(++idx));
+}
+
+/* create and setup a new example smart object's internals */
+static void
+_evas_smart_example_smart_add(Evas_Object *o)
+{
+ EVAS_SMART_DATA_ALLOC(o, Evas_Smart_Example_Data);
+
+ /* this is a border around the smart object's area, delimiting it */
+ priv->border = evas_object_image_filled_add(evas_object_evas_get(o));
+ evas_object_image_file_set(priv->border, border_img_path, NULL);
+ evas_object_image_border_set(priv->border, 3, 3, 3, 3);
+ evas_object_image_border_center_fill_set(
+ priv->border, EVAS_BORDER_FILL_NONE);
+ evas_object_smart_member_add(priv->border, o);
+
+ _evas_smart_example_parent_sc->add(o);
+}
+
+static void
+_evas_smart_example_smart_del(Evas_Object *o)
+{
+ EVAS_SMART_EXAMPLE_DATA_GET(o, priv);
+
+ if (priv->children[0])
+ {
+ _evas_smart_example_child_callbacks_unregister(priv->children[0]);
+ priv->children[0] = NULL;
+ }
+
+ if (priv->children[1])
+ {
+ _evas_smart_example_child_callbacks_unregister(priv->children[1]);
+ priv->children[1] = NULL;
+ }
+
+ _evas_smart_example_parent_sc->del(o);
+}
+
+static void
+_evas_smart_example_smart_show(Evas_Object *o)
+{
+ EVAS_SMART_EXAMPLE_DATA_GET(o, priv);
+
+ if (priv->children[0]) evas_object_show(priv->children[0]);
+ if (priv->children[1]) evas_object_show(priv->children[1]);
+ evas_object_show(priv->border);
+
+ _evas_smart_example_parent_sc->show(o);
+}
+
+static void
+_evas_smart_example_smart_hide(Evas_Object *o)
+{
+ EVAS_SMART_EXAMPLE_DATA_GET(o, priv);
+
+ if (priv->children[0]) evas_object_hide(priv->children[0]);
+ if (priv->children[1]) evas_object_hide(priv->children[1]);
+ evas_object_hide(priv->border);
+
+ _evas_smart_example_parent_sc->hide(o);
+}
+
+static void
+_evas_smart_example_smart_resize(Evas_Object *o,
+ Evas_Coord w,
+ Evas_Coord h)
+{
+ Evas_Coord ow, oh;
+ evas_object_geometry_get(o, NULL, NULL, &ow, &oh);
+ if ((ow == w) && (oh == h)) return;
+
+ /* this will trigger recalculation */
+ evas_object_smart_changed(o);
+}
+
+/* act on child objects' properties, before rendering */
+static void
+_evas_smart_example_smart_calculate(Evas_Object *o)
+{
+ Evas_Coord x, y, w, h;
+
+ EVAS_SMART_EXAMPLE_DATA_GET_OR_RETURN(o, priv);
+ evas_object_geometry_get(o, &x, &y, &w, &h);
+
+ evas_object_resize(priv->border, w, h);
+ evas_object_move(priv->border, x, y);
+
+ if (priv->children[0])
+ {
+ evas_object_move(priv->children[0], x + 3, y + 3);
+ evas_object_resize(priv->children[0], (w / 2) - 3, (h / 2) - 3);
+ }
+
+ if (priv->children[1])
+ {
+ evas_object_move(priv->children[1], x + (w / 2), y + (h / 2));
+ evas_object_resize(priv->children[1], (w / 2) - 3, (h / 2) - 3);
+ }
+}
+
+/* setting our smart interface */
+static void
+_evas_smart_example_smart_set_user(Evas_Smart_Class *sc)
+{
+ /* specializing these two */
+ sc->add = _evas_smart_example_smart_add;
+ sc->del = _evas_smart_example_smart_del;
+ sc->show = _evas_smart_example_smart_show;
+ sc->hide = _evas_smart_example_smart_hide;
+
+ /* clipped smart object has no hook on resizes or calculations */
+ sc->resize = _evas_smart_example_smart_resize;
+ sc->calculate = _evas_smart_example_smart_calculate;
+}
+
+/* BEGINS example smart object's own interface */
+
+/* add a new example smart object to a canvas */
+Evas_Object *
+evas_smart_example_add(Evas *evas)
+{
+ return evas_object_smart_add(evas, _evas_smart_example_smart_class_new());
+}
+
+static void
+_evas_smart_example_remove_do(Evas_Smart_Example_Data *priv,
+ Evas_Object *child,
+ int idx)
+{
+ priv->children[idx] = NULL;
+ priv->child_count--;
+ _evas_smart_example_child_callbacks_unregister(child);
+ evas_object_smart_member_del(child);
+}
+
+/* remove a child element, return its pointer (or NULL on errors) */
+Evas_Object *
+evas_smart_example_remove(Evas_Object *o,
+ Evas_Object *child)
+{
+ long idx;
+
+ EVAS_SMART_EXAMPLE_DATA_GET_OR_RETURN_VAL(o, priv, NULL);
+
+ if (priv->children[0] != child && priv->children[1] != child)
+ {
+ fprintf(stderr, "You are trying to remove something not belonging to"
+ " the example smart object!\n");
+ return NULL;
+ }
+
+ idx = (long)evas_object_data_get(child, "index");
+ idx--;
+
+ _evas_smart_example_remove_do(priv, child, idx);
+
+ evas_object_smart_callback_call(
+ o, EVT_CHILDREN_NUMBER_CHANGED, (void *)(long)priv->child_count);
+ evas_object_smart_changed(o);
+
+ return child;
+}
+
+/* set to return any previous object set to the left position of the
+ * smart object or NULL, if any (or on errors) */
+Evas_Object *
+evas_smart_example_set_left(Evas_Object *o,
+ Evas_Object *child)
+{
+ Evas_Object *ret = NULL;
+
+ EVAS_SMART_EXAMPLE_DATA_GET_OR_RETURN_VAL(o, priv, NULL);
+ if (!child)
+ return NULL;
+
+ if (priv->children[1] == child)
+ {
+ fprintf(stderr, "You mustn't place a child on both slots of"
+ " the example smart object!\n");
+ return NULL;
+ }
+
+ if (priv->children[0])
+ {
+ if (priv->children[0] != child)
+ {
+ ret = priv->children[0];
+ _evas_smart_example_remove_do(priv, priv->children[0], 0);
+ }
+ else return child;
+ }
+
+ priv->children[0] = child;
+ _evas_smart_example_child_callbacks_register(o, child, 0);
+ evas_object_smart_member_add(child, o);
+ evas_object_smart_changed(o);
+
+ priv->child_count++;
+ if (!ret)
+ {
+ evas_object_smart_callback_call(
+ o, EVT_CHILDREN_NUMBER_CHANGED, (void *)(long)priv->child_count);
+ }
+
+ return ret;
+}
+
+/* set to return any previous object set to the right position of the
+ * smart object or NULL, if any (or on errors) */
+Evas_Object *
+evas_smart_example_set_right(Evas_Object *o,
+ Evas_Object *child)
+{
+ Evas_Object *ret = NULL;
+
+ EVAS_SMART_EXAMPLE_DATA_GET_OR_RETURN_VAL(o, priv, NULL);
+ if (!child)
+ return NULL;
+
+ if (priv->children[0] == child)
+ {
+ fprintf(stderr, "You mustn't place a child on both slots of"
+ " the example smart object!\n");
+ return NULL;
+ }
+
+ if (priv->children[1])
+ {
+ if (priv->children[1] != child)
+ {
+ ret = priv->children[1];
+ _evas_smart_example_remove_do(priv, priv->children[1], 1);
+ }
+ else return child;
+ }
+
+ priv->children[1] = child;
+ _evas_smart_example_child_callbacks_register(o, child, 1);
+ evas_object_smart_member_add(child, o);
+ evas_object_smart_changed(o);
+
+ priv->child_count++;
+ if (!ret)
+ {
+ evas_object_smart_callback_call(
+ o, EVT_CHILDREN_NUMBER_CHANGED, (void *)(long)priv->child_count);
+ }
+
+ return ret;
+}
+
+/* END OF example smart object's own interface */
+
+static void
+_map_update(void)
+{
+ Evas_Map *m;
+ Evas_Coord x, y, w, h;
+
+ evas_object_geometry_get(d.smt, &x, &y, &w, &h);
+ m = evas_map_new(4);
+ evas_map_util_points_populate_from_object(m, d.smt);
+ evas_map_util_rotate(m, cur_angle, x + (w / 2), y + (h / 2));
+ evas_object_map_set(d.smt, m);
+ evas_object_map_enable_set(d.smt, EINA_TRUE);
+ evas_map_free(m);
+}
+
+static void
+_on_keydown(void *data __UNUSED__,
+ Evas *evas __UNUSED__,
+ Evas_Object *o __UNUSED__,
+ void *einfo)
+{
+ Evas_Event_Key_Down *ev = einfo;
+
+ if (strcmp(ev->keyname, "q") == 0) /* print help */
+ {
+ _on_destroy(NULL);
+ return;
+ }
+
+ if (strcmp(ev->keyname, "h") == 0) /* print help */
+ {
+ fprintf(stdout, commands);
+ return;
+ }
+
+ if (strcmp(ev->keyname, "w") == 0) /* clear out smart object (WRT
+ * members) */
+ {
+ if (d.rects[0])
+ {
+ evas_smart_example_remove(d.smt, d.rects[0]);
+ evas_object_del(d.rects[0]);
+ }
+ if (d.rects[1])
+ {
+ evas_smart_example_remove(d.smt, d.rects[1]);
+ evas_object_del(d.rects[1]);
+ }
+
+ memset(d.rects, 0, sizeof(d.rects));
+
+ fprintf(stdout, "Deleting all members of the smart object.\n");
+
+ return;
+ }
+
+ if (strcmp(ev->keyname, "l") == 0) /* insert random colored
+ * rectangle on the left */
+ {
+ Evas_Object *rect = evas_object_rectangle_add(d.evas), *prev;
+ evas_object_color_set(
+ rect, rand() % 255, rand() % 255, rand() % 255, 255);
+ evas_object_show(rect);
+
+ prev = evas_smart_example_set_left(d.smt, rect);
+ d.rects[0] = rect;
+
+ fprintf(stdout, "Setting smart object's left spot with a new"
+ " rectangle.\n");
+ fprintf(stdout, "Checking its new smart object parent: %s\n",
+ evas_object_smart_parent_get(rect) == d.smt ? "OK!" :
+ "Failure!");
+ if (prev)
+ {
+ int r, g, b;
+
+ evas_object_color_get(prev, &r, &g, &b, NULL);
+ fprintf(stdout, "Deleting previous left child,"
+ " which had colors (%d, %d, %d)\n", r, g, b);
+ evas_object_del(prev);
+ }
+
+ return;
+ }
+
+ if (strcmp(ev->keyname, "r") == 0) /* insert random colored
+ * rectangle on the right */
+ {
+ Evas_Object *rect = evas_object_rectangle_add(d.evas), *prev;
+ evas_object_color_set(
+ rect, rand() % 255, rand() % 255, rand() % 255, 255);
+ evas_object_show(rect);
+
+ prev = evas_smart_example_set_right(d.smt, rect);
+ d.rects[1] = rect;
+
+ fprintf(stdout, "Setting smart object's right spot with a new"
+ " rectangle.\n");
+ fprintf(stdout, "Checking its new smart object parent: %s\n",
+ evas_object_smart_parent_get(rect) == d.smt ? "OK!" :
+ "Failure!");
+ if (prev)
+ {
+ int r, g, b;
+
+ evas_object_color_get(prev, &r, &g, &b, NULL);
+ fprintf(stdout, "Deleting previous right child,"
+ " which had colors (%d, %d, %d)\n", r, g, b);
+ evas_object_del(prev);
+ }
+
+ return;
+ }
+
+ /* move smart object along the canvas */
+ if (strcmp(ev->keyname, "Right") == 0 || strcmp(ev->keyname, "Left") == 0 ||
+ strcmp(ev->keyname, "Up") == 0 || strcmp(ev->keyname, "Down") == 0)
+ {
+ Evas_Coord x, y;
+
+ evas_object_geometry_get(d.smt, &x, &y, NULL, NULL);
+
+ switch (ev->keyname[0])
+ {
+ case 'R':
+ x += 20;
+ break;
+
+ case 'L':
+ x -= 20;
+ break;
+
+ case 'U':
+ y -= 20;
+ break;
+
+ case 'D':
+ y += 20;
+ break;
+ }
+
+ evas_object_move(d.smt, x, y);
+ _map_update();
+
+ return;
+ }
+
+ /* increase smart object's size */
+ if (strcmp(ev->keyname, "i") == 0)
+ {
+ Evas_Coord w, h;
+
+ evas_object_geometry_get(d.smt, NULL, NULL, &w, &h);
+
+ w *= 1.1;
+ h *= 1.1;
+
+ evas_object_resize(d.smt, w, h);
+ _map_update();
+
+ return;
+ }
+
+ /* decrease smart object's size */
+ if (strcmp(ev->keyname, "d") == 0)
+ {
+ Evas_Coord w, h;
+
+ evas_object_geometry_get(d.smt, NULL, NULL, &w, &h);
+
+ w *= 0.9;
+ h *= 0.9;
+
+ evas_object_resize(d.smt, w, h);
+ _map_update();
+
+ return;
+ }
+
+ /* change smart object's clipper color */
+ if (strcmp(ev->keyname, "c") == 0)
+ {
+ cur_color = (cur_color + 1) % 4;
+
+ evas_object_color_set(
+ d.clipper, clipper_colors[cur_color].r, clipper_colors[cur_color].g,
+ clipper_colors[cur_color].b, clipper_colors[cur_color].a);
+
+ fprintf(stderr, "Changing clipper's color to %s\n",
+ _index_to_color(cur_color));
+
+ return;
+ }
+
+ /* rotate object to the right */
+ if (strcmp(ev->keyname, "period") == 0)
+ {
+ cur_angle = (cur_angle + 30) % 360;
+ _map_update();
+ return;
+ }
+
+ if (strcmp(ev->keyname, "comma") == 0)
+ {
+ cur_angle = (cur_angle - 30) % 360;
+ _map_update();
+ return;
+ }
+
+ fprintf(stderr, "Invalid key: '%s'\n", ev->keyname);
+}
+
+static void
+/* callback on number of member objects changed */
+_on_example_smart_object_child_num_change(void *data __UNUSED__,
+ Evas_Object *obj __UNUSED__,
+ void *event_info)
+{
+ fprintf(stdout, "Number of child members on our example smart"
+ " object changed to %lu\n", (long)event_info);
+}
+
+int
+main(void)
+{
+ const Evas_Smart_Cb_Description **descriptions;
+ unsigned int count;
+ Eina_Bool ret;
+
+ srand(time(NULL));
+
+ if (!ecore_evas_init())
+ return EXIT_FAILURE;
+
+ /* this will give you a window with an Evas canvas under the first
+ * engine available */
+ d.ee = ecore_evas_new(NULL, 10, 10, WIDTH, HEIGHT, NULL);
+ if (!d.ee)
+ goto error;
+
+ ecore_evas_callback_destroy_set(d.ee, _on_destroy);
+ ecore_evas_callback_resize_set(d.ee, _canvas_resize_cb);
+ ecore_evas_show(d.ee);
+
+ /* the canvas pointer, de facto */
+ d.evas = ecore_evas_get(d.ee);
+
+ d.bg = evas_object_rectangle_add(d.evas);
+ evas_object_color_set(d.bg, 255, 255, 255, 255);
+ evas_object_move(d.bg, 0, 0);
+ evas_object_resize(d.bg, WIDTH, HEIGHT);
+ evas_object_show(d.bg);
+
+ d.smt = evas_smart_example_add(d.evas);
+ evas_object_move(d.smt, WIDTH / 4, HEIGHT / 4);
+ evas_object_resize(d.smt, WIDTH / 2, HEIGHT / 2);
+ evas_object_show(d.smt);
+
+ ret = evas_object_smart_type_check(d.smt, _evas_smart_example_type);
+ fprintf(stdout, "Adding smart object of type \"%s\" to the canvas: %s.\n",
+ _evas_smart_example_type, ret ? "success" : "failure");
+
+ d.clipper = evas_object_smart_clipped_clipper_get(d.smt);
+ fprintf(stdout, "Checking if clipped smart object's clipper is a "
+ "\"static\" one: %s\n", evas_object_static_clip_get(
+ d.clipper) ? "yes" : "no");
+
+ evas_object_color_set(
+ d.clipper, clipper_colors[cur_color].r, clipper_colors[cur_color].g,
+ clipper_colors[cur_color].b, clipper_colors[cur_color].a);
+
+ evas_object_smart_callbacks_descriptions_get(
+ d.smt, &descriptions, &count, NULL, NULL);
+
+ for (; *descriptions; descriptions++)
+ {
+ fprintf(stdout, "We've found a smart callback on the smart object!"
+ "\n\tname: %s\n\ttype: %s\n", (*descriptions)->name,
+ (*descriptions)->type);
+
+ if (strcmp((*descriptions)->type, "i")) continue;
+ /* we know we don't have other types of smart callbacks
+ * here, just playing with it */
+
+ /* for now, we know the only one callback is the one
+ * reporting number of member objects changed on the
+ * example smart object */
+ evas_object_smart_callback_add(
+ d.smt, (*descriptions)->name,
+ _on_example_smart_object_child_num_change, NULL);
+ }
+
+ evas_object_focus_set(d.bg, EINA_TRUE);
+ evas_object_event_callback_add(
+ d.bg, EVAS_CALLBACK_KEY_DOWN, _on_keydown, NULL);
+
+ fprintf(stdout, commands);
+ ecore_main_loop_begin();
+
+ ecore_evas_free(d.ee);
+ ecore_evas_shutdown();
+ return 0;
+
+error:
+ fprintf(stderr, "you got to have at least one evas engine built and linked"
+ " up to ecore-evas for this example to run properly.\n");
+ ecore_evas_shutdown();
+ return -1;
+}
diff --git a/src/examples/evas/evas-stacking.c b/src/examples/evas/evas-stacking.c
new file mode 100644
index 0000000000..49fc81922f
--- /dev/null
+++ b/src/examples/evas/evas-stacking.c
@@ -0,0 +1,329 @@
+/**
+ * Simple Evas example illustrating <b>objects stacking</b> and
+ * <b>canvas layers</b>.
+ *
+ * You'll need at least one engine built for it (excluding the buffer
+ * one) and the png image loader also built. See stdout/stderr for
+ * output.
+ *
+ * @verbatim
+ * gcc -o evas-stacking evas-stacking.c `pkg-config --libs --cflags evas ecore ecore-evas edje`
+ * @endverbatim
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#else
+
+#define __UNUSED__
+
+#endif
+
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#define WIDTH 320
+#define HEIGHT 320
+
+struct test_data
+{
+ Ecore_Evas *ee;
+ Evas *canvas;
+ Evas_Object *bg;
+ Evas_Object *rects[3]; /* red, green, blue */
+ int layers[3]; /* default, below it, above it */
+ int cur_rect, cur_layer;
+};
+
+static struct test_data d = {0};
+
+static const char *commands = \
+ "commands are:\n"
+ "\tc - change the target rectangle to operate on\n"
+ "\ta - stack target rectangle one level above\n"
+ "\tb - stack target rectangle one level below\n"
+ "\tt - stack target rectangle up to the top of its layer\n"
+ "\tm - stack target rectangle down to the bottom of its layer\n"
+ "\tp - toggle target rectangle's 'pass events' property\n"
+ "\tr - toggle target rectangle's 'repeat events' property\n"
+ "\ts - print current stacking information\n"
+ "\tl - change background rectangle's layer\n"
+ "\th - print help\n";
+
+static void
+_on_mouse_down(void *data __UNUSED__,
+ Evas *evas __UNUSED__,
+ Evas_Object *o,
+ void *einfo __UNUSED__)
+{
+ fprintf(stdout, "Mouse down on rectangle %s!\n", evas_object_name_get(o));
+}
+
+/* here just to keep our example's window size and background image's
+ * size in synchrony */
+static void
+_canvas_resize_cb(Ecore_Evas *ee)
+{
+ int w, h;
+
+ ecore_evas_geometry_get(ee, NULL, NULL, &w, &h);
+ evas_object_resize(d.bg, w, h);
+}
+
+/* use the following commands to interact with this example - 'h' is
+ * the key for help */
+static void
+_on_keydown(void *data __UNUSED__,
+ Evas *evas __UNUSED__,
+ Evas_Object *o __UNUSED__,
+ void *einfo)
+{
+ Evas_Event_Key_Down *ev = einfo;
+ const char *name = evas_object_name_get(d.rects[d.cur_rect]);
+
+ if (strcmp(ev->keyname, "h") == 0) /* print help */
+ {
+ fprintf(stdout, commands);
+ return;
+ }
+
+ if (strcmp(ev->keyname, "s") == 0) /* get status of the
+ * rectangles WRT size
+ * hints */
+ {
+ Evas_Object *rect;
+
+ fprintf(stdout, "Order of stacking, from top to bottom, is: ");
+
+ rect = evas_object_top_get(evas);
+ fprintf(stdout, "%s", evas_object_name_get(rect));
+
+ rect = evas_object_below_get(rect);
+ while (rect)
+ {
+ fprintf(stdout, ", %s", evas_object_name_get(rect));
+ rect = evas_object_below_get(rect);
+ }
+
+ fprintf(stdout, ".\n");
+
+ fprintf(stdout, "Current target rectangle is %s\n",
+ evas_object_name_get(d.rects[d.cur_rect]));
+
+ fprintf(stdout, "Background rectangle's layer is %d\n",
+ evas_object_layer_get(d.bg));
+
+ return;
+ }
+
+ if (strcmp(ev->keyname, "l") == 0) /* change background rectangle's layer */
+ {
+ d.cur_layer = (d.cur_layer + 1) % 3;
+ evas_object_layer_set(d.bg, d.layers[d.cur_layer]);
+
+ fprintf(stdout, "Changing background rectangle's layer to %d\n",
+ d.layers[d.cur_layer]);
+ return;
+ }
+
+ if (strcmp(ev->keyname, "c") == 0) /* change rectangle to operate on */
+ {
+ d.cur_rect = (d.cur_rect + 1) % 3;
+
+ fprintf(stdout, "Changing target rectangle to the %s one\n",
+ evas_object_name_get(d.rects[d.cur_rect]));
+ return;
+ }
+
+ if (strcmp(ev->keyname, "t") == 0) /* bring target to top */
+ {
+ Evas_Object *neighbour;
+
+ evas_object_raise(d.rects[d.cur_rect]);
+
+ fprintf(stdout, "%s rectangle was re-stacked to the top if its layer\n",
+ name);
+
+ neighbour = evas_object_below_get(d.rects[d.cur_rect]);
+ fprintf(stdout, "Below of %s rect is %s\n", name,
+ neighbour ? evas_object_name_get(neighbour) : "no object");
+ return;
+ }
+
+ if (strcmp(ev->keyname, "m") == 0) /* bring target to bottom */
+ {
+ Evas_Object *neighbour;
+
+ evas_object_lower(d.rects[d.cur_rect]);
+
+ fprintf(stdout,
+ "%s rectangle was re-stacked to the bottom if its layer\n",
+ name);
+
+ neighbour = evas_object_below_get(d.rects[d.cur_rect]);
+ fprintf(stdout, "Below of %s rect is %s\n", name,
+ neighbour ? evas_object_name_get(neighbour) : "no object");
+ return;
+ }
+
+ if (strcmp(ev->keyname, "p") == 0) /* toggle pass events */
+ {
+ Eina_Bool pass = evas_object_pass_events_get(d.rects[d.cur_rect]);
+
+ evas_object_pass_events_set(d.rects[d.cur_rect], !pass);
+
+ fprintf(stdout, "%s rectangle is now set to%s pass (ignore) events\n",
+ name, pass ? " NOT" : "");
+
+ return;
+ }
+
+ if (strcmp(ev->keyname, "r") == 0) /* toggle repeat events */
+ {
+ Eina_Bool repeat = evas_object_repeat_events_get(d.rects[d.cur_rect]);
+
+ evas_object_repeat_events_set(d.rects[d.cur_rect], !repeat);
+
+ fprintf(stdout, "%s rectangle is now set to%s repeat events\n",
+ name, repeat ? " NOT" : "");
+
+ return;
+ }
+
+ if (strcmp(ev->keyname, "a") == 0) /* stack target above */
+ {
+ Evas_Object *neighbour = evas_object_above_get(d.rects[d.cur_rect]);
+
+ if (!neighbour || (evas_object_layer_get(d.rects[d.cur_rect]) !=
+ evas_object_layer_get(neighbour)))
+ return;
+
+ evas_object_stack_above(d.rects[d.cur_rect], neighbour);
+
+ fprintf(stdout, "%s rectangle was re-stacked one level above\n", name);
+
+ neighbour = evas_object_above_get(d.rects[d.cur_rect]);
+ fprintf(stdout, "Above of %s rect is %s\n", name,
+ neighbour ? evas_object_name_get(neighbour) : "no object");
+
+ neighbour = evas_object_below_get(d.rects[d.cur_rect]);
+ fprintf(stdout, "Below of %s rect is %s\n", name,
+ neighbour ? evas_object_name_get(neighbour) : "no object");
+ return;
+ }
+
+ if (strcmp(ev->keyname, "b") == 0) /* stack target below */
+ {
+ Evas_Object *neighbour = evas_object_below_get(d.rects[d.cur_rect]);
+
+ if (!neighbour || (evas_object_layer_get(d.rects[d.cur_rect]) !=
+ evas_object_layer_get(neighbour)))
+ return;
+
+ evas_object_stack_below(d.rects[d.cur_rect], neighbour);
+
+ fprintf(stdout, "%s rectangle was re-stacked one level below\n", name);
+
+ neighbour = evas_object_above_get(d.rects[d.cur_rect]);
+ fprintf(stdout, "Above of %s rect is %s\n", name,
+ neighbour ? evas_object_name_get(neighbour) : "no object");
+
+ neighbour = evas_object_below_get(d.rects[d.cur_rect]);
+
+ fprintf(stdout, "Below of %s rect is %s\n", name,
+ neighbour ? evas_object_name_get(neighbour) : "no object");
+ return;
+ }
+}
+
+static void
+_on_destroy(Ecore_Evas *ee __UNUSED__)
+{
+ ecore_main_loop_quit();
+}
+
+int
+main(void)
+{
+ if (!ecore_evas_init())
+ return EXIT_FAILURE;
+
+ /* this will give you a window with an Evas canvas under the first
+ * engine available */
+ d.ee = ecore_evas_new(NULL, 0, 0, WIDTH, HEIGHT, NULL);
+ if (!d.ee)
+ goto error;
+
+ ecore_evas_callback_destroy_set(d.ee, _on_destroy);
+ ecore_evas_callback_resize_set(d.ee, _canvas_resize_cb);
+ ecore_evas_show(d.ee);
+
+ /* the canvas pointer, de facto */
+ d.canvas = ecore_evas_get(d.ee);
+
+ d.bg = evas_object_rectangle_add(d.canvas);
+ evas_object_name_set(d.bg, "background"); /* white bg */
+ evas_object_color_set(d.bg, 255, 255, 255, 255);
+ evas_object_move(d.bg, 0, 0);
+ evas_object_resize(d.bg, WIDTH, HEIGHT);
+
+ d.layers[0] = evas_object_layer_get(d.bg);
+ d.layers[1] = d.layers[0] - 1;
+ d.layers[2] = d.layers[0] + 1;
+
+ d.cur_layer = 1;
+ evas_object_layer_set(d.bg, d.layers[d.cur_layer]); /* let's start with it
+ * below the default
+ * layer */
+
+ evas_object_show(d.bg);
+
+ evas_object_focus_set(d.bg, EINA_TRUE);
+ evas_object_event_callback_add(
+ d.bg, EVAS_CALLBACK_KEY_DOWN, _on_keydown, NULL);
+
+ d.rects[2] = evas_object_rectangle_add(d.canvas);
+ evas_object_name_set(d.rects[2], "blue");
+ evas_object_color_set(d.rects[2], 0, 0, 255, 255);
+
+ evas_object_resize(d.rects[2], WIDTH / 2.2, WIDTH / 2.2);
+ evas_object_move(d.rects[2], WIDTH / 6, WIDTH / 4.5);
+ evas_object_show(d.rects[2]);
+ evas_object_event_callback_add(
+ d.rects[2], EVAS_CALLBACK_MOUSE_DOWN, _on_mouse_down, NULL);
+
+ d.rects[1] = evas_object_rectangle_add(d.canvas);
+ evas_object_name_set(d.rects[1], "green");
+ evas_object_color_set(d.rects[1], 0, 255, 0, 255);
+
+ evas_object_resize(d.rects[1], WIDTH / 2.2, WIDTH / 2.2);
+ evas_object_move(d.rects[1], WIDTH / 2.5, WIDTH / 7);
+ evas_object_show(d.rects[1]);
+ evas_object_event_callback_add(
+ d.rects[1], EVAS_CALLBACK_MOUSE_DOWN, _on_mouse_down, NULL);
+
+ d.rects[0] = evas_object_rectangle_add(d.canvas);
+ evas_object_name_set(d.rects[0], "red");
+ evas_object_color_set(d.rects[0], 255, 0, 0, 255);
+
+ evas_object_resize(d.rects[0], WIDTH / 2.2, WIDTH / 2.2);
+ evas_object_move(d.rects[0], WIDTH / 3, WIDTH / 2.5);
+ evas_object_show(d.rects[0]);
+ evas_object_event_callback_add(
+ d.rects[0], EVAS_CALLBACK_MOUSE_DOWN, _on_mouse_down, NULL);
+
+ fprintf(stdout, commands);
+ ecore_main_loop_begin();
+
+ ecore_evas_shutdown();
+ return 0;
+
+error:
+ fprintf(stderr, "you got to have at least one evas engine built and linked"
+ " up to ecore-evas for this example to run properly.\n");
+ return -1;
+}
diff --git a/src/examples/evas/evas-table.c b/src/examples/evas/evas-table.c
new file mode 100644
index 0000000000..19fb68a5a4
--- /dev/null
+++ b/src/examples/evas/evas-table.c
@@ -0,0 +1,120 @@
+/**
+ * Simple Evas example illustrating usage of table object.
+ *
+ * You'll need at least one engine built for it (excluding the buffer
+ * one) and the png image loader also built.
+ *
+ * @verbatim
+ * gcc -o evas-table evas-table.c `pkg-config --libs --cflags ecore-evas`
+ * @endverbatim
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#else
+#define __UNUSED__
+#endif
+
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+
+#include <stdlib.h>
+
+#define WIDTH 100
+#define HEIGHT 150
+
+struct test_data
+{
+ Ecore_Evas *ee;
+ Evas *evas;
+ Evas_Object *bg;
+};
+
+static struct test_data d = {0};
+
+static void
+_on_destroy(Ecore_Evas *ee __UNUSED__)
+{
+ ecore_main_loop_quit();
+}
+
+/* here just to keep our example's window size and background image's
+ * size in synchrony */
+static void
+_canvas_resize_cb(Ecore_Evas *ee)
+{
+ int w, h;
+
+ ecore_evas_geometry_get(ee, NULL, NULL, &w, &h);
+ evas_object_resize(d.bg, w, h);
+}
+
+int
+main(void)
+{
+ Evas_Object *table, *rect;
+
+ if (!ecore_evas_init())
+ return EXIT_FAILURE;
+
+ /* this will give you a window with an Evas canvas under the first
+ * engine available */
+ d.ee = ecore_evas_new(NULL, 0, 0, WIDTH, HEIGHT, NULL);
+ if (!d.ee)
+ goto error;
+
+ ecore_evas_callback_destroy_set(d.ee, _on_destroy);
+ ecore_evas_callback_resize_set(d.ee, _canvas_resize_cb);
+ ecore_evas_show(d.ee);
+
+ /* the canvas pointer, de facto */
+ d.evas = ecore_evas_get(d.ee);
+
+ d.bg = evas_object_rectangle_add(d.evas);
+ evas_object_color_set(d.bg, 255, 255, 255, 255); /* white bg */
+ evas_object_move(d.bg, 0, 0); /* at canvas' origin */
+ evas_object_resize(d.bg, WIDTH, HEIGHT); /* covers full canvas */
+ evas_object_show(d.bg);
+
+ table = evas_object_table_add(d.evas);
+ evas_object_table_homogeneous_set(table, EVAS_OBJECT_TABLE_HOMOGENEOUS_NONE);
+ evas_object_table_padding_set(table, 0, 0);
+ evas_object_resize(table, WIDTH, HEIGHT);
+ evas_object_show(table);
+
+ rect = evas_object_rectangle_add(d.evas);
+ evas_object_color_set(rect, 255, 0, 0, 255);
+ evas_object_size_hint_min_set(rect, 100, 50);
+ evas_object_show(rect);
+ evas_object_table_pack(table, rect, 1, 1, 2, 1);
+
+ rect = evas_object_rectangle_add(d.evas);
+ evas_object_color_set(rect, 0, 255, 0, 255);
+ evas_object_size_hint_min_set(rect, 50, 100);
+ evas_object_show(rect);
+ evas_object_table_pack(table, rect, 1, 2, 1, 2);
+
+ rect = evas_object_rectangle_add(d.evas);
+ evas_object_color_set(rect, 0, 0, 255, 255);
+ evas_object_size_hint_min_set(rect, 50, 50);
+ evas_object_show(rect);
+ evas_object_table_pack(table, rect, 2, 2, 1, 1);
+
+ rect = evas_object_rectangle_add(d.evas);
+ evas_object_color_set(rect, 255, 255, 0, 255);
+ evas_object_size_hint_min_set(rect, 50, 50);
+ evas_object_show(rect);
+ evas_object_table_pack(table, rect, 2, 3, 1, 1);
+
+ ecore_main_loop_begin();
+
+ ecore_evas_free(d.ee);
+ ecore_evas_shutdown();
+ return 0;
+
+error:
+ fprintf(stderr, "you got to have at least one evas engine built and linked"
+ " up to ecore-evas for this example to run properly.\n");
+ ecore_evas_shutdown();
+ return -1;
+}
diff --git a/src/examples/evas/evas-text.c b/src/examples/evas/evas-text.c
new file mode 100644
index 0000000000..ba556629cc
--- /dev/null
+++ b/src/examples/evas/evas-text.c
@@ -0,0 +1,411 @@
+/**
+ * Simple Evas example illustrating text objects
+ *
+ * You'll need at least one engine built for it (excluding the buffer
+ * one). See stdout/stderr for output.
+ *
+ * @verbatim
+ * gcc -o evas-text evas-text.c `pkg-config --libs --cflags evas ecore ecore-evas`
+ * @endverbatim
+ */
+
+#ifdef HAVE_CONFIG_H
+
+#include "config.h"
+#else
+
+#define PACKAGE_EXAMPLES_DIR "."
+#define __UNUSED__
+
+#endif
+
+#include <Ecore.h>
+#include <Ecore_Evas.h>
+#include <stdio.h>
+#include <errno.h>
+
+#define WIDTH (320)
+#define HEIGHT (240)
+
+#define GREY {190, 190, 190, 255}
+#define BLACK {0, 0, 0, 255}
+#define WHITE {255, 255, 255, 255}
+#define RED {255, 0, 0, 255}
+#define GREEN {0, 255, 0, 255}
+#define BLUE {0, 0, 255, 255}
+
+#define POINTER_CYCLE(_ptr, _array) \
+ do \
+ { \
+ if ((unsigned)(((void *)(_ptr)) - ((void *)(_array))) >= \
+ sizeof(_array)) \
+ _ptr = _array; \
+ } \
+ while(0)
+
+static const char *commands = \
+ "commands are:\n"
+ "\tt - change text's current style\n"
+ "\tz - change text's font size\n"
+ "\tf - change text's font family\n"
+ "\tb - change text's base color\n"
+ "\ts - change text's \'shadow\' color\n"
+ "\to - change text's \'outline\' color\n"
+ "\tw - change text's \'glow\' color\n"
+ "\tg - change text's \'glow 2\' color\n"
+ "\th - print help\n";
+
+static const char *border_img_path = PACKAGE_EXAMPLES_DIR "/red.png";
+
+struct color_tuple
+{
+ int r, g, b, a;
+};
+
+struct text_preset_data
+{
+ const char **font_ptr;
+ const char *font[3];
+
+ struct color_tuple *text_ptr;
+ struct color_tuple text[6];
+
+ struct color_tuple *shadow_ptr;
+ struct color_tuple shadow[4];
+
+ struct color_tuple *outline_ptr;
+ struct color_tuple outline[4];
+
+ struct color_tuple *glow_ptr;
+ struct color_tuple glow[4];
+
+ struct color_tuple *glow2_ptr;
+ struct color_tuple glow2[4];
+};
+
+struct test_data
+{
+ Ecore_Evas *ee;
+ Evas *evas;
+ struct text_preset_data t_data;
+ Evas_Object *text, *bg, *border;
+};
+
+static struct test_data d = {0};
+
+static void
+_on_destroy(Ecore_Evas *ee __UNUSED__)
+{
+ ecore_main_loop_quit();
+}
+
+/* here just to keep our example's window size and background image's
+ * size in synchrony */
+static void
+_canvas_resize_cb(Ecore_Evas *ee)
+{
+ int w, h;
+
+ ecore_evas_geometry_get(ee, NULL, NULL, &w, &h);
+ evas_object_resize(d.bg, w, h);
+}
+
+static const char *
+_text_style_type_to_str(Evas_Text_Style_Type mode)
+{
+ switch (mode)
+ {
+ case EVAS_TEXT_STYLE_PLAIN:
+ return "plain";
+
+ case EVAS_TEXT_STYLE_SHADOW:
+ return "shadow";
+
+ case EVAS_TEXT_STYLE_OUTLINE:
+ return "outline";
+
+ case EVAS_TEXT_STYLE_SOFT_OUTLINE:
+ return "soft outline";
+
+ case EVAS_TEXT_STYLE_GLOW:
+ return "glow";
+
+ case EVAS_TEXT_STYLE_OUTLINE_SHADOW:
+ return "outline shadow";
+
+ case EVAS_TEXT_STYLE_FAR_SHADOW:
+ return "far shadow";
+
+ case EVAS_TEXT_STYLE_OUTLINE_SOFT_SHADOW:
+ return "outline soft shadow";
+
+ case EVAS_TEXT_STYLE_SOFT_SHADOW:
+ return "soft shadow";
+
+ case EVAS_TEXT_STYLE_FAR_SOFT_SHADOW:
+ return "far soft shadow";
+
+ default:
+ return "invalid";
+ }
+}
+
+static void
+_on_keydown(void *data __UNUSED__,
+ Evas *evas __UNUSED__,
+ Evas_Object *o __UNUSED__,
+ void *einfo)
+{
+ Evas_Event_Key_Down *ev = einfo;
+
+ if (strcmp(ev->keyname, "h") == 0) /* print help */
+ {
+ fprintf(stdout, commands);
+ return;
+ }
+
+ if (strcmp(ev->keyname, "t") == 0) /* change text's current style */
+ {
+ Evas_Text_Style_Type type = evas_object_text_style_get(d.text);
+
+ type = (type + 1) % 10;
+
+ evas_object_text_style_set(d.text, type);
+
+ fprintf(stdout, "Changing text's style to \'%s\'\n",
+ _text_style_type_to_str(type));
+
+ return;
+ }
+
+ if (strcmp(ev->keyname, "f") == 0) /* change text's font */
+ {
+ int sz;
+
+ (d.t_data.font_ptr)++;
+
+ evas_object_text_font_get(d.text, NULL, &sz);
+
+ POINTER_CYCLE(d.t_data.font_ptr, d.t_data.font);
+
+ evas_object_text_font_set(d.text, *d.t_data.font_ptr, sz);
+
+ fprintf(stdout, "Changing text's font to %s\n", *d.t_data.font_ptr);
+
+ return;
+ }
+
+ if (strcmp(ev->keyname, "b") == 0) /* change text's base color */
+ {
+ (d.t_data.text_ptr)++;
+
+ POINTER_CYCLE(d.t_data.text_ptr, d.t_data.text);
+
+ evas_object_color_set(
+ d.text, d.t_data.text_ptr->r, d.t_data.text_ptr->g,
+ d.t_data.text_ptr->b, d.t_data.text_ptr->a);
+
+ fprintf(stdout, "Changing base color for text to (%d, %d, %d, %d)\n",
+ d.t_data.text_ptr->r, d.t_data.text_ptr->g,
+ d.t_data.text_ptr->b, d.t_data.text_ptr->a);
+
+ return;
+ }
+
+ if (strcmp(ev->keyname, "g") == 0) /* change text's glow 2 color */
+ {
+ (d.t_data.glow2_ptr)++;
+
+ POINTER_CYCLE(d.t_data.glow2_ptr, d.t_data.glow2);
+
+ evas_object_text_glow2_color_set(
+ d.text, d.t_data.glow2_ptr->r, d.t_data.glow2_ptr->g,
+ d.t_data.glow2_ptr->b, d.t_data.glow2_ptr->a);
+
+ fprintf(stdout, "Changing glow 2 color for text to (%d, %d, %d, %d)\n",
+ d.t_data.glow2_ptr->r, d.t_data.glow2_ptr->g,
+ d.t_data.glow2_ptr->b, d.t_data.glow2_ptr->a);
+
+ return;
+ }
+
+ if (strcmp(ev->keyname, "w") == 0) /* change text's glow color */
+ {
+ (d.t_data.glow_ptr)++;
+
+ POINTER_CYCLE(d.t_data.glow_ptr, d.t_data.glow);
+
+ evas_object_text_glow_color_set(
+ d.text, d.t_data.glow_ptr->r, d.t_data.glow_ptr->g,
+ d.t_data.glow_ptr->b, d.t_data.glow_ptr->a);
+
+ fprintf(stdout, "Changing glow color for text to (%d, %d, %d, %d)\n",
+ d.t_data.glow_ptr->r, d.t_data.glow_ptr->g,
+ d.t_data.glow_ptr->b, d.t_data.glow_ptr->a);
+
+ return;
+ }
+
+ if (strcmp(ev->keyname, "o") == 0) /* change text's outline color */
+ {
+ (d.t_data.outline_ptr)++;
+
+ POINTER_CYCLE(d.t_data.outline_ptr, d.t_data.outline);
+
+ evas_object_text_outline_color_set(
+ d.text, d.t_data.outline_ptr->r, d.t_data.outline_ptr->g,
+ d.t_data.outline_ptr->b, d.t_data.outline_ptr->a);
+
+ fprintf(stdout, "Changing outline color for text to (%d, %d, %d, %d)\n",
+ d.t_data.outline_ptr->r, d.t_data.outline_ptr->g,
+ d.t_data.outline_ptr->b, d.t_data.outline_ptr->a);
+
+ return;
+ }
+
+ if (strcmp(ev->keyname, "s") == 0) /* change text's shadow color */
+ {
+ (d.t_data.shadow_ptr)++;
+
+ POINTER_CYCLE(d.t_data.shadow_ptr, d.t_data.shadow);
+
+ evas_object_text_shadow_color_set(
+ d.text, d.t_data.shadow_ptr->r, d.t_data.shadow_ptr->g,
+ d.t_data.shadow_ptr->b, d.t_data.shadow_ptr->a);
+
+ fprintf(stdout, "Changing shadow color for text to (%d, %d, %d, %d)\n",
+ d.t_data.shadow_ptr->r, d.t_data.shadow_ptr->g,
+ d.t_data.shadow_ptr->b, d.t_data.shadow_ptr->a);
+
+ return;
+ }
+
+ if (strcmp(ev->keyname, "z") == 0) /* change text's font size */
+ {
+ const char *font;
+ int size;
+
+ evas_object_text_font_get(d.text, &font, &size);
+
+ size = (size + 10) % 50;
+ if (!size) size = 10;
+
+ evas_object_text_font_set(d.text, font, size);
+
+ fprintf(stdout, "Changing text's font size to %d\n", size);
+
+ return;
+ }
+}
+
+int
+main(void)
+{
+ int size;
+ const char *font;
+
+ if (!ecore_evas_init())
+ return EXIT_FAILURE;
+
+ /* init values one is going to cycle through while running this
+ * example */
+ struct text_preset_data init_data =
+ {
+ .font = {"DejaVu", "Courier", "Utopia"},
+ .text = {BLACK, WHITE, GREY, RED, GREEN, BLUE},
+ .shadow = {WHITE, BLUE, GREEN, RED},
+ .outline = {WHITE, RED, GREEN, BLUE},
+ .glow = {WHITE, BLUE, GREEN, RED},
+ .glow2 = {WHITE, RED, BLUE, GREEN}
+ };
+
+ d.t_data = init_data;
+ d.t_data.font_ptr = d.t_data.font;
+ d.t_data.text_ptr = d.t_data.text;
+ d.t_data.glow_ptr = d.t_data.glow;
+ d.t_data.glow2_ptr = d.t_data.glow2;
+ d.t_data.outline_ptr = d.t_data.outline;
+ d.t_data.shadow_ptr = d.t_data.shadow;
+
+ /* this will give you a window with an Evas canvas under the first
+ * engine available */
+ d.ee = ecore_evas_new(NULL, 10, 10, WIDTH, HEIGHT, NULL);
+ if (!d.ee)
+ goto error;
+
+ ecore_evas_callback_destroy_set(d.ee, _on_destroy);
+ ecore_evas_callback_resize_set(d.ee, _canvas_resize_cb);
+ ecore_evas_show(d.ee);
+
+ /* the canvas pointer, de facto */
+ d.evas = ecore_evas_get(d.ee);
+
+ d.bg = evas_object_rectangle_add(d.evas);
+ evas_object_color_set(d.bg, 255, 255, 255, 255); /* white bg */
+ evas_object_move(d.bg, 0, 0); /* at canvas' origin */
+ evas_object_resize(d.bg, WIDTH, HEIGHT); /* covers full canvas */
+ evas_object_show(d.bg);
+
+ evas_object_focus_set(d.bg, EINA_TRUE);
+ evas_object_event_callback_add(
+ d.bg, EVAS_CALLBACK_KEY_DOWN, _on_keydown, NULL);
+
+ d.text = evas_object_text_add(d.evas);
+ evas_object_text_style_set(d.text, EVAS_TEXT_STYLE_PLAIN);
+
+ /* let the pre-set thingies be enforced */
+ evas_object_color_set(
+ d.text, d.t_data.text_ptr->r, d.t_data.text_ptr->g,
+ d.t_data.text_ptr->b, d.t_data.text_ptr->a);
+
+ evas_object_text_glow_color_set(
+ d.text, d.t_data.glow_ptr->r, d.t_data.glow_ptr->g,
+ d.t_data.glow_ptr->b, d.t_data.glow_ptr->a);
+
+ evas_object_text_glow2_color_set(
+ d.text, d.t_data.glow2_ptr->r, d.t_data.glow2_ptr->g,
+ d.t_data.glow2_ptr->b, d.t_data.glow2_ptr->a);
+
+ evas_object_text_outline_color_set(
+ d.text, d.t_data.outline_ptr->r, d.t_data.outline_ptr->g,
+ d.t_data.outline_ptr->b, d.t_data.outline_ptr->a);
+
+ evas_object_text_shadow_color_set(
+ d.text, d.t_data.shadow_ptr->r, d.t_data.shadow_ptr->g,
+ d.t_data.shadow_ptr->b, d.t_data.shadow_ptr->a);
+
+ evas_object_text_font_set(d.text, *d.t_data.font_ptr, 30);
+ evas_object_text_text_set(d.text, "sample text");
+
+ evas_object_resize(d.text, (3 * WIDTH) / 4, HEIGHT / 4);
+ evas_object_move(d.text, WIDTH / 8, (3 * HEIGHT) / 8);
+ evas_object_show(d.text);
+
+ evas_object_text_font_get(d.text, &font, &size);
+ fprintf(stdout, "Adding text object with font %s, size %d\n", font, size);
+
+ /* this is a border around the text object above, here just to
+ * emphasize its geometry */
+ d.border = evas_object_image_filled_add(d.evas);
+ evas_object_image_file_set(d.border, border_img_path, NULL);
+ evas_object_image_border_set(d.border, 3, 3, 3, 3);
+ evas_object_image_border_center_fill_set(d.border, EVAS_BORDER_FILL_NONE);
+
+ evas_object_resize(d.border, ((3 * WIDTH) / 4) + 3, (HEIGHT / 4) + 3);
+ evas_object_move(d.border, (WIDTH / 8) - 3, ((3 * HEIGHT) / 8) - 3);
+ evas_object_show(d.border);
+
+ fprintf(stdout, commands);
+ ecore_main_loop_begin();
+
+ ecore_evas_free(d.ee);
+ ecore_evas_shutdown();
+ return 0;
+
+error:
+ fprintf(stderr, "you got to have at least one evas engine built and linked"
+ " up to ecore-evas for this example to run properly.\n");
+ ecore_evas_shutdown();
+ return -1;
+}
+
diff --git a/src/examples/evas/im1.png b/src/examples/evas/im1.png
new file mode 100644
index 0000000000..aa3786928e
--- /dev/null
+++ b/src/examples/evas/im1.png
Binary files differ
diff --git a/legacy/ecore/src/examples/red.png b/src/examples/evas/red.png
index dd03528d70..dd03528d70 100644
--- a/legacy/ecore/src/examples/red.png
+++ b/src/examples/evas/red.png
Binary files differ
diff --git a/src/tests/Makefile.am b/src/tests/Makefile.am
index 8efa21a430..8d926619f4 100644
--- a/src/tests/Makefile.am
+++ b/src/tests/Makefile.am
@@ -1,3 +1,3 @@
MAINTAINERCLEANFILES = Makefile.in
-SUBDIRS = eina eo eet
+SUBDIRS = eina eo eet evas
diff --git a/src/tests/evas/Makefile.am b/src/tests/evas/Makefile.am
new file mode 100644
index 0000000000..229eba1dd2
--- /dev/null
+++ b/src/tests/evas/Makefile.am
@@ -0,0 +1,27 @@
+MAINTAINERCLEANFILES = Makefile.in
+
+AM_CPPFLAGS = \
+-I$(top_srcdir)/src/lib/eina \
+-I$(top_srcdir)/src/lib/eo \
+-I$(top_srcdir)/src/lib/evas \
+-I$(top_builddir)/src/lib/eina \
+-I$(top_builddir)/src/lib/eo \
+-I$(top_builddir)/src/lib/evas \
+@CHECK_CFLAGS@ \
+@EET_CFLAGS@
+
+if EFL_ENABLE_TESTS
+
+check_PROGRAMS = evas_suite
+
+evas_suite_SOURCES = \
+evas_suite.c \
+evas_test_init.c \
+evas_test_textblock.c \
+evas_test_text.c \
+evas_test_callbacks.c \
+evas_tests_helpers.h \
+evas_suite.h
+evas_suite_LDADD = @CHECK_LIBS@ $(top_builddir)/src/lib/evas/libevas.la $(top_builddir)/src/lib/eina/libeina.la
+
+endif
diff --git a/legacy/edje/src/tests/edje_suite.c b/src/tests/evas/evas_suite.c
index ad789b65df..0d3300c560 100644
--- a/legacy/edje/src/tests/edje_suite.c
+++ b/src/tests/evas/evas_suite.c
@@ -5,27 +5,30 @@
#include <stdlib.h>
#include <stdio.h>
-#include <Edje.h>
+#include <Evas.h>
-#include "edje_suite.h"
+#include "evas_suite.h"
-typedef struct _Edje_Test_Case Edje_Test_Case;
+typedef struct _Evas_Test_Case Evas_Test_Case;
-struct _Edje_Test_Case
+struct _Evas_Test_Case
{
const char *test_case;
void (*build)(TCase *tc);
};
-static const Edje_Test_Case etc[] = {
- { "Edje", edje_test_edje },
+static const Evas_Test_Case etc[] = {
+ { "Evas", evas_test_init },
+ { "Object Textblock", evas_test_textblock },
+ { "Object Text", evas_test_text },
+ { "Callbacks", evas_test_callbacks },
{ NULL, NULL }
};
static void
_list_tests(void)
{
- const Edje_Test_Case *itr;
+ const Evas_Test_Case *itr;
itr = etc;
fputs("Available Test Cases:\n", stderr);
@@ -45,13 +48,13 @@ _use_test(int argc, const char **argv, const char *test_case)
}
static Suite *
-edje_suite_build(int argc, const char **argv)
+evas_suite_build(int argc, const char **argv)
{
TCase *tc;
Suite *s;
int i;
- s = suite_create("Edje");
+ s = suite_create("Evas");
for (i = 0; etc[i].test_case; ++i)
{
@@ -90,12 +93,14 @@ main(int argc, char **argv)
return 0;
}
- s = edje_suite_build(argc - 1, (const char **)argv + 1);
+ evas_init();
+ s = evas_suite_build(argc - 1, (const char **)argv + 1);
sr = srunner_create(s);
srunner_run_all(sr, CK_ENV);
failed_count = srunner_ntests_failed(sr);
srunner_free(sr);
+ evas_shutdown();
return (failed_count == 0) ? 0 : 255;
}
diff --git a/src/tests/evas/evas_suite.h b/src/tests/evas/evas_suite.h
new file mode 100644
index 0000000000..31d6d18ac1
--- /dev/null
+++ b/src/tests/evas/evas_suite.h
@@ -0,0 +1,12 @@
+#ifndef _EVAS_SUITE_H
+#define _EVAS_SUITE_H
+
+#include <check.h>
+
+void evas_test_init(TCase *tc);
+void evas_test_textblock(TCase *tc);
+void evas_test_text(TCase *tc);
+void evas_test_callbacks(TCase *tc);
+
+
+#endif /* _EVAS_SUITE_H */
diff --git a/src/tests/evas/evas_test_callbacks.c b/src/tests/evas/evas_test_callbacks.c
new file mode 100644
index 0000000000..164851e94a
--- /dev/null
+++ b/src/tests/evas/evas_test_callbacks.c
@@ -0,0 +1,135 @@
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+
+#include "evas_suite.h"
+#include "Evas.h"
+#include "evas_tests_helpers.h"
+
+#define START_CALLBACK_TEST() \
+ Evas *evas; \
+ Evas_Object *rect; \
+ evas = EVAS_TEST_INIT_EVAS(); \
+ rect = evas_object_rectangle_add(evas); \
+do \
+{ \
+} \
+while (0)
+
+#define END_CALLBACK_TEST() \
+do \
+{ \
+ evas_object_del(rect); \
+ evas_free(evas); \
+ evas_shutdown(); \
+} \
+while (0)
+
+static uintptr_t counter = 1;
+
+static void
+_obj_event_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
+{
+ (void) e;
+ (void) obj;
+ (void) event_info;
+
+ fail_if(((uintptr_t) data) != counter);
+
+ counter++;
+}
+
+START_TEST(evas_object_event_callbacks_priority)
+{
+ START_CALLBACK_TEST();
+ counter = 1;
+ evas_object_event_callback_priority_add(rect, EVAS_CALLBACK_MOVE, -10,
+ _obj_event_cb, (void *) 1);
+ evas_object_event_callback_priority_add(rect, EVAS_CALLBACK_MOVE, 0,
+ _obj_event_cb, (void *) 2);
+ evas_object_event_callback_priority_add(rect, EVAS_CALLBACK_MOVE, 10,
+ _obj_event_cb, (void *) 3);
+ evas_object_move(rect, 2, 2);
+
+ /* Make sure we got through all the callbacks */
+ fail_if(counter != 4);
+
+ /* Delete _obj_event_cb 3 times */
+ evas_object_event_callback_del(rect, EVAS_CALLBACK_MOVE, _obj_event_cb);
+ evas_object_event_callback_del(rect, EVAS_CALLBACK_MOVE, _obj_event_cb);
+ evas_object_event_callback_del(rect, EVAS_CALLBACK_MOVE, _obj_event_cb);
+ counter = 1;
+ evas_object_event_callback_priority_add(rect, EVAS_CALLBACK_MOVE, 0,
+ _obj_event_cb, (void *) 2);
+ evas_object_event_callback_priority_add(rect, EVAS_CALLBACK_MOVE, -10,
+ _obj_event_cb, (void *) 1);
+ evas_object_event_callback_priority_add(rect, EVAS_CALLBACK_MOVE, 10,
+ _obj_event_cb, (void *) 3);
+ evas_object_move(rect, 3, 3);
+
+ /* Make sure we got through all the callbacks */
+ fail_if(counter != 4);
+
+ END_CALLBACK_TEST();
+}
+END_TEST
+
+static void
+_event_cb(void *data, Evas *e, void *event_info)
+{
+ (void) e;
+ (void) event_info;
+
+ fail_if(((uintptr_t) data) != counter);
+
+ counter++;
+}
+
+START_TEST(evas_event_callbacks_priority)
+{
+ START_CALLBACK_TEST();
+ evas_object_focus_set(rect, EINA_FALSE);
+ counter = 1;
+ evas_event_callback_priority_add(evas, EVAS_CALLBACK_CANVAS_OBJECT_FOCUS_IN,
+ -10, _event_cb, (void *) 1);
+ evas_event_callback_priority_add(evas, EVAS_CALLBACK_CANVAS_OBJECT_FOCUS_IN,
+ 0, _event_cb, (void *) 2);
+ evas_event_callback_priority_add(evas, EVAS_CALLBACK_CANVAS_OBJECT_FOCUS_IN,
+ 10, _event_cb, (void *) 3);
+ evas_object_focus_set(rect, EINA_TRUE);
+
+ /* Make sure we got through all the callbacks */
+ fail_if(counter != 4);
+
+ /* Delete _event_cb 3 times */
+ evas_event_callback_del(evas, EVAS_CALLBACK_CANVAS_OBJECT_FOCUS_IN,
+ _event_cb);
+ evas_event_callback_del(evas, EVAS_CALLBACK_CANVAS_OBJECT_FOCUS_IN,
+ _event_cb);
+ evas_event_callback_del(evas, EVAS_CALLBACK_CANVAS_OBJECT_FOCUS_IN,
+ _event_cb);
+ evas_object_focus_set(rect, EINA_FALSE);
+ counter = 1;
+ evas_event_callback_priority_add(evas, EVAS_CALLBACK_CANVAS_OBJECT_FOCUS_IN,
+ 0, _event_cb, (void *) 2);
+ evas_event_callback_priority_add(evas, EVAS_CALLBACK_CANVAS_OBJECT_FOCUS_IN,
+ -10, _event_cb, (void *) 1);
+ evas_event_callback_priority_add(evas, EVAS_CALLBACK_CANVAS_OBJECT_FOCUS_IN,
+ 10, _event_cb, (void *) 3);
+ evas_object_focus_set(rect, EINA_TRUE);
+
+ /* Make sure we got through all the callbacks */
+ fail_if(counter != 4);
+
+ END_CALLBACK_TEST();
+}
+END_TEST
+
+void evas_test_callbacks(TCase *tc)
+{
+ tcase_add_test(tc, evas_object_event_callbacks_priority);
+ tcase_add_test(tc, evas_event_callbacks_priority);
+}
diff --git a/src/tests/evas/evas_test_init.c b/src/tests/evas/evas_test_init.c
new file mode 100644
index 0000000000..7637d9cb2a
--- /dev/null
+++ b/src/tests/evas/evas_test_init.c
@@ -0,0 +1,19 @@
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+
+#include "evas_suite.h"
+#include "Evas.h"
+
+START_TEST(evas_simple)
+{
+}
+END_TEST
+
+void evas_test_init(TCase *tc)
+{
+ tcase_add_test(tc, evas_simple);
+}
diff --git a/src/tests/evas/evas_test_text.c b/src/tests/evas/evas_test_text.c
new file mode 100644
index 0000000000..99ab405e40
--- /dev/null
+++ b/src/tests/evas/evas_test_text.c
@@ -0,0 +1,493 @@
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+
+#include "evas_suite.h"
+#include "Evas.h"
+#include "evas_tests_helpers.h"
+
+#define START_TEXT_TEST() \
+ Evas *evas; \
+ Evas_Object *to; \
+ evas = EVAS_TEST_INIT_EVAS(); \
+ evas_font_hinting_set(evas, EVAS_FONT_HINTING_AUTO); \
+ to = evas_object_text_add(evas); \
+do \
+{ \
+} \
+while (0)
+
+#define END_TEXT_TEST() \
+do \
+{ \
+ evas_object_del(to); \
+ evas_free(evas); \
+ evas_shutdown(); \
+} \
+while (0)
+
+START_TEST(evas_text_simple)
+{
+ START_TEXT_TEST();
+ const char *buf = "Test - בדיקה";
+ evas_object_text_text_set(to, buf);
+ fail_if(strcmp(evas_object_text_text_get(to), buf));
+ END_TEXT_TEST();
+}
+END_TEST
+
+/* Various text related geometries */
+START_TEST(evas_text_geometries)
+{
+ START_TEXT_TEST();
+ const char *buf = "Tests";
+ const char *font = "Sans";
+ Evas_Font_Size size = 14;
+ Evas_Coord prev;
+ int i;
+ Evas_Coord x, y, w, h, px;
+
+ evas_object_text_text_set(to, buf);
+
+ /* All should be 0 without a font set */
+ fail_if(evas_object_text_ascent_get(to) != 0);
+ fail_if(evas_object_text_descent_get(to) != 0);
+ fail_if(evas_object_text_max_ascent_get(to) != 0);
+ fail_if(evas_object_text_max_descent_get(to) != 0);
+ fail_if(evas_object_text_horiz_advance_get(to) != 0);
+ fail_if(evas_object_text_vert_advance_get(to) != 0);
+
+ evas_object_text_font_set(to, font, size);
+
+ /* Check that they are bigger than 0. */
+ fail_if(evas_object_text_ascent_get(to) <= 0);
+ fail_if(evas_object_text_descent_get(to) <= 0);
+ fail_if(evas_object_text_max_ascent_get(to) <= 0);
+ fail_if(evas_object_text_max_descent_get(to) <= 0);
+ fail_if(evas_object_text_horiz_advance_get(to) <= 0);
+ fail_if(evas_object_text_vert_advance_get(to) <= 0);
+
+ /* Check that expanding the text does what we expect it */
+ evas_object_text_text_set(to, "Test");
+ prev = evas_object_text_ascent_get(to);
+ evas_object_text_text_set(to, "Testing");
+ fail_if(evas_object_text_ascent_get(to) != prev);
+
+ evas_object_text_text_set(to, "Test");
+ prev = evas_object_text_descent_get(to);
+ evas_object_text_text_set(to, "Testing");
+ fail_if(evas_object_text_descent_get(to) != prev);
+
+ evas_object_text_text_set(to, "Test");
+ prev = evas_object_text_max_ascent_get(to);
+ evas_object_text_text_set(to, "Testing");
+ fail_if(evas_object_text_max_ascent_get(to) != prev);
+
+ evas_object_text_text_set(to, "Test");
+ prev = evas_object_text_max_descent_get(to);
+ evas_object_text_text_set(to, "Testing");
+ fail_if(evas_object_text_max_descent_get(to) != prev);
+
+ evas_object_text_text_set(to, "Test");
+ prev = evas_object_text_horiz_advance_get(to);
+ evas_object_text_text_set(to, "Testing");
+ fail_if(evas_object_text_horiz_advance_get(to) <= prev);
+
+ evas_object_text_text_set(to, "Test");
+ prev = evas_object_text_vert_advance_get(to);
+ evas_object_text_text_set(to, "Testing");
+ fail_if(evas_object_text_vert_advance_get(to) != prev);
+
+ /* Go through all the characters, making sure the geometries we get
+ * are in a monotonically increasing order and that all sizes are
+ * bigger than 0. */
+ evas_object_text_text_set(to, "Testing...");
+ x = 0;
+ px = -100;
+ for (i = 0 ; i < eina_unicode_utf8_get_len("Testing...") ; i++)
+ {
+ fail_if(!evas_object_text_char_pos_get(to, i, &x, &y, &w, &h));
+ fail_if(x <= px);
+ px = x;
+ /* Get back the coords */
+ fail_if(i != evas_object_text_char_coords_get(to, x + (w / 2),
+ y + (h / 2), &x, &y, &w, &h));
+ }
+
+ /* Last up to pos */
+ Evas_Coord adv;
+ int pos, prev_pos;
+ evas_object_text_text_set(to, "Test - 유니코드");
+ adv = evas_object_text_horiz_advance_get(to);
+ pos = prev_pos = 0;
+ for (x = 0 ; x <= (adv - 1) ; x++)
+ {
+ pos = evas_object_text_last_up_to_pos(to, x, 0);
+ fail_if(pos < prev_pos);
+ prev_pos = pos;
+ }
+ pos = evas_object_text_last_up_to_pos(to, x, 0);
+ fail_if(pos != -1);
+ pos = evas_object_text_last_up_to_pos(to, -50, 0);
+ fail_if(pos != -1);
+
+ END_TEXT_TEST();
+}
+END_TEST
+
+/* Various evas stuff, such as scale */
+START_TEST(evas_text_evas)
+{
+ Evas_Coord w, h, bw, bh;
+ START_TEXT_TEST();
+ const char *buf = "Test - בדיקה";
+ const char *font = "Sans";
+ Evas_Font_Size size = 14;
+
+ evas_object_text_font_set(to, font, size);
+ evas_object_text_text_set(to, buf);
+ evas_object_geometry_get(to, NULL, NULL, &bw, &bh);
+ evas_object_scale_set(to, 3.0);
+ evas_object_geometry_get(to, NULL, NULL, &w, &h);
+ fail_if((w <= bw) || (h <= bh));
+
+ evas_object_scale_set(to, 0.5);
+ evas_object_geometry_get(to, NULL, NULL, &w, &h);
+ fail_if((w >= bw) || (h >= bh));
+
+ END_TEXT_TEST();
+}
+END_TEST
+
+/* Tests for functions that are in evas_object_text.c but
+ * don't really have anything to do with it. */
+START_TEST(evas_text_unrelated)
+{
+ START_TEXT_TEST();
+ const char *buf = "נסיון";
+ int pos;
+ int value;
+ /* Actually, they are tested in eina, just doing it for completeness. */
+ fail_if(evas_string_char_len_get(buf) != 5);
+
+ pos = 0;
+ fail_if(2 != evas_string_char_next_get(buf, pos, &value));
+ fail_if(value != L'נ');
+
+ pos = 2;
+ fail_if(0 != evas_string_char_prev_get(buf, pos, &value));
+ fail_if(value != L'ס');
+
+ END_TEXT_TEST();
+}
+END_TEST
+
+#define _CHECK_SET_GET(x) \
+do \
+{ \
+ Evas_Coord r, g, b, a; \
+ evas_object_text_##x##_set(to, 100, 150, 125, 12); \
+ evas_object_text_##x##_get(to, &r, &g, &b, &a); \
+ fail_if((r != 100) || (g != 150) || (b != 125) || (a != 12)); \
+ /* Set to the same value */ \
+ evas_object_text_##x##_set(to, 100, 150, 125, 12); \
+ evas_object_text_##x##_get(to, &r, &g, &b, &a); \
+ fail_if((r != 100) || (g != 150) || (b != 125) || (a != 12)); \
+} \
+while (0)
+
+START_TEST(evas_text_set_get)
+{
+ START_TEXT_TEST();
+ const char *buf = "Test - בדיקה";
+ /* Text */
+ evas_object_text_text_set(to, buf);
+ fail_if(strcmp(evas_object_text_text_get(to), buf));
+
+ /* Colors */
+ _CHECK_SET_GET(shadow_color);
+ _CHECK_SET_GET(glow_color);
+ _CHECK_SET_GET(glow2_color);
+ _CHECK_SET_GET(outline_color);
+
+ /* Font and size */
+ const char *font = "Sans";
+ Evas_Font_Size size = 14;
+ evas_object_text_font_set(to, font, size);
+ font = NULL;
+ size = 0;
+ evas_object_text_font_get(to, &font, &size);
+ fail_if(strcmp(font, "Sans"));
+ fail_if(size != 14);
+ evas_object_text_font_set(to, font, size);
+ font = NULL;
+ size = 0;
+ evas_object_text_font_get(to, &font, &size);
+ fail_if(strcmp(font, "Sans"));
+ fail_if(size != 14);
+
+ font = "NON-EXISTING-FONT";
+ size = 14;
+ evas_object_text_font_set(to, font, size);
+ font = NULL;
+ size = 0;
+ evas_object_text_font_get(to, &font, &size);
+ fail_if(strcmp(font, "NON-EXISTING-FONT"));
+
+ font = "Serif";
+ size = 2;
+ evas_object_text_font_set(to, font, size);
+ font = NULL;
+ size = 0;
+ evas_object_text_font_get(to, &font, &size);
+ fail_if(strcmp(font, "Serif"));
+ fail_if(size != 2);
+
+ evas_object_text_font_source_set(to, "/usr/share/fonts/Sans.ttf");
+ font = evas_object_text_font_source_get(to);
+ fail_if(strcmp(font, "/usr/share/fonts/Sans.ttf"));
+ evas_object_text_font_source_set(to, "/usr/share/fonts/Sans.ttf");
+ font = evas_object_text_font_source_get(to);
+ fail_if(strcmp(font, "/usr/share/fonts/Sans.ttf"));
+
+ /* BiDi Delimiters */
+ evas_object_text_bidi_delimiters_set(to, ",.|");
+ fail_if(strcmp(evas_object_text_bidi_delimiters_get(to), ",.|"));
+ evas_object_text_bidi_delimiters_set(to, ",|");
+ fail_if(strcmp(evas_object_text_bidi_delimiters_get(to), ",|"));
+ evas_object_text_bidi_delimiters_set(to, NULL);
+ fail_if(evas_object_text_bidi_delimiters_get(to));
+ evas_object_text_bidi_delimiters_set(to, ",|");
+ fail_if(strcmp(evas_object_text_bidi_delimiters_get(to), ",|"));
+
+ /* Style */
+ evas_object_text_text_set(to, "");
+ evas_object_text_style_set(to, EVAS_TEXT_STYLE_SHADOW);
+ fail_if(evas_object_text_style_get(to) != EVAS_TEXT_STYLE_SHADOW);
+ evas_object_text_style_set(to, EVAS_TEXT_STYLE_OUTLINE);
+ fail_if(evas_object_text_style_get(to) != EVAS_TEXT_STYLE_OUTLINE);
+
+ /* Rehinting */
+ evas_object_text_text_set(to, "Bla");
+ evas_font_hinting_set(evas, EVAS_FONT_HINTING_NONE);
+ evas_font_hinting_set(evas, EVAS_FONT_HINTING_AUTO);
+ evas_font_hinting_set(evas, EVAS_FONT_HINTING_BYTECODE);
+
+ /* Direction of an empty text should be NEUTRAL */
+ evas_object_text_text_set(to, "");
+ fail_if(evas_object_text_direction_get(to) != EVAS_BIDI_DIRECTION_NEUTRAL);
+
+ END_TEXT_TEST();
+}
+END_TEST
+
+START_TEST(evas_text_style)
+{
+ Evas_Coord l, r, t, b;
+ START_TEXT_TEST();
+ const char *buf = "Test";
+ evas_object_text_text_set(to, buf);
+ evas_object_text_style_set(to, EVAS_TEXT_STYLE_PLAIN);
+ evas_object_text_style_pad_get(to, &l, &r, &t, &b);
+ fail_if((l != 0) || (r != 0) || (t != 0) || (b != 0));
+
+ evas_object_text_style_set(to, EVAS_TEXT_STYLE_SHADOW);
+ evas_object_text_style_pad_get(to, &l, &r, &t, &b);
+ fail_if((l != 0) || (r != 1) || (t != 0) || (b != 1));
+
+ evas_object_text_style_set(to, EVAS_TEXT_STYLE_OUTLINE);
+ evas_object_text_style_pad_get(to, &l, &r, &t, &b);
+ fail_if((l != 1) || (r != 1) || (t != 1) || (b != 1));
+
+ evas_object_text_style_set(to, EVAS_TEXT_STYLE_SOFT_OUTLINE);
+ evas_object_text_style_pad_get(to, &l, &r, &t, &b);
+ fail_if((l != 2) || (r != 2) || (t != 2) || (b != 2));
+
+ evas_object_text_style_set(to, EVAS_TEXT_STYLE_GLOW);
+ evas_object_text_style_pad_get(to, &l, &r, &t, &b);
+ fail_if((l != 2) || (r != 2) || (t != 2) || (b != 2));
+
+ evas_object_text_style_set(to, EVAS_TEXT_STYLE_OUTLINE_SHADOW);
+ evas_object_text_style_pad_get(to, &l, &r, &t, &b);
+ fail_if((l != 1) || (r != 2) || (t != 1) || (b != 2));
+
+ evas_object_text_style_set(to, EVAS_TEXT_STYLE_FAR_SHADOW);
+ evas_object_text_style_pad_get(to, &l, &r, &t, &b);
+ fail_if((l != 1) || (r != 2) || (t != 1) || (b != 2));
+
+ evas_object_text_style_set(to, EVAS_TEXT_STYLE_OUTLINE_SOFT_SHADOW);
+ evas_object_text_style_pad_get(to, &l, &r, &t, &b);
+ fail_if((l != 1) || (r != 3) || (t != 1) || (b != 3));
+
+ evas_object_text_style_set(to, EVAS_TEXT_STYLE_SOFT_SHADOW);
+ evas_object_text_style_pad_get(to, &l, &r, &t, &b);
+ fail_if((l != 1) || (r != 3) || (t != 1) || (b != 3));
+
+ evas_object_text_style_set(to, EVAS_TEXT_STYLE_FAR_SOFT_SHADOW);
+ evas_object_text_style_pad_get(to, &l, &r, &t, &b);
+ fail_if((l != 0) || (r != 4) || (t != 0) || (b != 4));
+
+ fail_if(strcmp(evas_object_text_text_get(to), buf));
+ END_TEXT_TEST();
+}
+END_TEST
+
+#ifdef HAVE_FRIBIDI
+START_TEST(evas_text_bidi)
+{
+ START_TEXT_TEST();
+ const char *buf = "Test - בדיקה";
+ int i;
+ Evas_Coord x, y, w, h, px;
+ const char *font = "Sans";
+ Evas_Font_Size size = 14;
+
+ evas_object_text_font_set(to, font, size);
+
+ evas_object_text_text_set(to, buf);
+ fail_if(evas_object_text_direction_get(to) != EVAS_BIDI_DIRECTION_LTR);
+ evas_object_text_text_set(to, "בדיקה");
+ fail_if(evas_object_text_direction_get(to) != EVAS_BIDI_DIRECTION_RTL);
+
+ /* With RTL text coords should be monotontically decreasing. */
+ evas_object_text_text_set(to, "נסיון...");
+ x = 0;
+ px = 200;
+ for (i = 0 ; i < eina_unicode_utf8_get_len("נסיון...") ; i++)
+ {
+ fail_if(!evas_object_text_char_pos_get(to, i, &x, &y, &w, &h));
+ fail_if(x >= px);
+ px = x;
+ /* Get back the coords */
+ fail_if(i != evas_object_text_char_coords_get(to, x + (w / 2),
+ y + (h / 2), &x, &y, &w, &h));
+ }
+
+ /* Bidi text is a bit more complex */
+ evas_object_text_text_set(to, "Test - נסיון...");
+ x = 0;
+ px = -100;
+ for (i = 0 ; i < eina_unicode_utf8_get_len("Test - ") ; i++)
+ {
+ fail_if(!evas_object_text_char_pos_get(to, i, &x, &y, &w, &h));
+ fail_if(x <= px);
+ px = x;
+ /* Get back the coords */
+ fail_if(i != evas_object_text_char_coords_get(to, x + (w / 2),
+ y + (h / 2), &x, &y, &w, &h));
+ }
+
+ /* First rtl char requires more specific handling */
+ fail_if(!evas_object_text_char_pos_get(to, i, &x, &y, &w, &h));
+ fail_if(x <= px);
+ px = x;
+ fail_if(i != evas_object_text_char_coords_get(to, x + (w / 2),
+ y + (h / 2), &x, &y, &w, &h));
+ i++;
+ for ( ; i < eina_unicode_utf8_get_len("Test - נסיון") ; i++)
+ {
+ fail_if(!evas_object_text_char_pos_get(to, i, &x, &y, &w, &h));
+ fail_if(x >= px);
+ px = x;
+ /* Get back the coords */
+ fail_if(i != evas_object_text_char_coords_get(to, x + (w / 2),
+ y + (h / 2), &x, &y, &w, &h));
+ }
+ /* First ltr char requires more specific handling */
+ fail_if(!evas_object_text_char_pos_get(to, i, &x, &y, &w, &h));
+ fail_if(x <= px);
+ px = x;
+ i++;
+ for ( ; i < eina_unicode_utf8_get_len("Test - נסיון...") ; i++)
+ {
+ fail_if(!evas_object_text_char_pos_get(to, i, &x, &y, &w, &h));
+ fail_if(x <= px);
+ px = x;
+ /* Get back the coords */
+ fail_if(i != evas_object_text_char_coords_get(to, x + (w / 2),
+ y + (h / 2), &x, &y, &w, &h));
+ }
+
+ /* And with an rtl text */
+ evas_object_text_text_set(to, "נסיון - test...");
+ x = 0;
+ px = 100;
+ for (i = 0 ; i < eina_unicode_utf8_get_len("נסיון - ") ; i++)
+ {
+ fail_if(!evas_object_text_char_pos_get(to, i, &x, &y, &w, &h));
+ fail_if(x >= px);
+ px = x;
+ /* Get back the coords */
+ fail_if(i != evas_object_text_char_coords_get(to, x + (w / 2),
+ y + (h / 2), &x, &y, &w, &h));
+ }
+
+ /* First ltr char requires more specific handling */
+ fail_if(!evas_object_text_char_pos_get(to, i, &x, &y, &w, &h));
+ fail_if(x >= px);
+ px = x;
+ fail_if(i != evas_object_text_char_coords_get(to, x + (w / 2),
+ y + (h / 2), &x, &y, &w, &h));
+ i++;
+ for ( ; i < eina_unicode_utf8_get_len("נסיון - test") ; i++)
+ {
+ fail_if(!evas_object_text_char_pos_get(to, i, &x, &y, &w, &h));
+ fail_if(x <= px);
+ px = x;
+ /* Get back the coords */
+ fail_if(i != evas_object_text_char_coords_get(to, x + (w / 2),
+ y + (h / 2), &x, &y, &w, &h));
+ }
+ /* First rtl char requires more specific handling */
+ fail_if(!evas_object_text_char_pos_get(to, i, &x, &y, &w, &h));
+ fail_if(x >= px);
+ px = x;
+ i++;
+ for ( ; i < eina_unicode_utf8_get_len("נסיון - test...") ; i++)
+ {
+ fail_if(!evas_object_text_char_pos_get(to, i, &x, &y, &w, &h));
+ fail_if(x >= px);
+ px = x;
+ /* Get back the coords */
+ fail_if(i != evas_object_text_char_coords_get(to, x + (w / 2),
+ y + (h / 2), &x, &y, &w, &h));
+ }
+
+ /* And some last up to pos tests */
+ Evas_Coord adv;
+ int pos, prev_pos;
+ evas_object_text_text_set(to, "Test - נסיון...");
+ adv = evas_object_text_horiz_advance_get(to);
+ pos = prev_pos = 0;
+ for (x = 0 ; x <= (adv - 1) ; x++)
+ {
+ pos = evas_object_text_last_up_to_pos(to, x, 0);
+ fail_if(pos < prev_pos);
+ prev_pos = pos;
+ }
+ pos = evas_object_text_last_up_to_pos(to, x, 0);
+ fail_if(pos != -1);
+ pos = evas_object_text_last_up_to_pos(to, -50, 0);
+ fail_if(pos != -1);
+
+ END_TEXT_TEST();
+}
+END_TEST
+#endif
+
+void evas_test_text(TCase *tc)
+{
+ tcase_add_test(tc, evas_text_simple);
+ tcase_add_test(tc, evas_text_style);
+ tcase_add_test(tc, evas_text_set_get);
+ tcase_add_test(tc, evas_text_geometries);
+ tcase_add_test(tc, evas_text_evas);
+#ifdef HAVE_FRIBIDI
+ tcase_add_test(tc, evas_text_bidi);
+#endif
+
+ tcase_add_test(tc, evas_text_unrelated);
+}
diff --git a/src/tests/evas/evas_test_textblock.c b/src/tests/evas/evas_test_textblock.c
new file mode 100644
index 0000000000..e3fdfa8b6c
--- /dev/null
+++ b/src/tests/evas/evas_test_textblock.c
@@ -0,0 +1,2219 @@
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+
+#include <Eina.h>
+
+#include "evas_suite.h"
+#include "Evas.h"
+
+#include "evas_tests_helpers.h"
+
+/* Functions defined in evas_object_textblock.c */
+EAPI Eina_Bool
+_evas_textblock_check_item_node_link(Evas_Object *obj);
+EAPI int
+_evas_textblock_format_offset_get(const Evas_Object_Textblock_Node_Format *n);
+/* end of functions defined in evas_object_textblock.c */
+
+
+static const char *style_buf =
+ "DEFAULT='font=Sans font_size=10 color=#000 text_class=entry'"
+ "newline='br'"
+ "b='+ font=Sans:style=bold'";
+
+#define START_TB_TEST() \
+ Evas *evas; \
+ Evas_Object *tb; \
+ Evas_Textblock_Style *st; \
+ Evas_Textblock_Cursor *cur; \
+ evas = EVAS_TEST_INIT_EVAS(); \
+ evas_font_hinting_set(evas, EVAS_FONT_HINTING_AUTO); \
+ tb = evas_object_textblock_add(evas); \
+ fail_if(!tb); \
+ evas_object_textblock_legacy_newline_set(tb, EINA_FALSE); \
+ st = evas_textblock_style_new(); \
+ fail_if(!st); \
+ evas_textblock_style_set(st, style_buf); \
+ fail_if(strcmp(style_buf, evas_textblock_style_get(st))); \
+ evas_object_textblock_style_set(tb, st); \
+ cur = evas_object_textblock_cursor_new(tb); \
+do \
+{ \
+} \
+while (0)
+
+#define END_TB_TEST() \
+do \
+{ \
+ evas_textblock_cursor_free(cur); \
+ evas_object_del(tb); \
+ evas_textblock_style_free(st); \
+ evas_free(evas); \
+ evas_shutdown(); \
+} \
+while (0)
+
+START_TEST(evas_textblock_simple)
+{
+ START_TB_TEST();
+ const char *buf = "Th<i>i</i>s is a <br/> te<b>s</b>t.";
+ evas_object_textblock_text_markup_set(tb, buf);
+ fail_if(strcmp(evas_object_textblock_text_markup_get(tb), buf));
+ END_TB_TEST();
+}
+END_TEST
+
+#define _CHECK_CURSOR_COORDS() \
+do \
+{ \
+ Evas_Coord cx, cy, cw, ch; \
+ int ret; \
+ ret = evas_textblock_cursor_geometry_get(cur, &cx, &cy, &cw, &ch, \
+ NULL, EVAS_TEXTBLOCK_CURSOR_UNDER); \
+ fail_if(ret == -1); \
+ ret = evas_textblock_cursor_geometry_get(cur, &cx, &cy, &cw, &ch, \
+ NULL, EVAS_TEXTBLOCK_CURSOR_BEFORE); \
+ fail_if(ret == -1); \
+ ret = evas_textblock_cursor_char_geometry_get(cur, \
+ &cx, &cy, &cw, &ch); \
+ fail_if(ret == -1); \
+ ret = evas_textblock_cursor_pen_geometry_get(cur, &cx, &cy, &cw, &ch); \
+ fail_if(ret == -1); \
+ ret = evas_textblock_cursor_line_geometry_get(cur, \
+ &cx, &cy, &cw, &ch); \
+ fail_if(ret == -1); \
+} \
+while (0)
+START_TEST(evas_textblock_cursor)
+{
+ START_TB_TEST();
+ Evas_Coord x, y, w, h;
+ size_t i, len;
+ Evas_Coord nw, nh;
+ const char *buf = "This is a<br/> test.<ps/>Lets see if this works.<ps/>עוד פסקה.";
+
+ /* Walk the textblock using cursor_char_next */
+ evas_object_textblock_text_markup_set(tb, buf);
+ fail_if(strcmp(evas_object_textblock_text_markup_get(tb), buf));
+ len = eina_unicode_utf8_get_len(buf) - 12; /* 12 because len(<br/>) == 1 and len(<ps/>) == 1 */
+ for (i = 0 ; i < len ; i++)
+ {
+ _CHECK_CURSOR_COORDS();
+
+ fail_if(evas_textblock_cursor_pos_get(cur) != (int) i);
+
+ fail_if(!evas_textblock_cursor_char_next(cur) && (i < len - 1));
+ }
+ fail_if(evas_textblock_cursor_char_next(cur));
+
+ /* Jump to positions all aronud the textblock */
+ evas_textblock_cursor_pos_set(cur, -1);
+ fail_if(evas_textblock_cursor_pos_get(cur) != 0);
+
+ evas_textblock_cursor_pos_set(cur, len + 5);
+ fail_if(evas_textblock_cursor_pos_get(cur) != (int) len);
+
+ for (i = 0 ; i < len ; i++)
+ {
+ evas_textblock_cursor_pos_set(cur, i);
+
+ _CHECK_CURSOR_COORDS();
+
+ fail_if(evas_textblock_cursor_pos_get(cur) != (int) i);
+ }
+
+ /* Create another cursor and insert text, making sure everything
+ * is in sync. */
+ evas_object_textblock_clear(tb);
+ Evas_Textblock_Cursor *main_cur = evas_object_textblock_cursor_get(tb);
+ evas_textblock_cursor_copy(main_cur, cur);
+ fail_if(evas_textblock_cursor_pos_get(cur) !=
+ evas_textblock_cursor_pos_get(main_cur));
+
+ evas_textblock_cursor_text_prepend(main_cur, "a");
+ fail_if(evas_textblock_cursor_pos_get(cur) ==
+ evas_textblock_cursor_pos_get(main_cur));
+ evas_textblock_cursor_text_prepend(main_cur, "a");
+ fail_if(evas_textblock_cursor_pos_get(cur) ==
+ evas_textblock_cursor_pos_get(main_cur));
+
+ /* Insert text to a non-empty textblock */
+ evas_object_textblock_clear(tb);
+ evas_object_textblock_text_markup_set(tb, buf);
+ evas_textblock_cursor_copy(main_cur, cur);
+ fail_if(evas_textblock_cursor_pos_get(cur) !=
+ evas_textblock_cursor_pos_get(main_cur));
+
+ evas_textblock_cursor_text_prepend(main_cur, "a");
+ fail_if(evas_textblock_cursor_pos_get(cur) ==
+ evas_textblock_cursor_pos_get(main_cur));
+ evas_textblock_cursor_text_prepend(main_cur, "a");
+ fail_if(evas_textblock_cursor_pos_get(cur) ==
+ evas_textblock_cursor_pos_get(main_cur));
+
+ /* Make sure append works */
+ evas_textblock_cursor_copy(main_cur, cur);
+ fail_if(evas_textblock_cursor_pos_get(cur) !=
+ evas_textblock_cursor_pos_get(main_cur));
+ evas_textblock_cursor_text_append(main_cur, "a");
+ fail_if(evas_textblock_cursor_pos_get(cur) !=
+ evas_textblock_cursor_pos_get(main_cur));
+
+ /* Cursor comparison */
+ evas_textblock_cursor_pos_set(cur, 1);
+ evas_textblock_cursor_pos_set(main_cur, 2);
+ fail_if(evas_textblock_cursor_compare(cur, main_cur) != -1);
+
+ evas_textblock_cursor_pos_set(cur, 2);
+ evas_textblock_cursor_pos_set(main_cur, 2);
+ fail_if(evas_textblock_cursor_compare(cur, main_cur) != 0);
+
+ evas_textblock_cursor_pos_set(cur, 3);
+ evas_textblock_cursor_pos_set(main_cur, 2);
+ fail_if(evas_textblock_cursor_compare(cur, main_cur) != 1);
+
+ /* Paragraph first */
+ evas_object_textblock_text_markup_set(tb, buf);
+ for (i = 0 ; i < len ; i++)
+ {
+ evas_textblock_cursor_pos_set(cur, i);
+
+ evas_textblock_cursor_paragraph_first(cur);
+ fail_if(evas_textblock_cursor_pos_get(cur) != 0);
+ }
+
+ /* Paragraph last */
+ for (i = 0 ; i < len ; i++)
+ {
+ evas_textblock_cursor_pos_set(cur, i);
+
+ evas_textblock_cursor_paragraph_last(cur);
+ fail_if(evas_textblock_cursor_pos_get(cur) != (int) len);
+ }
+
+ /* Paragraph next */
+ evas_textblock_cursor_paragraph_last(cur);
+ fail_if(evas_textblock_cursor_paragraph_next(cur));
+
+ evas_textblock_cursor_paragraph_first(cur);
+ fail_if(!evas_textblock_cursor_paragraph_next(cur));
+ fail_if(!evas_textblock_cursor_paragraph_next(cur));
+
+ /* Paragraph prev */
+ evas_textblock_cursor_paragraph_first(cur);
+ fail_if(evas_textblock_cursor_paragraph_prev(cur));
+
+ evas_textblock_cursor_paragraph_last(cur);
+ fail_if(!evas_textblock_cursor_paragraph_prev(cur));
+ fail_if(!evas_textblock_cursor_paragraph_prev(cur));
+
+ /* Cher next */
+ evas_textblock_cursor_paragraph_last(cur);
+ fail_if(evas_textblock_cursor_char_next(cur));
+
+ evas_textblock_cursor_paragraph_first(cur);
+ fail_if(!evas_textblock_cursor_char_next(cur));
+ fail_if(!evas_textblock_cursor_paragraph_next(cur));
+ fail_if(!evas_textblock_cursor_char_next(cur));
+ fail_if(!evas_textblock_cursor_paragraph_next(cur));
+ fail_if(!evas_textblock_cursor_char_next(cur));
+
+ /* Cher prev */
+ evas_textblock_cursor_paragraph_first(cur);
+ fail_if(evas_textblock_cursor_char_prev(cur));
+
+ evas_textblock_cursor_paragraph_last(cur);
+ fail_if(!evas_textblock_cursor_char_prev(cur));
+ fail_if(!evas_textblock_cursor_paragraph_prev(cur));
+ fail_if(!evas_textblock_cursor_char_prev(cur));
+
+ /* Paragraph char first */
+ evas_textblock_cursor_paragraph_first(main_cur);
+ evas_textblock_cursor_paragraph_first(cur);
+ fail_if(!evas_textblock_cursor_char_next(cur));
+ evas_textblock_cursor_paragraph_char_first(cur);
+ fail_if(evas_textblock_cursor_compare(cur, main_cur));
+
+ /* Paragraph char last */
+ evas_textblock_cursor_paragraph_last(main_cur);
+ evas_textblock_cursor_paragraph_last(cur);
+ fail_if(!evas_textblock_cursor_char_prev(cur));
+ evas_textblock_cursor_paragraph_char_last(cur);
+ fail_if(evas_textblock_cursor_compare(cur, main_cur));
+
+ /* Line char first */
+ evas_textblock_cursor_paragraph_first(main_cur);
+ evas_textblock_cursor_paragraph_first(cur);
+ fail_if(!evas_textblock_cursor_char_next(cur));
+ evas_textblock_cursor_line_char_first(cur);
+ fail_if(evas_textblock_cursor_compare(cur, main_cur));
+
+ evas_textblock_cursor_pos_set(cur, 12);
+ evas_textblock_cursor_line_char_first(cur);
+ fail_if(evas_textblock_cursor_pos_get(cur) != 10);
+
+ /* Line char first */
+ evas_textblock_cursor_paragraph_last(main_cur);
+ evas_textblock_cursor_paragraph_last(cur);
+ fail_if(!evas_textblock_cursor_char_prev(cur));
+ evas_textblock_cursor_line_char_last(cur);
+ fail_if(evas_textblock_cursor_compare(cur, main_cur));
+
+ evas_textblock_cursor_pos_set(cur, 12);
+ evas_textblock_cursor_line_char_last(cur);
+ fail_if(evas_textblock_cursor_pos_get(cur) != 16);
+
+ /* Line set */
+ evas_textblock_cursor_paragraph_first(main_cur);
+ evas_textblock_cursor_paragraph_last(cur);
+
+ fail_if(!evas_textblock_cursor_line_set(cur, 0));
+ fail_if(evas_textblock_cursor_compare(cur, main_cur));
+ fail_if(!evas_textblock_cursor_line_set(cur, 1));
+ fail_if(!evas_textblock_cursor_line_set(cur, 2));
+ fail_if(!evas_textblock_cursor_line_set(cur, 3));
+
+ fail_if(evas_textblock_cursor_line_set(cur, -1));
+ fail_if(evas_textblock_cursor_line_set(cur, 99));
+
+ /* Paragraph text get */
+ evas_textblock_cursor_paragraph_first(cur);
+ fail_if(strcmp(evas_textblock_cursor_paragraph_text_get(cur),
+ "This is a<br/> test."));
+ evas_textblock_cursor_paragraph_next(cur);
+ fail_if(strcmp(evas_textblock_cursor_paragraph_text_get(cur),
+ "Lets see if this works."));
+ evas_textblock_cursor_paragraph_next(cur);
+ fail_if(strcmp(evas_textblock_cursor_paragraph_text_get(cur),
+ "עוד פסקה."));
+
+ /* Paragraph length get */
+ evas_textblock_cursor_paragraph_first(cur);
+ /* -4 because len(<br/>) == 1 */
+ fail_if(evas_textblock_cursor_paragraph_text_length_get(cur) !=
+ eina_unicode_utf8_get_len("This is a<br/> test.") - 4);
+ evas_textblock_cursor_paragraph_next(cur);
+ fail_if(evas_textblock_cursor_paragraph_text_length_get(cur) !=
+ eina_unicode_utf8_get_len("Lets see if this works."));
+ evas_textblock_cursor_paragraph_next(cur);
+ fail_if(evas_textblock_cursor_paragraph_text_length_get(cur) !=
+ eina_unicode_utf8_get_len("עוד פסקה."));
+
+ /* Cursor content get */
+ evas_textblock_cursor_pos_set(cur, 0);
+ fail_if(strcmp(evas_textblock_cursor_content_get(cur), "T"));
+ evas_textblock_cursor_pos_set(cur, 9);
+ fail_if(strcmp(evas_textblock_cursor_content_get(cur), "<br/>"));
+ evas_textblock_cursor_pos_set(cur, 43);
+ fail_if(strcmp(evas_textblock_cursor_content_get(cur), "ד"));
+
+ /* Eol get */
+ for (i = 0 ; i < len ; i++)
+ {
+ evas_textblock_cursor_pos_set(cur, i);
+ evas_textblock_cursor_copy(cur, main_cur);
+ evas_textblock_cursor_line_char_last(main_cur);
+
+ if (!evas_textblock_cursor_compare(cur, main_cur))
+ {
+ fail_if(!evas_textblock_cursor_eol_get(cur));
+ }
+ else
+ {
+ fail_if(evas_textblock_cursor_eol_get(cur));
+ }
+ }
+
+ /* Format positions */
+ const Evas_Object_Textblock_Node_Format *fnode;
+ fnode = evas_textblock_node_format_first_get(tb);
+ fail_if(!fnode);
+ evas_textblock_cursor_at_format_set(cur, fnode);
+ evas_textblock_cursor_copy(cur, main_cur);
+ fail_if(evas_textblock_cursor_pos_get(cur) != 9);
+ fail_if(evas_textblock_cursor_format_get(cur) != fnode);
+
+ fnode = evas_textblock_node_format_next_get(fnode);
+ fail_if(!fnode);
+ evas_textblock_cursor_at_format_set(cur, fnode);
+ fail_if(evas_textblock_cursor_pos_get(cur) != 16);
+ fail_if(evas_textblock_cursor_format_get(cur) != fnode);
+ evas_textblock_cursor_format_next(main_cur);
+ fail_if(evas_textblock_cursor_compare(main_cur, cur));
+
+ fnode = evas_textblock_node_format_prev_get(fnode);
+ fail_if(!fnode);
+ evas_textblock_cursor_at_format_set(cur, fnode);
+ fail_if(evas_textblock_cursor_pos_get(cur) != 9);
+ fail_if(evas_textblock_cursor_format_get(cur) != fnode);
+ evas_textblock_cursor_format_prev(main_cur);
+ fail_if(evas_textblock_cursor_compare(main_cur, cur));
+
+ evas_textblock_cursor_char_next(main_cur);
+ evas_textblock_cursor_format_prev(main_cur);
+ fail_if(evas_textblock_cursor_compare(main_cur, cur));
+
+
+ evas_object_textblock_text_markup_set(tb, buf);
+
+ /* Check that pen geometry and getting char at coord are in sync. */
+ do
+ {
+ int cur_pos;
+
+ /* Check if it's the last char, if it is, break, otherwise, go back
+ * to the current char because our test advanced the cursor. */
+ if (!evas_textblock_cursor_char_next(cur))
+ break;
+ else
+ evas_textblock_cursor_char_prev(cur);
+
+ cur_pos = evas_textblock_cursor_pos_get(cur);
+ evas_textblock_cursor_pen_geometry_get(cur, &x, &y, &w, &h);
+ evas_textblock_cursor_char_coord_set(cur, x + (w / 2), y + (h / 2));
+ fail_if(cur_pos != evas_textblock_cursor_pos_get(cur));
+ }
+ while (evas_textblock_cursor_char_next(cur));
+
+ /* Try positions before the first paragraph, and after the last paragraph */
+ evas_object_textblock_text_markup_set(tb, buf);
+ evas_object_textblock_size_native_get(tb, &nw, &nh);
+ evas_object_resize(tb, nw, nh);
+ evas_textblock_cursor_pos_set(cur, 5);
+ evas_textblock_cursor_char_coord_set(cur, nw / 2,
+ -50);
+ evas_textblock_cursor_paragraph_first(main_cur);
+ fail_if(evas_textblock_cursor_compare(cur, main_cur));
+
+ evas_textblock_cursor_pos_set(cur, 5);
+ evas_textblock_cursor_char_coord_set(cur, nw / 2,
+ nh + 50);
+ evas_textblock_cursor_paragraph_last(main_cur);
+ fail_if(evas_textblock_cursor_compare(cur, main_cur));
+
+ /* Try positions beyond the left/right limits of lines. */
+ for (i = 0 ; i < 2 ; i++)
+ {
+ evas_textblock_cursor_line_set(cur, i);
+ evas_textblock_cursor_line_geometry_get(cur, &x, &y, &w, &h);
+
+ evas_textblock_cursor_pos_set(main_cur, 5);
+ evas_textblock_cursor_char_coord_set(main_cur, x - 50, y);
+ fail_if(evas_textblock_cursor_compare(main_cur, cur));
+
+ evas_textblock_cursor_line_char_last(cur);
+ evas_textblock_cursor_pos_set(main_cur, 5);
+ evas_textblock_cursor_char_coord_set(main_cur, x + w + 50, y);
+ fail_if(evas_textblock_cursor_compare(main_cur, cur));
+ }
+
+#ifdef HAVE_FRIBIDI
+ evas_object_textblock_text_markup_set(tb,
+ "testנסיוןtestנסיון<ps/>"
+ "נסיוןtestנסיוןtest<ps/>"
+ "testנסיוןtest<ps/>"
+ "נסיוןtestנסיון<ps/>"
+ "testנסיון<br/>נסיון<ps/>"
+ "נסיוןtest<br/>test"
+ );
+
+ for (i = 0 ; i < 8 ; i++)
+ {
+ evas_textblock_cursor_line_set(cur, i);
+ evas_textblock_cursor_line_geometry_get(cur, &x, &y, &w, &h);
+ switch (i)
+ {
+ case 0:
+ case 2:
+ case 4:
+ case 5:
+ /* Ltr paragraph */
+ evas_textblock_cursor_pos_set(main_cur, 7);
+ evas_textblock_cursor_char_coord_set(main_cur, x - 50, y);
+ fail_if(evas_textblock_cursor_compare(main_cur, cur));
+
+ evas_textblock_cursor_line_char_last(cur);
+ evas_textblock_cursor_pos_set(main_cur, 7);
+ evas_textblock_cursor_char_coord_set(main_cur, x + w + 50, y);
+ fail_if(evas_textblock_cursor_compare(main_cur, cur));
+ break;
+ case 1:
+ case 3:
+ case 6:
+ case 7:
+ /* Rtl paragraph */
+ evas_textblock_cursor_line_char_last(cur);
+ evas_textblock_cursor_pos_set(main_cur, 7);
+ evas_textblock_cursor_char_coord_set(main_cur, x - 50, y);
+ fail_if(evas_textblock_cursor_compare(main_cur, cur));
+
+ evas_textblock_cursor_line_char_first(cur);
+ evas_textblock_cursor_pos_set(main_cur, 7);
+ evas_textblock_cursor_char_coord_set(main_cur, x + w + 50, y);
+ fail_if(evas_textblock_cursor_compare(main_cur, cur));
+ break;
+ }
+ }
+#endif
+
+ evas_object_textblock_text_markup_set(tb, buf);
+ /* Testing line geometry.*/
+ {
+ Evas_Coord lx, ly, lw, lh;
+ Evas_Coord plx, ply, plw, plh;
+ evas_textblock_cursor_line_set(cur, 0);
+ evas_textblock_cursor_copy(cur, main_cur);
+ evas_textblock_cursor_line_char_last(main_cur);
+ evas_textblock_cursor_line_geometry_get(cur, &plx, &ply, &plw, &plh);
+
+ while (evas_textblock_cursor_compare(cur, main_cur) <= 0)
+ {
+ evas_textblock_cursor_pen_geometry_get(cur, &x, &y, &w, &h);
+ fail_if(0 != evas_textblock_cursor_line_geometry_get(
+ cur, &lx, &ly, &lw, &lh));
+ fail_if((x < lx) || (x + w > lx + lw) ||
+ (y < ly) || (y + h > ly + lh));
+ fail_if((lx != plx) || (ly != ply) || (lw != plw) || (lh != plh));
+
+ plx = lx;
+ ply = ly;
+ plw = lw;
+ plh = lh;
+ evas_textblock_cursor_char_next(cur);
+ }
+
+ evas_textblock_cursor_line_set(cur, 1);
+ evas_textblock_cursor_copy(cur, main_cur);
+ evas_textblock_cursor_line_char_last(main_cur);
+ evas_textblock_cursor_line_geometry_get(cur, &plx, &ply, &plw, &plh);
+
+ while (evas_textblock_cursor_compare(cur, main_cur) <= 0)
+ {
+ evas_textblock_cursor_pen_geometry_get(cur, &x, &y, &w, &h);
+ fail_if(1 != evas_textblock_cursor_line_geometry_get(
+ cur, &lx, &ly, &lw, &lh));
+ fail_if((x < lx) || (x + w > lx + lw) ||
+ (y < ly) || (y + h > ly + lh));
+ fail_if((lx != plx) || (ly != ply) || (lw != plw) || (lh != plh));
+
+ plx = lx;
+ ply = ly;
+ plw = lw;
+ plh = lh;
+ evas_textblock_cursor_char_next(cur);
+ }
+
+ evas_textblock_cursor_paragraph_last(cur);
+ evas_textblock_cursor_line_set(cur, 0);
+ evas_textblock_cursor_line_geometry_get(cur, &plx, &ply, &plw, &plh);
+ evas_object_textblock_line_number_geometry_get(tb, 0,
+ &lx, &ly, &lw, &lh);
+ fail_if((lx != plx) || (ly != ply) || (lw != plw) || (lh != plh));
+ fail_if(0 != evas_textblock_cursor_line_coord_set(cur, ly + (lh / 2)));
+
+ evas_textblock_cursor_line_set(cur, 1);
+ evas_textblock_cursor_line_geometry_get(cur, &plx, &ply, &plw, &plh);
+ evas_object_textblock_line_number_geometry_get(tb, 1,
+ &lx, &ly, &lw, &lh);
+ fail_if((lx != plx) || (ly != ply) || (lw != plw) || (lh != plh));
+ fail_if(1 != evas_textblock_cursor_line_coord_set(cur, ly + (lh / 2)));
+
+ /* Before the start of the textblock */
+ fail_if(0 != evas_textblock_cursor_line_coord_set(cur, -50));
+ fail_if(3 != evas_textblock_cursor_line_coord_set(cur, 100000));
+
+ /* And now with a valigned textblock. */
+ evas_object_textblock_text_markup_set(tb, buf);
+ evas_object_textblock_size_native_get(tb, &nw, &nh);
+ evas_object_resize(tb, 2 * nw, 2 * nh);
+
+ evas_object_textblock_valign_set(tb, 0.5);
+ evas_textblock_cursor_paragraph_first(cur);
+ evas_textblock_cursor_pen_geometry_get(cur, &x, &y, &w, &h);
+ fail_if(y <= 0);
+
+ evas_textblock_cursor_paragraph_last(main_cur);
+ evas_textblock_cursor_char_coord_set(main_cur, x + w, y / 2);
+ fail_if(evas_textblock_cursor_compare(main_cur, cur));
+
+ evas_textblock_cursor_paragraph_last(main_cur);
+ evas_textblock_cursor_line_coord_set(main_cur, y / 2);
+ fail_if(evas_textblock_cursor_compare(main_cur, cur));
+
+ /* Fail if they are equal, i.e if it for some reason thinks it should
+ * go to the end. */
+ evas_textblock_cursor_paragraph_first(main_cur);
+ evas_textblock_cursor_paragraph_last(cur);
+ evas_textblock_cursor_char_coord_set(main_cur, x + w, nh + 1);
+ fail_if(!evas_textblock_cursor_compare(main_cur, cur));
+
+ evas_textblock_cursor_paragraph_first(main_cur);
+ evas_textblock_cursor_paragraph_last(cur);
+ evas_textblock_cursor_line_coord_set(main_cur, nh + 1);
+ fail_if(!evas_textblock_cursor_compare(main_cur, cur));
+
+ /* Fail if it doesn't go to the end. */
+ evas_textblock_cursor_paragraph_last(cur);
+ evas_textblock_cursor_paragraph_first(main_cur);
+ evas_textblock_cursor_char_coord_set(main_cur, x + w, (2 * nh) - 1);
+ fail_if(evas_textblock_cursor_compare(main_cur, cur));
+
+ evas_textblock_cursor_paragraph_first(main_cur);
+ evas_textblock_cursor_line_coord_set(main_cur, (2 * nh) - 1);
+ fail_if(evas_textblock_cursor_compare(main_cur, cur));
+ }
+
+ {
+ const char *buf_wb = "a This is_a t:e.s't a";
+ evas_object_textblock_text_markup_set(tb, buf_wb);
+
+ /* Word start/end */
+ evas_textblock_cursor_pos_set(cur, 3);
+ evas_textblock_cursor_word_start(cur);
+ fail_if(2 != evas_textblock_cursor_pos_get(cur));
+ evas_textblock_cursor_word_end(cur);
+ fail_if(5 != evas_textblock_cursor_pos_get(cur));
+
+ evas_textblock_cursor_pos_set(cur, 13);
+ evas_textblock_cursor_word_end(cur);
+ fail_if(18 != evas_textblock_cursor_pos_get(cur));
+ evas_textblock_cursor_word_start(cur);
+ fail_if(12 != evas_textblock_cursor_pos_get(cur));
+ evas_textblock_cursor_word_start(cur);
+ fail_if(12 != evas_textblock_cursor_pos_get(cur));
+ evas_textblock_cursor_word_start(cur);
+ fail_if(12 != evas_textblock_cursor_pos_get(cur));
+ evas_textblock_cursor_word_end(cur);
+ fail_if(18 != evas_textblock_cursor_pos_get(cur));
+ evas_textblock_cursor_word_end(cur);
+ fail_if(18 != evas_textblock_cursor_pos_get(cur));
+
+ /* Bug with 1 char word separators at paragraph start. */
+ evas_object_textblock_text_markup_set(tb, "=test");
+ evas_textblock_cursor_pos_set(cur, 4);
+ evas_textblock_cursor_word_start(cur);
+ fail_if(1 != evas_textblock_cursor_pos_get(cur));
+ }
+
+ END_TB_TEST();
+}
+END_TEST
+
+START_TEST(evas_textblock_format_removal)
+{
+ START_TB_TEST();
+ int i;
+ const char *buf = "Th<b>is a<a>tes</a>st</b>.";
+ const Evas_Object_Textblock_Node_Format *fnode;
+ Evas_Textblock_Cursor *main_cur = evas_object_textblock_cursor_get(tb);
+ evas_object_textblock_text_markup_set(tb, buf);
+
+ /* Remove the "b" pair. */
+ fnode = evas_textblock_node_format_first_get(tb);
+ evas_textblock_node_format_remove_pair(tb,
+ (Evas_Object_Textblock_Node_Format *) fnode);
+
+ fnode = evas_textblock_node_format_first_get(tb);
+ fail_if (!fnode);
+ fail_if(strcmp(evas_textblock_node_format_text_get(fnode),
+ "+ a"));
+
+ fnode = evas_textblock_node_format_next_get(fnode);
+ fail_if (!fnode);
+ fail_if(strcmp(evas_textblock_node_format_text_get(fnode),
+ "- a"));
+
+ fnode = evas_textblock_node_format_next_get(fnode);
+ fail_if (fnode);
+
+ /* Now also remove the a pair */
+ fnode = evas_textblock_node_format_first_get(tb);
+ evas_textblock_node_format_remove_pair(tb,
+ (Evas_Object_Textblock_Node_Format *) fnode);
+ fnode = evas_textblock_node_format_first_get(tb);
+ fail_if (fnode);
+
+ /* Remove the "a" pair. */
+ evas_object_textblock_text_markup_set(tb, buf);
+
+ fnode = evas_textblock_node_format_first_get(tb);
+ fnode = evas_textblock_node_format_next_get(fnode);
+ evas_textblock_node_format_remove_pair(tb,
+ (Evas_Object_Textblock_Node_Format *) fnode);
+
+ fnode = evas_textblock_node_format_first_get(tb);
+ fail_if (!fnode);
+ fail_if(strcmp(evas_textblock_node_format_text_get(fnode),
+ "+ b"));
+
+ fnode = evas_textblock_node_format_next_get(fnode);
+ fail_if (!fnode);
+ fail_if(strcmp(evas_textblock_node_format_text_get(fnode),
+ "- b"));
+
+ fnode = evas_textblock_node_format_next_get(fnode);
+ fail_if (fnode);
+
+ /* Now also remove the b pair */
+ fnode = evas_textblock_node_format_first_get(tb);
+ evas_textblock_node_format_remove_pair(tb,
+ (Evas_Object_Textblock_Node_Format *) fnode);
+ fnode = evas_textblock_node_format_first_get(tb);
+ fail_if (fnode);
+
+ /* Now remove formats by removing text */
+ evas_object_textblock_text_markup_set(tb, buf);
+ evas_textblock_cursor_pos_set(cur, 6);
+ evas_textblock_cursor_char_delete(cur);
+ evas_textblock_cursor_char_delete(cur);
+ evas_textblock_cursor_char_delete(cur);
+ /* Only b formats should remain */
+ fnode = evas_textblock_node_format_first_get(tb);
+ fail_if (!fnode);
+ fail_if(strcmp(evas_textblock_node_format_text_get(fnode),
+ "+ b"));
+
+ fnode = evas_textblock_node_format_next_get(fnode);
+ fail_if (!fnode);
+ fail_if(strcmp(evas_textblock_node_format_text_get(fnode),
+ "- b"));
+
+ fnode = evas_textblock_node_format_next_get(fnode);
+ fail_if (fnode);
+
+ /* No formats should remain. */
+ evas_textblock_cursor_pos_set(cur, 2);
+ evas_textblock_cursor_char_delete(cur);
+ evas_textblock_cursor_char_delete(cur);
+ evas_textblock_cursor_char_delete(cur);
+ evas_textblock_cursor_char_delete(cur);
+ evas_textblock_cursor_char_delete(cur);
+ evas_textblock_cursor_char_delete(cur);
+ fnode = evas_textblock_node_format_first_get(tb);
+ fail_if (fnode);
+
+ /* Try to remove the formats in a way that shouldn't remove them */
+ evas_object_textblock_text_markup_set(tb, buf);
+ evas_textblock_cursor_pos_set(cur, 7);
+ evas_textblock_cursor_char_delete(cur);
+ evas_textblock_cursor_char_delete(cur);
+ evas_textblock_cursor_char_delete(cur);
+ evas_textblock_cursor_char_delete(cur);
+ fnode = evas_textblock_node_format_first_get(tb);
+ fail_if (!fnode);
+ fail_if(strcmp(evas_textblock_node_format_text_get(fnode),
+ "+ b"));
+
+ fnode = evas_textblock_node_format_next_get(fnode);
+ fail_if (!fnode);
+ fail_if(strcmp(evas_textblock_node_format_text_get(fnode),
+ "+ a"));
+
+ fnode = evas_textblock_node_format_next_get(fnode);
+ fail_if (!fnode);
+ fail_if(strcmp(evas_textblock_node_format_text_get(fnode),
+ "- a"));
+
+ fnode = evas_textblock_node_format_next_get(fnode);
+ fail_if (!fnode);
+ fail_if(strcmp(evas_textblock_node_format_text_get(fnode),
+ "- b"));
+
+ fnode = evas_textblock_node_format_next_get(fnode);
+ fail_if (fnode);
+
+ /* Try range deletion to delete a */
+ evas_object_textblock_text_markup_set(tb, buf);
+ evas_textblock_cursor_pos_set(cur, 6);
+ evas_textblock_cursor_pos_set(main_cur, 9);
+ evas_textblock_cursor_range_delete(cur, main_cur);
+ fnode = evas_textblock_node_format_first_get(tb);
+ fail_if (!fnode);
+ fail_if(strcmp(evas_textblock_node_format_text_get(fnode),
+ "+ b"));
+
+ fnode = evas_textblock_node_format_next_get(fnode);
+ fail_if (!fnode);
+ fail_if(strcmp(evas_textblock_node_format_text_get(fnode),
+ "- b"));
+
+ fnode = evas_textblock_node_format_next_get(fnode);
+ fail_if (fnode);
+
+ /* Range deletion to delete both */
+ evas_object_textblock_text_markup_set(tb, buf);
+ evas_textblock_cursor_pos_set(cur, 2);
+ evas_textblock_cursor_pos_set(main_cur, 11);
+ evas_textblock_cursor_range_delete(cur, main_cur);
+ fnode = evas_textblock_node_format_first_get(tb);
+ fail_if (fnode);
+
+ /* Range deletion across paragraphs */
+ evas_object_textblock_text_markup_set(tb,
+ "Th<b>is a<a>te<ps/>"
+ "s</a>st</b>.");
+ evas_textblock_cursor_pos_set(cur, 6);
+ evas_textblock_cursor_pos_set(main_cur, 10);
+ evas_textblock_cursor_range_delete(cur, main_cur);
+ fnode = evas_textblock_node_format_first_get(tb);
+ fail_if (!fnode);
+ fail_if(strcmp(evas_textblock_node_format_text_get(fnode),
+ "+ b"));
+
+ fnode = evas_textblock_node_format_next_get(fnode);
+ fail_if (!fnode);
+ fail_if(strcmp(evas_textblock_node_format_text_get(fnode),
+ "- b"));
+
+ fnode = evas_textblock_node_format_next_get(fnode);
+ fail_if (fnode);
+
+ /* Range deletion across paragraph - a bug found in elm. */
+ evas_object_textblock_text_markup_set(tb,
+ "This is an entry widget in this window that<ps/>"
+ "uses markup <b>like this</> for styling and<ps/>"
+ "formatting <em>like this</>, as well as<ps/>"
+ "<a href=X><link>links in the text</></a>, so enter text<ps/>"
+ "in here to edit it. By the way, links are<ps/>"
+ "called <a href=anc-02>Anchors</a> so you will need<ps/>"
+ "to refer to them this way.<ps/>"
+ "<ps/>"
+
+ "Also you can stick in items with (relsize + ascent): "
+ "<item relsize=16x16 vsize=ascent href=emoticon/evil-laugh></item>"
+ " (full) "
+ "<item relsize=16x16 vsize=full href=emoticon/guilty-smile></item>"
+ " (to the left)<ps/>"
+
+ "Also (size + ascent): "
+ "<item size=16x16 vsize=ascent href=emoticon/haha></item>"
+ " (full) "
+ "<item size=16x16 vsize=full href=emoticon/happy-panting></item>"
+ " (before this)<ps/>"
+
+ "And as well (absize + ascent): "
+ "<item absize=64x64 vsize=ascent href=emoticon/knowing-grin></item>"
+ " (full) "
+ "<item absize=64x64 vsize=full href=emoticon/not-impressed></item>"
+ " or even paths to image files on disk too like: "
+ "<item absize=96x128 vsize=full href=file://bla/images/sky_01.jpg></item>"
+ " ... end.");
+ evas_textblock_cursor_paragraph_first(cur);
+ evas_textblock_cursor_paragraph_last(main_cur);
+ evas_textblock_cursor_range_delete(cur, main_cur);
+ fnode = evas_textblock_node_format_first_get(tb);
+ fail_if(fnode);
+
+
+ /* Deleting a range with just one char and surrounded by formats, that
+ * deletes a paragraph. */
+ evas_object_textblock_text_markup_set(tb, "A<ps/><b>B</b>");
+ evas_textblock_cursor_pos_set(cur, 2);
+ evas_textblock_cursor_pos_set(main_cur, 3);
+ evas_textblock_cursor_range_delete(cur, main_cur);
+ fnode = evas_textblock_node_format_first_get(tb);
+ fnode = evas_textblock_node_format_next_get(fnode);
+ fail_if (fnode);
+
+ /* Two formats in the same place. */
+ evas_object_textblock_text_markup_set(tb, "a<b><a>b</a></b>b");
+ evas_textblock_cursor_pos_set(cur, 1);
+ evas_textblock_cursor_char_delete(cur);
+ fnode = evas_textblock_node_format_first_get(tb);
+ fail_if (fnode);
+
+ /* Two formats across different paragraphs with notihng in between. */
+ evas_object_textblock_text_markup_set(tb, "<b><ps/></b>");
+ evas_textblock_cursor_pos_set(cur, 0);
+ evas_textblock_cursor_char_delete(cur);
+ fnode = evas_textblock_node_format_first_get(tb);
+ fail_if (fnode);
+
+ /* Try with range */
+ evas_object_textblock_text_markup_set(tb, "<b><ps/></b>");
+ evas_textblock_cursor_pos_set(cur, 0);
+ evas_textblock_cursor_pos_set(main_cur, 1);
+ evas_textblock_cursor_range_delete(cur, main_cur);
+ fnode = evas_textblock_node_format_first_get(tb);
+ fail_if (fnode);
+
+ /* Verify fmt position and REP_CHAR positions are the same */
+ evas_object_textblock_text_markup_set(tb,
+ "This is<ps/>an <item absize=93x152 vsize=ascent></>a.");
+ evas_textblock_cursor_pos_set(cur, 7);
+ evas_textblock_cursor_char_delete(cur);
+ fnode = evas_textblock_node_format_first_get(tb);
+ fail_if(_evas_textblock_format_offset_get(fnode) != 10);
+
+ /* Out of order <b><i></b></i> mixes. */
+ evas_object_textblock_text_markup_set(tb, "a<b>b<i>c</b>d</i>e");
+ evas_textblock_cursor_pos_set(cur, 2);
+
+ for (i = 0 ; i < 2 ; i++)
+ {
+ fnode = evas_textblock_node_format_first_get(tb);
+ fail_if (!fnode);
+ fail_if(strcmp(evas_textblock_node_format_text_get(fnode), "+ b"));
+
+ fnode = evas_textblock_node_format_next_get(fnode);
+ fail_if (!fnode);
+ fail_if(strcmp(evas_textblock_node_format_text_get(fnode), "+ i"));
+
+ fnode = evas_textblock_node_format_next_get(fnode);
+ fail_if (!fnode);
+ fail_if(strcmp(evas_textblock_node_format_text_get(fnode), "- b"));
+
+ fnode = evas_textblock_node_format_next_get(fnode);
+ fail_if (!fnode);
+ fail_if(strcmp(evas_textblock_node_format_text_get(fnode), "- i"));
+
+ fnode = evas_textblock_node_format_next_get(fnode);
+ fail_if (fnode);
+
+ evas_textblock_cursor_char_delete(cur);
+ }
+ fnode = evas_textblock_node_format_first_get(tb);
+ fail_if (!fnode);
+ fail_if(strcmp(evas_textblock_node_format_text_get(fnode), "+ b"));
+
+ fnode = evas_textblock_node_format_next_get(fnode);
+ fail_if (!fnode);
+ fail_if(strcmp(evas_textblock_node_format_text_get(fnode), "- b"));
+
+ fnode = evas_textblock_node_format_next_get(fnode);
+ fail_if (fnode);
+
+ /* This time with a generic closer */
+ evas_object_textblock_text_markup_set(tb, "a<b>b<i>c</b>d</>e");
+ evas_textblock_cursor_pos_set(cur, 2);
+
+ for (i = 0 ; i < 2 ; i++)
+ {
+ fnode = evas_textblock_node_format_first_get(tb);
+ fail_if (!fnode);
+ fail_if(strcmp(evas_textblock_node_format_text_get(fnode), "+ b"));
+
+ fnode = evas_textblock_node_format_next_get(fnode);
+ fail_if (!fnode);
+ fail_if(strcmp(evas_textblock_node_format_text_get(fnode), "+ i"));
+
+ fnode = evas_textblock_node_format_next_get(fnode);
+ fail_if (!fnode);
+ fail_if(strcmp(evas_textblock_node_format_text_get(fnode), "- b"));
+
+ fnode = evas_textblock_node_format_next_get(fnode);
+ fail_if (!fnode);
+ fail_if(strcmp(evas_textblock_node_format_text_get(fnode), "- "));
+
+ fnode = evas_textblock_node_format_next_get(fnode);
+ fail_if (fnode);
+
+ evas_textblock_cursor_char_delete(cur);
+ }
+ fnode = evas_textblock_node_format_first_get(tb);
+ fail_if (!fnode);
+ fail_if(strcmp(evas_textblock_node_format_text_get(fnode), "+ b"));
+
+ fnode = evas_textblock_node_format_next_get(fnode);
+ fail_if (!fnode);
+ fail_if(strcmp(evas_textblock_node_format_text_get(fnode), "- b"));
+
+ fnode = evas_textblock_node_format_next_get(fnode);
+ fail_if (fnode);
+
+ /* And now with remove pair. */
+ evas_object_textblock_text_markup_set(tb, "a<b>b<i>c</b>d</i>e");
+ evas_textblock_cursor_pos_set(cur, 2);
+ fnode = evas_textblock_node_format_first_get(tb);
+ evas_textblock_node_format_remove_pair(tb,
+ (Evas_Object_Textblock_Node_Format *) fnode);
+
+ fnode = evas_textblock_node_format_first_get(tb);
+ fail_if (!fnode);
+ fail_if(strcmp(evas_textblock_node_format_text_get(fnode), "+ i"));
+
+ fnode = evas_textblock_node_format_next_get(fnode);
+ fail_if (!fnode);
+ fail_if(strcmp(evas_textblock_node_format_text_get(fnode), "- i"));
+
+ fnode = evas_textblock_node_format_next_get(fnode);
+ fail_if (fnode);
+
+ /* Remove the other pair */
+ evas_object_textblock_text_markup_set(tb, "a<b>b<i>c</>d</i>e");
+ evas_textblock_cursor_pos_set(cur, 2);
+ fnode = evas_textblock_node_format_first_get(tb);
+ fnode = evas_textblock_node_format_next_get(fnode);
+ evas_textblock_node_format_remove_pair(tb,
+ (Evas_Object_Textblock_Node_Format *) fnode);
+
+ fnode = evas_textblock_node_format_first_get(tb);
+ fail_if (!fnode);
+ fail_if(strcmp(evas_textblock_node_format_text_get(fnode), "+ b"));
+
+ fnode = evas_textblock_node_format_next_get(fnode);
+ fail_if (!fnode);
+ fail_if(strcmp(evas_textblock_node_format_text_get(fnode), "- i"));
+
+ fnode = evas_textblock_node_format_next_get(fnode);
+ fail_if (fnode);
+
+ /* Remove two pairs with the same name and same positions. */
+ evas_object_textblock_text_markup_set(tb, "<a><a>A</a></a>");
+ evas_textblock_cursor_pos_set(cur, 0);
+ evas_textblock_cursor_char_delete(cur);
+
+ fnode = evas_textblock_node_format_first_get(tb);
+ fail_if (fnode);
+
+ /* Try to remove a format that doesn't have a pair (with a bad mkup) */
+ evas_object_textblock_text_markup_set(tb, "a<b>b<i>c</>d</i>e");
+ evas_textblock_cursor_pos_set(cur, 2);
+ fnode = evas_textblock_node_format_first_get(tb);
+ evas_textblock_node_format_remove_pair(tb,
+ (Evas_Object_Textblock_Node_Format *) fnode);
+
+ fnode = evas_textblock_node_format_first_get(tb);
+ fail_if (!fnode);
+ fail_if(strcmp(evas_textblock_node_format_text_get(fnode), "+ i"));
+
+ fnode = evas_textblock_node_format_next_get(fnode);
+ fail_if (!fnode);
+ fail_if(strcmp(evas_textblock_node_format_text_get(fnode), "- "));
+
+ fnode = evas_textblock_node_format_next_get(fnode);
+ fail_if (!fnode);
+ fail_if(strcmp(evas_textblock_node_format_text_get(fnode), "- i"));
+
+ fnode = evas_textblock_node_format_next_get(fnode);
+ fail_if (fnode);
+
+ END_TB_TEST();
+}
+END_TEST
+
+/* Testing items */
+START_TEST(evas_textblock_items)
+{
+ Evas_Coord w, h, w2, h2, nw, nh, ih;
+ START_TB_TEST();
+ const char *buf = "This is an <item absize=93x152></>.";
+
+ /* Absolute item size */
+ buf = "This is an <item absize=93x152 vsize=full></>.";
+ evas_object_textblock_text_markup_set(tb, buf);
+ evas_object_textblock_size_formatted_get(tb, &w, &h);
+ fail_if((w < 93) || (h != 152));
+ evas_textblock_cursor_pos_set(cur, 11);
+ evas_textblock_cursor_format_item_geometry_get(cur, NULL, NULL, &w, &h);
+ fail_if((w != 93) || (h != 152));
+
+ buf = "This is an <item absize=93x152 vsize=ascent></>.";
+ evas_object_textblock_text_markup_set(tb, buf);
+ evas_object_textblock_size_formatted_get(tb, &w, &h);
+ fail_if((w < 93) || (h <= 152));
+ evas_textblock_cursor_pos_set(cur, 11);
+ evas_textblock_cursor_format_item_geometry_get(cur, NULL, NULL, &w, &h);
+ fail_if((w != 93) || (h != 152));
+
+ /* Size is the same as abssize, unless there's scaling applied. */
+ buf = "This is an <item size=93x152 vsize=full></>.";
+ evas_object_textblock_text_markup_set(tb, buf);
+ evas_object_textblock_size_formatted_get(tb, &w, &h);
+ fail_if((w < 93) || (h != 152));
+ evas_textblock_cursor_pos_set(cur, 11);
+ evas_textblock_cursor_format_item_geometry_get(cur, NULL, NULL, &w, &h);
+ fail_if((w != 93) || (h != 152));
+
+ buf = "This is an <item size=93x152 vsize=ascent></>.";
+ evas_object_textblock_text_markup_set(tb, buf);
+ evas_object_textblock_size_formatted_get(tb, &w, &h);
+ fail_if((w < 93) || (h <= 152));
+ evas_textblock_cursor_pos_set(cur, 11);
+ evas_textblock_cursor_format_item_geometry_get(cur, NULL, NULL, &w, &h);
+ fail_if((w != 93) || (h != 152));
+
+ evas_object_scale_set(tb, 2.0);
+ buf = "This is an <item size=93x152 vsize=full></>.";
+ evas_object_textblock_text_markup_set(tb, buf);
+ evas_object_textblock_size_formatted_get(tb, &w, &h);
+ fail_if((w < (2 * 93)) || (h != (2 * 152)));
+ evas_textblock_cursor_pos_set(cur, 11);
+ evas_textblock_cursor_format_item_geometry_get(cur, NULL, NULL, &w, &h);
+ fail_if((w != (2 * 93)) || (h != (2 * 152)));
+ evas_textblock_cursor_pos_set(cur, 11);
+ evas_textblock_cursor_format_item_geometry_get(cur, NULL, NULL, &w, &h);
+ fail_if((w != (2 * 93)) || (h != (2 * 152)));
+
+ buf = "This is an <item size=93x152 vsize=ascent></>.";
+ evas_object_textblock_text_markup_set(tb, buf);
+ evas_object_textblock_size_formatted_get(tb, &w, &h);
+ fail_if((w < (2 * 93)) || (h <= (2 * 152)));
+ evas_textblock_cursor_pos_set(cur, 11);
+ evas_textblock_cursor_format_item_geometry_get(cur, NULL, NULL, &w, &h);
+ fail_if((w != (2 * 93)) || (h != (2 * 152)));
+
+ evas_object_scale_set(tb, 1.0);
+
+ /* Relsize */
+ /* relsize means it should adjust itself to the size of the line */
+ buf = "This is an <item relsize=93x152 vsize=full></>.";
+ evas_object_textblock_text_markup_set(tb, buf);
+ evas_object_textblock_size_formatted_get(tb, &w, &h);
+ fail_if((w >= 93) || (h >= 152));
+ evas_textblock_cursor_pos_set(cur, 11);
+ evas_textblock_cursor_format_item_geometry_get(cur, NULL, NULL, &w, &ih);
+ fail_if((w > 90) || (h != ih));
+
+ buf = "This is an <item relize=93x152 vsize=ascent></>.";
+ evas_object_textblock_text_markup_set(tb, buf);
+ evas_object_textblock_size_formatted_get(tb, &w, &h);
+ fail_if((w >= 93) || (h >= 152));
+ evas_textblock_cursor_pos_set(cur, 11);
+ evas_textblock_cursor_format_item_geometry_get(cur, NULL, NULL, &w, &ih);
+ fail_if((w > 90) || (h <= ih));
+
+ /* Relsize and abs size in the same line, all should be the same size */
+ buf = "<item relsize=64x64 vsize=ascent href=emoticon/knowing-grin></item><item absize=64x64 vsize=ascent href=emoticon/knowing-grin></item><item relsize=64x64 vsize=ascent href=emoticon/knowing-grin></item>";
+ evas_object_textblock_text_markup_set(tb, buf);
+ evas_object_textblock_size_formatted_get(tb, &w, &h);
+ evas_object_textblock_size_native_get(tb, &nw, &nh);
+ fail_if((nw != w) || (nh != h));
+ evas_textblock_cursor_format_item_geometry_get(cur, NULL, NULL, &w, &h);
+ evas_textblock_cursor_char_next(cur);
+ evas_textblock_cursor_format_item_geometry_get(cur, NULL, NULL, &w2, &h2);
+ fail_if((w != w2) || (h != h2));
+ evas_textblock_cursor_format_item_geometry_get(cur, NULL, NULL, &w, &h);
+ evas_textblock_cursor_char_next(cur);
+ evas_textblock_cursor_format_item_geometry_get(cur, NULL, NULL, &w2, &h2);
+ fail_if((w != w2) || (h != h2));
+
+ /* FIXME: Also verify x,y positions of the item. */
+
+ /* FIXME We need some item tests that involve line wrapping that make the
+ * items move between lines that are in different sizes.
+ * Also, tests that involve wrapping positions with relsized items. We
+ * want to make sure the item gets a relsize on the correct time (before
+ * the wrapping, and then is updated after the wrapping) and that
+ * all the lines have the correct sizes afterwards. */
+
+ END_TB_TEST();
+}
+END_TEST
+
+/* Wrapping tests */
+START_TEST(evas_textblock_wrapping)
+{
+ Evas_Coord bw, bh, w, h, nw, nh;
+ int i;
+ START_TB_TEST();
+ evas_object_textblock_text_markup_set(tb, "a");
+ evas_object_textblock_size_formatted_get(tb, &bw, &bh);
+
+ /* Char wrap */
+ evas_object_textblock_text_markup_set(tb, "aaaaaaa");
+ evas_textblock_cursor_format_prepend(cur, "+ wrap=char");
+ evas_object_resize(tb, bw, bh);
+ evas_object_textblock_size_formatted_get(tb, &w, &h);
+ /* Wrap to minimum */
+ fail_if(w != bw);
+ fail_if(h <= bh);
+
+ /* Mixed - fallback to char wrap */
+ evas_object_textblock_text_markup_set(tb, "aaaaaaa");
+ evas_textblock_cursor_format_prepend(cur, "+ wrap=mixed");
+ evas_object_resize(tb, bw, bh);
+ evas_object_textblock_size_formatted_get(tb, &w, &h);
+ /* Wrap to minimum */
+ fail_if(w != bw);
+ fail_if(h <= bh);
+
+ /* Basic Word wrap */
+ evas_object_textblock_text_markup_set(tb, "aaaa");
+ evas_object_textblock_size_formatted_get(tb, &bw, &bh);
+
+ evas_object_textblock_text_markup_set(tb, "aaaa aa");
+ evas_textblock_cursor_format_prepend(cur, "+ wrap=word");
+ evas_object_resize(tb, bw, bh);
+ evas_object_textblock_size_formatted_get(tb, &w, &h);
+ /* Wrap to minimum */
+ fail_if(w != bw);
+ fail_if(h <= bh);
+
+ /* Mixed - fallback to word wrap */
+ evas_object_textblock_text_markup_set(tb, "aaaa aa");
+ evas_textblock_cursor_format_prepend(cur, "+ wrap=mixed");
+ evas_object_resize(tb, bw + 1, bh);
+ evas_object_textblock_size_formatted_get(tb, &w, &h);
+ /* Wrap to minimum */
+ fail_if(w != bw);
+ fail_if(h <= bh);
+
+ /* Wrap and then expand again. */
+ evas_object_textblock_text_markup_set(tb, "aaaa aa");
+ evas_textblock_cursor_format_prepend(cur, "+ wrap=word");
+ evas_object_resize(tb, bw, bh);
+ evas_object_textblock_size_formatted_get(tb, &w, &h);
+ evas_object_textblock_size_native_get(tb, &nw, &nh);
+ evas_object_resize(tb, nw, nh);
+ evas_object_textblock_size_formatted_get(tb, &w, &h);
+ fail_if((w != nw) || (h != nh));
+
+ /* Reduce size until reaching the minimum, making sure we don't
+ * get something wrong along the way */
+ /* Char wrap */
+ evas_object_textblock_text_markup_set(tb, "a");
+ evas_object_textblock_size_formatted_get(tb, &bw, &bh);
+ evas_object_textblock_text_markup_set(tb,
+ "aaaa aaaa aaa aa aaa<ps/>"
+ "aaaa aaa aaa aaa aaa<ps/>"
+ "a aaaaa aaaaaaaaaaaaaa<br/>aaaaa<ps/>"
+ "aaaaaa"
+ );
+ evas_textblock_cursor_format_prepend(cur, "+ wrap=char");
+ evas_object_textblock_size_native_get(tb, &nw, &nh);
+
+ Evas_Coord iw;
+ for (iw = nw ; iw >= bw ; iw--)
+ {
+ evas_object_resize(tb, iw, 1000);
+ evas_object_textblock_size_formatted_get(tb, &w, &h);
+ fail_if(w < bw);
+ fail_if(w > iw);
+ }
+ fail_if(w != bw);
+
+ /* Word wrap */
+ evas_object_textblock_text_markup_set(tb, "aaaaaa");
+ evas_object_textblock_size_formatted_get(tb, &bw, &bh);
+ evas_object_textblock_text_markup_set(tb,
+ "aaaa aaaa aaa aa aaa<ps/>"
+ "aaaa aaa aaa aaa aaa<ps/>"
+ "a aaaaa aaaaaa<br/>aaaaa<ps/>"
+ "aaaaa"
+ );
+ evas_textblock_cursor_format_prepend(cur, "+ wrap=word");
+ evas_object_textblock_size_native_get(tb, &nw, &nh);
+
+ for (iw = nw ; iw >= bw ; iw--)
+ {
+ evas_object_resize(tb, iw, 1000);
+ evas_object_textblock_size_formatted_get(tb, &w, &h);
+ fail_if(w < bw);
+ fail_if(w > iw);
+ }
+ fail_if(w != bw);
+
+ /* Mixed wrap */
+ evas_object_textblock_text_markup_set(tb, "a");
+ evas_object_textblock_size_formatted_get(tb, &bw, &bh);
+ evas_object_textblock_text_markup_set(tb,
+ "aaaa aaaa aaa aa aaa<ps/>"
+ "aaaa aaa aaa aaa aaa<ps/>"
+ "a aaaaa aaaaaa<br/>aaaaa<ps/>"
+ "aaaaa"
+ );
+ evas_textblock_cursor_format_prepend(cur, "+ wrap=mixed");
+ evas_object_textblock_size_native_get(tb, &nw, &nh);
+
+ for (iw = nw ; iw >= bw ; iw--)
+ {
+ evas_object_resize(tb, iw, 1000);
+ evas_object_textblock_size_formatted_get(tb, &w, &h);
+ fail_if(w < bw);
+ fail_if(w > iw);
+ }
+ fail_if(w != bw);
+
+ /* Resize, making sure we keep going down in the minimum size. */
+ char *wrap_style[] = { "+ wrap=word", "+ wrap=char", "+ wrap=mixed" };
+ int wrap_items = sizeof(wrap_style) / sizeof(*wrap_style);
+
+ evas_object_textblock_text_markup_set(tb,
+ "This is an entry widget in this window that<br/>"
+ "uses markup <b>like this</> for styling and<br/>"
+ "formatting <em>like this</>, as well as<br/>"
+ "<a href=X><link>links in the text</></a>, so enter text<br/>"
+ "in here to edit it. By the way, links are<br/>"
+ "called <a href=anc-02>Anchors</a> so you will need<br/>"
+ "to refer to them this way.<br/>"
+ "<br/>"
+
+ "Also you can stick in items with (relsize + ascent): "
+ "<item relsize=16x16 vsize=ascent href=emoticon/evil-laugh></item>"
+ " (full) "
+ "<item relsize=16x16 vsize=full href=emoticon/guilty-smile></item>"
+ " (to the left)<br/>"
+
+ "Also (size + ascent): "
+ "<item size=16x16 vsize=ascent href=emoticon/haha></item>"
+ " (full) "
+ "<item size=16x16 vsize=full href=emoticon/happy-panting></item>"
+ " (before this)<br/>"
+
+ "And as well (absize + ascent): "
+ "<item absize=64x64 vsize=ascent href=emoticon/knowing-grin></item>"
+ " (full) "
+ "<item absize=64x64 vsize=full href=emoticon/not-impressed></item>"
+ " or even paths to image files on disk too like: "
+ "<item absize=96x128 vsize=full href=file://%s/images/sky_01.jpg></item>"
+ " ... end."
+ );
+
+ /* Get minimum size */
+ evas_object_textblock_size_native_get(tb, &nw, &nh);
+
+ for (i = 0 ; i < wrap_items ; i++)
+ {
+ evas_textblock_cursor_format_prepend(cur, wrap_style[i]);
+ evas_object_resize(tb, 0, 0);
+ evas_object_textblock_size_formatted_get(tb, &bw, &bh);
+
+ for (iw = nw ; iw >= bw ; iw--)
+ {
+ evas_object_resize(tb, iw, 1000);
+ evas_object_textblock_size_formatted_get(tb, &w, &h);
+ fail_if(w < bw);
+ fail_if(w > iw);
+ }
+ fail_if(w != bw);
+ }
+
+
+ /* Ellipsis */
+ evas_object_textblock_text_markup_set(tb, "aaaaaaaaaa");
+ evas_textblock_cursor_format_prepend(cur, "+ ellipsis=1.0");
+ evas_object_textblock_size_native_get(tb, &nw, &nh);
+ evas_object_resize(tb, nw / 2, nh);
+ evas_object_textblock_size_formatted_get(tb, &w, &h);
+ fail_if((w > (nw / 2)) || (h != nh));
+
+ evas_object_textblock_text_markup_set(tb, "aaaaaaaaaaaaaaaaaa<br/>b");
+ evas_textblock_cursor_format_prepend(cur, "+ ellipsis=1.0 wrap=word");
+ evas_object_textblock_size_native_get(tb, &nw, &nh);
+ evas_object_resize(tb, nw / 2, nh * 2);
+ evas_object_textblock_size_formatted_get(tb, &w, &h);
+ fail_if(w > (nw / 2));
+
+ END_TB_TEST();
+}
+END_TEST
+
+/* Various textblock stuff */
+START_TEST(evas_textblock_various)
+{
+ Evas_Coord w, h, bw, bh;
+ START_TB_TEST();
+ const char *buf = "This<ps/>textblock<ps/>has<ps/>a<ps/>lot<ps/>of<ps/>lines<ps/>.";
+ evas_object_textblock_text_markup_set(tb, buf);
+ evas_object_textblock_size_formatted_get(tb, &w, &h);
+ /* Move outside of the screen so it'll have to search for the correct
+ * paragraph and etc. */
+ evas_object_move(tb, -(w / 2), -(h / 2));
+
+ /* Replacement char */
+ evas_object_textblock_text_markup_set(tb, "*");
+ evas_object_textblock_size_formatted_get(tb, &bw, &bh);
+ evas_object_textblock_replace_char_set(tb, "*");
+ evas_object_textblock_text_markup_set(tb, "|");
+ evas_object_textblock_size_formatted_get(tb, &w, &h);
+ fail_if((w != bw) || (h != bh));
+
+ /* Items have correct text node information */
+ evas_object_textblock_text_markup_set(tb, "");
+ fail_if(!_evas_textblock_check_item_node_link(tb));
+ evas_object_textblock_text_markup_set(tb, "<ps/>");
+ fail_if(!_evas_textblock_check_item_node_link(tb));
+ evas_object_textblock_text_markup_set(tb, "a<ps/>");
+ fail_if(!_evas_textblock_check_item_node_link(tb));
+ evas_object_textblock_text_markup_set(tb, "a<ps/>a");
+ fail_if(!_evas_textblock_check_item_node_link(tb));
+ evas_object_textblock_text_markup_set(tb, "a<ps/>a<ps/>");
+ fail_if(!_evas_textblock_check_item_node_link(tb));
+ evas_object_textblock_text_markup_set(tb, "a<ps/>a<ps/>a");
+ fail_if(!_evas_textblock_check_item_node_link(tb));
+
+ /* These shouldn't crash (although the desired outcome is not yet defined) */
+ evas_object_textblock_text_markup_set(tb, "&#xfffc;");
+ evas_textblock_cursor_pos_set(cur, 0);
+ evas_textblock_cursor_char_delete(cur);
+
+ evas_object_textblock_text_markup_set(tb, "\xEF\xBF\xBC");
+ evas_textblock_cursor_pos_set(cur, 0);
+ evas_textblock_cursor_char_delete(cur);
+
+ END_TB_TEST();
+}
+END_TEST
+
+/* Various geometries. e.g. range geometry. */
+START_TEST(evas_textblock_geometries)
+{
+ START_TB_TEST();
+ const char *buf = "This is a <br/> test.";
+ evas_object_textblock_text_markup_set(tb, buf);
+
+ /* Single line range */
+ Evas_Textblock_Cursor *main_cur = evas_object_textblock_cursor_get(tb);
+ evas_textblock_cursor_pos_set(cur, 0);
+ evas_textblock_cursor_pos_set(main_cur, 6);
+
+ Eina_List *rects, *rects2;
+ Evas_Textblock_Rectangle *tr, *tr2;
+ rects = evas_textblock_cursor_range_geometry_get(cur, main_cur);
+ fail_if(!rects);
+ rects2 = evas_textblock_cursor_range_geometry_get(main_cur, cur);
+ fail_if(!rects2);
+
+ fail_if(eina_list_count(rects) != 1);
+ fail_if(eina_list_count(rects2) != 1);
+
+ tr = eina_list_data_get(rects);
+ fail_if((tr->h <= 0) || (tr->w <= 0));
+ tr2 = eina_list_data_get(rects2);
+ fail_if((tr2->h <= 0) || (tr2->w <= 0));
+
+ fail_if((tr->x != tr2->x) || (tr->y != tr2->y) || (tr->w != tr2->w) ||
+ (tr->h != tr2->h));
+
+ /* Multiline range */
+ evas_textblock_cursor_pos_set(cur, 0);
+ evas_textblock_cursor_pos_set(main_cur, 14);
+
+ rects = evas_textblock_cursor_range_geometry_get(cur, main_cur);
+ fail_if(!rects);
+ rects2 = evas_textblock_cursor_range_geometry_get(main_cur, cur);
+ fail_if(!rects2);
+
+ fail_if(eina_list_count(rects) != 2);
+ fail_if(eina_list_count(rects2) != 2);
+
+ tr = eina_list_data_get(rects);
+ fail_if((tr->h <= 0) || (tr->w <= 0));
+ tr2 = eina_list_data_get(rects2);
+ fail_if((tr2->h <= 0) || (tr2->w <= 0));
+
+ fail_if((tr->x != tr2->x) || (tr->y != tr2->y) || (tr->w != tr2->w) ||
+ (tr->h != tr2->h));
+
+ tr = eina_list_data_get(eina_list_next(rects));
+ fail_if((tr->h <= 0) || (tr->w <= 0));
+ tr2 = eina_list_data_get(eina_list_next(rects2));
+ fail_if((tr2->h <= 0) || (tr2->w <= 0));
+
+ fail_if((tr->x != tr2->x) || (tr->y != tr2->y) || (tr->w != tr2->w) ||
+ (tr->h != tr2->h));
+
+ /* Check that the second line is positioned below the first */
+ tr = eina_list_data_get(rects);
+ tr2 = eina_list_data_get(eina_list_next(rects));
+ fail_if(tr->y >= tr2->y);
+
+ END_TB_TEST();
+}
+END_TEST
+
+/* Should handle all the text editing. */
+START_TEST(evas_textblock_editing)
+{
+ START_TB_TEST();
+ const char *buf = "First par.<ps/>Second par.";
+ evas_object_textblock_text_markup_set(tb, buf);
+ Evas_Textblock_Cursor *main_cur = evas_object_textblock_cursor_get(tb);
+
+ /* Check deletion works */
+ /* Try deleting after the end of the textblock */
+ {
+ char *content;
+ evas_textblock_cursor_paragraph_last(cur);
+ content = strdup(evas_object_textblock_text_markup_get(tb));
+ evas_textblock_cursor_char_delete(cur);
+ fail_if(strcmp(content, evas_object_textblock_text_markup_get(tb)));
+ free(content);
+ }
+
+ /* Delete the first char */
+ evas_textblock_cursor_paragraph_first(cur);
+ evas_textblock_cursor_char_delete(cur);
+ fail_if(strcmp(evas_object_textblock_text_markup_get(tb),
+ "irst par.<ps/>Second par."));
+
+ /* Delete some arbitrary char */
+ evas_textblock_cursor_char_next(cur);
+ evas_textblock_cursor_char_next(cur);
+ evas_textblock_cursor_char_next(cur);
+ evas_textblock_cursor_char_delete(cur);
+ fail_if(strcmp(evas_object_textblock_text_markup_get(tb),
+ "irs par.<ps/>Second par."));
+
+ /* Delete a range */
+ evas_textblock_cursor_pos_set(main_cur, 1);
+ evas_textblock_cursor_pos_set(cur, 6);
+ evas_textblock_cursor_range_delete(cur, main_cur);
+ fail_if(strcmp(evas_object_textblock_text_markup_get(tb),
+ "ir.<ps/>Second par."));
+ evas_textblock_cursor_paragraph_char_first(main_cur);
+ evas_textblock_cursor_paragraph_char_last(cur);
+ evas_textblock_cursor_char_next(cur);
+ evas_textblock_cursor_range_delete(cur, main_cur);
+ fail_if(strcmp(evas_object_textblock_text_markup_get(tb),
+ "Second par."));
+
+ evas_object_textblock_text_markup_set(tb, buf);
+ evas_textblock_cursor_paragraph_last(main_cur);
+ evas_object_textblock_text_markup_prepend(main_cur, "Test<b>bla</b>bla.");
+ evas_textblock_cursor_paragraph_last(cur);
+ evas_textblock_cursor_paragraph_char_first(main_cur);
+ evas_textblock_cursor_range_delete(cur, main_cur);
+ fail_if(strcmp(evas_object_textblock_text_markup_get(tb),
+ "First par.<ps/>"));
+
+ /* Merging paragraphs */
+ evas_object_textblock_text_markup_set(tb, buf);
+ evas_textblock_cursor_paragraph_char_last(cur);
+ evas_textblock_cursor_copy(cur, main_cur);
+ evas_textblock_cursor_char_delete(cur);
+
+ evas_textblock_cursor_paragraph_first(cur);
+ fail_if(evas_textblock_cursor_paragraph_next(cur));
+
+ /* Split paragraphs */
+ evas_textblock_cursor_format_prepend(cur, "ps");
+
+ evas_textblock_cursor_paragraph_first(cur);
+ fail_if(!evas_textblock_cursor_paragraph_next(cur));
+ fail_if(evas_textblock_cursor_paragraph_next(cur));
+
+ /* Merge paragraphs using range deletion */
+ evas_object_textblock_text_markup_set(tb, buf);
+ evas_textblock_cursor_paragraph_first(cur);
+ evas_textblock_cursor_paragraph_char_last(cur);
+ evas_textblock_cursor_copy(cur, main_cur);
+ evas_textblock_cursor_char_prev(cur);
+ evas_textblock_cursor_char_next(main_cur);
+
+ evas_textblock_cursor_range_delete(cur, main_cur);
+ evas_textblock_cursor_paragraph_first(cur);
+ fail_if(evas_textblock_cursor_paragraph_next(cur));
+
+ {
+ /* Limit to 1000 iterations so we'll never get into an infinite loop,
+ * even if broken */
+ int limit = 1000;
+ evas_object_textblock_text_markup_set(tb, "this is a test eauoeuaou<ps/>this is a test1<ps/>this is a test 3");
+ evas_textblock_cursor_paragraph_last(cur);
+ while (evas_textblock_cursor_pos_get(cur) > 0)
+ {
+ limit--;
+ fail_if(limit <= 0);
+ evas_textblock_cursor_copy(cur, main_cur);
+ evas_textblock_cursor_char_prev(cur);
+ evas_textblock_cursor_word_start(cur);
+ evas_textblock_cursor_range_delete(cur, main_cur);
+ }
+ }
+
+
+ /* Insert illegal characters inside the format. */
+ {
+ const char *content;
+ evas_object_textblock_text_markup_set(tb, "a\n");
+ evas_textblock_cursor_pos_set(cur, 1);
+ content = evas_textblock_cursor_content_get(cur);
+
+ evas_object_textblock_text_markup_set(tb, "a\t");
+ evas_textblock_cursor_pos_set(cur, 1);
+ content = evas_textblock_cursor_content_get(cur);
+
+ evas_object_textblock_text_markup_set(tb, "a\xEF\xBF\xBC");
+ evas_textblock_cursor_pos_set(cur, 1);
+ content = evas_textblock_cursor_content_get(cur);
+
+ evas_object_textblock_text_markup_set(tb, "a\xE2\x80\xA9");
+ evas_textblock_cursor_pos_set(cur, 1);
+ content = evas_textblock_cursor_content_get(cur);
+ (void) content;
+ }
+
+ /* FIXME: Also add text appending/prepending */
+
+ END_TB_TEST();
+}
+END_TEST
+
+/* Text getters */
+START_TEST(evas_textblock_text_getters)
+{
+ START_TB_TEST();
+ const char *buf = "This is a <br/> test.<ps/>"
+ "טקסט בעברית<ps/>and now in english.";
+ evas_object_textblock_text_markup_set(tb, buf);
+ evas_textblock_cursor_paragraph_first(cur);
+
+ fail_if(strcmp(evas_textblock_cursor_paragraph_text_get(cur),
+ "This is a <br/> test."));
+
+ evas_textblock_cursor_paragraph_next(cur);
+ fail_if(strcmp(evas_textblock_cursor_paragraph_text_get(cur),
+ "טקסט בעברית"));
+
+ evas_textblock_cursor_paragraph_next(cur);
+ fail_if(strcmp(evas_textblock_cursor_paragraph_text_get(cur),
+ "and now in english."));
+
+ /* Range get */
+ Evas_Textblock_Cursor *main_cur = evas_object_textblock_cursor_get(tb);
+ evas_textblock_cursor_pos_set(main_cur, 2);
+ evas_textblock_cursor_pos_set(cur, 2);
+ fail_if(*evas_textblock_cursor_range_text_get(main_cur, cur,
+ EVAS_TEXTBLOCK_TEXT_MARKUP));
+
+ evas_textblock_cursor_pos_set(main_cur, 2);
+ evas_textblock_cursor_pos_set(cur, 6);
+ fail_if(strcmp(evas_textblock_cursor_range_text_get(main_cur, cur,
+ EVAS_TEXTBLOCK_TEXT_MARKUP), "is i"));
+
+ evas_textblock_cursor_pos_set(main_cur, 5);
+ evas_textblock_cursor_pos_set(cur, 14);
+ fail_if(strcmp(evas_textblock_cursor_range_text_get(main_cur, cur,
+ EVAS_TEXTBLOCK_TEXT_MARKUP), "is a <br/> te"));
+
+ evas_textblock_cursor_pos_set(main_cur, 14);
+ evas_textblock_cursor_pos_set(cur, 20);
+ fail_if(strcmp(evas_textblock_cursor_range_text_get(main_cur, cur,
+ EVAS_TEXTBLOCK_TEXT_MARKUP), "st.<ps/>טק"));
+
+ evas_textblock_cursor_pos_set(main_cur, 14);
+ evas_textblock_cursor_pos_set(cur, 32);
+ fail_if(strcmp(evas_textblock_cursor_range_text_get(main_cur, cur,
+ EVAS_TEXTBLOCK_TEXT_MARKUP), "st.<ps/>טקסט בעברית<ps/>an"));
+
+ /* Backward range get */
+ evas_textblock_cursor_pos_set(main_cur, 2);
+ evas_textblock_cursor_pos_set(cur, 2);
+ fail_if(*evas_textblock_cursor_range_text_get(cur, main_cur,
+ EVAS_TEXTBLOCK_TEXT_MARKUP));
+
+ evas_textblock_cursor_pos_set(main_cur, 2);
+ evas_textblock_cursor_pos_set(cur, 6);
+ fail_if(strcmp(evas_textblock_cursor_range_text_get(cur, main_cur,
+ EVAS_TEXTBLOCK_TEXT_MARKUP), "is i"));
+
+ evas_textblock_cursor_pos_set(main_cur, 5);
+ evas_textblock_cursor_pos_set(cur, 14);
+ fail_if(strcmp(evas_textblock_cursor_range_text_get(cur, main_cur,
+ EVAS_TEXTBLOCK_TEXT_MARKUP), "is a <br/> te"));
+
+ evas_textblock_cursor_pos_set(main_cur, 14);
+ evas_textblock_cursor_pos_set(cur, 20);
+ fail_if(strcmp(evas_textblock_cursor_range_text_get(cur, main_cur,
+ EVAS_TEXTBLOCK_TEXT_MARKUP), "st.<ps/>טק"));
+
+ evas_textblock_cursor_pos_set(main_cur, 14);
+ evas_textblock_cursor_pos_set(cur, 32);
+ fail_if(strcmp(evas_textblock_cursor_range_text_get(cur, main_cur,
+ EVAS_TEXTBLOCK_TEXT_MARKUP), "st.<ps/>טקסט בעברית<ps/>an"));
+
+ /* Uninit cursors and other weird cases */
+ evas_object_textblock_clear(tb);
+ evas_textblock_cursor_copy(main_cur, cur);
+ evas_textblock_cursor_text_prepend(main_cur, "aaa");
+ fail_if(strcmp(evas_textblock_cursor_range_text_get(cur, main_cur,
+ EVAS_TEXTBLOCK_TEXT_MARKUP), "aaa"));
+
+ /* Markup to plain and vice versa */
+ {
+ char *tmp, *tmp2;
+
+ /* Real textblock object */
+ tmp = evas_textblock_text_markup_to_utf8(tb, "<br/>aa<\n/>bb<\t/>");
+ fail_if(strcmp(tmp, "\naa\nbb\t"));
+ tmp2 = evas_textblock_text_utf8_to_markup(tb, tmp);
+ fail_if(strcmp(tmp2, "<br/>aa<br/>bb<tab/>"));
+ free(tmp2);
+ free(tmp);
+
+ tmp = evas_textblock_text_markup_to_utf8(tb, "a<item></item>");
+ fail_if(strcmp(tmp, "a\xEF\xBF\xBC"));
+ tmp2 = evas_textblock_text_utf8_to_markup(tb, tmp);
+ fail_if(strcmp(tmp2, "a&#xfffc;"));
+ free(tmp2);
+ free(tmp);
+
+ tmp = evas_textblock_text_markup_to_utf8(tb, "a&nbsp;");
+ fail_if(strcmp(tmp, "a\xC2\xA0"));
+ tmp2 = evas_textblock_text_utf8_to_markup(tb, tmp);
+ fail_if(strcmp(tmp2, "a\xC2\xA0"));
+ free(tmp2);
+ free(tmp);
+
+ tmp = evas_textblock_text_markup_to_utf8(tb, "a<b>b</b><more></>a");
+ fail_if(strcmp(tmp, "aba"));
+ tmp2 = evas_textblock_text_utf8_to_markup(tb, tmp);
+ fail_if(strcmp(tmp2, "aba"));
+ free(tmp2);
+ free(tmp);
+
+ tmp = evas_textblock_text_markup_to_utf8(tb, "a&amp;a");
+ fail_if(strcmp(tmp, "a&a"));
+ tmp2 = evas_textblock_text_utf8_to_markup(tb, tmp);
+ fail_if(strcmp(tmp2, "a&amp;a"));
+ free(tmp2);
+ free(tmp);
+
+ tmp = evas_textblock_text_markup_to_utf8(tb, "a<newline/>a");
+ fail_if(strcmp(tmp, "a\na"));
+ tmp2 = evas_textblock_text_utf8_to_markup(tb, tmp);
+ fail_if(strcmp(tmp2, "a<br/>a"));
+ free(tmp2);
+ free(tmp);
+
+ /* NULL textblock object */
+ tmp = evas_textblock_text_markup_to_utf8(NULL, "<br/>aa<\n/>bb<\t/>");
+ fail_if(strcmp(tmp, "\naa\nbb\t"));
+ tmp2 = evas_textblock_text_utf8_to_markup(NULL, tmp);
+ fail_if(strcmp(tmp2, "<br/>aa<br/>bb<tab/>"));
+ free(tmp2);
+ free(tmp);
+
+ tmp = evas_textblock_text_markup_to_utf8(NULL, "a<item></item>");
+ fail_if(strcmp(tmp, "a\xEF\xBF\xBC"));
+ tmp2 = evas_textblock_text_utf8_to_markup(NULL, tmp);
+ fail_if(strcmp(tmp2, "a&#xfffc;"));
+ free(tmp2);
+ free(tmp);
+
+ tmp = evas_textblock_text_markup_to_utf8(NULL, "a&nbsp;");
+ fail_if(strcmp(tmp, "a\xC2\xA0"));
+ tmp2 = evas_textblock_text_utf8_to_markup(NULL, tmp);
+ fail_if(strcmp(tmp2, "a\xC2\xA0"));
+ free(tmp2);
+ free(tmp);
+
+ tmp = evas_textblock_text_markup_to_utf8(NULL, "a<b>b</b><more></>a");
+ fail_if(strcmp(tmp, "aba"));
+ tmp2 = evas_textblock_text_utf8_to_markup(NULL, tmp);
+ fail_if(strcmp(tmp2, "aba"));
+ free(tmp2);
+ free(tmp);
+
+ tmp = evas_textblock_text_markup_to_utf8(tb, "a&amp;a");
+ fail_if(strcmp(tmp, "a&a"));
+ tmp2 = evas_textblock_text_utf8_to_markup(tb, tmp);
+ fail_if(strcmp(tmp2, "a&amp;a"));
+ free(tmp2);
+ free(tmp);
+
+ tmp = evas_textblock_text_markup_to_utf8(NULL, "a<newline/>a");
+ fail_if(strcmp(tmp, "aa"));
+ tmp2 = evas_textblock_text_utf8_to_markup(NULL, tmp);
+ fail_if(strcmp(tmp2, "aa"));
+ free(tmp2);
+ free(tmp);
+ }
+
+ END_TB_TEST();
+}
+END_TEST
+
+/* Formats */
+START_TEST(evas_textblock_formats)
+{
+ START_TB_TEST();
+ const char *buf = "Th<b>i<font_size=15 wrap=none>s i</font_size=13>s</> a <br/> te<ps/>st<item></>.";
+ const Evas_Object_Textblock_Node_Format *fnode;
+ evas_object_textblock_text_markup_set(tb, buf);
+
+ /* Walk from the start */
+ fnode = evas_textblock_node_format_first_get(tb);
+ fail_if(!fnode);
+ fail_if(strcmp(evas_textblock_node_format_text_get(fnode), "+ b"));
+
+ fnode = evas_textblock_node_format_next_get(fnode);
+ fail_if(!fnode);
+ fail_if(strcmp(evas_textblock_node_format_text_get(fnode),
+ "+ font_size=15 wrap=none"));
+
+ fnode = evas_textblock_node_format_next_get(fnode);
+ fail_if(!fnode);
+ fail_if(strcmp(evas_textblock_node_format_text_get(fnode),
+ "- font_size=13"));
+
+ fnode = evas_textblock_node_format_next_get(fnode);
+ fail_if(!fnode);
+ fail_if(strcmp(evas_textblock_node_format_text_get(fnode), "- "));
+
+ fnode = evas_textblock_node_format_next_get(fnode);
+ fail_if(!fnode);
+ fail_if(strcmp(evas_textblock_node_format_text_get(fnode), "br"));
+
+ fnode = evas_textblock_node_format_next_get(fnode);
+ fail_if(!fnode);
+ fail_if(strcmp(evas_textblock_node_format_text_get(fnode), "ps"));
+
+ fnode = evas_textblock_node_format_next_get(fnode);
+ fail_if(!fnode);
+ fail_if(strcmp(evas_textblock_node_format_text_get(fnode), "+ item"));
+
+ fnode = evas_textblock_node_format_next_get(fnode);
+ fail_if(!fnode);
+ fail_if(strcmp(evas_textblock_node_format_text_get(fnode), "- "));
+
+ fnode = evas_textblock_node_format_next_get(fnode);
+ fail_if(fnode);
+
+ /* Walk backwards */
+ fnode = evas_textblock_node_format_last_get(tb);
+ fail_if(!fnode);
+ fail_if(strcmp(evas_textblock_node_format_text_get(fnode), "- "));
+
+ fnode = evas_textblock_node_format_prev_get(fnode);
+ fail_if(!fnode);
+ fail_if(strcmp(evas_textblock_node_format_text_get(fnode), "+ item"));
+
+ fnode = evas_textblock_node_format_prev_get(fnode);
+ fail_if(!fnode);
+ fail_if(strcmp(evas_textblock_node_format_text_get(fnode), "ps"));
+
+ fnode = evas_textblock_node_format_prev_get(fnode);
+ fail_if(!fnode);
+ fail_if(strcmp(evas_textblock_node_format_text_get(fnode), "br"));
+
+ fnode = evas_textblock_node_format_prev_get(fnode);
+ fail_if(!fnode);
+ fail_if(strcmp(evas_textblock_node_format_text_get(fnode), "- "));
+
+ fnode = evas_textblock_node_format_prev_get(fnode);
+ fail_if(!fnode);
+ fail_if(strcmp(evas_textblock_node_format_text_get(fnode),
+ "- font_size=13"));
+
+ fnode = evas_textblock_node_format_prev_get(fnode);
+ fail_if(!fnode);
+ fail_if(strcmp(evas_textblock_node_format_text_get(fnode),
+ "+ font_size=15 wrap=none"));
+
+ fnode = evas_textblock_node_format_prev_get(fnode);
+ fail_if(!fnode);
+ fail_if(strcmp(evas_textblock_node_format_text_get(fnode), "+ b"));
+
+ fnode = evas_textblock_node_format_prev_get(fnode);
+ fail_if(fnode);
+
+ /* Cursor and format detection */
+ fnode = evas_textblock_node_format_first_get(tb);
+ fail_if(!fnode);
+ evas_textblock_cursor_at_format_set(cur, fnode);
+ fail_if(evas_textblock_cursor_format_is_visible_get(cur));
+
+ fnode = evas_textblock_node_format_next_get(fnode);
+ fail_if(!fnode);
+ evas_textblock_cursor_at_format_set(cur, fnode);
+ fail_if(evas_textblock_cursor_format_is_visible_get(cur));
+
+ fnode = evas_textblock_node_format_next_get(fnode);
+ fail_if(!fnode);
+ evas_textblock_cursor_at_format_set(cur, fnode);
+ fail_if(evas_textblock_cursor_format_is_visible_get(cur));
+
+ fnode = evas_textblock_node_format_next_get(fnode);
+ fail_if(!fnode);
+ evas_textblock_cursor_at_format_set(cur, fnode);
+ fail_if(evas_textblock_cursor_format_is_visible_get(cur));
+
+ fnode = evas_textblock_node_format_next_get(fnode);
+ fail_if(!fnode);
+ evas_textblock_cursor_at_format_set(cur, fnode);
+ fail_if(!evas_textblock_cursor_format_is_visible_get(cur));
+
+ fnode = evas_textblock_node_format_next_get(fnode);
+ fail_if(!fnode);
+ evas_textblock_cursor_at_format_set(cur, fnode);
+ fail_if(!evas_textblock_cursor_format_is_visible_get(cur));
+
+ size_t i = 0;
+ evas_textblock_cursor_paragraph_first(cur);
+ do
+ {
+ switch (i)
+ {
+ case 2:
+ case 3:
+ case 6:
+ case 7:
+ case 10:
+ case 14:
+ case 17:
+ case 18:
+ fail_if(!evas_textblock_cursor_is_format(cur));
+ break;
+ default:
+ fail_if(evas_textblock_cursor_is_format(cur));
+ fail_if(evas_textblock_cursor_format_is_visible_get(cur));
+ break;
+ }
+ i++;
+ }
+ while (evas_textblock_cursor_char_next(cur));
+
+ /* Format text nodes invalidation */
+ {
+ Evas_Coord w, h, nw, nh;
+ evas_object_textblock_text_markup_set(tb, "Test");
+ evas_object_textblock_size_formatted_get(tb, &w, &h);
+ evas_textblock_cursor_paragraph_first(cur);
+ evas_textblock_cursor_format_prepend(cur, "+ font_size=40");
+ evas_object_textblock_size_formatted_get(tb, &nw, &nh);
+ fail_if((w >= nw) || (h >= nh));
+ }
+ /* FIXME: Should extend invalidation tests. */
+
+ /* Various formats, just verify there's no seg, we can't really
+ * verify them visually, well, we can some of them. Possibly in the
+ * future we will */
+ evas_object_textblock_text_markup_set(tb,
+ "<font_size=40>font_size=40</><ps/>"
+ "<color=#F210B3FF>color=#F210B3FF</><ps/>"
+ "<underline=single underline_color=#A2B3C4>underline=single underline_color=#A2B3C4</><ps/>"
+ "<underline=double underline_color=#F00 underline2_color=#00F>underline=double underline_color=#F00 underline2_color=#00F</><ps/>"
+ "<underline=dashed underline_dash_color=#0F0 underline_dash_width=2 underline_dash_gap=1>underline=dashed underline_dash_color=#0F0 underline_dash_width=2 underline_dash_gap=1</><ps/>"
+ "<style=outline outline_color=#F0FA>style=outline outline_color=#F0FA</><ps/>"
+ "<style=shadow shadow_color=#F0F>style=shadow shadow_color=#F0F</><ps/>"
+ "<style=glow glow_color=#BBB>style=glow glow_color=#BBB</><ps/>"
+ "<style=glow glow2_color=#0F0>style=glow glow2_color=#0F0</><ps/>"
+ "<style=glow color=#fff glow2_color=#fe87 glow_color=#f214>style=glow color=#fff glow2_color=#fe87 glow_color=#f214</><ps/>"
+ "<backing=on backing_color=#00F>backing=on backing_color=#00F</><ps/>"
+ "<strikethrough=on strikethrough_color=#FF0>strikethrough=on strikethrough_color=#FF0</><ps/>"
+ "<align=right>align=right</><ps/>"
+ "<backing=on backing_color=#F008 valign=0.0>valign=0.0</><ps/>"
+ "<backing=on backing_color=#0F08 tabstops=50>tabstops=<\\t></>50</><ps/>"
+ "<backing=on backing_color=#00F8 linesize=40>linesize=40</><ps/>"
+ "<backing=on backing_color=#F0F8 linerelsize=200%>linerelsize=200%</><ps/>"
+ "<backing=on backing_color=#0FF8 linegap=20>linegap=20</><ps/>"
+ "<backing=on backing_color=#FF08 linerelgap=100%>linerelgap=100%</><ps/>");
+
+ /* Force a relayout */
+ evas_object_textblock_size_formatted_get(tb, NULL, NULL);
+
+ /* Removing paired formats. */
+ evas_object_textblock_text_markup_set(tb, "<a>aa<b>bb</b>cc</a>");
+ fnode = evas_textblock_node_format_first_get(tb);
+ evas_textblock_node_format_remove_pair(tb, (Evas_Object_Textblock_Node_Format *) fnode);
+ fnode = evas_textblock_node_format_first_get(tb);
+ fail_if(!fnode);
+ fail_if(strcmp(evas_textblock_node_format_text_get(fnode), "+ b"));
+ fnode = evas_textblock_node_format_next_get(fnode);
+ fail_if(!fnode);
+ fail_if(strcmp(evas_textblock_node_format_text_get(fnode), "- b"));
+
+ evas_object_textblock_text_markup_set(tb, "<a>aa<b>bb</b>cc</a>");
+ fnode = evas_textblock_node_format_first_get(tb);
+ fnode = evas_textblock_node_format_next_get(fnode);
+ evas_textblock_node_format_remove_pair(tb, (Evas_Object_Textblock_Node_Format *) fnode);
+ fnode = evas_textblock_node_format_first_get(tb);
+ fail_if(!fnode);
+ fail_if(strcmp(evas_textblock_node_format_text_get(fnode), "+ a"));
+ fnode = evas_textblock_node_format_next_get(fnode);
+ fail_if(!fnode);
+ fail_if(strcmp(evas_textblock_node_format_text_get(fnode), "- a"));
+
+ /* Format list get */
+ evas_object_textblock_text_markup_set(tb, "<a>a</>a<item>b</>"
+ "b<item>b</>c<a>c</>");
+ const Eina_List *flist = evas_textblock_node_format_list_get(tb, "a");
+ const Eina_List *itr;
+ EINA_LIST_FOREACH(flist, itr, fnode)
+ {
+ fail_if(strcmp(evas_textblock_node_format_text_get(fnode), "+ a"));
+ }
+
+ flist = evas_textblock_node_format_list_get(tb, "item");
+ EINA_LIST_FOREACH(flist, itr, fnode)
+ {
+ fail_if(strcmp(evas_textblock_node_format_text_get(fnode), "+ item"));
+ }
+
+ /* Make sure we get all the types of visible formats correctly. */
+ evas_object_textblock_text_markup_set(tb, "<ps/>a<br/>a<tab/>a<item></>");
+ fail_if(strcmp(evas_textblock_node_format_text_get(
+ evas_textblock_cursor_format_get(cur)), "ps"));
+ fail_if(strcmp(evas_textblock_cursor_content_get(cur), "<ps/>"));
+ fail_if(!evas_textblock_cursor_format_is_visible_get(cur));
+ fail_if(!evas_textblock_cursor_char_next(cur));
+ fail_if(!evas_textblock_cursor_char_next(cur));
+ fail_if(strcmp(evas_textblock_node_format_text_get(
+ evas_textblock_cursor_format_get(cur)), "br"));
+ fail_if(strcmp(evas_textblock_cursor_content_get(cur), "<br/>"));
+ fail_if(!evas_textblock_cursor_format_is_visible_get(cur));
+ fail_if(!evas_textblock_cursor_char_next(cur));
+ fail_if(!evas_textblock_cursor_char_next(cur));
+ fail_if(strcmp(evas_textblock_node_format_text_get(
+ evas_textblock_cursor_format_get(cur)), "tab"));
+ fail_if(strcmp(evas_textblock_cursor_content_get(cur), "<tab/>"));
+ fail_if(!evas_textblock_cursor_format_is_visible_get(cur));
+ fail_if(!evas_textblock_cursor_char_next(cur));
+ fail_if(!evas_textblock_cursor_char_next(cur));
+ fail_if(strcmp(evas_textblock_node_format_text_get(
+ evas_textblock_cursor_format_get(cur)), "+ item"));
+ fail_if(strcmp(evas_textblock_cursor_content_get(cur), "<item>"));
+ fail_if(!evas_textblock_cursor_format_is_visible_get(cur));
+
+ END_TB_TEST();
+}
+END_TEST
+
+/* Different text styles, for example, shadow. */
+START_TEST(evas_textblock_style)
+{
+ Evas_Coord w, h, nw, nh;
+ Evas_Coord l, r, t, b;
+ START_TB_TEST();
+ Evas_Textblock_Style *newst;
+ const char *buf = "Test<ps/>Test2<ps/>נסיון";
+ evas_object_textblock_text_markup_set(tb, buf);
+ fail_if(strcmp(evas_object_textblock_text_markup_get(tb), buf));
+
+ evas_object_textblock_size_formatted_get(tb, &w, &h);
+ newst = evas_textblock_style_new();
+ fail_if(!newst);
+ evas_textblock_style_set(newst,
+ "DEFAULT='font=Sans font_size=20 color=#000 text_class=entry'"
+ "br='\n'"
+ "ps='ps'"
+ "tab='\t'");
+ evas_object_textblock_style_set(tb, newst);
+ evas_object_textblock_size_formatted_get(tb, &nw, &nh);
+ fail_if((w >= nw) || (h >= nh));
+
+ /* Style padding. */
+ evas_object_textblock_text_markup_set(tb, "Test");
+ evas_object_textblock_style_insets_get(tb, &l, &r, &t, &b);
+ fail_if((l != 0) || (r != 0) || (t != 0) || (b != 0));
+
+ evas_object_textblock_text_markup_set(tb, "<style=shadow>Test</>");
+ evas_object_textblock_style_insets_get(tb, &l, &r, &t, &b);
+ fail_if((l != 0) || (r != 1) || (t != 0) || (b != 1));
+
+ evas_object_textblock_text_markup_set(tb, "<style=outline>Test</>");
+ evas_object_textblock_style_insets_get(tb, &l, &r, &t, &b);
+ fail_if((l != 1) || (r != 1) || (t != 1) || (b != 1));
+
+ evas_object_textblock_text_markup_set(tb, "<style=soft_outline>Test</>");
+ evas_object_textblock_style_insets_get(tb, &l, &r, &t, &b);
+ fail_if((l != 2) || (r != 2) || (t != 2) || (b != 2));
+
+ evas_object_textblock_text_markup_set(tb, "<style=glow>Test</>");
+ evas_object_textblock_style_insets_get(tb, &l, &r, &t, &b);
+ fail_if((l != 2) || (r != 2) || (t != 2) || (b != 2));
+
+ evas_object_textblock_text_markup_set(tb, "<style=outline_shadow>Test</>");
+ evas_object_textblock_style_insets_get(tb, &l, &r, &t, &b);
+ fail_if((l != 1) || (r != 2) || (t != 1) || (b != 2));
+
+ evas_object_textblock_text_markup_set(tb, "<style=far_shadow>Test</>");
+ evas_object_textblock_style_insets_get(tb, &l, &r, &t, &b);
+ fail_if((l != 1) || (r != 2) || (t != 1) || (b != 2));
+
+ evas_object_textblock_text_markup_set(tb, "<style=outline_soft_shadow>Test</>");
+ evas_object_textblock_style_insets_get(tb, &l, &r, &t, &b);
+ fail_if((l != 1) || (r != 3) || (t != 1) || (b != 3));
+
+ evas_object_textblock_text_markup_set(tb, "<style=soft_shadow>Test</>");
+ evas_object_textblock_style_insets_get(tb, &l, &r, &t, &b);
+ fail_if((l != 1) || (r != 3) || (t != 1) || (b != 3));
+
+ evas_object_textblock_text_markup_set(tb, "<style=far_soft_shadow>Test</>");
+ evas_object_textblock_style_insets_get(tb, &l, &r, &t, &b);
+ fail_if((l != 0) || (r != 4) || (t != 0) || (b != 4));
+
+ /* Mixed style padding */
+ evas_object_textblock_text_markup_set(tb,
+ "<style=far_shadow>Test</><style=far_soft_shadow>Test</>");
+ evas_object_textblock_style_insets_get(tb, &l, &r, &t, &b);
+ fail_if((l != 1) || (r != 4) || (t != 1) || (b != 4));
+
+ END_TB_TEST();
+}
+END_TEST
+
+/* Various setters and getters */
+START_TEST(evas_textblock_set_get)
+{
+ START_TB_TEST();
+ const char *buf = "";
+ evas_object_textblock_text_markup_set(tb, buf);
+ fail_if(strcmp(evas_textblock_style_get(st), style_buf));
+ fail_if(evas_object_textblock_style_get(tb) != st);
+ evas_object_textblock_replace_char_set(tb, "|");
+ fail_if(strcmp(evas_object_textblock_replace_char_get(tb), "|"));
+ evas_object_textblock_replace_char_set(tb, "ש");
+ fail_if(strcmp(evas_object_textblock_replace_char_get(tb), "ש"));
+
+ evas_object_textblock_valign_set(tb, -1.0);
+ fail_if(evas_object_textblock_valign_get(tb) != 0.0);
+ evas_object_textblock_valign_set(tb, 0.0);
+ fail_if(evas_object_textblock_valign_get(tb) != 0.0);
+ evas_object_textblock_valign_set(tb, 0.432);
+ fail_if(evas_object_textblock_valign_get(tb) != 0.432);
+ evas_object_textblock_valign_set(tb, 1.0);
+ fail_if(evas_object_textblock_valign_get(tb) != 1.0);
+ evas_object_textblock_valign_set(tb, 1.5);
+ fail_if(evas_object_textblock_valign_get(tb) != 1.0);
+
+ evas_object_textblock_bidi_delimiters_set(tb, ",.|");
+ fail_if(strcmp(evas_object_textblock_bidi_delimiters_get(tb), ",.|"));
+ evas_object_textblock_bidi_delimiters_set(tb, ",|");
+ fail_if(strcmp(evas_object_textblock_bidi_delimiters_get(tb), ",|"));
+ evas_object_textblock_bidi_delimiters_set(tb, NULL);
+ fail_if(evas_object_textblock_bidi_delimiters_get(tb));
+ evas_object_textblock_bidi_delimiters_set(tb, ",|");
+ fail_if(strcmp(evas_object_textblock_bidi_delimiters_get(tb), ",|"));
+
+ /* Hinting */
+ evas_object_textblock_text_markup_set(tb, "This is<ps/>a test<br/>bla");
+ /* Force relayout */
+ evas_object_textblock_size_formatted_get(tb, NULL, NULL);
+ evas_font_hinting_set(evas, EVAS_FONT_HINTING_NONE);
+ evas_font_hinting_set(evas, EVAS_FONT_HINTING_AUTO);
+ evas_font_hinting_set(evas, EVAS_FONT_HINTING_BYTECODE);
+ END_TB_TEST();
+}
+END_TEST
+
+/* Aux evas stuff, such as scale. */
+START_TEST(evas_textblock_evas)
+{
+ Evas_Coord w, h, sw, sh;
+ START_TB_TEST();
+ const char *buf = "Test";
+ evas_object_textblock_text_markup_set(tb, buf);
+ evas_object_textblock_size_formatted_get(tb, &w, &h);
+ evas_object_scale_set(tb, 3.0);
+ evas_object_textblock_size_formatted_get(tb, &sw, &sh);
+ fail_if((sw <= w) || (sh <= h));
+
+ evas_object_scale_set(tb, 0.5);
+ evas_object_textblock_size_formatted_get(tb, &sw, &sh);
+ fail_if((sw >= w) || (sh >= h));
+
+ END_TB_TEST();
+}
+END_TEST
+
+/* All the string escaping stuff */
+START_TEST(evas_textblock_escaping)
+{
+ int len;
+ START_TB_TEST();
+ fail_if(strcmp(evas_textblock_escape_string_get("&amp;"), "&"));
+ fail_if(strcmp(evas_textblock_string_escape_get("&", &len), "&amp;"));
+ fail_if(len != 1);
+
+ fail_if(strcmp(evas_textblock_escape_string_get("&middot;"), "\xc2\xb7"));
+ fail_if(strcmp(evas_textblock_string_escape_get("\xc2\xb7", &len),
+ "&middot;"));
+ fail_if(len != 2);
+
+ fail_if(strcmp(evas_textblock_escape_string_get("&#x1f459;"),
+ "\xF0\x9F\x91\x99"));
+ fail_if(strcmp(evas_textblock_escape_string_get("&#128089;"),
+ "\xF0\x9F\x91\x99"));
+
+ fail_if(evas_textblock_escape_string_get("&middot;aa"));
+ const char *tmp = "&middot;aa";
+ fail_if(strcmp(evas_textblock_escape_string_range_get(tmp, tmp + 8),
+ "\xc2\xb7"));
+ fail_if(evas_textblock_escape_string_range_get(tmp, tmp + 9));
+ fail_if(evas_textblock_escape_string_range_get(tmp, tmp + 7));
+ fail_if(evas_textblock_escape_string_range_get(tmp, tmp + 5));
+
+ const char *buf = "This &middot; is";
+ evas_object_textblock_text_markup_set(tb, buf);
+ fail_if(strcmp(evas_object_textblock_text_markup_get(tb), buf));
+
+ buf = "This &nbsp; is";
+ evas_object_textblock_text_markup_set(tb, buf);
+ fail_if(strcmp(evas_object_textblock_text_markup_get(tb), buf));
+
+ END_TB_TEST();
+}
+END_TEST
+
+START_TEST(evas_textblock_size)
+{
+ START_TB_TEST();
+ Evas_Coord w, h, h2, nw, nh;
+ const char *buf = "This is a <br/> test.<br/>גם בעברית";
+ /* When wrapping is off, native size should be the same as formatted
+ * size */
+
+ evas_object_textblock_size_formatted_get(tb, &w, &h);
+ evas_object_textblock_size_native_get(tb, &nw, &nh);
+ fail_if((w != nw) || (h != nh));
+ fail_if(w != 0);
+
+ evas_object_textblock_text_markup_set(tb, "a<br/>a");
+ evas_object_textblock_size_formatted_get(tb, &w, &h2);
+ evas_object_textblock_size_native_get(tb, &nw, &nh);
+ fail_if((w != nw) || (h2 != nh));
+
+ /* Two lines == double the height */
+ fail_if(h * 2 != h2);
+
+ evas_object_textblock_text_markup_set(tb, buf);
+
+ evas_object_textblock_size_formatted_get(tb, &w, &h);
+ evas_object_textblock_size_native_get(tb, &nw, &nh);
+ fail_if((w != nw) || (h != nh));
+ fail_if(w <= 0);
+
+ /* This time with margins. */
+ {
+ Evas_Textblock_Style *newst;
+ Evas_Coord oldw, oldh, oldnw, oldnh;
+
+ evas_object_textblock_text_markup_set(tb, buf);
+ evas_object_textblock_size_formatted_get(tb, &oldw, &oldh);
+ evas_object_textblock_size_native_get(tb, &oldnw, &oldnh);
+
+
+ newst = evas_textblock_style_new();
+ fail_if(!newst);
+ evas_textblock_style_set(newst,
+ "DEFAULT='left_margin=4 right_margin=4'");
+ evas_object_textblock_style_user_push(tb, newst);
+
+ evas_object_textblock_size_formatted_get(tb, &w, &h);
+ evas_object_textblock_size_native_get(tb, &nw, &nh);
+
+ fail_if((w != oldw + 8) || (h != oldh) ||
+ (nw != oldnw + 8) || (nh != oldnh));
+ }
+
+ /* FIXME: There is a lot more to be done. */
+ END_TB_TEST();
+}
+END_TEST
+
+void evas_test_textblock(TCase *tc)
+{
+ tcase_add_test(tc, evas_textblock_simple);
+ tcase_add_test(tc, evas_textblock_cursor);
+ tcase_add_test(tc, evas_textblock_size);
+ tcase_add_test(tc, evas_textblock_editing);
+ tcase_add_test(tc, evas_textblock_style);
+ tcase_add_test(tc, evas_textblock_evas);
+ tcase_add_test(tc, evas_textblock_text_getters);
+ tcase_add_test(tc, evas_textblock_formats);
+ tcase_add_test(tc, evas_textblock_format_removal);
+ tcase_add_test(tc, evas_textblock_escaping);
+ tcase_add_test(tc, evas_textblock_set_get);
+ tcase_add_test(tc, evas_textblock_geometries);
+ tcase_add_test(tc, evas_textblock_various);
+ tcase_add_test(tc, evas_textblock_wrapping);
+ tcase_add_test(tc, evas_textblock_items);
+}
+
diff --git a/src/tests/evas/evas_tests_helpers.h b/src/tests/evas/evas_tests_helpers.h
new file mode 100644
index 0000000000..2ed07894f4
--- /dev/null
+++ b/src/tests/evas/evas_tests_helpers.h
@@ -0,0 +1,40 @@
+#ifndef EVAS_TEST_HELPERS_H
+#define EVAS_TEST_HELPERS_H
+
+/* FIXME: Currently depends on the buffer engine, should we do anything
+ * fancier? */
+
+#define EVAS_TEST_INIT_EVAS() _setup_evas()
+
+#define EVAS_TEST_FREE_EVAS() \
+do \
+{ \
+ evas_textblock_cursor_free(cur); \
+ evas_object_del(tb); \
+ evas_textblock_style_free(st); \
+ evas_free(evas); \
+ evas_shutdown(); \
+} \
+while (0)
+
+static Evas *
+_setup_evas()
+{
+ Evas *evas;
+ Evas_Engine_Info *einfo;
+
+ evas_init();
+ evas = evas_new();
+
+ evas_output_method_set(evas, evas_render_method_lookup("buffer"));
+ einfo = evas_engine_info_get(evas);
+ evas_engine_info_set(evas, einfo);
+
+ evas_output_size_set(evas, 500, 500);
+ evas_output_viewport_set(evas, 0, 0, 500, 500);
+
+ return evas;
+}
+
+#endif
+