aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/evas/src/lib/canvas
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/evas/src/lib/canvas')
-rw-r--r--libraries/evas/src/lib/canvas/Makefile.am67
-rw-r--r--libraries/evas/src/lib/canvas/Makefile.in763
-rw-r--r--libraries/evas/src/lib/canvas/evas_async_events.c173
-rw-r--r--libraries/evas/src/lib/canvas/evas_callbacks.c543
-rw-r--r--libraries/evas/src/lib/canvas/evas_clip.c321
-rw-r--r--libraries/evas/src/lib/canvas/evas_data.c72
-rw-r--r--libraries/evas/src/lib/canvas/evas_events.c1867
-rw-r--r--libraries/evas/src/lib/canvas/evas_filter.c1427
-rw-r--r--libraries/evas/src/lib/canvas/evas_focus.c61
-rw-r--r--libraries/evas/src/lib/canvas/evas_font_dir.c1349
-rw-r--r--libraries/evas/src/lib/canvas/evas_gl.c272
-rw-r--r--libraries/evas/src/lib/canvas/evas_key.c245
-rw-r--r--libraries/evas/src/lib/canvas/evas_key_grab.c179
-rw-r--r--libraries/evas/src/lib/canvas/evas_layer.c193
-rw-r--r--libraries/evas/src/lib/canvas/evas_main.c710
-rw-r--r--libraries/evas/src/lib/canvas/evas_map.c1037
-rw-r--r--libraries/evas/src/lib/canvas/evas_name.c72
-rw-r--r--libraries/evas/src/lib/canvas/evas_object_box.c2127
-rw-r--r--libraries/evas/src/lib/canvas/evas_object_grid.c465
-rw-r--r--libraries/evas/src/lib/canvas/evas_object_image.c3957
-rw-r--r--libraries/evas/src/lib/canvas/evas_object_inform.c79
-rw-r--r--libraries/evas/src/lib/canvas/evas_object_intercept.c585
-rw-r--r--libraries/evas/src/lib/canvas/evas_object_line.c461
-rw-r--r--libraries/evas/src/lib/canvas/evas_object_main.c1398
-rw-r--r--libraries/evas/src/lib/canvas/evas_object_polygon.c554
-rw-r--r--libraries/evas/src/lib/canvas/evas_object_rectangle.c387
-rw-r--r--libraries/evas/src/lib/canvas/evas_object_smart.c951
-rw-r--r--libraries/evas/src/lib/canvas/evas_object_smart_clipped.c183
-rw-r--r--libraries/evas/src/lib/canvas/evas_object_table.c1373
-rw-r--r--libraries/evas/src/lib/canvas/evas_object_text.c1943
-rw-r--r--libraries/evas/src/lib/canvas/evas_object_textblock.c10052
-rw-r--r--libraries/evas/src/lib/canvas/evas_rectangle.c98
-rw-r--r--libraries/evas/src/lib/canvas/evas_render.c1914
-rw-r--r--libraries/evas/src/lib/canvas/evas_smart.c266
-rw-r--r--libraries/evas/src/lib/canvas/evas_stack.c391
-rw-r--r--libraries/evas/src/lib/canvas/evas_stats.c185
-rw-r--r--libraries/evas/src/lib/canvas/evas_touch_point.c110
37 files changed, 0 insertions, 36830 deletions
diff --git a/libraries/evas/src/lib/canvas/Makefile.am b/libraries/evas/src/lib/canvas/Makefile.am
deleted file mode 100644
index e302668..0000000
--- a/libraries/evas/src/lib/canvas/Makefile.am
+++ /dev/null
@@ -1,67 +0,0 @@
1MAINTAINERCLEANFILES = Makefile.in
2
3AM_CPPFLAGS = \
4-I. \
5-I$(top_srcdir)/src/lib \
6-I$(top_srcdir)/src/lib/include \
7-I$(top_srcdir)/src/lib/cserve \
8-DPACKAGE_BIN_DIR=\"$(bindir)\" \
9-DPACKAGE_LIB_DIR=\"$(libdir)\" \
10-DPACKAGE_DATA_DIR=\"$(datadir)/$(PACKAGE)\" \
11@FREETYPE_CFLAGS@ \
12@EET_CFLAGS@ \
13@FONTCONFIG_CFLAGS@ \
14@EVAS_CFLAGS@ \
15@EINA_CFLAGS@ \
16@EVIL_CFLAGS@ \
17@PIXMAN_CFLAGS@
18
19noinst_LTLIBRARIES = libevas_canvas.la
20libevas_canvas_la_SOURCES = \
21evas_callbacks.c \
22evas_clip.c \
23evas_data.c \
24evas_events.c \
25evas_filter.c \
26evas_focus.c \
27evas_key.c \
28evas_key_grab.c \
29evas_layer.c \
30evas_main.c \
31evas_name.c \
32evas_object_image.c \
33evas_object_main.c \
34evas_object_inform.c \
35evas_object_intercept.c \
36evas_object_line.c \
37evas_object_polygon.c \
38evas_object_rectangle.c \
39evas_object_smart.c \
40evas_object_smart_clipped.c \
41evas_object_box.c \
42evas_object_table.c \
43evas_object_text.c \
44evas_object_textblock.c \
45evas_object_grid.c \
46evas_font_dir.c \
47evas_rectangle.c \
48evas_render.c \
49evas_smart.c \
50evas_stack.c \
51evas_async_events.c \
52evas_stats.c \
53evas_touch_point.c \
54evas_map.c \
55evas_gl.c
56
57#evas_object_textgrid.c
58
59libevas_canvas_la_LIBADD = @EVAS_LIBS@ @EVIL_LIBS@
60
61if EVAS_USE_LINEBREAK
62AM_CPPFLAGS += @LINEBREAK_CFLAGS@
63libevas_canvas_la_LIBADD += @LINEBREAK_LIBS@
64endif
65
66clean-local:
67 rm -rf *.gcno
diff --git a/libraries/evas/src/lib/canvas/Makefile.in b/libraries/evas/src/lib/canvas/Makefile.in
deleted file mode 100644
index c7e48bc..0000000
--- a/libraries/evas/src/lib/canvas/Makefile.in
+++ /dev/null
@@ -1,763 +0,0 @@
1# Makefile.in generated by automake 1.11.1 from Makefile.am.
2# @configure_input@
3
4# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
5# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
6# Inc.
7# This Makefile.in is free software; the Free Software Foundation
8# gives unlimited permission to copy and/or distribute it,
9# with or without modifications, as long as this notice is preserved.
10
11# This program is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
13# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
14# PARTICULAR PURPOSE.
15
16@SET_MAKE@
17
18VPATH = @srcdir@
19pkgdatadir = $(datadir)/@PACKAGE@
20pkgincludedir = $(includedir)/@PACKAGE@
21pkglibdir = $(libdir)/@PACKAGE@
22pkglibexecdir = $(libexecdir)/@PACKAGE@
23am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
24install_sh_DATA = $(install_sh) -c -m 644
25install_sh_PROGRAM = $(install_sh) -c
26install_sh_SCRIPT = $(install_sh) -c
27INSTALL_HEADER = $(INSTALL_DATA)
28transform = $(program_transform_name)
29NORMAL_INSTALL = :
30PRE_INSTALL = :
31POST_INSTALL = :
32NORMAL_UNINSTALL = :
33PRE_UNINSTALL = :
34POST_UNINSTALL = :
35build_triplet = @build@
36host_triplet = @host@
37@EVAS_USE_LINEBREAK_TRUE@am__append_1 = @LINEBREAK_CFLAGS@
38@EVAS_USE_LINEBREAK_TRUE@am__append_2 = @LINEBREAK_LIBS@
39subdir = src/lib/canvas
40DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
41ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
42am__aclocal_m4_deps = $(top_srcdir)/m4/efl_attribute.m4 \
43 $(top_srcdir)/m4/efl_coverage.m4 \
44 $(top_srcdir)/m4/efl_doxygen.m4 \
45 $(top_srcdir)/m4/efl_fnmatch.m4 \
46 $(top_srcdir)/m4/efl_path_max.m4 $(top_srcdir)/m4/efl_tests.m4 \
47 $(top_srcdir)/m4/evas_check_engine.m4 \
48 $(top_srcdir)/m4/evas_check_loader.m4 \
49 $(top_srcdir)/m4/evas_converter.m4 \
50 $(top_srcdir)/m4/evas_dither.m4 \
51 $(top_srcdir)/m4/evas_scaler.m4 $(top_srcdir)/m4/libtool.m4 \
52 $(top_srcdir)/m4/ltoptions.m4 $(top_srcdir)/m4/ltsugar.m4 \
53 $(top_srcdir)/m4/ltversion.m4 $(top_srcdir)/m4/lt~obsolete.m4 \
54 $(top_srcdir)/configure.ac
55am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
56 $(ACLOCAL_M4)
57mkinstalldirs = $(install_sh) -d
58CONFIG_HEADER = $(top_builddir)/config.h
59CONFIG_CLEAN_FILES =
60CONFIG_CLEAN_VPATH_FILES =
61LTLIBRARIES = $(noinst_LTLIBRARIES)
62am__DEPENDENCIES_1 =
63libevas_canvas_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
64am_libevas_canvas_la_OBJECTS = evas_callbacks.lo evas_clip.lo \
65 evas_data.lo evas_events.lo evas_filter.lo evas_focus.lo \
66 evas_key.lo evas_key_grab.lo evas_layer.lo evas_main.lo \
67 evas_name.lo evas_object_image.lo evas_object_main.lo \
68 evas_object_inform.lo evas_object_intercept.lo \
69 evas_object_line.lo evas_object_polygon.lo \
70 evas_object_rectangle.lo evas_object_smart.lo \
71 evas_object_smart_clipped.lo evas_object_box.lo \
72 evas_object_table.lo evas_object_text.lo \
73 evas_object_textblock.lo evas_object_grid.lo evas_font_dir.lo \
74 evas_rectangle.lo evas_render.lo evas_smart.lo evas_stack.lo \
75 evas_async_events.lo evas_stats.lo evas_touch_point.lo \
76 evas_map.lo evas_gl.lo
77libevas_canvas_la_OBJECTS = $(am_libevas_canvas_la_OBJECTS)
78AM_V_lt = $(am__v_lt_$(V))
79am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY))
80am__v_lt_0 = --silent
81DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
82depcomp = $(SHELL) $(top_srcdir)/depcomp
83am__depfiles_maybe = depfiles
84am__mv = mv -f
85COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
86 $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
87LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
88 $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
89 $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
90 $(AM_CFLAGS) $(CFLAGS)
91AM_V_CC = $(am__v_CC_$(V))
92am__v_CC_ = $(am__v_CC_$(AM_DEFAULT_VERBOSITY))
93am__v_CC_0 = @echo " CC " $@;
94AM_V_at = $(am__v_at_$(V))
95am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY))
96am__v_at_0 = @
97CCLD = $(CC)
98LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
99 $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
100 $(AM_LDFLAGS) $(LDFLAGS) -o $@
101AM_V_CCLD = $(am__v_CCLD_$(V))
102am__v_CCLD_ = $(am__v_CCLD_$(AM_DEFAULT_VERBOSITY))
103am__v_CCLD_0 = @echo " CCLD " $@;
104AM_V_GEN = $(am__v_GEN_$(V))
105am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY))
106am__v_GEN_0 = @echo " GEN " $@;
107SOURCES = $(libevas_canvas_la_SOURCES)
108DIST_SOURCES = $(libevas_canvas_la_SOURCES)
109ETAGS = etags
110CTAGS = ctags
111DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
112ACLOCAL = @ACLOCAL@
113ALLOCA = @ALLOCA@
114AMTAR = @AMTAR@
115AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
116AR = @AR@
117AS = @AS@
118AUTOCONF = @AUTOCONF@
119AUTOHEADER = @AUTOHEADER@
120AUTOMAKE = @AUTOMAKE@
121AWK = @AWK@
122CC = @CC@
123CCDEPMODE = @CCDEPMODE@
124CFLAGS = @CFLAGS@
125CHECK_CFLAGS = @CHECK_CFLAGS@
126CHECK_LIBS = @CHECK_LIBS@
127CPP = @CPP@
128CPPFLAGS = @CPPFLAGS@
129CXX = @CXX@
130CXXCPP = @CXXCPP@
131CXXDEPMODE = @CXXDEPMODE@
132CXXFLAGS = @CXXFLAGS@
133CYGPATH_W = @CYGPATH_W@
134DEFS = @DEFS@
135DEPDIR = @DEPDIR@
136DIRECTFB_CFLAGS = @DIRECTFB_CFLAGS@
137DIRECTFB_LIBS = @DIRECTFB_LIBS@
138DLLTOOL = @DLLTOOL@
139DSYMUTIL = @DSYMUTIL@
140DUMPBIN = @DUMPBIN@
141ECHO_C = @ECHO_C@
142ECHO_N = @ECHO_N@
143ECHO_T = @ECHO_T@
144ECORE_EVAS_CFLAGS = @ECORE_EVAS_CFLAGS@
145ECORE_EVAS_LIBS = @ECORE_EVAS_LIBS@
146EDB_CFLAGS = @EDB_CFLAGS@
147EDB_LIBS = @EDB_LIBS@
148EDJE_CFLAGS = @EDJE_CFLAGS@
149EDJE_LIBS = @EDJE_LIBS@
150EET_CFLAGS = @EET_CFLAGS@
151EET_LIBS = @EET_LIBS@
152EFL_COVERAGE_CFLAGS = @EFL_COVERAGE_CFLAGS@
153EFL_COVERAGE_LIBS = @EFL_COVERAGE_LIBS@
154EFL_FNMATCH_LIBS = @EFL_FNMATCH_LIBS@
155EGREP = @EGREP@
156EINA_CFLAGS = @EINA_CFLAGS@
157EINA_LIBS = @EINA_LIBS@
158EVAS_CFLAGS = @EVAS_CFLAGS@
159EVAS_LIBS = @EVAS_LIBS@
160EVAS_SSE3_CFLAGS = @EVAS_SSE3_CFLAGS@
161EVIL_CFLAGS = @EVIL_CFLAGS@
162EVIL_LIBS = @EVIL_LIBS@
163EXEEXT = @EXEEXT@
164EXOTIC_CFLAGS = @EXOTIC_CFLAGS@
165EXOTIC_LIBS = @EXOTIC_LIBS@
166FGREP = @FGREP@
167FONTCONFIG_CFLAGS = @FONTCONFIG_CFLAGS@
168FONTCONFIG_LIBS = @FONTCONFIG_LIBS@
169FREETYPE_CFLAGS = @FREETYPE_CFLAGS@
170FREETYPE_LIBS = @FREETYPE_LIBS@
171FRIBIDI_CFLAGS = @FRIBIDI_CFLAGS@
172FRIBIDI_LIBS = @FRIBIDI_LIBS@
173GL_EET_CFLAGS = @GL_EET_CFLAGS@
174GL_EET_LIBS = @GL_EET_LIBS@
175GREP = @GREP@
176HARFBUZZ_CFLAGS = @HARFBUZZ_CFLAGS@
177HARFBUZZ_LIBS = @HARFBUZZ_LIBS@
178INSTALL = @INSTALL@
179INSTALL_DATA = @INSTALL_DATA@
180INSTALL_PROGRAM = @INSTALL_PROGRAM@
181INSTALL_SCRIPT = @INSTALL_SCRIPT@
182INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
183LD = @LD@
184LDFLAGS = @LDFLAGS@
185LIBOBJS = @LIBOBJS@
186LIBS = @LIBS@
187LIBTOOL = @LIBTOOL@
188LINEBREAK_CFLAGS = @LINEBREAK_CFLAGS@
189LINEBREAK_LIBS = @LINEBREAK_LIBS@
190LIPO = @LIPO@
191LN_S = @LN_S@
192LTLIBOBJS = @LTLIBOBJS@
193MAKEINFO = @MAKEINFO@
194MKDIR_P = @MKDIR_P@
195MODULE_ARCH = @MODULE_ARCH@
196NM = @NM@
197NMEDIT = @NMEDIT@
198OBJC = @OBJC@
199OBJCDEPMODE = @OBJCDEPMODE@
200OBJCFLAGS = @OBJCFLAGS@
201OBJDUMP = @OBJDUMP@
202OBJEXT = @OBJEXT@
203OTOOL = @OTOOL@
204OTOOL64 = @OTOOL64@
205PACKAGE = @PACKAGE@
206PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
207PACKAGE_NAME = @PACKAGE_NAME@
208PACKAGE_STRING = @PACKAGE_STRING@
209PACKAGE_TARNAME = @PACKAGE_TARNAME@
210PACKAGE_URL = @PACKAGE_URL@
211PACKAGE_VERSION = @PACKAGE_VERSION@
212PATH_SEPARATOR = @PATH_SEPARATOR@
213PIXMAN_CFLAGS = @PIXMAN_CFLAGS@
214PIXMAN_LIBS = @PIXMAN_LIBS@
215PKG_CONFIG = @PKG_CONFIG@
216PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
217PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
218PNG_CFLAGS = @PNG_CFLAGS@
219PNG_LIBS = @PNG_LIBS@
220RANLIB = @RANLIB@
221SDL_CFLAGS = @SDL_CFLAGS@
222SDL_LIBS = @SDL_LIBS@
223SED = @SED@
224SET_MAKE = @SET_MAKE@
225SHELL = @SHELL@
226SHM_OPEN_LINK = @SHM_OPEN_LINK@
227STRIP = @STRIP@
228SVG_CFLAGS = @SVG_CFLAGS@
229SVG_LIBS = @SVG_LIBS@
230VALGRIND_CFLAGS = @VALGRIND_CFLAGS@
231VALGRIND_LIBS = @VALGRIND_LIBS@
232VERSION = @VERSION@
233VMAJ = @VMAJ@
234WAYLAND_EGL_CFLAGS = @WAYLAND_EGL_CFLAGS@
235WAYLAND_EGL_LIBS = @WAYLAND_EGL_LIBS@
236XCB_CFLAGS = @XCB_CFLAGS@
237XCB_GL_CFLAGS = @XCB_GL_CFLAGS@
238XCB_GL_LIBS = @XCB_GL_LIBS@
239XCB_LIBS = @XCB_LIBS@
240XEXT_CFLAGS = @XEXT_CFLAGS@
241XEXT_LIBS = @XEXT_LIBS@
242XMKMF = @XMKMF@
243X_CFLAGS = @X_CFLAGS@
244X_EXTRA_LIBS = @X_EXTRA_LIBS@
245X_LIBS = @X_LIBS@
246X_PRE_LIBS = @X_PRE_LIBS@
247abs_builddir = @abs_builddir@
248abs_srcdir = @abs_srcdir@
249abs_top_builddir = @abs_top_builddir@
250abs_top_srcdir = @abs_top_srcdir@
251ac_ct_CC = @ac_ct_CC@
252ac_ct_CXX = @ac_ct_CXX@
253ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
254ac_ct_OBJC = @ac_ct_OBJC@
255altivec_cflags = @altivec_cflags@
256am__include = @am__include@
257am__leading_dot = @am__leading_dot@
258am__quote = @am__quote@
259am__tar = @am__tar@
260am__untar = @am__untar@
261bindir = @bindir@
262build = @build@
263build_alias = @build_alias@
264build_cpu = @build_cpu@
265build_os = @build_os@
266build_vendor = @build_vendor@
267builddir = @builddir@
268datadir = @datadir@
269datarootdir = @datarootdir@
270dlopen_libs = @dlopen_libs@
271docdir = @docdir@
272dvidir = @dvidir@
273edje_cc = @edje_cc@
274efl_doxygen = @efl_doxygen@
275efl_have_doxygen = @efl_have_doxygen@
276evas_engine_buffer_cflags = @evas_engine_buffer_cflags@
277evas_engine_buffer_libs = @evas_engine_buffer_libs@
278evas_engine_direct3d_cflags = @evas_engine_direct3d_cflags@
279evas_engine_direct3d_libs = @evas_engine_direct3d_libs@
280evas_engine_directfb_cflags = @evas_engine_directfb_cflags@
281evas_engine_directfb_libs = @evas_engine_directfb_libs@
282evas_engine_fb_cflags = @evas_engine_fb_cflags@
283evas_engine_fb_libs = @evas_engine_fb_libs@
284evas_engine_gl_cocoa_cflags = @evas_engine_gl_cocoa_cflags@
285evas_engine_gl_cocoa_libs = @evas_engine_gl_cocoa_libs@
286evas_engine_gl_common_libs = @evas_engine_gl_common_libs@
287evas_engine_gl_sdl_cflags = @evas_engine_gl_sdl_cflags@
288evas_engine_gl_sdl_libs = @evas_engine_gl_sdl_libs@
289evas_engine_gl_xcb_cflags = @evas_engine_gl_xcb_cflags@
290evas_engine_gl_xcb_libs = @evas_engine_gl_xcb_libs@
291evas_engine_gl_xlib_cflags = @evas_engine_gl_xlib_cflags@
292evas_engine_gl_xlib_libs = @evas_engine_gl_xlib_libs@
293evas_engine_psl1ght_cflags = @evas_engine_psl1ght_cflags@
294evas_engine_psl1ght_libs = @evas_engine_psl1ght_libs@
295evas_engine_software_16_ddraw_cflags = @evas_engine_software_16_ddraw_cflags@
296evas_engine_software_16_ddraw_libs = @evas_engine_software_16_ddraw_libs@
297evas_engine_software_16_sdl_cflags = @evas_engine_software_16_sdl_cflags@
298evas_engine_software_16_sdl_libs = @evas_engine_software_16_sdl_libs@
299evas_engine_software_16_wince_cflags = @evas_engine_software_16_wince_cflags@
300evas_engine_software_16_wince_libs = @evas_engine_software_16_wince_libs@
301evas_engine_software_16_x11_cflags = @evas_engine_software_16_x11_cflags@
302evas_engine_software_16_x11_libs = @evas_engine_software_16_x11_libs@
303evas_engine_software_8_x11_cflags = @evas_engine_software_8_x11_cflags@
304evas_engine_software_8_x11_libs = @evas_engine_software_8_x11_libs@
305evas_engine_software_ddraw_cflags = @evas_engine_software_ddraw_cflags@
306evas_engine_software_ddraw_libs = @evas_engine_software_ddraw_libs@
307evas_engine_software_gdi_cflags = @evas_engine_software_gdi_cflags@
308evas_engine_software_gdi_libs = @evas_engine_software_gdi_libs@
309evas_engine_software_xcb_cflags = @evas_engine_software_xcb_cflags@
310evas_engine_software_xcb_libs = @evas_engine_software_xcb_libs@
311evas_engine_software_xlib_cflags = @evas_engine_software_xlib_cflags@
312evas_engine_software_xlib_libs = @evas_engine_software_xlib_libs@
313evas_engine_wayland_egl_cflags = @evas_engine_wayland_egl_cflags@
314evas_engine_wayland_egl_libs = @evas_engine_wayland_egl_libs@
315evas_engine_wayland_shm_cflags = @evas_engine_wayland_shm_cflags@
316evas_engine_wayland_shm_libs = @evas_engine_wayland_shm_libs@
317evas_image_loader_bmp_cflags = @evas_image_loader_bmp_cflags@
318evas_image_loader_bmp_libs = @evas_image_loader_bmp_libs@
319evas_image_loader_edb_cflags = @evas_image_loader_edb_cflags@
320evas_image_loader_edb_libs = @evas_image_loader_edb_libs@
321evas_image_loader_eet_cflags = @evas_image_loader_eet_cflags@
322evas_image_loader_eet_libs = @evas_image_loader_eet_libs@
323evas_image_loader_generic_cflags = @evas_image_loader_generic_cflags@
324evas_image_loader_generic_libs = @evas_image_loader_generic_libs@
325evas_image_loader_gif_cflags = @evas_image_loader_gif_cflags@
326evas_image_loader_gif_libs = @evas_image_loader_gif_libs@
327evas_image_loader_ico_cflags = @evas_image_loader_ico_cflags@
328evas_image_loader_ico_libs = @evas_image_loader_ico_libs@
329evas_image_loader_jpeg_cflags = @evas_image_loader_jpeg_cflags@
330evas_image_loader_jpeg_libs = @evas_image_loader_jpeg_libs@
331evas_image_loader_pmaps_cflags = @evas_image_loader_pmaps_cflags@
332evas_image_loader_pmaps_libs = @evas_image_loader_pmaps_libs@
333evas_image_loader_png_cflags = @evas_image_loader_png_cflags@
334evas_image_loader_png_libs = @evas_image_loader_png_libs@
335evas_image_loader_psd_cflags = @evas_image_loader_psd_cflags@
336evas_image_loader_psd_libs = @evas_image_loader_psd_libs@
337evas_image_loader_svg_cflags = @evas_image_loader_svg_cflags@
338evas_image_loader_svg_libs = @evas_image_loader_svg_libs@
339evas_image_loader_tga_cflags = @evas_image_loader_tga_cflags@
340evas_image_loader_tga_libs = @evas_image_loader_tga_libs@
341evas_image_loader_tiff_cflags = @evas_image_loader_tiff_cflags@
342evas_image_loader_tiff_libs = @evas_image_loader_tiff_libs@
343evas_image_loader_wbmp_cflags = @evas_image_loader_wbmp_cflags@
344evas_image_loader_wbmp_libs = @evas_image_loader_wbmp_libs@
345evas_image_loader_xpm_cflags = @evas_image_loader_xpm_cflags@
346evas_image_loader_xpm_libs = @evas_image_loader_xpm_libs@
347exec_prefix = @exec_prefix@
348have_evas_engine_gl_x11 = @have_evas_engine_gl_x11@
349have_evas_engine_gl_xcb = @have_evas_engine_gl_xcb@
350have_evas_engine_gl_xlib = @have_evas_engine_gl_xlib@
351have_evas_engine_software_x11 = @have_evas_engine_software_x11@
352have_evas_engine_software_xcb = @have_evas_engine_software_xcb@
353have_evas_engine_software_xlib = @have_evas_engine_software_xlib@
354have_lcov = @have_lcov@
355host = @host@
356host_alias = @host_alias@
357host_cpu = @host_cpu@
358host_os = @host_os@
359host_vendor = @host_vendor@
360htmldir = @htmldir@
361includedir = @includedir@
362infodir = @infodir@
363install_sh = @install_sh@
364libdir = @libdir@
365libexecdir = @libexecdir@
366localedir = @localedir@
367localstatedir = @localstatedir@
368lt_ECHO = @lt_ECHO@
369lt_enable_auto_import = @lt_enable_auto_import@
370mandir = @mandir@
371mkdir_p = @mkdir_p@
372oldincludedir = @oldincludedir@
373pdfdir = @pdfdir@
374pkgconfig_requires_private = @pkgconfig_requires_private@
375prefix = @prefix@
376program_transform_name = @program_transform_name@
377psdir = @psdir@
378pthread_cflags = @pthread_cflags@
379pthread_libs = @pthread_libs@
380release_info = @release_info@
381requirement_evas = @requirement_evas@
382sbindir = @sbindir@
383sharedstatedir = @sharedstatedir@
384srcdir = @srcdir@
385sysconfdir = @sysconfdir@
386target_alias = @target_alias@
387top_build_prefix = @top_build_prefix@
388top_builddir = @top_builddir@
389top_srcdir = @top_srcdir@
390version_info = @version_info@
391MAINTAINERCLEANFILES = Makefile.in
392AM_CPPFLAGS = -I. -I$(top_srcdir)/src/lib \
393 -I$(top_srcdir)/src/lib/include -I$(top_srcdir)/src/lib/cserve \
394 -DPACKAGE_BIN_DIR=\"$(bindir)\" \
395 -DPACKAGE_LIB_DIR=\"$(libdir)\" \
396 -DPACKAGE_DATA_DIR=\"$(datadir)/$(PACKAGE)\" @FREETYPE_CFLAGS@ \
397 @EET_CFLAGS@ @FONTCONFIG_CFLAGS@ @EVAS_CFLAGS@ @EINA_CFLAGS@ \
398 @EVIL_CFLAGS@ @PIXMAN_CFLAGS@ $(am__append_1)
399noinst_LTLIBRARIES = libevas_canvas.la
400libevas_canvas_la_SOURCES = \
401evas_callbacks.c \
402evas_clip.c \
403evas_data.c \
404evas_events.c \
405evas_filter.c \
406evas_focus.c \
407evas_key.c \
408evas_key_grab.c \
409evas_layer.c \
410evas_main.c \
411evas_name.c \
412evas_object_image.c \
413evas_object_main.c \
414evas_object_inform.c \
415evas_object_intercept.c \
416evas_object_line.c \
417evas_object_polygon.c \
418evas_object_rectangle.c \
419evas_object_smart.c \
420evas_object_smart_clipped.c \
421evas_object_box.c \
422evas_object_table.c \
423evas_object_text.c \
424evas_object_textblock.c \
425evas_object_grid.c \
426evas_font_dir.c \
427evas_rectangle.c \
428evas_render.c \
429evas_smart.c \
430evas_stack.c \
431evas_async_events.c \
432evas_stats.c \
433evas_touch_point.c \
434evas_map.c \
435evas_gl.c
436
437
438#evas_object_textgrid.c
439libevas_canvas_la_LIBADD = @EVAS_LIBS@ @EVIL_LIBS@ $(am__append_2)
440all: all-am
441
442.SUFFIXES:
443.SUFFIXES: .c .lo .o .obj
444$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
445 @for dep in $?; do \
446 case '$(am__configure_deps)' in \
447 *$$dep*) \
448 ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
449 && { if test -f $@; then exit 0; else break; fi; }; \
450 exit 1;; \
451 esac; \
452 done; \
453 echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/lib/canvas/Makefile'; \
454 $(am__cd) $(top_srcdir) && \
455 $(AUTOMAKE) --gnu src/lib/canvas/Makefile
456.PRECIOUS: Makefile
457Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
458 @case '$?' in \
459 *config.status*) \
460 cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
461 *) \
462 echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
463 cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
464 esac;
465
466$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
467 cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
468
469$(top_srcdir)/configure: $(am__configure_deps)
470 cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
471$(ACLOCAL_M4): $(am__aclocal_m4_deps)
472 cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
473$(am__aclocal_m4_deps):
474
475clean-noinstLTLIBRARIES:
476 -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
477 @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
478 dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
479 test "$$dir" != "$$p" || dir=.; \
480 echo "rm -f \"$${dir}/so_locations\""; \
481 rm -f "$${dir}/so_locations"; \
482 done
483libevas_canvas.la: $(libevas_canvas_la_OBJECTS) $(libevas_canvas_la_DEPENDENCIES)
484 $(AM_V_CCLD)$(LINK) $(libevas_canvas_la_OBJECTS) $(libevas_canvas_la_LIBADD) $(LIBS)
485
486mostlyclean-compile:
487 -rm -f *.$(OBJEXT)
488
489distclean-compile:
490 -rm -f *.tab.c
491
492@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/evas_async_events.Plo@am__quote@
493@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/evas_callbacks.Plo@am__quote@
494@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/evas_clip.Plo@am__quote@
495@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/evas_data.Plo@am__quote@
496@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/evas_events.Plo@am__quote@
497@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/evas_filter.Plo@am__quote@
498@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/evas_focus.Plo@am__quote@
499@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/evas_font_dir.Plo@am__quote@
500@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/evas_gl.Plo@am__quote@
501@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/evas_key.Plo@am__quote@
502@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/evas_key_grab.Plo@am__quote@
503@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/evas_layer.Plo@am__quote@
504@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/evas_main.Plo@am__quote@
505@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/evas_map.Plo@am__quote@
506@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/evas_name.Plo@am__quote@
507@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/evas_object_box.Plo@am__quote@
508@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/evas_object_grid.Plo@am__quote@
509@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/evas_object_image.Plo@am__quote@
510@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/evas_object_inform.Plo@am__quote@
511@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/evas_object_intercept.Plo@am__quote@
512@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/evas_object_line.Plo@am__quote@
513@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/evas_object_main.Plo@am__quote@
514@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/evas_object_polygon.Plo@am__quote@
515@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/evas_object_rectangle.Plo@am__quote@
516@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/evas_object_smart.Plo@am__quote@
517@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/evas_object_smart_clipped.Plo@am__quote@
518@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/evas_object_table.Plo@am__quote@
519@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/evas_object_text.Plo@am__quote@
520@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/evas_object_textblock.Plo@am__quote@
521@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/evas_rectangle.Plo@am__quote@
522@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/evas_render.Plo@am__quote@
523@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/evas_smart.Plo@am__quote@
524@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/evas_stack.Plo@am__quote@
525@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/evas_stats.Plo@am__quote@
526@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/evas_touch_point.Plo@am__quote@
527
528.c.o:
529@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
530@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
531@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
532@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
533@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
534@am__fastdepCC_FALSE@ $(COMPILE) -c $<
535
536.c.obj:
537@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
538@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
539@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
540@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
541@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
542@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
543
544.c.lo:
545@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
546@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
547@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@
548@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
549@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
550@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
551
552mostlyclean-libtool:
553 -rm -f *.lo
554
555clean-libtool:
556 -rm -rf .libs _libs
557
558ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
559 list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
560 unique=`for i in $$list; do \
561 if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
562 done | \
563 $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
564 END { if (nonempty) { for (i in files) print i; }; }'`; \
565 mkid -fID $$unique
566tags: TAGS
567
568TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
569 $(TAGS_FILES) $(LISP)
570 set x; \
571 here=`pwd`; \
572 list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
573 unique=`for i in $$list; do \
574 if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
575 done | \
576 $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
577 END { if (nonempty) { for (i in files) print i; }; }'`; \
578 shift; \
579 if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
580 test -n "$$unique" || unique=$$empty_fix; \
581 if test $$# -gt 0; then \
582 $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
583 "$$@" $$unique; \
584 else \
585 $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
586 $$unique; \
587 fi; \
588 fi
589ctags: CTAGS
590CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
591 $(TAGS_FILES) $(LISP)
592 list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
593 unique=`for i in $$list; do \
594 if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
595 done | \
596 $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
597 END { if (nonempty) { for (i in files) print i; }; }'`; \
598 test -z "$(CTAGS_ARGS)$$unique" \
599 || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
600 $$unique
601
602GTAGS:
603 here=`$(am__cd) $(top_builddir) && pwd` \
604 && $(am__cd) $(top_srcdir) \
605 && gtags -i $(GTAGS_ARGS) "$$here"
606
607distclean-tags:
608 -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
609
610distdir: $(DISTFILES)
611 @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
612 topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
613 list='$(DISTFILES)'; \
614 dist_files=`for file in $$list; do echo $$file; done | \
615 sed -e "s|^$$srcdirstrip/||;t" \
616 -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
617 case $$dist_files in \
618 */*) $(MKDIR_P) `echo "$$dist_files" | \
619 sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
620 sort -u` ;; \
621 esac; \
622 for file in $$dist_files; do \
623 if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
624 if test -d $$d/$$file; then \
625 dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
626 if test -d "$(distdir)/$$file"; then \
627 find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
628 fi; \
629 if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
630 cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
631 find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
632 fi; \
633 cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
634 else \
635 test -f "$(distdir)/$$file" \
636 || cp -p $$d/$$file "$(distdir)/$$file" \
637 || exit 1; \
638 fi; \
639 done
640check-am: all-am
641check: check-am
642all-am: Makefile $(LTLIBRARIES)
643installdirs:
644install: install-am
645install-exec: install-exec-am
646install-data: install-data-am
647uninstall: uninstall-am
648
649install-am: all-am
650 @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
651
652installcheck: installcheck-am
653install-strip:
654 $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
655 install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
656 `test -z '$(STRIP)' || \
657 echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
658mostlyclean-generic:
659
660clean-generic:
661
662distclean-generic:
663 -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
664 -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
665
666maintainer-clean-generic:
667 @echo "This command is intended for maintainers to use"
668 @echo "it deletes files that may require special tools to rebuild."
669 -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
670clean: clean-am
671
672clean-am: clean-generic clean-libtool clean-local \
673 clean-noinstLTLIBRARIES mostlyclean-am
674
675distclean: distclean-am
676 -rm -rf ./$(DEPDIR)
677 -rm -f Makefile
678distclean-am: clean-am distclean-compile distclean-generic \
679 distclean-tags
680
681dvi: dvi-am
682
683dvi-am:
684
685html: html-am
686
687html-am:
688
689info: info-am
690
691info-am:
692
693install-data-am:
694
695install-dvi: install-dvi-am
696
697install-dvi-am:
698
699install-exec-am:
700
701install-html: install-html-am
702
703install-html-am:
704
705install-info: install-info-am
706
707install-info-am:
708
709install-man:
710
711install-pdf: install-pdf-am
712
713install-pdf-am:
714
715install-ps: install-ps-am
716
717install-ps-am:
718
719installcheck-am:
720
721maintainer-clean: maintainer-clean-am
722 -rm -rf ./$(DEPDIR)
723 -rm -f Makefile
724maintainer-clean-am: distclean-am maintainer-clean-generic
725
726mostlyclean: mostlyclean-am
727
728mostlyclean-am: mostlyclean-compile mostlyclean-generic \
729 mostlyclean-libtool
730
731pdf: pdf-am
732
733pdf-am:
734
735ps: ps-am
736
737ps-am:
738
739uninstall-am:
740
741.MAKE: install-am install-strip
742
743.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
744 clean-libtool clean-local clean-noinstLTLIBRARIES ctags \
745 distclean distclean-compile distclean-generic \
746 distclean-libtool distclean-tags distdir dvi dvi-am html \
747 html-am info info-am install install-am install-data \
748 install-data-am install-dvi install-dvi-am install-exec \
749 install-exec-am install-html install-html-am install-info \
750 install-info-am install-man install-pdf install-pdf-am \
751 install-ps install-ps-am install-strip installcheck \
752 installcheck-am installdirs maintainer-clean \
753 maintainer-clean-generic mostlyclean mostlyclean-compile \
754 mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
755 tags uninstall uninstall-am
756
757
758clean-local:
759 rm -rf *.gcno
760
761# Tell versions [3.59,3.63) of GNU make to not export all variables.
762# Otherwise a system limit (for SysV at least) may be exceeded.
763.NOEXPORT:
diff --git a/libraries/evas/src/lib/canvas/evas_async_events.c b/libraries/evas/src/lib/canvas/evas_async_events.c
deleted file mode 100644
index bd2e3a8..0000000
--- a/libraries/evas/src/lib/canvas/evas_async_events.c
+++ /dev/null
@@ -1,173 +0,0 @@
1#ifdef HAVE_CONFIG_H
2# include <config.h>
3#endif
4
5#ifdef BUILD_ASYNC_EVENTS
6
7# ifndef _MSC_VER
8# include <unistd.h>
9# endif
10# include <fcntl.h>
11# include <errno.h>
12
13#endif
14
15#include "evas_common.h"
16#include "evas_private.h"
17
18#ifdef BUILD_ASYNC_EVENTS
19
20static int _fd_write = -1;
21static int _fd_read = -1;
22
23static int _init_evas_event = 0;
24
25typedef struct _Evas_Event_Async Evas_Event_Async;
26
27struct _Evas_Event_Async
28{
29 const void *target;
30 void *event_info;
31 Evas_Async_Events_Put_Cb func;
32 Evas_Callback_Type type;
33};
34
35int
36evas_async_events_init(void)
37{
38 int filedes[2];
39
40 _init_evas_event++;
41 if (_init_evas_event > 1) return _init_evas_event;
42
43 if (pipe(filedes) == -1)
44 {
45 _init_evas_event = 0;
46 return 0;
47 }
48
49 _fd_read = filedes[0];
50 _fd_write = filedes[1];
51
52 fcntl(_fd_read, F_SETFL, O_NONBLOCK);
53
54 return _init_evas_event;
55}
56
57int
58evas_async_events_shutdown(void)
59{
60 _init_evas_event--;
61 if (_init_evas_event > 0) return _init_evas_event;
62
63 close(_fd_read);
64 close(_fd_write);
65 _fd_read = -1;
66 _fd_write = -1;
67
68 return _init_evas_event;
69}
70
71#endif
72
73EAPI int
74evas_async_events_fd_get(void)
75{
76#ifdef BUILD_ASYNC_EVENTS
77 return _fd_read;
78#else
79 return -1;
80#endif
81}
82
83EAPI int
84evas_async_events_process(void)
85{
86#ifdef BUILD_ASYNC_EVENTS
87 Evas_Event_Async *ev;
88 int check;
89 int count = 0;
90
91 if (_fd_read == -1) return 0;
92
93 do
94 {
95 check = read(_fd_read, &ev, sizeof (Evas_Event_Async *));
96
97 if (check == sizeof (Evas_Event_Async *))
98 {
99 if (ev->func) ev->func((void *)ev->target, ev->type, ev->event_info);
100 free(ev);
101 count++;
102 }
103 }
104 while (check > 0);
105
106 evas_cache_image_wakeup();
107
108 if (check < 0)
109 {
110 switch (errno)
111 {
112 case EBADF:
113 case EINVAL:
114 case EIO:
115 case EISDIR:
116 _fd_read = -1;
117 }
118 }
119
120 return count;
121#else
122 return 0;
123#endif
124}
125
126EAPI Eina_Bool
127evas_async_events_put(const void *target, Evas_Callback_Type type, void *event_info, Evas_Async_Events_Put_Cb func)
128{
129#ifdef BUILD_ASYNC_EVENTS
130 Evas_Event_Async *ev;
131 ssize_t check;
132 Eina_Bool result = EINA_FALSE;
133
134 if (!func) return 0;
135 if (_fd_write == -1) return 0;
136
137 ev = calloc(1, sizeof (Evas_Event_Async));
138 if (!ev) return 0;
139
140 ev->func = func;
141 ev->target = target;
142 ev->type = type;
143 ev->event_info = event_info;
144
145 do
146 {
147 check = write(_fd_write, &ev, sizeof (Evas_Event_Async*));
148 }
149 while ((check != sizeof (Evas_Event_Async*)) &&
150 ((errno == EINTR) || (errno == EAGAIN)));
151
152 evas_cache_image_wakeup();
153
154 if (check == sizeof (Evas_Event_Async*))
155 result = EINA_TRUE;
156 else
157 {
158 switch (errno)
159 {
160 case EBADF:
161 case EINVAL:
162 case EIO:
163 case EPIPE:
164 _fd_write = -1;
165 }
166 }
167
168 return result;
169#else
170 func((void*) target, type, event_info);
171 return EINA_TRUE;
172#endif
173}
diff --git a/libraries/evas/src/lib/canvas/evas_callbacks.c b/libraries/evas/src/lib/canvas/evas_callbacks.c
deleted file mode 100644
index 47cfb0c..0000000
--- a/libraries/evas/src/lib/canvas/evas_callbacks.c
+++ /dev/null
@@ -1,543 +0,0 @@
1#include "evas_common.h"
2#include "evas_private.h"
3
4static void evas_object_event_callback_clear(Evas_Object *obj);
5static void evas_event_callback_clear(Evas *e);
6int _evas_event_counter = 0;
7
8EVAS_MEMPOOL(_mp_fn);
9EVAS_MEMPOOL(_mp_cb);
10EVAS_MEMPOOL(_mp_pc);
11
12void
13_evas_post_event_callback_call(Evas *e)
14{
15 Evas_Post_Callback *pc;
16 int skip = 0;
17
18 if (e->delete_me) return;
19 _evas_walk(e);
20 EINA_LIST_FREE(e->post_events, pc)
21 {
22 if ((!skip) && (!e->delete_me) && (!pc->delete_me))
23 {
24 if (!pc->func((void*)pc->data, e)) skip = 1;
25 }
26 EVAS_MEMPOOL_FREE(_mp_pc, pc);
27 }
28 _evas_unwalk(e);
29}
30
31void
32_evas_post_event_callback_free(Evas *e)
33{
34 Evas_Post_Callback *pc;
35
36 EINA_LIST_FREE(e->post_events, pc)
37 {
38 EVAS_MEMPOOL_FREE(_mp_pc, pc);
39 }
40 _evas_unwalk(e);
41}
42
43void
44evas_event_callback_list_post_free(Eina_Inlist **list)
45{
46 Eina_Inlist *l;
47
48 /* MEM OK */
49 for (l = *list; l;)
50 {
51 Evas_Func_Node *fn;
52
53 fn = (Evas_Func_Node *)l;
54 l = l->next;
55 if (fn->delete_me)
56 {
57 *list = eina_inlist_remove(*list, EINA_INLIST_GET(fn));
58 EVAS_MEMPOOL_FREE(_mp_fn, fn);
59 }
60 }
61}
62
63static void
64evas_object_event_callback_clear(Evas_Object *obj)
65{
66 if (!obj->callbacks) return;
67 if (!obj->callbacks->deletions_waiting) return;
68 obj->callbacks->deletions_waiting = 0;
69 evas_event_callback_list_post_free(&obj->callbacks->callbacks);
70 if (!obj->callbacks->callbacks)
71 {
72 EVAS_MEMPOOL_FREE(_mp_cb, obj->callbacks);
73 obj->callbacks = NULL;
74 }
75}
76
77static void
78evas_event_callback_clear(Evas *e)
79{
80 if (!e->callbacks) return;
81 if (!e->callbacks->deletions_waiting) return;
82 e->callbacks->deletions_waiting = 0;
83 evas_event_callback_list_post_free(&e->callbacks->callbacks);
84 if (!e->callbacks->callbacks)
85 {
86 EVAS_MEMPOOL_FREE(_mp_cb, e->callbacks);
87 e->callbacks = NULL;
88 }
89}
90
91void
92evas_object_event_callback_all_del(Evas_Object *obj)
93{
94 Evas_Func_Node *fn;
95
96 if (!obj->callbacks) return;
97 EINA_INLIST_FOREACH(obj->callbacks->callbacks, fn)
98 fn->delete_me = 1;
99}
100
101void
102evas_object_event_callback_cleanup(Evas_Object *obj)
103{
104 /* MEM OK */
105 if (!obj->callbacks) return;
106 evas_event_callback_list_post_free(&obj->callbacks->callbacks);
107 EVAS_MEMPOOL_FREE(_mp_cb, obj->callbacks);
108 obj->callbacks = NULL;
109}
110
111void
112evas_event_callback_all_del(Evas *e)
113{
114 Evas_Func_Node *fn;
115
116 if (!e->callbacks) return;
117 EINA_INLIST_FOREACH(e->callbacks->callbacks, fn)
118 fn->delete_me = 1;
119}
120
121void
122evas_event_callback_cleanup(Evas *e)
123{
124 /* MEM OK */
125 if (!e->callbacks) return;
126 evas_event_callback_list_post_free(&e->callbacks->callbacks);
127 EVAS_MEMPOOL_FREE(_mp_cb, e->callbacks);
128 e->callbacks = NULL;
129}
130
131void
132evas_event_callback_call(Evas *e, Evas_Callback_Type type, void *event_info)
133{
134 Eina_Inlist **l_mod = NULL, *l;
135
136 _evas_walk(e);
137 if (e->callbacks)
138 {
139 l_mod = &e->callbacks->callbacks;
140 e->callbacks->walking_list++;
141 for (l = *l_mod; l; l = l->next)
142 {
143 Evas_Func_Node *fn;
144
145 fn = (Evas_Func_Node *)l;
146 if ((fn->type == type) && (!fn->delete_me))
147 {
148 Evas_Event_Cb func = fn->func;
149 if (func)
150 func(fn->data, e, event_info);
151 }
152 if (e->delete_me) break;
153 }
154 e->callbacks->walking_list--;
155 if (!e->callbacks->walking_list)
156 {
157 evas_event_callback_clear(e);
158 l_mod = NULL;
159 }
160 }
161 _evas_unwalk(e);
162}
163
164void
165evas_object_event_callback_call(Evas_Object *obj, Evas_Callback_Type type, void *event_info, int event_id)
166{
167 /* MEM OK */
168 Eina_Inlist **l_mod = NULL, *l;
169 Evas_Button_Flags flags = EVAS_BUTTON_NONE;
170 Evas *e;
171
172 if ((obj->delete_me) || (!obj->layer)) return;
173 if ((obj->last_event == event_id) &&
174 (obj->last_event_type == type)) return;
175 if (obj->last_event > event_id)
176 {
177 if ((obj->last_event_type == EVAS_CALLBACK_MOUSE_OUT) &&
178 ((type >= EVAS_CALLBACK_MOUSE_DOWN) &&
179 (type <= EVAS_CALLBACK_MULTI_MOVE)))
180 {
181 return;
182 }
183 }
184 obj->last_event = event_id;
185 obj->last_event_type = type;
186 if (!(e = obj->layer->evas)) return;
187
188 _evas_walk(e);
189 if (obj->callbacks)
190 {
191 l_mod = &obj->callbacks->callbacks;
192 switch (type)
193 {
194 case EVAS_CALLBACK_MOUSE_DOWN:
195 {
196 Evas_Event_Mouse_Down *ev = event_info;
197
198 flags = ev->flags;
199 if (ev->flags & (EVAS_BUTTON_DOUBLE_CLICK | EVAS_BUTTON_TRIPLE_CLICK))
200 {
201 if (obj->last_mouse_down_counter < (e->last_mouse_down_counter - 1))
202 ev->flags &= ~(EVAS_BUTTON_DOUBLE_CLICK | EVAS_BUTTON_TRIPLE_CLICK);
203 }
204 obj->last_mouse_down_counter = e->last_mouse_down_counter;
205 break;
206 }
207 case EVAS_CALLBACK_MOUSE_UP:
208 {
209 Evas_Event_Mouse_Up *ev = event_info;
210
211 flags = ev->flags;
212 if (ev->flags & (EVAS_BUTTON_DOUBLE_CLICK | EVAS_BUTTON_TRIPLE_CLICK))
213 {
214 if (obj->last_mouse_up_counter < (e->last_mouse_up_counter - 1))
215 ev->flags &= ~(EVAS_BUTTON_DOUBLE_CLICK | EVAS_BUTTON_TRIPLE_CLICK);
216 }
217 obj->last_mouse_up_counter = e->last_mouse_up_counter;
218 break;
219 }
220 default:
221 break;
222 }
223 obj->callbacks->walking_list++;
224 for (l = *l_mod; l; l = l->next)
225 {
226 Evas_Func_Node *fn;
227
228 fn = (Evas_Func_Node *)l;
229 if ((fn->type == type) && (!fn->delete_me))
230 {
231 Evas_Object_Event_Cb func = fn->func;
232 if (func)
233 func(fn->data, obj->layer->evas, obj, event_info);
234 }
235 if (obj->delete_me) break;
236 }
237 obj->callbacks->walking_list--;
238 if (!obj->callbacks->walking_list)
239 {
240 evas_object_event_callback_clear(obj);
241 l_mod = NULL;
242 }
243
244 if (type == EVAS_CALLBACK_MOUSE_DOWN)
245 {
246 Evas_Event_Mouse_Down *ev = event_info;
247 ev->flags = flags;
248 }
249 else if (type == EVAS_CALLBACK_MOUSE_UP)
250 {
251 Evas_Event_Mouse_Up *ev = event_info;
252 ev->flags = flags;
253 }
254 }
255
256 if (!((obj->no_propagate) && (l_mod) && (*l_mod)))
257 {
258 if (!obj->no_propagate)
259 {
260 if ((obj->smart.parent) && (type != EVAS_CALLBACK_FREE) &&
261 (type <= EVAS_CALLBACK_KEY_UP))
262 evas_object_event_callback_call(obj->smart.parent, type, event_info, event_id);
263 }
264 }
265 _evas_unwalk(e);
266}
267
268static int
269_callback_priority_cmp(const void *_a, const void *_b)
270{
271 const Evas_Func_Node *a, *b;
272 a = EINA_INLIST_CONTAINER_GET(_a, Evas_Func_Node);
273 b = EINA_INLIST_CONTAINER_GET(_b, Evas_Func_Node);
274 if (a->priority < b->priority)
275 return -1;
276 else
277 return 1;
278}
279
280EAPI void
281evas_object_event_callback_add(Evas_Object *obj, Evas_Callback_Type type, Evas_Object_Event_Cb func, const void *data)
282{
283 evas_object_event_callback_priority_add(obj, type,
284 EVAS_CALLBACK_PRIORITY_DEFAULT, func, data);
285}
286
287EAPI void
288evas_object_event_callback_priority_add(Evas_Object *obj, Evas_Callback_Type type, Evas_Callback_Priority priority, Evas_Object_Event_Cb func, const void *data)
289{
290 /* MEM OK */
291 Evas_Func_Node *fn;
292
293 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
294 return;
295 MAGIC_CHECK_END();
296
297 if (!func) return;
298
299 if (!obj->callbacks)
300 {
301 EVAS_MEMPOOL_INIT(_mp_cb, "evas_callbacks", Evas_Callbacks, 512, );
302 obj->callbacks = EVAS_MEMPOOL_ALLOC(_mp_cb, Evas_Callbacks);
303 if (!obj->callbacks) return;
304 EVAS_MEMPOOL_PREP(_mp_cb, obj->callbacks, Evas_Callbacks);
305 }
306
307 EVAS_MEMPOOL_INIT(_mp_fn, "evas_func_node", Evas_Func_Node, 2048, );
308 fn = EVAS_MEMPOOL_ALLOC(_mp_fn, Evas_Func_Node);
309 if (!fn) return;
310 EVAS_MEMPOOL_PREP(_mp_fn, fn, Evas_Func_Node);
311 fn->func = func;
312 fn->data = (void *)data;
313 fn->type = type;
314 fn->priority = priority;
315
316 obj->callbacks->callbacks =
317 eina_inlist_sorted_insert(obj->callbacks->callbacks, EINA_INLIST_GET(fn),
318 _callback_priority_cmp);
319}
320
321EAPI void *
322evas_object_event_callback_del(Evas_Object *obj, Evas_Callback_Type type, Evas_Object_Event_Cb func)
323{
324 /* MEM OK */
325 Evas_Func_Node *fn;
326
327 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
328 return NULL;
329 MAGIC_CHECK_END();
330
331 if (!func) return NULL;
332
333 if (!obj->callbacks) return NULL;
334
335 EINA_INLIST_FOREACH(obj->callbacks->callbacks, fn)
336 {
337 if ((fn->func == func) && (fn->type == type) && (!fn->delete_me))
338 {
339 void *tmp;
340
341 tmp = fn->data;
342 fn->delete_me = 1;
343 obj->callbacks->deletions_waiting = 1;
344 if (!obj->callbacks->walking_list)
345 evas_object_event_callback_clear(obj);
346 return tmp;
347 }
348 }
349 return NULL;
350}
351
352EAPI void *
353evas_object_event_callback_del_full(Evas_Object *obj, Evas_Callback_Type type, Evas_Object_Event_Cb func, const void *data)
354{
355 /* MEM OK */
356 Evas_Func_Node *fn;
357
358 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
359 return NULL;
360 MAGIC_CHECK_END();
361
362 if (!func) return NULL;
363
364 if (!obj->callbacks) return NULL;
365
366 EINA_INLIST_FOREACH(obj->callbacks->callbacks, fn)
367 {
368 if ((fn->func == func) && (fn->type == type) && (fn->data == data) && (!fn->delete_me))
369 {
370 void *tmp;
371
372 tmp = fn->data;
373 fn->delete_me = 1;
374 obj->callbacks->deletions_waiting = 1;
375 if (!obj->callbacks->walking_list)
376 evas_object_event_callback_clear(obj);
377 return tmp;
378 }
379 }
380 return NULL;
381}
382
383EAPI void
384evas_event_callback_add(Evas *e, Evas_Callback_Type type, Evas_Event_Cb func, const void *data)
385{
386 evas_event_callback_priority_add(e, type, EVAS_CALLBACK_PRIORITY_DEFAULT,
387 func, data);
388}
389
390EAPI void
391evas_event_callback_priority_add(Evas *e, Evas_Callback_Type type, Evas_Callback_Priority priority, Evas_Event_Cb func, const void *data)
392{
393 /* MEM OK */
394 Evas_Func_Node *fn;
395
396 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
397 return;
398 MAGIC_CHECK_END();
399
400 if (!func) return;
401
402 if (!e->callbacks)
403 {
404 EVAS_MEMPOOL_INIT(_mp_cb, "evas_callbacks", Evas_Callbacks, 512, );
405 e->callbacks = EVAS_MEMPOOL_ALLOC(_mp_cb, Evas_Callbacks);
406 if (!e->callbacks) return;
407 EVAS_MEMPOOL_PREP(_mp_cb, e->callbacks, Evas_Callbacks);
408 }
409
410 EVAS_MEMPOOL_INIT(_mp_fn, "evas_func_node", Evas_Func_Node, 2048, );
411 fn = EVAS_MEMPOOL_ALLOC(_mp_fn, Evas_Func_Node);
412 if (!fn) return;
413 EVAS_MEMPOOL_PREP(_mp_fn, fn, Evas_Func_Node);
414 fn->func = func;
415 fn->data = (void *)data;
416 fn->type = type;
417 fn->priority = priority;
418
419 e->callbacks->callbacks = eina_inlist_sorted_insert(e->callbacks->callbacks,
420 EINA_INLIST_GET(fn), _callback_priority_cmp);
421}
422
423EAPI void *
424evas_event_callback_del(Evas *e, Evas_Callback_Type type, Evas_Event_Cb func)
425{
426 /* MEM OK */
427 Evas_Func_Node *fn;
428
429 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
430 return NULL;
431 MAGIC_CHECK_END();
432
433 if (!func) return NULL;
434
435 if (!e->callbacks) return NULL;
436
437 EINA_INLIST_FOREACH(e->callbacks->callbacks, fn)
438 {
439 if ((fn->func == func) && (fn->type == type) && (!fn->delete_me))
440 {
441 void *data;
442
443 data = fn->data;
444 fn->delete_me = 1;
445 e->callbacks->deletions_waiting = 1;
446 if (!e->callbacks->walking_list)
447 evas_event_callback_clear(e);
448 return data;
449 }
450 }
451 return NULL;
452}
453
454EAPI void *
455evas_event_callback_del_full(Evas *e, Evas_Callback_Type type, Evas_Event_Cb func, const void *data)
456{
457 /* MEM OK */
458 Evas_Func_Node *fn;
459
460 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
461 return NULL;
462 MAGIC_CHECK_END();
463
464 if (!func) return NULL;
465
466 if (!e->callbacks) return NULL;
467
468 EINA_INLIST_FOREACH(e->callbacks->callbacks, fn)
469 {
470 if ((fn->func == func) && (fn->type == type) && (fn->data == data) && (!fn->delete_me))
471 {
472 void *tmp;
473
474 tmp = fn->data;
475 fn->delete_me = 1;
476 e->callbacks->deletions_waiting = 1;
477 if (!e->callbacks->walking_list)
478 evas_event_callback_clear(e);
479 return tmp;
480 }
481 }
482 return NULL;
483}
484
485EAPI void
486evas_post_event_callback_push(Evas *e, Evas_Object_Event_Post_Cb func, const void *data)
487{
488 Evas_Post_Callback *pc;
489
490 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
491 return;
492 MAGIC_CHECK_END();
493
494 EVAS_MEMPOOL_INIT(_mp_pc, "evas_post_callback", Evas_Post_Callback, 64, );
495 pc = EVAS_MEMPOOL_ALLOC(_mp_pc, Evas_Post_Callback);
496 if (!pc) return;
497 EVAS_MEMPOOL_PREP(_mp_pc, pc, Evas_Post_Callback);
498 if (e->delete_me) return;
499
500 pc->func = func;
501 pc->data = data;
502 e->post_events = eina_list_prepend(e->post_events, pc);
503}
504
505EAPI void
506evas_post_event_callback_remove(Evas *e, Evas_Object_Event_Post_Cb func)
507{
508 Evas_Post_Callback *pc;
509 Eina_List *l;
510
511 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
512 return;
513 MAGIC_CHECK_END();
514
515 EINA_LIST_FOREACH(e->post_events, l, pc)
516 {
517 if (pc->func == func)
518 {
519 pc->delete_me = 1;
520 return;
521 }
522 }
523}
524
525EAPI void
526evas_post_event_callback_remove_full(Evas *e, Evas_Object_Event_Post_Cb func, const void *data)
527{
528 Evas_Post_Callback *pc;
529 Eina_List *l;
530
531 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
532 return;
533 MAGIC_CHECK_END();
534
535 EINA_LIST_FOREACH(e->post_events, l, pc)
536 {
537 if ((pc->func == func) && (pc->data == data))
538 {
539 pc->delete_me = 1;
540 return;
541 }
542 }
543}
diff --git a/libraries/evas/src/lib/canvas/evas_clip.c b/libraries/evas/src/lib/canvas/evas_clip.c
deleted file mode 100644
index 1ae2f73..0000000
--- a/libraries/evas/src/lib/canvas/evas_clip.c
+++ /dev/null
@@ -1,321 +0,0 @@
1#include "evas_common.h"
2#include "evas_private.h"
3
4void
5evas_object_clip_dirty(Evas_Object *obj)
6{
7 Eina_List *l;
8 Evas_Object *data;
9
10 if (obj->cur.cache.clip.dirty) return ;
11
12 obj->cur.cache.clip.dirty = 1;
13 EINA_LIST_FOREACH(obj->clip.clipees, l, data)
14 evas_object_clip_dirty(data);
15}
16
17void
18evas_object_recalc_clippees(Evas_Object *obj)
19{
20 Eina_List *l;
21 Evas_Object *data;
22
23 if (obj->cur.cache.clip.dirty)
24 {
25 evas_object_clip_recalc(obj);
26 EINA_LIST_FOREACH(obj->clip.clipees, l, data)
27 evas_object_recalc_clippees(data);
28 }
29}
30
31int
32evas_object_clippers_was_visible(Evas_Object *obj)
33{
34 if (obj->prev.visible)
35 {
36 if (obj->prev.clipper)
37 return evas_object_clippers_is_visible(obj->prev.clipper);
38 return 1;
39 }
40 return 0;
41}
42
43/* aaaaargh (pirate voice) ... notes!
44 *
45 * we have a big problem until now that's gone undetected... until yesterday.
46 * that problem involves clips and maps and smart objects. hooray! 3 of the
47 * more complex bits of evas - and maps and smart objects being one of the
48 * nastiest ones.
49 *
50 * what is the problem? when a clip crosses a map boundary. that is to say
51 * that when the clipper and clippee are not within the child tree of the
52 * mapped object. in this case "bad stuff" happens. basically as clips are
53 * then used to render objects, but they no longer apply as you'd expect as
54 * the map transfomr the objects to-be-clipped separately from the objects
55 * that clip them and this whole relationship is broken by maps. it somehow
56 * managed to not break with the advent of smart objects. lucky me... but
57 * maps killed it. now... what do we do? that is a good question. detect
58 * such a broken link and "turn off clipping" in that event - sure. but this
59 * isn't going to be cheap as ANY addition or deletion of a map to an object
60 * or any change in clipper of an object or any change in smart object
61 * membership needs to walk the obj tree both up and down from the changed
62 * object and probably walk entire object trees to find these and mark them.
63 * thats silly-expensive and i was about to fix it that way but it has since
64 * dawned on me that that is just going to kill performance in some critical
65 * areas like during object setup and manipulation, as well as teardown.
66 *
67 * aaaaagh! best for now is to document this as a "don't do it damnit!" thing
68 * and have the apps avoid it. but even then - how to do this? this is not
69 * easy. everywhere i turn so far i come up to either expensive operations,
70 * breaks in logic, or nasty re-work of apps or4 the whole concept of clipping,
71 * smart objects and maps... and that will have to wait for evas 2.0
72 *
73 * the below does clip fixups etc. in the even a clip spans a map boundary.
74 * not pretty, but necessary.
75 */
76
77#define MAP_ACROSS 1
78static void
79evas_object_child_map_across_mark(Evas_Object *obj, Evas_Object *map_obj, Eina_Bool force)
80{
81#ifdef MAP_ACROSS
82 if ((obj->cur.map_parent != map_obj) || force)
83 {
84 obj->cur.map_parent = map_obj;
85 obj->cur.cache.clip.dirty = 1;
86 evas_object_clip_recalc(obj);
87 if (obj->smart.smart)
88 {
89 Evas_Object *obj2;
90
91 EINA_INLIST_FOREACH(evas_object_smart_members_get_direct(obj), obj2)
92 {
93 // if obj has its own map - skip it. already done
94 if ((obj2->cur.map) && (obj2->cur.usemap)) continue;
95 evas_object_child_map_across_mark(obj2, map_obj, force);
96 }
97 }
98 else if (obj->clip.clipees)
99 {
100 Eina_List *l;
101 Evas_Object *obj2;
102
103 EINA_LIST_FOREACH(obj->clip.clipees, l, obj2)
104 evas_object_child_map_across_mark(obj2, map_obj, force);
105 }
106 }
107#endif
108}
109
110void
111evas_object_clip_across_check(Evas_Object *obj)
112{
113#ifdef MAP_ACROSS
114 if (!obj->cur.clipper) return;
115 if (obj->cur.clipper->cur.map_parent != obj->cur.map_parent)
116 evas_object_child_map_across_mark(obj, obj->cur.map_parent, 1);
117#endif
118}
119
120void
121evas_object_clip_across_clippees_check(Evas_Object *obj)
122{
123#ifdef MAP_ACROSS
124 Eina_List *l;
125 Evas_Object *obj2;
126
127 if (!obj->clip.clipees) return;
128// schloooooooooooow:
129// evas_object_child_map_across_mark(obj, obj->cur.map_parent, 1);
130// buggy:
131 evas_object_child_map_across_mark(obj, obj->cur.map_parent, 0);
132 if (obj->cur.cache.clip.dirty)
133 {
134 EINA_LIST_FOREACH(obj->clip.clipees, l, obj2)
135 evas_object_clip_across_clippees_check(obj2);
136 }
137#endif
138}
139
140// this function is called on an object when map is enabled or disabled on it
141// thus creating a "map boundary" at that point.
142//
143// FIXME: flip2 test broken in elm - might be show/hide of clips
144void
145evas_object_mapped_clip_across_mark(Evas_Object *obj)
146{
147#ifdef MAP_ACROSS
148 if ((obj->cur.map) && (obj->cur.usemap))
149 evas_object_child_map_across_mark(obj, obj, 0);
150 else
151 {
152 if (obj->smart.parent)
153 evas_object_child_map_across_mark
154 (obj, obj->smart.parent->cur.map_parent, 0);
155 else
156 evas_object_child_map_across_mark(obj, NULL, 0);
157 }
158#endif
159}
160
161/* public functions */
162extern const char *o_rect_type;
163
164EAPI void
165evas_object_clip_set(Evas_Object *obj, Evas_Object *clip)
166{
167 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
168 return;
169 MAGIC_CHECK_END();
170 if (!clip)
171 {
172 evas_object_clip_unset(obj);
173 return;
174 }
175 MAGIC_CHECK(clip, Evas_Object, MAGIC_OBJ);
176 return;
177 MAGIC_CHECK_END();
178 if (obj->cur.clipper == clip) return;
179 if (obj == clip) return;
180 if (evas_object_intercept_call_clip_set(obj, clip)) return;
181 // illegal to set anything but a rect as a clip
182 if (clip->type != o_rect_type)
183 {
184 ERR("For now a clip on other object than a rectangle is disabled");
185 return;
186 }
187 if (obj->smart.smart)
188 {
189 if (obj->smart.smart->smart_class->clip_set)
190 obj->smart.smart->smart_class->clip_set(obj, clip);
191 }
192 if (obj->cur.clipper)
193 {
194 /* unclip */
195 obj->cur.clipper->clip.clipees = eina_list_remove(obj->cur.clipper->clip.clipees, obj);
196 if (!obj->cur.clipper->clip.clipees)
197 {
198 obj->cur.clipper->cur.have_clipees = 0;
199 if (obj->cur.clipper->cur.visible)
200 evas_damage_rectangle_add(obj->cur.clipper->layer->evas,
201 obj->cur.clipper->cur.geometry.x,
202 obj->cur.clipper->cur.geometry.y,
203 obj->cur.clipper->cur.geometry.w,
204 obj->cur.clipper->cur.geometry.h);
205 }
206 evas_object_change(obj->cur.clipper);
207 evas_object_change(obj);
208 obj->cur.clipper = NULL;
209 }
210 /* clip me */
211 if ((!clip->clip.clipees) && (clip->cur.visible))
212 {
213 /* Basically it just went invisible */
214 clip->changed = 1;
215 clip->layer->evas->changed = 1;
216 evas_damage_rectangle_add(clip->layer->evas,
217 clip->cur.geometry.x, clip->cur.geometry.y,
218 clip->cur.geometry.w, clip->cur.geometry.h);
219 }
220 obj->cur.clipper = clip;
221 clip->clip.clipees = eina_list_append(clip->clip.clipees, obj);
222 if (clip->clip.clipees) clip->cur.have_clipees = 1;
223
224 /* If it's NOT a rectangle set the mask bits too */
225 /* FIXME: Optmz ths chck */
226 if (strcmp(evas_object_type_get(clip),"rectangle") == 0)
227 obj->cur.mask = NULL;
228 else
229 {
230 void *engdata;
231 obj->cur.mask = clip;
232 engdata = clip->func->engine_data_get(clip);
233 /* FIXME: Images only */
234 clip->layer->evas->engine.func->image_mask_create(
235 clip->layer->evas->engine.data.output,
236 engdata);
237 }
238 evas_object_change(clip);
239 evas_object_change(obj);
240 evas_object_clip_dirty(obj);
241 evas_object_recalc_clippees(obj);
242 if ((!obj->smart.smart) &&
243 (!((obj->cur.map) && (obj->cur.usemap))))
244 {
245 if (evas_object_is_in_output_rect(obj,
246 obj->layer->evas->pointer.x,
247 obj->layer->evas->pointer.y, 1, 1))
248 evas_event_feed_mouse_move(obj->layer->evas,
249 obj->layer->evas->pointer.x,
250 obj->layer->evas->pointer.y,
251 obj->layer->evas->last_timestamp,
252 NULL);
253 }
254 evas_object_clip_across_check(obj);
255}
256
257EAPI Evas_Object *
258evas_object_clip_get(const Evas_Object *obj)
259{
260 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
261 return NULL;
262 MAGIC_CHECK_END();
263 return obj->cur.clipper;
264}
265
266EAPI void
267evas_object_clip_unset(Evas_Object *obj)
268{
269 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
270 return;
271 MAGIC_CHECK_END();
272 if (!obj->cur.clipper) return;
273 /* unclip */
274 if (evas_object_intercept_call_clip_unset(obj)) return;
275 if (obj->smart.smart)
276 {
277 if (obj->smart.smart->smart_class->clip_unset)
278 obj->smart.smart->smart_class->clip_unset(obj);
279 }
280 if (obj->cur.clipper)
281 {
282 obj->cur.clipper->clip.clipees = eina_list_remove(obj->cur.clipper->clip.clipees, obj);
283 if (!obj->cur.clipper->clip.clipees)
284 {
285 obj->cur.clipper->cur.have_clipees = 0;
286 if (obj->cur.clipper->cur.visible)
287 evas_damage_rectangle_add(obj->cur.clipper->layer->evas,
288 obj->cur.clipper->cur.geometry.x,
289 obj->cur.clipper->cur.geometry.y,
290 obj->cur.clipper->cur.geometry.w,
291 obj->cur.clipper->cur.geometry.h);
292 }
293 evas_object_change(obj->cur.clipper);
294 }
295 obj->cur.clipper = NULL;
296 evas_object_change(obj);
297 evas_object_clip_dirty(obj);
298 evas_object_recalc_clippees(obj);
299 if ((!obj->smart.smart) &&
300 (!((obj->cur.map) && (obj->cur.usemap))))
301 {
302 if (evas_object_is_in_output_rect(obj,
303 obj->layer->evas->pointer.x,
304 obj->layer->evas->pointer.y, 1, 1))
305 evas_event_feed_mouse_move(obj->layer->evas,
306 obj->layer->evas->pointer.x,
307 obj->layer->evas->pointer.y,
308 obj->layer->evas->last_timestamp,
309 NULL);
310 }
311 evas_object_clip_across_check(obj);
312}
313
314EAPI const Eina_List *
315evas_object_clipees_get(const Evas_Object *obj)
316{
317 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
318 return NULL;
319 MAGIC_CHECK_END();
320 return obj->clip.clipees;
321}
diff --git a/libraries/evas/src/lib/canvas/evas_data.c b/libraries/evas/src/lib/canvas/evas_data.c
deleted file mode 100644
index 3ac9d63..0000000
--- a/libraries/evas/src/lib/canvas/evas_data.c
+++ /dev/null
@@ -1,72 +0,0 @@
1#include "evas_common.h"
2#include "evas_private.h"
3
4
5EAPI void
6evas_object_data_set(Evas_Object *obj, const char *key, const void *data)
7{
8 Evas_Data_Node *node;
9
10 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
11 return;
12 MAGIC_CHECK_END();
13 if (!key) return;
14
15 evas_object_data_del(obj, key);
16 if (!data) return;
17 node = malloc(sizeof(Evas_Data_Node) + strlen(key) + 1);
18 node->key = (char *)node + sizeof(Evas_Data_Node);
19 strcpy(node->key, key);
20 node->data = (void *)data;
21 obj->data.elements = eina_list_prepend(obj->data.elements, node);
22}
23
24EAPI void *
25evas_object_data_get(const Evas_Object *obj, const char *key)
26{
27 Eina_List *l;
28 Evas_Data_Node *node;
29
30 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
31 return NULL;
32 MAGIC_CHECK_END();
33 if (!key) return NULL;
34
35 EINA_LIST_FOREACH(obj->data.elements, l, node)
36 {
37 if (!strcmp(node->key, key))
38 {
39 Eina_List *lst;
40 lst = obj->data.elements;
41 lst = eina_list_promote_list(lst, l);
42 ((Evas_Object *)obj)->data.elements = lst;
43 return node->data;
44 }
45 }
46 return NULL;
47}
48
49EAPI void *
50evas_object_data_del(Evas_Object *obj, const char *key)
51{
52 Eina_List *l;
53 Evas_Data_Node *node;
54
55 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
56 return NULL;
57 MAGIC_CHECK_END();
58 if (!key) return NULL;
59 EINA_LIST_FOREACH(obj->data.elements, l, node)
60 {
61 if (!strcmp(node->key, key))
62 {
63 void *data;
64
65 data = node->data;
66 obj->data.elements = eina_list_remove_list(obj->data.elements, l);
67 free(node);
68 return data;
69 }
70 }
71 return NULL;
72}
diff --git a/libraries/evas/src/lib/canvas/evas_events.c b/libraries/evas/src/lib/canvas/evas_events.c
deleted file mode 100644
index 1ee8388..0000000
--- a/libraries/evas/src/lib/canvas/evas_events.c
+++ /dev/null
@@ -1,1867 +0,0 @@
1#include "evas_common.h"
2#include "evas_private.h"
3
4static Eina_List *
5_evas_event_object_list_in_get(Evas *e, Eina_List *in,
6 const Eina_Inlist *list, Evas_Object *stop,
7 int x, int y, int *no_rep);
8
9static void
10_evas_event_havemap_adjust(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Eina_Bool mouse_grabbed)
11{
12 if (obj->smart.parent)
13 _evas_event_havemap_adjust(obj->smart.parent, x, y, mouse_grabbed);
14
15 if ((!obj->cur.usemap) || (!obj->cur.map) || (!obj->cur.map->count == 4))
16 return;
17
18 evas_map_coords_get(obj->cur.map, *x, *y, x, y, mouse_grabbed);
19 *x += obj->cur.geometry.x;
20 *y += obj->cur.geometry.y;
21}
22
23static Eina_List *
24_evas_event_object_list_raw_in_get(Evas *e, Eina_List *in,
25 const Eina_Inlist *list, Evas_Object *stop,
26 int x, int y, int *no_rep)
27{
28 Evas_Object *obj;
29 int inside;
30
31 if (!list) return in;
32 for (obj = _EINA_INLIST_CONTAINER(obj, list);
33 obj;
34 obj = _EINA_INLIST_CONTAINER(obj, EINA_INLIST_GET(obj)->prev))
35 {
36 if (obj == stop)
37 {
38 *no_rep = 1;
39 return in;
40 }
41 if (evas_event_passes_through(obj)) continue;
42 if ((obj->cur.visible) && (obj->delete_me == 0) &&
43 (!obj->clip.clipees) &&
44 (evas_object_clippers_is_visible(obj)))
45 {
46 if (obj->smart.smart)
47 {
48 int norep = 0;
49
50 if ((obj->cur.usemap) && (obj->cur.map) &&
51 (obj->cur.map->count == 4))
52 {
53 inside = evas_object_is_in_output_rect(obj, x, y, 1, 1);
54 if (inside)
55 {
56 if (!evas_map_coords_get(obj->cur.map, x, y,
57 &(obj->cur.map->mx),
58 &(obj->cur.map->my), 0))
59 {
60 inside = 0;
61 }
62 else
63 {
64 in = _evas_event_object_list_in_get
65 (e, in,
66 evas_object_smart_members_get_direct(obj),
67 stop,
68 obj->cur.geometry.x + obj->cur.map->mx,
69 obj->cur.geometry.y + obj->cur.map->my,
70 &norep);
71 }
72 }
73 }
74 else
75 {
76 in = _evas_event_object_list_in_get
77 (e, in, evas_object_smart_members_get_direct(obj),
78 stop, x, y, &norep);
79 }
80 if (norep)
81 {
82 if (!obj->repeat_events)
83 {
84 *no_rep = 1;
85 return in;
86 }
87 }
88 }
89 else
90 {
91 inside = evas_object_is_in_output_rect(obj, x, y, 1, 1);
92
93 if ((obj->cur.usemap) && (obj->cur.map) &&
94 (obj->cur.map->count == 4))
95 {
96 if ((inside) &&
97 (!evas_map_coords_get(obj->cur.map, x, y,
98 &(obj->cur.map->mx),
99 &(obj->cur.map->my), 0)))
100 {
101 inside = 0;
102 }
103 }
104
105 if (inside && ((!obj->precise_is_inside) ||
106 (evas_object_is_inside(obj, x, y))))
107 {
108 if (!evas_event_freezes_through(obj))
109 in = eina_list_append(in, obj);
110 if (!obj->repeat_events)
111 {
112 *no_rep = 1;
113 return in;
114 }
115 }
116 }
117 }
118 }
119 *no_rep = 0;
120 return in;
121}
122
123static Eina_List *
124_evas_event_object_list_in_get(Evas *e, Eina_List *in,
125 const Eina_Inlist *list, Evas_Object *stop,
126 int x, int y, int *no_rep)
127{
128 if (!list) return NULL;
129 return _evas_event_object_list_raw_in_get(e, in, list->last, stop,
130 x, y, no_rep);
131}
132
133Eina_List *
134evas_event_objects_event_list(Evas *e, Evas_Object *stop, int x, int y)
135{
136 Evas_Layer *lay;
137 Eina_List *in = NULL;
138
139 if ((!e->layers) || (e->events_frozen > 0)) return NULL;
140 EINA_INLIST_REVERSE_FOREACH((EINA_INLIST_GET(e->layers)), lay)
141 {
142 int norep = 0;
143 in = _evas_event_object_list_in_get(e, in,
144 EINA_INLIST_GET(lay->objects),
145 stop, x, y, &norep);
146 if (norep) return in;
147 }
148 return in;
149}
150
151static Eina_List *
152evas_event_list_copy(Eina_List *list)
153{
154 Eina_List *l, *new_l = NULL;
155 const void *data;
156
157 EINA_LIST_FOREACH(list, l, data)
158 new_l = eina_list_append(new_l, data);
159 return new_l;
160}
161/* public functions */
162
163EAPI void
164evas_event_default_flags_set(Evas *e, Evas_Event_Flags flags)
165{
166 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
167 return;
168 MAGIC_CHECK_END();
169 e->default_event_flags = flags;
170}
171
172EAPI Evas_Event_Flags
173evas_event_default_flags_get(const Evas *e)
174{
175 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
176 return EVAS_EVENT_FLAG_ON_HOLD;
177 MAGIC_CHECK_END();
178 return e->default_event_flags;
179}
180
181EAPI void
182evas_event_freeze(Evas *e)
183{
184 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
185 return;
186 MAGIC_CHECK_END();
187 e->events_frozen++;
188}
189
190EAPI void
191evas_event_thaw(Evas *e)
192{
193 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
194 return;
195 MAGIC_CHECK_END();
196 e->events_frozen--;
197 if (e->events_frozen == 0)
198 {
199 Evas_Layer *lay;
200
201 EINA_INLIST_FOREACH((EINA_INLIST_GET(e->layers)), lay)
202 {
203 Evas_Object *obj;
204
205 EINA_INLIST_FOREACH(lay->objects, obj)
206 {
207 evas_object_clip_recalc(obj);
208 evas_object_recalc_clippees(obj);
209 }
210 }
211 }
212 if (e->events_frozen < 0)
213 evas_debug_generic(" Thaw of events when already thawed!!!\n");
214}
215
216EAPI int
217evas_event_freeze_get(const Evas *e)
218{
219 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
220 return 0;
221 MAGIC_CHECK_END();
222 return e->events_frozen;
223}
224
225EAPI void
226evas_event_thaw_eval(Evas *e)
227{
228 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
229 return;
230 MAGIC_CHECK_END();
231 if (e->events_frozen != 0) return;
232
233 evas_event_feed_mouse_move(e, e->pointer.x, e->pointer.y,
234 e->last_timestamp, NULL);
235}
236
237EAPI void
238evas_event_feed_mouse_down(Evas *e, int b, Evas_Button_Flags flags, unsigned int timestamp, const void *data)
239{
240 Eina_List *l, *copy;
241 Evas_Event_Mouse_Down ev;
242 Evas_Object *obj;
243 int addgrab = 0;
244 int event_id = 0;
245
246 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
247 return;
248 MAGIC_CHECK_END();
249
250 if ((b < 1) || (b > 32)) return;
251
252 e->pointer.button |= (1 << (b - 1));
253 e->pointer.downs++;
254
255 if (e->events_frozen > 0) return;
256 e->last_timestamp = timestamp;
257
258 _evas_object_event_new();
259
260 event_id = _evas_event_counter;
261 ev.button = b;
262 ev.output.x = e->pointer.x;
263 ev.output.y = e->pointer.y;
264 ev.canvas.x = e->pointer.x;
265 ev.canvas.y = e->pointer.y;
266 ev.data = (void *)data;
267 ev.modifiers = &(e->modifiers);
268 ev.locks = &(e->locks);
269 ev.flags = flags;
270 ev.timestamp = timestamp;
271 ev.event_flags = e->default_event_flags;
272
273 _evas_walk(e);
274 /* append new touch point to the touch point list */
275 _evas_touch_point_append(e, 0, e->pointer.x, e->pointer.y);
276 /* If this is the first finger down, i.e no other fingers pressed,
277 * get a new event list, otherwise, keep the current grabbed list. */
278 if (e->pointer.mouse_grabbed == 0)
279 {
280 Eina_List *ins = evas_event_objects_event_list(e,
281 NULL,
282 e->pointer.x,
283 e->pointer.y);
284 /* free our old list of ins */
285 e->pointer.object.in = eina_list_free(e->pointer.object.in);
286 /* and set up the new one */
287 e->pointer.object.in = ins;
288 /* adjust grabbed count by the nuymber of currently held down
289 * fingers/buttons */
290 if (e->pointer.downs > 1) addgrab = e->pointer.downs - 1;
291 }
292 copy = evas_event_list_copy(e->pointer.object.in);
293 EINA_LIST_FOREACH(copy, l, obj)
294 {
295 if ((obj->pointer_mode == EVAS_OBJECT_POINTER_MODE_AUTOGRAB) ||
296 (obj->pointer_mode == EVAS_OBJECT_POINTER_MODE_NOGRAB_NO_REPEAT_UPDOWN))
297 {
298 obj->mouse_grabbed += addgrab + 1;
299 e->pointer.mouse_grabbed += addgrab + 1;
300 if (obj->pointer_mode == EVAS_OBJECT_POINTER_MODE_NOGRAB_NO_REPEAT_UPDOWN)
301 {
302 e->pointer.nogrep++;
303 break;
304 }
305 }
306 }
307 EINA_LIST_FOREACH(copy, l, obj)
308 {
309 if (obj->delete_me) continue;
310 ev.canvas.x = e->pointer.x;
311 ev.canvas.y = e->pointer.y;
312 _evas_event_havemap_adjust(obj, &ev.canvas.x, &ev.canvas.y, obj->mouse_grabbed);
313
314 if (e->events_frozen <= 0)
315 evas_object_event_callback_call(obj, EVAS_CALLBACK_MOUSE_DOWN, &ev, event_id);
316 if (e->delete_me) break;
317 if (obj->pointer_mode == EVAS_OBJECT_POINTER_MODE_NOGRAB_NO_REPEAT_UPDOWN)
318 break;
319 }
320 if (copy) eina_list_free(copy);
321 e->last_mouse_down_counter++;
322 _evas_post_event_callback_call(e);
323 /* update touch point's state to EVAS_TOUCH_POINT_STILL */
324 _evas_touch_point_update(e, 0, e->pointer.x, e->pointer.y, EVAS_TOUCH_POINT_STILL);
325 _evas_unwalk(e);
326}
327
328static int
329_post_up_handle(Evas *e, unsigned int timestamp, const void *data)
330{
331 Eina_List *l, *copy, *ins, *ll;
332 Evas_Event_Mouse_Out ev;
333 Evas_Object *obj;
334 int post_called = 0;
335 int event_id = 0;
336
337 _evas_object_event_new();
338
339 event_id = _evas_event_counter;
340 ev.buttons = e->pointer.button;
341 ev.output.x = e->pointer.x;
342 ev.output.y = e->pointer.y;
343 ev.canvas.x = e->pointer.x;
344 ev.canvas.y = e->pointer.y;
345 ev.data = (void *)data;
346 ev.modifiers = &(e->modifiers);
347 ev.locks = &(e->locks);
348 ev.timestamp = timestamp;
349 ev.event_flags = e->default_event_flags;
350
351 /* get new list of ins */
352 ins = evas_event_objects_event_list(e, NULL, e->pointer.x, e->pointer.y);
353 /* go thru old list of in objects */
354 copy = evas_event_list_copy(e->pointer.object.in);
355 EINA_LIST_FOREACH(copy, ll, obj)
356 {
357 ev.canvas.x = e->pointer.x;
358 ev.canvas.y = e->pointer.y;
359 _evas_event_havemap_adjust(obj, &ev.canvas.x, &ev.canvas.y, obj->mouse_grabbed);
360 if ((!eina_list_data_find(ins, obj)) ||
361 (!e->pointer.inside))
362 {
363 if (obj->mouse_in)
364 {
365 obj->mouse_in = 0;
366 if (e->events_frozen <= 0)
367 evas_object_event_callback_call(obj, EVAS_CALLBACK_MOUSE_OUT, &ev, event_id);
368 }
369 }
370 if (e->delete_me) break;
371 }
372 _evas_post_event_callback_call(e);
373
374 if (copy) copy = eina_list_free(copy);
375 if (e->pointer.inside)
376 {
377 Evas_Event_Mouse_In ev_in;
378 Evas_Object *obj_itr;
379
380 _evas_object_event_new();
381
382 event_id = _evas_event_counter;
383 ev_in.buttons = e->pointer.button;
384 ev_in.output.x = e->pointer.x;
385 ev_in.output.y = e->pointer.y;
386 ev_in.canvas.x = e->pointer.x;
387 ev_in.canvas.y = e->pointer.y;
388 ev_in.data = (void *)data;
389 ev_in.modifiers = &(e->modifiers);
390 ev_in.locks = &(e->locks);
391 ev_in.timestamp = timestamp;
392 ev_in.event_flags = e->default_event_flags;
393
394 EINA_LIST_FOREACH(ins, l, obj_itr)
395 {
396 ev_in.canvas.x = e->pointer.x;
397 ev_in.canvas.y = e->pointer.y;
398 _evas_event_havemap_adjust(obj_itr, &ev_in.canvas.x, &ev_in.canvas.y, obj_itr->mouse_grabbed);
399 if (!eina_list_data_find(e->pointer.object.in, obj_itr))
400 {
401 if (!obj_itr->mouse_in)
402 {
403 obj_itr->mouse_in = 1;
404 if (e->events_frozen <= 0)
405 evas_object_event_callback_call(obj_itr, EVAS_CALLBACK_MOUSE_IN, &ev_in, event_id);
406 }
407 }
408 if (e->delete_me) break;
409 }
410 post_called = 1;
411 _evas_post_event_callback_call(e);
412 }
413 else
414 {
415 ins = eina_list_free(ins);
416 }
417
418 if (e->pointer.mouse_grabbed == 0)
419 {
420 /* free our old list of ins */
421 eina_list_free(e->pointer.object.in);
422 /* and set up the new one */
423 e->pointer.object.in = ins;
424 }
425 else
426 {
427 /* free our cur ins */
428 eina_list_free(ins);
429 }
430 if (e->pointer.inside)
431 evas_event_feed_mouse_move(e, e->pointer.x, e->pointer.y, timestamp, data);
432 return post_called;
433}
434
435EAPI void
436evas_event_feed_mouse_up(Evas *e, int b, Evas_Button_Flags flags, unsigned int timestamp, const void *data)
437{
438 Eina_List *l, *copy;
439
440 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
441 return;
442 MAGIC_CHECK_END();
443
444 if ((b < 1) || (b > 32)) return;
445
446 e->pointer.button &= ~(1 << (b - 1));
447 e->pointer.downs--;
448
449 if (e->events_frozen > 0) return;
450 e->last_timestamp = timestamp;
451
452 {
453 Evas_Event_Mouse_Up ev;
454 Evas_Object *obj;
455 int event_id = 0;
456
457 _evas_object_event_new();
458
459 event_id = _evas_event_counter;
460 ev.button = b;
461 ev.output.x = e->pointer.x;
462 ev.output.y = e->pointer.y;
463 ev.canvas.x = e->pointer.x;
464 ev.canvas.y = e->pointer.y;
465 ev.data = (void *)data;
466 ev.modifiers = &(e->modifiers);
467 ev.locks = &(e->locks);
468 ev.flags = flags;
469 ev.timestamp = timestamp;
470 ev.event_flags = e->default_event_flags;
471
472 _evas_walk(e);
473 /* update released touch point */
474 _evas_touch_point_update(e, 0, e->pointer.x, e->pointer.y, EVAS_TOUCH_POINT_UP);
475 copy = evas_event_list_copy(e->pointer.object.in);
476 EINA_LIST_FOREACH(copy, l, obj)
477 {
478 ev.canvas.x = e->pointer.x;
479 ev.canvas.y = e->pointer.y;
480 _evas_event_havemap_adjust(obj, &ev.canvas.x, &ev.canvas.y, obj->mouse_grabbed);
481 if ((obj->pointer_mode == EVAS_OBJECT_POINTER_MODE_AUTOGRAB) &&
482 (obj->mouse_grabbed > 0))
483 {
484 obj->mouse_grabbed--;
485 e->pointer.mouse_grabbed--;
486 }
487 if (!obj->delete_me)
488 {
489 if ((e->events_frozen <= 0) &&
490 (!evas_event_freezes_through(obj)))
491 evas_object_event_callback_call(obj, EVAS_CALLBACK_MOUSE_UP, &ev, event_id);
492 }
493 if (e->delete_me) break;
494 if (obj->pointer_mode == EVAS_OBJECT_POINTER_MODE_NOGRAB_NO_REPEAT_UPDOWN)
495 {
496 if (e->pointer.nogrep > 0) e->pointer.nogrep--;
497 break;
498 }
499 }
500 if (copy) copy = eina_list_free(copy);
501 e->last_mouse_up_counter++;
502 _evas_post_event_callback_call(e);
503 }
504
505 if (e->pointer.mouse_grabbed == 0)
506 {
507 _post_up_handle(e, timestamp, data);
508 }
509
510 if (e->pointer.mouse_grabbed < 0)
511 {
512 ERR("BUG? e->pointer.mouse_grabbed (=%d) < 0!",
513 e->pointer.mouse_grabbed);
514 }
515 /* remove released touch point from the touch point list */
516 _evas_touch_point_remove(e, 0);
517
518 _evas_unwalk(e);
519}
520
521EAPI void
522evas_event_feed_mouse_cancel(Evas *e, unsigned int timestamp, const void *data)
523{
524 int i;
525
526 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
527 return;
528 MAGIC_CHECK_END();
529
530 if (e->events_frozen > 0) return;
531
532 _evas_walk(e);
533 for (i = 0; i < 32; i++)
534 {
535 if ((e->pointer.button & (1 << i)))
536 evas_event_feed_mouse_up(e, i + 1, 0, timestamp, data);
537 }
538 // FIXME: multi cancel too?
539 _evas_unwalk(e);
540}
541
542EAPI void
543evas_event_feed_mouse_wheel(Evas *e, int direction, int z, unsigned int timestamp, const void *data)
544{
545 Eina_List *l, *copy;
546 Evas_Event_Mouse_Wheel ev;
547 Evas_Object *obj;
548 int event_id = 0;
549
550 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
551 return;
552 MAGIC_CHECK_END();
553
554 if (e->events_frozen > 0) return;
555 e->last_timestamp = timestamp;
556
557 _evas_object_event_new();
558
559 event_id = _evas_event_counter;
560 ev.direction = direction;
561 ev.z = z;
562 ev.output.x = e->pointer.x;
563 ev.output.y = e->pointer.y;
564 ev.canvas.x = e->pointer.x;
565 ev.canvas.y = e->pointer.y;
566 ev.data = (void *) data;
567 ev.modifiers = &(e->modifiers);
568 ev.locks = &(e->locks);
569 ev.timestamp = timestamp;
570 ev.event_flags = e->default_event_flags;
571
572 _evas_walk(e);
573 copy = evas_event_list_copy(e->pointer.object.in);
574
575 EINA_LIST_FOREACH(copy, l, obj)
576 {
577 ev.canvas.x = e->pointer.x;
578 ev.canvas.y = e->pointer.y;
579 _evas_event_havemap_adjust(obj, &ev.canvas.x, &ev.canvas.y, obj->mouse_grabbed);
580 if ((e->events_frozen <= 0) && !evas_event_freezes_through(obj))
581 evas_object_event_callback_call(obj, EVAS_CALLBACK_MOUSE_WHEEL, &ev, event_id);
582 if (e->delete_me) break;
583 }
584 if (copy) copy = eina_list_free(copy);
585 _evas_post_event_callback_call(e);
586
587 _evas_unwalk(e);
588}
589
590EAPI void
591evas_event_feed_mouse_move(Evas *e, int x, int y, unsigned int timestamp, const void *data)
592{
593 Evas_Object *nogrep_obj = NULL;
594 int px, py;
595//// Evas_Coord pcx, pcy;
596
597 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
598 return;
599 MAGIC_CHECK_END();
600
601 px = e->pointer.x;
602 py = e->pointer.y;
603//// pcx = e->pointer.canvas_x;
604//// pcy = e->pointer.canvas_y;
605
606 if (e->events_frozen > 0) return;
607 e->last_timestamp = timestamp;
608
609 e->pointer.x = x;
610 e->pointer.y = y;
611//// e->pointer.canvas_x = x;
612//// e->pointer.canvas_y = y;
613//// e->pointer.canvas_x = evas_coord_screen_x_to_world(e, x);
614//// e->pointer.canvas_y = evas_coord_screen_y_to_world(e, y);
615 if ((!e->pointer.inside) && (e->pointer.mouse_grabbed == 0)) return;
616 _evas_walk(e);
617 /* update moved touch point */
618 if ((px != x) || (py != y))
619 _evas_touch_point_update(e, 0, e->pointer.x, e->pointer.y, EVAS_TOUCH_POINT_MOVE);
620 /* if our mouse button is grabbed to any objects */
621 if (e->pointer.mouse_grabbed > 0)
622 {
623 /* go thru old list of in objects */
624 Eina_List *outs = NULL;
625 Eina_List *l, *copy;
626
627 {
628 Evas_Event_Mouse_Move ev;
629 Evas_Object *obj;
630 int event_id = 0;
631
632 _evas_object_event_new();
633
634 event_id = _evas_event_counter;
635 ev.buttons = e->pointer.button;
636 ev.cur.output.x = e->pointer.x;
637 ev.cur.output.y = e->pointer.y;
638 ev.cur.canvas.x = e->pointer.x;
639 ev.cur.canvas.y = e->pointer.y;
640 ev.prev.output.x = px;
641 ev.prev.output.y = py;
642 ev.prev.canvas.x = px;
643 ev.prev.canvas.y = py;
644 ev.data = (void *)data;
645 ev.modifiers = &(e->modifiers);
646 ev.locks = &(e->locks);
647 ev.timestamp = timestamp;
648 ev.event_flags = e->default_event_flags;
649 copy = evas_event_list_copy(e->pointer.object.in);
650 EINA_LIST_FOREACH(copy, l, obj)
651 {
652 ev.cur.canvas.x = e->pointer.x;
653 ev.cur.canvas.y = e->pointer.y;
654 _evas_event_havemap_adjust(obj, &ev.cur.canvas.x,
655 &ev.cur.canvas.y,
656 obj->mouse_grabbed);
657 if ((e->events_frozen <= 0) &&
658 (evas_object_clippers_is_visible(obj) ||
659 obj->mouse_grabbed) &&
660 (!evas_event_passes_through(obj)) &&
661 (!evas_event_freezes_through(obj)) &&
662 (!obj->clip.clipees))
663 {
664 if ((px != x) || (py != y))
665 evas_object_event_callback_call(obj, EVAS_CALLBACK_MOUSE_MOVE, &ev, event_id);
666 }
667 else
668 outs = eina_list_append(outs, obj);
669 if ((obj->pointer_mode == EVAS_OBJECT_POINTER_MODE_NOGRAB_NO_REPEAT_UPDOWN) &&
670 (e->pointer.nogrep > 0))
671 {
672 eina_list_free(copy);
673 nogrep_obj = obj;
674 goto nogrep;
675 }
676 if (e->delete_me) break;
677 }
678 _evas_post_event_callback_call(e);
679 }
680 {
681 Evas_Event_Mouse_Out ev;
682 int event_id = 0;
683
684 _evas_object_event_new();
685
686 event_id = _evas_event_counter;
687 ev.buttons = e->pointer.button;
688 ev.output.x = e->pointer.x;
689 ev.output.y = e->pointer.y;
690 ev.canvas.x = e->pointer.x;
691 ev.canvas.y = e->pointer.y;
692 ev.data = (void *)data;
693 ev.modifiers = &(e->modifiers);
694 ev.locks = &(e->locks);
695 ev.timestamp = timestamp;
696 ev.event_flags = e->default_event_flags;
697
698 if (copy) eina_list_free(copy);
699 while (outs)
700 {
701 Evas_Object *obj;
702
703 obj = outs->data;
704 outs = eina_list_remove(outs, obj);
705 if ((obj->mouse_grabbed == 0) && (!e->delete_me))
706 {
707 ev.canvas.x = e->pointer.x;
708 ev.canvas.y = e->pointer.y;
709 _evas_event_havemap_adjust(obj, &ev.canvas.x, &ev.canvas.y, obj->mouse_grabbed);
710 e->pointer.object.in = eina_list_remove(e->pointer.object.in, obj);
711 if (obj->mouse_in)
712 {
713 obj->mouse_in = 0;
714 if (!obj->delete_me)
715 {
716 if (e->events_frozen <= 0)
717 evas_object_event_callback_call(obj, EVAS_CALLBACK_MOUSE_OUT, &ev, event_id);
718 }
719 }
720 }
721 }
722 _evas_post_event_callback_call(e);
723 }
724 }
725 else
726 {
727 Eina_List *ins;
728 Eina_List *l, *copy;
729 Evas_Event_Mouse_Move ev;
730 Evas_Event_Mouse_Out ev2;
731 Evas_Event_Mouse_In ev3;
732 Evas_Object *obj;
733 int event_id = 0, event_id2 = 0;
734
735 _evas_object_event_new();
736
737 event_id = _evas_event_counter;
738 ev.buttons = e->pointer.button;
739 ev.cur.output.x = e->pointer.x;
740 ev.cur.output.y = e->pointer.y;
741 ev.cur.canvas.x = e->pointer.x;
742 ev.cur.canvas.y = e->pointer.y;
743 ev.prev.output.x = px;
744 ev.prev.output.y = py;
745 ev.prev.canvas.x = px;
746 ev.prev.canvas.y = py;
747 ev.data = (void *)data;
748 ev.modifiers = &(e->modifiers);
749 ev.locks = &(e->locks);
750 ev.timestamp = timestamp;
751 ev.event_flags = e->default_event_flags;
752
753 ev2.buttons = e->pointer.button;
754 ev2.output.x = e->pointer.x;
755 ev2.output.y = e->pointer.y;
756 ev2.canvas.x = e->pointer.x;
757 ev2.canvas.y = e->pointer.y;
758 ev2.data = (void *)data;
759 ev2.modifiers = &(e->modifiers);
760 ev2.locks = &(e->locks);
761 ev2.timestamp = timestamp;
762 ev2.event_flags = e->default_event_flags;
763
764 ev3.buttons = e->pointer.button;
765 ev3.output.x = e->pointer.x;
766 ev3.output.y = e->pointer.y;
767 ev3.canvas.x = e->pointer.x;
768 ev3.canvas.y = e->pointer.y;
769 ev3.data = (void *)data;
770 ev3.modifiers = &(e->modifiers);
771 ev3.locks = &(e->locks);
772 ev3.timestamp = timestamp;
773 ev3.event_flags = e->default_event_flags;
774
775 /* get all new in objects */
776 ins = evas_event_objects_event_list(e, NULL, x, y);
777 /* go thru old list of in objects */
778 copy = evas_event_list_copy(e->pointer.object.in);
779 EINA_LIST_FOREACH(copy, l, obj)
780 {
781 /* if its under the pointer and its visible and its in the new */
782 /* in list */
783 // FIXME: i don't think we need this
784 // evas_object_clip_recalc(obj);
785 if ((e->events_frozen <= 0) &&
786 evas_object_is_in_output_rect(obj, x, y, 1, 1) &&
787 (evas_object_clippers_is_visible(obj) ||
788 obj->mouse_grabbed) &&
789 eina_list_data_find(ins, obj) &&
790 (!evas_event_passes_through(obj)) &&
791 (!evas_event_freezes_through(obj)) &&
792 (!obj->clip.clipees) &&
793 ((!obj->precise_is_inside) || evas_object_is_inside(obj, x, y))
794 )
795 {
796 if ((px != x) || (py != y))
797 {
798 ev.cur.canvas.x = e->pointer.x;
799 ev.cur.canvas.y = e->pointer.y;
800 _evas_event_havemap_adjust(obj, &ev.cur.canvas.x, &ev.cur.canvas.y, obj->mouse_grabbed);
801 evas_object_event_callback_call(obj, EVAS_CALLBACK_MOUSE_MOVE, &ev, event_id);
802 }
803 }
804 /* otherwise it has left the object */
805 else
806 {
807 if (obj->mouse_in)
808 {
809 obj->mouse_in = 0;
810 ev2.canvas.x = e->pointer.x;
811 ev2.canvas.y = e->pointer.y;
812 _evas_event_havemap_adjust(obj, &ev2.canvas.x, &ev2.canvas.y, obj->mouse_grabbed);
813 if (e->events_frozen <= 0)
814 evas_object_event_callback_call(obj, EVAS_CALLBACK_MOUSE_OUT, &ev2, event_id);
815 }
816 }
817 if (e->delete_me) break;
818 }
819 _evas_post_event_callback_call(e);
820
821 _evas_object_event_new();
822
823 event_id2 = _evas_event_counter;
824 if (copy) copy = eina_list_free(copy);
825 /* go thru our current list of ins */
826 EINA_LIST_FOREACH(ins, l, obj)
827 {
828 ev3.canvas.x = e->pointer.x;
829 ev3.canvas.y = e->pointer.y;
830 _evas_event_havemap_adjust(obj, &ev3.canvas.x, &ev3.canvas.y, obj->mouse_grabbed);
831 /* if its not in the old list of ins send an enter event */
832 if (!eina_list_data_find(e->pointer.object.in, obj))
833 {
834 if (!obj->mouse_in)
835 {
836 obj->mouse_in = 1;
837 if (e->events_frozen <= 0)
838 evas_object_event_callback_call(obj, EVAS_CALLBACK_MOUSE_IN, &ev3, event_id2);
839 }
840 }
841 if (e->delete_me) break;
842 }
843 if (e->pointer.mouse_grabbed == 0)
844 {
845 /* free our old list of ins */
846 eina_list_free(e->pointer.object.in);
847 /* and set up the new one */
848 e->pointer.object.in = ins;
849 }
850 else
851 {
852 /* free our cur ins */
853 eina_list_free(ins);
854 }
855 _evas_post_event_callback_call(e);
856 }
857 _evas_unwalk(e);
858 return;
859nogrep:
860 {
861 Eina_List *ins = NULL;
862 Eina_List *newin = NULL;
863 Eina_List *l, *copy, *lst = NULL;
864 Evas_Event_Mouse_Move ev;
865 Evas_Event_Mouse_Out ev2;
866 Evas_Event_Mouse_In ev3;
867 Evas_Object *obj, *below_obj;
868 int event_id = 0, event_id2 = 0;
869 int norep = 0, breaknext = 0;
870
871 _evas_object_event_new();
872
873 event_id = _evas_event_counter;
874 ev.buttons = e->pointer.button;
875 ev.cur.output.x = e->pointer.x;
876 ev.cur.output.y = e->pointer.y;
877 ev.cur.canvas.x = e->pointer.x;
878 ev.cur.canvas.y = e->pointer.y;
879 ev.prev.output.x = px;
880 ev.prev.output.y = py;
881 ev.prev.canvas.x = px;
882 ev.prev.canvas.y = py;
883 ev.data = (void *)data;
884 ev.modifiers = &(e->modifiers);
885 ev.locks = &(e->locks);
886 ev.timestamp = timestamp;
887 ev.event_flags = e->default_event_flags;
888
889 ev2.buttons = e->pointer.button;
890 ev2.output.x = e->pointer.x;
891 ev2.output.y = e->pointer.y;
892 ev2.canvas.x = e->pointer.x;
893 ev2.canvas.y = e->pointer.y;
894 ev2.data = (void *)data;
895 ev2.modifiers = &(e->modifiers);
896 ev2.locks = &(e->locks);
897 ev2.timestamp = timestamp;
898 ev2.event_flags = e->default_event_flags;
899
900 ev3.buttons = e->pointer.button;
901 ev3.output.x = e->pointer.x;
902 ev3.output.y = e->pointer.y;
903 ev3.canvas.x = e->pointer.x;
904 ev3.canvas.y = e->pointer.y;
905 ev3.data = (void *)data;
906 ev3.modifiers = &(e->modifiers);
907 ev3.locks = &(e->locks);
908 ev3.timestamp = timestamp;
909 ev3.event_flags = e->default_event_flags;
910
911 /* go thru old list of in objects */
912 copy = evas_event_list_copy(e->pointer.object.in);
913 EINA_LIST_FOREACH(copy, l, obj)
914 {
915 if (breaknext)
916 {
917 lst = l;
918 break;
919 }
920 if (obj == nogrep_obj) breaknext = 1;
921 }
922
923 /* get all new in objects */
924 below_obj = evas_object_below_get(nogrep_obj);
925 if (below_obj)
926 ins = _evas_event_object_list_raw_in_get(e, NULL,
927 EINA_INLIST_GET(below_obj), NULL,
928 e->pointer.x, e->pointer.y,
929 &norep);
930 EINA_LIST_FOREACH(copy, l, obj)
931 {
932 newin = eina_list_append(newin, obj);
933 if (obj == nogrep_obj) break;
934 }
935 EINA_LIST_FOREACH(ins, l, obj)
936 {
937 newin = eina_list_append(newin, obj);
938 }
939
940 EINA_LIST_FOREACH(lst, l, obj)
941 {
942 /* if its under the pointer and its visible and its in the new */
943 /* in list */
944 // FIXME: i don't think we need this
945 // evas_object_clip_recalc(obj);
946 if ((e->events_frozen <= 0) &&
947 evas_object_is_in_output_rect(obj, x, y, 1, 1) &&
948 (evas_object_clippers_is_visible(obj) ||
949 obj->mouse_grabbed) &&
950 eina_list_data_find(newin, obj) &&
951 (!evas_event_passes_through(obj)) &&
952 (!evas_event_freezes_through(obj)) &&
953 (!obj->clip.clipees) &&
954 ((!obj->precise_is_inside) || evas_object_is_inside(obj, x, y))
955 )
956 {
957 if ((px != x) || (py != y))
958 {
959 ev.cur.canvas.x = e->pointer.x;
960 ev.cur.canvas.y = e->pointer.y;
961 _evas_event_havemap_adjust(obj, &ev.cur.canvas.x, &ev.cur.canvas.y, obj->mouse_grabbed);
962 evas_object_event_callback_call(obj, EVAS_CALLBACK_MOUSE_MOVE, &ev, event_id);
963 }
964 }
965 /* otherwise it has left the object */
966 else
967 {
968 if (obj->mouse_in)
969 {
970 obj->mouse_in = 0;
971 ev2.canvas.x = e->pointer.x;
972 ev2.canvas.y = e->pointer.y;
973 _evas_event_havemap_adjust(obj, &ev2.canvas.x, &ev2.canvas.y, obj->mouse_grabbed);
974 if (e->events_frozen <= 0)
975 evas_object_event_callback_call(obj, EVAS_CALLBACK_MOUSE_OUT, &ev2, event_id);
976 }
977 }
978 if (e->delete_me) break;
979 }
980 _evas_post_event_callback_call(e);
981
982 _evas_object_event_new();
983
984 event_id2 = _evas_event_counter;
985 if (copy) copy = eina_list_free(copy);
986 /* go thru our current list of ins */
987 EINA_LIST_FOREACH(newin, l, obj)
988 {
989 ev3.canvas.x = e->pointer.x;
990 ev3.canvas.y = e->pointer.y;
991 _evas_event_havemap_adjust(obj, &ev3.canvas.x, &ev3.canvas.y, obj->mouse_grabbed);
992 /* if its not in the old list of ins send an enter event */
993 if (!eina_list_data_find(e->pointer.object.in, obj))
994 {
995 if (!obj->mouse_in)
996 {
997 obj->mouse_in = 1;
998 if (e->events_frozen <= 0)
999 evas_object_event_callback_call(obj, EVAS_CALLBACK_MOUSE_IN, &ev3, event_id2);
1000 }
1001 }
1002 if (e->delete_me) break;
1003 }
1004 /* free our old list of ins */
1005 eina_list_free(e->pointer.object.in);
1006 /* and set up the new one */
1007 e->pointer.object.in = newin;
1008
1009 _evas_post_event_callback_call(e);
1010 }
1011 _evas_unwalk(e);
1012}
1013
1014EAPI void
1015evas_event_feed_mouse_in(Evas *e, unsigned int timestamp, const void *data)
1016{
1017 Eina_List *ins;
1018 Eina_List *l;
1019 Evas_Event_Mouse_In ev;
1020 Evas_Object *obj;
1021 int event_id = 0;
1022
1023 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1024 return;
1025 MAGIC_CHECK_END();
1026 e->pointer.inside = 1;
1027
1028 if (e->events_frozen > 0) return;
1029 e->last_timestamp = timestamp;
1030
1031 if (e->pointer.mouse_grabbed != 0) return;
1032
1033 _evas_object_event_new();
1034
1035 event_id = _evas_event_counter;
1036 ev.buttons = e->pointer.button;
1037 ev.output.x = e->pointer.x;
1038 ev.output.y = e->pointer.y;
1039 ev.canvas.x = e->pointer.x;
1040 ev.canvas.y = e->pointer.y;
1041 ev.data = (void *)data;
1042 ev.modifiers = &(e->modifiers);
1043 ev.locks = &(e->locks);
1044 ev.timestamp = timestamp;
1045 ev.event_flags = e->default_event_flags;
1046
1047 _evas_walk(e);
1048 /* get new list of ins */
1049 ins = evas_event_objects_event_list(e, NULL, e->pointer.x, e->pointer.y);
1050 EINA_LIST_FOREACH(ins, l, obj)
1051 {
1052 ev.canvas.x = e->pointer.x;
1053 ev.canvas.y = e->pointer.y;
1054 _evas_event_havemap_adjust(obj, &ev.canvas.x, &ev.canvas.y, obj->mouse_grabbed);
1055 if (!eina_list_data_find(e->pointer.object.in, obj))
1056 {
1057 if (!obj->mouse_in)
1058 {
1059 obj->mouse_in = 1;
1060 if (e->events_frozen <= 0)
1061 evas_object_event_callback_call(obj, EVAS_CALLBACK_MOUSE_IN, &ev, event_id);
1062 }
1063 }
1064 if (e->delete_me) break;
1065 }
1066 /* free our old list of ins */
1067 e->pointer.object.in = eina_list_free(e->pointer.object.in);
1068 /* and set up the new one */
1069 e->pointer.object.in = ins;
1070 _evas_post_event_callback_call(e);
1071 evas_event_feed_mouse_move(e, e->pointer.x, e->pointer.y, timestamp, data);
1072 _evas_unwalk(e);
1073}
1074
1075EAPI void
1076evas_event_feed_mouse_out(Evas *e, unsigned int timestamp, const void *data)
1077{
1078 Evas_Event_Mouse_Out ev;
1079 int event_id = 0;
1080
1081 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1082 return;
1083 MAGIC_CHECK_END();
1084 e->pointer.inside = 0;
1085
1086 if (e->events_frozen > 0) return;
1087 e->last_timestamp = timestamp;
1088
1089 _evas_object_event_new();
1090
1091 event_id = _evas_event_counter;
1092 ev.buttons = e->pointer.button;
1093 ev.output.x = e->pointer.x;
1094 ev.output.y = e->pointer.y;
1095 ev.canvas.x = e->pointer.x;
1096 ev.canvas.y = e->pointer.y;
1097 ev.data = (void *)data;
1098 ev.modifiers = &(e->modifiers);
1099 ev.locks = &(e->locks);
1100 ev.timestamp = timestamp;
1101 ev.event_flags = e->default_event_flags;
1102
1103 _evas_walk(e);
1104 /* if our mouse button is inside any objects */
1105 {
1106 /* go thru old list of in objects */
1107 Eina_List *l, *copy;
1108 Evas_Object *obj;
1109
1110 copy = evas_event_list_copy(e->pointer.object.in);
1111 EINA_LIST_FOREACH(copy, l, obj)
1112 {
1113 ev.canvas.x = e->pointer.x;
1114 ev.canvas.y = e->pointer.y;
1115 _evas_event_havemap_adjust(obj, &ev.canvas.x, &ev.canvas.y, obj->mouse_grabbed);
1116 if (obj->mouse_in)
1117 {
1118 obj->mouse_in = 0;
1119 if (!obj->delete_me)
1120 {
1121 if (e->events_frozen <= 0)
1122 evas_object_event_callback_call(obj, EVAS_CALLBACK_MOUSE_OUT, &ev, event_id);
1123 }
1124 obj->mouse_grabbed = 0;
1125 }
1126 if (e->delete_me) break;
1127 }
1128 if (copy) copy = eina_list_free(copy);
1129 /* free our old list of ins */
1130 e->pointer.object.in = eina_list_free(e->pointer.object.in);
1131 e->pointer.mouse_grabbed = 0;
1132 _evas_post_event_callback_call(e);
1133 }
1134 _evas_unwalk(e);
1135}
1136
1137EAPI void
1138evas_event_feed_multi_down(Evas *e,
1139 int d, int x, int y,
1140 double rad, double radx, double rady,
1141 double pres, double ang,
1142 double fx, double fy,
1143 Evas_Button_Flags flags, unsigned int timestamp,
1144 const void *data)
1145{
1146 Eina_List *l, *copy;
1147 Evas_Event_Multi_Down ev;
1148 Evas_Object *obj;
1149 int addgrab = 0;
1150 int event_id = 0;
1151
1152 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1153 return;
1154 MAGIC_CHECK_END();
1155
1156 e->pointer.downs++;
1157 if (e->events_frozen > 0) return;
1158 e->last_timestamp = timestamp;
1159
1160 _evas_object_event_new();
1161
1162 event_id = _evas_event_counter;
1163 ev.device = d;
1164 ev.output.x = x;
1165 ev.output.y = y;
1166 ev.canvas.x = x;
1167 ev.canvas.y = y;
1168 ev.radius = rad;
1169 ev.radius_x = radx;
1170 ev.radius_y = rady;
1171 ev.pressure = pres;
1172 ev.angle = ang;
1173 ev.canvas.xsub = fx;
1174 ev.canvas.ysub = fy;
1175 ev.data = (void *)data;
1176 ev.modifiers = &(e->modifiers);
1177 ev.locks = &(e->locks);
1178 ev.flags = flags;
1179 ev.timestamp = timestamp;
1180 ev.event_flags = e->default_event_flags;
1181
1182 _evas_walk(e);
1183 /* append new touch point to the touch point list */
1184 _evas_touch_point_append(e, d, x, y);
1185 if (e->pointer.mouse_grabbed == 0)
1186 {
1187 if (e->pointer.downs > 1) addgrab = e->pointer.downs - 1;
1188 }
1189 copy = evas_event_list_copy(e->pointer.object.in);
1190 EINA_LIST_FOREACH(copy, l, obj)
1191 {
1192 if (obj->pointer_mode != EVAS_OBJECT_POINTER_MODE_NOGRAB)
1193 {
1194 obj->mouse_grabbed += addgrab + 1;
1195 e->pointer.mouse_grabbed += addgrab + 1;
1196 }
1197 }
1198 EINA_LIST_FOREACH(copy, l, obj)
1199 {
1200 ev.canvas.x = x;
1201 ev.canvas.y = y;
1202 ev.canvas.xsub = fx;
1203 ev.canvas.ysub = fy;
1204 _evas_event_havemap_adjust(obj, &ev.canvas.x, &ev.canvas.y, obj->mouse_grabbed);
1205 if (x != ev.canvas.x)
1206 ev.canvas.xsub = ev.canvas.x; // fixme - lost precision
1207 if (y != ev.canvas.y)
1208 ev.canvas.ysub = ev.canvas.y; // fixme - lost precision
1209 if (e->events_frozen <= 0)
1210 evas_object_event_callback_call(obj, EVAS_CALLBACK_MULTI_DOWN, &ev, event_id);
1211 if (e->delete_me) break;
1212 }
1213 if (copy) eina_list_free(copy);
1214 _evas_post_event_callback_call(e);
1215 /* update touch point's state to EVAS_TOUCH_POINT_STILL */
1216 _evas_touch_point_update(e, d, x, y, EVAS_TOUCH_POINT_STILL);
1217 _evas_unwalk(e);
1218}
1219
1220EAPI void
1221evas_event_feed_multi_up(Evas *e,
1222 int d, int x, int y,
1223 double rad, double radx, double rady,
1224 double pres, double ang,
1225 double fx, double fy,
1226 Evas_Button_Flags flags, unsigned int timestamp,
1227 const void *data)
1228{
1229 Eina_List *l, *copy;
1230 Evas_Event_Multi_Up ev;
1231 Evas_Object *obj;
1232 int event_id = 0;
1233
1234 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1235 return;
1236 MAGIC_CHECK_END();
1237
1238 e->pointer.downs--;
1239 if (e->events_frozen > 0) return;
1240 e->last_timestamp = timestamp;
1241
1242 _evas_object_event_new();
1243
1244 event_id = _evas_event_counter;
1245 ev.device = d;
1246 ev.output.x = x;
1247 ev.output.y = y;
1248 ev.canvas.x = x;
1249 ev.canvas.y = y;
1250 ev.radius = rad;
1251 ev.radius_x = radx;
1252 ev.radius_y = rady;
1253 ev.pressure = pres;
1254 ev.angle = ang;
1255 ev.canvas.xsub = fx;
1256 ev.canvas.ysub = fy;
1257 ev.data = (void *)data;
1258 ev.modifiers = &(e->modifiers);
1259 ev.locks = &(e->locks);
1260 ev.flags = flags;
1261 ev.timestamp = timestamp;
1262 ev.event_flags = e->default_event_flags;
1263
1264 _evas_walk(e);
1265 /* update released touch point */
1266 _evas_touch_point_update(e, d, x, y, EVAS_TOUCH_POINT_UP);
1267 copy = evas_event_list_copy(e->pointer.object.in);
1268 EINA_LIST_FOREACH(copy, l, obj)
1269 {
1270 ev.canvas.x = x;
1271 ev.canvas.y = y;
1272 ev.canvas.xsub = fx;
1273 ev.canvas.ysub = fy;
1274 _evas_event_havemap_adjust(obj, &ev.canvas.x, &ev.canvas.y, obj->mouse_grabbed);
1275 if (x != ev.canvas.x)
1276 ev.canvas.xsub = ev.canvas.x; // fixme - lost precision
1277 if (y != ev.canvas.y)
1278 ev.canvas.ysub = ev.canvas.y; // fixme - lost precision
1279 if ((obj->pointer_mode != EVAS_OBJECT_POINTER_MODE_NOGRAB) &&
1280 (obj->mouse_grabbed > 0))
1281 {
1282 obj->mouse_grabbed--;
1283 e->pointer.mouse_grabbed--;
1284 }
1285 if (e->events_frozen <= 0)
1286 evas_object_event_callback_call(obj, EVAS_CALLBACK_MULTI_UP, &ev, event_id);
1287 if (e->delete_me) break;
1288 }
1289 if (copy) copy = eina_list_free(copy);
1290 if ((e->pointer.mouse_grabbed == 0) && !_post_up_handle(e, timestamp, data))
1291 _evas_post_event_callback_call(e);
1292 /* remove released touch point from the touch point list */
1293 _evas_touch_point_remove(e, d);
1294 _evas_unwalk(e);
1295}
1296
1297EAPI void
1298evas_event_feed_multi_move(Evas *e,
1299 int d, int x, int y,
1300 double rad, double radx, double rady,
1301 double pres, double ang,
1302 double fx, double fy,
1303 unsigned int timestamp, const void *data)
1304{
1305 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1306 return;
1307 MAGIC_CHECK_END();
1308
1309 if (e->events_frozen > 0) return;
1310 e->last_timestamp = timestamp;
1311
1312 if ((!e->pointer.inside) && (e->pointer.mouse_grabbed == 0)) return;
1313
1314 _evas_walk(e);
1315 /* update moved touch point */
1316 _evas_touch_point_update(e, d, x, y, EVAS_TOUCH_POINT_MOVE);
1317 /* if our mouse button is grabbed to any objects */
1318 if (e->pointer.mouse_grabbed > 0)
1319 {
1320 /* go thru old list of in objects */
1321 Eina_List *l, *copy;
1322 Evas_Event_Multi_Move ev;
1323 Evas_Object *obj;
1324 int event_id = 0;
1325
1326 _evas_object_event_new();
1327
1328 event_id = _evas_event_counter;
1329 ev.device = d;
1330 ev.cur.output.x = x;
1331 ev.cur.output.y = y;
1332 ev.cur.canvas.x = x;
1333 ev.cur.canvas.y = y;
1334 ev.radius = rad;
1335 ev.radius_x = radx;
1336 ev.radius_y = rady;
1337 ev.pressure = pres;
1338 ev.angle = ang;
1339 ev.cur.canvas.xsub = fx;
1340 ev.cur.canvas.ysub = fy;
1341 ev.data = (void *)data;
1342 ev.modifiers = &(e->modifiers);
1343 ev.locks = &(e->locks);
1344 ev.timestamp = timestamp;
1345 ev.event_flags = e->default_event_flags;
1346
1347 copy = evas_event_list_copy(e->pointer.object.in);
1348 EINA_LIST_FOREACH(copy, l, obj)
1349 {
1350 if ((e->events_frozen <= 0) &&
1351 (evas_object_clippers_is_visible(obj) || obj->mouse_grabbed) &&
1352 (!evas_event_passes_through(obj)) &&
1353 (!evas_event_freezes_through(obj)) &&
1354 (!obj->clip.clipees))
1355 {
1356 ev.cur.canvas.x = x;
1357 ev.cur.canvas.y = y;
1358 ev.cur.canvas.xsub = fx;
1359 ev.cur.canvas.ysub = fy;
1360 _evas_event_havemap_adjust(obj, &ev.cur.canvas.x, &ev.cur.canvas.y, obj->mouse_grabbed);
1361 if (x != ev.cur.canvas.x)
1362 ev.cur.canvas.xsub = ev.cur.canvas.x; // fixme - lost precision
1363 if (y != ev.cur.canvas.y)
1364 ev.cur.canvas.ysub = ev.cur.canvas.y; // fixme - lost precision
1365 evas_object_event_callback_call(obj, EVAS_CALLBACK_MULTI_MOVE, &ev, event_id);
1366 }
1367 if (e->delete_me) break;
1368 }
1369 _evas_post_event_callback_call(e);
1370 }
1371 else
1372 {
1373 Eina_List *ins;
1374 Eina_List *l, *copy;
1375 Evas_Event_Multi_Move ev;
1376 Evas_Object *obj;
1377 int event_id = 0;
1378
1379 _evas_object_event_new();
1380
1381 event_id = _evas_event_counter;
1382 ev.device = d;
1383 ev.cur.output.x = x;
1384 ev.cur.output.y = y;
1385 ev.cur.canvas.x = x;
1386 ev.cur.canvas.y = y;
1387 ev.radius = rad;
1388 ev.radius_x = radx;
1389 ev.radius_y = rady;
1390 ev.pressure = pres;
1391 ev.angle = ang;
1392 ev.cur.canvas.xsub = fx;
1393 ev.cur.canvas.ysub = fy;
1394 ev.data = (void *)data;
1395 ev.modifiers = &(e->modifiers);
1396 ev.locks = &(e->locks);
1397 ev.timestamp = timestamp;
1398 ev.event_flags = e->default_event_flags;
1399
1400 /* get all new in objects */
1401 ins = evas_event_objects_event_list(e, NULL, x, y);
1402 /* go thru old list of in objects */
1403 copy = evas_event_list_copy(e->pointer.object.in);
1404 EINA_LIST_FOREACH(copy, l, obj)
1405 {
1406 /* if its under the pointer and its visible and its in the new */
1407 /* in list */
1408 // FIXME: i don't think we need this
1409 // evas_object_clip_recalc(obj);
1410 if ((e->events_frozen <= 0) &&
1411 evas_object_is_in_output_rect(obj, x, y, 1, 1) &&
1412 (evas_object_clippers_is_visible(obj) ||
1413 obj->mouse_grabbed) &&
1414 eina_list_data_find(ins, obj) &&
1415 (!evas_event_passes_through(obj)) &&
1416 (!evas_event_freezes_through(obj)) &&
1417 (!obj->clip.clipees) &&
1418 ((!obj->precise_is_inside) || evas_object_is_inside(obj, x, y))
1419 )
1420 {
1421 ev.cur.canvas.x = x;
1422 ev.cur.canvas.y = y;
1423 ev.cur.canvas.xsub = fx;
1424 ev.cur.canvas.ysub = fy;
1425 _evas_event_havemap_adjust(obj, &ev.cur.canvas.x, &ev.cur.canvas.y, obj->mouse_grabbed);
1426 if (x != ev.cur.canvas.x)
1427 ev.cur.canvas.xsub = ev.cur.canvas.x; // fixme - lost precision
1428 if (y != ev.cur.canvas.y)
1429 ev.cur.canvas.ysub = ev.cur.canvas.y; // fixme - lost precision
1430 evas_object_event_callback_call(obj, EVAS_CALLBACK_MULTI_MOVE, &ev, event_id);
1431 }
1432 if (e->delete_me) break;
1433 }
1434 if (copy) copy = eina_list_free(copy);
1435 if (e->pointer.mouse_grabbed == 0)
1436 {
1437 /* free our old list of ins */
1438 eina_list_free(e->pointer.object.in);
1439 /* and set up the new one */
1440 e->pointer.object.in = ins;
1441 }
1442 else
1443 {
1444 /* free our cur ins */
1445 eina_list_free(ins);
1446 }
1447 _evas_post_event_callback_call(e);
1448 }
1449 _evas_unwalk(e);
1450}
1451
1452EAPI void
1453evas_event_feed_key_down(Evas *e, const char *keyname, const char *key, const char *string, const char *compose, unsigned int timestamp, const void *data)
1454{
1455 int event_id = 0;
1456 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1457 return;
1458 MAGIC_CHECK_END();
1459
1460 if (!keyname) return;
1461 if (e->events_frozen > 0) return;
1462 e->last_timestamp = timestamp;
1463 _evas_walk(e);
1464
1465 Evas_Event_Key_Down ev;
1466 Eina_Bool exclusive;
1467
1468 _evas_object_event_new();
1469
1470 event_id = _evas_event_counter;
1471 exclusive = EINA_FALSE;
1472 ev.keyname = (char *)keyname;
1473 ev.data = (void *)data;
1474 ev.modifiers = &(e->modifiers);
1475 ev.locks = &(e->locks);
1476 ev.key = key;
1477 ev.string = string;
1478 ev.compose = compose;
1479 ev.timestamp = timestamp;
1480 ev.event_flags = e->default_event_flags;
1481
1482 if (e->grabs)
1483 {
1484 Eina_List *l;
1485 Evas_Key_Grab *g;
1486
1487 e->walking_grabs++;
1488 EINA_LIST_FOREACH(e->grabs, l, g)
1489 {
1490 if (g->just_added)
1491 {
1492 g->just_added = EINA_FALSE;
1493 continue;
1494 }
1495 if (g->delete_me) continue;
1496 if (((e->modifiers.mask & g->modifiers) ||
1497 (g->modifiers == e->modifiers.mask)) &&
1498 (!strcmp(keyname, g->keyname)))
1499 {
1500 if (!(e->modifiers.mask & g->not_modifiers))
1501 {
1502 if (e->events_frozen <= 0 &&
1503 !evas_event_freezes_through(g->object))
1504 evas_object_event_callback_call(g->object,
1505 EVAS_CALLBACK_KEY_DOWN,
1506 &ev, event_id);
1507 if (g->exclusive) exclusive = EINA_TRUE;
1508 }
1509 }
1510 if (e->delete_me) break;
1511 }
1512 e->walking_grabs--;
1513 if (e->walking_grabs <= 0)
1514 {
1515 while (e->delete_grabs > 0)
1516 {
1517 e->delete_grabs--;
1518 for (l = e->grabs; l;)
1519 {
1520 g = eina_list_data_get(l);
1521 l = eina_list_next(l);
1522 if (g->delete_me)
1523 evas_key_grab_free(g->object, g->keyname, g->modifiers,
1524 g->not_modifiers);
1525 }
1526 }
1527 }
1528 }
1529 if ((e->focused) && (!exclusive))
1530 {
1531 if (e->events_frozen <= 0 && !evas_event_freezes_through(e->focused))
1532 evas_object_event_callback_call(e->focused, EVAS_CALLBACK_KEY_DOWN,
1533 &ev, event_id);
1534 }
1535 _evas_post_event_callback_call(e);
1536 _evas_unwalk(e);
1537}
1538
1539EAPI void
1540evas_event_feed_key_up(Evas *e, const char *keyname, const char *key, const char *string, const char *compose, unsigned int timestamp, const void *data)
1541{
1542 int event_id = 0;
1543 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1544 return;
1545 MAGIC_CHECK_END();
1546 if (!keyname) return;
1547 if (e->events_frozen > 0) return;
1548 e->last_timestamp = timestamp;
1549 _evas_walk(e);
1550
1551 Evas_Event_Key_Up ev;
1552 Eina_Bool exclusive;
1553
1554 _evas_object_event_new();
1555
1556 event_id = _evas_event_counter;
1557 exclusive = EINA_FALSE;
1558 ev.keyname = (char *)keyname;
1559 ev.data = (void *)data;
1560 ev.modifiers = &(e->modifiers);
1561 ev.locks = &(e->locks);
1562 ev.key = key;
1563 ev.string = string;
1564 ev.compose = compose;
1565 ev.timestamp = timestamp;
1566 ev.event_flags = e->default_event_flags;
1567
1568 if (e->grabs)
1569 {
1570 Eina_List *l;
1571 Evas_Key_Grab *g;
1572
1573 e->walking_grabs++;
1574 EINA_LIST_FOREACH(e->grabs, l, g)
1575 {
1576 if (g->just_added)
1577 {
1578 g->just_added = EINA_FALSE;
1579 continue;
1580 }
1581 if (g->delete_me) continue;
1582 if (((e->modifiers.mask & g->modifiers) ||
1583 (g->modifiers == e->modifiers.mask)) &&
1584 (!((e->modifiers.mask & g->not_modifiers) ||
1585 (g->not_modifiers == ~e->modifiers.mask))) &&
1586 (!strcmp(keyname, g->keyname)))
1587 {
1588 if (e->events_frozen <= 0 &&
1589 !evas_event_freezes_through(g->object))
1590 evas_object_event_callback_call(g->object,
1591 EVAS_CALLBACK_KEY_UP, &ev, event_id);
1592 if (g->exclusive) exclusive = EINA_TRUE;
1593 }
1594 if (e->delete_me) break;
1595 }
1596 e->walking_grabs--;
1597 if (e->walking_grabs <= 0)
1598 {
1599 while (e->delete_grabs > 0)
1600 {
1601 Eina_List *ll, *l_next;
1602 Evas_Key_Grab *gr;
1603
1604 e->delete_grabs--;
1605 EINA_LIST_FOREACH_SAFE(e->grabs, ll, l_next, gr)
1606 {
1607 if (gr->delete_me)
1608 evas_key_grab_free(gr->object, gr->keyname,
1609 gr->modifiers, gr->not_modifiers);
1610 }
1611 }
1612 }
1613 }
1614 if ((e->focused) && (!exclusive))
1615 {
1616 if (e->events_frozen <= 0 && !evas_event_freezes_through(e->focused))
1617 evas_object_event_callback_call(e->focused, EVAS_CALLBACK_KEY_UP,
1618 &ev, event_id);
1619 }
1620 _evas_post_event_callback_call(e);
1621 _evas_unwalk(e);
1622}
1623
1624EAPI void
1625evas_event_feed_hold(Evas *e, int hold, unsigned int timestamp, const void *data)
1626{
1627 Eina_List *l, *copy;
1628 Evas_Event_Hold ev;
1629 Evas_Object *obj;
1630 int event_id = 0;
1631
1632 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1633 return;
1634 MAGIC_CHECK_END();
1635
1636 if (e->events_frozen > 0) return;
1637 e->last_timestamp = timestamp;
1638
1639 _evas_object_event_new();
1640
1641 event_id = _evas_event_counter;
1642 ev.hold = hold;
1643 ev.data = (void *)data;
1644 ev.timestamp = timestamp;
1645 ev.event_flags = e->default_event_flags;
1646
1647 _evas_walk(e);
1648 copy = evas_event_list_copy(e->pointer.object.in);
1649 EINA_LIST_FOREACH(copy, l, obj)
1650 {
1651 if ((e->events_frozen <= 0) && !evas_event_freezes_through(obj))
1652 evas_object_event_callback_call(obj, EVAS_CALLBACK_HOLD, &ev, event_id);
1653 if (e->delete_me) break;
1654 }
1655 if (copy) copy = eina_list_free(copy);
1656 _evas_post_event_callback_call(e);
1657 _evas_unwalk(e);
1658 _evas_object_event_new();
1659}
1660
1661EAPI void
1662evas_object_freeze_events_set(Evas_Object *obj, Eina_Bool freeze)
1663{
1664 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1665 return;
1666 MAGIC_CHECK_END();
1667
1668 freeze = !!freeze;
1669 if (obj->freeze_events == freeze) return;
1670 obj->freeze_events = freeze;
1671 evas_object_smart_member_cache_invalidate(obj, EINA_FALSE, EINA_TRUE);
1672}
1673
1674EAPI Eina_Bool
1675evas_object_freeze_events_get(const Evas_Object *obj)
1676{
1677 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1678 return EINA_FALSE;
1679 MAGIC_CHECK_END();
1680 return obj->freeze_events;
1681}
1682
1683EAPI void
1684evas_object_pass_events_set(Evas_Object *obj, Eina_Bool pass)
1685{
1686 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1687 return;
1688 MAGIC_CHECK_END();
1689 pass = !!pass;
1690 if (obj->pass_events == pass) return;
1691 obj->pass_events = pass;
1692 evas_object_smart_member_cache_invalidate(obj, EINA_TRUE, EINA_FALSE);
1693 if (evas_object_is_in_output_rect(obj,
1694 obj->layer->evas->pointer.x,
1695 obj->layer->evas->pointer.y, 1, 1) &&
1696 ((!obj->precise_is_inside) ||
1697 (evas_object_is_inside(obj,
1698 obj->layer->evas->pointer.x,
1699 obj->layer->evas->pointer.y))))
1700 evas_event_feed_mouse_move(obj->layer->evas,
1701 obj->layer->evas->pointer.x,
1702 obj->layer->evas->pointer.y,
1703 obj->layer->evas->last_timestamp,
1704 NULL);
1705}
1706
1707EAPI Eina_Bool
1708evas_object_pass_events_get(const Evas_Object *obj)
1709{
1710 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1711 return EINA_FALSE;
1712 MAGIC_CHECK_END();
1713 return obj->pass_events;
1714}
1715
1716EAPI void
1717evas_object_repeat_events_set(Evas_Object *obj, Eina_Bool repeat)
1718{
1719 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1720 return;
1721 MAGIC_CHECK_END();
1722 repeat = !!repeat;
1723 if (obj->repeat_events == repeat) return;
1724 obj->repeat_events = repeat;
1725 if (evas_object_is_in_output_rect(obj,
1726 obj->layer->evas->pointer.x,
1727 obj->layer->evas->pointer.y, 1, 1) &&
1728 ((!obj->precise_is_inside) ||
1729 (evas_object_is_inside(obj,
1730 obj->layer->evas->pointer.x,
1731 obj->layer->evas->pointer.y))))
1732 evas_event_feed_mouse_move(obj->layer->evas,
1733 obj->layer->evas->pointer.x,
1734 obj->layer->evas->pointer.y,
1735 obj->layer->evas->last_timestamp,
1736 NULL);
1737}
1738
1739EAPI Eina_Bool
1740evas_object_repeat_events_get(const Evas_Object *obj)
1741{
1742 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1743 return EINA_FALSE;
1744 MAGIC_CHECK_END();
1745 return obj->repeat_events;
1746}
1747
1748EAPI void
1749evas_object_propagate_events_set(Evas_Object *obj, Eina_Bool prop)
1750{
1751 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1752 return;
1753 MAGIC_CHECK_END();
1754 obj->no_propagate = !prop;
1755}
1756
1757EAPI Eina_Bool
1758evas_object_propagate_events_get(const Evas_Object *obj)
1759{
1760 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1761 return EINA_FALSE;
1762 MAGIC_CHECK_END();
1763 return !(obj->no_propagate);
1764}
1765
1766EAPI void
1767evas_object_pointer_mode_set(Evas_Object *obj, Evas_Object_Pointer_Mode setting)
1768{
1769 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1770 return;
1771 MAGIC_CHECK_END();
1772 obj->pointer_mode = setting;
1773}
1774
1775EAPI Evas_Object_Pointer_Mode
1776evas_object_pointer_mode_get(const Evas_Object *obj)
1777{
1778 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1779 return EVAS_OBJECT_POINTER_MODE_AUTOGRAB;
1780 MAGIC_CHECK_END();
1781 return obj->pointer_mode;
1782}
1783
1784EAPI void
1785evas_event_refeed_event(Evas *e, void *event_copy, Evas_Callback_Type event_type)
1786{
1787 switch (event_type)
1788 {
1789 case EVAS_CALLBACK_MOUSE_IN:
1790 {
1791 Evas_Event_Mouse_In *ev = event_copy;
1792 evas_event_feed_mouse_in(e, ev->timestamp, ev->data);
1793 break;
1794 }
1795 case EVAS_CALLBACK_MOUSE_OUT:
1796 {
1797 Evas_Event_Mouse_Out *ev = event_copy;
1798 evas_event_feed_mouse_out(e, ev->timestamp, ev->data);
1799 break;
1800 }
1801 case EVAS_CALLBACK_MOUSE_DOWN:
1802 {
1803 Evas_Event_Mouse_Down *ev = event_copy;
1804 evas_event_feed_mouse_down(e, ev->button, ev->flags, ev-> timestamp, ev->data);
1805 break;
1806 }
1807 case EVAS_CALLBACK_MOUSE_UP:
1808 {
1809 Evas_Event_Mouse_Up *ev = event_copy;
1810 evas_event_feed_mouse_up(e, ev->button, ev->flags, ev-> timestamp, ev->data);
1811 break;
1812 }
1813 case EVAS_CALLBACK_MOUSE_MOVE:
1814 {
1815 Evas_Event_Mouse_Move *ev = event_copy;
1816 evas_event_feed_mouse_move(e, ev->cur.canvas.x, ev->cur.canvas.y, ev->timestamp, ev->data);
1817 break;
1818 }
1819 case EVAS_CALLBACK_MOUSE_WHEEL:
1820 {
1821 Evas_Event_Mouse_Wheel *ev = event_copy;
1822 evas_event_feed_mouse_wheel(e, ev->direction, ev-> z, ev->timestamp, ev->data);
1823 break;
1824 }
1825 case EVAS_CALLBACK_MULTI_DOWN:
1826 {
1827 Evas_Event_Multi_Down *ev = event_copy;
1828 evas_event_feed_multi_down(e, ev->device, ev->canvas.x, ev->canvas.y, ev->radius, ev->radius_x, ev->radius_y, ev->pressure, ev->angle, ev->canvas.xsub, ev->canvas.ysub, ev->flags, ev->timestamp, ev->data);
1829 break;
1830 }
1831 case EVAS_CALLBACK_MULTI_UP:
1832 {
1833 Evas_Event_Multi_Up *ev = event_copy;
1834 evas_event_feed_multi_up(e, ev->device, ev->canvas.x, ev->canvas.y, ev->radius, ev->radius_x, ev->radius_y, ev->pressure, ev->angle, ev->canvas.xsub, ev->canvas.ysub, ev->flags, ev->timestamp, ev->data);
1835 break;
1836 }
1837 case EVAS_CALLBACK_MULTI_MOVE:
1838 {
1839 Evas_Event_Multi_Move *ev = event_copy;
1840 evas_event_feed_multi_move(e, ev->device, ev->cur.canvas.x, ev->cur.canvas.y, ev->radius, ev->radius_x, ev->radius_y, ev->pressure, ev->angle, ev->cur.canvas.xsub, ev->cur.canvas.ysub, ev->timestamp, ev->data);
1841 break;
1842 }
1843 case EVAS_CALLBACK_KEY_DOWN:
1844 {
1845 Evas_Event_Key_Down *ev = event_copy;
1846 evas_event_feed_key_down(e, ev->keyname, ev->key, ev->string, ev->compose, ev->timestamp, ev->data);
1847 break;
1848 }
1849 case EVAS_CALLBACK_KEY_UP:
1850 {
1851 Evas_Event_Key_Up *ev = event_copy;
1852 evas_event_feed_key_up(e, ev->keyname, ev->key, ev->string, ev->compose, ev->timestamp, ev->data);
1853 break;
1854 }
1855 default: /* All non-input events are not handeled */
1856 break;
1857 }
1858}
1859
1860EAPI int
1861evas_event_down_count_get(const Evas *e)
1862{
1863 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1864 return 0;
1865 MAGIC_CHECK_END();
1866 return e->pointer.downs;
1867}
diff --git a/libraries/evas/src/lib/canvas/evas_filter.c b/libraries/evas/src/lib/canvas/evas_filter.c
deleted file mode 100644
index 6194ec2..0000000
--- a/libraries/evas/src/lib/canvas/evas_filter.c
+++ /dev/null
@@ -1,1427 +0,0 @@
1/*
2 * Filter implementation for evas
3 */
4
5#if 0 // filtering disabled
6typedef enum
7{
8 /** Apply any filter effects to this object (Default) */
9 EVAS_FILTER_MODE_OBJECT,
10 /** Filter all objects beneath this object on the canvas */
11 EVAS_FILTER_MODE_BELOW,
12} Evas_Filter_Mode;
13typedef enum
14{
15 /** No filter: Default */
16 EVAS_FILTER_NONE,
17 /** A blur filter. Params are quality (float), and radius (int). */
18 EVAS_FILTER_BLUR,
19 /** Negates the colors of an image. Also called solarize */
20 EVAS_FILTER_INVERT,
21 EVAS_FILTER_SOLARIZE = EVAS_FILTER_INVERT,
22 /** Makes a sepia version of the image. */
23 EVAS_FILTER_SEPIA,
24 /** Makes a greyscale version of the image. Params are 'red',
25 * 'green', 'blue' (all floats) which must add to 1. The defaults are
26 * 0.3, 0.59 and 0.11 which approximates human vision. Setting 'all'
27 * sets rgb to the same value. */
28 EVAS_FILTER_GREYSCALE,
29 EVAS_FILTER_GRAYSCALE = EVAS_FILTER_GREYSCALE,
30 /** Brighten (or darken) image. Param 'adjust' float (-1.0 to 1.0)
31 * amount to adjust. */
32 EVAS_FILTER_BRIGHTNESS,
33 /** Enhance contrast on image. Param 'adjust' float (-1.0 to 1.0)
34 * amount to adjust. */
35 EVAS_FILTER_CONTRAST,
36
37 EVAS_FILTER_LAST = EVAS_FILTER_CONTRAST
38} Evas_Filter;
39
40/**
41 * Set the filter mode for an object.
42 *
43 * There are two valid filtering modes currently:
44 * - EVAS_FILTER_MODE_OBJECT: which applies the filter to the object itself
45 * - EVAS_FILTER_MODE_BELOW: which makes the object invisible and filters
46 * what is below the object.
47 *
48 * The default filter mode is EVAS_FILTER_MODE_OBJECT.
49 *
50 * @param o Object to set filter mode on.
51 * @param mode Mode to set.
52 * @return EINA_TRUE on success, EINA_FALSE otherwise.
53 */
54 EAPI Eina_Bool evas_object_filter_mode_set (Evas_Object *o, Evas_Filter_Mode mode);
55
56/**
57 * Get the current filtering mode for an object.
58 *
59 * By default all objects are in object filtering mode, even if no filter is
60 * set.
61 *
62 * @param o Object to get filter mode of.
63 * @return Filter mode (default EVAS_FILTER_MODE_OBJECT)
64 */
65 EAPI Evas_Filter_Mode evas_object_filter_mode_get (Evas_Object *o);
66
67/**
68 * Set the current filter type.
69 *
70 * This sets the filter type, whether a blur, color filter or some other type
71 * of filter. This is normally the only filter call necessary, although some
72 * filters require additional parameters.
73 *
74 * If the object has a filter already, and existing parameters will be
75 * cleared.
76 *
77 * Setting the blur to EVAS_FILTER_NONE removes any filter.
78 *
79 * @param o Object to set the filter on.
80 * @param filter Filter to set.
81 * @return EINA_TRUE On success
82 */
83 EAPI Eina_Bool evas_object_filter_set (Evas_Object *o, Evas_Filter filter);
84
85/**
86 * Get the current filter.
87 *
88 * @param o Object to get filter of.
89 * @return The filter if set, or EVAS_FILTER_NONE.
90 */
91 EAPI Evas_Filter evas_object_filter_get (Evas_Object *o);
92
93/**
94 * Set an integer parameter of a filter.
95 *
96 * This sets an integer parameter of a filter, if such parameter is known to
97 * the filter. Note that some parameters may actually set multiple fields.
98 * The individual filters define the specific parameters available.
99 *
100 * It should be noted that filter parameters are lost after the filter type
101 * changes, so set the filter type, then the parameters.
102 *
103 * @param o Object to set parameter on.
104 * @param param Name of parameter to set.
105 * @param val Value to set.
106 * @return EINA_TRUE if at least one parameter was set, EINA_FALSE
107 * otherwise.
108 */
109 EAPI Eina_Bool evas_object_filter_param_int_set (Evas_Object *o, const char *param, int val);
110
111/**
112 * Get an integer value parameter from a filter.
113 *
114 * Gets the first matching parameter for a filter. Note there is no way to
115 * later fields if they do not have their own accessor name.
116 *
117 * Also note that there is no way to tell the difference between a -1 as a
118 * value, and the error code. Ask your filter writer to use a different
119 * range.
120 *
121 * @param o The object.
122 * @Param param Name of the parameter to get.
123 * @return The value, or -1 on error.
124 */
125 EAPI int evas_object_filter_param_int_get (Evas_Object *o, const char *param);
126
127/**
128 * Set a string parameter on a filter
129 *
130 * Currently unimplemented as no filters use this yet
131 */
132 EAPI Eina_Bool evas_object_filter_param_str_set (Evas_Object *o, const char *param, const char *val);
133
134/**
135 * Get a string parameter from a filter
136 *
137 * Currently unimplemented as no filters use this yet
138 */
139 EAPI const char *evas_object_filter_param_str_get (Evas_Object *o, const char *param);
140
141/**
142 * Set an object parameter on a filter
143 *
144 * Currently unimplemented as no filters use this yet
145 */
146 EAPI Eina_Bool evas_object_filter_param_obj_set (Evas_Object *o, const char *param, Evas_Object *val);
147
148/**
149 * get an object parameter from a filter
150 *
151 * Currently unimplemented as no filters use this yet
152 */
153 EAPI Evas_Object *evas_object_filter_param_obj_get (Evas_Object *o, const char *param);
154
155/**
156 * Set a float parameter of a filter.
157 *
158 * This is the same as evas_object_filter_param_int_set(), but for floating
159 * point values.
160 *
161 * @param o Object to set value on.
162 * @param param Name of the parameter to set.
163 * @param EINA_TRUE if at least one parameter was set, EINA_FALSE otherwise.
164 */
165 EAPI Eina_Bool evas_object_filter_param_float_set(Evas_Object *o, const char *param, double val);
166
167/**
168 * Get a float parameter of a filter.
169 *
170 * This is the same as evas_object_filter_param_int_get(), but for floating
171 * point values.
172 *
173 * @param o Object to set value on.
174 * @param param Name of the parameter to set.
175 * @return The value, or -1 on error.
176 */
177 EAPI double evas_object_filter_param_float_get(Evas_Object *o, const char *param);
178
179#include <stddef.h> // offsetof
180
181#include "evas_common.h"
182#include "evas_private.h"
183
184#include <assert.h>
185/* disable neon - even after fixes:
186 * Error: ARM register expected -- vdup.u32 q14,$0xff000000'
187 * not going to fix now
188#ifdef BUILD_NEON
189# define BUILD_NEON0 1
190#else
191# define BUILD_NEON0 0
192#endif
193*/
194
195#define BUILD_NEON0 0
196
197typedef struct Evas_Filter_Info_Blur
198{
199 double quality;
200 int radius;
201} Evas_Filter_Info_Blur;
202
203typedef struct Evas_Filter_Info_GreyScale
204{
205 double r,g,b;
206} Evas_Filter_Info_GreyScale;
207
208typedef struct Evas_Filter_Info_Brightness
209{
210 double adjust;
211} Evas_Filter_Info_Brightness;
212
213typedef struct Evas_Filter_Info_Contrast
214{
215 double adjust;
216} Evas_Filter_Info_Contrast;
217
218typedef int (*Filter_Size_FN)(Evas_Filter_Info *,int,int,int*,int*,Eina_Bool);
219typedef uint8_t *(*Key_FN)(const Evas_Filter_Info *, uint32_t *);
220
221struct fieldinfo
222{
223 const char *field;
224 int type;
225 size_t offset;
226};
227
228struct filterinfo
229{
230 Evas_Software_Filter_Fn filter;
231 const size_t datasize;
232 Filter_Size_FN sizefn;
233 Key_FN keyfn;
234 Eina_Bool alwaysalpha;
235};
236
237enum
238{
239 TYPE_INT,
240 TYPE_FLOAT
241};
242
243static int blur_size_get(Evas_Filter_Info*, int, int, int *, int *, Eina_Bool);
244static uint8_t *gaussian_key_get(const Evas_Filter_Info *, uint32_t *);
245
246static Eina_Bool gaussian_filter(Evas_Filter_Info *, RGBA_Image*, RGBA_Image*);
247static Eina_Bool negation_filter(Evas_Filter_Info *, RGBA_Image*, RGBA_Image*);
248static Eina_Bool sepia_filter(Evas_Filter_Info *, RGBA_Image*, RGBA_Image*);
249static Eina_Bool greyscale_filter(Evas_Filter_Info*, RGBA_Image*, RGBA_Image*);
250static Eina_Bool brightness_filter(Evas_Filter_Info*, RGBA_Image*, RGBA_Image*);
251static Eina_Bool contrast_filter(Evas_Filter_Info *, RGBA_Image*, RGBA_Image*);
252
253struct filterinfo filterinfo[] =
254{
255 /* None */
256 { NULL, 0, NULL, NULL, EINA_FALSE},
257 /* Blur */
258 { gaussian_filter, sizeof(Evas_Filter_Info_Blur), blur_size_get, gaussian_key_get, EINA_TRUE },
259 /* Negation */
260 { negation_filter, 0, NULL, NULL, EINA_FALSE },
261 /* Sepia */
262 { sepia_filter, 0, NULL, NULL, EINA_FALSE },
263 /* Greyscale */
264 { greyscale_filter, sizeof(Evas_Filter_Info_GreyScale), NULL, NULL, EINA_FALSE },
265 /* Brightness */
266 { brightness_filter, sizeof(Evas_Filter_Info_Brightness), NULL, NULL, EINA_FALSE },
267 /* Contrast */
268 { contrast_filter, sizeof(Evas_Filter_Info_Contrast), NULL, NULL, EINA_FALSE},
269};
270
271
272static struct fieldinfo blurfields[] =
273{
274 { "quality", TYPE_FLOAT, offsetof(Evas_Filter_Info_Blur, quality) },
275 { "radius", TYPE_INT, offsetof(Evas_Filter_Info_Blur, radius) },
276 { NULL, 0, 0 },
277};
278
279static struct fieldinfo greyfields[] =
280{
281 { "red", TYPE_FLOAT, offsetof(Evas_Filter_Info_GreyScale, r) },
282 { "green", TYPE_FLOAT, offsetof(Evas_Filter_Info_GreyScale, g) },
283 { "blue", TYPE_FLOAT, offsetof(Evas_Filter_Info_GreyScale, b) },
284
285 { "all", TYPE_FLOAT, offsetof(Evas_Filter_Info_GreyScale, r) },
286 { "all", TYPE_FLOAT, offsetof(Evas_Filter_Info_GreyScale, g) },
287 { "all", TYPE_FLOAT, offsetof(Evas_Filter_Info_GreyScale, b) },
288 { NULL, 0, 0 },
289};
290
291static struct fieldinfo brightnessfields[] =
292{
293 { "adjust", TYPE_FLOAT, offsetof(Evas_Filter_Info_Brightness, adjust) },
294 { NULL, 0, 0 },
295};
296
297static struct fieldinfo contrastfields[] =
298{
299 { "adjust", TYPE_FLOAT, offsetof(Evas_Filter_Info_Contrast, adjust) },
300 { NULL, 0, 0 },
301};
302
303static struct fieldinfo *filterfields[] =
304{
305 NULL,
306 blurfields,
307 NULL,
308 NULL,
309 greyfields,
310 brightnessfields,
311 contrastfields,
312};
313
314static Evas_Filter_Info *filter_alloc(Evas_Object *o);
315
316EAPI Eina_Bool
317evas_object_filter_mode_set(Evas_Object *o, Evas_Filter_Mode mode)
318{
319 Evas_Filter_Info *info;
320
321 MAGIC_CHECK(o, Evas_Object, MAGIC_OBJ);
322 return EINA_FALSE;
323 MAGIC_CHECK_END();
324
325 if ((mode != EVAS_FILTER_MODE_OBJECT) && (mode != EVAS_FILTER_MODE_BELOW))
326 return EINA_FALSE;
327
328 if (!o->filter)
329 {
330 filter_alloc(o);
331 }
332 if (!o->filter) return EINA_FALSE;
333 info = o->filter;
334
335 if (info->mode == mode) return EINA_TRUE; /* easy case */
336 info->mode = mode;
337 info->dirty = 1;
338 return EINA_TRUE;
339}
340
341EAPI Evas_Filter_Mode
342evas_object_filter_mode_get(Evas_Object *o)
343{
344 MAGIC_CHECK(o, Evas_Object, MAGIC_OBJ);
345 return EVAS_FILTER_MODE_OBJECT;
346 MAGIC_CHECK_END();
347
348 if (!o->filter) return EVAS_FILTER_MODE_OBJECT;
349 return o->filter->mode;
350}
351
352EAPI Eina_Bool
353evas_object_filter_set(Evas_Object *o, Evas_Filter filter)
354{
355 Evas_Filter_Info *info;
356 struct filterinfo *finfo;
357
358 MAGIC_CHECK(o, Evas_Object, MAGIC_OBJ);
359 return EINA_FALSE;
360 MAGIC_CHECK_END();
361
362 /* force filter to be signed: else gcc complains, but enums may always be
363 * signed */
364 if (((int)filter < (int)EVAS_FILTER_NONE) || (filter > EVAS_FILTER_LAST))
365 return EINA_FALSE;
366
367 /* Don't alloc on no-op */
368 if (!o-filter && filter == EVAS_FILTER_NONE) return EINA_TRUE;
369
370 if (!o->filter) filter_alloc(o);
371 if (!o->filter) return EINA_FALSE;
372
373 info = o->filter;
374
375 if (info->filter == filter) return EINA_TRUE;
376
377 finfo = filterinfo + filter;
378 info->filter = filter;
379 info->dirty = 1;
380 if (info->data)
381 {
382 if (info->data_free)
383 info->data_free(info->data);
384 else
385 free(info->data);
386 }
387 info->datalen = finfo->datasize;
388 if (finfo->datasize)
389 {
390 info->data = calloc(1, finfo->datasize);
391 if (!info->data)
392 {
393 o->filter = EVAS_FILTER_NONE;
394 return EINA_FALSE;
395 }
396 }
397 else
398 info->data = NULL;
399 info->data_free = NULL;
400
401 return EINA_TRUE;
402}
403
404EAPI Evas_Filter
405evas_object_filter_get(Evas_Object *o)
406{
407 MAGIC_CHECK(o, Evas_Object, MAGIC_OBJ);
408 return EVAS_FILTER_NONE;
409 MAGIC_CHECK_END();
410
411 if (!o->filter) return EVAS_FILTER_NONE;
412 return o->filter->filter;
413}
414
415EAPI Eina_Bool
416evas_object_filter_param_int_set(Evas_Object *o, const char *param, int val)
417{
418 char *data;
419 const struct fieldinfo *fields;
420 Eina_Bool found;
421 int i;
422
423 MAGIC_CHECK(o, Evas_Object, MAGIC_OBJ);
424 return EINA_FALSE;
425 MAGIC_CHECK_END();
426
427 if ((!o->filter) || (!o->filter->data)) return EINA_FALSE;
428
429 fields = filterfields[o->filter->filter];
430 data = o->filter->data;
431 found = EINA_FALSE;
432 for (i = 0; fields[i].field; i++)
433 {
434 if (!strcmp(fields[i].field, param))
435 {
436 if (fields[i].type != TYPE_INT) continue;
437 *(int *)(data + fields[i].offset) = val;
438 o->filter->dirty = 1;
439 evas_object_change(o);
440 found = EINA_TRUE;
441 }
442 }
443 return found;
444}
445
446EAPI int
447evas_object_filter_param_int_get(Evas_Object *o, const char *param)
448{
449 char *data;
450 const struct fieldinfo *fields;
451 int val;
452 int i;
453
454 MAGIC_CHECK(o, Evas_Object, MAGIC_OBJ);
455 return -1;
456 MAGIC_CHECK_END();
457
458 if ((!o->filter) || (!o->filter->data)) return -1;
459
460 fields = filterfields[o->filter->filter];
461 if (!fields) return -1;
462 data = o->filter->data;
463
464 for (i = 0; fields[i].field; i++)
465 {
466 if (!strcmp(fields[i].field, param))
467 {
468 if (fields[i].type != TYPE_INT) continue;
469 val = *(int *)(data + fields[i].offset);
470 return val;
471 }
472 }
473 return -1;
474}
475
476EAPI Eina_Bool
477evas_object_filter_param_str_set(Evas_Object *o __UNUSED__,
478 const char *param __UNUSED__,
479 const char *val __UNUSED__)
480{
481 return EINA_FALSE;
482}
483
484EAPI const char *
485evas_object_filter_param_str_get(Evas_Object *o __UNUSED__,
486 const char *param __UNUSED__)
487{
488 return NULL;
489}
490
491EAPI Eina_Bool
492evas_object_filter_param_obj_set(Evas_Object *o __UNUSED__,
493 const char *param __UNUSED__,
494 Evas_Object *val __UNUSED__)
495{
496 return EINA_FALSE;
497}
498
499EAPI Evas_Object *
500evas_object_filter_param_obj_get(Evas_Object *o __UNUSED__,
501 const char *param __UNUSED__)
502{
503 return NULL;
504}
505
506EAPI Eina_Bool
507evas_object_filter_param_float_set(Evas_Object *o, const char *param,
508 double val)
509{
510 char *data;
511 const struct fieldinfo *fields;
512 int i;
513 Eina_Bool rv;
514
515 MAGIC_CHECK(o, Evas_Object, MAGIC_OBJ);
516 return EINA_FALSE;
517 MAGIC_CHECK_END();
518
519 if ((!o->filter) || (!o->filter->data)) return EINA_FALSE;
520
521 rv = EINA_FALSE;
522 fields = filterfields[o->filter->filter];
523 if (!fields) return EINA_FALSE;
524
525 data = o->filter->data;
526
527 for (i = 0; fields[i].field; i++)
528 {
529 if (!strcmp(fields[i].field, param))
530 {
531 if (fields[i].type != TYPE_FLOAT) continue;
532 *(double *)(data + fields[i].offset) = val;
533 o->filter->dirty = 1;
534 o->changed = 1;
535 evas_object_change(o);
536 rv = EINA_TRUE;
537 }
538 }
539 return rv;
540}
541
542EAPI double
543evas_object_filter_param_float_get(Evas_Object *o, const char *param)
544{
545 char *data;
546 const struct fieldinfo *fields;
547 double val;
548 int i;
549
550 MAGIC_CHECK(o, Evas_Object, MAGIC_OBJ);
551 return -1;
552 MAGIC_CHECK_END();
553
554 if ((!o->filter) || (!o->filter->data)) return -1;
555
556 fields = filterfields[o->filter->filter];
557 if (!fields) return -1;
558 data = o->filter->data;
559
560 for (i = 0; fields[i].field; i++)
561 {
562 if (!strcmp(fields[i].field, param))
563 {
564 if (fields[i].type != TYPE_FLOAT) continue;
565 val = *(double *)(data + fields[i].offset);
566 return val;
567 }
568 }
569 return -1;
570}
571
572
573
574
575
576/*
577 * Internal call
578 */
579int
580evas_filter_get_size(Evas_Filter_Info *info, int inw, int inh,
581 int *outw, int *outh, Eina_Bool inv)
582{
583 if (!info) return -1;
584 if ((!outw) && (!outh)) return 0;
585
586 if (filterinfo[info->filter].sizefn)
587 return filterinfo[info->filter].sizefn(info, inw, inh, outw, outh, inv);
588
589 if (outw) *outw = inw;
590 if (outh) *outh = inh;
591 return 0;
592}
593
594Eina_Bool
595evas_filter_always_alpha(Evas_Filter_Info *info)
596{
597 if (!info) return EINA_FALSE;
598 return filterinfo[info->filter].alwaysalpha;
599}
600
601/*
602 * Another internal call:
603 * Given a filterinfo, generate a unique key for it
604 *
605 * For simple filters, it's just the filter type.
606 * for more complex filters, it's the type, with it's params.
607 *
608 * Note management of the key data is up to the caller, that is it should
609 * probably be freed after use.
610 *
611 * Note the automatic fallback generation places the single byte at the end so
612 * the memcpy will be aligned. Micro-optimisations FTW!
613 *
614 * @param info Filter info to generate from
615 * @param len Length of the buffer returned.
616 * @return key Key buffer
617 */
618uint8_t *
619evas_filter_key_get(const Evas_Filter_Info *info, uint32_t *lenp)
620{
621 struct filterinfo *finfo;
622 uint8_t *key;
623 int len;
624
625 if (!info) return NULL;
626
627 finfo = filterinfo + info->filter;
628 if (finfo->keyfn) return finfo->keyfn(info, lenp);
629
630 len = 1 + finfo->datasize;
631 key = malloc(len);
632 if (!key) return NULL;
633 if (finfo->datasize) memcpy(key, info->data, finfo->datasize);
634 key[finfo->datasize] = info->filter;
635 if (lenp) *lenp = len;
636 return key;
637}
638
639Evas_Software_Filter_Fn
640evas_filter_software_get(Evas_Filter_Info *info)
641{
642 return filterinfo[info->filter].filter;
643}
644
645void
646evas_filter_free(Evas_Object *o)
647{
648 if (!o->filter) return;
649 if (o->filter->key) free(o->filter->key);
650 free(o->filter);
651 o->filter = NULL;
652}
653
654
655
656
657/*
658 * Private calls
659 */
660static Evas_Filter_Info *
661filter_alloc(Evas_Object *o)
662{
663 Evas_Filter_Info *info;
664
665 if (!o) return NULL;
666 info = calloc(1,sizeof(struct Evas_Filter_Info));
667 if (!info) return NULL;
668 info->dirty = 1;
669 info->filter = EVAS_FILTER_NONE;
670 info->mode = EVAS_FILTER_MODE_OBJECT;
671 info->datalen = 0;
672
673 o->filter = info;
674
675 return info;
676}
677
678static int
679blur_size_get(Evas_Filter_Info *info, int inw, int inh, int *outw, int *outh,
680 Eina_Bool inv)
681{
682 Evas_Filter_Info_Blur *blur = info->data;
683
684 if (inv)
685 {
686 if (outw) *outw = MAX(inw - (blur->radius * 2), 0);
687 if (outh) *outh = MAX(inh - (blur->radius * 2), 0);
688 }
689 else
690 {
691 if (outw) *outw = inw + (blur->radius * 2);
692 if (outh) *outh = inh + (blur->radius * 2);
693 }
694 return 0;
695}
696
697/*
698 * Generate a key for the Gaussian generator.
699 *
700 * The size is:
701 * - 1 byte for the type (blur)
702 * - 1 byte for the quality (0-1 -> 0-255)
703 * - 2 bytes for radius (max is 508 anyway)
704 *
705 * @param info Filter info
706 * @param len Length of the returned buffer
707 * @return new buffer
708 */
709static uint8_t *
710gaussian_key_get(const Evas_Filter_Info *info, uint32_t *lenp)
711{
712 struct Evas_Filter_Info_Blur *blur;
713 uint8_t *key;
714
715 if ((!info) || (!info->data)) return NULL;
716 blur = info->data;
717
718 if (lenp) *lenp = 4;
719 key = malloc(4);
720 if (!key) return NULL;
721 key[0] = EVAS_FILTER_BLUR;
722 key[1] = blur->quality * 255;
723 key[2] = blur->radius >> 8;
724 key[3] = blur->radius;
725
726 return key;
727}
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747/**
748 * Software implementations
749 */
750#define all(OP, A, R, G, B, W, I) \
751 do { \
752 A OP A_VAL(I) * W; \
753 R OP R_VAL(I) * W; \
754 G OP G_VAL(I) * W; \
755 B OP B_VAL(I) * W; \
756 } while (0)
757#define wavg(x,n) (((x) / (n)) & 0xff)
758#define wavgd(x,n) ((uint32_t)((x) / (n)) & 0xff)
759
760typedef int (*FilterH)(int, uint32_t *, int, uint32_t *);
761typedef int (*FilterV)(int, uint32_t *, int, int, uint32_t *);
762
763static int gaussian_filter_h(int rad, uint32_t *in, int w, uint32_t *out);
764static int gaussian_filter_h64(int rad, uint32_t *in, int w, uint32_t *out);
765static int gaussian_filter_hd(int rad, uint32_t *in, int w, uint32_t *out);
766static int gaussian_filter_v(int rad, uint32_t *in, int h, int skip, uint32_t *out);
767static int gaussian_filter_v64(int rad, uint32_t *in, int h, int skip, uint32_t *out);
768static int gaussian_filter_vd(int rad, uint32_t *in, int h, int skip, uint32_t *out);
769static const uint32_t *gaussian_row_get(int row, int *npoints, uint32_t *weight);
770static const uint64_t *gaussian_row_get64(int row, int *npoints, uint64_t *weight);
771static const double *gaussian_row_getd(int row, int *npoints, double *weight);
772
773static Eina_Bool
774gaussian_filter(Evas_Filter_Info *filter, RGBA_Image *src, RGBA_Image *dst)
775{
776 int i;
777 uint32_t nw, nh;
778 uint32_t *in, *tmp, *out;
779 FilterV filter_v = gaussian_filter_v;
780 FilterH filter_h = gaussian_filter_h;
781 Evas_Filter_Info_Blur *blur;
782 int w, h;
783
784 blur = filter->data;
785
786 /* Use 64 bit version if we are going to overflow */
787 if (blur->radius > 508) /** too big for doubles: Bail out */
788 return EINA_FALSE;
789 else if (blur->radius > 28)
790 {
791 filter_v = gaussian_filter_vd;
792 filter_h = gaussian_filter_hd;
793 }
794 else if (blur->radius > 12)
795 {
796 filter_v = gaussian_filter_v64;
797 filter_h = gaussian_filter_h64;
798 }
799
800 w = src->cache_entry.w;
801 h = src->cache_entry.h;
802 in = src->image.data;
803
804 if (!in) return EINA_FALSE;
805
806 nw = w + (2 * blur->radius);
807 nh = h + (2 * blur->radius);
808
809 out = dst->image.data;
810 if (!out) return EINA_FALSE;
811 tmp = malloc(nw * h * sizeof(uint32_t));
812
813 for (i = 0; i < h; i++)
814 filter_h(blur->radius,in + (i * w), w, tmp + (i * nw));
815
816 for (i = 0; i < (int)nw; i++)
817 filter_v(blur->radius,tmp + i, h, nw, out + i);
818
819 free(tmp);
820 return EINA_TRUE;
821}
822
823/* Blur only horizontally */
824static int
825gaussian_filter_h(int rad, uint32_t *in, int w, uint32_t *out)
826{
827 const uint32_t *points;
828 int npoints = 0;
829 uint32_t weight = 0;
830 int i = 0, k = 0;
831 uint32_t r, g, b, a;
832
833 /* Get twice the radius: even rows have 1 element */
834 points = gaussian_row_get(rad * 2, &npoints, &weight);
835 for (i = -rad; i < (w + rad); i++)
836 {
837 r = g = b = a = 0;
838 for (k = -rad; k <= rad; k++)
839 {
840 if ((k + i) < 0) continue;
841 if ((k + i) >= w) continue;
842 all(+=, a, r, g, b, points[k + rad], in + k + i);
843 }
844 *(out) = ARGB_JOIN(wavg(a, weight),
845 wavg(r, weight),
846 wavg(g, weight),
847 wavg(b, weight));
848 out++;
849 }
850 return 0;
851}
852
853/* Blur only horizontally */
854static int
855gaussian_filter_hd(int rad, uint32_t *in, int w, uint32_t *out)
856{
857 const double *points;
858 int npoints = 0;
859 double weight = 0.0;
860 int i = 0, k = 0;
861 double r, g, b, a;
862
863 /* Get twice the radius: even rows have 1 element */
864 points = gaussian_row_getd(rad * 2, &npoints, &weight);
865 for (i = -rad; i < (w + rad); i++)
866 {
867 r = g = b = a = 0;
868 for (k = -rad; k <= rad; k++)
869 {
870 if ((k + i) < 0) continue;
871 if ((k + i) >= w) continue;
872 all(+=, a, r, g, b, points[k + rad], in + k + i);
873 }
874 *(out) = ARGB_JOIN(wavgd(a, weight),
875 wavgd(r, weight),
876 wavgd(g, weight),
877 wavgd(b, weight));
878 out++;
879 }
880 return 0;
881}
882
883
884/* Blur only horizontally */
885static int
886gaussian_filter_h64(int rad, uint32_t *in, int w, uint32_t *out)
887{
888 const uint64_t *points;
889 int npoints = 0;
890 uint64_t weight = 0;
891 int i = 0, k = 0;
892 uint64_t r, g, b, a;
893
894 /* Get twice the radius: even rows have 1 element */
895 points = gaussian_row_get64(rad * 2, &npoints, &weight);
896 for (i = -rad ; i < w + rad; i ++){
897 r = g = b = a = 0;
898 for (k = -rad ; k <= rad ; k ++){
899 if ((k + i) < 0) continue;
900 if ((k + i) >= w) continue;
901 all(+=, a, r, g, b, points[k + rad], in + k + i);
902 }
903 *(out) = ARGB_JOIN(wavg(a, weight),
904 wavg(r, weight),
905 wavg(g, weight),
906 wavg(b, weight));
907 out++;
908 }
909 return 0;
910}
911
912static int
913gaussian_filter_v(int rad, uint32_t *in, int h, int skip, uint32_t *out)
914{
915 const uint32_t *points;
916 int npoints = 0;
917 uint32_t weight = 0;
918 int i = 0, k = 0;
919 uint32_t r, g, b, a;
920
921 /* Get twice the radius: even rows have 1 element */
922 points = gaussian_row_get(rad * 2, &npoints, &weight);
923 weight = 0;
924 for (i = 0; i < npoints; i++) weight += points[i];
925
926 for (i = -rad; i < (h + rad); i++)
927 {
928 r = g = b = a = 0;
929 for (k = -rad; k <= rad; k++)
930 {
931 if ((k + i) < 0) continue;
932 if ((k + i) >= h) continue;
933 all(+=, a, r, g, b, points[k + rad], in + (skip * (k + i)));
934 }
935 *(out) = ARGB_JOIN(wavg(a, weight),
936 wavg(r, weight),
937 wavg(g, weight),
938 wavg(b, weight));
939 out += skip;
940 }
941 return 0;
942}
943
944static int
945gaussian_filter_v64(int rad, uint32_t *in, int h, int skip, uint32_t *out)
946{
947 const uint64_t *points;
948 int npoints = 0;
949 uint64_t weight;
950 int i = 0, k = 0;
951 uint64_t r, g, b, a;
952
953 /* Get twice the radius: even rows have 1 element */
954 points = gaussian_row_get64(rad * 2, &npoints, &weight);
955 weight = 0;
956 for (i = 0; i < npoints; i++) weight += points[i];
957
958 for (i = -rad; i < (h + rad); i++)
959 {
960 r = g = b = a = 0;
961 for (k = -rad ; k <= rad ; k++)
962 {
963 if ((k + i) < 0) continue;
964 if ((k + i) >= h) continue;
965 all(+=, a, r, g, b, points[k + rad], in + (skip * (k + i)));
966 }
967 *(out) = ARGB_JOIN(wavg(a, weight),
968 wavg(r, weight),
969 wavg(g, weight),
970 wavg(b, weight));
971 out += skip;
972 }
973 return 0;
974}
975
976static int
977gaussian_filter_vd(int rad, uint32_t *in, int h, int skip, uint32_t *out)
978{
979 const double *points;
980 int npoints = 0;
981 double weight = 0.0;
982 int i = 0, k = 0;
983 double r, g, b, a;
984
985 /* Get twice the radius: even rows have 1 element */
986 points = gaussian_row_getd(rad * 2, &npoints, &weight);
987 weight = 0;
988 for (i = 0 ; i < npoints ; i ++) weight += points[i];
989
990 for (i = -rad ; i < h + rad; i ++)
991 {
992 r = g = b = a = 0;
993 for (k = -rad ; k <= rad ; k ++)
994 {
995 if ((k + i) < 0) continue;
996 if ((k + i) >= h) continue;
997 all(+=, a, r, g, b, points[k + rad], in + (skip * (k + i)));
998 }
999 *(out) = ARGB_JOIN(wavgd(a, weight),
1000 wavgd(r, weight),
1001 wavgd(g, weight),
1002 wavgd(b, weight));
1003 out += skip;
1004 }
1005 return 0;
1006}
1007
1008static const uint32_t *
1009gaussian_row_get(int row, int *npoints, uint32_t *weight)
1010{
1011 static uint32_t *points = NULL;
1012 static int last = -1;
1013 static uint32_t lastweight = -1;
1014 int c, k;
1015
1016 if (row < 0) return NULL;
1017
1018 if (npoints) *npoints = row + 1;
1019
1020 if (last == row)
1021 {
1022 if (weight) *weight = lastweight;
1023 return points;
1024 }
1025 if (points) free(points);
1026
1027 points = malloc((row + 1) * sizeof(uint32_t));
1028 if (!points)
1029 {
1030 last = -1;
1031 return NULL;
1032 }
1033 last = row;
1034
1035 c = 1;
1036 for (k = 0; k <= row; k++)
1037 {
1038 points[k] = c;
1039 c = c * (row - k) / (k + 1);
1040 }
1041
1042 for (k = 0, lastweight = 0; k <= row; k++) lastweight += points[k];
1043 if (weight) *weight = lastweight;
1044 return points;
1045}
1046
1047static const uint64_t *
1048gaussian_row_get64(int row, int *npoints, uint64_t *weight)
1049{
1050 static uint64_t *points = NULL;
1051 static int last = -1;
1052 static uint64_t lastweight = -1;
1053 uint64_t c;
1054 int k;
1055
1056 if (row < 0) return NULL;
1057
1058 if (npoints) *npoints = row + 1;
1059 if (last == row)
1060 {
1061 if (weight) *weight = lastweight;
1062 return points;
1063 }
1064 if (points) free(points);
1065
1066 points = malloc((row + 1) * sizeof(uint64_t));
1067 if (!points)
1068 {
1069 last = -1;
1070 return NULL;
1071 }
1072 last = row;
1073
1074 c = 1;
1075 for (k = 0; k <= row; k++)
1076 {
1077 points[k] = c;
1078 c = c * (row - k) / (k + 1);
1079 }
1080
1081 for (k = 0, lastweight = 0; k <= row; k ++) lastweight += points[k];
1082 if (weight) *weight = lastweight;
1083
1084 return points;
1085}
1086
1087static const double *
1088gaussian_row_getd(int row, int *npoints, double *weight)
1089{
1090 static double *points = NULL;
1091 static int last = -1;
1092 static double lastweight = -1;
1093 double c;
1094 int k;
1095
1096 if (row < 0) return NULL;
1097
1098 if (last == row)
1099 {
1100 if (weight) *weight = lastweight;
1101 return points;
1102 }
1103
1104 if (points) free(points);
1105 points = malloc((row + 1) * sizeof(double));
1106 if (!points)
1107 {
1108 last = -1;
1109 return NULL;
1110 }
1111 last = row;
1112
1113 if (npoints) *npoints = row + 1;
1114
1115 c = 1;
1116 for (k = 0; k <= row; k++)
1117 {
1118 points[k] = c;
1119 c = c * (row - k) / (k + 1);
1120 }
1121
1122 for (k = 0, lastweight = 0; k <= row; k++) lastweight += points[k];
1123 if (weight) *weight = lastweight;
1124
1125 return points;
1126}
1127
1128#if BUILD_NEON0
1129static Eina_Bool
1130negation_filter_neon(Evas_Filter_Info *info, RGBA_Image *src, RGBA_Image *dst)
1131{
1132 uint32_t tmp;
1133
1134 if (src->cache_entry.flags.alpha)
1135 {
1136 // FIXME: not implemented
1137 }
1138 else
1139 {
1140 /* No alpha */
1141#define AP "NEG_FILTER_NA"
1142 asm volatile (
1143
1144 ".fpu neon \n\t"
1145 "vdup.u32 q14, $0xff000000 \n\t"
1146 "vmvn.u32 q15, q1 \n\t"
1147
1148 // fixme: do check for small loops
1149 AP"loopinit: \n\t"
1150 "sub %[tmp], %[e], #31 \n\t"
1151
1152 AP"loop: \n\t"
1153 "vldm %[s]!, {d0,d1,d2,d3} \n\t"
1154 "vand q2, q0, q15 \n\t"
1155 "vand q3, q1, q15 \n\t"
1156 "vand q4, q0, q14 \n\t"
1157 "vand q5, q1, q14 \n\t"
1158 // fixme: can i do this with xor
1159 "cmp %[tmp], %[s] \n\t"
1160
1161 "vmvn q6, q2 \n\t"
1162 "vmvn q7, q3 \n\t"
1163
1164 "vorr q0, q6,q4 \n\t"
1165 "vorr q1, q7,q5 \n\t"
1166
1167 "vstm %[d]!, {d0,d1,d2,d3} \n\t"
1168
1169 "bhi "AP"loop \n\t"
1170
1171 : // no out
1172 : // input
1173 [e] "r" (src->image.data+ src->cache_entry.w*src->cache_entry.h),
1174 [s] "r" (src->image.data),
1175 [tmp] "r" (tmp),
1176 [d] "r" (dst->image.data)
1177 : "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q14", "q15",
1178 "memory"
1179 );
1180#undef AP
1181 }
1182 return EINA_TRUE;
1183}
1184#endif
1185
1186static Eina_Bool
1187negation_filter(Evas_Filter_Info *info, RGBA_Image *src, RGBA_Image *dst)
1188{
1189 uint32_t *in, *out;
1190 int i,j;
1191 int w,h;
1192 uint32_t a;
1193 uint8_t r,g,b;
1194
1195#if BUILD_NEON0
1196 if (evas_common_cpu_has_feature(CPU_FEATURE_NEON) &&
1197 (!src->cache_entry.flags.alpha))
1198 return negation_filter_neon(info, src, dst);
1199#endif
1200
1201 in = src->image.data;
1202 out = dst->image.data;
1203 w = src->cache_entry.w;
1204 h = src->cache_entry.h;
1205
1206 if (src->cache_entry.flags.alpha)
1207 {
1208 for (i = 0; i < h; i++)
1209 {
1210 for (j = 0; j < w; j++)
1211 {
1212 a = A_VAL(in);
1213 r = R_VAL(in);
1214 g = G_VAL(in);
1215 b = B_VAL(in);
1216 *out = ARGB_JOIN(a, a - r, a - g, a - b);
1217 out++;
1218 in++;
1219 }
1220 }
1221 }
1222 else
1223 {
1224 for (i = 0; i < h; i++)
1225 {
1226 for (j = 0; j < w; j++)
1227 {
1228 a = A_VAL(in);
1229 r = R_VAL(in);
1230 g = G_VAL(in);
1231 b = B_VAL(in);
1232 *out = ARGB_JOIN(a, ~r, ~g, ~b);
1233 out++;
1234 in++;
1235 }
1236 }
1237 }
1238 return EINA_TRUE;
1239 info = NULL;
1240}
1241
1242static Eina_Bool
1243sepia_filter(Evas_Filter_Info *info __UNUSED__, RGBA_Image *src, RGBA_Image *dst)
1244{
1245 uint32_t *in, *out;
1246 int i, j;
1247 int w, h;
1248 uint32_t a, r, g, b, nr, ng, nb;
1249
1250 in = src->image.data;
1251 out = dst->image.data;
1252 w = src->cache_entry.w;
1253 h = src->cache_entry.h;
1254
1255 for (i = 0; i < h; i++)
1256 {
1257 for (j = 0; j < w; j++)
1258 {
1259 a = A_VAL(in);
1260 r = R_VAL(in);
1261 g = G_VAL(in);
1262 b = B_VAL(in);
1263 nr = ((uint32_t)((r * 0.393) + (g * 0.769) + (b * 0.189)));
1264 ng = ((uint32_t)((r * 0.349) + (g * 0.686) + (b * 0.168)));
1265 nb = ((uint32_t)((r * 0.272) + (g * 0.534) + (b * 0.131)));
1266 if (nr > 255) nr = 255;
1267 if (ng > 255) ng = 255;
1268 if (nb > 255) nb = 255;
1269 *out = ARGB_JOIN(a, nr, ng, nb);
1270 out++;
1271 in++;
1272 }
1273 }
1274
1275 return EINA_TRUE;
1276
1277}
1278
1279static Eina_Bool
1280greyscale_filter(Evas_Filter_Info *info __UNUSED__, RGBA_Image *src, RGBA_Image *dst)
1281{
1282 uint32_t *in, *out;
1283 int i, j;
1284 int w, h;
1285 uint32_t cur;
1286 uint32_t a, r, g, b;
1287
1288 in = src->image.data;
1289 out = dst->image.data;
1290 w = src->cache_entry.w;
1291 h = src->cache_entry.h;
1292
1293 if (src->cache_entry.flags.alpha)
1294 {
1295 for (i = 0; i < h; i++)
1296 {
1297 for (j = 0; j < w; j++)
1298 {
1299 a = A_VAL(in);
1300 r = R_VAL(in);
1301 g = G_VAL(in);
1302 b = B_VAL(in);
1303 cur = (r * 0.3) + (g * 0.59) + (b * 0.11);
1304 *out = ARGB_JOIN(a, r, g, b);
1305 out++;
1306 in++;
1307 }
1308 }
1309 }
1310 else
1311 {
1312 for (i = 0 ; i < h ; i ++)
1313 {
1314 for (j = 0; j < w ; j ++)
1315 {
1316 r = R_VAL(in);
1317 g = G_VAL(in);
1318 b = B_VAL(in);
1319 cur = r * 0.3 + g * 0.59 + b * 0.11;
1320 *out = ARGB_JOIN(255, r, g, b);
1321 out++;
1322 in++;
1323 }
1324 }
1325 }
1326 return EINA_TRUE;
1327}
1328
1329static Eina_Bool
1330brightness_filter(Evas_Filter_Info *info, RGBA_Image *src, RGBA_Image *dst)
1331{
1332 uint32_t *in, *out;
1333 int i, j;
1334 int w, h;
1335 int a,r,g,b;
1336 int delta;
1337 int adjdelta;
1338 Evas_Filter_Info_Brightness *bness;
1339
1340 in = src->image.data;
1341 out = dst->image.data;
1342 w = src->cache_entry.w;
1343 h = src->cache_entry.h;
1344 bness = info->data;
1345
1346 delta = bness->adjust * 255;
1347 if (delta > 255)
1348 delta = 255;
1349 else if (delta < -255)
1350 delta = -255;
1351
1352 /* Note we could optimise the -255, 0 and 255 cases, but why would people
1353 * be doing that */
1354 if (delta >= 0)
1355 {
1356 for (i = 0; i < h; i++)
1357 {
1358 for (j = 0; j < w; j++)
1359 {
1360 a = A_VAL(in);
1361 r = R_VAL(in);
1362 g = G_VAL(in);
1363 b = B_VAL(in);
1364 adjdelta = (a * delta) >> 8;
1365 r = MIN(r + adjdelta, a);
1366 g = MIN(g + adjdelta, a);
1367 b = MIN(b + adjdelta, a);
1368 *out = ARGB_JOIN(a, r ,g, b);
1369 out++;
1370 in++;
1371 }
1372 }
1373 }
1374 else
1375 {
1376 /* Delta negative */
1377 for (i = 0; i < h; i++)
1378 {
1379 for (j = 0; j < w; j++)
1380 {
1381 a = A_VAL(in);
1382 r = R_VAL(in);
1383 g = G_VAL(in);
1384 b = B_VAL(in);
1385 adjdelta = (a * delta) >> 8;
1386 r = MAX(r + adjdelta, 0);
1387 g = MAX(g + adjdelta, 0);
1388 b = MAX(b + adjdelta, 0);
1389 *out = ARGB_JOIN(a, r ,g, b);
1390 out++;
1391 in++;
1392 }
1393 }
1394 }
1395
1396 return EINA_TRUE;
1397
1398}
1399
1400static Eina_Bool
1401contrast_filter(Evas_Filter_Info *info __UNUSED__, RGBA_Image *src, RGBA_Image *dst)
1402{
1403 uint32_t *in, *out;
1404 int i, j;
1405 int w, h;
1406
1407 in = src->image.data;
1408 out = dst->image.data;
1409 w = src->cache_entry.w;
1410 h = src->cache_entry.h;
1411
1412 for (i = 0; i < h; i++)
1413 {
1414 for (j = 0; j < w; j++)
1415 {
1416 // FIXME: not even implemented
1417 out++;
1418 in++;
1419 }
1420 }
1421
1422 return EINA_TRUE;
1423
1424}
1425#endif
1426
1427/* vim:set ts=8 sw=3 sts=3 expandtab cino=>5n-2f0^-2{2(0W1st0 :*/
diff --git a/libraries/evas/src/lib/canvas/evas_focus.c b/libraries/evas/src/lib/canvas/evas_focus.c
deleted file mode 100644
index 29da7e7..0000000
--- a/libraries/evas/src/lib/canvas/evas_focus.c
+++ /dev/null
@@ -1,61 +0,0 @@
1#include "evas_common.h"
2#include "evas_private.h"
3
4/* private calls */
5
6/* local calls */
7
8/* public calls */
9
10EAPI void
11evas_object_focus_set(Evas_Object *obj, Eina_Bool focus)
12{
13 int event_id = 0;
14 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
15 return;
16 MAGIC_CHECK_END();
17
18 _evas_object_event_new();
19
20 event_id = _evas_event_counter;
21 if (focus)
22 {
23 if (obj->focused) goto end;
24 if (obj->layer->evas->focused)
25 evas_object_focus_set(obj->layer->evas->focused, 0);
26 obj->focused = 1;
27 obj->layer->evas->focused = obj;
28 evas_object_event_callback_call(obj, EVAS_CALLBACK_FOCUS_IN, NULL, event_id);
29 evas_event_callback_call(obj->layer->evas,
30 EVAS_CALLBACK_CANVAS_OBJECT_FOCUS_IN, obj);
31 }
32 else
33 {
34 if (!obj->focused) goto end;
35 obj->focused = 0;
36 obj->layer->evas->focused = NULL;
37 evas_object_event_callback_call(obj, EVAS_CALLBACK_FOCUS_OUT, NULL, event_id);
38 evas_event_callback_call(obj->layer->evas,
39 EVAS_CALLBACK_CANVAS_OBJECT_FOCUS_OUT, obj);
40 }
41 end:
42 _evas_post_event_callback_call(obj->layer->evas);
43}
44
45EAPI Eina_Bool
46evas_object_focus_get(const Evas_Object *obj)
47{
48 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
49 return 0;
50 MAGIC_CHECK_END();
51 return obj->focused;
52}
53
54EAPI Evas_Object *
55evas_focus_get(const Evas *e)
56{
57 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
58 return NULL;
59 MAGIC_CHECK_END();
60 return e->focused;
61}
diff --git a/libraries/evas/src/lib/canvas/evas_font_dir.c b/libraries/evas/src/lib/canvas/evas_font_dir.c
deleted file mode 100644
index e97f7f7..0000000
--- a/libraries/evas/src/lib/canvas/evas_font_dir.c
+++ /dev/null
@@ -1,1349 +0,0 @@
1#ifdef HAVE_CONFIG_H
2# include <config.h>
3#endif
4
5#ifdef HAVE_EVIL
6# include <Evil.h>
7#endif
8
9#ifdef BUILD_FONT_LOADER_EET
10#include <Eet.h>
11#endif
12
13#ifdef HAVE_FONTCONFIG
14#include <fontconfig/fontconfig.h>
15#endif
16
17#include "evas_common.h"
18#include "evas_private.h"
19
20/* font dir cache */
21static Eina_Hash *font_dirs = NULL;
22static Eina_List *fonts_cache = NULL;
23static Eina_List *fonts_zero = NULL;
24
25typedef struct _Fndat Fndat;
26
27struct _Fndat
28{
29 Evas_Font_Description *fdesc;
30 const char *source;
31 Evas_Font_Size size;
32 Evas_Font_Set *font;
33 int ref;
34 Font_Rend_Flags wanted_rend;
35
36#ifdef HAVE_FONTCONFIG
37 FcFontSet *set;
38 FcPattern *p_nm;
39#endif
40};
41
42/* private methods for font dir cache */
43static Eina_Bool font_cache_dir_free(const Eina_Hash *hash, const void *key, void *data, void *fdata);
44static Evas_Font_Dir *object_text_font_cache_dir_update(char *dir, Evas_Font_Dir *fd);
45static Evas_Font *object_text_font_cache_font_find_x(Evas_Font_Dir *fd, char *font);
46static Evas_Font *object_text_font_cache_font_find_file(Evas_Font_Dir *fd, char *font);
47static Evas_Font *object_text_font_cache_font_find_alias(Evas_Font_Dir *fd, char *font);
48static Evas_Font *object_text_font_cache_font_find(Evas_Font_Dir *fd, char *font);
49static Evas_Font_Dir *object_text_font_cache_dir_add(char *dir);
50static void object_text_font_cache_dir_del(char *dir, Evas_Font_Dir *fd);
51static int evas_object_text_font_string_parse(char *buffer, char dest[14][256]);
52
53#ifdef HAVE_FONTCONFIG
54static int fc_init = 0;
55#endif
56
57void
58evas_font_dir_cache_free(void)
59{
60 if (!font_dirs) return;
61
62 eina_hash_foreach(font_dirs, font_cache_dir_free, NULL);
63 eina_hash_free(font_dirs);
64 font_dirs = NULL;
65
66#ifdef HAVE_FONTCONFIG
67/* this is bad i got a:
68 * fccache.c:512: FcCacheFini: Assertion fcCacheChains[i] == ((void *)0)' failed.
69 *
70 * all i can do for now is shut this puppy down. butthat breaks, so disable
71 * it as in reality - there is little reason to care about the memory not
72 * being freed etc.
73 *
74 * fc_init--;
75 * if (fc_init == 0) FcFini();
76 */
77#endif
78}
79
80const char *
81evas_font_dir_cache_find(char *dir, char *font)
82{
83 Evas_Font_Dir *fd = NULL;
84
85 if (!font_dirs) font_dirs = eina_hash_string_superfast_new(NULL);
86 else fd = eina_hash_find(font_dirs, dir);
87 fd = object_text_font_cache_dir_update(dir, fd);
88 if (fd)
89 {
90 Evas_Font *fn;
91
92 fn = object_text_font_cache_font_find(fd, font);
93 if (fn)
94 {
95 return fn->path;
96 }
97 }
98 return NULL;
99}
100
101static Eina_List *
102evas_font_set_get(const char *name)
103{
104 Eina_List *fonts = NULL;
105 char *p;
106
107 p = strchr(name, ',');
108 if (!p)
109 {
110 fonts = eina_list_append(fonts, eina_stringshare_add(name));
111 }
112 else
113 {
114 const char *pp;
115 char *nm;
116
117 pp = name;
118 while (p)
119 {
120 nm = alloca(p - pp + 1);
121 strncpy(nm, pp, p - pp);
122 nm[p - pp] = 0;
123 fonts = eina_list_append(fonts, eina_stringshare_add(nm));
124 pp = p + 1;
125 p = strchr(pp, ',');
126 if (!p) fonts = eina_list_append(fonts, eina_stringshare_add(pp));
127 }
128 }
129 return fonts;
130}
131
132void
133evas_fonts_zero_free(Evas *evas)
134{
135 Fndat *fd;
136
137 EINA_LIST_FREE(fonts_zero, fd)
138 {
139 if (fd->fdesc) evas_font_desc_unref(fd->fdesc);
140 if (fd->source) eina_stringshare_del(fd->source);
141 evas->engine.func->font_free(evas->engine.data.output, fd->font);
142#ifdef HAVE_FONTCONFIG
143 if (fd->set) FcFontSetDestroy(fd->set);
144 if (fd->p_nm) FcPatternDestroy(fd->p_nm);
145#endif
146 free(fd);
147 }
148}
149
150void
151evas_fonts_zero_presure(Evas *evas)
152{
153 Fndat *fd;
154
155 while (fonts_zero
156 && eina_list_count(fonts_zero) > 4) /* 4 is arbitrary */
157 {
158 fd = eina_list_data_get(fonts_zero);
159
160 if (fd->ref != 0) break;
161 fonts_zero = eina_list_remove_list(fonts_zero, fonts_zero);
162
163 if (fd->fdesc) evas_font_desc_unref(fd->fdesc);
164 if (fd->source) eina_stringshare_del(fd->source);
165 evas->engine.func->font_free(evas->engine.data.output, fd->font);
166#ifdef HAVE_FONTCONFIG
167 if (fd->set) FcFontSetDestroy(fd->set);
168 if (fd->p_nm) FcPatternDestroy(fd->p_nm);
169#endif
170 free(fd);
171
172 if (eina_list_count(fonts_zero) < 5) break;
173 }
174}
175
176void
177evas_font_free(Evas *evas, void *font)
178{
179 Eina_List *l;
180 Fndat *fd;
181
182 EINA_LIST_FOREACH(fonts_cache, l, fd)
183 {
184 if (fd->font == font)
185 {
186 fd->ref--;
187 if (fd->ref == 0)
188 {
189 fonts_cache = eina_list_remove_list(fonts_cache, l);
190 fonts_zero = eina_list_append(fonts_zero, fd);
191 }
192 break;
193 }
194 }
195 while (fonts_zero
196 && eina_list_count(fonts_zero) > 42) /* 42 is arbitrary */
197 {
198 fd = eina_list_data_get(fonts_zero);
199
200 if (fd->ref != 0) break;
201 fonts_zero = eina_list_remove_list(fonts_zero, fonts_zero);
202
203 if (fd->fdesc) evas_font_desc_unref(fd->fdesc);
204 if (fd->source) eina_stringshare_del(fd->source);
205 evas->engine.func->font_free(evas->engine.data.output, fd->font);
206#ifdef HAVE_FONTCONFIG
207 if (fd->set) FcFontSetDestroy(fd->set);
208 if (fd->p_nm) FcPatternDestroy(fd->p_nm);
209#endif
210 free(fd);
211
212 if (eina_list_count(fonts_zero) < 43) break;
213 }
214}
215
216static void
217evas_font_init(void)
218{
219 static int done = 0;
220 if (done) return;
221 done = 1;
222#ifdef HAVE_FONTCONFIG
223 fc_init++;
224 if (fc_init == 1)
225 {
226 FcInit();
227 FcConfigEnableHome(1);
228 }
229#endif
230}
231
232#ifdef HAVE_FONTCONFIG
233static Evas_Font_Set *
234evas_load_fontconfig(Evas *evas, FcFontSet *set, int size,
235 Font_Rend_Flags wanted_rend)
236{
237 Evas_Font_Set *font = NULL;
238 int i;
239
240 /* Do loading for all in family */
241 for (i = 0; i < set->nfont; i++)
242 {
243 FcValue filename;
244
245 FcPatternGet(set->fonts[i], FC_FILE, 0, &filename);
246
247 if (font)
248 evas->engine.func->font_add(evas->engine.data.output, font, (char *)filename.u.s, size, wanted_rend);
249 else
250 font = evas->engine.func->font_load(evas->engine.data.output, (char *)filename.u.s, size, wanted_rend);
251 }
252
253 return font;
254}
255#endif
256
257#ifdef HAVE_FONTCONFIG
258/* In sync with Evas_Font_Style, Evas_Font_Weight and Evas_Font_Width */
259static int _fc_slant_map[] =
260{
261 FC_SLANT_ROMAN,
262 FC_SLANT_OBLIQUE,
263 FC_SLANT_ITALIC
264};
265
266static int _fc_weight_map[] =
267{
268 FC_WEIGHT_NORMAL,
269 FC_WEIGHT_THIN,
270 FC_WEIGHT_ULTRALIGHT,
271 FC_WEIGHT_LIGHT,
272 FC_WEIGHT_BOOK,
273 FC_WEIGHT_MEDIUM,
274 FC_WEIGHT_SEMIBOLD,
275 FC_WEIGHT_BOLD,
276 FC_WEIGHT_ULTRABOLD,
277 FC_WEIGHT_BLACK,
278 FC_WEIGHT_EXTRABLACK
279};
280
281# ifdef FC_WIDTH
282static int _fc_width_map[] =
283{
284 FC_WIDTH_NORMAL,
285 FC_WIDTH_ULTRACONDENSED,
286 FC_WIDTH_EXTRACONDENSED,
287 FC_WIDTH_CONDENSED,
288 FC_WIDTH_SEMICONDENSED,
289 FC_WIDTH_SEMIEXPANDED,
290 FC_WIDTH_EXPANDED,
291 FC_WIDTH_EXTRAEXPANDED,
292 FC_WIDTH_ULTRAEXPANDED
293};
294# endif
295
296#endif
297
298struct _Style_Map
299{
300 const char *name;
301 int type;
302};
303typedef struct _Style_Map Style_Map;
304
305static Style_Map _style_width_map[] =
306{
307 {"normal", EVAS_FONT_WIDTH_NORMAL},
308 {"ultracondensed", EVAS_FONT_WIDTH_ULTRACONDENSED},
309 {"extracondensed", EVAS_FONT_WIDTH_EXTRACONDENSED},
310 {"condensed", EVAS_FONT_WIDTH_CONDENSED},
311 {"semicondensed", EVAS_FONT_WIDTH_SEMICONDENSED},
312 {"semiexpanded", EVAS_FONT_WIDTH_SEMIEXPANDED},
313 {"expanded", EVAS_FONT_WIDTH_EXPANDED},
314 {"extraexpanded", EVAS_FONT_WIDTH_EXTRAEXPANDED},
315 {"ultraexpanded", EVAS_FONT_WIDTH_ULTRAEXPANDED},
316};
317
318static Style_Map _style_weight_map[] =
319{
320 {"normal", EVAS_FONT_WEIGHT_NORMAL},
321 {"thin", EVAS_FONT_WEIGHT_THIN},
322 {"ultralight", EVAS_FONT_WEIGHT_ULTRALIGHT},
323 {"light", EVAS_FONT_WEIGHT_LIGHT},
324 {"book", EVAS_FONT_WEIGHT_BOOK},
325 {"medium", EVAS_FONT_WEIGHT_MEDIUM},
326 {"semibold", EVAS_FONT_WEIGHT_SEMIBOLD},
327 {"bold", EVAS_FONT_WEIGHT_BOLD},
328 {"ultrabold", EVAS_FONT_WEIGHT_ULTRABOLD},
329 {"black", EVAS_FONT_WEIGHT_BLACK},
330 {"extrablack", EVAS_FONT_WEIGHT_EXTRABLACK}
331};
332
333static Style_Map _style_slant_map[] =
334{
335 {"normal", EVAS_FONT_SLANT_NORMAL},
336 {"oblique", EVAS_FONT_SLANT_OBLIQUE},
337 {"italic", EVAS_FONT_SLANT_ITALIC}
338};
339
340#define _STYLE_MAP_LEN(x) (sizeof(x) / sizeof(*(x)))
341/**
342 * @internal
343 * Find a certain attribute from the map in the style.
344 * @return the index of the found one.
345 */
346static int
347_evas_font_style_find_internal(const char *style, const char *style_end,
348 Style_Map _map[], size_t map_len)
349{
350 size_t i;
351 while (style < style_end)
352 {
353 for (i = 0 ; i < map_len ; i++)
354 {
355 size_t len;
356 const char *cur = _map[i].name;
357 len = strlen(cur);
358 if (!strncasecmp(style, cur, len) &&
359 (!cur[len] || (cur[len] == ' ')))
360 {
361 return _map[i].type;
362 }
363 }
364 style = strchr(style, ' ');
365 if (!style)
366 break;
367
368 while (*style && (*style == ' '))
369 style++;
370 }
371 return 0;
372}
373
374int
375evas_font_style_find(const char *start, const char *end,
376 Evas_Font_Style style)
377{
378#define _RET_STYLE(x) \
379 return _evas_font_style_find_internal(start, end, \
380 _style_##x##_map, _STYLE_MAP_LEN(_style_##x##_map));
381 switch (style)
382 {
383 case EVAS_FONT_STYLE_SLANT:
384 _RET_STYLE(slant);
385 case EVAS_FONT_STYLE_WEIGHT:
386 _RET_STYLE(weight);
387 case EVAS_FONT_STYLE_WIDTH:
388 _RET_STYLE(width);
389 default:
390 return 0;
391 }
392#undef _RET_STYLE
393}
394
395void
396evas_font_desc_unref(Evas_Font_Description *fdesc)
397{
398 if (--(fdesc->ref) == 0)
399 {
400 eina_stringshare_del(fdesc->name);
401 eina_stringshare_del(fdesc->fallbacks);
402 eina_stringshare_del(fdesc->lang);
403 free(fdesc);
404 }
405}
406
407Evas_Font_Description *
408evas_font_desc_ref(Evas_Font_Description *fdesc)
409{
410 fdesc->ref++;
411 return fdesc;
412}
413
414Evas_Font_Description *
415evas_font_desc_new(void)
416{
417 Evas_Font_Description *fdesc;
418 fdesc = calloc(1, sizeof(*fdesc));
419 fdesc->ref = 1;
420 fdesc->is_new = EINA_TRUE;
421
422 return fdesc;
423}
424
425Evas_Font_Description *
426evas_font_desc_dup(const Evas_Font_Description *fdesc)
427{
428 Evas_Font_Description *new;
429 new = evas_font_desc_new();
430 memcpy(new, fdesc, sizeof(*new));
431 new->ref = 1;
432 new->is_new = EINA_TRUE;
433 new->name = eina_stringshare_ref(new->name);
434
435 return new;
436}
437
438int
439evas_font_desc_cmp(const Evas_Font_Description *a,
440 const Evas_Font_Description *b)
441{
442 /* FIXME: Do actual comparison, i.e less than and bigger than. */
443 return !((a->name == b->name) && (a->weight == b->weight) &&
444 (a->slant == b->slant) && (a->width == b->width) &&
445 (a->lang == b->lang));
446}
447
448void
449evas_font_name_parse(Evas_Font_Description *fdesc, const char *name)
450{
451 const char *end;
452
453 end = strchr(name, ':');
454 if (!end)
455 eina_stringshare_replace(&(fdesc->name), name);
456 else
457 eina_stringshare_replace_length(&(fdesc->name), name, end - name);
458
459 while (end)
460 {
461 const char *tend;
462 name = end;
463 end = strchr(end + 1, ':');
464 if (!end)
465 tend = name + strlen(name);
466 else
467 tend = end;
468
469 if (!strncmp(name, ":style=", 7))
470 {
471#define _SET_STYLE(x) \
472 fdesc->x = _evas_font_style_find_internal(name + 7, tend, \
473 _style_##x##_map, _STYLE_MAP_LEN(_style_##x##_map));
474 _SET_STYLE(slant);
475 _SET_STYLE(weight);
476 _SET_STYLE(width);
477#undef _SET_STYLE
478 }
479 else if (!strncmp(name, ":lang=", 6))
480 {
481 const char *tmp = name + 6;
482 eina_stringshare_replace_length(&(fdesc->lang), tmp, tend - tmp);
483 }
484 }
485}
486
487void *
488evas_font_load(Evas *evas, Evas_Font_Description *fdesc, const char *source, Evas_Font_Size size)
489{
490#ifdef HAVE_FONTCONFIG
491 FcPattern *p_nm = NULL;
492 FcFontSet *set = NULL;
493#endif
494
495 Evas_Font_Set *font = NULL;
496 Eina_List *fonts, *l;
497 Fndat *fd;
498 char *nm;
499 Font_Rend_Flags wanted_rend = 0;
500
501 if (!fdesc) return NULL;
502 fdesc->is_new = EINA_FALSE;
503
504 if (fdesc->slant != EVAS_FONT_SLANT_NORMAL)
505 wanted_rend |= FONT_REND_SLANT;
506 if (fdesc->weight == EVAS_FONT_WEIGHT_BOLD)
507 wanted_rend |= FONT_REND_WEIGHT;
508
509 evas_font_init();
510
511 EINA_LIST_FOREACH(fonts_cache, l, fd)
512 {
513 if (!evas_font_desc_cmp(fdesc, fd->fdesc))
514 {
515 if (((!source) && (!fd->source)) ||
516 ((source) && (fd->source) && (!strcmp(source, fd->source))))
517 {
518 if ((size == fd->size) &&
519 (wanted_rend == fd->wanted_rend))
520 {
521 fonts_cache = eina_list_promote_list(fonts_cache, l);
522 fd->ref++;
523 return fd->font;
524 }
525#ifdef HAVE_FONTCONFIG
526 else if (fd->set && fd->p_nm)
527 {
528 font = evas_load_fontconfig(evas, fd->set, size,
529 wanted_rend);
530 goto on_find;
531 }
532#endif
533 }
534 }
535 }
536
537 EINA_LIST_FOREACH(fonts_zero, l, fd)
538 {
539 if (!evas_font_desc_cmp(fdesc, fd->fdesc))
540 {
541 if (((!source) && (!fd->source)) ||
542 ((source) && (fd->source) && (!strcmp(source, fd->source))))
543 {
544 if ((size == fd->size) &&
545 (wanted_rend == fd->wanted_rend))
546 {
547 fonts_zero = eina_list_remove_list(fonts_zero, l);
548 fonts_cache = eina_list_prepend(fonts_cache, fd);
549 fd->ref++;
550 return fd->font;
551 }
552#ifdef HAVE_FONTCONFIG
553 else if (fd->set && fd->p_nm)
554 {
555 font = evas_load_fontconfig(evas, fd->set, size,
556 wanted_rend);
557 goto on_find;
558 }
559#endif
560 }
561 }
562 }
563
564 fonts = evas_font_set_get(fdesc->name);
565 EINA_LIST_FOREACH(fonts, l, nm) /* Load each font in append */
566 {
567 if (l == fonts || !font) /* First iteration OR no font */
568 {
569#ifdef BUILD_FONT_LOADER_EET
570 if (source) /* Load Font from "eet" source */
571 {
572 Eet_File *ef;
573 char *fake_name;
574
575 fake_name = evas_file_path_join(source, nm);
576 if (fake_name)
577 {
578 font = evas->engine.func->font_load(evas->engine.data.output, fake_name, size, wanted_rend);
579 if (!font) /* Load from fake name failed, probably not cached */
580 {
581 /* read original!!! */
582 ef = eet_open(source, EET_FILE_MODE_READ);
583 if (ef)
584 {
585 void *fdata;
586 int fsize = 0;
587
588 fdata = eet_read(ef, nm, &fsize);
589 if ((fdata) && (fsize > 0))
590 {
591 font = evas->engine.func->font_memory_load(evas->engine.data.output, fake_name, size, fdata, fsize, wanted_rend);
592 free(fdata);
593 }
594 eet_close(ef);
595 }
596 }
597 free(fake_name);
598 }
599 }
600 if (!font) /* Source load failed */
601 {
602#endif
603 if (evas_file_path_is_full_path((char *)nm)) /* Try filename */
604 font = evas->engine.func->font_load(evas->engine.data.output, (char *)nm, size, wanted_rend);
605 else /* search font path */
606 {
607 Eina_List *ll;
608 char *dir;
609
610 EINA_LIST_FOREACH(evas->font_path, ll, dir)
611 {
612 const char *f_file;
613
614 f_file = evas_font_dir_cache_find(dir, (char *)nm);
615 if (f_file)
616 {
617 font = evas->engine.func->font_load(evas->engine.data.output, f_file, size, wanted_rend);
618 if (font) break;
619 }
620 }
621 }
622#ifdef BUILD_FONT_LOADER_EET
623 }
624#endif
625 }
626 else /* Base font loaded, append others */
627 {
628#ifdef BUILD_FONT_LOADER_EET
629 void *ok = NULL;
630
631 if (source)
632 {
633 Eet_File *ef;
634 char *fake_name;
635
636 fake_name = evas_file_path_join(source, nm);
637 if (fake_name)
638 {
639 /* FIXME: make an engine func */
640 if (!evas->engine.func->font_add(evas->engine.data.output, font, fake_name, size, wanted_rend))
641 {
642 /* read original!!! */
643 ef = eet_open(source, EET_FILE_MODE_READ);
644 if (ef)
645 {
646 void *fdata;
647 int fsize = 0;
648
649 fdata = eet_read(ef, nm, &fsize);
650 if ((fdata) && (fsize > 0))
651 {
652 ok = evas->engine.func->font_memory_add(evas->engine.data.output, font, fake_name, size, fdata, fsize, wanted_rend);
653 free(fdata);
654 }
655 eet_close(ef);
656 }
657 }
658 else
659 ok = (void *)1;
660 free(fake_name);
661 }
662 }
663 if (!ok)
664 {
665#endif
666 if (evas_file_path_is_full_path((char *)nm))
667 evas->engine.func->font_add(evas->engine.data.output, font, (char *)nm, size, wanted_rend);
668 else
669 {
670 Eina_List *ll;
671 char *dir;
672
673 EINA_LIST_FOREACH(evas->font_path, ll, dir)
674 {
675 const char *f_file;
676
677 f_file = evas_font_dir_cache_find(dir, (char *)nm);
678 if (f_file)
679 {
680 if (evas->engine.func->font_add(evas->engine.data.output, font, f_file, size, wanted_rend))
681 break;
682 }
683 }
684 }
685#ifdef BUILD_FONT_LOADER_EET
686 }
687#endif
688 }
689 eina_stringshare_del(nm);
690 }
691 fonts = eina_list_free(fonts);
692
693#ifdef HAVE_FONTCONFIG
694 if (!font) /* Search using fontconfig */
695 {
696 FcResult res;
697
698 p_nm = FcPatternBuild (NULL,
699 FC_WEIGHT, FcTypeInteger, _fc_weight_map[fdesc->weight],
700 FC_SLANT, FcTypeInteger, _fc_slant_map[fdesc->slant],
701#ifdef FC_WIDTH
702 FC_WIDTH, FcTypeInteger, _fc_width_map[fdesc->width],
703#endif
704 NULL);
705 FcPatternAddString (p_nm, FC_FAMILY, (FcChar8*) fdesc->name);
706
707 /* Handle font fallbacks */
708 if (fdesc->fallbacks)
709 {
710 while (1)
711 {
712 const char *start, *end;
713 start = fdesc->fallbacks;
714 end = strchr(start, ',');
715 if (end)
716 {
717 char *tmp = alloca((end - start) + 1);
718 strncpy(tmp, start, end - start);
719 tmp[end - start] = 0;
720 FcPatternAddString (p_nm, FC_FAMILY, (FcChar8*) tmp);
721 }
722 else
723 {
724 FcPatternAddString (p_nm, FC_FAMILY, (FcChar8*) start);
725 break;
726 }
727 }
728 }
729
730 if (fdesc->lang)
731 FcPatternAddString (p_nm, FC_LANG, (FcChar8 *) fdesc->lang);
732
733 FcConfigSubstitute(NULL, p_nm, FcMatchPattern);
734 FcDefaultSubstitute(p_nm);
735
736 /* do matching */
737 set = FcFontSort(NULL, p_nm, FcTrue, NULL, &res);
738 if (!set)
739 {
740 ERR("No fontconfig font matches '%s'. It was the last resource, no font found!", fdesc->name);
741 FcPatternDestroy(p_nm);
742 p_nm = NULL;
743 }
744 else
745 {
746 font = evas_load_fontconfig(evas, set, size, wanted_rend);
747 }
748 }
749#endif
750
751#ifdef HAVE_FONTCONFIG
752 on_find:
753#endif
754 fd = calloc(1, sizeof(Fndat));
755 if (fd)
756 {
757 fd->fdesc = evas_font_desc_ref(fdesc);
758 if (source) fd->source = eina_stringshare_add(source);
759 fd->font = font;
760 fd->wanted_rend = wanted_rend;
761 fd->size = size;
762 fd->ref = 1;
763 fonts_cache = eina_list_prepend(fonts_cache, fd);
764#ifdef HAVE_FONTCONFIG
765 fd->set = set;
766 fd->p_nm = p_nm;
767#endif
768 }
769
770 if (font)
771 evas->engine.func->font_hinting_set(evas->engine.data.output, font,
772 evas->hinting);
773 return font;
774}
775
776void
777evas_font_load_hinting_set(Evas *evas, void *font, int hinting)
778{
779 evas->engine.func->font_hinting_set(evas->engine.data.output, font,
780 hinting);
781}
782
783Eina_List *
784evas_font_dir_available_list(const Evas *evas)
785{
786 Eina_List *l;
787 Eina_List *ll;
788 Eina_List *available = NULL;
789 char *dir;
790
791#ifdef HAVE_FONTCONFIG
792 /* Add font config fonts */
793 FcPattern *p;
794 FcFontSet *set = NULL;
795 FcObjectSet *os;
796 int i;
797
798 evas_font_init();
799
800 p = FcPatternCreate();
801 os = FcObjectSetBuild(FC_FAMILY, FC_STYLE, NULL);
802
803 if (p && os) set = FcFontList(NULL, p, os);
804
805 if (p) FcPatternDestroy(p);
806 if (os) FcObjectSetDestroy(os);
807
808 if (set)
809 {
810 for (i = 0; i < set->nfont; i++)
811 {
812 char *font;
813
814 font = (char *)FcNameUnparse(set->fonts[i]);
815 available = eina_list_append(available, eina_stringshare_add(font));
816 free(font);
817 }
818
819 FcFontSetDestroy(set);
820 }
821#endif
822
823 /* Add fonts in evas font_path*/
824 if (!evas->font_path)
825 return available;
826
827 if (!font_dirs) font_dirs = eina_hash_string_superfast_new(NULL);
828
829 EINA_LIST_FOREACH(evas->font_path, l, dir)
830 {
831 Evas_Font_Dir *fd;
832
833 fd = eina_hash_find(font_dirs, dir);
834 fd = object_text_font_cache_dir_update(dir, fd);
835 if (fd && fd->aliases)
836 {
837 Evas_Font_Alias *fa;
838
839 EINA_LIST_FOREACH(fd->aliases, ll, fa)
840 available = eina_list_append(available, eina_stringshare_add((char *)fa->alias));
841 }
842 }
843
844 return available;
845}
846
847void
848evas_font_dir_available_list_free(Eina_List *available)
849{
850 while (available)
851 {
852 eina_stringshare_del(available->data);
853 available = eina_list_remove(available, available->data);
854 }
855}
856
857/* private stuff */
858static Eina_Bool
859font_cache_dir_free(const Eina_Hash *hash __UNUSED__, const void *key, void *data, void *fdata __UNUSED__)
860{
861 object_text_font_cache_dir_del((char *) key, data);
862 return 1;
863}
864
865static Evas_Font_Dir *
866object_text_font_cache_dir_update(char *dir, Evas_Font_Dir *fd)
867{
868 DATA64 mt;
869 char *tmp;
870
871 if (fd)
872 {
873 mt = evas_file_modified_time(dir);
874 if (mt != fd->dir_mod_time)
875 {
876 object_text_font_cache_dir_del(dir, fd);
877 eina_hash_del(font_dirs, dir, fd);
878 }
879 else
880 {
881 tmp = evas_file_path_join(dir, "fonts.dir");
882 if (tmp)
883 {
884 mt = evas_file_modified_time(tmp);
885 free(tmp);
886 if (mt != fd->fonts_dir_mod_time)
887 {
888 object_text_font_cache_dir_del(dir, fd);
889 eina_hash_del(font_dirs, dir, fd);
890 }
891 else
892 {
893 tmp = evas_file_path_join(dir, "fonts.alias");
894 if (tmp)
895 {
896 mt = evas_file_modified_time(tmp);
897 free(tmp);
898 }
899 if (mt != fd->fonts_alias_mod_time)
900 {
901 object_text_font_cache_dir_del(dir, fd);
902 eina_hash_del(font_dirs, dir, fd);
903 }
904 else
905 return fd;
906 }
907 }
908 }
909 }
910 return object_text_font_cache_dir_add(dir);
911}
912
913static Evas_Font *
914object_text_font_cache_font_find_x(Evas_Font_Dir *fd, char *font)
915{
916 Eina_List *l;
917 char font_prop[14][256];
918 int num;
919 Evas_Font *fn;
920
921 num = evas_object_text_font_string_parse(font, font_prop);
922 if (num != 14) return NULL;
923 EINA_LIST_FOREACH(fd->fonts, l, fn)
924 {
925 if (fn->type == 1)
926 {
927 int i;
928 int match = 0;
929
930 for (i = 0; i < 14; i++)
931 {
932 if ((font_prop[i][0] == '*') && (font_prop[i][1] == 0))
933 match++;
934 else
935 {
936 if (!strcasecmp(font_prop[i], fn->x.prop[i])) match++;
937 else break;
938 }
939 }
940 if (match == 14) return fn;
941 }
942 }
943 return NULL;
944}
945
946static Evas_Font *
947object_text_font_cache_font_find_file(Evas_Font_Dir *fd, char *font)
948{
949 Eina_List *l;
950 Evas_Font *fn;
951
952 EINA_LIST_FOREACH(fd->fonts, l, fn)
953 {
954 if (fn->type == 0)
955 {
956 if (!strcasecmp(font, fn->simple.name)) return fn;
957 }
958 }
959 return NULL;
960}
961
962static Evas_Font *
963object_text_font_cache_font_find_alias(Evas_Font_Dir *fd, char *font)
964{
965 Eina_List *l;
966 Evas_Font_Alias *fa;
967
968 EINA_LIST_FOREACH(fd->aliases, l, fa)
969 if (!strcasecmp(fa->alias, font)) return fa->fn;
970 return NULL;
971}
972
973static Evas_Font *
974object_text_font_cache_font_find(Evas_Font_Dir *fd, char *font)
975{
976 Evas_Font *fn;
977
978 fn = eina_hash_find(fd->lookup, font);
979 if (fn) return fn;
980 fn = object_text_font_cache_font_find_alias(fd, font);
981 if (!fn) fn = object_text_font_cache_font_find_x(fd, font);
982 if (!fn) fn = object_text_font_cache_font_find_file(fd, font);
983 if (!fn) return NULL;
984 eina_hash_add(fd->lookup, font, fn);
985 return fn;
986}
987
988static Evas_Font_Dir *
989object_text_font_cache_dir_add(char *dir)
990{
991 Evas_Font_Dir *fd;
992 char *tmp, *tmp2;
993 Eina_List *fdir;
994 Evas_Font *fn;
995
996 fd = calloc(1, sizeof(Evas_Font_Dir));
997 if (!fd) return NULL;
998 fd->lookup = eina_hash_string_superfast_new(NULL);
999
1000 eina_hash_add(font_dirs, dir, fd);
1001
1002 /* READ fonts.alias, fonts.dir and directory listing */
1003
1004 /* fonts.dir */
1005 tmp = evas_file_path_join(dir, "fonts.dir");
1006 if (tmp)
1007 {
1008 FILE *f;
1009
1010 f = fopen(tmp, "rb");
1011 if (f)
1012 {
1013 int num;
1014 char fname[4096], fdef[4096];
1015
1016 if (fscanf(f, "%i\n", &num) != 1) goto cant_read;
1017 /* read font lines */
1018 while (fscanf(f, "%4090s %[^\n]\n", fname, fdef) == 2)
1019 {
1020 char font_prop[14][256];
1021 int i;
1022
1023 /* skip comments */
1024 if ((fdef[0] == '!') || (fdef[0] == '#')) continue;
1025 /* parse font def */
1026 num = evas_object_text_font_string_parse((char *)fdef, font_prop);
1027 if (num == 14)
1028 {
1029 fn = calloc(1, sizeof(Evas_Font));
1030 if (fn)
1031 {
1032 fn->type = 1;
1033 for (i = 0; i < 14; i++)
1034 fn->x.prop[i] = eina_stringshare_add(font_prop[i]);
1035 tmp2 = evas_file_path_join(dir, fname);
1036 if (tmp2)
1037 {
1038 fn->path = eina_stringshare_add(tmp2);
1039 free(tmp2);
1040 }
1041 fd->fonts = eina_list_append(fd->fonts, fn);
1042 }
1043 }
1044 }
1045 cant_read: ;
1046 fclose(f);
1047 }
1048 free(tmp);
1049 }
1050
1051 /* directoy listing */
1052 fdir = evas_file_path_list(dir, "*.ttf", 0);
1053 while (fdir)
1054 {
1055 tmp = evas_file_path_join(dir, fdir->data);
1056 if (tmp)
1057 {
1058 fn = calloc(1, sizeof(Evas_Font));
1059 if (fn)
1060 {
1061 char *p;
1062
1063 fn->type = 0;
1064 tmp2 = alloca(strlen(fdir->data) + 1);
1065 strcpy(tmp2, fdir->data);
1066 p = strrchr(tmp2, '.');
1067 if (p) *p = 0;
1068 fn->simple.name = eina_stringshare_add(tmp2);
1069 tmp2 = evas_file_path_join(dir, fdir->data);
1070 if (tmp2)
1071 {
1072 fn->path = eina_stringshare_add(tmp2);
1073 free(tmp2);
1074 }
1075 fd->fonts = eina_list_append(fd->fonts, fn);
1076 }
1077 free(tmp);
1078 }
1079 free(fdir->data);
1080 fdir = eina_list_remove(fdir, fdir->data);
1081 }
1082
1083 /* fonts.alias */
1084 tmp = evas_file_path_join(dir, "fonts.alias");
1085 if (tmp)
1086 {
1087 FILE *f;
1088
1089 f = fopen(tmp, "rb");
1090 if (f)
1091 {
1092 char fname[4096], fdef[4096];
1093
1094 /* read font alias lines */
1095 while (fscanf(f, "%4090s %[^\n]\n", fname, fdef) == 2)
1096 {
1097 Evas_Font_Alias *fa;
1098
1099 /* skip comments */
1100 if ((fname[0] == '!') || (fname[0] == '#')) continue;
1101 fa = calloc(1, sizeof(Evas_Font_Alias));
1102 if (fa)
1103 {
1104 fa->alias = eina_stringshare_add(fname);
1105 fa->fn = object_text_font_cache_font_find_x(fd, fdef);
1106 if ((!fa->alias) || (!fa->fn))
1107 {
1108 if (fa->alias) eina_stringshare_del(fa->alias);
1109 free(fa);
1110 }
1111 else
1112 fd->aliases = eina_list_append(fd->aliases, fa);
1113 }
1114 }
1115 fclose(f);
1116 }
1117 free(tmp);
1118 }
1119
1120 fd->dir_mod_time = evas_file_modified_time(dir);
1121 tmp = evas_file_path_join(dir, "fonts.dir");
1122 if (tmp)
1123 {
1124 fd->fonts_dir_mod_time = evas_file_modified_time(tmp);
1125 free(tmp);
1126 }
1127 tmp = evas_file_path_join(dir, "fonts.alias");
1128 if (tmp)
1129 {
1130 fd->fonts_alias_mod_time = evas_file_modified_time(tmp);
1131 free(tmp);
1132 }
1133
1134 return fd;
1135}
1136
1137static void
1138object_text_font_cache_dir_del(char *dir __UNUSED__, Evas_Font_Dir *fd)
1139{
1140 if (fd->lookup) eina_hash_free(fd->lookup);
1141 while (fd->fonts)
1142 {
1143 Evas_Font *fn;
1144 int i;
1145
1146 fn = fd->fonts->data;
1147 fd->fonts = eina_list_remove(fd->fonts, fn);
1148 for (i = 0; i < 14; i++)
1149 {
1150 if (fn->x.prop[i]) eina_stringshare_del(fn->x.prop[i]);
1151 }
1152 if (fn->simple.name) eina_stringshare_del(fn->simple.name);
1153 if (fn->path) eina_stringshare_del(fn->path);
1154 free(fn);
1155 }
1156 while (fd->aliases)
1157 {
1158 Evas_Font_Alias *fa;
1159
1160 fa = fd->aliases->data;
1161 fd->aliases = eina_list_remove(fd->aliases, fa);
1162 if (fa->alias) eina_stringshare_del(fa->alias);
1163 free(fa);
1164 }
1165 free(fd);
1166}
1167
1168static int
1169evas_object_text_font_string_parse(char *buffer, char dest[14][256])
1170{
1171 char *p;
1172 int n, m, i;
1173
1174 n = 0;
1175 m = 0;
1176 p = buffer;
1177 if (p[0] != '-') return 0;
1178 i = 1;
1179 while (p[i])
1180 {
1181 dest[n][m] = p[i];
1182 if ((p[i] == '-') || (m == 255))
1183 {
1184 dest[n][m] = 0;
1185 n++;
1186 m = -1;
1187 }
1188 i++;
1189 m++;
1190 if (n == 14) return n;
1191 }
1192 dest[n][m] = 0;
1193 n++;
1194 return n;
1195}
1196
1197EAPI void
1198evas_font_path_clear(Evas *e)
1199{
1200 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1201 return;
1202 MAGIC_CHECK_END();
1203 while (e->font_path)
1204 {
1205 eina_stringshare_del(e->font_path->data);
1206 e->font_path = eina_list_remove(e->font_path, e->font_path->data);
1207 }
1208}
1209
1210EAPI void
1211evas_font_path_append(Evas *e, const char *path)
1212{
1213 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1214 return;
1215 MAGIC_CHECK_END();
1216
1217 if (!path) return;
1218 e->font_path = eina_list_append(e->font_path, eina_stringshare_add(path));
1219}
1220
1221EAPI void
1222evas_font_path_prepend(Evas *e, const char *path)
1223{
1224 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1225 return;
1226 MAGIC_CHECK_END();
1227
1228 if (!path) return;
1229 e->font_path = eina_list_prepend(e->font_path, eina_stringshare_add(path));
1230}
1231
1232EAPI const Eina_List *
1233evas_font_path_list(const Evas *e)
1234{
1235 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1236 return NULL;
1237 MAGIC_CHECK_END();
1238 return e->font_path;
1239}
1240
1241static void
1242evas_font_object_rehint(Evas_Object *obj)
1243{
1244 if (obj->smart.smart)
1245 {
1246 EINA_INLIST_FOREACH(evas_object_smart_members_get_direct(obj), obj)
1247 evas_font_object_rehint(obj);
1248 }
1249 else
1250 {
1251 if (!strcmp(obj->type, "text"))
1252 _evas_object_text_rehint(obj);
1253 if (!strcmp(obj->type, "textblock"))
1254 _evas_object_textblock_rehint(obj);
1255 }
1256}
1257
1258EAPI void
1259evas_font_hinting_set(Evas *e, Evas_Font_Hinting_Flags hinting)
1260{
1261 Evas_Layer *lay;
1262
1263 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1264 return;
1265 MAGIC_CHECK_END();
1266 if (e->hinting == hinting) return;
1267 e->hinting = hinting;
1268
1269 EINA_INLIST_FOREACH(e->layers, lay)
1270 {
1271 Evas_Object *obj;
1272
1273 EINA_INLIST_FOREACH(lay->objects, obj)
1274 evas_font_object_rehint(obj);
1275 }
1276}
1277
1278EAPI Evas_Font_Hinting_Flags
1279evas_font_hinting_get(const Evas *e)
1280{
1281 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1282 return EVAS_FONT_HINTING_BYTECODE;
1283 MAGIC_CHECK_END();
1284 return e->hinting;
1285}
1286
1287EAPI Eina_Bool
1288evas_font_hinting_can_hint(const Evas *e, Evas_Font_Hinting_Flags hinting)
1289{
1290 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1291 return 0;
1292 MAGIC_CHECK_END();
1293 if (e->engine.func->font_hinting_can_hint)
1294 return e->engine.func->font_hinting_can_hint(e->engine.data.output,
1295 hinting);
1296 return EINA_FALSE;
1297}
1298
1299EAPI void
1300evas_font_cache_flush(Evas *e)
1301{
1302 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1303 return;
1304 MAGIC_CHECK_END();
1305
1306 e->engine.func->font_cache_flush(e->engine.data.output);
1307}
1308
1309EAPI void
1310evas_font_cache_set(Evas *e, int size)
1311{
1312 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1313 return;
1314 MAGIC_CHECK_END();
1315
1316 if (size < 0) size = 0;
1317 e->engine.func->font_cache_set(e->engine.data.output, size);
1318}
1319
1320EAPI int
1321evas_font_cache_get(const Evas *e)
1322{
1323 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1324 return 0;
1325 MAGIC_CHECK_END();
1326
1327 return e->engine.func->font_cache_get(e->engine.data.output);
1328}
1329
1330EAPI Eina_List *
1331evas_font_available_list(const Evas *e)
1332{
1333 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1334 return NULL;
1335 MAGIC_CHECK_END();
1336
1337 return evas_font_dir_available_list(e);
1338}
1339
1340EAPI void
1341evas_font_available_list_free(Evas *e, Eina_List *available)
1342{
1343 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1344 return;
1345 MAGIC_CHECK_END();
1346
1347 evas_font_dir_available_list_free(available);
1348}
1349
diff --git a/libraries/evas/src/lib/canvas/evas_gl.c b/libraries/evas/src/lib/canvas/evas_gl.c
deleted file mode 100644
index 85ed851..0000000
--- a/libraries/evas/src/lib/canvas/evas_gl.c
+++ /dev/null
@@ -1,272 +0,0 @@
1/* vim:set ts=8 sw=3 sts=3 expandtab cino=>5n-2f0^-2{2(0W1st0 :*/
2#include "evas_common.h"
3#include "evas_private.h"
4#include "Evas_GL.h"
5
6struct _Evas_GL
7{
8 DATA32 magic;
9 Evas *evas;
10
11 Eina_List *contexts;
12 Eina_List *surfaces;
13};
14
15struct _Evas_GL_Context
16{
17 void *data;
18};
19
20struct _Evas_GL_Surface
21{
22 void *data;
23};
24
25EAPI Evas_GL *
26evas_gl_new(Evas *e)
27{
28 Evas_GL *evas_gl;
29
30 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
31 return NULL;
32 MAGIC_CHECK_END();
33
34 evas_gl = calloc(1, sizeof(Evas_GL));
35 if (!evas_gl) return NULL;
36
37 evas_gl->magic = MAGIC_EVAS_GL;
38 evas_gl->evas = e;
39
40 if (!evas_gl->evas->engine.func->gl_context_create)
41 {
42 ERR("GL engine not available\n");
43 free(evas_gl);
44 return NULL;
45 }
46
47 return evas_gl;
48}
49
50EAPI void
51evas_gl_free(Evas_GL *evas_gl)
52{
53 MAGIC_CHECK(evas_gl, Evas_GL, MAGIC_EVAS_GL);
54 return;
55 MAGIC_CHECK_END();
56
57
58 // Delete undeleted surfaces
59 while (evas_gl->surfaces)
60 evas_gl_surface_destroy(evas_gl, evas_gl->surfaces->data);
61
62 // Delete undeleted contexts
63 while (evas_gl->contexts)
64 evas_gl_context_destroy(evas_gl, evas_gl->contexts->data);
65
66 evas_gl->magic = 0;
67 free(evas_gl);
68}
69
70EAPI Evas_GL_Config *
71evas_gl_config_new()
72{
73 Evas_GL_Config *cfg;
74
75 cfg = calloc(1, sizeof(Evas_GL_Config));
76
77 if (!cfg) return NULL;
78
79 return cfg;
80}
81
82EAPI void
83evas_gl_config_free(Evas_GL_Config *cfg)
84{
85 if (cfg) free(cfg);
86}
87
88EAPI Evas_GL_Surface *
89evas_gl_surface_create(Evas_GL *evas_gl, Evas_GL_Config *config, int width, int height)
90{
91 Evas_GL_Surface *surf;
92
93 MAGIC_CHECK(evas_gl, Evas_GL, MAGIC_EVAS_GL);
94 return NULL;
95 MAGIC_CHECK_END();
96
97 if (!config)
98 {
99 ERR("Invalid Config\n");
100 return NULL;
101 }
102
103 surf = calloc(1, sizeof(Evas_GL_Surface));
104
105 if (!surf) return NULL;
106
107 surf->data = evas_gl->evas->engine.func->gl_surface_create(evas_gl->evas->engine.data.output, config, width, height);
108
109 if (!surf->data)
110 {
111 ERR("Failed creating a surface from the engine\n");
112 free(surf);
113 return NULL;
114 }
115
116 // Keep track of the surface creations
117 evas_gl->surfaces = eina_list_prepend(evas_gl->surfaces, surf);
118
119 return surf;
120}
121
122EAPI void
123evas_gl_surface_destroy(Evas_GL *evas_gl, Evas_GL_Surface *surf)
124{
125 // Magic
126 MAGIC_CHECK(evas_gl, Evas_GL, MAGIC_EVAS_GL);
127 return;
128 MAGIC_CHECK_END();
129
130 if (!surf)
131 {
132 ERR("Trying to destroy a NULL surface pointer!\n");
133 return;
134 }
135
136 // Call Engine's Surface Destroy
137 evas_gl->evas->engine.func->gl_surface_destroy(evas_gl->evas->engine.data.output, surf->data);
138
139 // Remove it from the list
140 evas_gl->surfaces = eina_list_remove(evas_gl->surfaces, surf);
141
142 // Delete the object
143 free(surf);
144 surf = NULL;
145}
146
147EAPI Evas_GL_Context *
148evas_gl_context_create(Evas_GL *evas_gl, Evas_GL_Context *share_ctx)
149{
150 Evas_GL_Context *ctx;
151
152 // Magic
153 MAGIC_CHECK(evas_gl, Evas_GL, MAGIC_EVAS_GL);
154 return NULL;
155 MAGIC_CHECK_END();
156
157 // Allocate a context object
158 ctx = calloc(1, sizeof(Evas_GL_Context));
159 if (!ctx)
160 {
161 ERR("Unable to create a Evas_GL_Context object\n");
162 return NULL;
163 }
164
165 // Call engine->gl_create_context
166 if (share_ctx)
167 {
168 ctx->data = evas_gl->evas->engine.func->gl_context_create(evas_gl->evas->engine.data.output, share_ctx->data);
169 }
170 else
171 {
172 ctx->data = evas_gl->evas->engine.func->gl_context_create(evas_gl->evas->engine.data.output, NULL);
173 }
174
175 // Set a few variables
176 if (!ctx->data)
177 {
178 ERR("Failed creating a context from the engine\n");
179 free(ctx);
180 return NULL;
181 }
182
183 // Keep track of the context creations
184 evas_gl->contexts = eina_list_prepend(evas_gl->contexts, ctx);
185
186 return ctx;
187
188}
189
190EAPI void
191evas_gl_context_destroy(Evas_GL *evas_gl, Evas_GL_Context *ctx)
192{
193
194 MAGIC_CHECK(evas_gl, Evas_GL, MAGIC_EVAS_GL);
195 return;
196 MAGIC_CHECK_END();
197
198 if (!ctx)
199 {
200 ERR("Trying to destroy a NULL context pointer!\n");
201 return;
202 }
203
204 // Call Engine's destroy
205 evas_gl->evas->engine.func->gl_context_destroy(evas_gl->evas->engine.data.output, ctx->data);
206
207 // Remove it from the list
208 evas_gl->contexts = eina_list_remove(evas_gl->contexts, ctx);
209
210 // Delete the object
211 free(ctx);
212 ctx = NULL;
213}
214
215EAPI Eina_Bool
216evas_gl_make_current(Evas_GL *evas_gl, Evas_GL_Surface *surf, Evas_GL_Context *ctx)
217{
218 Eina_Bool ret;
219
220 MAGIC_CHECK(evas_gl, Evas_GL, MAGIC_EVAS_GL);
221 return EINA_FALSE;
222 MAGIC_CHECK_END();
223
224 if ((!surf) || (!ctx))
225 ret = (Eina_Bool)evas_gl->evas->engine.func->gl_make_current(evas_gl->evas->engine.data.output, NULL, NULL);
226 else
227 ret = (Eina_Bool)evas_gl->evas->engine.func->gl_make_current(evas_gl->evas->engine.data.output, surf->data, ctx->data);
228
229 return ret;
230}
231
232EAPI const char *
233evas_gl_string_query(Evas_GL *evas_gl, int name)
234{
235 MAGIC_CHECK(evas_gl, Evas_GL, MAGIC_EVAS_GL);
236 return EINA_FALSE;
237 MAGIC_CHECK_END();
238
239 return (const char *)evas_gl->evas->engine.func->gl_string_query(evas_gl->evas->engine.data.output, name);
240}
241
242EAPI Evas_GL_Func
243evas_gl_proc_address_get(Evas_GL *evas_gl, const char *name)
244{
245 MAGIC_CHECK(evas_gl, Evas_GL, MAGIC_EVAS_GL);
246 return EINA_FALSE;
247 MAGIC_CHECK_END();
248
249 return (Evas_GL_Func)evas_gl->evas->engine.func->gl_proc_address_get(evas_gl->evas->engine.data.output, name);
250}
251
252EAPI Eina_Bool
253evas_gl_native_surface_get(Evas_GL *evas_gl, Evas_GL_Surface *surf, Evas_Native_Surface *ns)
254{
255 MAGIC_CHECK(evas_gl, Evas_GL, MAGIC_EVAS_GL);
256 return EINA_FALSE;
257 MAGIC_CHECK_END();
258
259 return (Eina_Bool)evas_gl->evas->engine.func->gl_native_surface_get(evas_gl->evas->engine.data.output, surf->data, ns);
260}
261
262
263EAPI Evas_GL_API *
264evas_gl_api_get(Evas_GL *evas_gl)
265{
266 MAGIC_CHECK(evas_gl, Evas_GL, MAGIC_EVAS_GL);
267 return NULL;
268 MAGIC_CHECK_END();
269
270 return (Evas_GL_API*)evas_gl->evas->engine.func->gl_api_get(evas_gl->evas->engine.data.output);
271
272}
diff --git a/libraries/evas/src/lib/canvas/evas_key.c b/libraries/evas/src/lib/canvas/evas_key.c
deleted file mode 100644
index f74ef34..0000000
--- a/libraries/evas/src/lib/canvas/evas_key.c
+++ /dev/null
@@ -1,245 +0,0 @@
1#include "evas_common.h"
2#include "evas_private.h"
3
4/* private calls */
5
6static int
7evas_key_modifier_number(const Evas_Modifier *m, const char *keyname)
8{
9 int i;
10
11 for (i = 0; i < m->mod.count; i++)
12 {
13 if (!strcmp(m->mod.list[i], keyname)) return i;
14 }
15 return -1;
16}
17
18static int
19evas_key_lock_number(const Evas_Lock *l, const char *keyname)
20{
21 int i;
22
23 for (i = 0; i < l->lock.count; i++)
24 {
25 if (!strcmp(l->lock.list[i], keyname)) return i;
26 }
27 return -1;
28}
29
30/* local calls */
31
32/* public calls */
33
34EAPI const Evas_Modifier *
35evas_key_modifier_get(const Evas *e)
36{
37 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
38 return NULL;
39 MAGIC_CHECK_END();
40 return &(e->modifiers);
41}
42
43EAPI const Evas_Lock *
44evas_key_lock_get(const Evas *e)
45{
46 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
47 return NULL;
48 MAGIC_CHECK_END();
49 return &(e->locks);
50}
51
52EAPI Eina_Bool
53evas_key_modifier_is_set(const Evas_Modifier *m, const char *keyname)
54{
55 Evas_Modifier_Mask num;
56 int n;
57
58 if (!m) return 0;
59 if (!keyname) return 0;
60 n = evas_key_modifier_number(m, keyname);
61 if (n < 0) return 0;
62 num = (Evas_Modifier_Mask)n;
63 num = 1 << num;
64 if (m->mask & num) return 1;
65 return 0;
66}
67
68EAPI Eina_Bool
69evas_key_lock_is_set(const Evas_Lock *l, const char *keyname)
70{
71 Evas_Modifier_Mask num;
72 int n;
73
74 if (!l) return 0;
75 if (!keyname) return 0;
76 n = evas_key_lock_number(l, keyname);
77 if (n < 0) return 0;
78 num = (Evas_Modifier_Mask)n;
79 num = 1 << num;
80 if (l->mask & num) return 1;
81 return 0;
82}
83
84EAPI void
85evas_key_modifier_add(Evas *e, const char *keyname)
86{
87 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
88 return;
89 MAGIC_CHECK_END();
90 if (!keyname) return;
91 if (e->modifiers.mod.count >= 64) return;
92 evas_key_modifier_del(e, keyname);
93 e->modifiers.mod.count++;
94 e->modifiers.mod.list = realloc(e->modifiers.mod.list, e->modifiers.mod.count * sizeof(char *));
95 e->modifiers.mod.list[e->modifiers.mod.count - 1] = strdup(keyname);
96 e->modifiers.mask = 0;
97}
98
99EAPI void
100evas_key_modifier_del(Evas *e, const char *keyname)
101{
102 int i;
103
104 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
105 return;
106 MAGIC_CHECK_END();
107 if (!keyname) return;
108 for (i = 0; i < e->modifiers.mod.count; i++)
109 {
110 if (!strcmp(e->modifiers.mod.list[i], keyname))
111 {
112 int j;
113
114 free(e->modifiers.mod.list[i]);
115 e->modifiers.mod.count--;
116 for (j = i; j < e->modifiers.mod.count; j++)
117 e->modifiers.mod.list[j] = e->modifiers.mod.list[j + 1];
118 e->modifiers.mask = 0;
119 return;
120 }
121 }
122}
123
124EAPI void
125evas_key_lock_add(Evas *e, const char *keyname)
126{
127 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
128 return;
129 MAGIC_CHECK_END();
130 if (!keyname) return;
131 if (e->locks.lock.count >= 64) return;
132 evas_key_lock_del(e, keyname);
133 e->locks.lock.count++;
134 e->locks.lock.list = realloc(e->locks.lock.list, e->locks.lock.count * sizeof(char *));
135 e->locks.lock.list[e->locks.lock.count - 1] = strdup(keyname);
136 e->locks.mask = 0;
137}
138
139EAPI void
140evas_key_lock_del(Evas *e, const char *keyname)
141{
142 int i;
143
144 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
145 return;
146 MAGIC_CHECK_END();
147 if (!keyname) return;
148 e->locks.mask = 0;
149 for (i = 0; i < e->locks.lock.count; i++)
150 {
151 if (!strcmp(e->locks.lock.list[i], keyname))
152 {
153 int j;
154
155 free(e->locks.lock.list[i]);
156 e->locks.lock.count--;
157 for (j = i; j < e->locks.lock.count; j++)
158 e->locks.lock.list[j] = e->locks.lock.list[j + 1];
159 e->locks.mask = 0;
160 return;
161 }
162 }
163}
164
165EAPI void
166evas_key_modifier_on(Evas *e, const char *keyname)
167{
168 Evas_Modifier_Mask num;
169 int n;
170
171 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
172 return;
173 MAGIC_CHECK_END();
174 n = (Evas_Modifier_Mask)evas_key_modifier_number(&(e->modifiers), keyname);
175 if (n < 0) return;
176 num = (Evas_Modifier_Mask)n;
177 num = 1 << num;
178 e->modifiers.mask |= num;
179}
180
181EAPI void
182evas_key_modifier_off(Evas *e, const char *keyname)
183{
184 Evas_Modifier_Mask num;
185 int n;
186
187 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
188 return;
189 MAGIC_CHECK_END();
190 n = evas_key_modifier_number(&(e->modifiers), keyname);
191 if (n < 0) return;
192 num = (Evas_Modifier_Mask)n;
193 num = 1 << num;
194 e->modifiers.mask &= ~num;
195}
196
197EAPI void
198evas_key_lock_on(Evas *e, const char *keyname)
199{
200 Evas_Modifier_Mask num;
201 int n;
202
203 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
204 return;
205 MAGIC_CHECK_END();
206 n = evas_key_lock_number(&(e->locks), keyname);
207 if (n < 0) return;
208 num = (Evas_Modifier_Mask)n;
209 num = 1 << num;
210 e->locks.mask |= num;
211}
212
213EAPI void
214evas_key_lock_off(Evas *e, const char *keyname)
215{
216 Evas_Modifier_Mask num;
217 int n;
218
219 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
220 return;
221 MAGIC_CHECK_END();
222 n = evas_key_lock_number(&(e->locks), keyname);
223 if (n < 0) return;
224 num = (Evas_Modifier_Mask)n;
225 num = 1 << num;
226 e->locks.mask &= ~num;
227}
228
229/* errr need to add key grabbing/ungrabbing calls - missing modifier stuff. */
230
231EAPI Evas_Modifier_Mask
232evas_key_modifier_mask_get(const Evas *e, const char *keyname)
233{
234 Evas_Modifier_Mask num;
235 int n;
236
237 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
238 return 0;
239 MAGIC_CHECK_END();
240 if (!keyname) return 0;
241 n = evas_key_modifier_number(&(e->modifiers), keyname);
242 if (n < 0) return 0;
243 num = (Evas_Modifier_Mask)n;
244 return 1 << num;
245}
diff --git a/libraries/evas/src/lib/canvas/evas_key_grab.c b/libraries/evas/src/lib/canvas/evas_key_grab.c
deleted file mode 100644
index 3fc2172..0000000
--- a/libraries/evas/src/lib/canvas/evas_key_grab.c
+++ /dev/null
@@ -1,179 +0,0 @@
1#include "evas_common.h"
2#include "evas_private.h"
3
4/* private calls */
5
6/* FIXME: this is not optimal, but works. i should have a hash of keys per */
7/* Evas and then a linked lists of grabs for that key and what */
8/* modifiers/not_modifers they use */
9
10static Evas_Key_Grab *evas_key_grab_new (Evas_Object *obj, const char *keyname, Evas_Modifier_Mask modifiers, Evas_Modifier_Mask not_modifiers, Eina_Bool exclusive);
11static Evas_Key_Grab *evas_key_grab_find (Evas_Object *obj, const char *keyname, Evas_Modifier_Mask modifiers, Evas_Modifier_Mask not_modifiers, Eina_Bool exclusive);
12
13static Evas_Key_Grab *
14evas_key_grab_new(Evas_Object *obj, const char *keyname, Evas_Modifier_Mask modifiers, Evas_Modifier_Mask not_modifiers, Eina_Bool exclusive)
15{
16 /* MEM OK */
17 Evas_Key_Grab *g;
18
19 g = evas_mem_calloc(sizeof(Evas_Key_Grab));
20 if (!g) return NULL;
21 g->object = obj;
22 g->modifiers = modifiers;
23 g->not_modifiers = not_modifiers;
24 g->exclusive = exclusive;
25 g->keyname = strdup(keyname);
26 if (obj->layer->evas->walking_grabs)
27 g->just_added = EINA_TRUE;
28 if (!g->keyname)
29 {
30 if (!evas_mem_free(strlen(keyname) + 1))
31 {
32 free(g);
33 return NULL;
34 }
35 g->keyname = strdup(keyname);
36 if (!g->keyname)
37 {
38 free(g);
39 return NULL;
40 }
41 }
42 g->object->grabs = eina_list_append(g->object->grabs, g);
43 if (eina_error_get())
44 {
45 MERR_BAD();
46 evas_mem_free(sizeof(Eina_List));
47 g->object->grabs = eina_list_append(g->object->grabs, g);
48 if (eina_error_get())
49 {
50 MERR_FATAL();
51 free(g->keyname);
52 free(g);
53 return NULL;
54 }
55 }
56 obj->layer->evas->grabs = eina_list_append(obj->layer->evas->grabs, g);
57 if (eina_error_get())
58 {
59 MERR_BAD();
60 evas_mem_free(sizeof(Eina_List));
61 obj->layer->evas->grabs = eina_list_append(obj->layer->evas->grabs, g);
62 if (eina_error_get())
63 {
64 MERR_FATAL();
65 g->object->grabs = eina_list_remove(g->object->grabs, g);
66 free(g->keyname);
67 free(g);
68 return NULL;
69 }
70 }
71 return g;
72}
73
74static Evas_Key_Grab *
75evas_key_grab_find(Evas_Object *obj, const char *keyname, Evas_Modifier_Mask modifiers, Evas_Modifier_Mask not_modifiers, Eina_Bool exclusive)
76{
77 /* MEM OK */
78 Eina_List *l;
79 Evas_Key_Grab *g;
80
81 EINA_LIST_FOREACH(obj->layer->evas->grabs, l, g)
82 {
83 if ((g->modifiers == modifiers) &&
84 (g->not_modifiers == not_modifiers) &&
85 (!strcmp(g->keyname, keyname)))
86 {
87 if ((exclusive) || (obj == g->object)) return g;
88 }
89 }
90 return NULL;
91}
92
93/* local calls */
94
95void
96evas_object_grabs_cleanup(Evas_Object *obj)
97{
98 if (obj->layer->evas->walking_grabs)
99 {
100 Eina_List *l;
101 Evas_Key_Grab *g;
102
103 EINA_LIST_FOREACH(obj->grabs, l, g)
104 g->delete_me = EINA_TRUE;
105 }
106 else
107 {
108 while (obj->grabs)
109 {
110 Evas_Key_Grab *g = obj->grabs->data;
111 if (g->keyname) free(g->keyname);
112 free(g);
113 obj->layer->evas->grabs = eina_list_remove(obj->layer->evas->grabs,
114 g);
115 obj->grabs = eina_list_remove(obj->grabs, g);
116 }
117 }
118}
119
120void
121evas_key_grab_free(Evas_Object *obj, const char *keyname, Evas_Modifier_Mask modifiers, Evas_Modifier_Mask not_modifiers)
122{
123 /* MEM OK */
124 Evas_Key_Grab *g;
125
126 g = evas_key_grab_find(obj, keyname, modifiers, not_modifiers, 0);
127 if (!g) return;
128 g->object->grabs = eina_list_remove(g->object->grabs, g);
129 obj->layer->evas->grabs = eina_list_remove(obj->layer->evas->grabs, g);
130 if (g->keyname) free(g->keyname);
131 free(g);
132}
133
134/* public calls */
135
136EAPI Eina_Bool
137evas_object_key_grab(Evas_Object *obj, const char *keyname, Evas_Modifier_Mask modifiers, Evas_Modifier_Mask not_modifiers, Eina_Bool exclusive)
138{
139 /* MEM OK */
140 Evas_Key_Grab *g;
141
142 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
143 return EINA_FALSE;
144 MAGIC_CHECK_END();
145 if (!keyname) return EINA_FALSE;
146 if (exclusive)
147 {
148 g = evas_key_grab_find(obj, keyname, modifiers, not_modifiers,
149 exclusive);
150 if (g) return EINA_FALSE;
151 }
152 g = evas_key_grab_new(obj, keyname, modifiers, not_modifiers, exclusive);
153 if (!g) return EINA_FALSE;
154 return EINA_TRUE;
155}
156
157EAPI void
158evas_object_key_ungrab(Evas_Object *obj, const char *keyname, Evas_Modifier_Mask modifiers, Evas_Modifier_Mask not_modifiers)
159{
160 /* MEM OK */
161 Evas_Key_Grab *g;
162
163 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
164 return;
165 MAGIC_CHECK_END();
166 if (!keyname) return;
167 g = evas_key_grab_find(obj, keyname, modifiers, not_modifiers, 0);
168 if (!g) return;
169 if (g->object->layer->evas->walking_grabs)
170 {
171 if (!g->delete_me)
172 {
173 g->object->layer->evas->delete_grabs++;
174 g->delete_me = EINA_TRUE;
175 }
176 }
177 else
178 evas_key_grab_free(g->object, keyname, modifiers, not_modifiers);
179}
diff --git a/libraries/evas/src/lib/canvas/evas_layer.c b/libraries/evas/src/lib/canvas/evas_layer.c
deleted file mode 100644
index 54e9907..0000000
--- a/libraries/evas/src/lib/canvas/evas_layer.c
+++ /dev/null
@@ -1,193 +0,0 @@
1#include "evas_common.h"
2#include "evas_private.h"
3
4static void _evas_layer_free(Evas_Layer *lay);
5
6void
7evas_object_inject(Evas_Object *obj, Evas *e)
8{
9 Evas_Layer *lay;
10
11 if (obj->in_layer) return;
12 lay = evas_layer_find(e, obj->cur.layer);
13 if (!lay)
14 {
15 lay = evas_layer_new(e);
16 lay->layer = obj->cur.layer;
17 evas_layer_add(lay);
18 }
19 lay->objects = (Evas_Object *)eina_inlist_append(EINA_INLIST_GET(lay->objects), EINA_INLIST_GET(obj));
20 lay->usage++;
21 obj->layer = lay;
22 obj->in_layer = 1;
23}
24
25void
26evas_object_release(Evas_Object *obj, int clean_layer)
27{
28 if (!obj->in_layer) return;
29 obj->layer->objects = (Evas_Object *)eina_inlist_remove(EINA_INLIST_GET(obj->layer->objects), EINA_INLIST_GET(obj));
30 obj->layer->usage--;
31 if (clean_layer)
32 {
33 if (obj->layer->usage <= 0)
34 {
35 evas_layer_del(obj->layer);
36 _evas_layer_free(obj->layer);
37 }
38 }
39 obj->layer = NULL;
40 obj->in_layer = 0;
41}
42
43Evas_Layer *
44evas_layer_new(Evas *e)
45{
46 Evas_Layer *lay;
47
48 lay = calloc(1, sizeof(Evas_Layer));
49 if (!lay) return NULL;
50 lay->evas = e;
51 return lay;
52}
53
54static void
55_evas_layer_free(Evas_Layer *lay)
56{
57 free(lay);
58}
59
60void
61evas_layer_pre_free(Evas_Layer *lay)
62{
63 Evas_Object *obj;
64
65 EINA_INLIST_FOREACH(lay->objects, obj)
66 {
67 if ((!obj->smart.parent) && (!obj->delete_me))
68 evas_object_del(obj);
69 }
70}
71
72void
73evas_layer_free_objects(Evas_Layer *lay)
74{
75 while (lay->objects)
76 {
77 Evas_Object *obj;
78
79 obj = (Evas_Object *)lay->objects;
80 evas_object_free(obj, 0);
81 }
82}
83
84void
85evas_layer_clean(Evas *e)
86{
87 Evas_Layer *tmp;
88
89 while (e->layers)
90 {
91 tmp = e->layers;
92 evas_layer_del(tmp);
93 _evas_layer_free(tmp);
94 }
95}
96
97Evas_Layer *
98evas_layer_find(Evas *e, short layer_num)
99{
100 Evas_Layer *layer;
101
102 EINA_INLIST_FOREACH(e->layers, layer)
103 {
104 if (layer->layer == layer_num) return layer;
105 }
106 return NULL;
107}
108
109void
110evas_layer_add(Evas_Layer *lay)
111{
112 Evas_Layer *layer;
113
114 EINA_INLIST_FOREACH(lay->evas->layers, layer)
115 {
116 if (layer->layer > lay->layer)
117 {
118 lay->evas->layers = (Evas_Layer *)eina_inlist_prepend_relative(EINA_INLIST_GET(lay->evas->layers),
119 EINA_INLIST_GET(lay),
120 EINA_INLIST_GET(layer));
121 return;
122 }
123 }
124 lay->evas->layers = (Evas_Layer *)eina_inlist_append(EINA_INLIST_GET(lay->evas->layers), EINA_INLIST_GET(lay));
125}
126
127void
128evas_layer_del(Evas_Layer *lay)
129{
130 Evas *e;
131
132 e = lay->evas;
133 e->layers = (Evas_Layer *)eina_inlist_remove(EINA_INLIST_GET(e->layers), EINA_INLIST_GET(lay));
134}
135
136/* public functions */
137
138EAPI void
139evas_object_layer_set(Evas_Object *obj, short l)
140{
141 Evas *e;
142
143 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
144 return;
145 MAGIC_CHECK_END();
146 if (obj->delete_me) return;
147 if (evas_object_intercept_call_layer_set(obj, l)) return;
148 if (obj->smart.parent) return;
149 if (obj->cur.layer == l)
150 {
151 evas_object_raise(obj);
152 return;
153 }
154 e = obj->layer->evas;
155 evas_object_release(obj, 1);
156 obj->cur.layer = l;
157 evas_object_inject(obj, e);
158 obj->restack = 1;
159 evas_object_change(obj);
160 if (obj->clip.clipees)
161 {
162 evas_object_inform_call_restack(obj);
163 return;
164 }
165 evas_object_change(obj);
166 if (!obj->smart.smart)
167 {
168 if (evas_object_is_in_output_rect(obj,
169 obj->layer->evas->pointer.x,
170 obj->layer->evas->pointer.y, 1, 1) &&
171 obj->cur.visible)
172 if (eina_list_data_find(obj->layer->evas->pointer.object.in, obj))
173 evas_event_feed_mouse_move(obj->layer->evas,
174 obj->layer->evas->pointer.x,
175 obj->layer->evas->pointer.y,
176 obj->layer->evas->last_timestamp,
177 NULL);
178 }
179 evas_object_inform_call_restack(obj);
180}
181
182EAPI short
183evas_object_layer_get(const Evas_Object *obj)
184{
185 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
186 return 0;
187 MAGIC_CHECK_END();
188 if (obj->smart.parent)
189 {
190 return obj->smart.parent->cur.layer;
191 }
192 return obj->cur.layer;
193}
diff --git a/libraries/evas/src/lib/canvas/evas_main.c b/libraries/evas/src/lib/canvas/evas_main.c
deleted file mode 100644
index 687744f..0000000
--- a/libraries/evas/src/lib/canvas/evas_main.c
+++ /dev/null
@@ -1,710 +0,0 @@
1#include "evas_common.h"
2#include "evas_private.h"
3#include "evas_cs.h"
4
5#ifdef LKDEBUG
6EAPI Eina_Bool lockdebug = EINA_FALSE;
7EAPI int lockmax = 0;
8#endif
9
10static int _evas_init_count = 0;
11int _evas_log_dom_global = -1;
12EAPI int
13evas_init(void)
14{
15 if (++_evas_init_count != 1)
16 return _evas_init_count;
17
18#ifdef LKDEBUG
19 if (getenv("EVAS_LOCK_DEBUG"))
20 {
21 lockdebug = EINA_TRUE;
22 lockmax = atoi(getenv("EVAS_LOCK_DEBUG"));
23 }
24#endif
25
26#ifdef HAVE_EVIL
27 if (!evil_init())
28 return --_evas_init_count;
29#endif
30
31 if (!eina_init())
32 goto shutdown_evil;
33
34 _evas_log_dom_global = eina_log_domain_register
35 ("evas_main", EVAS_DEFAULT_LOG_COLOR);
36 if (_evas_log_dom_global < 0)
37 {
38 EINA_LOG_ERR("Can not create a module log domain.");
39 goto shutdown_eina;
40 }
41
42 evas_module_init();
43#ifdef BUILD_ASYNC_EVENTS
44 if (!evas_async_events_init())
45 goto shutdown_module;
46#endif
47#ifdef EVAS_CSERVE
48 if (getenv("EVAS_CSERVE")) evas_cserve_init();
49#endif
50#ifdef BUILD_ASYNC_PRELOAD
51 _evas_preload_thread_init();
52#endif
53#ifdef EVAS_FRAME_QUEUING
54 evas_common_frameq_init();
55#endif
56
57 return _evas_init_count;
58
59#ifdef BUILD_ASYNC_EVENTS
60 shutdown_module:
61 evas_module_shutdown();
62 eina_log_domain_unregister(_evas_log_dom_global);
63#endif
64 shutdown_eina:
65 eina_shutdown();
66 shutdown_evil:
67#ifdef HAVE_EVIL
68 evil_shutdown();
69#endif
70
71 return --_evas_init_count;
72}
73
74EAPI int
75evas_shutdown(void)
76{
77 if (--_evas_init_count != 0)
78 return _evas_init_count;
79
80#ifdef EVAS_FRAME_QUEUING
81 if (evas_common_frameq_enabled())
82 {
83 evas_common_frameq_finish();
84 evas_common_frameq_destroy();
85 }
86#endif
87#ifdef BUILD_ASYNC_EVENTS
88 _evas_preload_thread_shutdown();
89#endif
90#ifdef EVAS_CSERVE
91 if (getenv("EVAS_CSERVE")) evas_cserve_shutdown();
92#endif
93#ifdef BUILD_ASYNC_EVENTS
94 evas_async_events_shutdown();
95#endif
96 evas_font_dir_cache_free();
97 evas_common_shutdown();
98 evas_module_shutdown();
99 eina_log_domain_unregister(_evas_log_dom_global);
100 eina_shutdown();
101#ifdef HAVE_EVIL
102 evil_shutdown();
103#endif
104
105 return _evas_init_count;
106}
107
108
109EAPI Evas *
110evas_new(void)
111{
112 Evas *e;
113
114 e = calloc(1, sizeof(Evas));
115 if (!e) return NULL;
116
117 e->magic = MAGIC_EVAS;
118 e->output.render_method = RENDER_METHOD_INVALID;
119 e->viewport.w = 1;
120 e->viewport.h = 1;
121 e->framespace.x = 0;
122 e->framespace.y = 0;
123 e->framespace.w = 0;
124 e->framespace.h = 0;
125 e->hinting = EVAS_FONT_HINTING_BYTECODE;
126 e->name_hash = eina_hash_string_superfast_new(NULL);
127 eina_clist_init(&e->calc_list);
128 eina_clist_init(&e->calc_done);
129
130#define EVAS_ARRAY_SET(E, Array) \
131 eina_array_step_set(&E->Array, sizeof (E->Array), 4096);
132
133 EVAS_ARRAY_SET(e, delete_objects);
134 EVAS_ARRAY_SET(e, active_objects);
135 EVAS_ARRAY_SET(e, restack_objects);
136 EVAS_ARRAY_SET(e, render_objects);
137 EVAS_ARRAY_SET(e, pending_objects);
138 EVAS_ARRAY_SET(e, obscuring_objects);
139 EVAS_ARRAY_SET(e, temporary_objects);
140 EVAS_ARRAY_SET(e, calculate_objects);
141 EVAS_ARRAY_SET(e, clip_changes);
142
143#undef EVAS_ARRAY_SET
144
145 return e;
146}
147
148EAPI void
149evas_free(Evas *e)
150{
151 Eina_Rectangle *r;
152 Evas_Coord_Touch_Point *touch_point;
153 Evas_Layer *lay;
154 int i;
155 int del;
156
157 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
158 return;
159 MAGIC_CHECK_END();
160
161#ifdef EVAS_FRAME_QUEUING
162 evas_common_frameq_flush();
163#endif
164
165 if (e->walking_list == 0) evas_render_idle_flush(e);
166
167 if (e->walking_list > 0) return;
168
169 if (e->callbacks)
170 {
171 if (e->callbacks->deletions_waiting) return;
172
173 e->callbacks->deletions_waiting = 0;
174 evas_event_callback_list_post_free(&e->callbacks->callbacks);
175 if (!e->callbacks->callbacks)
176 {
177 free(e->callbacks);
178 e->callbacks = NULL;
179 }
180
181 _evas_post_event_callback_free(e);
182 }
183
184 del = 1;
185 e->walking_list++;
186 e->cleanup = 1;
187 while (del)
188 {
189 del = 0;
190 EINA_INLIST_FOREACH(e->layers, lay)
191 {
192 Evas_Object *o;
193
194 evas_layer_pre_free(lay);
195
196 EINA_INLIST_FOREACH(lay->objects, o)
197 {
198 if ((o->callbacks) && (o->callbacks->walking_list))
199 {
200 /* Defer free */
201 e->delete_me = 1;
202 e->walking_list--;
203 return;
204 }
205 if (!o->delete_me)
206 del = 1;
207 }
208 }
209 }
210 EINA_INLIST_FOREACH(e->layers, lay)
211 evas_layer_free_objects(lay);
212 evas_layer_clean(e);
213
214 e->walking_list--;
215
216 evas_font_path_clear(e);
217 e->pointer.object.in = eina_list_free(e->pointer.object.in);
218
219 if (e->name_hash) eina_hash_free(e->name_hash);
220 e->name_hash = NULL;
221
222 EINA_LIST_FREE(e->damages, r)
223 eina_rectangle_free(r);
224 EINA_LIST_FREE(e->obscures, r)
225 eina_rectangle_free(r);
226
227 evas_fonts_zero_free(e);
228
229 evas_event_callback_all_del(e);
230 evas_event_callback_cleanup(e);
231
232 if (e->engine.func)
233 {
234 e->engine.func->context_free(e->engine.data.output, e->engine.data.context);
235 e->engine.func->output_free(e->engine.data.output);
236 e->engine.func->info_free(e, e->engine.info);
237 }
238
239 for (i = 0; i < e->modifiers.mod.count; i++)
240 free(e->modifiers.mod.list[i]);
241 if (e->modifiers.mod.list) free(e->modifiers.mod.list);
242
243 for (i = 0; i < e->locks.lock.count; i++)
244 free(e->locks.lock.list[i]);
245 if (e->locks.lock.list) free(e->locks.lock.list);
246
247 if (e->engine.module) evas_module_unref(e->engine.module);
248
249 eina_array_flush(&e->delete_objects);
250 eina_array_flush(&e->active_objects);
251 eina_array_flush(&e->restack_objects);
252 eina_array_flush(&e->render_objects);
253 eina_array_flush(&e->pending_objects);
254 eina_array_flush(&e->obscuring_objects);
255 eina_array_flush(&e->temporary_objects);
256 eina_array_flush(&e->calculate_objects);
257 eina_array_flush(&e->clip_changes);
258
259 EINA_LIST_FREE(e->touch_points, touch_point)
260 free(touch_point);
261
262 e->magic = 0;
263 free(e);
264}
265
266EAPI void
267evas_output_method_set(Evas *e, int render_method)
268{
269 Evas_Module *em;
270
271 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
272 return;
273 MAGIC_CHECK_END();
274
275 /* if our engine to set it to is invalid - abort */
276 if (render_method == RENDER_METHOD_INVALID) return;
277 /* if the engine is already set up - abort */
278 if (e->output.render_method != RENDER_METHOD_INVALID) return;
279 /* Request the right engine. */
280 em = evas_module_engine_get(render_method);
281 if (!em) return ;
282 if (em->id_engine != render_method) return;
283 if (!evas_module_load(em)) return;
284
285 /* set the correct render */
286 e->output.render_method = render_method;
287 e->engine.func = (em->functions);
288 evas_module_use(em);
289 if (e->engine.module) evas_module_unref(e->engine.module);
290 e->engine.module = em;
291 evas_module_ref(em);
292 /* get the engine info struct */
293 if (e->engine.func->info) e->engine.info = e->engine.func->info(e);
294 return;
295}
296
297EAPI int
298evas_output_method_get(const Evas *e)
299{
300 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
301 return RENDER_METHOD_INVALID;
302 MAGIC_CHECK_END();
303
304 return e->output.render_method;
305}
306
307EAPI Evas_Engine_Info *
308evas_engine_info_get(const Evas *e)
309{
310 Evas_Engine_Info *info;
311
312 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
313 return NULL;
314 MAGIC_CHECK_END();
315
316 if (!e->engine.info) return NULL;
317
318 info = e->engine.info;
319 ((Evas *)e)->engine.info_magic = info->magic;
320
321 return info;
322}
323
324EAPI Eina_Bool
325evas_engine_info_set(Evas *e, Evas_Engine_Info *info)
326{
327 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
328 return EINA_FALSE;
329 MAGIC_CHECK_END();
330 if (!info) return EINA_FALSE;
331 if (info != e->engine.info) return EINA_FALSE;
332 if (info->magic != e->engine.info_magic) return EINA_FALSE;
333 return (Eina_Bool)e->engine.func->setup(e, info);
334}
335
336EAPI void
337evas_output_size_set(Evas *e, int w, int h)
338{
339 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
340 return;
341 MAGIC_CHECK_END();
342
343 if ((w == e->output.w) && (h == e->output.h)) return;
344 if (w < 1) w = 1;
345 if (h < 1) h = 1;
346
347#ifdef EVAS_FRAME_QUEUING
348 evas_common_frameq_flush();
349#endif
350
351 e->output.w = w;
352 e->output.h = h;
353 e->output.changed = 1;
354 e->output_validity++;
355 e->changed = 1;
356 evas_render_invalidate(e);
357}
358
359EAPI void
360evas_output_size_get(const Evas *e, int *w, int *h)
361{
362 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
363 if (w) *w = 0;
364 if (h) *h = 0;
365 return;
366 MAGIC_CHECK_END();
367
368 if (w) *w = e->output.w;
369 if (h) *h = e->output.h;
370}
371
372EAPI void
373evas_output_viewport_set(Evas *e, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h)
374{
375 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
376 return;
377 MAGIC_CHECK_END();
378
379 if ((x == e->viewport.x) && (y == e->viewport.y) &&
380 (w == e->viewport.w) && (h == e->viewport.h)) return;
381 if (w <= 0) return;
382 if (h <= 0) return;
383 if ((x != 0) || (y != 0))
384 {
385 ERR("Compat error. viewport x,y != 0,0 not supported");
386 x = 0;
387 y = 0;
388 }
389 e->viewport.x = x;
390 e->viewport.y = y;
391 e->viewport.w = w;
392 e->viewport.h = h;
393 e->viewport.changed = 1;
394 e->output_validity++;
395 e->changed = 1;
396}
397
398EAPI void
399evas_output_viewport_get(const Evas *e, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h)
400{
401 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
402 if (x) *x = 0;
403 if (y) *y = 0;
404 if (w) *w = 0;
405 if (h) *h = 0;
406 return;
407 MAGIC_CHECK_END();
408
409 if (x) *x = e->viewport.x;
410 if (y) *y = e->viewport.y;
411 if (w) *w = e->viewport.w;
412 if (h) *h = e->viewport.h;
413}
414
415EAPI void
416evas_output_framespace_set(Evas *e, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h)
417{
418 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
419 return;
420 MAGIC_CHECK_END();
421
422 if ((x == e->framespace.x) && (y == e->framespace.y) &&
423 (w == e->framespace.w) && (h == e->framespace.h)) return;
424 e->framespace.x = x;
425 e->framespace.y = y;
426 e->framespace.w = w;
427 e->framespace.h = h;
428 e->framespace.changed = 1;
429 e->output_validity++;
430 e->changed = 1;
431}
432
433EAPI void
434evas_output_framespace_get(const Evas *e, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h)
435{
436 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
437 if (x) *x = 0;
438 if (y) *y = 0;
439 if (w) *w = 0;
440 if (h) *h = 0;
441 return;
442 MAGIC_CHECK_END();
443
444 if (x) *x = e->framespace.x;
445 if (y) *y = e->framespace.y;
446 if (w) *w = e->framespace.w;
447 if (h) *h = e->framespace.h;
448}
449
450EAPI Evas_Coord
451evas_coord_screen_x_to_world(const Evas *e, int x)
452{
453 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
454 return 0;
455 MAGIC_CHECK_END();
456 if (e->output.w == e->viewport.w) return e->viewport.x + x;
457 return (long long)e->viewport.x + (((long long)x * (long long)e->viewport.w) / (long long)e->output.w);
458}
459
460EAPI Evas_Coord
461evas_coord_screen_y_to_world(const Evas *e, int y)
462{
463 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
464 return 0;
465 MAGIC_CHECK_END();
466 if (e->output.h == e->viewport.h) return e->viewport.y + y;
467 return (long long)e->viewport.y + (((long long)y * (long long)e->viewport.h) / (long long)e->output.h);
468}
469
470EAPI int
471evas_coord_world_x_to_screen(const Evas *e, Evas_Coord x)
472{
473 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
474 return 0;
475 MAGIC_CHECK_END();
476 if (e->output.w == e->viewport.w) return x - e->viewport.x;
477 return (int)((((long long)x - (long long)e->viewport.x) * (long long)e->output.w) / (long long)e->viewport.w);
478}
479
480EAPI int
481evas_coord_world_y_to_screen(const Evas *e, Evas_Coord y)
482{
483 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
484 return 0;
485 MAGIC_CHECK_END();
486 if (e->output.h == e->viewport.h) return y - e->viewport.y;
487 return (int)((((long long)y - (long long)e->viewport.y) * (long long)e->output.h) / (long long)e->viewport.h);
488}
489
490EAPI int
491evas_render_method_lookup(const char *name)
492{
493 Evas_Module *em;
494
495 if (!name) return RENDER_METHOD_INVALID;
496 /* search on the engines list for the name */
497 em = evas_module_find_type(EVAS_MODULE_TYPE_ENGINE, name);
498 if (!em) return RENDER_METHOD_INVALID;
499
500 return em->id_engine;
501}
502
503EAPI Eina_List *
504evas_render_method_list(void)
505{
506 return evas_module_engine_list();
507}
508
509EAPI void
510evas_render_method_list_free(Eina_List *list)
511{
512 eina_list_free(list);
513}
514
515EAPI Eina_Bool
516evas_object_image_extension_can_load_get(const char *file)
517{
518 const char *tmp;
519 Eina_Bool result;
520
521 tmp = eina_stringshare_add(file);
522 result = evas_common_extension_can_load_get(tmp);
523 eina_stringshare_del(tmp);
524
525 return result;
526}
527
528EAPI Eina_Bool
529evas_object_image_extension_can_load_fast_get(const char *file)
530{
531 return evas_common_extension_can_load_get(file);
532}
533
534EAPI void
535evas_pointer_output_xy_get(const Evas *e, int *x, int *y)
536{
537 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
538 if (x) *x = 0;
539 if (y) *y = 0;
540 return;
541 MAGIC_CHECK_END();
542 if (x) *x = e->pointer.x;
543 if (y) *y = e->pointer.y;
544}
545
546EAPI void
547evas_pointer_canvas_xy_get(const Evas *e, Evas_Coord *x, Evas_Coord *y)
548{
549 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
550 if (x) *x = 0;
551 if (y) *y = 0;
552 return;
553 MAGIC_CHECK_END();
554 if (x) *x = e->pointer.x;
555 if (y) *y = e->pointer.y;
556}
557
558EAPI int
559evas_pointer_button_down_mask_get(const Evas *e)
560{
561 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
562 return 0;
563 MAGIC_CHECK_END();
564 return (int)e->pointer.button;
565}
566
567EAPI Eina_Bool
568evas_pointer_inside_get(const Evas *e)
569{
570 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
571 return 0;
572 MAGIC_CHECK_END();
573 return (int)e->pointer.inside;
574}
575
576EAPI void
577evas_data_attach_set(Evas *e, void *data)
578{
579 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
580 return;
581 MAGIC_CHECK_END();
582 e->attach_data = data;
583}
584
585EAPI void *
586evas_data_attach_get(const Evas *e)
587{
588 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
589 return NULL;
590 MAGIC_CHECK_END();
591 return e->attach_data;
592}
593
594EAPI void
595evas_focus_in(Evas *e)
596{
597 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
598 return;
599 MAGIC_CHECK_END();
600 if (e->focus) return;
601 e->focus = 1;
602 evas_event_callback_call(e, EVAS_CALLBACK_CANVAS_FOCUS_IN, NULL);
603}
604
605EAPI void
606evas_focus_out(Evas *e)
607{
608 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
609 return;
610 MAGIC_CHECK_END();
611 if (!e->focus) return;
612 e->focus = 0;
613 evas_event_callback_call(e, EVAS_CALLBACK_CANVAS_FOCUS_OUT, NULL);
614}
615
616EAPI Eina_Bool
617evas_focus_state_get(const Evas *e)
618{
619 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
620 return 0;
621 MAGIC_CHECK_END();
622 return e->focus;
623}
624
625EAPI void
626evas_nochange_push(Evas *e)
627{
628 e->nochange++;
629}
630
631EAPI void
632evas_nochange_pop(Evas *e)
633{
634 e->nochange--;
635}
636
637void
638_evas_walk(Evas *e)
639{
640 e->walking_list++;
641}
642
643void
644_evas_unwalk(Evas *e)
645{
646 e->walking_list--;
647 if ((e->walking_list == 0) && (e->delete_me)) evas_free(e);
648}
649
650EAPI const char *
651evas_load_error_str(Evas_Load_Error error)
652{
653 switch (error)
654 {
655 case EVAS_LOAD_ERROR_NONE:
656 return "No error on load";
657 case EVAS_LOAD_ERROR_GENERIC:
658 return "A non-specific error occurred";
659 case EVAS_LOAD_ERROR_DOES_NOT_EXIST:
660 return "File (or file path) does not exist";
661 case EVAS_LOAD_ERROR_PERMISSION_DENIED:
662 return "Permission deinied to an existing file (or path)";
663 case EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED:
664 return "Allocation of resources failure prevented load";
665 case EVAS_LOAD_ERROR_CORRUPT_FILE:
666 return "File corrupt (but was detected as a known format)";
667 case EVAS_LOAD_ERROR_UNKNOWN_FORMAT:
668 return "File is not a known format";
669 default:
670 return "Unknown error";
671 }
672}
673
674EAPI void
675evas_color_hsv_to_rgb(float h, float s, float v, int *r, int *g, int *b)
676{
677 evas_common_convert_color_hsv_to_rgb(h, s, v, r, g, b);
678}
679
680EAPI void
681evas_color_rgb_to_hsv(int r, int g, int b, float *h, float *s, float *v)
682{
683 evas_common_convert_color_rgb_to_hsv(r, g, b, h, s, v);
684}
685
686EAPI void
687evas_color_argb_premul(int a, int *r, int *g, int *b)
688{
689 evas_common_convert_color_argb_premul(a, r, g, b);
690}
691
692EAPI void
693evas_color_argb_unpremul(int a, int *r, int *g, int *b)
694{
695 evas_common_convert_color_argb_unpremul(a, r, g, b);
696}
697
698EAPI void
699evas_data_argb_premul(unsigned int *data, unsigned int len)
700{
701 if (!data || (len < 1)) return;
702 evas_common_convert_argb_premul(data, len);
703}
704
705EAPI void
706evas_data_argb_unpremul(unsigned int *data, unsigned int len)
707{
708 if (!data || (len < 1)) return;
709 evas_common_convert_argb_unpremul(data, len);
710}
diff --git a/libraries/evas/src/lib/canvas/evas_map.c b/libraries/evas/src/lib/canvas/evas_map.c
deleted file mode 100644
index 5dcb760..0000000
--- a/libraries/evas/src/lib/canvas/evas_map.c
+++ /dev/null
@@ -1,1037 +0,0 @@
1#include "evas_common.h"
2#include "evas_private.h"
3#include <math.h>
4
5static void
6_evas_map_calc_geom_change(Evas_Object *obj)
7{
8 int is, was = 0, pass = 0;
9
10 evas_object_change(obj);
11 evas_object_clip_dirty(obj);
12 if (obj->layer->evas->events_frozen <= 0)
13 {
14 evas_object_recalc_clippees(obj);
15 if (!pass)
16 {
17 if (!obj->smart.smart)
18 {
19 is = evas_object_is_in_output_rect(obj,
20 obj->layer->evas->pointer.x,
21 obj->layer->evas->pointer.y, 1, 1);
22 if ((is ^ was) && obj->cur.visible)
23 evas_event_feed_mouse_move(obj->layer->evas,
24 obj->layer->evas->pointer.x,
25 obj->layer->evas->pointer.y,
26 obj->layer->evas->last_timestamp,
27 NULL);
28 }
29 }
30 }
31 evas_object_inform_call_move(obj);
32 evas_object_inform_call_resize(obj);
33}
34
35static void
36_evas_map_calc_map_geometry(Evas_Object *obj)
37{
38 Evas_Coord x1, x2, yy1, yy2;
39 const Evas_Map_Point *p, *p_end;
40 Eina_Bool ch = EINA_FALSE;
41
42 if (!obj->cur.map) return;
43
44 // WARN: Do not merge below code to SLP until it is fixed.
45 // It has an infinite loop bug.
46 if (obj->prev.map)
47 {
48 // FIXME: this causes an infinite loop somewhere... hard to debug
49 if (obj->prev.map->count == obj->cur.map->count)
50 {
51 const Evas_Map_Point *p2;
52
53 p = obj->cur.map->points;
54 p_end = p + obj->cur.map->count;
55 p2 = obj->prev.map->points;
56
57 for (; p < p_end; p++, p2++)
58 {
59 if ((p->a != p2->a) ||
60 (p->r != p2->r) ||
61 (p->g != p2->g) ||
62 (p->b != p2->b))
63 {
64 ch = 1;
65 break;
66 }
67 if ((p->x != p2->x) ||
68 (p->y != p2->y) ||
69 (p->z != p2->z))
70 {
71 ch = 1;
72 break;
73 }
74 }
75 }
76 else
77 ch = 1;
78 }
79 else
80 ch = 1;
81
82 p = obj->cur.map->points;
83 p_end = p + obj->cur.map->count;
84 x1 = x2 = lround(p->x);
85 yy1 = yy2 = lround(p->y);
86 p++;
87 for (; p < p_end; p++)
88 {
89 Evas_Coord x, y;
90
91 x = lround(p->x);
92 y = lround(p->y);
93 if (x < x1) x1 = x;
94 if (x > x2) x2 = x;
95 if (y < yy1) yy1 = y;
96 if (y > yy2) yy2 = y;
97 }
98// this causes clip-out bugs now mapped objs canbe opaque!!!
99// // add 1 pixel of fuzz around the map region to ensure updates are correct
100// x1 -= 1; yy1 -= 1;
101// x2 += 1; yy2 += 1;
102 if (obj->cur.map->normal_geometry.x != x1) ch = 1;
103 if (obj->cur.map->normal_geometry.y != yy1) ch = 1;
104 if (obj->cur.map->normal_geometry.w != (x2 - x1)) ch = 1;
105 if (obj->cur.map->normal_geometry.h != (yy2 - yy1)) ch = 1;
106 obj->cur.map->normal_geometry.x = x1;
107 obj->cur.map->normal_geometry.y = yy1;
108 obj->cur.map->normal_geometry.w = (x2 - x1);
109 obj->cur.map->normal_geometry.h = (yy2 - yy1);
110 if (ch) _evas_map_calc_geom_change(obj);
111}
112
113static inline Evas_Map *
114_evas_map_new(int count)
115{
116 int i;
117 int alloc;
118 Evas_Map *m;
119
120 /* Adjust allocation such that: at least 4 points, and always an even
121 * number: this allows the software engine to work efficiently */
122 alloc = (count < 4) ? 4 : count;
123 if (alloc & 0x1) alloc ++;
124
125 m = calloc(1, sizeof(Evas_Map) + (alloc * sizeof(Evas_Map_Point)));
126 if (!m) return NULL;
127 m->count = count;
128 m->persp.foc = 0;
129 m->alpha = 1;
130 m->smooth = 1;
131 m->magic = MAGIC_MAP;
132 for (i = 0; i < count; i++)
133 {
134 m->points[i].r = 255;
135 m->points[i].g = 255;
136 m->points[i].b = 255;
137 m->points[i].a = 255;
138 }
139 return m;
140}
141
142static inline Eina_Bool
143_evas_map_copy(Evas_Map *dst, const Evas_Map *src)
144{
145 if (dst->count != src->count)
146 {
147 ERR("cannot copy map of different sizes: dst=%i, src=%i", dst->count, src->count);
148 return EINA_FALSE;
149 }
150 memcpy(dst->points, src->points, src->count * sizeof(Evas_Map_Point));
151 dst->smooth = src->smooth;
152 dst->alpha = src->alpha;
153 dst->persp = src->persp;
154 return EINA_TRUE;
155}
156
157static inline Evas_Map *
158_evas_map_dup(const Evas_Map *orig)
159{
160 Evas_Map *copy = _evas_map_new(orig->count);
161 if (!copy) return NULL;
162 memcpy(copy->points, orig->points, orig->count * sizeof(Evas_Map_Point));
163 copy->smooth = orig->smooth;
164 copy->alpha = orig->alpha;
165 copy->persp = orig->persp;
166 return copy;
167}
168
169static inline void
170_evas_map_free(Evas_Object *obj, Evas_Map *m)
171{
172 if (obj)
173 {
174 if (m->surface)
175 obj->layer->evas->engine.func->image_map_surface_free
176 (obj->layer->evas->engine.data.output, m->surface);
177 }
178 m->magic = 0;
179 free(m);
180}
181
182/****************************************************************************/
183/* util functions for manipulating maps, so you don't need to know the math */
184/****************************************************************************/
185static inline void
186_evas_map_util_points_populate(Evas_Map *m, const Evas_Coord x, const Evas_Coord y, const Evas_Coord w, const Evas_Coord h, const Evas_Coord z)
187{
188 Evas_Map_Point *p = m->points;
189 int i;
190
191 p[0].x = x;
192 p[0].y = y;
193 p[0].z = z;
194 p[0].u = 0.0;
195 p[0].v = 0.0;
196
197 p[1].x = x + w;
198 p[1].y = y;
199 p[1].z = z;
200 p[1].u = w;
201 p[1].v = 0.0;
202
203 p[2].x = x + w;
204 p[2].y = y + h;
205 p[2].z = z;
206 p[2].u = w;
207 p[2].v = h;
208
209 p[3].x = x;
210 p[3].y = y + h;
211 p[3].z = z;
212 p[3].u = 0.0;
213 p[3].v = h;
214
215 for (i = 0; i < 4; i++)
216 {
217 p[i].px = p[i].x;
218 p[i].py = p[i].y;
219 }
220}
221
222Eina_Bool
223evas_map_coords_get(const Evas_Map *m, Evas_Coord x, Evas_Coord y,
224 Evas_Coord *mx, Evas_Coord *my, int grab)
225{
226 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
227 return EINA_FALSE;
228 MAGIC_CHECK_END();
229
230 int i, j, edges, edge[m->count][2], douv;
231 Evas_Coord xe[2];
232 double u[2] = { 0.0, 0.0 };
233 double v[2] = { 0.0, 0.0 };
234
235 if (m->count < 4) return 0;
236 // FIXME need to handle grab mode and extrapolte coords outside
237 // map
238 if (grab)
239 {
240 Evas_Coord ymin, ymax;
241
242 ymin = m->points[0].y;
243 ymax = m->points[0].y;
244 for (i = 1; i < m->count; i++)
245 {
246 if (m->points[i].y < ymin) ymin = m->points[i].y;
247 else if (m->points[i].y > ymax) ymax = m->points[i].y;
248 }
249 if (y <= ymin) y = ymin + 1;
250 if (y >= ymax) y = ymax - 1;
251 }
252 edges = 0;
253 for (i = 0; i < m->count; i++)
254 {
255 j = (i + 1) % m->count;
256 if ((m->points[i].y <= y) && (m->points[j].y > y))
257 {
258 edge[edges][0] = i;
259 edge[edges][1] = j;
260 edges++;
261 }
262 else if ((m->points[j].y <= y) && (m->points[i].y > y))
263 {
264 edge[edges][0] = j;
265 edge[edges][1] = i;
266 edges++;
267 }
268 }
269 douv = 0;
270 if ((mx) || (my)) douv = 1;
271 for (i = 0; i < (edges - 1); i+= 2)
272 {
273 Evas_Coord yp, yd;
274
275 j = i + 1;
276 yd = m->points[edge[i][1]].y - m->points[edge[i][0]].y;
277 if (yd > 0)
278 {
279 yp = y - m->points[edge[i][0]].y;
280 xe[0] = m->points[edge[i][1]].x - m->points[edge[i][0]].x;
281 xe[0] = m->points[edge[i][0]].x + ((xe[0] * yp) / yd);
282 if (douv)
283 {
284 u[0] = m->points[edge[i][1]].u - m->points[edge[i][0]].u;
285 u[0] = m->points[edge[i][0]].u + ((u[0] * yp) / yd);
286 v[0] = m->points[edge[i][1]].v - m->points[edge[i][0]].v;
287 v[0] = m->points[edge[i][0]].v + ((v[0] * yp) / yd);
288 }
289 }
290 else
291 {
292 xe[0] = m->points[edge[i][0]].x;
293 if (douv)
294 {
295 u[0] = m->points[edge[i][0]].u;
296 v[0] = m->points[edge[i][0]].v;
297 }
298 }
299 yd = m->points[edge[j][1]].y - m->points[edge[j][0]].y;
300 if (yd > 0)
301 {
302 yp = y - m->points[edge[j][0]].y;
303 xe[1] = m->points[edge[j][1]].x - m->points[edge[j][0]].x;
304 xe[1] = m->points[edge[j][0]].x + ((xe[1] * yp) / yd);
305 if (douv)
306 {
307 u[1] = m->points[edge[j][1]].u - m->points[edge[j][0]].u;
308 u[1] = m->points[edge[j][0]].u + ((u[1] * yp) / yd);
309 v[1] = m->points[edge[j][1]].v - m->points[edge[j][0]].v;
310 v[1] = m->points[edge[j][0]].v + ((v[1] * yp) / yd);
311 }
312 }
313 else
314 {
315 xe[1] = m->points[edge[j][0]].x;
316 if (douv)
317 {
318 u[1] = m->points[edge[j][0]].u;
319 v[1] = m->points[edge[j][0]].v;
320 }
321 }
322 if (xe[0] > xe[1])
323 {
324 int ti;
325
326 ti = xe[0]; xe[0] = xe[1]; xe[1] = ti;
327 if (douv)
328 {
329 double td;
330
331 td = u[0]; u[0] = u[1]; u[1] = td;
332 td = v[0]; v[0] = v[1]; v[1] = td;
333 }
334 }
335 if ((x >= xe[0]) && (x < xe[1]))
336 {
337 if (douv)
338 {
339 if (mx)
340 *mx = u[0] + (((x - xe[0]) * (u[1] - u[0])) /
341 (xe[1] - xe[0]));
342 if (my)
343 *my = v[0] + (((x - xe[0]) * (v[1] - v[0])) /
344 (xe[1] - xe[0]));
345 }
346 return EINA_TRUE;
347 }
348 if (grab)
349 {
350 if (douv)
351 {
352 if (mx)
353 *mx = u[0] + (((x - xe[0]) * (u[1] - u[0])) /
354 (xe[1] - xe[0]));
355 if (my)
356 *my = v[0] + (((x - xe[0]) * (v[1] - v[0])) /
357 (xe[1] - xe[0]));
358 }
359 return EINA_TRUE;
360 }
361 }
362 return EINA_FALSE;
363}
364
365Eina_Bool
366evas_map_inside_get(const Evas_Map *m, Evas_Coord x, Evas_Coord y)
367{
368 return evas_map_coords_get(m, x, y, NULL, NULL, 0);
369}
370
371EAPI void
372evas_object_map_enable_set(Evas_Object *obj, Eina_Bool enabled)
373{
374 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
375 return;
376 MAGIC_CHECK_END();
377 Eina_Bool pchange = EINA_FALSE;
378
379 enabled = !!enabled;
380 if (obj->cur.usemap == enabled) return;
381 pchange = obj->changed;
382 obj->cur.usemap = enabled;
383 if (enabled)
384 {
385 if (!obj->cur.map)
386 obj->cur.map = _evas_map_new(4);
387 evas_object_mapped_clip_across_mark(obj);
388// obj->cur.map->normal_geometry = obj->cur.geometry;
389 }
390 else
391 {
392 if (obj->cur.map)
393 {
394 _evas_map_calc_geom_change(obj);
395 evas_object_mapped_clip_across_mark(obj);
396 //FIXME: Since the last frame is not updated when map is
397 //disabled, afterimage problem is happened in s/w rendering.
398 //Need to find out the fundamental reason then fix it.
399 evas_damage_rectangle_add(obj->layer->evas,
400 0,
401 0,
402 obj->layer->evas->output.w,
403 obj->layer->evas->output.h);
404 }
405 }
406 _evas_map_calc_map_geometry(obj);
407 /* This is a bit heavy handed, but it fixes the case of same geometry, but
408 * changed colour or UV settings. */
409 evas_object_change(obj);
410 if (!obj->changed_pchange) obj->changed_pchange = pchange;
411 obj->changed_map = EINA_TRUE;
412}
413
414EAPI Eina_Bool
415evas_object_map_enable_get(const Evas_Object *obj)
416{
417 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
418 return EINA_FALSE;
419 MAGIC_CHECK_END();
420 return obj->cur.usemap;
421}
422
423
424EAPI void
425evas_object_map_source_set(Evas_Object *obj, Evas_Object *src)
426{
427 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
428 return;
429 MAGIC_CHECK_END();
430 (void)src; /* method still needs to be implemented. */
431}
432
433EAPI Evas_Object *
434evas_object_map_source_get(const Evas_Object *obj)
435{
436 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
437 return NULL;
438 MAGIC_CHECK_END();
439 return NULL;
440}
441
442EAPI void
443evas_object_map_set(Evas_Object *obj, const Evas_Map *map)
444{
445 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
446 return;
447 MAGIC_CHECK_END();
448
449 if (!map)
450 {
451 if (obj->cur.map)
452 {
453 if (obj->cur.map->surface)
454 {
455 obj->layer->evas->engine.func->image_map_surface_free
456 (obj->layer->evas->engine.data.output,
457 obj->cur.map->surface);
458 obj->cur.map->surface = NULL;
459 }
460 obj->prev.geometry = obj->cur.map->normal_geometry;
461 if (!obj->prev.map)
462 {
463 _evas_map_free(obj, obj->cur.map);
464 obj->cur.map = NULL;
465 evas_object_mapped_clip_across_mark(obj);
466 return;
467 }
468 _evas_map_free(obj, obj->cur.map);
469 obj->cur.map = NULL;
470 if (!obj->cur.usemap) _evas_map_calc_geom_change(obj);
471 else _evas_map_calc_map_geometry(obj);
472 if (obj->cur.usemap)
473 {
474 evas_object_mapped_clip_across_mark(obj);
475 //FIXME: Since the last frame is not updated when map is
476 //disabled, afterimage problem is happened in s/w
477 //rendering. Need to find out the fundamental reason
478 //then fix it.
479 evas_damage_rectangle_add(obj->layer->evas,
480 0,
481 0,
482 obj->layer->evas->output.w,
483 obj->layer->evas->output.h);
484 }
485 }
486 return;
487 }
488
489 if ((obj->cur.map) && (obj->cur.map->count == map->count))
490 {
491 Evas_Map *omap = obj->cur.map;
492 obj->cur.map = _evas_map_new(map->count);
493 memcpy(obj->cur.map, omap, sizeof(Evas_Map) + (map->count * sizeof(Evas_Map_Point)));
494 _evas_map_copy(obj->cur.map, map);
495 if (obj->prev.map == omap) obj->prev.map = NULL;
496 free(omap);
497 }
498 else
499 {
500 if (obj->cur.map) evas_map_free(obj->cur.map);
501 obj->cur.map = _evas_map_dup(map);
502 if (obj->cur.usemap)
503 evas_object_mapped_clip_across_mark(obj);
504 }
505 _evas_map_calc_map_geometry(obj);
506}
507
508EAPI const Evas_Map *
509evas_object_map_get(const Evas_Object *obj)
510{
511 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
512 return NULL;
513 MAGIC_CHECK_END();
514
515 return obj->cur.map;
516}
517
518EAPI Evas_Map *
519evas_map_new(int count)
520{
521 if (count != 4)
522 {
523 ERR("map point count (%i) != 4 is unsupported!", count);
524 return NULL;
525 }
526
527 return _evas_map_new(count);
528}
529
530EAPI void
531evas_map_smooth_set(Evas_Map *m, Eina_Bool enabled)
532{
533 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
534 return;
535 MAGIC_CHECK_END();
536
537 m->smooth = enabled;
538}
539
540EAPI Eina_Bool
541evas_map_smooth_get(const Evas_Map *m)
542{
543 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
544 return EINA_FALSE;
545 MAGIC_CHECK_END();
546
547 return m->smooth;
548}
549
550EAPI void
551evas_map_alpha_set(Evas_Map *m, Eina_Bool enabled)
552{
553 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
554 return;
555 MAGIC_CHECK_END();
556
557 m->alpha = enabled;
558}
559
560EAPI Eina_Bool
561evas_map_alpha_get(const Evas_Map *m)
562{
563 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
564 return EINA_FALSE;
565 MAGIC_CHECK_END();
566
567 return m->alpha;
568}
569
570EAPI Evas_Map *
571evas_map_dup(const Evas_Map *m)
572{
573 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
574 return NULL;
575 MAGIC_CHECK_END();
576
577 return _evas_map_dup(m);
578}
579
580EAPI void
581evas_map_free(Evas_Map *m)
582{
583 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
584 return;
585 MAGIC_CHECK_END();
586
587 _evas_map_free(NULL, m);
588}
589
590EAPI int
591evas_map_count_get(const Evas_Map *m)
592{
593 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
594 return -1;
595 MAGIC_CHECK_END();
596
597 return m->count;
598}
599
600EAPI void
601evas_map_point_coord_set(Evas_Map *m, int idx, Evas_Coord x, Evas_Coord y, Evas_Coord z)
602{
603 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
604 return;
605 MAGIC_CHECK_END();
606
607 Evas_Map_Point *p;
608
609 if (idx >= m->count) return;
610 p = m->points + idx;
611 p->x = p->px = x;
612 p->y = p->py = y;
613 p->z = z;
614}
615
616EAPI void
617evas_map_point_coord_get(const Evas_Map *m, int idx, Evas_Coord *x, Evas_Coord *y, Evas_Coord *z)
618{
619 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
620 goto error;
621 MAGIC_CHECK_END();
622
623 const Evas_Map_Point *p;
624
625 if (idx >= m->count) goto error;
626 p = m->points + idx;
627 if (x) *x = p->x;
628 if (y) *y = p->y;
629 if (z) *z = p->z;
630 return;
631
632 error:
633 if (x) *x = 0;
634 if (y) *y = 0;
635 if (z) *z = 0;
636}
637
638EAPI void
639evas_map_point_image_uv_set(Evas_Map *m, int idx, double u, double v)
640{
641 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
642 return;
643 MAGIC_CHECK_END();
644
645 Evas_Map_Point *p;
646
647 if (idx >= m->count) return;
648 p = m->points + idx;
649 p->u = u;
650 p->v = v;
651}
652
653EAPI void
654evas_map_point_image_uv_get(const Evas_Map *m, int idx, double *u, double *v)
655{
656 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
657 goto error;
658 MAGIC_CHECK_END();
659
660 const Evas_Map_Point *p;
661
662 if (idx >= m->count) goto error;
663 p = m->points + idx;
664 if (u) *u = p->u;
665 if (v) *v = p->v;
666 return;
667
668 error:
669 if (u) *u = 0.0;
670 if (v) *v = 0.0;
671}
672
673EAPI void
674evas_map_point_color_set(Evas_Map *m, int idx, int r, int g, int b, int a)
675{
676 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
677 return;
678 MAGIC_CHECK_END();
679
680 Evas_Map_Point *p;
681
682 if (idx >= m->count) return;
683 p = m->points + idx;
684 p->r = r;
685 p->g = g;
686 p->b = b;
687 p->a = a;
688}
689
690EAPI void
691evas_map_point_color_get(const Evas_Map *m, int idx, int *r, int *g, int *b, int *a)
692{
693 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
694 return;
695 MAGIC_CHECK_END();
696
697 const Evas_Map_Point *p;
698
699 if (idx >= m->count) return;
700 p = m->points + idx;
701 if (r) *r = p->r;
702 if (g) *g = p->g;
703 if (b) *b = p->b;
704 if (a) *a = p->a;
705}
706
707EAPI void
708evas_map_util_points_populate_from_object_full(Evas_Map *m, const Evas_Object *obj, Evas_Coord z)
709{
710 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
711 return;
712 MAGIC_CHECK_END();
713
714 if (m->count != 4)
715 {
716 ERR("map has count=%d where 4 was expected.", m->count);
717 return;
718 }
719 _evas_map_util_points_populate(m, obj->cur.geometry.x, obj->cur.geometry.y,
720 obj->cur.geometry.w, obj->cur.geometry.h, z);
721}
722
723EAPI void
724evas_map_util_points_populate_from_object(Evas_Map *m, const Evas_Object *obj)
725{
726 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
727 return;
728 MAGIC_CHECK_END();
729
730 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
731 return;
732 MAGIC_CHECK_END();
733
734 if (m->count != 4)
735 {
736 ERR("map has count=%d where 4 was expected.", m->count);
737 return;
738 }
739 _evas_map_util_points_populate(m, obj->cur.geometry.x, obj->cur.geometry.y,
740 obj->cur.geometry.w, obj->cur.geometry.h, 0);
741}
742
743EAPI void
744evas_map_util_points_populate_from_geometry(Evas_Map *m, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h, Evas_Coord z)
745{
746 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
747 return;
748 MAGIC_CHECK_END();
749
750 if (m->count != 4)
751 {
752 ERR("map has count=%d where 4 was expected.", m->count);
753 return;
754 }
755 _evas_map_util_points_populate(m, x, y, w, h, z);
756}
757
758EAPI void
759evas_map_util_points_color_set(Evas_Map *m, int r, int g, int b, int a)
760{
761 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
762 return;
763 MAGIC_CHECK_END();
764
765 Evas_Map_Point *p, *p_end;
766
767 p = m->points;
768 p_end = p + m->count;
769 for (; p < p_end; p++)
770 {
771 p->r = r;
772 p->g = g;
773 p->b = b;
774 p->a = a;
775 }
776}
777
778EAPI void
779evas_map_util_rotate(Evas_Map *m, double degrees, Evas_Coord cx, Evas_Coord cy)
780{
781 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
782 return;
783 MAGIC_CHECK_END();
784
785 double r = (degrees * M_PI) / 180.0;
786 Evas_Map_Point *p, *p_end;
787
788 p = m->points;
789 p_end = p + m->count;
790
791 for (; p < p_end; p++)
792 {
793 double x, y, xx, yy;
794
795 x = p->x - cx;
796 y = p->y - cy;
797
798 xx = x * cos(r);
799 yy = x * sin(r);
800 x = xx - (y * sin(r));
801 y = yy + (y * cos(r));
802
803 p->px = p->x = x + cx;
804 p->py = p->y = y + cy;
805 }
806}
807
808EAPI void
809evas_map_util_zoom(Evas_Map *m, double zoomx, double zoomy, Evas_Coord cx, Evas_Coord cy)
810{
811 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
812 return;
813 MAGIC_CHECK_END();
814
815 Evas_Map_Point *p, *p_end;
816
817 p = m->points;
818 p_end = p + m->count;
819
820 for (; p < p_end; p++)
821 {
822 double x, y;
823
824 x = p->x - cx;
825 y = p->y - cy;
826
827 x = (((double)x) * zoomx);
828 y = (((double)y) * zoomy);
829
830 p->px = p->x = x + cx;
831 p->py = p->y = y + cy;
832 }
833}
834
835EAPI void
836evas_map_util_3d_rotate(Evas_Map *m, double dx, double dy, double dz,
837 Evas_Coord cx, Evas_Coord cy, Evas_Coord cz)
838{
839 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
840 return;
841 MAGIC_CHECK_END();
842
843 double rz = (dz * M_PI) / 180.0;
844 double rx = (dx * M_PI) / 180.0;
845 double ry = (dy * M_PI) / 180.0;
846 Evas_Map_Point *p, *p_end;
847
848 p = m->points;
849 p_end = p + m->count;
850
851 for (; p < p_end; p++)
852 {
853 double x, y, z, xx, yy, zz;
854
855 x = p->x - cx;
856 y = p->y - cy;
857 z = p->z - cz;
858
859 if (rz != 0.0)
860 {
861 xx = x * cos(rz);
862 yy = x * sin(rz);
863 x = xx - (y * sin(rz));
864 y = yy + (y * cos(rz));
865 }
866
867 if (ry != 0.0)
868 {
869 xx = x * cos(ry);
870 zz = x * sin(ry);
871 x = xx - (z * sin(ry));
872 z = zz + (z * cos(ry));
873 }
874
875 if (rx != 0.0)
876 {
877 zz = z * cos(rx);
878 yy = z * sin(rx);
879 z = zz - (y * sin(rx));
880 y = yy + (y * cos(rx));
881 }
882
883 p->px = p->x = x + cx;
884 p->py = p->y = y + cy;
885 p->z = z + cz;
886 }
887}
888
889EAPI void
890evas_map_util_3d_lighting(Evas_Map *m,
891 Evas_Coord lx, Evas_Coord ly, Evas_Coord lz,
892 int lr, int lg, int lb, int ar, int ag, int ab)
893{
894 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
895 return;
896 MAGIC_CHECK_END();
897
898 int i;
899
900 for (i = 0; i < m->count; i++)
901 {
902 double x, y, z;
903 double nx, ny, nz, x1, yy1, z1, x2, yy2, z2, ln, br;
904 int h, j, mr, mg, mb;
905
906 x = m->points[i].x;
907 y = m->points[i].y;
908 z = m->points[i].z;
909 // calc normal
910 h = (i - 1 + 4) % 4 + (i & ~0x3); // prev point
911 j = (i + 1) % 4 + (i & ~0x3); // next point
912
913 x1 = m->points[h].x - x;
914 yy1 = m->points[h].y - y;
915 z1 = m->points[h].z - z;
916
917 x2 = m->points[j].x - x;
918 yy2 = m->points[j].y - y;
919 z2 = m->points[j].z - z;
920 nx = (yy1 * z2) - (z1 * yy2);
921 ny = (z1 * x2) - (x1 * z2);
922 nz = (x1 * yy2) - (yy1 * x2);
923
924 ln = (nx * nx) + (ny * ny) + (nz * nz);
925 ln = sqrt(ln);
926
927 if (ln != 0.0)
928 {
929 nx /= ln;
930 ny /= ln;
931 nz /= ln;
932 }
933
934 // calc point -> light vector
935 x = lx - x;
936 y = ly - y;
937 z = lz - z;
938
939 ln = (x * x) + (y * y) + (z * z);
940 ln = sqrt(ln);
941
942 if (ln != 0.0)
943 {
944 x /= ln;
945 y /= ln;
946 z /= ln;
947 }
948
949 // brightness - tan (0.0 -> 1.0 brightness really)
950 br = (nx * x) + (ny * y) + (nz * z);
951 if (br < 0.0) br = 0.0;
952
953 mr = ar + ((lr - ar) * br);
954 mg = ag + ((lg - ag) * br);
955 mb = ab + ((lb - ab) * br);
956 if (m->points[i].a != 255)
957 {
958 mr = (mr * m->points[i].a) / 255;
959 mg = (mg * m->points[i].a) / 255;
960 mb = (mb * m->points[i].a) / 255;
961 }
962 m->points[i].r = (m->points[i].r * mr) / 255;
963 m->points[i].g = (m->points[i].g * mg) / 255;
964 m->points[i].b = (m->points[i].b * mb) / 255;
965 }
966}
967
968EAPI void
969evas_map_util_3d_perspective(Evas_Map *m,
970 Evas_Coord px, Evas_Coord py,
971 Evas_Coord z0, Evas_Coord foc)
972{
973 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
974 return;
975 MAGIC_CHECK_END();
976
977 Evas_Map_Point *p, *p_end;
978
979 p = m->points;
980 p_end = p + m->count;
981
982 m->persp.px = px;
983 m->persp.py = py;
984 m->persp.z0 = z0;
985 m->persp.foc = foc;
986
987 if (foc <= 0) return;
988
989 for (; p < p_end; p++)
990 {
991 double x, y, zz;
992
993 x = p->x - px;
994 y = p->y - py;
995
996 zz = ((p->z - z0) + foc);
997
998 if (zz > 0)
999 {
1000 x = (x * foc) / zz;
1001 y = (y * foc) / zz;
1002 }
1003
1004 p->x = px + x;
1005 p->y = py + y;
1006 }
1007}
1008
1009EAPI Eina_Bool
1010evas_map_util_clockwise_get(Evas_Map *m)
1011{
1012 MAGIC_CHECK(m, Evas_Map, MAGIC_MAP);
1013 return EINA_FALSE;
1014 MAGIC_CHECK_END();
1015
1016 int i, j, k, count;
1017 long long c;
1018
1019 if (m->count < 3) return EINA_FALSE;
1020
1021 count = 0;
1022 for (i = 0; i < m->count; i++)
1023 {
1024 j = (i + 1) % m->count;
1025 k = (i + 2) % m->count;
1026 c =
1027 ((m->points[j].x - m->points[i].x) *
1028 (m->points[k].y - m->points[j].y))
1029 -
1030 ((m->points[j].y - m->points[i].y) *
1031 (m->points[k].x - m->points[j].x));
1032 if (c < 0) count--;
1033 else if (c > 0) count++;
1034 }
1035 if (count > 0) return EINA_TRUE;
1036 return EINA_FALSE;
1037}
diff --git a/libraries/evas/src/lib/canvas/evas_name.c b/libraries/evas/src/lib/canvas/evas_name.c
deleted file mode 100644
index 1a9d20f..0000000
--- a/libraries/evas/src/lib/canvas/evas_name.c
+++ /dev/null
@@ -1,72 +0,0 @@
1#include "evas_common.h"
2#include "evas_private.h"
3
4EAPI void
5evas_object_name_set(Evas_Object *obj, const char *name)
6{
7 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
8 return;
9 MAGIC_CHECK_END();
10 if (obj->name)
11 {
12 eina_hash_del(obj->layer->evas->name_hash, obj->name, obj);
13 free(obj->name);
14 }
15 if (!name) obj->name = NULL;
16 else
17 {
18 obj->name = strdup(name);
19 eina_hash_add(obj->layer->evas->name_hash, obj->name, obj);
20 }
21}
22
23EAPI const char *
24evas_object_name_get(const Evas_Object *obj)
25{
26 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
27 return NULL;
28 MAGIC_CHECK_END();
29 return obj->name;
30}
31
32EAPI Evas_Object *
33evas_object_name_find(const Evas *e, const char *name)
34{
35 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
36 return NULL;
37 MAGIC_CHECK_END();
38 if (!name) return NULL;
39 return (Evas_Object *)eina_hash_find(e->name_hash, name);
40}
41
42static Evas_Object *
43_evas_object_name_child_find(const Evas_Object *obj, const char *name, int recurse)
44{
45 const Eina_Inlist *lst;
46 Evas_Object *child;
47
48 if (!obj->smart.smart) return NULL;
49 lst = evas_object_smart_members_get_direct(obj);
50 EINA_INLIST_FOREACH(lst, child)
51 {
52 if (child->delete_me) continue;
53 if (!child->name) continue;
54 if (!strcmp(name, child->name)) return child;
55 if (recurse != 0)
56 {
57 if ((obj = _evas_object_name_child_find(child, name, recurse - 1)))
58 return (Evas_Object *)obj;
59 }
60 }
61 return NULL;
62}
63
64EAPI Evas_Object *
65evas_object_name_child_find(const Evas_Object *obj, const char *name, int recurse)
66{
67 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
68 return NULL;
69 MAGIC_CHECK_END();
70 if (!name) return NULL;
71 return _evas_object_name_child_find(obj, name, recurse);
72}
diff --git a/libraries/evas/src/lib/canvas/evas_object_box.c b/libraries/evas/src/lib/canvas/evas_object_box.c
deleted file mode 100644
index 228d37c..0000000
--- a/libraries/evas/src/lib/canvas/evas_object_box.c
+++ /dev/null
@@ -1,2127 +0,0 @@
1#include "evas_common.h"
2
3#ifdef _WIN32_WCE
4# undef remove
5#endif
6
7typedef struct _Evas_Object_Box_Iterator Evas_Object_Box_Iterator;
8typedef struct _Evas_Object_Box_Accessor Evas_Object_Box_Accessor;
9
10struct _Evas_Object_Box_Iterator
11{
12 Eina_Iterator iterator;
13
14 Eina_Iterator *real_iterator;
15 const Evas_Object *box;
16};
17
18struct _Evas_Object_Box_Accessor
19{
20 Eina_Accessor accessor;
21
22 Eina_Accessor *real_accessor;
23 const Evas_Object *box;
24};
25
26#define _evas_object_box_type "Evas_Object_Box"
27#define SIG_CHILD_ADDED "child,added"
28#define SIG_CHILD_REMOVED "child,removed"
29
30static const Evas_Smart_Cb_Description _signals[] =
31{
32 {SIG_CHILD_ADDED, ""},
33 {SIG_CHILD_REMOVED, ""},
34 {NULL, NULL}
35};
36
37
38static void _sizing_eval(Evas_Object *obj);
39
40#define EVAS_OBJECT_BOX_DATA_GET(o, ptr) \
41 Evas_Object_Box_Data *ptr = evas_object_smart_data_get(o)
42
43#define EVAS_OBJECT_BOX_DATA_GET_OR_RETURN(o, ptr) \
44 EVAS_OBJECT_BOX_DATA_GET(o, ptr); \
45 if (!ptr) \
46 { \
47 CRIT("no widget data for object %p (%s)", \
48 o, evas_object_type_get(o)); \
49 fflush(stderr); \
50 abort(); \
51 return; \
52}
53
54#define EVAS_OBJECT_BOX_DATA_GET_OR_RETURN_VAL(o, ptr, val) \
55 EVAS_OBJECT_BOX_DATA_GET(o, ptr); \
56 if (!ptr) \
57 { \
58 CRIT("no widget data for object %p (%s)", \
59 o, evas_object_type_get(o)); \
60 fflush(stderr); \
61 abort(); \
62 return val; \
63 }
64
65EVAS_SMART_SUBCLASS_NEW(_evas_object_box_type, _evas_object_box,
66 Evas_Object_Box_Api, Evas_Smart_Class,
67 evas_object_smart_clipped_class_get, NULL)
68
69static Eina_Bool
70_evas_object_box_iterator_next(Evas_Object_Box_Iterator *it, void **data)
71{
72 Evas_Object_Box_Option *opt;
73
74 if (!eina_iterator_next(it->real_iterator, (void **)&opt))
75 return EINA_FALSE;
76 if (data) *data = opt->obj;
77 return EINA_TRUE;
78}
79
80static Evas_Object *
81_evas_object_box_iterator_get_container(Evas_Object_Box_Iterator *it)
82{
83 return (Evas_Object *)it->box;
84}
85
86static void
87_evas_object_box_iterator_free(Evas_Object_Box_Iterator *it)
88{
89 eina_iterator_free(it->real_iterator);
90 free(it);
91}
92
93static Eina_Bool
94_evas_object_box_accessor_get_at(Evas_Object_Box_Accessor *it, unsigned int idx, void **data)
95{
96 Evas_Object_Box_Option *opt = NULL;
97
98 if (!eina_accessor_data_get(it->real_accessor, idx, (void *)&opt))
99 return EINA_FALSE;
100 if (data) *data = opt->obj;
101 return EINA_TRUE;
102}
103
104static Evas_Object *
105_evas_object_box_accessor_get_container(Evas_Object_Box_Accessor *it)
106{
107 return (Evas_Object *)it->box;
108}
109
110static void
111_evas_object_box_accessor_free(Evas_Object_Box_Accessor *it)
112{
113 eina_accessor_free(it->real_accessor);
114 free(it);
115}
116
117static void
118_on_child_resize(void *data, Evas *evas __UNUSED__, Evas_Object *o __UNUSED__, void *einfo __UNUSED__)
119{
120 Evas_Object *box = data;
121 EVAS_OBJECT_BOX_DATA_GET_OR_RETURN(box, priv);
122 if (!priv->layouting) evas_object_smart_changed(box);
123}
124
125static void
126_on_child_del(void *data, Evas *evas __UNUSED__, Evas_Object *o, void *einfo __UNUSED__)
127{
128 const Evas_Object_Box_Api *api;
129 Evas_Object *box = data;
130
131 EVAS_OBJECT_BOX_DATA_GET(box, priv);
132 api = priv->api;
133
134 if ((!api) || (!api->remove))
135 {
136 ERR("no api->remove");
137 return;
138 }
139
140 if (!api->remove(box, priv, o))
141 ERR("child removal failed");
142 evas_object_smart_changed(box);
143}
144
145static void
146_on_child_hints_changed(void *data, Evas *evas __UNUSED__, Evas_Object *o __UNUSED__, void *einfo __UNUSED__)
147{
148 Evas_Object *box = data;
149 EVAS_OBJECT_BOX_DATA_GET_OR_RETURN(box, priv);
150 if (!priv->layouting) evas_object_smart_changed(box);
151}
152
153static void
154_on_hints_changed(void *data __UNUSED__, Evas *evas __UNUSED__, Evas_Object *o , void *einfo __UNUSED__)
155{
156 _sizing_eval(o);
157}
158
159static Evas_Object_Box_Option *
160_evas_object_box_option_new(Evas_Object *o, Evas_Object_Box_Data *priv, Evas_Object *child)
161{
162 Evas_Object_Box_Option *opt;
163 const Evas_Object_Box_Api *api;
164
165 api = priv->api;
166 if ((!api) || (!api->option_new))
167 {
168 ERR("no api->option_new");
169 return NULL;
170 }
171
172 opt = api->option_new(o, priv, child);
173 if (!opt)
174 {
175 ERR("option_new failed");
176 return NULL;
177 }
178
179 return opt;
180}
181
182static void
183_evas_object_box_child_callbacks_unregister(Evas_Object *obj)
184{
185 evas_object_event_callback_del
186 (obj, EVAS_CALLBACK_RESIZE, _on_child_resize);
187 evas_object_event_callback_del
188 (obj, EVAS_CALLBACK_FREE, _on_child_del);
189 evas_object_event_callback_del
190 (obj, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _on_child_hints_changed);
191}
192
193static Evas_Object_Box_Option *
194_evas_object_box_option_callbacks_register(Evas_Object *o, Evas_Object_Box_Data *priv, Evas_Object_Box_Option *opt)
195{
196 const Evas_Object_Box_Api *api;
197 Evas_Object *obj = opt->obj;
198
199 api = priv->api;
200
201 if ((!api) || (!api->option_free))
202 {
203 WRN("api->option_free not set (may cause memory leaks, segfaults)");
204 return NULL;
205 }
206
207 evas_object_event_callback_add
208 (obj, EVAS_CALLBACK_RESIZE, _on_child_resize, o);
209 evas_object_event_callback_add
210 (obj, EVAS_CALLBACK_FREE, _on_child_del, o);
211 evas_object_event_callback_add
212 (obj, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _on_child_hints_changed, o);
213
214 return opt;
215}
216
217static Evas_Object_Box_Option *
218_evas_object_box_option_new_default(Evas_Object *o __UNUSED__, Evas_Object_Box_Data *priv __UNUSED__, Evas_Object *child)
219{
220 Evas_Object_Box_Option *opt;
221
222 opt = (Evas_Object_Box_Option *)malloc(sizeof(*opt));
223 if (!opt)
224 return NULL;
225
226 opt->obj = child;
227
228 return opt;
229}
230
231static void
232_evas_object_box_option_free_default(Evas_Object *o __UNUSED__, Evas_Object_Box_Data *priv __UNUSED__, Evas_Object_Box_Option *opt)
233{
234 free(opt);
235}
236
237static Evas_Object_Box_Option *
238_evas_object_box_append_default(Evas_Object *o, Evas_Object_Box_Data *priv, Evas_Object *child)
239{
240 Evas_Object_Box_Option *opt;
241
242 opt = _evas_object_box_option_new(o, priv, child);
243 if (!opt)
244 return NULL;
245
246 priv->children = eina_list_append(priv->children, opt);
247 priv->children_changed = EINA_TRUE;
248 evas_object_smart_callback_call(o, SIG_CHILD_ADDED, opt);
249
250 return opt;
251}
252
253static Evas_Object_Box_Option *
254_evas_object_box_prepend_default(Evas_Object *o, Evas_Object_Box_Data *priv, Evas_Object *child)
255{
256 Evas_Object_Box_Option *opt;
257
258 opt = _evas_object_box_option_new(o, priv, child);
259 if (!opt)
260 return NULL;
261
262 priv->children = eina_list_prepend(priv->children, opt);
263 priv->children_changed = EINA_TRUE;
264 evas_object_smart_callback_call(o, SIG_CHILD_ADDED, opt);
265
266 return opt;
267}
268
269static Evas_Object_Box_Option *
270_evas_object_box_insert_before_default(Evas_Object *o, Evas_Object_Box_Data *priv, Evas_Object *child, const Evas_Object *reference)
271{
272 Eina_List *l;
273 Evas_Object_Box_Option *opt;
274
275 EINA_LIST_FOREACH(priv->children, l, opt)
276 {
277 if (opt->obj == reference)
278 {
279 Evas_Object_Box_Option *new_opt;
280
281 new_opt = _evas_object_box_option_new(o, priv, child);
282 if (!new_opt)
283 return NULL;
284
285 priv->children = eina_list_prepend_relative
286 (priv->children, new_opt, opt);
287 priv->children_changed = EINA_TRUE;
288 evas_object_smart_callback_call(o, SIG_CHILD_ADDED, new_opt);
289 return new_opt;
290 }
291 }
292
293 return NULL;
294}
295
296static Evas_Object_Box_Option *
297_evas_object_box_insert_after_default(Evas_Object *o, Evas_Object_Box_Data *priv, Evas_Object *child, const Evas_Object *reference)
298{
299 Eina_List *l;
300 Evas_Object_Box_Option *opt;
301
302 EINA_LIST_FOREACH(priv->children, l, opt)
303 {
304 if (opt->obj == reference)
305 {
306 Evas_Object_Box_Option *new_opt;
307
308 new_opt = _evas_object_box_option_new(o, priv, child);
309 if (!new_opt)
310 return NULL;
311
312 priv->children = eina_list_append_relative
313 (priv->children, new_opt, opt);
314 priv->children_changed = EINA_TRUE;
315 evas_object_smart_callback_call(o, SIG_CHILD_ADDED, new_opt);
316 return new_opt;
317 }
318 }
319
320 return NULL;
321}
322
323static Evas_Object_Box_Option *
324_evas_object_box_insert_at_default(Evas_Object *o, Evas_Object_Box_Data *priv, Evas_Object *child, unsigned int pos)
325{
326 Eina_List *l;
327 unsigned int i;
328
329 if ((pos == 0) && (eina_list_count(priv->children) == 0))
330 {
331 Evas_Object_Box_Option *new_opt;
332
333 new_opt = _evas_object_box_option_new(o, priv, child);
334 if (!new_opt)
335 return NULL;
336
337 priv->children = eina_list_prepend(priv->children, new_opt);
338 priv->children_changed = EINA_TRUE;
339 evas_object_smart_callback_call(o, SIG_CHILD_ADDED, new_opt);
340 return new_opt;
341 }
342
343 for (l = priv->children, i = 0; l; l = l->next, i++)
344 {
345 Evas_Object_Box_Option *opt = l->data;
346
347 if (i == pos)
348 {
349 Evas_Object_Box_Option *new_opt;
350
351 new_opt = _evas_object_box_option_new(o, priv, child);
352 if (!new_opt)
353 return NULL;
354
355 priv->children = eina_list_prepend_relative
356 (priv->children, new_opt, opt);
357 priv->children_changed = EINA_TRUE;
358 evas_object_smart_callback_call(o, SIG_CHILD_ADDED, new_opt);
359 return new_opt;
360 }
361 }
362
363 return NULL;
364}
365
366static Evas_Object *
367_evas_object_box_remove_default(Evas_Object *o, Evas_Object_Box_Data *priv, Evas_Object *child)
368{
369 const Evas_Object_Box_Api *api;
370 Evas_Object_Box_Option *opt;
371 Eina_List *l;
372
373 api = priv->api;
374
375 if ((!api) || (!api->option_free))
376 {
377 ERR("api->option_free not set (may cause memory leaks, segfaults)");
378 return NULL;
379 }
380
381 EINA_LIST_FOREACH(priv->children, l, opt)
382 {
383 Evas_Object *obj = opt->obj;
384
385 if (obj == child)
386 {
387 priv->children = eina_list_remove(priv->children, opt);
388 api->option_free(o, priv, opt);
389 priv->children_changed = EINA_TRUE;
390 evas_object_smart_callback_call(o, SIG_CHILD_REMOVED, obj);
391
392 return obj;
393 }
394 }
395
396 return NULL;
397}
398
399static Evas_Object *
400_evas_object_box_remove_at_default(Evas_Object *o, Evas_Object_Box_Data *priv, unsigned int pos)
401{
402 const Evas_Object_Box_Api *api;
403 Eina_List *node;
404 Evas_Object_Box_Option *opt;
405 Evas_Object *obj;
406
407 api = priv->api;
408
409 if ((!api) || (!api->option_free))
410 {
411 WRN("api->option_free not set (may cause memory leaks, segfaults)");
412 return NULL;
413 }
414
415 node = eina_list_nth_list(priv->children, pos);
416 if (!node)
417 {
418 ERR("No item to be removed at position %d", pos);
419 return NULL;
420 }
421
422 opt = node->data;
423 obj = opt->obj;
424
425 priv->children = eina_list_remove_list(priv->children, node);
426 api->option_free(o, priv, opt);
427 priv->children_changed = EINA_TRUE;
428 evas_object_smart_callback_call(o, SIG_CHILD_REMOVED, obj);
429 return obj;
430}
431
432static void
433_evas_object_box_smart_add(Evas_Object *o)
434{
435 Evas_Object_Box_Data *priv;
436
437 priv = evas_object_smart_data_get(o);
438 if (!priv)
439 {
440 const Evas_Smart *smart;
441 const Evas_Smart_Class *sc;
442
443 priv = (Evas_Object_Box_Data *)calloc(1, sizeof(*priv));
444 if (!priv)
445 {
446 ERR("Could not allocate object private data.");
447 return;
448 }
449
450 smart = evas_object_smart_smart_get(o);
451 sc = evas_smart_class_get(smart);
452 priv->api = (const Evas_Object_Box_Api *)sc;
453
454 evas_object_smart_data_set(o, priv);
455 }
456 _evas_object_box_parent_sc->add(o);
457
458
459 evas_object_event_callback_add
460 (o, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _on_hints_changed, o);
461 priv->children = NULL;
462 priv->align.h = 0.5;
463 priv->align.v = 0.5;
464 priv->pad.h = 0;
465 priv->pad.v = 0;
466 priv->layout.cb = evas_object_box_layout_horizontal;
467 priv->layout.data = NULL;
468 priv->layout.free_data = NULL;
469}
470
471static void
472_evas_object_box_smart_del(Evas_Object *o)
473{
474 const Evas_Object_Box_Api *api;
475 Eina_List *l;
476
477 EVAS_OBJECT_BOX_DATA_GET(o, priv);
478
479 api = priv->api;
480 if ((!api) || (!api->option_free))
481 {
482 WRN("api->option_free not set (may cause memory leaks, segfaults)");
483 return;
484 }
485
486 l = priv->children;
487 while (l)
488 {
489 Evas_Object_Box_Option *opt = l->data;
490
491 _evas_object_box_child_callbacks_unregister(opt->obj);
492 api->option_free(o, priv, opt);
493 l = eina_list_remove_list(l, l);
494 }
495
496 if (priv->layout.data && priv->layout.free_data)
497 priv->layout.free_data(priv->layout.data);
498
499 _evas_object_box_parent_sc->del(o);
500}
501
502static void
503_evas_object_box_smart_resize(Evas_Object *o, Evas_Coord w, Evas_Coord h)
504{
505 Evas_Coord ow, oh;
506 evas_object_geometry_get(o, NULL, NULL, &ow, &oh);
507 if ((ow == w) && (oh == h)) return;
508 evas_object_smart_changed(o);
509}
510
511static void
512_evas_object_box_smart_calculate(Evas_Object *o)
513{
514 EVAS_OBJECT_BOX_DATA_GET_OR_RETURN(o, priv);
515 if (priv->layout.cb)
516 {
517 priv->layouting = 1;
518 priv->layout.cb(o, priv, priv->layout.data);
519 priv->layouting = 0;
520 priv->children_changed = EINA_FALSE;
521 }
522 else
523 ERR("No layout function set for %p box.", o);
524}
525
526static void
527_evas_object_box_smart_set_user(Evas_Object_Box_Api *api)
528{
529 api->base.add = _evas_object_box_smart_add;
530 api->base.del = _evas_object_box_smart_del;
531 api->base.resize = _evas_object_box_smart_resize;
532 api->base.calculate = _evas_object_box_smart_calculate;
533 api->base.callbacks = _signals;
534
535 api->append = _evas_object_box_append_default;
536 api->prepend = _evas_object_box_prepend_default;
537 api->insert_before = _evas_object_box_insert_before_default;
538 api->insert_after = _evas_object_box_insert_after_default;
539 api->insert_at = _evas_object_box_insert_at_default;
540 api->remove = _evas_object_box_remove_default;
541 api->remove_at = _evas_object_box_remove_at_default;
542 api->option_new = _evas_object_box_option_new_default;
543 api->option_free = _evas_object_box_option_free_default;
544}
545
546EAPI Evas_Object *
547evas_object_box_add(Evas *evas)
548{
549 return evas_object_smart_add(evas, _evas_object_box_smart_class_new());
550}
551
552EAPI Evas_Object *
553evas_object_box_add_to(Evas_Object *parent)
554{
555 Evas *evas;
556 Evas_Object *o;
557
558 evas = evas_object_evas_get(parent);
559 o = evas_object_box_add(evas);
560 evas_object_smart_member_add(o, parent);
561 return o;
562}
563
564EAPI void
565evas_object_box_smart_set(Evas_Object_Box_Api *api)
566{
567 if (!api)
568 return;
569 _evas_object_box_smart_set(api);
570}
571
572EAPI const Evas_Object_Box_Api *
573evas_object_box_smart_class_get(void)
574{
575 static Evas_Object_Box_Api _sc =
576 EVAS_OBJECT_BOX_API_INIT_NAME_VERSION(_evas_object_box_type);
577 static const Evas_Object_Box_Api *class = NULL;
578
579 if (class)
580 return class;
581
582 evas_object_box_smart_set(&_sc);
583 class = &_sc;
584
585 return class;
586}
587
588EAPI void
589evas_object_box_layout_set(Evas_Object *o, Evas_Object_Box_Layout cb, const void *data, void (*free_data)(void *data))
590{
591 EVAS_OBJECT_BOX_DATA_GET_OR_RETURN(o, priv);
592
593 if ((priv->layout.cb == cb) && (priv->layout.data == data) &&
594 (priv->layout.free_data == free_data))
595 return;
596
597 if (priv->layout.data && priv->layout.free_data)
598 priv->layout.free_data(priv->layout.data);
599
600 priv->layout.cb = cb;
601 priv->layout.data = (void *)data;
602 priv->layout.free_data = free_data;
603 evas_object_smart_changed(o);
604}
605
606static void
607_fixed_point_divide_and_decompose_integer(int dividend, int divisor, int *int_part, int *frac_part)
608{
609 int quotient = (long long)(dividend << 16) / divisor;
610 *frac_part = quotient & 0xffff;
611 *int_part = quotient >> 16;
612}
613
614static void
615_layout_dimension_change_min_max_cell_bound(int dim, int *new_dim, int min_d, int max_d, int cell_sz)
616{
617 if (dim > cell_sz)
618 {
619 if ((min_d != 0) && (cell_sz < min_d))
620 *new_dim = min_d;
621 else
622 *new_dim = cell_sz;
623 }
624 else
625 {
626 if ((max_d != -1) && (cell_sz > max_d))
627 *new_dim = max_d;
628 else
629 *new_dim = cell_sz;
630 }
631}
632
633static void
634_layout_set_offset_and_expand_dimension_space_max_bounded(int dim, int *new_dim, int space_sz, int max_dim, int *offset, double align, int pad_before, int pad_after)
635{
636 if (align >= 0.0)
637 {
638 *new_dim = dim;
639 *offset = (space_sz - (dim + pad_before + pad_after)) * align
640 + pad_before;
641 }
642 else
643 {
644 if ((max_dim != -1) && (space_sz > max_dim))
645 {
646 *new_dim = max_dim;
647 *offset = (space_sz - (max_dim + pad_before + pad_after)) * 0.5
648 + pad_before;
649 }
650 else
651 {
652 *new_dim = space_sz;
653 *offset = 0;
654 }
655 }
656}
657
658static void
659_layout_set_offset_and_change_dimension_min_max_cell_bounded(int dim, int *new_dim, int min_dim, int max_dim, int cell_sz, int *offset, double align, int pad_before, int pad_after)
660{
661 if (align >= 0.0)
662 {
663 *new_dim = dim;
664 *offset =
665 (cell_sz - (dim + pad_before + pad_after)) * align + pad_before;
666 }
667 else
668 {
669 *offset = pad_before;
670 _layout_dimension_change_min_max_cell_bound
671 (dim, new_dim, min_dim, max_dim, cell_sz - pad_before - pad_after);
672 }
673}
674
675static void
676_sizing_eval(Evas_Object *obj)
677{
678 Evas_Coord minw, minh, maxw, maxh;
679 Evas_Coord w, h;
680
681 evas_object_size_hint_min_get(obj, &minw, &minh);
682 evas_object_size_hint_max_get(obj, &maxw, &maxh);
683 evas_object_geometry_get(obj, NULL, NULL, &w, &h);
684
685 if (w < minw) w = minw;
686 if (h < minh) h = minh;
687 if ((maxw >= 0) && (w > maxw)) w = maxw;
688 if ((maxh >= 0) && (h > maxh)) h = maxh;
689
690 evas_object_resize(obj, w, h);
691}
692
693static int
694_evas_object_box_layout_horizontal_weight_apply(Evas_Object_Box_Data *priv, Evas_Object_Box_Option **objects, int n_objects, int remaining, int weight_total)
695{
696 int rem_diff = 0;
697 int i;
698
699 for (i = 0; i < n_objects; i++)
700 {
701 Evas_Object_Box_Option *opt = objects[i];
702 Evas_Object *o = opt->obj;
703 int h;
704
705 evas_object_geometry_get(o, NULL, NULL, NULL, &h);
706
707 if (remaining <= 0)
708 {
709 int min_w;
710
711 evas_object_size_hint_min_get(o, &min_w, NULL);
712 evas_object_resize(o, min_w, h);
713 }
714 else
715 {
716 double normal_weight, weight_x;
717 int target_size;
718 int max_w;
719
720 evas_object_size_hint_weight_get(o, &weight_x, NULL);
721 normal_weight = weight_x / weight_total;
722 target_size = (int)((double)remaining * normal_weight);
723
724 evas_object_size_hint_max_get(o, &max_w, NULL);
725 if ((max_w != -1) && (target_size > max_w))
726 {
727 evas_object_resize(o, max_w, h);
728 rem_diff += max_w;
729 objects[i] = objects[n_objects - 1];
730 weight_total -= weight_x;
731 n_objects--;
732 return _evas_object_box_layout_horizontal_weight_apply
733 (priv, objects, n_objects, remaining - rem_diff,
734 weight_total);
735 }
736 else
737 {
738 evas_object_resize(o, target_size, h);
739 rem_diff += target_size;
740 }
741 }
742 }
743
744 return remaining - rem_diff;
745}
746
747EAPI void
748evas_object_box_layout_horizontal(Evas_Object *o, Evas_Object_Box_Data *priv, void *data __UNUSED__)
749{
750 int pad_inc = 0, sub_pixel = 0;
751 int req_w, global_pad, remaining, top_h = 0;
752 double weight_total = 0.0;
753 int weight_use = 0;
754 int x, y, w, h;
755 int n_children;
756 Evas_Object_Box_Option *opt;
757 Evas_Object_Box_Option **objects;
758 Eina_List *l;
759
760 n_children = eina_list_count(priv->children);
761 if (!n_children)
762 return;
763
764 objects = (Evas_Object_Box_Option **)alloca(sizeof(Evas_Object_Box_Option *) * n_children);
765 if (!objects)
766 return;
767
768 evas_object_geometry_get(o, &x, &y, &w, &h);
769 global_pad = priv->pad.h;
770 req_w = global_pad * (n_children - 1);
771
772 EINA_LIST_FOREACH(priv->children, l, opt)
773 {
774 int padding_l, padding_r;
775 double weight_x;
776
777 _sizing_eval(opt->obj);
778 evas_object_size_hint_weight_get(opt->obj, &weight_x, NULL);
779 evas_object_size_hint_padding_get
780 (opt->obj, &padding_l, &padding_r, NULL, NULL);
781 req_w += padding_l + padding_r;
782
783 if (!weight_x)
784 {
785 int child_w;
786
787 evas_object_geometry_get(opt->obj, NULL, NULL, &child_w, NULL);
788 req_w += child_w;
789 }
790 else
791 {
792 objects[weight_use] = opt;
793 weight_use++;
794 weight_total += weight_x;
795 }
796 }
797
798 remaining = w - req_w;
799
800 if (weight_use)
801 remaining = _evas_object_box_layout_horizontal_weight_apply
802 (priv, objects, weight_use, remaining, weight_total);
803
804 if (priv->align.h >= 0.0)
805 x += remaining * priv->align.h;
806 else if (n_children == 1)
807 x += remaining / 2;
808 else
809 { /* justified */
810 _fixed_point_divide_and_decompose_integer
811 (remaining, n_children - 1, &global_pad, &pad_inc);
812 global_pad += priv->pad.h;
813 }
814
815 EINA_LIST_FOREACH(priv->children, l, opt)
816 {
817 int child_w, child_h, max_h, new_h, off_x, off_y;
818 int padding_l, padding_r, padding_t, padding_b;
819 double align_y;
820
821 evas_object_size_hint_align_get(opt->obj, NULL, &align_y);
822 evas_object_size_hint_padding_get
823 (opt->obj, &padding_l, &padding_r, &padding_t, &padding_b);
824 evas_object_size_hint_max_get(opt->obj, NULL, &max_h);
825
826 evas_object_geometry_get(opt->obj, NULL, NULL, &child_w, &child_h);
827
828 off_x = padding_l;
829 new_h = child_h;
830 if (new_h > top_h) top_h = new_h;
831
832 _layout_set_offset_and_expand_dimension_space_max_bounded
833 (child_h, &new_h, h, max_h, &off_y, align_y, padding_t, padding_b);
834
835 if (new_h != child_h)
836 evas_object_resize(opt->obj, child_w, new_h);
837 evas_object_move(opt->obj, x + off_x, y + off_y);
838
839 x += child_w + padding_l + padding_r + global_pad;
840 sub_pixel += pad_inc;
841 if (sub_pixel >= 1 << 16)
842 {
843 x++;
844 sub_pixel -= 1 << 16;
845 }
846 }
847
848 evas_object_size_hint_min_set(o, req_w, top_h);
849}
850
851static int
852_evas_object_box_layout_vertical_weight_apply(Evas_Object_Box_Data *priv, Evas_Object_Box_Option **objects, int n_objects, int remaining, int weight_total)
853{
854 int rem_diff = 0;
855 int i;
856
857 for (i = 0; i < n_objects; i++)
858 {
859 Evas_Object_Box_Option *opt = objects[i];
860 Evas_Object *o = opt->obj;
861 int w;
862
863 evas_object_geometry_get(o, NULL, NULL, &w, NULL);
864
865 if (remaining <= 0)
866 {
867 int min_h;
868
869 evas_object_size_hint_min_get(o, NULL, &min_h);
870 evas_object_resize(o, w, min_h);
871 }
872 else
873 {
874 double normal_weight, weight_y;
875 int target_size;
876 int max_h;
877
878 evas_object_size_hint_weight_get(o, NULL, &weight_y);
879 normal_weight = weight_y / weight_total;
880 target_size = (int)((double)remaining * normal_weight);
881
882 evas_object_size_hint_max_get(o, NULL, &max_h);
883 if ((max_h != -1) && (target_size > max_h))
884 {
885 evas_object_resize(o, w, max_h);
886 rem_diff += max_h;
887 objects[i] = objects[n_objects - 1];
888 weight_total -= weight_y;
889 n_objects--;
890 return _evas_object_box_layout_vertical_weight_apply
891 (priv, objects, n_objects, remaining - rem_diff,
892 weight_total);
893 }
894 else
895 {
896 evas_object_resize(o, w, target_size);
897 rem_diff += target_size;
898 }
899 }
900 }
901
902 return remaining - rem_diff;
903}
904
905EAPI void
906evas_object_box_layout_vertical(Evas_Object *o, Evas_Object_Box_Data *priv, void *data __UNUSED__)
907{
908 int pad_inc = 0, sub_pixel = 0;
909 int req_h, global_pad, remaining, top_w = 0;
910 double weight_total = 0.0;
911 int weight_use = 0;
912 int x, y, w, h;
913 int n_children;
914 Evas_Object_Box_Option *opt;
915 Evas_Object_Box_Option **objects;
916 Eina_List *l;
917
918 n_children = eina_list_count(priv->children);
919 if (!n_children)
920 return;
921
922 objects = (Evas_Object_Box_Option **)alloca(sizeof(Evas_Object_Box_Option *) * n_children);
923 if (!objects)
924 return;
925
926 evas_object_geometry_get(o, &x, &y, &w, &h);
927 global_pad = priv->pad.v;
928 req_h = global_pad * (n_children - 1);
929
930 EINA_LIST_FOREACH(priv->children, l, opt)
931 {
932 int padding_t, padding_b;
933 double weight_y;
934
935 _sizing_eval(opt->obj);
936 evas_object_size_hint_weight_get(opt->obj, NULL, &weight_y);
937 evas_object_size_hint_padding_get
938 (opt->obj, NULL, NULL, &padding_t, &padding_b);
939 req_h += padding_t + padding_b;
940
941 if (!weight_y)
942 {
943 int child_h;
944
945 evas_object_geometry_get(opt->obj, NULL, NULL, NULL, &child_h);
946 req_h += child_h;
947 }
948 else
949 {
950 objects[weight_use] = opt;
951 weight_use++;
952 weight_total += weight_y;
953 }
954 }
955
956 remaining = h - req_h;
957
958 if (weight_use)
959 remaining = _evas_object_box_layout_vertical_weight_apply
960 (priv, objects, weight_use, remaining, weight_total);
961
962 if (priv->align.v >= 0.0)
963 y += remaining * priv->align.v;
964 else if (n_children == 1)
965 y += remaining / 2;
966 else
967 { /* justified */
968 _fixed_point_divide_and_decompose_integer
969 (remaining, n_children - 1, &global_pad, &pad_inc);
970 global_pad += priv->pad.v;
971 }
972
973 EINA_LIST_FOREACH(priv->children, l, opt)
974 {
975 int child_w, child_h, max_w, new_w, off_x, off_y;
976 int padding_l, padding_r, padding_t, padding_b;
977 double align_x;
978
979 evas_object_size_hint_align_get(opt->obj, &align_x, NULL);
980 evas_object_size_hint_padding_get
981 (opt->obj, &padding_l, &padding_r, &padding_t, &padding_b);
982 evas_object_size_hint_max_get(opt->obj, &max_w, NULL);
983
984 evas_object_geometry_get(opt->obj, NULL, NULL, &child_w, &child_h);
985
986 off_y = padding_t;
987 new_w = child_w;
988
989 _layout_set_offset_and_expand_dimension_space_max_bounded
990 (child_w, &new_w, w, max_w, &off_x, align_x, padding_l, padding_r);
991
992 if (new_w > top_w) top_w = new_w;
993
994 if (new_w != child_w)
995 evas_object_resize(opt->obj, new_w, child_h);
996 evas_object_move(opt->obj, x + off_x, y + off_y);
997
998 y += child_h + padding_t + padding_b + global_pad;
999 sub_pixel += pad_inc;
1000 if (sub_pixel >= 1 << 16)
1001 {
1002 y++;
1003 sub_pixel -= 1 << 16;
1004 }
1005 }
1006
1007 evas_object_size_hint_min_set(o, top_w, req_h);
1008}
1009
1010EAPI void
1011evas_object_box_layout_homogeneous_horizontal(Evas_Object *o, Evas_Object_Box_Data *priv, void *data __UNUSED__)
1012{
1013 int cell_sz, share, inc;
1014 int sub_pixel = 0;
1015 int x, y, w, h;
1016 int n_children;
1017 Evas_Object_Box_Option *opt;
1018 Eina_List *l;
1019
1020 n_children = eina_list_count(priv->children);
1021 if (!n_children)
1022 return;
1023
1024 evas_object_geometry_get(o, &x, &y, &w, &h);
1025
1026 share = w - priv->pad.h * (n_children - 1);
1027 _fixed_point_divide_and_decompose_integer
1028 (share, n_children, &cell_sz, &inc);
1029
1030 EINA_LIST_FOREACH(priv->children, l, opt)
1031 {
1032 int child_w, child_h, max_h, min_w, max_w, new_w, new_h, off_x, off_y;
1033 int padding_l, padding_r, padding_t, padding_b;
1034 double align_x, align_y;
1035
1036 evas_object_size_hint_align_get(opt->obj, &align_x, &align_y);
1037 evas_object_size_hint_padding_get
1038 (opt->obj, &padding_l, &padding_r, &padding_t, &padding_b);
1039 evas_object_size_hint_max_get(opt->obj, &max_w, &max_h);
1040 evas_object_size_hint_min_get(opt->obj, &min_w, NULL);
1041
1042 _sizing_eval(opt->obj);
1043 evas_object_geometry_get(opt->obj, NULL, NULL, &child_w, &child_h);
1044
1045 new_w = child_w;
1046 new_h = child_h;
1047
1048 _layout_set_offset_and_expand_dimension_space_max_bounded
1049 (child_h, &new_h, h, max_h, &off_y, align_y, padding_t, padding_b);
1050
1051 _layout_set_offset_and_change_dimension_min_max_cell_bounded
1052 (child_w, &new_w, min_w, max_w, cell_sz, &off_x, align_x,
1053 padding_l, padding_r);
1054
1055 if ((new_w != child_w) || (new_h != child_h))
1056 evas_object_resize(opt->obj, new_w, new_h);
1057 evas_object_move(opt->obj, x + off_x, y + off_y);
1058
1059 x += cell_sz + priv->pad.h;
1060 sub_pixel += inc;
1061 if (sub_pixel >= 1 << 16)
1062 {
1063 x++;
1064 sub_pixel -= 1 << 16;
1065 }
1066 }
1067
1068 evas_object_size_hint_min_set(o, w, h);
1069}
1070
1071EAPI void
1072evas_object_box_layout_homogeneous_vertical(Evas_Object *o, Evas_Object_Box_Data *priv, void *data __UNUSED__)
1073{
1074 int cell_sz, share, inc;
1075 int sub_pixel = 0;
1076 int x, y, w, h;
1077 int n_children;
1078 Evas_Object_Box_Option *opt;
1079 Eina_List *l;
1080
1081 n_children = eina_list_count(priv->children);
1082 if (!n_children)
1083 return;
1084
1085 evas_object_geometry_get(o, &x, &y, &w, &h);
1086
1087 share = h - priv->pad.v * (n_children - 1);
1088 _fixed_point_divide_and_decompose_integer
1089 (share, n_children, &cell_sz, &inc);
1090
1091 EINA_LIST_FOREACH(priv->children, l, opt)
1092 {
1093 int child_w, child_h, max_w, min_h, max_h, new_w, new_h, off_x, off_y;
1094 int padding_l, padding_r, padding_t, padding_b;
1095 double align_x, align_y;
1096
1097 evas_object_size_hint_align_get(opt->obj, &align_x, &align_y);
1098 evas_object_size_hint_padding_get
1099 (opt->obj, &padding_l, &padding_r, &padding_t, &padding_b);
1100 evas_object_size_hint_max_get(opt->obj, &max_w, &max_h);
1101 evas_object_size_hint_min_get(opt->obj, NULL, &min_h);
1102
1103 _sizing_eval(opt->obj);
1104 evas_object_geometry_get(opt->obj, NULL, NULL, &child_w, &child_h);
1105 new_w = child_w;
1106 new_h = child_h;
1107
1108 _layout_set_offset_and_expand_dimension_space_max_bounded
1109 (child_w, &new_w, w, max_w, &off_x, align_x, padding_l, padding_r);
1110
1111 _layout_set_offset_and_change_dimension_min_max_cell_bounded
1112 (child_h, &new_h, min_h, max_h, cell_sz, &off_y, align_y,
1113 padding_t, padding_b);
1114
1115 if ((new_w != child_w) || (new_h != child_h))
1116 evas_object_resize(opt->obj, new_w, new_h);
1117 evas_object_move(opt->obj, x + off_x, y + off_y);
1118
1119 y += cell_sz + priv->pad.v;
1120 sub_pixel += inc;
1121 if (sub_pixel >= 1 << 16)
1122 {
1123 y++;
1124 sub_pixel -= 1 << 16;
1125 }
1126 }
1127
1128 evas_object_size_hint_min_set(o, w, h);
1129}
1130
1131EAPI void
1132evas_object_box_layout_homogeneous_max_size_horizontal(Evas_Object *o, Evas_Object_Box_Data *priv, void *data __UNUSED__)
1133{
1134 int remaining, global_pad, pad_inc = 0, sub_pixel = 0;
1135 int cell_sz = 0;
1136 int x, y, w, h;
1137 int top_h = 0;
1138 int n_children;
1139 Evas_Object_Box_Option *opt;
1140 Eina_List *l;
1141
1142 n_children = eina_list_count(priv->children);
1143 if (!n_children)
1144 return;
1145
1146 evas_object_geometry_get(o, &x, &y, &w, &h);
1147
1148 EINA_LIST_FOREACH(priv->children, l, opt)
1149 {
1150 int child_w, padding_l, padding_r;
1151
1152 _sizing_eval(opt->obj);
1153 evas_object_size_hint_padding_get
1154 (opt->obj, &padding_l, &padding_r, NULL, NULL);
1155 evas_object_geometry_get(opt->obj, NULL, NULL, &child_w, NULL);
1156 if (child_w + padding_l + padding_r > cell_sz)
1157 cell_sz = child_w + padding_l + padding_r;
1158 }
1159
1160 global_pad = priv->pad.h;
1161 remaining = w - n_children * cell_sz - global_pad * (n_children - 1);
1162
1163 if (priv->align.h >= 0.0)
1164 x += remaining * priv->align.h;
1165 else if (n_children == 1)
1166 x += remaining / 2;
1167 else
1168 { /* justified */
1169 _fixed_point_divide_and_decompose_integer
1170 (remaining, n_children - 1, &global_pad, &pad_inc);
1171 global_pad += priv->pad.h;
1172 }
1173
1174 EINA_LIST_FOREACH(priv->children, l, opt)
1175 {
1176 int child_w, child_h, min_w, max_w, max_h, new_w, new_h, off_x, off_y;
1177 int padding_l, padding_r, padding_t, padding_b;
1178 double align_x, align_y;
1179
1180 evas_object_size_hint_align_get(opt->obj, &align_x, &align_y);
1181 evas_object_size_hint_padding_get
1182 (opt->obj, &padding_l, &padding_r, &padding_t, &padding_b);
1183 evas_object_size_hint_max_get(opt->obj, &max_w, &max_h);
1184 evas_object_size_hint_min_get(opt->obj, &min_w, NULL);
1185
1186 evas_object_geometry_get(opt->obj, NULL, NULL, &child_w, &child_h);
1187
1188 new_w = child_w;
1189 new_h = child_h;
1190 if (new_h > top_h) top_h = new_h;
1191
1192 _layout_set_offset_and_expand_dimension_space_max_bounded
1193 (child_h, &new_h, h, max_h, &off_y, align_y, padding_t, padding_b);
1194
1195 _layout_set_offset_and_change_dimension_min_max_cell_bounded
1196 (child_w, &new_w, min_w, max_w, cell_sz, &off_x, align_x,
1197 padding_l, padding_r);
1198
1199 if ((new_w != child_w) || (new_h != child_h))
1200 evas_object_resize(opt->obj, new_w, new_h);
1201 evas_object_move(opt->obj, x + off_x, y + off_y);
1202
1203 x += cell_sz + global_pad;
1204 sub_pixel += pad_inc;
1205 if (sub_pixel >= 1 << 16)
1206 {
1207 x++;
1208 sub_pixel -= 1 << 16;
1209 }
1210 }
1211
1212 evas_object_size_hint_min_set(o, x, top_h);
1213}
1214
1215EAPI void
1216evas_object_box_layout_homogeneous_max_size_vertical(Evas_Object *o, Evas_Object_Box_Data *priv, void *data __UNUSED__)
1217{
1218 int remaining, global_pad, pad_inc = 0, sub_pixel = 0;
1219 int cell_sz = 0;
1220 int x, y, w, h;
1221 int top_w = 0;
1222 int n_children;
1223 Evas_Object_Box_Option *opt;
1224 Eina_List *l;
1225
1226 n_children = eina_list_count(priv->children);
1227 if (!n_children)
1228 return;
1229
1230 evas_object_geometry_get(o, &x, &y, &w, &h);
1231
1232 EINA_LIST_FOREACH(priv->children, l, opt)
1233 {
1234 int child_h, padding_t, padding_b;
1235
1236 _sizing_eval(opt->obj);
1237 evas_object_size_hint_padding_get
1238 (opt->obj, NULL, NULL, &padding_t, &padding_b);
1239 evas_object_geometry_get(opt->obj, NULL, NULL, NULL, &child_h);
1240 if (child_h + padding_t + padding_b > cell_sz)
1241 cell_sz = child_h + padding_t + padding_b;
1242 }
1243
1244 global_pad = priv->pad.v;
1245 remaining = h - n_children * cell_sz - global_pad * (n_children - 1);
1246
1247 if (priv->align.v >= 0.0)
1248 y += remaining * priv->align.v;
1249 else if (n_children == 1)
1250 y += remaining / 2;
1251 else
1252 { /* justified */
1253 _fixed_point_divide_and_decompose_integer
1254 (remaining, n_children - 1, &global_pad, &pad_inc);
1255 global_pad += priv->pad.v;
1256 }
1257
1258 EINA_LIST_FOREACH(priv->children, l, opt)
1259 {
1260 int child_w, child_h, max_h, min_h, max_w, new_w, new_h, off_x, off_y;
1261 int padding_l, padding_r, padding_t, padding_b;
1262 double align_x, align_y;
1263
1264 evas_object_size_hint_align_get(opt->obj, &align_x, &align_y);
1265 evas_object_size_hint_padding_get
1266 (opt->obj, &padding_l, &padding_r, &padding_t, &padding_b);
1267 evas_object_size_hint_max_get(opt->obj, &max_w, &max_h);
1268 evas_object_size_hint_min_get(opt->obj, NULL, &min_h);
1269
1270 evas_object_geometry_get(opt->obj, NULL, NULL, &child_w, &child_h);
1271
1272 new_w = child_w;
1273 new_h = child_h;
1274 if (new_w > top_w) top_w = new_w;
1275
1276 _layout_set_offset_and_expand_dimension_space_max_bounded
1277 (child_w, &new_w, w, max_w, &off_x, align_x, padding_l, padding_r);
1278
1279 _layout_set_offset_and_change_dimension_min_max_cell_bounded
1280 (child_h, &new_h, min_h, max_h, cell_sz, &off_y, align_y,
1281 padding_t, padding_b);
1282
1283 if ((new_w != child_w) || (new_h != child_h))
1284 evas_object_resize(opt->obj, new_w, new_h);
1285 evas_object_move(opt->obj, x + off_x, y + off_y);
1286
1287 y += cell_sz + global_pad;
1288 sub_pixel += pad_inc;
1289 if (sub_pixel >= 1 << 16)
1290 {
1291 y++;
1292 sub_pixel -= 1 << 16;
1293 }
1294 }
1295
1296 evas_object_size_hint_min_set(o, top_w, y);
1297}
1298
1299static void
1300_evas_object_box_layout_flow_horizontal_row_info_collect(Evas_Object_Box_Data *priv, int box_w, int *row_count, int *row_max_h, int *row_break, int *row_width, int *off_y_ret, int *max_h_ret)
1301{
1302 int i, remain_w = box_w, start_i = 0;
1303 int off_y = 0, max_h = 0, n_rows = 0;
1304 Eina_List *l;
1305
1306 for (i = 0, l = priv->children; l; i++, l = l->next)
1307 {
1308 Evas_Object_Box_Option *opt = l->data;
1309 int padding_l, padding_r, padding_t, padding_b;
1310 int child_w, child_h, off_x = 0;
1311
1312 evas_object_size_hint_padding_get
1313 (opt->obj, &padding_l, &padding_r, &padding_t, &padding_b);
1314
1315 _sizing_eval(opt->obj);
1316 evas_object_geometry_get(opt->obj, NULL, NULL, &child_w, &child_h);
1317
1318 child_w += padding_l + padding_r + priv->pad.h;
1319 child_h += padding_t + padding_b;
1320
1321 remain_w -= child_w;
1322 if (remain_w + priv->pad.h >= 0)
1323 { /* continue "line" */
1324 if (child_h > max_h)
1325 max_h = child_h;
1326
1327 off_x += child_w;
1328 row_width[n_rows] += child_w;
1329 }
1330 else
1331 { /* break line */
1332 if (i == start_i)
1333 { /* obj goes to actual line */
1334 max_h = child_h;
1335 row_width[n_rows] = child_w;
1336 }
1337 else
1338 { /* obj goes to next line */
1339 row_max_h[n_rows] = max_h;
1340 row_break[n_rows] = i - 1;
1341 n_rows++;
1342
1343 off_x = child_w;
1344 off_y += max_h;
1345 max_h = child_h;
1346
1347 row_width[n_rows] = child_w;
1348 start_i = i;
1349
1350 remain_w = box_w - off_x;
1351 }
1352 }
1353 }
1354
1355 row_break[n_rows] = i - 1;
1356 row_max_h[n_rows] = max_h;
1357
1358 *row_count = n_rows;
1359 *off_y_ret = off_y;
1360 *max_h_ret = max_h;
1361}
1362
1363EAPI void
1364evas_object_box_layout_flow_horizontal(Evas_Object *o, Evas_Object_Box_Data *priv, void *data __UNUSED__)
1365{
1366 int n_children;
1367 int r, row_count = 0;
1368 int min_w = 0, min_h = 0;
1369 int max_h, inc_y;
1370 int remain_y, i;
1371 int x, y, w, h;
1372 Eina_List *l;
1373 int *row_max_h;
1374 int *row_break;
1375 int *row_width;
1376 int offset_y;
1377
1378 n_children = eina_list_count(priv->children);
1379 if (!n_children)
1380 return;
1381
1382 /* *per row* arrays */
1383 row_max_h = (int *)alloca(sizeof(int) * n_children);
1384 if (!row_max_h)
1385 return;
1386 row_break = (int *)alloca(sizeof(int) * n_children);
1387 if (!row_break)
1388 return;
1389 row_width = (int *)alloca(sizeof(int) * n_children);
1390 if (!row_width)
1391 return;
1392
1393 memset(row_width, 0, sizeof(row_width));
1394
1395 evas_object_geometry_get(o, &x, &y, &w, &h);
1396
1397 _evas_object_box_layout_flow_horizontal_row_info_collect
1398 (priv, w, &row_count, row_max_h, row_break, row_width, &offset_y, &max_h);
1399
1400 inc_y = 0;
1401 remain_y = h - (offset_y + max_h);
1402
1403 if (remain_y > 0)
1404 {
1405 if (priv->align.v >= 0.0)
1406 inc_y = priv->align.v * remain_y;
1407 else if (row_count == 0)
1408 y += remain_y / 2;
1409 else /* y-justified */
1410 inc_y = remain_y / row_count;
1411 }
1412
1413 inc_y += priv->pad.v;
1414
1415 for (i = 0, r = 0, l = priv->children; r <= row_count; r++)
1416 {
1417 int row_justify = 0, just_inc = 0, sub_pixel = 0;
1418 int row_size, remain_x;
1419
1420 row_size = row_break[r] - i;
1421 remain_x = (w - row_width[r]);
1422
1423 if (priv->align.h < 0.0)
1424 {
1425 if (row_size == 0)
1426 x += remain_x / 2;
1427 else
1428 _fixed_point_divide_and_decompose_integer
1429 (remain_x, row_size, &row_justify, &just_inc);
1430 }
1431
1432 row_justify += priv->pad.h;
1433
1434 for (; i <= row_break[r]; i++, l = l->next)
1435 {
1436 Evas_Object_Box_Option *opt = l->data;
1437 int off_x, off_y, y_remain;
1438 int padding_l, padding_r;
1439 int child_w, child_h;
1440 double align_y;
1441
1442 evas_object_size_hint_align_get(opt->obj, NULL, &align_y);
1443 evas_object_size_hint_padding_get
1444 (opt->obj, &padding_l, &padding_r, NULL, NULL);
1445
1446 evas_object_geometry_get
1447 (opt->obj, NULL, NULL, &child_w, &child_h);
1448
1449 y_remain = row_max_h[r] - child_h;
1450
1451 off_x = padding_l;
1452 if (priv->align.h >= 0.0)
1453 off_x += remain_x * priv->align.h;
1454 off_y = y_remain * align_y;
1455
1456 evas_object_move(opt->obj, x + off_x, y + off_y);
1457
1458 x += child_w + padding_l + padding_r + row_justify;
1459
1460 sub_pixel += just_inc;
1461 if (sub_pixel >= 1 << 16)
1462 {
1463 x++;
1464 sub_pixel -= 1 << 16;
1465 }
1466 }
1467
1468 evas_object_geometry_get(o, &x, NULL, NULL, NULL);
1469 if (min_w < row_width[r])
1470 min_w = row_width[r];
1471 min_h += row_max_h[r];
1472 y += row_max_h[r] + inc_y;
1473 }
1474
1475 evas_object_size_hint_min_set(o, min_w, min_h);
1476}
1477
1478static void
1479_evas_object_box_layout_flow_vertical_col_info_collect(Evas_Object_Box_Data *priv, int box_h, int *col_count, int *col_max_w, int *col_break, int *col_height, int *off_x_ret, int *max_w_ret)
1480{
1481 int i, remain_h = box_h, start_i = 0;
1482 int off_x = 0, max_w = 0, n_cols = 0;
1483 Eina_List *l;
1484
1485 for (i = 0, l = priv->children; l; i++, l = l->next)
1486 {
1487 Evas_Object_Box_Option *opt = l->data;
1488 int padding_l, padding_r, padding_t, padding_b;
1489 int child_w, child_h, off_y = 0;
1490
1491 evas_object_size_hint_padding_get
1492 (opt->obj, &padding_l, &padding_r, &padding_t, &padding_b);
1493
1494 _sizing_eval(opt->obj);
1495 evas_object_geometry_get(opt->obj, NULL, NULL, &child_w, &child_h);
1496
1497 child_w += padding_l + padding_r;
1498 child_h += padding_t + padding_b + priv->pad.v;
1499
1500 remain_h -= child_h;
1501 if (remain_h + priv->pad.v >= 0)
1502 { /* continue "col" */
1503 if (child_w > max_w)
1504 max_w = child_w;
1505
1506 off_y += child_h;
1507 col_height[n_cols] += child_h;
1508 }
1509 else
1510 {
1511 /* break col */
1512 if (i == start_i)
1513 { /* obj goes to actual col */
1514 max_w = child_w;
1515 col_height[n_cols] = child_h;
1516 }
1517 else
1518 { /* obj goes to next col */
1519 col_max_w[n_cols] = max_w;
1520 col_break[n_cols] = i - 1;
1521 n_cols++;
1522
1523 off_x += max_w;
1524 off_y = child_h;
1525 max_w = child_w;
1526
1527 col_height[n_cols] = child_h;
1528 start_i = i;
1529
1530 remain_h = box_h - off_y;
1531 }
1532 }
1533 }
1534
1535 col_break[n_cols] = i - 1;
1536 col_max_w[n_cols] = max_w;
1537
1538 *col_count = n_cols;
1539 *off_x_ret = off_x;
1540 *max_w_ret = max_w;
1541}
1542
1543EAPI void
1544evas_object_box_layout_flow_vertical(Evas_Object *o, Evas_Object_Box_Data *priv, void *data __UNUSED__)
1545{
1546 int n_children;
1547 int c, col_count;
1548 int min_w = 0, min_h = 0;
1549 int max_w, inc_x;
1550 int remain_x, i;
1551 int x, y, w, h;
1552 Eina_List *l;
1553 int *col_max_w;
1554 int *col_break;
1555 int *col_height;
1556 int offset_x;
1557
1558 n_children = eina_list_count(priv->children);
1559 if (!n_children)
1560 return;
1561
1562 /* *per col* arrays */
1563 col_max_w = (int *)alloca(sizeof(int) * n_children);
1564 if (!col_max_w)
1565 return;
1566 col_break = (int *)alloca(sizeof(int) * n_children);
1567 if (!col_break)
1568 return;
1569 col_height = (int *)alloca(sizeof(int) * n_children);
1570 if (!col_height)
1571 return;
1572
1573 memset(col_height, 0, sizeof(col_height));
1574
1575 evas_object_geometry_get(o, &x, &y, &w, &h);
1576
1577 _evas_object_box_layout_flow_vertical_col_info_collect
1578 (priv, h, &col_count, col_max_w, col_break, col_height, &offset_x, &max_w);
1579
1580 inc_x = 0;
1581 remain_x = w - (offset_x + max_w);
1582
1583 if (remain_x > 0)
1584 {
1585 if (priv->align.h >= 0)
1586 inc_x = priv->align.h * remain_x;
1587 else if (col_count == 0)
1588 x += remain_x / 2;
1589 else /* x-justified */
1590 inc_x = remain_x / col_count;
1591 }
1592
1593 inc_x += priv->pad.h;
1594
1595 for (i = 0, c = 0, l = priv->children; c <= col_count; c++)
1596 {
1597 int col_justify = 0, just_inc = 0, sub_pixel = 0;
1598 int col_size, remain_y;
1599
1600 col_size = col_break[c] - i;
1601 remain_y = (h - col_height[c]);
1602
1603 if (priv->align.v < 0.0)
1604 {
1605 if (col_size == 0)
1606 y += remain_y / 2;
1607 else
1608 _fixed_point_divide_and_decompose_integer
1609 (remain_y, col_size, &col_justify, &just_inc);
1610 }
1611
1612 col_justify += priv->pad.v;
1613
1614 for (; i <= col_break[c]; i++, l = l->next)
1615 {
1616 Evas_Object_Box_Option *opt = l->data;
1617 int off_x, off_y, x_remain;
1618 int padding_t, padding_b;
1619 int child_w, child_h;
1620 double align_x;
1621
1622 evas_object_size_hint_align_get(opt->obj, &align_x, NULL);
1623 evas_object_size_hint_padding_get
1624 (opt->obj, NULL, NULL, &padding_t, &padding_b);
1625
1626 evas_object_geometry_get
1627 (opt->obj, NULL, NULL, &child_w, &child_h);
1628
1629 x_remain = col_max_w[c] - child_w;
1630
1631 off_x = x_remain * align_x;
1632 off_y = padding_t;
1633 if (priv->align.v >= 0.0)
1634 off_y += remain_y * priv->align.v;
1635
1636 evas_object_move(opt->obj, x + off_x, y + off_y);
1637
1638 y += child_h + padding_t + padding_b + col_justify;
1639
1640 sub_pixel += just_inc;
1641 if (sub_pixel >= 1 << 16)
1642 {
1643 y++;
1644 sub_pixel -= 1 << 16;
1645 }
1646 }
1647
1648 evas_object_geometry_get(o, NULL, &y, NULL, NULL);
1649 min_w += col_max_w[c];
1650 if (min_h < col_height[c])
1651 min_h = col_height[c];
1652 x += col_max_w[c] + inc_x;
1653 }
1654
1655 evas_object_size_hint_min_set(o, min_w, min_h);
1656}
1657
1658EAPI void
1659evas_object_box_layout_stack(Evas_Object *o, Evas_Object_Box_Data *priv, void *data __UNUSED__)
1660{
1661 Eina_List *l;
1662 Evas_Coord ox, oy, ow, oh;
1663 Evas_Coord top_w = 0, top_h = 0;
1664 Evas_Object_Box_Option *opt;
1665 Evas_Object *old_child = NULL;
1666
1667 evas_object_geometry_get(o, &ox, &oy, &ow, &oh);
1668
1669 EINA_LIST_FOREACH(priv->children, l, opt)
1670 {
1671 Evas_Object *child = opt->obj;
1672 Evas_Coord max_w, max_h, min_w, min_h, pad_l, pad_r, pad_t, pad_b,
1673 child_w, child_h, new_w, new_h, off_x, off_y;
1674 double align_x, align_y;
1675
1676 evas_object_size_hint_align_get(child, &align_x, &align_y);
1677 evas_object_size_hint_padding_get
1678 (child, &pad_l, &pad_r, &pad_t, &pad_b);
1679 evas_object_size_hint_max_get(child, &max_w, &max_h);
1680 evas_object_size_hint_min_get(child, &min_w, &min_h);
1681
1682 _sizing_eval(opt->obj);
1683 evas_object_geometry_get(child, NULL, NULL, &child_w, &child_h);
1684 new_w = child_w;
1685 new_h = child_h;
1686 if (new_w > top_w) top_w = new_w;
1687 if (new_h > top_h) top_h = new_h;
1688
1689 _layout_set_offset_and_change_dimension_min_max_cell_bounded
1690 (child_w, &new_w, min_w, max_w, ow, &off_x, align_x, pad_l, pad_r);
1691 _layout_set_offset_and_change_dimension_min_max_cell_bounded
1692 (child_h, &new_h, min_h, max_h, oh, &off_y, align_y, pad_t, pad_b);
1693
1694 if ((new_w != child_w) || (new_h != child_h))
1695 evas_object_resize(child, new_w, new_h);
1696 evas_object_move(child, ox + off_x, oy + off_y);
1697
1698 if (old_child)
1699 evas_object_stack_above(child, old_child);
1700 old_child = child;
1701 }
1702
1703 evas_object_size_hint_min_set(o, top_w, top_h);
1704}
1705
1706EAPI void
1707evas_object_box_align_set(Evas_Object *o, double horizontal, double vertical)
1708{
1709 EVAS_OBJECT_BOX_DATA_GET_OR_RETURN(o, priv);
1710 if (priv->align.h == horizontal && priv->align.v == vertical)
1711 return;
1712 priv->align.h = horizontal;
1713 priv->align.v = vertical;
1714 evas_object_smart_changed(o);
1715}
1716
1717EAPI void
1718evas_object_box_align_get(const Evas_Object *o, double *horizontal, double *vertical)
1719{
1720 EVAS_OBJECT_BOX_DATA_GET(o, priv);
1721 if (priv)
1722 {
1723 if (horizontal) *horizontal = priv->align.h;
1724 if (vertical) *vertical = priv->align.v;
1725 }
1726 else
1727 {
1728 if (horizontal) *horizontal = 0.5;
1729 if (vertical) *vertical = 0.5;
1730 }
1731}
1732
1733EAPI void
1734evas_object_box_padding_set(Evas_Object *o, Evas_Coord horizontal, Evas_Coord vertical)
1735{
1736 EVAS_OBJECT_BOX_DATA_GET_OR_RETURN(o, priv);
1737 if (priv->pad.h == horizontal && priv->pad.v == vertical)
1738 return;
1739 priv->pad.h = horizontal;
1740 priv->pad.v = vertical;
1741 evas_object_smart_changed(o);
1742}
1743
1744EAPI void
1745evas_object_box_padding_get(const Evas_Object *o, Evas_Coord *horizontal, Evas_Coord *vertical)
1746{
1747 EVAS_OBJECT_BOX_DATA_GET(o, priv);
1748 if (priv)
1749 {
1750 if (horizontal) *horizontal = priv->pad.h;
1751 if (vertical) *vertical = priv->pad.v;
1752 }
1753 else
1754 {
1755 if (horizontal) *horizontal = 0;
1756 if (vertical) *vertical = 0;
1757 }
1758}
1759
1760EAPI Evas_Object_Box_Option *
1761evas_object_box_append(Evas_Object *o, Evas_Object *child)
1762{
1763 Evas_Object_Box_Option *opt;
1764 const Evas_Object_Box_Api *api;
1765
1766 EVAS_OBJECT_BOX_DATA_GET_OR_RETURN_VAL(o, priv, 0);
1767 if (!child)
1768 return NULL;
1769
1770 api = priv->api;
1771 if ((!api) || (!api->append))
1772 return NULL;
1773
1774 opt = api->append(o, priv, child);
1775
1776 if (opt)
1777 {
1778 evas_object_smart_member_add(child, o);
1779 evas_object_smart_changed(o);
1780 return _evas_object_box_option_callbacks_register(o, priv, opt);
1781 }
1782
1783 return NULL;
1784}
1785
1786EAPI Evas_Object_Box_Option *
1787evas_object_box_prepend(Evas_Object *o, Evas_Object *child)
1788{
1789 Evas_Object_Box_Option *opt;
1790 const Evas_Object_Box_Api *api;
1791
1792 EVAS_OBJECT_BOX_DATA_GET_OR_RETURN_VAL(o, priv, 0);
1793 if (!child)
1794 return NULL;
1795
1796 api = priv->api;
1797 if ((!api) || (!api->prepend))
1798 return NULL;
1799
1800 opt = api->prepend(o, priv, child);
1801
1802 if (opt)
1803 {
1804 evas_object_smart_member_add(child, o);
1805 evas_object_smart_changed(o);
1806 return _evas_object_box_option_callbacks_register(o, priv, opt);
1807 }
1808
1809 return NULL;
1810}
1811
1812EAPI Evas_Object_Box_Option *
1813evas_object_box_insert_before(Evas_Object *o, Evas_Object *child, const Evas_Object *reference)
1814{
1815 Evas_Object_Box_Option *opt;
1816 const Evas_Object_Box_Api *api;
1817
1818 EVAS_OBJECT_BOX_DATA_GET_OR_RETURN_VAL(o, priv, 0);
1819 if (!child)
1820 return NULL;
1821
1822 api = priv->api;
1823 if ((!api) || (!api->insert_before))
1824 return NULL;
1825
1826 opt = api->insert_before(o, priv, child, reference);
1827
1828 if (opt)
1829 {
1830 evas_object_smart_member_add(child, o);
1831 evas_object_smart_changed(o);
1832 return _evas_object_box_option_callbacks_register(o, priv, opt);
1833 }
1834
1835 return NULL;
1836}
1837
1838EAPI Evas_Object_Box_Option *
1839evas_object_box_insert_after(Evas_Object *o, Evas_Object *child, const Evas_Object *reference)
1840{
1841 Evas_Object_Box_Option *opt;
1842 const Evas_Object_Box_Api *api;
1843
1844 EVAS_OBJECT_BOX_DATA_GET_OR_RETURN_VAL(o, priv, NULL);
1845 if (!child)
1846 return NULL;
1847
1848 api = priv->api;
1849 if ((!api) || (!api->insert_after))
1850 return NULL;
1851
1852 opt = api->insert_after(o, priv, child, reference);
1853
1854 if (opt)
1855 {
1856 evas_object_smart_member_add(child, o);
1857 evas_object_smart_changed(o);
1858 return _evas_object_box_option_callbacks_register(o, priv, opt);
1859 }
1860
1861 return NULL;
1862}
1863
1864EAPI Evas_Object_Box_Option *
1865evas_object_box_insert_at(Evas_Object *o, Evas_Object *child, unsigned int pos)
1866{
1867 Evas_Object_Box_Option *opt;
1868 const Evas_Object_Box_Api *api;
1869
1870 EVAS_OBJECT_BOX_DATA_GET_OR_RETURN_VAL(o, priv, 0);
1871 if (!child)
1872 return NULL;
1873
1874 api = priv->api;
1875 if ((!api) || (!api->insert_at))
1876 return NULL;
1877
1878 opt = api->insert_at(o, priv, child, pos);
1879
1880 if (opt)
1881 {
1882 evas_object_smart_member_add(child, o);
1883 evas_object_smart_changed(o);
1884 return _evas_object_box_option_callbacks_register(o, priv, opt);
1885 }
1886
1887 return NULL;
1888}
1889
1890EAPI Eina_Bool
1891evas_object_box_remove(Evas_Object *o, Evas_Object *child)
1892{
1893 const Evas_Object_Box_Api *api;
1894 Evas_Object *obj;
1895
1896 EVAS_OBJECT_BOX_DATA_GET_OR_RETURN_VAL(o, priv, 0);
1897 if (!child) return EINA_FALSE;
1898
1899 api = priv->api;
1900 if ((!api) || (!api->remove))
1901 return 0;
1902
1903 obj = api->remove(o, priv, child);
1904
1905 if (obj)
1906 {
1907 _evas_object_box_child_callbacks_unregister(obj);
1908 evas_object_smart_member_del(obj);
1909 evas_object_smart_changed(o);
1910 return EINA_TRUE;
1911 }
1912
1913 return EINA_FALSE;
1914}
1915
1916EAPI Eina_Bool
1917evas_object_box_remove_at(Evas_Object *o, unsigned int pos)
1918{
1919 const Evas_Object_Box_Api *api;
1920 Evas_Object *obj;
1921
1922 EVAS_OBJECT_BOX_DATA_GET_OR_RETURN_VAL(o, priv, 0);
1923 api = priv->api;
1924 if ((!api) || (!api->remove_at)) return EINA_FALSE;
1925
1926 obj = api->remove_at(o, priv, pos);
1927
1928 if (obj)
1929 {
1930 _evas_object_box_child_callbacks_unregister(obj);
1931 evas_object_smart_member_del(obj);
1932 evas_object_smart_changed(o);
1933 return EINA_TRUE;
1934 }
1935
1936 return EINA_FALSE;
1937}
1938
1939EAPI Eina_Bool
1940evas_object_box_remove_all(Evas_Object *o, Eina_Bool clear)
1941{
1942 const Evas_Object_Box_Api *api;
1943
1944 EVAS_OBJECT_BOX_DATA_GET_OR_RETURN_VAL(o, priv, 0);
1945
1946 api = priv->api;
1947 if ((!api) || (!api->remove)) return EINA_FALSE;
1948
1949 evas_object_smart_changed(o);
1950
1951 while (priv->children)
1952 {
1953 Evas_Object_Box_Option *opt = priv->children->data;
1954 Evas_Object *obj;
1955
1956 obj = api->remove(o, priv, opt->obj);
1957 if (obj)
1958 {
1959 _evas_object_box_child_callbacks_unregister(obj);
1960 evas_object_smart_member_del(obj);
1961 if (clear)
1962 evas_object_del(obj);
1963 }
1964 else return EINA_FALSE;
1965 }
1966
1967 return EINA_TRUE;
1968}
1969
1970EAPI Eina_Iterator *
1971evas_object_box_iterator_new(const Evas_Object *o)
1972{
1973 Evas_Object_Box_Iterator *it;
1974
1975 EVAS_OBJECT_BOX_DATA_GET_OR_RETURN_VAL(o, priv, NULL);
1976
1977 if (!priv->children) return NULL;
1978
1979 it = calloc(1, sizeof(Evas_Object_Box_Iterator));
1980 if (!it) return NULL;
1981
1982 EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
1983
1984 it->real_iterator = eina_list_iterator_new(priv->children);
1985 it->box = o;
1986
1987 it->iterator.next = FUNC_ITERATOR_NEXT(_evas_object_box_iterator_next);
1988 it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(_evas_object_box_iterator_get_container);
1989 it->iterator.free = FUNC_ITERATOR_FREE(_evas_object_box_iterator_free);
1990
1991 return &it->iterator;
1992}
1993
1994EAPI Eina_Accessor *
1995evas_object_box_accessor_new(const Evas_Object *o)
1996{
1997 Evas_Object_Box_Accessor *it;
1998
1999 EVAS_OBJECT_BOX_DATA_GET_OR_RETURN_VAL(o, priv, NULL);
2000
2001 if (!priv->children) return NULL;
2002
2003 it = calloc(1, sizeof(Evas_Object_Box_Accessor));
2004 if (!it) return NULL;
2005
2006 EINA_MAGIC_SET(&it->accessor, EINA_MAGIC_ACCESSOR);
2007
2008 it->real_accessor = eina_list_accessor_new(priv->children);
2009 it->box = o;
2010
2011 it->accessor.get_at = FUNC_ACCESSOR_GET_AT(_evas_object_box_accessor_get_at);
2012 it->accessor.get_container = FUNC_ACCESSOR_GET_CONTAINER(_evas_object_box_accessor_get_container);
2013 it->accessor.free = FUNC_ACCESSOR_FREE(_evas_object_box_accessor_free);
2014
2015 return &it->accessor;
2016}
2017
2018EAPI Eina_List *
2019evas_object_box_children_get(const Evas_Object *o)
2020{
2021 Eina_List *new_list = NULL, *l;
2022 Evas_Object_Box_Option *opt;
2023
2024 EVAS_OBJECT_BOX_DATA_GET_OR_RETURN_VAL(o, priv, NULL);
2025
2026 EINA_LIST_FOREACH(priv->children, l, opt)
2027 new_list = eina_list_append(new_list, opt->obj);
2028
2029 return new_list;
2030}
2031
2032EAPI const char *
2033evas_object_box_option_property_name_get(Evas_Object *o, int property)
2034{
2035 const Evas_Object_Box_Api *api;
2036
2037 EVAS_OBJECT_BOX_DATA_GET_OR_RETURN_VAL(o, priv, NULL);
2038
2039 if (property < 0)
2040 return NULL;
2041
2042 api = priv->api;
2043 if ((!api) || (!api->property_name_get))
2044 return NULL;
2045
2046 return api->property_name_get(o, property);
2047}
2048
2049EAPI int
2050evas_object_box_option_property_id_get(Evas_Object *o, const char *name)
2051{
2052 const Evas_Object_Box_Api *api;
2053
2054 EVAS_OBJECT_BOX_DATA_GET_OR_RETURN_VAL(o, priv, -1);
2055
2056 if (!name)
2057 return -1;
2058
2059 api = priv->api;
2060 if ((!api) || (!api->property_id_get))
2061 return -1;
2062
2063 return api->property_id_get(o, name);
2064}
2065
2066EAPI Eina_Bool
2067evas_object_box_option_property_set(Evas_Object *o, Evas_Object_Box_Option *opt, int property, ...)
2068{
2069 Eina_Bool ret;
2070 va_list args;
2071
2072 va_start(args, property);
2073 ret = evas_object_box_option_property_vset(o, opt, property, args);
2074 va_end(args);
2075
2076 return ret;
2077}
2078
2079
2080EAPI Eina_Bool
2081evas_object_box_option_property_vset(Evas_Object *o, Evas_Object_Box_Option *opt, int property, va_list args)
2082{
2083 const Evas_Object_Box_Api *api;
2084
2085 EVAS_OBJECT_BOX_DATA_GET_OR_RETURN_VAL(o, priv, 0);
2086
2087 if (!opt) return EINA_FALSE;
2088
2089 api = priv->api;
2090 if ((!api) || (!api->property_set))
2091 return EINA_FALSE;
2092
2093 if (!api->property_set(o, opt, property, args))
2094 return EINA_FALSE;
2095
2096 evas_object_smart_changed(o);
2097 return EINA_TRUE;
2098}
2099
2100EAPI Eina_Bool
2101evas_object_box_option_property_get(Evas_Object *o, Evas_Object_Box_Option *opt, int property, ...)
2102{
2103 Eina_Bool ret;
2104 va_list args;
2105
2106 va_start(args, property);
2107 ret = evas_object_box_option_property_vget(o, opt, property, args);
2108 va_end(args);
2109
2110 return ret;
2111}
2112
2113EAPI Eina_Bool
2114evas_object_box_option_property_vget(Evas_Object *o, Evas_Object_Box_Option *opt, int property, va_list args)
2115{
2116 const Evas_Object_Box_Api *api;
2117
2118 EVAS_OBJECT_BOX_DATA_GET_OR_RETURN_VAL(o, priv, 0);
2119
2120 if (!opt) return EINA_FALSE;
2121
2122 api = priv->api;
2123 if ((!api) || (!api->property_get))
2124 return EINA_FALSE;
2125
2126 return api->property_get(o, opt, property, args);
2127}
diff --git a/libraries/evas/src/lib/canvas/evas_object_grid.c b/libraries/evas/src/lib/canvas/evas_object_grid.c
deleted file mode 100644
index db0f43d..0000000
--- a/libraries/evas/src/lib/canvas/evas_object_grid.c
+++ /dev/null
@@ -1,465 +0,0 @@
1#include "evas_common.h"
2#include <errno.h>
3
4typedef struct _Evas_Object_Grid_Data Evas_Object_Grid_Data;
5typedef struct _Evas_Object_Grid_Option Evas_Object_Grid_Option;
6typedef struct _Evas_Object_Grid_Iterator Evas_Object_Grid_Iterator;
7typedef struct _Evas_Object_Grid_Accessor Evas_Object_Grid_Accessor;
8
9struct _Evas_Object_Grid_Option
10{
11 Evas_Object *obj;
12 Eina_List *l;
13 int x, y, w, h;
14};
15
16struct _Evas_Object_Grid_Data
17{
18 Evas_Object_Smart_Clipped_Data base;
19 Eina_List *children;
20 struct {
21 int w, h;
22 } size;
23 Eina_Bool is_mirrored : 1;
24};
25
26struct _Evas_Object_Grid_Iterator
27{
28 Eina_Iterator iterator;
29
30 Eina_Iterator *real_iterator;
31 const Evas_Object *grid;
32};
33
34struct _Evas_Object_Grid_Accessor
35{
36 Eina_Accessor accessor;
37
38 Eina_Accessor *real_accessor;
39 const Evas_Object *grid;
40};
41
42#define EVAS_OBJECT_GRID_DATA_GET(o, ptr) \
43 Evas_Object_Grid_Data *ptr = evas_object_smart_data_get(o)
44
45#define EVAS_OBJECT_GRID_DATA_GET_OR_RETURN(o, ptr) \
46 EVAS_OBJECT_GRID_DATA_GET(o, ptr); \
47 if (!ptr) \
48 { \
49 CRIT("no widget data for object %p (%s)", \
50 o, evas_object_type_get(o)); \
51 abort(); \
52 return; \
53 }
54
55#define EVAS_OBJECT_GRID_DATA_GET_OR_RETURN_VAL(o, ptr, val) \
56 EVAS_OBJECT_GRID_DATA_GET(o, ptr); \
57 if (!ptr) \
58 { \
59 CRIT("No widget data for object %p (%s)", \
60 o, evas_object_type_get(o)); \
61 abort(); \
62 return val; \
63 }
64
65static const char EVAS_OBJECT_GRID_OPTION_KEY[] = "|EvGd";
66
67static Eina_Bool
68_evas_object_grid_iterator_next(Evas_Object_Grid_Iterator *it, void **data)
69{
70 Evas_Object_Grid_Option *opt;
71
72 if (!eina_iterator_next(it->real_iterator, (void **)&opt))
73 return EINA_FALSE;
74 if (data) *data = opt->obj;
75 return EINA_TRUE;
76}
77
78static Evas_Object *
79_evas_object_grid_iterator_get_container(Evas_Object_Grid_Iterator *it)
80{
81 return (Evas_Object *)it->grid;
82}
83
84static void
85_evas_object_grid_iterator_free(Evas_Object_Grid_Iterator *it)
86{
87 eina_iterator_free(it->real_iterator);
88 free(it);
89}
90
91static Eina_Bool
92_evas_object_grid_accessor_get_at(Evas_Object_Grid_Accessor *it, unsigned int idx, void **data)
93{
94 Evas_Object_Grid_Option *opt = NULL;
95
96 if (!eina_accessor_data_get(it->real_accessor, idx, (void **)&opt))
97 return EINA_FALSE;
98 if (data) *data = opt->obj;
99 return EINA_TRUE;
100}
101
102static Evas_Object *
103_evas_object_grid_accessor_get_container(Evas_Object_Grid_Accessor *it)
104{
105 return (Evas_Object *)it->grid;
106}
107
108static void
109_evas_object_grid_accessor_free(Evas_Object_Grid_Accessor *it)
110{
111 eina_accessor_free(it->real_accessor);
112 free(it);
113}
114
115static Evas_Object_Grid_Option *
116_evas_object_grid_option_get(Evas_Object *o)
117{
118 return evas_object_data_get(o, EVAS_OBJECT_GRID_OPTION_KEY);
119}
120
121static void
122_evas_object_grid_option_set(Evas_Object *o, const Evas_Object_Grid_Option *opt)
123{
124 evas_object_data_set(o, EVAS_OBJECT_GRID_OPTION_KEY, opt);
125}
126
127static Evas_Object_Grid_Option *
128_evas_object_grid_option_del(Evas_Object *o)
129{
130 return evas_object_data_del(o, EVAS_OBJECT_GRID_OPTION_KEY);
131}
132
133static void
134_on_child_del(void *data, Evas *evas __UNUSED__, Evas_Object *child, void *einfo __UNUSED__)
135{
136 Evas_Object *grid = data;
137 evas_object_grid_unpack(grid, child);
138}
139
140static void
141_evas_object_grid_child_connect(Evas_Object *o, Evas_Object *child)
142{
143 evas_object_event_callback_add
144 (child, EVAS_CALLBACK_DEL, _on_child_del, o);
145}
146
147static void
148_evas_object_grid_child_disconnect(Evas_Object *o, Evas_Object *child)
149{
150 evas_object_event_callback_del_full
151 (child, EVAS_CALLBACK_DEL, _on_child_del, o);
152}
153
154EVAS_SMART_SUBCLASS_NEW("Evas_Object_Grid", _evas_object_grid,
155 Evas_Smart_Class, Evas_Smart_Class,
156 evas_object_smart_clipped_class_get, NULL)
157
158static void
159_evas_object_grid_smart_add(Evas_Object *o)
160{
161 EVAS_SMART_DATA_ALLOC(o, Evas_Object_Grid_Data)
162
163 priv->size.w = 100;
164 priv->size.h = 100;
165
166 _evas_object_grid_parent_sc->add(o);
167}
168
169static void
170_evas_object_grid_smart_del(Evas_Object *o)
171{
172 EVAS_OBJECT_GRID_DATA_GET(o, priv);
173 Eina_List *l;
174
175 l = priv->children;
176 while (l)
177 {
178 Evas_Object_Grid_Option *opt = l->data;
179 _evas_object_grid_child_disconnect(o, opt->obj);
180 _evas_object_grid_option_del(opt->obj);
181 free(opt);
182 l = eina_list_remove_list(l, l);
183 }
184 _evas_object_grid_parent_sc->del(o);
185}
186
187static void
188_evas_object_grid_smart_resize(Evas_Object *o, Evas_Coord w, Evas_Coord h)
189{
190 Evas_Coord ow, oh;
191 evas_object_geometry_get(o, NULL, NULL, &ow, &oh);
192 if ((ow == w) && (oh == h)) return;
193 evas_object_smart_changed(o);
194}
195
196static void
197_evas_object_grid_smart_calculate(Evas_Object *o)
198{
199 Eina_List *l;
200 Evas_Object_Grid_Option *opt;
201 Evas_Coord x, y, w, h, vw, vh, t;
202 Eina_Bool mirror;
203
204 EVAS_OBJECT_GRID_DATA_GET_OR_RETURN(o, priv);
205 if (!priv) return;
206 if (!priv->children) return;
207 evas_object_geometry_get(o, &x, &y, &w, &h);
208 mirror = priv->is_mirrored;
209 vw = priv->size.w;
210 vh = priv->size.h;
211 EINA_LIST_FOREACH(priv->children, l, opt)
212 {
213 Evas_Coord x1, y1, x2, y2;
214
215 x1 = x + ((w * opt->x) / vw);
216 y1 = y + ((h * opt->y) / vh);
217 x2 = x + ((w * (opt->x + opt->w)) / vw);
218 y2 = y + ((h * (opt->y + opt->h)) / vh);
219 if (mirror)
220 {
221 t = x1; x1 = x2; x2 = t;
222 t = y1; y1 = y2; y2 = t;
223 }
224 evas_object_move(opt->obj, x1, y1);
225 evas_object_resize(opt->obj, x2 - x1, y2 - y1);
226 }
227}
228
229static void
230_evas_object_grid_smart_set_user(Evas_Smart_Class *sc)
231{
232 sc->add = _evas_object_grid_smart_add;
233 sc->del = _evas_object_grid_smart_del;
234 sc->resize = _evas_object_grid_smart_resize;
235 sc->calculate = _evas_object_grid_smart_calculate;
236}
237
238EAPI Evas_Object *
239evas_object_grid_add(Evas *evas)
240{
241 return evas_object_smart_add(evas, _evas_object_grid_smart_class_new());
242}
243
244EAPI Evas_Object *
245evas_object_grid_add_to(Evas_Object *parent)
246{
247 Evas *evas;
248 Evas_Object *o;
249
250 evas = evas_object_evas_get(parent);
251 o = evas_object_grid_add(evas);
252 evas_object_smart_member_add(o, parent);
253 return o;
254}
255
256EAPI void
257evas_object_grid_size_set(Evas_Object *o, int w, int h)
258{
259 EVAS_OBJECT_GRID_DATA_GET_OR_RETURN(o, priv);
260 if ((priv->size.w == w) && (priv->size.h == h)) return;
261 priv->size.w = w;
262 priv->size.h = h;
263 evas_object_smart_changed(o);
264}
265
266EAPI void
267evas_object_grid_size_get(const Evas_Object *o, int *w, int *h)
268{
269 if (w) *w = 0;
270 if (h) *h = 0;
271 EVAS_OBJECT_GRID_DATA_GET_OR_RETURN(o, priv);
272 if (w) *w = priv->size.w;
273 if (h) *h = priv->size.h;
274}
275
276EAPI Eina_Bool
277evas_object_grid_pack(Evas_Object *o, Evas_Object *child, int x, int y, int w, int h)
278{
279 Evas_Object_Grid_Option *opt;
280 Eina_Bool newobj = EINA_FALSE;
281
282 EVAS_OBJECT_GRID_DATA_GET_OR_RETURN_VAL(o, priv, 0);
283
284 opt = _evas_object_grid_option_get(child);
285 if (!opt)
286 {
287 opt = malloc(sizeof(*opt));
288 if (!opt)
289 {
290 ERR("could not allocate grid option data.");
291 return EINA_FALSE;
292 }
293 newobj = EINA_TRUE;
294 }
295
296 opt->x = x;
297 opt->y = y;
298 opt->w = w;
299 opt->h = h;
300
301 if (newobj)
302 {
303 opt->obj = child;
304 priv->children = eina_list_append(priv->children, opt);
305 opt->l = eina_list_last(priv->children);
306 _evas_object_grid_option_set(child, opt);
307 evas_object_smart_member_add(child, o);
308 _evas_object_grid_child_connect(o, child);
309 }
310 // FIXME: we could keep a changed list
311 evas_object_smart_changed(o);
312 return EINA_TRUE;
313}
314
315static void
316_evas_object_grid_remove_opt(Evas_Object_Grid_Data *priv, Evas_Object_Grid_Option *opt)
317{
318 priv->children = eina_list_remove_list(priv->children, opt->l);
319 opt->l = NULL;
320}
321
322EAPI Eina_Bool
323evas_object_grid_unpack(Evas_Object *o, Evas_Object *child)
324{
325 Evas_Object_Grid_Option *opt;
326
327 EVAS_OBJECT_GRID_DATA_GET_OR_RETURN_VAL(o, priv, 0);
328
329 if (o != evas_object_smart_parent_get(child))
330 {
331 ERR("cannot unpack child from incorrect grid!");
332 return EINA_FALSE;
333 }
334
335 opt = _evas_object_grid_option_del(child);
336 if (!opt)
337 {
338 ERR("cannot unpack child with no packing option!");
339 return EINA_FALSE;
340 }
341
342 _evas_object_grid_child_disconnect(o, child);
343 _evas_object_grid_remove_opt(priv, opt);
344 evas_object_smart_member_del(child);
345 free(opt);
346 return EINA_TRUE;
347}
348
349EAPI void
350evas_object_grid_clear(Evas_Object *o, Eina_Bool clear)
351{
352 Evas_Object_Grid_Option *opt;
353
354 EVAS_OBJECT_GRID_DATA_GET_OR_RETURN(o, priv);
355
356 EINA_LIST_FREE(priv->children, opt)
357 {
358 _evas_object_grid_child_disconnect(o, opt->obj);
359 _evas_object_grid_option_del(opt->obj);
360 evas_object_smart_member_del(opt->obj);
361 if (clear)
362 evas_object_del(opt->obj);
363 free(opt);
364 }
365}
366
367EAPI Eina_Bool
368evas_object_grid_pack_get(Evas_Object *o, Evas_Object *child, int *x, int *y, int *w, int *h)
369{
370 Evas_Object_Grid_Option *opt;
371
372 if (x) *x = 0;
373 if (y) *y = 0;
374 if (w) *w = 0;
375 if (h) *h = 0;
376 EVAS_OBJECT_GRID_DATA_GET_OR_RETURN_VAL(o, priv, 0);
377 opt = _evas_object_grid_option_get(child);
378 if (!opt) return 0;
379 if (x) *x = opt->x;
380 if (y) *y = opt->y;
381 if (w) *w = opt->w;
382 if (h) *h = opt->h;
383 return 1;
384}
385
386EAPI Eina_Iterator *
387evas_object_grid_iterator_new(const Evas_Object *o)
388{
389 Evas_Object_Grid_Iterator *it;
390
391 EVAS_OBJECT_GRID_DATA_GET_OR_RETURN_VAL(o, priv, NULL);
392
393 if (!priv->children) return NULL;
394
395 it = calloc(1, sizeof(Evas_Object_Grid_Iterator));
396 if (!it) return NULL;
397
398 EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
399
400 it->real_iterator = eina_list_iterator_new(priv->children);
401 it->grid = o;
402
403 it->iterator.next = FUNC_ITERATOR_NEXT(_evas_object_grid_iterator_next);
404 it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(_evas_object_grid_iterator_get_container);
405 it->iterator.free = FUNC_ITERATOR_FREE(_evas_object_grid_iterator_free);
406
407 return &it->iterator;
408}
409
410EAPI Eina_Accessor *
411evas_object_grid_accessor_new(const Evas_Object *o)
412{
413 Evas_Object_Grid_Accessor *it;
414
415 EVAS_OBJECT_GRID_DATA_GET_OR_RETURN_VAL(o, priv, NULL);
416
417 if (!priv->children) return NULL;
418
419 it = calloc(1, sizeof(Evas_Object_Grid_Accessor));
420 if (!it) return NULL;
421
422 EINA_MAGIC_SET(&it->accessor, EINA_MAGIC_ACCESSOR);
423
424 it->real_accessor = eina_list_accessor_new(priv->children);
425 it->grid = o;
426
427 it->accessor.get_at = FUNC_ACCESSOR_GET_AT(_evas_object_grid_accessor_get_at);
428 it->accessor.get_container = FUNC_ACCESSOR_GET_CONTAINER(_evas_object_grid_accessor_get_container);
429 it->accessor.free = FUNC_ACCESSOR_FREE(_evas_object_grid_accessor_free);
430
431 return &it->accessor;
432}
433
434EAPI Eina_List *
435evas_object_grid_children_get(const Evas_Object *o)
436{
437 Eina_List *new_list = NULL, *l;
438 Evas_Object_Grid_Option *opt;
439
440 EVAS_OBJECT_GRID_DATA_GET_OR_RETURN_VAL(o, priv, NULL);
441
442 EINA_LIST_FOREACH(priv->children, l, opt)
443 new_list = eina_list_append(new_list, opt->obj);
444
445 return new_list;
446}
447
448EAPI Eina_Bool
449evas_object_grid_mirrored_get(const Evas_Object *obj)
450{
451 EVAS_OBJECT_GRID_DATA_GET_OR_RETURN_VAL(obj, priv, EINA_FALSE);
452 return priv->is_mirrored;
453}
454
455EAPI void
456evas_object_grid_mirrored_set(Evas_Object *obj, Eina_Bool mirrored)
457{
458 EVAS_OBJECT_GRID_DATA_GET_OR_RETURN(obj, priv);
459 mirrored = !!mirrored;
460 if (priv->is_mirrored != mirrored)
461 {
462 priv->is_mirrored = mirrored;
463 _evas_object_grid_smart_calculate(obj);
464 }
465}
diff --git a/libraries/evas/src/lib/canvas/evas_object_image.c b/libraries/evas/src/lib/canvas/evas_object_image.c
deleted file mode 100644
index 4ebea08..0000000
--- a/libraries/evas/src/lib/canvas/evas_object_image.c
+++ /dev/null
@@ -1,3957 +0,0 @@
1#ifdef HAVE_CONFIG_H
2# include "config.h" /* so that EAPI in Evas.h is correctly defined */
3#endif
4
5#include <sys/types.h>
6#include <unistd.h>
7#include <stdlib.h>
8#ifdef HAVE_SYS_MMAN_H
9# include <sys/mman.h>
10#endif
11#include <math.h>
12
13#include "evas_common.h"
14#include "evas_private.h"
15#include "../engines/common/evas_convert_color.h"
16#include "../engines/common/evas_convert_colorspace.h"
17#include "../engines/common/evas_convert_yuv.h"
18
19#define VERBOSE_PROXY_ERROR 1
20
21/* private magic number for image objects */
22static const char o_type[] = "image";
23
24/* private struct for rectangle object internal data */
25typedef struct _Evas_Object_Image Evas_Object_Image;
26
27struct _Evas_Object_Image
28{
29 DATA32 magic;
30
31 struct {
32 int spread;
33 Evas_Coord_Rectangle fill;
34 struct {
35 short w, h, stride;
36 } image;
37 struct {
38 short l, r, t, b;
39 unsigned char fill;
40 double scale;
41 } border;
42
43 Evas_Object *source;
44 Evas_Map *defmap;
45 const char *file;
46 const char *key;
47 int frame;
48 Evas_Colorspace cspace;
49
50 unsigned char smooth_scale : 1;
51 unsigned char has_alpha :1;
52 unsigned char opaque :1;
53 unsigned char opaque_valid :1;
54 } cur, prev;
55
56 int pixels_checked_out;
57 int load_error;
58 Eina_List *pixel_updates;
59
60 struct {
61 unsigned char scale_down_by;
62 double dpi;
63 short w, h;
64 struct {
65 short x, y, w, h;
66 } region;
67 Eina_Bool orientation : 1;
68 } load_opts;
69
70 struct {
71 Evas_Object_Image_Pixels_Get_Cb get_pixels;
72 void *get_pixels_data;
73 } func;
74
75 Evas_Video_Surface video;
76
77 const char *tmpf;
78 int tmpf_fd;
79
80 Evas_Image_Scale_Hint scale_hint;
81 Evas_Image_Content_Hint content_hint;
82
83 void *engine_data;
84
85 unsigned char changed : 1;
86 unsigned char dirty_pixels : 1;
87 unsigned char filled : 1;
88 unsigned char proxyrendering : 1;
89 unsigned char preloading : 1;
90 unsigned char video_rendering : 1;
91 unsigned char video_surface : 1;
92 unsigned char video_visible : 1;
93 unsigned char created : 1;
94};
95
96/* private methods for image objects */
97static void evas_object_image_unload(Evas_Object *obj, Eina_Bool dirty);
98static void evas_object_image_load(Evas_Object *obj);
99static Evas_Coord evas_object_image_figure_x_fill(Evas_Object *obj, Evas_Coord start, Evas_Coord size, Evas_Coord *size_ret);
100static Evas_Coord evas_object_image_figure_y_fill(Evas_Object *obj, Evas_Coord start, Evas_Coord size, Evas_Coord *size_ret);
101
102static void evas_object_image_init(Evas_Object *obj);
103static void *evas_object_image_new(void);
104static void evas_object_image_render(Evas_Object *obj, void *output, void *context, void *surface, int x, int y);
105static void evas_object_image_free(Evas_Object *obj);
106static void evas_object_image_render_pre(Evas_Object *obj);
107static void evas_object_image_render_post(Evas_Object *obj);
108
109static unsigned int evas_object_image_id_get(Evas_Object *obj);
110static unsigned int evas_object_image_visual_id_get(Evas_Object *obj);
111static void *evas_object_image_engine_data_get(Evas_Object *obj);
112
113static int evas_object_image_is_opaque(Evas_Object *obj);
114static int evas_object_image_was_opaque(Evas_Object *obj);
115static int evas_object_image_is_inside(Evas_Object *obj, Evas_Coord x, Evas_Coord y);
116static int evas_object_image_has_opaque_rect(Evas_Object *obj);
117static int evas_object_image_get_opaque_rect(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h);
118static int evas_object_image_can_map(Evas_Object *obj);
119
120static void *evas_object_image_data_convert_internal(Evas_Object_Image *o, void *data, Evas_Colorspace to_cspace);
121static void evas_object_image_filled_resize_listener(void *data, Evas *e, Evas_Object *obj, void *einfo);
122
123static void _proxy_unset(Evas_Object *proxy);
124static void _proxy_set(Evas_Object *proxy, Evas_Object *src);
125static void _proxy_error(Evas_Object *proxy, void *context, void *output, void *surface, int x, int y);
126
127static void _cleanup_tmpf(Evas_Object *obj);
128
129static const Evas_Object_Func object_func =
130{
131 /* methods (compulsory) */
132 evas_object_image_free,
133 evas_object_image_render,
134 evas_object_image_render_pre,
135 evas_object_image_render_post,
136 evas_object_image_id_get,
137 evas_object_image_visual_id_get,
138 evas_object_image_engine_data_get,
139 /* these are optional. NULL = nothing */
140 NULL,
141 NULL,
142 NULL,
143 NULL,
144 evas_object_image_is_opaque,
145 evas_object_image_was_opaque,
146 evas_object_image_is_inside,
147 NULL,
148 NULL,
149 NULL,
150 evas_object_image_has_opaque_rect,
151 evas_object_image_get_opaque_rect,
152 evas_object_image_can_map
153};
154
155EVAS_MEMPOOL(_mp_obj);
156
157static void
158_evas_object_image_cleanup(Evas_Object *obj, Evas_Object_Image *o)
159{
160 if ((o->preloading) && (o->engine_data))
161 {
162 o->preloading = 0;
163 obj->layer->evas->engine.func->image_data_preload_cancel(obj->layer->evas->engine.data.output,
164 o->engine_data,
165 obj);
166 }
167 if (o->tmpf) _cleanup_tmpf(obj);
168 if (o->cur.source) _proxy_unset(obj);
169}
170
171EAPI Evas_Object *
172evas_object_image_add(Evas *e)
173{
174 Evas_Object *obj;
175 Evas_Object_Image *o;
176
177 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
178 return NULL;
179 MAGIC_CHECK_END();
180 obj = evas_object_new(e);
181 evas_object_image_init(obj);
182 evas_object_inject(obj, e);
183 o = (Evas_Object_Image *)(obj->object_data);
184 o->cur.cspace = obj->layer->evas->engine.func->image_colorspace_get(obj->layer->evas->engine.data.output,
185 o->engine_data);
186 return obj;
187}
188
189EAPI Evas_Object *
190evas_object_image_filled_add(Evas *e)
191{
192 Evas_Object *obj;
193 obj = evas_object_image_add(e);
194 evas_object_image_filled_set(obj, 1);
195 return obj;
196}
197
198static void
199_cleanup_tmpf(Evas_Object *obj)
200{
201#ifdef HAVE_SYS_MMAN_H
202 Evas_Object_Image *o;
203
204 o = (Evas_Object_Image *)(obj->object_data);
205 if (!o->tmpf) return;
206#ifdef __linux__
207#else
208 unlink(o->tmpf);
209#endif
210 if (o->tmpf_fd >= 0) close(o->tmpf_fd);
211 eina_stringshare_del(o->tmpf);
212 o->tmpf_fd = -1;
213 o->tmpf = NULL;
214#else
215 (void) obj;
216#endif
217}
218
219static void
220_create_tmpf(Evas_Object *obj, void *data, int size, char *format __UNUSED__)
221{
222#ifdef HAVE_SYS_MMAN_H
223 Evas_Object_Image *o;
224 char buf[4096];
225 void *dst;
226 int fd = -1;
227
228 o = (Evas_Object_Image *)(obj->object_data);
229#ifdef __linux__
230 snprintf(buf, sizeof(buf), "/dev/shm/.evas-tmpf-%i-%p-%i-XXXXXX",
231 (int)getpid(), data, (int)size);
232 fd = mkstemp(buf);
233#endif
234 if (fd < 0)
235 {
236 snprintf(buf, sizeof(buf), "/tmp/.evas-tmpf-%i-%p-%i-XXXXXX",
237 (int)getpid(), data, (int)size);
238 fd = mkstemp(buf);
239 }
240 if (fd < 0) return;
241 if (ftruncate(fd, size) < 0)
242 {
243 unlink(buf);
244 close(fd);
245 return;
246 }
247 unlink(buf);
248
249 eina_mmap_safety_enabled_set(EINA_TRUE);
250
251 dst = mmap(NULL, size,
252 PROT_READ | PROT_WRITE,
253 MAP_SHARED,
254 fd, 0);
255 if (dst == MAP_FAILED)
256 {
257 close(fd);
258 return;
259 }
260 o->tmpf_fd = fd;
261#ifdef __linux__
262 snprintf(buf, sizeof(buf), "/proc/%li/fd/%i", (long)getpid(), fd);
263#endif
264 o->tmpf = eina_stringshare_add(buf);
265 memcpy(dst, data, size);
266 munmap(dst, size);
267#else
268 (void) obj;
269 (void) data;
270 (void) size;
271 (void) format;
272#endif
273}
274
275EAPI void
276evas_object_image_memfile_set(Evas_Object *obj, void *data, int size, char *format, char *key)
277{
278 Evas_Object_Image *o;
279
280 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
281 return;
282 MAGIC_CHECK_END();
283 o = (Evas_Object_Image *)(obj->object_data);
284 MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
285 return;
286 MAGIC_CHECK_END();
287 _cleanup_tmpf(obj);
288 evas_object_image_file_set(obj, NULL, NULL);
289 // invalidate the cache effectively
290 evas_object_image_alpha_set(obj, !o->cur.has_alpha);
291 evas_object_image_alpha_set(obj, !o->cur.has_alpha);
292
293 if ((size < 1) || (!data)) return;
294
295 _create_tmpf(obj, data, size, format);
296 evas_object_image_file_set(obj, o->tmpf, key);
297 if (!o->engine_data)
298 {
299 ERR("unable to load '%s' from memory", o->tmpf);
300 _cleanup_tmpf(obj);
301 return;
302 }
303}
304
305EAPI void
306evas_object_image_file_set(Evas_Object *obj, const char *file, const char *key)
307{
308 Evas_Object_Image *o;
309 Evas_Image_Load_Opts lo;
310
311 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
312 return;
313 MAGIC_CHECK_END();
314 o = (Evas_Object_Image *)(obj->object_data);
315 MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
316 return;
317 MAGIC_CHECK_END();
318 if ((o->tmpf) && (file != o->tmpf)) _cleanup_tmpf(obj);
319 if ((o->cur.file) && (file) && (!strcmp(o->cur.file, file)))
320 {
321 if ((!o->cur.key) && (!key))
322 return;
323 if ((o->cur.key) && (key) && (!strcmp(o->cur.key, key)))
324 return;
325 }
326/*
327 * WTF? why cancel a null image preload? this is just silly (tm)
328 if (!o->engine_data)
329 obj->layer->evas->engine.func->image_data_preload_cancel(obj->layer->evas->engine.data.output,
330 o->engine_data,
331 obj);
332 */
333 if (o->cur.source) _proxy_unset(obj);
334 if (o->cur.file) eina_stringshare_del(o->cur.file);
335 if (o->cur.key) eina_stringshare_del(o->cur.key);
336 if (file) o->cur.file = eina_stringshare_add(file);
337 else o->cur.file = NULL;
338 if (key) o->cur.key = eina_stringshare_add(key);
339 else o->cur.key = NULL;
340 o->prev.file = NULL;
341 o->prev.key = NULL;
342 if (o->engine_data)
343 {
344 if (o->preloading)
345 {
346 o->preloading = 0;
347 obj->layer->evas->engine.func->image_data_preload_cancel(obj->layer->evas->engine.data.output,
348 o->engine_data,
349 obj);
350 }
351 obj->layer->evas->engine.func->image_free(obj->layer->evas->engine.data.output,
352 o->engine_data);
353 }
354 o->load_error = EVAS_LOAD_ERROR_NONE;
355 lo.scale_down_by = o->load_opts.scale_down_by;
356 lo.dpi = o->load_opts.dpi;
357 lo.w = o->load_opts.w;
358 lo.h = o->load_opts.h;
359 lo.region.x = o->load_opts.region.x;
360 lo.region.y = o->load_opts.region.y;
361 lo.region.w = o->load_opts.region.w;
362 lo.region.h = o->load_opts.region.h;
363 lo.orientation = o->load_opts.orientation;
364 o->engine_data = obj->layer->evas->engine.func->image_load(obj->layer->evas->engine.data.output,
365 o->cur.file,
366 o->cur.key,
367 &o->load_error,
368 &lo);
369 if (o->engine_data)
370 {
371 int w, h;
372 int stride;
373
374 obj->layer->evas->engine.func->image_size_get(obj->layer->evas->engine.data.output,
375 o->engine_data, &w, &h);
376 if (obj->layer->evas->engine.func->image_stride_get)
377 obj->layer->evas->engine.func->image_stride_get(obj->layer->evas->engine.data.output,
378 o->engine_data, &stride);
379 else
380 stride = w * 4;
381 o->cur.has_alpha = obj->layer->evas->engine.func->image_alpha_get(obj->layer->evas->engine.data.output,
382 o->engine_data);
383 o->cur.cspace = obj->layer->evas->engine.func->image_colorspace_get(obj->layer->evas->engine.data.output,
384 o->engine_data);
385 o->cur.image.w = w;
386 o->cur.image.h = h;
387 o->cur.image.stride = stride;
388 }
389 else
390 {
391 if (o->load_error == EVAS_LOAD_ERROR_NONE)
392 o->load_error = EVAS_LOAD_ERROR_GENERIC;
393 o->cur.has_alpha = 1;
394 o->cur.cspace = EVAS_COLORSPACE_ARGB8888;
395 o->cur.image.w = 0;
396 o->cur.image.h = 0;
397 o->cur.image.stride = 0;
398 }
399 o->changed = 1;
400 evas_object_change(obj);
401}
402
403EAPI void
404evas_object_image_file_get(const Evas_Object *obj, const char **file, const char **key)
405{
406 Evas_Object_Image *o;
407
408 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
409 if (file) *file = NULL;
410 if (key) *key = NULL;
411 return;
412 MAGIC_CHECK_END();
413 o = (Evas_Object_Image *)(obj->object_data);
414 MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
415 if (file) *file = NULL;
416 if (key) *key = NULL;
417 return;
418 MAGIC_CHECK_END();
419 if (file) *file = o->cur.file;
420 if (key) *key = o->cur.key;
421}
422
423EAPI Eina_Bool
424evas_object_image_source_set(Evas_Object *obj, Evas_Object *src)
425{
426 Evas_Object_Image *o;
427
428 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
429 return EINA_FALSE;
430 MAGIC_CHECK_END();
431 o = obj->object_data;
432 MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
433 return EINA_FALSE;
434 MAGIC_CHECK_END();
435
436 if (src == obj) return EINA_FALSE;
437 if (o->cur.source == src) return EINA_TRUE;
438
439 _evas_object_image_cleanup(obj, o);
440 /* Kill the image if any */
441 if (o->cur.file || o->cur.key)
442 evas_object_image_file_set(obj, NULL, NULL);
443
444 if (src)
445 {
446 _proxy_set(obj, src);
447 }
448
449 return EINA_TRUE;
450}
451
452
453EAPI Evas_Object *
454evas_object_image_source_get(Evas_Object *obj)
455{
456 Evas_Object_Image *o;
457
458 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
459 return NULL;
460 MAGIC_CHECK_END();
461 o = obj->object_data;
462 MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
463 return NULL;
464 MAGIC_CHECK_END();
465
466 return o->cur.source;
467}
468
469EAPI Eina_Bool
470evas_object_image_source_unset(Evas_Object *obj)
471{
472 return evas_object_image_source_set(obj, NULL);
473}
474
475EAPI void
476evas_object_image_border_set(Evas_Object *obj, int l, int r, int t, int b)
477{
478 Evas_Object_Image *o;
479
480 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
481 return;
482 MAGIC_CHECK_END();
483 o = (Evas_Object_Image *)(obj->object_data);
484 MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
485 return;
486 MAGIC_CHECK_END();
487 if (l < 0) l = 0;
488 if (r < 0) r = 0;
489 if (t < 0) t = 0;
490 if (b < 0) b = 0;
491 if ((o->cur.border.l == l) &&
492 (o->cur.border.r == r) &&
493 (o->cur.border.t == t) &&
494 (o->cur.border.b == b)) return;
495 o->cur.border.l = l;
496 o->cur.border.r = r;
497 o->cur.border.t = t;
498 o->cur.border.b = b;
499 o->cur.opaque_valid = 0;
500 o->changed = 1;
501 evas_object_change(obj);
502}
503
504EAPI void
505evas_object_image_border_get(const Evas_Object *obj, int *l, int *r, int *t, int *b)
506{
507 Evas_Object_Image *o;
508
509 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
510 if (l) *l = 0;
511 if (r) *r = 0;
512 if (t) *t = 0;
513 if (b) *b = 0;
514 return;
515 MAGIC_CHECK_END();
516 o = (Evas_Object_Image *)(obj->object_data);
517 MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
518 if (l) *l = 0;
519 if (r) *r = 0;
520 if (t) *t = 0;
521 if (b) *b = 0;
522 return;
523 MAGIC_CHECK_END();
524 if (l) *l = o->cur.border.l;
525 if (r) *r = o->cur.border.r;
526 if (t) *t = o->cur.border.t;
527 if (b) *b = o->cur.border.b;
528}
529
530EAPI void
531evas_object_image_border_center_fill_set(Evas_Object *obj, Evas_Border_Fill_Mode fill)
532{
533 Evas_Object_Image *o;
534
535 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
536 return;
537 MAGIC_CHECK_END();
538 o = (Evas_Object_Image *)(obj->object_data);
539 MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
540 return;
541 MAGIC_CHECK_END();
542 if (fill == o->cur.border.fill) return;
543 o->cur.border.fill = fill;
544 o->changed = 1;
545 evas_object_change(obj);
546}
547
548EAPI Evas_Border_Fill_Mode
549evas_object_image_border_center_fill_get(const Evas_Object *obj)
550{
551 Evas_Object_Image *o;
552
553 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
554 return 0;
555 MAGIC_CHECK_END();
556 o = (Evas_Object_Image *)(obj->object_data);
557 MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
558 return 0;
559 MAGIC_CHECK_END();
560 return o->cur.border.fill;
561}
562
563EAPI void
564evas_object_image_filled_set(Evas_Object *obj, Eina_Bool setting)
565{
566 Evas_Object_Image *o;
567
568 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
569 return;
570 MAGIC_CHECK_END();
571 o = (Evas_Object_Image *)(obj->object_data);
572 MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
573 return;
574 MAGIC_CHECK_END();
575
576 setting = !!setting;
577 if (o->filled == setting) return;
578
579 o->filled = setting;
580 if (!o->filled)
581 evas_object_event_callback_del(obj, EVAS_CALLBACK_RESIZE, evas_object_image_filled_resize_listener);
582 else
583 {
584 Evas_Coord w, h;
585
586 evas_object_geometry_get(obj, NULL, NULL, &w, &h);
587 evas_object_image_fill_set(obj, 0, 0, w, h);
588
589 evas_object_event_callback_add(obj, EVAS_CALLBACK_RESIZE, evas_object_image_filled_resize_listener, NULL);
590 }
591}
592
593EAPI Eina_Bool
594evas_object_image_filled_get(const Evas_Object *obj)
595{
596 Evas_Object_Image *o;
597
598 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
599 return 0;
600 MAGIC_CHECK_END();
601 o = (Evas_Object_Image *)(obj->object_data);
602 MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
603 return 0;
604 MAGIC_CHECK_END();
605
606 return o->filled;
607}
608
609EAPI void
610evas_object_image_border_scale_set(Evas_Object *obj, double scale)
611{
612 Evas_Object_Image *o;
613
614 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
615 return;
616 MAGIC_CHECK_END();
617 o = (Evas_Object_Image *)(obj->object_data);
618 MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
619 return;
620 MAGIC_CHECK_END();
621 if (scale == o->cur.border.scale) return;
622 o->cur.border.scale = scale;
623 o->changed = 1;
624 evas_object_change(obj);
625}
626
627EAPI double
628evas_object_image_border_scale_get(const Evas_Object *obj)
629{
630 Evas_Object_Image *o;
631
632 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
633 return 1.0;
634 MAGIC_CHECK_END();
635 o = (Evas_Object_Image *)(obj->object_data);
636 MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
637 return 1.0;
638 MAGIC_CHECK_END();
639 return o->cur.border.scale;
640}
641
642EAPI void
643evas_object_image_fill_set(Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h)
644{
645 Evas_Object_Image *o;
646
647 if (w < 0) w = -w;
648 if (h < 0) h = -h;
649 if (w == 0) return;
650 if (h == 0) return;
651 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
652 return;
653 MAGIC_CHECK_END();
654 o = (Evas_Object_Image *)(obj->object_data);
655 MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
656 return;
657 MAGIC_CHECK_END();
658 if ((o->cur.fill.x == x) &&
659 (o->cur.fill.y == y) &&
660 (o->cur.fill.w == w) &&
661 (o->cur.fill.h == h)) return;
662 o->cur.fill.x = x;
663 o->cur.fill.y = y;
664 o->cur.fill.w = w;
665 o->cur.fill.h = h;
666 o->cur.opaque_valid = 0;
667 o->changed = 1;
668 evas_object_change(obj);
669}
670
671EAPI void
672evas_object_image_fill_get(const Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h)
673{
674 Evas_Object_Image *o;
675
676 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
677 if (x) *x = 0;
678 if (y) *y = 0;
679 if (w) *w = 0;
680 if (h) *h = 0;
681 return;
682 MAGIC_CHECK_END();
683 o = (Evas_Object_Image *)(obj->object_data);
684 MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
685 if (x) *x = 0;
686 if (y) *y = 0;
687 if (w) *w = 0;
688 if (h) *h = 0;
689 return;
690 MAGIC_CHECK_END();
691 if (x) *x = o->cur.fill.x;
692 if (y) *y = o->cur.fill.y;
693 if (w) *w = o->cur.fill.w;
694 if (h) *h = o->cur.fill.h;
695}
696
697
698EAPI void
699evas_object_image_fill_spread_set(Evas_Object *obj, Evas_Fill_Spread spread)
700{
701 Evas_Object_Image *o;
702
703 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
704 return;
705 MAGIC_CHECK_END();
706 o = (Evas_Object_Image *)(obj->object_data);
707 MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
708 return;
709 MAGIC_CHECK_END();
710 if (spread == (Evas_Fill_Spread)o->cur.spread) return;
711 o->cur.spread = spread;
712 o->changed = 1;
713 evas_object_change(obj);
714}
715
716EAPI Evas_Fill_Spread
717evas_object_image_fill_spread_get(const Evas_Object *obj)
718{
719 Evas_Object_Image *o;
720
721 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
722 return EVAS_TEXTURE_REPEAT;
723 MAGIC_CHECK_END();
724 o = (Evas_Object_Image *)(obj->object_data);
725 MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
726 return EVAS_TEXTURE_REPEAT;
727 MAGIC_CHECK_END();
728 return (Evas_Fill_Spread)o->cur.spread;
729}
730
731EAPI void
732evas_object_image_size_set(Evas_Object *obj, int w, int h)
733{
734 Evas_Object_Image *o;
735 int stride = 0;
736
737 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
738 return;
739 MAGIC_CHECK_END();
740 o = (Evas_Object_Image *)(obj->object_data);
741 MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
742 return;
743 MAGIC_CHECK_END();
744 _evas_object_image_cleanup(obj, o);
745 if (w < 1) w = 1;
746 if (h < 1) h = 1;
747 if (w > 32768) return;
748 if (h > 32768) return;
749 if ((w == o->cur.image.w) &&
750 (h == o->cur.image.h)) return;
751 o->cur.image.w = w;
752 o->cur.image.h = h;
753 if (o->engine_data)
754 o->engine_data = obj->layer->evas->engine.func->image_size_set(obj->layer->evas->engine.data.output,
755 o->engine_data,
756 w, h);
757 else
758 o->engine_data = obj->layer->evas->engine.func->image_new_from_copied_data
759 (obj->layer->evas->engine.data.output, w, h, NULL, o->cur.has_alpha,
760 o->cur.cspace);
761
762 if (o->engine_data)
763 {
764 if (obj->layer->evas->engine.func->image_scale_hint_set)
765 obj->layer->evas->engine.func->image_scale_hint_set
766 (obj->layer->evas->engine.data.output,
767 o->engine_data, o->scale_hint);
768 if (obj->layer->evas->engine.func->image_content_hint_set)
769 obj->layer->evas->engine.func->image_content_hint_set
770 (obj->layer->evas->engine.data.output,
771 o->engine_data, o->content_hint);
772 if (obj->layer->evas->engine.func->image_stride_get)
773 obj->layer->evas->engine.func->image_stride_get
774 (obj->layer->evas->engine.data.output,
775 o->engine_data, &stride);
776 else
777 stride = w * 4;
778 }
779 else
780 stride = w * 4;
781 o->cur.image.stride = stride;
782
783/* FIXME - in engine call above
784 if (o->engine_data)
785 o->engine_data = obj->layer->evas->engine.func->image_alpha_set(obj->layer->evas->engine.data.output,
786 o->engine_data,
787 o->cur.has_alpha);
788*/
789 EVAS_OBJECT_IMAGE_FREE_FILE_AND_KEY(o);
790 o->changed = 1;
791 evas_object_change(obj);
792}
793
794EAPI void
795evas_object_image_size_get(const Evas_Object *obj, int *w, int *h)
796{
797 Evas_Object_Image *o;
798
799 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
800 if (w) *w = 0;
801 if (h) *h = 0;
802 return;
803 MAGIC_CHECK_END();
804 o = (Evas_Object_Image *)(obj->object_data);
805 MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
806 if (w) *w = 0;
807 if (h) *h = 0;
808 return;
809 MAGIC_CHECK_END();
810 if (w) *w = o->cur.image.w;
811 if (h) *h = o->cur.image.h;
812}
813
814EAPI int
815evas_object_image_stride_get(const Evas_Object *obj)
816{
817 Evas_Object_Image *o;
818
819 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
820 return 0;
821 MAGIC_CHECK_END();
822 o = (Evas_Object_Image *)(obj->object_data);
823 MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
824 return 0;
825 MAGIC_CHECK_END();
826 return o->cur.image.stride;
827}
828
829EAPI Evas_Load_Error
830evas_object_image_load_error_get(const Evas_Object *obj)
831{
832 Evas_Object_Image *o;
833
834 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
835 return 0;
836 MAGIC_CHECK_END();
837 o = (Evas_Object_Image *)(obj->object_data);
838 MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
839 return 0;
840 MAGIC_CHECK_END();
841 return o->load_error;
842}
843
844EAPI void *
845evas_object_image_data_convert(Evas_Object *obj, Evas_Colorspace to_cspace)
846{
847 Evas_Object_Image *o;
848 DATA32 *data;
849
850 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
851 return NULL;
852 MAGIC_CHECK_END();
853 o = (Evas_Object_Image *)(obj->object_data);
854 MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
855 return NULL;
856 MAGIC_CHECK_END();
857 if ((o->preloading) && (o->engine_data))
858 {
859 o->preloading = 0;
860 obj->layer->evas->engine.func->image_data_preload_cancel(obj->layer->evas->engine.data.output,
861 o->engine_data,
862 obj);
863 }
864 if (!o->engine_data) return NULL;
865 if (o->video_surface)
866 o->video.update_pixels(o->video.data, obj, &o->video);
867 if (o->cur.cspace == to_cspace) return NULL;
868 data = NULL;
869 o->engine_data = obj->layer->evas->engine.func->image_data_get(obj->layer->evas->engine.data.output,
870 o->engine_data,
871 0,
872 &data,
873 &o->load_error);
874 return evas_object_image_data_convert_internal(o, data, to_cspace);
875}
876
877EAPI void
878evas_object_image_data_set(Evas_Object *obj, void *data)
879{
880 Evas_Object_Image *o;
881 void *p_data;
882
883 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
884 return;
885 MAGIC_CHECK_END();
886 o = (Evas_Object_Image *)(obj->object_data);
887 MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
888 return;
889 MAGIC_CHECK_END();
890 _evas_object_image_cleanup(obj, o);
891#ifdef EVAS_FRAME_QUEUING
892 if (o->engine_data)
893 evas_common_pipe_op_image_flush(o->engine_data);
894#endif
895 p_data = o->engine_data;
896 if (data)
897 {
898 if (o->engine_data)
899 o->engine_data = obj->layer->evas->engine.func->image_data_put(obj->layer->evas->engine.data.output,
900 o->engine_data,
901 data);
902 else
903 o->engine_data = obj->layer->evas->engine.func->image_new_from_data(obj->layer->evas->engine.data.output,
904 o->cur.image.w,
905 o->cur.image.h,
906 data,
907 o->cur.has_alpha,
908 o->cur.cspace);
909 if (o->engine_data)
910 {
911 int stride = 0;
912
913 if (obj->layer->evas->engine.func->image_scale_hint_set)
914 obj->layer->evas->engine.func->image_scale_hint_set
915 (obj->layer->evas->engine.data.output,
916 o->engine_data, o->scale_hint);
917 if (obj->layer->evas->engine.func->image_content_hint_set)
918 obj->layer->evas->engine.func->image_content_hint_set
919 (obj->layer->evas->engine.data.output,
920 o->engine_data, o->content_hint);
921 if (obj->layer->evas->engine.func->image_stride_get)
922 obj->layer->evas->engine.func->image_stride_get
923 (obj->layer->evas->engine.data.output,
924 o->engine_data, &stride);
925 else
926 stride = o->cur.image.w * 4;
927 o->cur.image.stride = stride;
928 }
929 }
930 else
931 {
932 if (o->engine_data)
933 obj->layer->evas->engine.func->image_free(obj->layer->evas->engine.data.output,
934 o->engine_data);
935 o->load_error = EVAS_LOAD_ERROR_NONE;
936 o->cur.image.w = 0;
937 o->cur.image.h = 0;
938 o->cur.image.stride = 0;
939 o->engine_data = NULL;
940 }
941/* FIXME - in engine call above
942 if (o->engine_data)
943 o->engine_data = obj->layer->evas->engine.func->image_alpha_set(obj->layer->evas->engine.data.output,
944 o->engine_data,
945 o->cur.has_alpha);
946*/
947 if (o->pixels_checked_out > 0) o->pixels_checked_out--;
948 if (p_data != o->engine_data)
949 {
950 EVAS_OBJECT_IMAGE_FREE_FILE_AND_KEY(o);
951 o->pixels_checked_out = 0;
952 }
953 o->changed = 1;
954 evas_object_change(obj);
955}
956
957EAPI void *
958evas_object_image_data_get(const Evas_Object *obj, Eina_Bool for_writing)
959{
960 Evas_Object_Image *o;
961 DATA32 *data;
962
963 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
964 return NULL;
965 MAGIC_CHECK_END();
966 o = (Evas_Object_Image *)(obj->object_data);
967 MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
968 return NULL;
969 MAGIC_CHECK_END();
970 if (!o->engine_data) return NULL;
971#ifdef EVAS_FRAME_QUEUING
972 evas_common_pipe_op_image_flush(o->engine_data);
973#endif
974
975 data = NULL;
976 if (obj->layer->evas->engine.func->image_scale_hint_set)
977 obj->layer->evas->engine.func->image_scale_hint_set
978 (obj->layer->evas->engine.data.output,
979 o->engine_data, o->scale_hint);
980 if (obj->layer->evas->engine.func->image_content_hint_set)
981 obj->layer->evas->engine.func->image_content_hint_set
982 (obj->layer->evas->engine.data.output,
983 o->engine_data, o->content_hint);
984 o->engine_data = obj->layer->evas->engine.func->image_data_get(obj->layer->evas->engine.data.output,
985 o->engine_data,
986 for_writing,
987 &data,
988 &o->load_error);
989
990 /* if we fail to get engine_data, we have to return NULL */
991 if (!o->engine_data) return NULL;
992
993 if (o->engine_data)
994 {
995 int stride = 0;
996
997 if (obj->layer->evas->engine.func->image_stride_get)
998 obj->layer->evas->engine.func->image_stride_get
999 (obj->layer->evas->engine.data.output,
1000 o->engine_data, &stride);
1001 else
1002 stride = o->cur.image.w * 4;
1003 o->cur.image.stride = stride;
1004 }
1005 o->pixels_checked_out++;
1006 if (for_writing)
1007 {
1008 EVAS_OBJECT_IMAGE_FREE_FILE_AND_KEY(o);
1009 }
1010
1011 return data;
1012}
1013
1014EAPI void
1015evas_object_image_preload(Evas_Object *obj, Eina_Bool cancel)
1016{
1017 Evas_Object_Image *o;
1018
1019 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1020 return ;
1021 MAGIC_CHECK_END();
1022 o = (Evas_Object_Image *)(obj->object_data);
1023 MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
1024 return ;
1025 MAGIC_CHECK_END();
1026 if (!o->engine_data)
1027 {
1028 o->preloading = 1;
1029 evas_object_inform_call_image_preloaded(obj);
1030 return;
1031 }
1032 // FIXME: if already busy preloading, then dont request again until
1033 // preload done
1034 if (cancel)
1035 {
1036 if (o->preloading)
1037 {
1038 o->preloading = 0;
1039 obj->layer->evas->engine.func->image_data_preload_cancel(obj->layer->evas->engine.data.output,
1040 o->engine_data,
1041 obj);
1042 }
1043 }
1044 else
1045 {
1046 if (!o->preloading)
1047 {
1048 o->preloading = 1;
1049 obj->layer->evas->engine.func->image_data_preload_request(obj->layer->evas->engine.data.output,
1050 o->engine_data,
1051 obj);
1052 }
1053 }
1054}
1055
1056EAPI void
1057evas_object_image_data_copy_set(Evas_Object *obj, void *data)
1058{
1059 Evas_Object_Image *o;
1060
1061 if (!data) return;
1062 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1063 return;
1064 MAGIC_CHECK_END();
1065 o = (Evas_Object_Image *)(obj->object_data);
1066 MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
1067 return;
1068 MAGIC_CHECK_END();
1069 _evas_object_image_cleanup(obj, o);
1070 if ((o->cur.image.w <= 0) ||
1071 (o->cur.image.h <= 0)) return;
1072 if (o->engine_data)
1073 obj->layer->evas->engine.func->image_free(obj->layer->evas->engine.data.output,
1074 o->engine_data);
1075 o->engine_data = obj->layer->evas->engine.func->image_new_from_copied_data(obj->layer->evas->engine.data.output,
1076 o->cur.image.w,
1077 o->cur.image.h,
1078 data,
1079 o->cur.has_alpha,
1080 o->cur.cspace);
1081 if (o->engine_data)
1082 {
1083 int stride = 0;
1084
1085 o->engine_data = obj->layer->evas->engine.func->image_alpha_set(obj->layer->evas->engine.data.output,
1086 o->engine_data,
1087 o->cur.has_alpha);
1088 if (obj->layer->evas->engine.func->image_scale_hint_set)
1089 obj->layer->evas->engine.func->image_scale_hint_set
1090 (obj->layer->evas->engine.data.output,
1091 o->engine_data, o->scale_hint);
1092 if (obj->layer->evas->engine.func->image_content_hint_set)
1093 obj->layer->evas->engine.func->image_content_hint_set
1094 (obj->layer->evas->engine.data.output,
1095 o->engine_data, o->content_hint);
1096 if (obj->layer->evas->engine.func->image_stride_get)
1097 obj->layer->evas->engine.func->image_stride_get
1098 (obj->layer->evas->engine.data.output,
1099 o->engine_data, &stride);
1100 else
1101 stride = o->cur.image.w * 4;
1102 o->cur.image.stride = stride;
1103 }
1104 o->pixels_checked_out = 0;
1105 EVAS_OBJECT_IMAGE_FREE_FILE_AND_KEY(o);
1106}
1107
1108EAPI void
1109evas_object_image_data_update_add(Evas_Object *obj, int x, int y, int w, int h)
1110{
1111 Evas_Object_Image *o;
1112 Eina_Rectangle *r;
1113
1114 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1115 return;
1116 MAGIC_CHECK_END();
1117 o = (Evas_Object_Image *)(obj->object_data);
1118 MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
1119 return;
1120 MAGIC_CHECK_END();
1121 RECTS_CLIP_TO_RECT(x, y, w, h, 0, 0, o->cur.image.w, o->cur.image.h);
1122 if ((w <= 0) || (h <= 0)) return;
1123 NEW_RECT(r, x, y, w, h);
1124 if (r) o->pixel_updates = eina_list_append(o->pixel_updates, r);
1125 o->changed = 1;
1126 evas_object_change(obj);
1127}
1128
1129EAPI void
1130evas_object_image_alpha_set(Evas_Object *obj, Eina_Bool has_alpha)
1131{
1132 Evas_Object_Image *o;
1133
1134 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1135 return;
1136 MAGIC_CHECK_END();
1137 o = (Evas_Object_Image *)(obj->object_data);
1138 MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
1139 return;
1140 MAGIC_CHECK_END();
1141 if ((o->preloading) && (o->engine_data))
1142 {
1143 o->preloading = 0;
1144 obj->layer->evas->engine.func->image_data_preload_cancel(obj->layer->evas->engine.data.output,
1145 o->engine_data,
1146 obj);
1147 }
1148 if (((has_alpha) && (o->cur.has_alpha)) ||
1149 ((!has_alpha) && (!o->cur.has_alpha)))
1150 return;
1151 o->cur.has_alpha = has_alpha;
1152 if (o->engine_data)
1153 {
1154 int stride = 0;
1155
1156#ifdef EVAS_FRAME_QUEUING
1157 evas_common_pipe_op_image_flush(o->engine_data);
1158#endif
1159 o->engine_data = obj->layer->evas->engine.func->image_alpha_set(obj->layer->evas->engine.data.output,
1160 o->engine_data,
1161 o->cur.has_alpha);
1162 if (obj->layer->evas->engine.func->image_scale_hint_set)
1163 obj->layer->evas->engine.func->image_scale_hint_set
1164 (obj->layer->evas->engine.data.output,
1165 o->engine_data, o->scale_hint);
1166 if (obj->layer->evas->engine.func->image_content_hint_set)
1167 obj->layer->evas->engine.func->image_content_hint_set
1168 (obj->layer->evas->engine.data.output,
1169 o->engine_data, o->content_hint);
1170 if (obj->layer->evas->engine.func->image_stride_get)
1171 obj->layer->evas->engine.func->image_stride_get
1172 (obj->layer->evas->engine.data.output,
1173 o->engine_data, &stride);
1174 else
1175 stride = o->cur.image.w * 4;
1176 o->cur.image.stride = stride;
1177 }
1178 evas_object_image_data_update_add(obj, 0, 0, o->cur.image.w, o->cur.image.h);
1179 EVAS_OBJECT_IMAGE_FREE_FILE_AND_KEY(o);
1180}
1181
1182
1183EAPI Eina_Bool
1184evas_object_image_alpha_get(const Evas_Object *obj)
1185{
1186 Evas_Object_Image *o;
1187
1188 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1189 return 0;
1190 MAGIC_CHECK_END();
1191 o = (Evas_Object_Image *)(obj->object_data);
1192 MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
1193 return 0;
1194 MAGIC_CHECK_END();
1195 return o->cur.has_alpha;
1196}
1197
1198EAPI void
1199evas_object_image_smooth_scale_set(Evas_Object *obj, Eina_Bool smooth_scale)
1200{
1201 Evas_Object_Image *o;
1202
1203 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1204 return;
1205 MAGIC_CHECK_END();
1206 o = (Evas_Object_Image *)(obj->object_data);
1207 MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
1208 return;
1209 MAGIC_CHECK_END();
1210 if (((smooth_scale) && (o->cur.smooth_scale)) ||
1211 ((!smooth_scale) && (!o->cur.smooth_scale)))
1212 return;
1213 o->cur.smooth_scale = smooth_scale;
1214 o->changed = 1;
1215 evas_object_change(obj);
1216}
1217
1218EAPI Eina_Bool
1219evas_object_image_smooth_scale_get(const Evas_Object *obj)
1220{
1221 Evas_Object_Image *o;
1222
1223 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1224 return 0;
1225 MAGIC_CHECK_END();
1226 o = (Evas_Object_Image *)(obj->object_data);
1227 MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
1228 return 0;
1229 MAGIC_CHECK_END();
1230 return o->cur.smooth_scale;
1231}
1232
1233EAPI void
1234evas_object_image_reload(Evas_Object *obj)
1235{
1236 Evas_Object_Image *o;
1237
1238 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1239 return;
1240 MAGIC_CHECK_END();
1241 o = (Evas_Object_Image *)(obj->object_data);
1242 MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
1243 return;
1244 MAGIC_CHECK_END();
1245 if ((o->preloading) && (o->engine_data))
1246 {
1247 o->preloading = 0;
1248 obj->layer->evas->engine.func->image_data_preload_cancel(obj->layer->evas->engine.data.output,
1249 o->engine_data,
1250 obj);
1251 }
1252 if ((!o->cur.file) ||
1253 (o->pixels_checked_out > 0)) return;
1254 if (o->engine_data)
1255 o->engine_data = obj->layer->evas->engine.func->image_dirty_region(obj->layer->evas->engine.data.output, o->engine_data, 0, 0, o->cur.image.w, o->cur.image.h);
1256 evas_object_image_unload(obj, 1);
1257 evas_object_inform_call_image_unloaded(obj);
1258 evas_object_image_load(obj);
1259 o->prev.file = NULL;
1260 o->prev.key = NULL;
1261 o->changed = 1;
1262 evas_object_change(obj);
1263}
1264
1265EAPI Eina_Bool
1266evas_object_image_save(const Evas_Object *obj, const char *file, const char *key, const char *flags)
1267{
1268 Evas_Object_Image *o;
1269 DATA32 *data = NULL;
1270 int quality = 80, compress = 9, ok = 0;
1271 RGBA_Image *im;
1272
1273 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1274 return 0;
1275 MAGIC_CHECK_END();
1276 o = (Evas_Object_Image *)(obj->object_data);
1277 MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
1278 return 0;
1279 MAGIC_CHECK_END();
1280
1281 if (!o->engine_data) return 0;
1282 o->engine_data = obj->layer->evas->engine.func->image_data_get(obj->layer->evas->engine.data.output,
1283 o->engine_data,
1284 0,
1285 &data,
1286 &o->load_error);
1287 if (flags)
1288 {
1289 char *p, *pp;
1290 char *tflags;
1291
1292 tflags = alloca(strlen(flags) + 1);
1293 strcpy(tflags, flags);
1294 p = tflags;
1295 while (p)
1296 {
1297 pp = strchr(p, ' ');
1298 if (pp) *pp = 0;
1299 sscanf(p, "quality=%i", &quality);
1300 sscanf(p, "compress=%i", &compress);
1301 if (pp) p = pp + 1;
1302 else break;
1303 }
1304 }
1305 im = (RGBA_Image*) evas_cache_image_data(evas_common_image_cache_get(),
1306 o->cur.image.w,
1307 o->cur.image.h,
1308 data,
1309 o->cur.has_alpha,
1310 EVAS_COLORSPACE_ARGB8888);
1311 if (im)
1312 {
1313 if (o->cur.cspace == EVAS_COLORSPACE_ARGB8888)
1314 im->image.data = data;
1315 else
1316 im->image.data = evas_object_image_data_convert_internal(o,
1317 data,
1318 EVAS_COLORSPACE_ARGB8888);
1319 if (im->image.data)
1320 {
1321 ok = evas_common_save_image_to_file(im, file, key, quality, compress);
1322
1323 if (o->cur.cspace != EVAS_COLORSPACE_ARGB8888)
1324 free(im->image.data);
1325 }
1326
1327 evas_cache_image_drop(&im->cache_entry);
1328 }
1329 return ok;
1330}
1331
1332EAPI Eina_Bool
1333evas_object_image_pixels_import(Evas_Object *obj, Evas_Pixel_Import_Source *pixels)
1334{
1335 Evas_Object_Image *o;
1336
1337 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1338 return 0;
1339 MAGIC_CHECK_END();
1340 o = (Evas_Object_Image *)(obj->object_data);
1341 MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
1342 return 0;
1343 MAGIC_CHECK_END();
1344 _evas_object_image_cleanup(obj, o);
1345 if ((pixels->w != o->cur.image.w) || (pixels->h != o->cur.image.h)) return 0;
1346 switch (pixels->format)
1347 {
1348#if 0
1349 case EVAS_PIXEL_FORMAT_ARGB32:
1350 {
1351 if (o->engine_data)
1352 {
1353 DATA32 *image_pixels = NULL;
1354
1355 o->engine_data =
1356 obj->layer->evas->engine.func->image_data_get(obj->layer->evas->engine.data.output,
1357 o->engine_data,
1358 1,
1359 &image_pixels,
1360 &o->load_error);
1361/* FIXME: need to actualyl support this */
1362/* memcpy(image_pixels, pixels->rows, o->cur.image.w * o->cur.image.h * 4);*/
1363 if (o->engine_data)
1364 o->engine_data =
1365 obj->layer->evas->engine.func->image_data_put(obj->layer->evas->engine.data.output,
1366 o->engine_data,
1367 image_pixels);
1368 if (o->engine_data)
1369 o->engine_data =
1370 obj->layer->evas->engine.func->image_alpha_set(obj->layer->evas->engine.data.output,
1371 o->engine_data,
1372 o->cur.has_alpha);
1373 o->changed = 1;
1374 evas_object_change(obj);
1375 }
1376 }
1377 break;
1378#endif
1379#ifdef BUILD_CONVERT_YUV
1380 case EVAS_PIXEL_FORMAT_YUV420P_601:
1381 {
1382 if (o->engine_data)
1383 {
1384 DATA32 *image_pixels = NULL;
1385
1386 o->engine_data =
1387 obj->layer->evas->engine.func->image_data_get(obj->layer->evas->engine.data.output,
1388 o->engine_data,
1389 1,
1390 &image_pixels,
1391 &o->load_error);
1392 if (image_pixels)
1393 evas_common_convert_yuv_420p_601_rgba((DATA8 **) pixels->rows,
1394 (DATA8 *) image_pixels,
1395 o->cur.image.w,
1396 o->cur.image.h);
1397 if (o->engine_data)
1398 o->engine_data =
1399 obj->layer->evas->engine.func->image_data_put(obj->layer->evas->engine.data.output,
1400 o->engine_data,
1401 image_pixels);
1402 if (o->engine_data)
1403 o->engine_data =
1404 obj->layer->evas->engine.func->image_alpha_set(obj->layer->evas->engine.data.output,
1405 o->engine_data,
1406 o->cur.has_alpha);
1407 o->changed = 1;
1408 evas_object_change(obj);
1409 }
1410 }
1411 break;
1412#endif
1413 default:
1414 return 0;
1415 break;
1416 }
1417 return 1;
1418}
1419
1420EAPI void
1421evas_object_image_pixels_get_callback_set(Evas_Object *obj, Evas_Object_Image_Pixels_Get_Cb func, void *data)
1422{
1423 Evas_Object_Image *o;
1424
1425 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1426 return;
1427 MAGIC_CHECK_END();
1428 o = (Evas_Object_Image *)(obj->object_data);
1429 MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
1430 return;
1431 MAGIC_CHECK_END();
1432 o->func.get_pixels = func;
1433 o->func.get_pixels_data = data;
1434}
1435
1436EAPI void
1437evas_object_image_pixels_dirty_set(Evas_Object *obj, Eina_Bool dirty)
1438{
1439 Evas_Object_Image *o;
1440
1441 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1442 return;
1443 MAGIC_CHECK_END();
1444 o = (Evas_Object_Image *)(obj->object_data);
1445 MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
1446 return;
1447 MAGIC_CHECK_END();
1448 if (dirty) o->dirty_pixels = 1;
1449 else o->dirty_pixels = 0;
1450 o->changed = 1;
1451 evas_object_change(obj);
1452}
1453
1454EAPI Eina_Bool
1455evas_object_image_pixels_dirty_get(const Evas_Object *obj)
1456{
1457 Evas_Object_Image *o;
1458
1459 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1460 return 0;
1461 MAGIC_CHECK_END();
1462 o = (Evas_Object_Image *)(obj->object_data);
1463 MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
1464 return 0;
1465 MAGIC_CHECK_END();
1466 if (o->dirty_pixels) return 1;
1467 return 0;
1468}
1469
1470EAPI void
1471evas_object_image_load_dpi_set(Evas_Object *obj, double dpi)
1472{
1473 Evas_Object_Image *o;
1474
1475 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1476 return;
1477 MAGIC_CHECK_END();
1478 o = (Evas_Object_Image *)(obj->object_data);
1479 MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
1480 return;
1481 MAGIC_CHECK_END();
1482 if (dpi == o->load_opts.dpi) return;
1483 o->load_opts.dpi = dpi;
1484 if (o->cur.file)
1485 {
1486 evas_object_image_unload(obj, 0);
1487 evas_object_inform_call_image_unloaded(obj);
1488 evas_object_image_load(obj);
1489 o->changed = 1;
1490 evas_object_change(obj);
1491 }
1492}
1493
1494EAPI double
1495evas_object_image_load_dpi_get(const Evas_Object *obj)
1496{
1497 Evas_Object_Image *o;
1498
1499 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1500 return 0.0;
1501 MAGIC_CHECK_END();
1502 o = (Evas_Object_Image *)(obj->object_data);
1503 MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
1504 return 0.0;
1505 MAGIC_CHECK_END();
1506 return o->load_opts.dpi;
1507}
1508
1509EAPI void
1510evas_object_image_load_size_set(Evas_Object *obj, int w, int h)
1511{
1512 Evas_Object_Image *o;
1513
1514 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1515 return;
1516 MAGIC_CHECK_END();
1517 o = (Evas_Object_Image *)(obj->object_data);
1518 MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
1519 return;
1520 MAGIC_CHECK_END();
1521 if ((o->load_opts.w == w) && (o->load_opts.h == h)) return;
1522 o->load_opts.w = w;
1523 o->load_opts.h = h;
1524 if (o->cur.file)
1525 {
1526 evas_object_image_unload(obj, 0);
1527 evas_object_inform_call_image_unloaded(obj);
1528 evas_object_image_load(obj);
1529 o->changed = 1;
1530 evas_object_change(obj);
1531 }
1532}
1533
1534EAPI void
1535evas_object_image_load_size_get(const Evas_Object *obj, int *w, int *h)
1536{
1537 Evas_Object_Image *o;
1538
1539 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1540 return;
1541 MAGIC_CHECK_END();
1542 o = (Evas_Object_Image *)(obj->object_data);
1543 MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
1544 return;
1545 MAGIC_CHECK_END();
1546 if (w) *w = o->load_opts.w;
1547 if (h) *h = o->load_opts.h;
1548}
1549
1550EAPI void
1551evas_object_image_load_scale_down_set(Evas_Object *obj, int scale_down)
1552{
1553 Evas_Object_Image *o;
1554
1555 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1556 return;
1557 MAGIC_CHECK_END();
1558 o = (Evas_Object_Image *)(obj->object_data);
1559 MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
1560 return;
1561 MAGIC_CHECK_END();
1562 if (o->load_opts.scale_down_by == scale_down) return;
1563 o->load_opts.scale_down_by = scale_down;
1564 if (o->cur.file)
1565 {
1566 evas_object_image_unload(obj, 0);
1567 evas_object_inform_call_image_unloaded(obj);
1568 evas_object_image_load(obj);
1569 o->changed = 1;
1570 evas_object_change(obj);
1571 }
1572}
1573
1574EAPI int
1575evas_object_image_load_scale_down_get(const Evas_Object *obj)
1576{
1577 Evas_Object_Image *o;
1578
1579 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1580 return 0;
1581 MAGIC_CHECK_END();
1582 o = (Evas_Object_Image *)(obj->object_data);
1583 MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
1584 return 0;
1585 MAGIC_CHECK_END();
1586 return o->load_opts.scale_down_by;
1587}
1588
1589EAPI void
1590evas_object_image_load_region_set(Evas_Object *obj, int x, int y, int w, int h)
1591{
1592 Evas_Object_Image *o;
1593
1594 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1595 return;
1596 MAGIC_CHECK_END();
1597 o = (Evas_Object_Image *)(obj->object_data);
1598 MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
1599 return;
1600 MAGIC_CHECK_END();
1601 if ((o->load_opts.region.x == x) && (o->load_opts.region.y == y) &&
1602 (o->load_opts.region.w == w) && (o->load_opts.region.h == h)) return;
1603 o->load_opts.region.x = x;
1604 o->load_opts.region.y = y;
1605 o->load_opts.region.w = w;
1606 o->load_opts.region.h = h;
1607 if (o->cur.file)
1608 {
1609 evas_object_image_unload(obj, 0);
1610 evas_object_inform_call_image_unloaded(obj);
1611 evas_object_image_load(obj);
1612 o->changed = 1;
1613 evas_object_change(obj);
1614 }
1615}
1616
1617EAPI void
1618evas_object_image_load_region_get(const Evas_Object *obj, int *x, int *y, int *w, int *h)
1619{
1620 Evas_Object_Image *o;
1621
1622 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1623 return;
1624 MAGIC_CHECK_END();
1625 o = (Evas_Object_Image *)(obj->object_data);
1626 MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
1627 return;
1628 MAGIC_CHECK_END();
1629 if (x) *x = o->load_opts.region.x;
1630 if (y) *y = o->load_opts.region.y;
1631 if (w) *w = o->load_opts.region.w;
1632 if (h) *h = o->load_opts.region.h;
1633}
1634
1635EAPI void
1636evas_object_image_load_orientation_set(Evas_Object *obj, Eina_Bool enable)
1637{
1638 Evas_Object_Image *o;
1639
1640 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1641 return;
1642 MAGIC_CHECK_END();
1643 o = (Evas_Object_Image *)(obj->object_data);
1644 MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
1645 return;
1646 MAGIC_CHECK_END();
1647 o->load_opts.orientation = !!enable;
1648}
1649
1650EAPI Eina_Bool
1651evas_object_image_load_orientation_get(const Evas_Object *obj)
1652{
1653 Evas_Object_Image *o;
1654
1655 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1656 return EINA_FALSE;
1657 MAGIC_CHECK_END();
1658 o = (Evas_Object_Image *)(obj->object_data);
1659 MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
1660 return EINA_FALSE;
1661 MAGIC_CHECK_END();
1662 return o->load_opts.orientation;
1663}
1664
1665EAPI void
1666evas_object_image_colorspace_set(Evas_Object *obj, Evas_Colorspace cspace)
1667{
1668 Evas_Object_Image *o;
1669
1670 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1671 return;
1672 MAGIC_CHECK_END();
1673 o = (Evas_Object_Image *)(obj->object_data);
1674 MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
1675 return;
1676 MAGIC_CHECK_END();
1677
1678 _evas_object_image_cleanup(obj, o);
1679#ifdef EVAS_FRAME_QUEUING
1680 if ((Evas_Colorspace)o->cur.cspace != cspace)
1681 {
1682 if (o->engine_data)
1683 evas_common_pipe_op_image_flush(o->engine_data);
1684 }
1685#endif
1686
1687 o->cur.cspace = cspace;
1688 if (o->engine_data)
1689 obj->layer->evas->engine.func->image_colorspace_set(obj->layer->evas->engine.data.output,
1690 o->engine_data,
1691 cspace);
1692}
1693
1694EAPI Evas_Colorspace
1695evas_object_image_colorspace_get(const Evas_Object *obj)
1696{
1697 Evas_Object_Image *o;
1698
1699 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1700 return EVAS_COLORSPACE_ARGB8888;
1701 MAGIC_CHECK_END();
1702 o = (Evas_Object_Image *)(obj->object_data);
1703 MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
1704 return EVAS_COLORSPACE_ARGB8888;
1705 MAGIC_CHECK_END();
1706 return o->cur.cspace;
1707}
1708
1709EAPI void
1710evas_object_image_video_surface_set(Evas_Object *obj, Evas_Video_Surface *surf)
1711{
1712 Evas_Object_Image *o;
1713
1714 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1715 return;
1716 MAGIC_CHECK_END();
1717 o = (Evas_Object_Image *)(obj->object_data);
1718 MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
1719 return;
1720 MAGIC_CHECK_END();
1721 _evas_object_image_cleanup(obj, o);
1722 if (o->video_surface)
1723 {
1724 o->video_surface = 0;
1725 obj->layer->evas->video_objects = eina_list_remove(obj->layer->evas->video_objects, obj);
1726 }
1727
1728 if (surf)
1729 {
1730 if (surf->version != EVAS_VIDEO_SURFACE_VERSION) return ;
1731
1732 if (!surf->update_pixels ||
1733 !surf->move ||
1734 !surf->resize ||
1735 !surf->hide ||
1736 !surf->show)
1737 return ;
1738
1739 o->created = EINA_TRUE;
1740 o->video_surface = 1;
1741 o->video = *surf;
1742
1743 obj->layer->evas->video_objects = eina_list_append(obj->layer->evas->video_objects, obj);
1744 }
1745 else
1746 {
1747 o->video_surface = 0;
1748 o->video.update_pixels = NULL;
1749 o->video.move = NULL;
1750 o->video.resize = NULL;
1751 o->video.hide = NULL;
1752 o->video.show = NULL;
1753 o->video.data = NULL;
1754 }
1755}
1756
1757EAPI const Evas_Video_Surface *
1758evas_object_image_video_surface_get(const Evas_Object *obj)
1759{
1760 Evas_Object_Image *o;
1761
1762 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1763 return NULL;
1764 MAGIC_CHECK_END();
1765 o = (Evas_Object_Image *)(obj->object_data);
1766 MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
1767 return NULL;
1768 MAGIC_CHECK_END();
1769 if (!o->video_surface) return NULL;
1770 return &o->video;
1771}
1772
1773EAPI void
1774evas_object_image_native_surface_set(Evas_Object *obj, Evas_Native_Surface *surf)
1775{
1776 Evas_Object_Image *o;
1777
1778 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1779 return;
1780 MAGIC_CHECK_END();
1781 o = (Evas_Object_Image *)(obj->object_data);
1782 MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
1783 return;
1784 MAGIC_CHECK_END();
1785 _evas_object_image_cleanup(obj, o);
1786 if (!obj->layer->evas->engine.func->image_native_set) return;
1787 if ((surf) &&
1788 ((surf->version < 2) ||
1789 (surf->version > EVAS_NATIVE_SURFACE_VERSION))) return;
1790 o->engine_data =
1791 obj->layer->evas->engine.func->image_native_set(obj->layer->evas->engine.data.output,
1792 o->engine_data,
1793 surf);
1794}
1795
1796EAPI Evas_Native_Surface *
1797evas_object_image_native_surface_get(const Evas_Object *obj)
1798{
1799 Evas_Object_Image *o;
1800
1801 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1802 return NULL;
1803 MAGIC_CHECK_END();
1804 o = (Evas_Object_Image *)(obj->object_data);
1805 MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
1806 return NULL;
1807 MAGIC_CHECK_END();
1808 if (!obj->layer->evas->engine.func->image_native_get) return NULL;
1809 return obj->layer->evas->engine.func->image_native_get(obj->layer->evas->engine.data.output,
1810 o->engine_data);
1811}
1812
1813EAPI void
1814evas_object_image_scale_hint_set(Evas_Object *obj, Evas_Image_Scale_Hint hint)
1815{
1816 Evas_Object_Image *o;
1817
1818 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1819 return;
1820 MAGIC_CHECK_END();
1821 o = (Evas_Object_Image *)(obj->object_data);
1822 MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
1823 return;
1824 MAGIC_CHECK_END();
1825 if (o->scale_hint == hint) return;
1826#ifdef EVAS_FRAME_QUEUING
1827 if (o->engine_data)
1828 evas_common_pipe_op_image_flush(o->engine_data);
1829#endif
1830 o->scale_hint = hint;
1831 if (o->engine_data)
1832 {
1833 int stride = 0;
1834
1835 if (obj->layer->evas->engine.func->image_scale_hint_set)
1836 obj->layer->evas->engine.func->image_scale_hint_set
1837 (obj->layer->evas->engine.data.output,
1838 o->engine_data, o->scale_hint);
1839 if (obj->layer->evas->engine.func->image_stride_get)
1840 obj->layer->evas->engine.func->image_stride_get
1841 (obj->layer->evas->engine.data.output,
1842 o->engine_data, &stride);
1843 else
1844 stride = o->cur.image.w * 4;
1845 o->cur.image.stride = stride;
1846 }
1847}
1848
1849EAPI Evas_Image_Scale_Hint
1850evas_object_image_scale_hint_get(const Evas_Object *obj)
1851{
1852 Evas_Object_Image *o;
1853
1854 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1855 return EVAS_IMAGE_SCALE_HINT_NONE;
1856 MAGIC_CHECK_END();
1857 o = (Evas_Object_Image *)(obj->object_data);
1858 MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
1859 return EVAS_IMAGE_SCALE_HINT_NONE;
1860 MAGIC_CHECK_END();
1861 return o->scale_hint;
1862}
1863
1864EAPI void
1865evas_object_image_content_hint_set(Evas_Object *obj, Evas_Image_Content_Hint hint)
1866{
1867 Evas_Object_Image *o;
1868
1869 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1870 return;
1871 MAGIC_CHECK_END();
1872 o = (Evas_Object_Image *)(obj->object_data);
1873 MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
1874 return;
1875 MAGIC_CHECK_END();
1876 if (o->content_hint == hint) return;
1877#ifdef EVAS_FRAME_QUEUING
1878 if (o->engine_data)
1879 evas_common_pipe_op_image_flush(o->engine_data);
1880#endif
1881 o->content_hint = hint;
1882 if (o->engine_data)
1883 {
1884 int stride = 0;
1885
1886 if (obj->layer->evas->engine.func->image_content_hint_set)
1887 obj->layer->evas->engine.func->image_content_hint_set
1888 (obj->layer->evas->engine.data.output,
1889 o->engine_data, o->content_hint);
1890 if (obj->layer->evas->engine.func->image_stride_get)
1891 obj->layer->evas->engine.func->image_stride_get
1892 (obj->layer->evas->engine.data.output,
1893 o->engine_data, &stride);
1894 else
1895 stride = o->cur.image.w * 4;
1896 o->cur.image.stride = stride;
1897 }
1898}
1899
1900EAPI void
1901evas_object_image_alpha_mask_set(Evas_Object *obj, Eina_Bool ismask)
1902{
1903 Evas_Object_Image *o;
1904
1905 if (!ismask) return;
1906
1907 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1908 return;
1909 MAGIC_CHECK_END();
1910 o = (Evas_Object_Image *)(obj->object_data);
1911 MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
1912 return;
1913 MAGIC_CHECK_END();
1914
1915 /* Convert to A8 if not already */
1916
1917 /* done */
1918
1919}
1920
1921#define FRAME_MAX 1024
1922EAPI Evas_Image_Content_Hint
1923evas_object_image_content_hint_get(const Evas_Object *obj)
1924{
1925 Evas_Object_Image *o;
1926
1927 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1928 return EVAS_IMAGE_CONTENT_HINT_NONE;
1929 MAGIC_CHECK_END();
1930 o = (Evas_Object_Image *)(obj->object_data);
1931 MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
1932 return EVAS_IMAGE_CONTENT_HINT_NONE;
1933 MAGIC_CHECK_END();
1934 return o->content_hint;
1935}
1936
1937EAPI Eina_Bool
1938evas_object_image_region_support_get(const Evas_Object *obj)
1939{
1940 Evas_Object_Image *o;
1941
1942 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1943 return EINA_FALSE;
1944 MAGIC_CHECK_END();
1945 o = (Evas_Object_Image *) (obj->object_data);
1946 MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
1947 return EINA_FALSE;
1948 MAGIC_CHECK_END();
1949
1950 return obj->layer->evas->engine.func->image_can_region_get(
1951 obj->layer->evas->engine.data.output,
1952 o->engine_data);
1953}
1954
1955/* animated feature */
1956EAPI Eina_Bool
1957evas_object_image_animated_get(const Evas_Object *obj)
1958{
1959 Evas_Object_Image *o;
1960
1961 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1962 return EINA_FALSE;
1963 MAGIC_CHECK_END();
1964 o = (Evas_Object_Image *)(obj->object_data);
1965 MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
1966 return EINA_FALSE;
1967 MAGIC_CHECK_END();
1968
1969 if (obj->layer->evas->engine.func->image_animated_get)
1970 return obj->layer->evas->engine.func->image_animated_get(obj->layer->evas->engine.data.output, o->engine_data);
1971 return EINA_FALSE;
1972}
1973
1974EAPI int
1975evas_object_image_animated_frame_count_get(const Evas_Object *obj)
1976{
1977 Evas_Object_Image *o;
1978
1979 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1980 return -1;
1981 MAGIC_CHECK_END();
1982 o = (Evas_Object_Image *)(obj->object_data);
1983 MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
1984 return -1;
1985 MAGIC_CHECK_END();
1986
1987 if (!evas_object_image_animated_get(obj)) return -1;
1988 if (obj->layer->evas->engine.func->image_animated_frame_count_get)
1989 return obj->layer->evas->engine.func->image_animated_frame_count_get(obj->layer->evas->engine.data.output, o->engine_data);
1990 return -1;
1991}
1992
1993EAPI Evas_Image_Animated_Loop_Hint
1994evas_object_image_animated_loop_type_get(const Evas_Object *obj)
1995{
1996 Evas_Object_Image *o;
1997
1998 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1999 return EVAS_IMAGE_ANIMATED_HINT_NONE;
2000 MAGIC_CHECK_END();
2001 o = (Evas_Object_Image *)(obj->object_data);
2002 MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
2003 return EVAS_IMAGE_ANIMATED_HINT_NONE;
2004 MAGIC_CHECK_END();
2005
2006 if (!evas_object_image_animated_get(obj)) return EVAS_IMAGE_ANIMATED_HINT_NONE;
2007
2008 if (obj->layer->evas->engine.func->image_animated_loop_type_get)
2009 return obj->layer->evas->engine.func->image_animated_loop_type_get(obj->layer->evas->engine.data.output, o->engine_data);
2010 return EVAS_IMAGE_ANIMATED_HINT_NONE;
2011}
2012
2013EAPI int
2014evas_object_image_animated_loop_count_get(const Evas_Object *obj)
2015{
2016 Evas_Object_Image *o;
2017
2018 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
2019 return -1;
2020 MAGIC_CHECK_END();
2021 o = (Evas_Object_Image *)(obj->object_data);
2022 MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
2023 return -1;
2024 MAGIC_CHECK_END();
2025
2026 if (!evas_object_image_animated_get(obj)) return -1;
2027
2028 if (obj->layer->evas->engine.func->image_animated_loop_count_get)
2029 return obj->layer->evas->engine.func->image_animated_loop_count_get(obj->layer->evas->engine.data.output, o->engine_data);
2030 return -1;
2031}
2032
2033EAPI double
2034evas_object_image_animated_frame_duration_get(const Evas_Object *obj, int start_frame, int frame_num)
2035{
2036 Evas_Object_Image *o;
2037 int frame_count = 0;
2038
2039 if (start_frame < 1) return -1;
2040 if (frame_num < 0) return -1;
2041
2042 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
2043 return -1;
2044 MAGIC_CHECK_END();
2045 o = (Evas_Object_Image *)(obj->object_data);
2046 MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
2047 return -1;
2048 MAGIC_CHECK_END();
2049
2050 if (!evas_object_image_animated_get(obj)) return -1;
2051
2052 if (!obj->layer->evas->engine.func->image_animated_frame_count_get) return -1;
2053
2054 frame_count = obj->layer->evas->engine.func->image_animated_frame_count_get(obj->layer->evas->engine.data.output, o->engine_data);
2055
2056 if ((start_frame + frame_num) > frame_count) return -1;
2057 if (obj->layer->evas->engine.func->image_animated_frame_duration_get)
2058 return obj->layer->evas->engine.func->image_animated_frame_duration_get(obj->layer->evas->engine.data.output, o->engine_data, start_frame, frame_num);
2059 return -1;
2060}
2061
2062EAPI void
2063evas_object_image_animated_frame_set(Evas_Object *obj, int frame_index)
2064{
2065 Evas_Object_Image *o;
2066 int frame_count = 0;
2067
2068 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
2069 return;
2070 MAGIC_CHECK_END();
2071 o = (Evas_Object_Image *)(obj->object_data);
2072 MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
2073 return;
2074 MAGIC_CHECK_END();
2075
2076 if (!o->cur.file) return;
2077 if (o->cur.frame == frame_index) return;
2078
2079 if (!evas_object_image_animated_get(obj)) return;
2080
2081 frame_count = evas_object_image_animated_frame_count_get(obj);
2082
2083 /* limit the size of frame to FRAME_MAX */
2084 if ((frame_count > FRAME_MAX) || (frame_count < 0) || (frame_index > frame_count))
2085 return;
2086
2087 if (!obj->layer->evas->engine.func->image_animated_frame_set) return;
2088 if (!obj->layer->evas->engine.func->image_animated_frame_set(obj->layer->evas->engine.data.output, o->engine_data, frame_index))
2089 return;
2090
2091 o->prev.frame = o->cur.frame;
2092 o->cur.frame = frame_index;
2093
2094 o->changed = 1;
2095 evas_object_change(obj);
2096
2097}
2098
2099EAPI void
2100evas_image_cache_flush(Evas *e)
2101{
2102 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
2103 return;
2104 MAGIC_CHECK_END();
2105
2106 e->engine.func->image_cache_flush(e->engine.data.output);
2107}
2108
2109EAPI void
2110evas_image_cache_reload(Evas *e)
2111{
2112 Evas_Layer *layer;
2113
2114 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
2115 return;
2116 MAGIC_CHECK_END();
2117
2118 evas_image_cache_flush(e);
2119 EINA_INLIST_FOREACH(e->layers, layer)
2120 {
2121 Evas_Object *obj;
2122
2123 EINA_INLIST_FOREACH(layer->objects, obj)
2124 {
2125 Evas_Object_Image *o;
2126
2127 o = (Evas_Object_Image *)(obj->object_data);
2128 if (o->magic == MAGIC_OBJ_IMAGE)
2129 {
2130 evas_object_image_unload(obj, 1);
2131 evas_object_inform_call_image_unloaded(obj);
2132 }
2133 }
2134 }
2135 evas_image_cache_flush(e);
2136 EINA_INLIST_FOREACH(e->layers, layer)
2137 {
2138 Evas_Object *obj;
2139
2140 EINA_INLIST_FOREACH(layer->objects, obj)
2141 {
2142 Evas_Object_Image *o;
2143
2144 o = (Evas_Object_Image *)(obj->object_data);
2145 if (o->magic == MAGIC_OBJ_IMAGE)
2146 {
2147 evas_object_image_load(obj);
2148 o->changed = 1;
2149 evas_object_change(obj);
2150 }
2151 }
2152 }
2153 evas_image_cache_flush(e);
2154}
2155
2156EAPI void
2157evas_image_cache_set(Evas *e, int size)
2158{
2159 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
2160 return;
2161 MAGIC_CHECK_END();
2162
2163 if (size < 0) size = 0;
2164 e->engine.func->image_cache_set(e->engine.data.output, size);
2165}
2166
2167EAPI int
2168evas_image_cache_get(const Evas *e)
2169{
2170 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
2171 return 0;
2172 MAGIC_CHECK_END();
2173
2174 return e->engine.func->image_cache_get(e->engine.data.output);
2175}
2176
2177EAPI Eina_Bool
2178evas_image_max_size_get(const Evas *e, int *maxw, int *maxh)
2179{
2180 int w = 0, h = 0;
2181 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
2182 return EINA_FALSE;
2183 MAGIC_CHECK_END();
2184
2185 if (maxw) *maxw = 0xffff;
2186 if (maxh) *maxh = 0xffff;
2187 if (!e->engine.func->image_max_size_get) return EINA_FALSE;
2188 e->engine.func->image_max_size_get(e->engine.data.output, &w, &h);
2189 if (maxw) *maxw = w;
2190 if (maxh) *maxh = h;
2191 return EINA_TRUE;
2192}
2193
2194/* all nice and private */
2195static void
2196_proxy_unset(Evas_Object *proxy)
2197{
2198 Evas_Object_Image *o;
2199
2200 o = proxy->object_data;
2201 if (!o->cur.source) return;
2202
2203 o->cur.source->proxy.proxies = eina_list_remove(o->cur.source->proxy.proxies, proxy);
2204
2205 o->cur.source = NULL;
2206 if (o->cur.defmap)
2207 {
2208 evas_map_free(o->cur.defmap);
2209 o->cur.defmap = NULL;
2210 }
2211}
2212
2213
2214static void
2215_proxy_set(Evas_Object *proxy, Evas_Object *src)
2216{
2217 Evas_Object_Image *o;
2218
2219 o = proxy->object_data;
2220
2221 evas_object_image_file_set(proxy, NULL, NULL);
2222
2223 o->cur.source = src;
2224
2225 src->proxy.proxies = eina_list_append(src->proxy.proxies, proxy);
2226 src->proxy.redraw = EINA_TRUE;
2227}
2228
2229/* Some moron just set a proxy on a proxy.
2230 * Give them some pixels. A random color
2231 */
2232static void
2233_proxy_error(Evas_Object *proxy, void *context, void *output, void *surface,
2234 int x, int y)
2235{
2236 Evas_Func *func;
2237 int r = rand() % 255;
2238 int g = rand() % 255;
2239 int b = rand() % 255;
2240
2241 /* XXX: Eina log error or something I'm sure
2242 * If it bugs you, just fix it. Don't tell me */
2243 if (VERBOSE_PROXY_ERROR) printf("Err: Argh! Recursive proxies.\n");
2244
2245 func = proxy->layer->evas->engine.func;
2246 func->context_color_set(output, context, r, g, b, 255);
2247 func->context_multiplier_unset(output, context);
2248 func->context_render_op_set(output, context, proxy->cur.render_op);
2249 func->rectangle_draw(output, context, surface, proxy->cur.geometry.x + x,
2250 proxy->cur.geometry.y + y,
2251 proxy->cur.geometry.w,
2252 proxy->cur.geometry.h);
2253 return;
2254}
2255
2256/*
2257static void
2258_proxy_subrender_recurse(Evas_Object *obj, Evas_Object *clip, void *output, void *surface, void *ctx, int x, int y)
2259{
2260 Evas_Object *obj2;
2261 Evas *e = obj->layer->evas;
2262
2263 if (obj->clip.clipees) return;
2264 if (!obj->cur.visible) return;
2265 if ((!clip) || (clip != obj->cur.clipper))
2266 {
2267 if (!obj->cur.cache.clip.visible) return;
2268 if ((obj->cur.cache.clip.a == 0) &&
2269 (obj->cur.render_op == EVAS_RENDER_BLEND)) return;
2270 }
2271 if ((obj->func->is_visible) && (!obj->func->is_visible(obj))) return;
2272
2273 if (!obj->pre_render_done)
2274 obj->func->render_pre(obj);
2275 ctx = e->engine.func->context_new(output);
2276 if (obj->smart.smart)
2277 {
2278 EINA_INLIST_FOREACH(evas_object_smart_members_get_direct(obj), obj2)
2279 {
2280 _proxy_subrender_recurse(obj2, clip, output, surface, ctx, x, y);
2281 }
2282 }
2283 else
2284 {
2285 obj->func->render(obj, output, ctx, surface, x, y);
2286 }
2287 e->engine.func->context_free(output, ctx);
2288}
2289*/
2290
2291/**
2292 * Render the source object when a proxy is set.
2293 *
2294 * Used to force a draw if necessary, else just makes sures it's available.
2295 */
2296static void
2297_proxy_subrender(Evas *e, Evas_Object *source)
2298{
2299 void *ctx;
2300/* Evas_Object *obj2, *clip;*/
2301 int w, h;
2302
2303 if (!source) return;
2304
2305 w = source->cur.geometry.w;
2306 h = source->cur.geometry.h;
2307
2308 source->proxy.redraw = EINA_FALSE;
2309
2310 /* We need to redraw surface then */
2311 if ((source->proxy.surface) &&
2312 ((source->proxy.w != w) || (source->proxy.h != h)))
2313 {
2314 e->engine.func->image_map_surface_free(e->engine.data.output,
2315 source->proxy.surface);
2316 source->proxy.surface = NULL;
2317 }
2318
2319 /* FIXME: Hardcoded alpha 'on' */
2320 /* FIXME (cont): Should see if the object has alpha */
2321 if (!source->proxy.surface)
2322 {
2323 source->proxy.surface = e->engine.func->image_map_surface_new
2324 (e->engine.data.output, w, h, 1);
2325 source->proxy.w = w;
2326 source->proxy.h = h;
2327 }
2328
2329 ctx = e->engine.func->context_new(e->engine.data.output);
2330 e->engine.func->context_color_set(e->engine.data.output, ctx, 0, 0, 0, 0);
2331 e->engine.func->context_render_op_set(e->engine.data.output, ctx, EVAS_RENDER_COPY);
2332 e->engine.func->rectangle_draw(e->engine.data.output, ctx,
2333 source->proxy.surface, 0, 0, w, h);
2334 e->engine.func->context_free(e->engine.data.output, ctx);
2335
2336 ctx = e->engine.func->context_new(e->engine.data.output);
2337 evas_render_mapped(e, source, ctx, source->proxy.surface,
2338 -source->cur.geometry.x,
2339 -source->cur.geometry.y,
2340 1, 0, 0, e->output.w, e->output.h);
2341 e->engine.func->context_free(e->engine.data.output, ctx);
2342 source->proxy.surface = e->engine.func->image_dirty_region
2343 (e->engine.data.output, source->proxy.surface, 0, 0, w, h);
2344/*
2345 ctx = e->engine.func->context_new(e->engine.data.output);
2346 if (source->smart.smart)
2347 {
2348 clip = evas_object_smart_clipped_clipper_get(source);
2349 EINA_INLIST_FOREACH(evas_object_smart_members_get_direct(source), obj2)
2350 {
2351 _proxy_subrender_recurse(obj2, clip, e->engine.data.output,
2352 source->proxy.surface,
2353 ctx,
2354 -source->cur.geometry.x,
2355 -source->cur.geometry.y);
2356 }
2357 }
2358 else
2359 {
2360 if (!source->pre_render_done)
2361 source->func->render_pre(source);
2362 source->func->render(source, e->engine.data.output, ctx,
2363 source->proxy.surface,
2364 -source->cur.geometry.x,
2365 -source->cur.geometry.y);
2366 }
2367
2368 e->engine.func->context_free(e->engine.data.output, ctx);
2369 source->proxy.surface = e->engine.func->image_dirty_region
2370 (e->engine.data.output, source->proxy.surface, 0, 0, w, h);
2371 */
2372}
2373
2374#if 0 // filtering disabled
2375/*
2376 *
2377 * Note that this is similar to proxy_subrender_recurse. It should be
2378 * possible to merge I guess
2379 */
2380static void
2381image_filter_draw_under_recurse(Evas *e, Evas_Object *obj, Evas_Object *stop,
2382 void *output, void *ctx, void *surface,
2383 int x, int y)
2384{
2385 Evas_Object *obj2;
2386
2387 if (obj->clip.clipees) return;
2388 /* FIXME: Doing bounding box test */
2389 if (!evas_object_is_in_output_rect(obj, stop->cur.geometry.x,
2390 stop->cur.geometry.y,
2391 stop->cur.geometry.w,
2392 stop->cur.geometry.h))
2393 return;
2394
2395 if (!evas_object_is_visible(obj)) return;
2396 obj->pre_render_done = 1;
2397 ctx = e->engine.func->context_new(output);
2398
2399 if (obj->smart.smart)
2400 {
2401 EINA_INLIST_FOREACH(evas_object_smart_members_get_direct(obj), obj2)
2402 {
2403 if (obj2 == stop) return;
2404 image_filter_draw_under_recurse(e, obj2, stop, output, surface,
2405 ctx, x, y);
2406 }
2407 }
2408 else
2409 obj->func->render(obj, output, ctx, surface, x ,y);
2410 e->engine.func->context_free(output, ctx);
2411}
2412
2413/*
2414 * Draw all visible objects intersecting an object which are _beneath_ it.
2415 */
2416static void
2417image_filter_draw_under(Evas *e, Evas_Object *stop, void *output, void *ctx, void *surface, int dx, int dy)
2418{
2419 Evas_Layer *lay;
2420 int x, y;
2421
2422 x = stop->cur.geometry.x - dx;
2423 y = stop->cur.geometry.y - dy;
2424
2425 EINA_INLIST_FOREACH(e->layers, lay)
2426 {
2427 Evas_Object *obj;
2428 EINA_INLIST_FOREACH(lay->objects, obj)
2429 {
2430 if (obj->delete_me) continue;
2431 if (obj == stop) return;
2432 /* FIXME: Do bounding box check */
2433 image_filter_draw_under_recurse(e, obj, stop, output, ctx,
2434 surface, -x, -y);
2435 }
2436 }
2437 e->engine.func->image_dirty_region(output, surface, 0, 0, 300, 300);
2438 e->engine.func->output_flush(output);
2439}
2440
2441/*
2442 * Update the filtered object.
2443 *
2444 * Creates a new context, and renders stuff (filtered) onto that.
2445 */
2446Filtered_Image *
2447image_filter_update(Evas *e, Evas_Object *obj, void *src, int imagew, int imageh, int *outw, int *outh)
2448{
2449 int w, h;
2450 void *ctx;
2451 Evas_Filter_Info *info;
2452 void *surface;
2453 Eina_Bool alpha;
2454
2455 info = obj->filter;
2456
2457 if (info->mode == EVAS_FILTER_MODE_BELOW)
2458 {
2459 w = obj->cur.geometry.w;
2460 h = obj->cur.geometry.h;
2461 evas_filter_get_size(info, w, h, &imagew, &imageh, EINA_TRUE);
2462 alpha = EINA_FALSE;
2463 }
2464 else
2465 {
2466 evas_filter_get_size(info, imagew, imageh, &w, &h, EINA_FALSE);
2467 alpha = e->engine.func->image_alpha_get(e->engine.data.output, src);
2468 }
2469
2470 /* Certain filters may make alpha images anyway */
2471 if (alpha == EINA_FALSE) alpha = evas_filter_always_alpha(info);
2472
2473 surface = e->engine.func->image_map_surface_new(e->engine.data.output, w, h,
2474 alpha);
2475
2476 if (info->mode == EVAS_FILTER_MODE_BELOW)
2477 {
2478 void *subsurface;
2479 int disw, dish;
2480 int dx, dy;
2481 disw = obj->cur.geometry.w;
2482 dish = obj->cur.geometry.h;
2483 dx = (imagew - w) >> 1;
2484 dy = (imageh - h) >> 1;
2485 subsurface = e->engine.func->image_map_surface_new
2486 (e->engine.data.output, imagew, imageh, 1);
2487 ctx = e->engine.func->context_new(e->engine.data.output);
2488 e->engine.func->context_color_set(e->engine.data.output, ctx, 0, 255, 0, 255);
2489 e->engine.func->context_render_op_set(e->engine.data.output, ctx, EVAS_RENDER_COPY);
2490 e->engine.func->rectangle_draw(e->engine.data.output, ctx,
2491 subsurface, 0, 0, imagew, imageh);
2492
2493 image_filter_draw_under(e, obj, e->engine.data.output, ctx,
2494 subsurface, dx, dy);
2495
2496 e->engine.func->context_free(e->engine.data.output, ctx);
2497
2498 ctx = e->engine.func->context_new(e->engine.data.output);
2499
2500 e->engine.func->image_draw_filtered(e->engine.data.output,
2501 ctx, surface, subsurface, info);
2502
2503 e->engine.func->context_free(e->engine.data.output, ctx);
2504
2505 e->engine.func->image_map_surface_free(e->engine.data.output,
2506 subsurface);
2507 }
2508 else
2509 {
2510 ctx = e->engine.func->context_new(e->engine.data.output);
2511 e->engine.func->image_draw_filtered(e->engine.data.output,
2512 ctx, surface, src, info);
2513 e->engine.func->context_free(e->engine.data.output, ctx);
2514 }
2515
2516 e->engine.func->image_dirty_region(e->engine.data.output, surface,
2517 0, 0, w, h);
2518 if (outw) *outw = w;
2519 if (outh) *outh = h;
2520 return e->engine.func->image_filtered_save(src, surface,
2521 obj->filter->key,
2522 obj->filter->len);
2523}
2524#endif
2525
2526static void
2527evas_object_image_unload(Evas_Object *obj, Eina_Bool dirty)
2528{
2529 Evas_Object_Image *o;
2530
2531 o = (Evas_Object_Image *)(obj->object_data);
2532
2533 if ((!o->cur.file) ||
2534 (o->pixels_checked_out > 0)) return;
2535 if (dirty)
2536 {
2537 if (o->engine_data)
2538 o->engine_data = obj->layer->evas->engine.func->image_dirty_region
2539 (obj->layer->evas->engine.data.output,
2540 o->engine_data,
2541 0, 0,
2542 o->cur.image.w, o->cur.image.h);
2543 }
2544 if (o->engine_data)
2545 {
2546 if (o->preloading)
2547 {
2548 o->preloading = 0;
2549 obj->layer->evas->engine.func->image_data_preload_cancel(obj->layer->evas->engine.data.output,
2550 o->engine_data,
2551 obj);
2552 }
2553 obj->layer->evas->engine.func->image_free(obj->layer->evas->engine.data.output,
2554 o->engine_data);
2555 }
2556 o->engine_data = NULL;
2557 o->load_error = EVAS_LOAD_ERROR_NONE;
2558 o->cur.has_alpha = 1;
2559 o->cur.cspace = EVAS_COLORSPACE_ARGB8888;
2560 o->cur.image.w = 0;
2561 o->cur.image.h = 0;
2562 o->cur.image.stride = 0;
2563}
2564
2565static void
2566evas_object_image_load(Evas_Object *obj)
2567{
2568 Evas_Object_Image *o;
2569 Evas_Image_Load_Opts lo;
2570
2571 o = (Evas_Object_Image *)(obj->object_data);
2572 if (o->engine_data) return;
2573
2574 lo.scale_down_by = o->load_opts.scale_down_by;
2575 lo.dpi = o->load_opts.dpi;
2576 lo.w = o->load_opts.w;
2577 lo.h = o->load_opts.h;
2578 lo.region.x = o->load_opts.region.x;
2579 lo.region.y = o->load_opts.region.y;
2580 lo.region.w = o->load_opts.region.w;
2581 lo.region.h = o->load_opts.region.h;
2582 lo.orientation = o->load_opts.orientation;
2583 o->engine_data = obj->layer->evas->engine.func->image_load
2584 (obj->layer->evas->engine.data.output,
2585 o->cur.file,
2586 o->cur.key,
2587 &o->load_error,
2588 &lo);
2589 if (o->engine_data)
2590 {
2591 int w, h;
2592 int stride = 0;
2593
2594 obj->layer->evas->engine.func->image_size_get
2595 (obj->layer->evas->engine.data.output,
2596 o->engine_data, &w, &h);
2597 if (obj->layer->evas->engine.func->image_stride_get)
2598 obj->layer->evas->engine.func->image_stride_get
2599 (obj->layer->evas->engine.data.output,
2600 o->engine_data, &stride);
2601 else
2602 stride = w * 4;
2603 o->cur.has_alpha = obj->layer->evas->engine.func->image_alpha_get
2604 (obj->layer->evas->engine.data.output,
2605 o->engine_data);
2606 o->cur.cspace = obj->layer->evas->engine.func->image_colorspace_get
2607 (obj->layer->evas->engine.data.output,
2608 o->engine_data);
2609 o->cur.image.w = w;
2610 o->cur.image.h = h;
2611 o->cur.image.stride = stride;
2612 }
2613 else
2614 {
2615 o->load_error = EVAS_LOAD_ERROR_GENERIC;
2616 }
2617}
2618
2619static Evas_Coord
2620evas_object_image_figure_x_fill(Evas_Object *obj, Evas_Coord start, Evas_Coord size, Evas_Coord *size_ret)
2621{
2622 Evas_Coord w;
2623
2624 w = ((size * obj->layer->evas->output.w) /
2625 (Evas_Coord)obj->layer->evas->viewport.w);
2626 if (size <= 0) size = 1;
2627 if (start > 0)
2628 {
2629 while (start - size > 0) start -= size;
2630 }
2631 else if (start < 0)
2632 {
2633 while (start < 0) start += size;
2634 }
2635 start = ((start * obj->layer->evas->output.w) /
2636 (Evas_Coord)obj->layer->evas->viewport.w);
2637 *size_ret = w;
2638 return start;
2639}
2640
2641static Evas_Coord
2642evas_object_image_figure_y_fill(Evas_Object *obj, Evas_Coord start, Evas_Coord size, Evas_Coord *size_ret)
2643{
2644 Evas_Coord h;
2645
2646 h = ((size * obj->layer->evas->output.h) /
2647 (Evas_Coord)obj->layer->evas->viewport.h);
2648 if (size <= 0) size = 1;
2649 if (start > 0)
2650 {
2651 while (start - size > 0) start -= size;
2652 }
2653 else if (start < 0)
2654 {
2655 while (start < 0) start += size;
2656 }
2657 start = ((start * obj->layer->evas->output.h) /
2658 (Evas_Coord)obj->layer->evas->viewport.h);
2659 *size_ret = h;
2660 return start;
2661}
2662
2663static void
2664evas_object_image_init(Evas_Object *obj)
2665{
2666 /* alloc image ob, setup methods and default values */
2667 obj->object_data = evas_object_image_new();
2668 /* set up default settings for this kind of object */
2669 obj->cur.color.r = 255;
2670 obj->cur.color.g = 255;
2671 obj->cur.color.b = 255;
2672 obj->cur.color.a = 255;
2673 obj->cur.geometry.x = 0;
2674 obj->cur.geometry.y = 0;
2675 obj->cur.geometry.w = 0;
2676 obj->cur.geometry.h = 0;
2677 obj->cur.layer = 0;
2678 obj->cur.anti_alias = 0;
2679 obj->cur.render_op = EVAS_RENDER_BLEND;
2680 /* set up object-specific settings */
2681 obj->prev = obj->cur;
2682 /* set up methods (compulsory) */
2683 obj->func = &object_func;
2684 obj->type = o_type;
2685}
2686
2687static void *
2688evas_object_image_new(void)
2689{
2690 Evas_Object_Image *o;
2691
2692 /* alloc obj private data */
2693 EVAS_MEMPOOL_INIT(_mp_obj, "evas_object_image", Evas_Object_Image, 256, NULL);
2694 o = EVAS_MEMPOOL_ALLOC(_mp_obj, Evas_Object_Image);
2695 if (!o) return NULL;
2696 EVAS_MEMPOOL_PREP(_mp_obj, o, Evas_Object_Image);
2697 o->magic = MAGIC_OBJ_IMAGE;
2698 o->cur.fill.w = 0;
2699 o->cur.fill.h = 0;
2700 o->cur.smooth_scale = 1;
2701 o->cur.border.fill = 1;
2702 o->cur.border.scale = 1.0;
2703 o->cur.cspace = EVAS_COLORSPACE_ARGB8888;
2704 o->cur.spread = EVAS_TEXTURE_REPEAT;
2705 o->cur.opaque_valid = 0;
2706 o->cur.source = NULL;
2707 o->prev = o->cur;
2708 o->tmpf_fd = -1;
2709 return o;
2710}
2711
2712static void
2713evas_object_image_free(Evas_Object *obj)
2714{
2715 Evas_Object_Image *o;
2716 Eina_Rectangle *r;
2717
2718 /* frees private object data. very simple here */
2719 o = (Evas_Object_Image *)(obj->object_data);
2720 MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
2721 return;
2722 MAGIC_CHECK_END();
2723 /* free obj */
2724 _cleanup_tmpf(obj);
2725 if (o->cur.file) eina_stringshare_del(o->cur.file);
2726 if (o->cur.key) eina_stringshare_del(o->cur.key);
2727 if (o->cur.source) _proxy_unset(obj);
2728 if (o->engine_data)
2729 {
2730 if (o->preloading)
2731 {
2732 o->preloading = 0;
2733 obj->layer->evas->engine.func->image_data_preload_cancel(obj->layer->evas->engine.data.output,
2734 o->engine_data,
2735 obj);
2736 }
2737 obj->layer->evas->engine.func->image_free(obj->layer->evas->engine.data.output,
2738 o->engine_data);
2739 }
2740 if (o->video_surface)
2741 {
2742 o->video_surface = 0;
2743 obj->layer->evas->video_objects = eina_list_remove(obj->layer->evas->video_objects, obj);
2744 }
2745 o->engine_data = NULL;
2746 o->magic = 0;
2747 EINA_LIST_FREE(o->pixel_updates, r)
2748 eina_rectangle_free(r);
2749 EVAS_MEMPOOL_FREE(_mp_obj, o);
2750}
2751
2752static void
2753evas_object_image_render(Evas_Object *obj, void *output, void *context, void *surface, int x, int y)
2754{
2755 Evas_Object_Image *o;
2756 int imagew, imageh, uvw, uvh;
2757 void *pixels;
2758
2759 /* render object to surface with context, and offset by x,y */
2760 o = (Evas_Object_Image *)(obj->object_data);
2761
2762 if ((o->cur.fill.w < 1) || (o->cur.fill.h < 1))
2763 return; /* no error message, already printed in pre_render */
2764
2765 /* Proxy sanity */
2766 if (o->proxyrendering)
2767 {
2768 _proxy_error(obj, context, output, surface, x, y);
2769 return;
2770 }
2771
2772 /* We are displaying the overlay */
2773 if (o->video_visible)
2774 {
2775 /* Create a transparent rectangle */
2776 obj->layer->evas->engine.func->context_color_set(output,
2777 context,
2778 0, 0, 0, 0);
2779 obj->layer->evas->engine.func->context_multiplier_unset(output,
2780 context);
2781 obj->layer->evas->engine.func->context_render_op_set(output, context,
2782 EVAS_RENDER_COPY);
2783 obj->layer->evas->engine.func->rectangle_draw(output,
2784 context,
2785 surface,
2786 obj->cur.geometry.x + x,
2787 obj->cur.geometry.y + y,
2788 obj->cur.geometry.w,
2789 obj->cur.geometry.h);
2790
2791 return ;
2792 }
2793
2794 obj->layer->evas->engine.func->context_color_set(output,
2795 context,
2796 255, 255, 255, 255);
2797
2798 if ((obj->cur.cache.clip.r == 255) &&
2799 (obj->cur.cache.clip.g == 255) &&
2800 (obj->cur.cache.clip.b == 255) &&
2801 (obj->cur.cache.clip.a == 255))
2802 {
2803 obj->layer->evas->engine.func->context_multiplier_unset(output,
2804 context);
2805 }
2806 else
2807 obj->layer->evas->engine.func->context_multiplier_set(output,
2808 context,
2809 obj->cur.cache.clip.r,
2810 obj->cur.cache.clip.g,
2811 obj->cur.cache.clip.b,
2812 obj->cur.cache.clip.a);
2813
2814 obj->layer->evas->engine.func->context_render_op_set(output, context,
2815 obj->cur.render_op);
2816
2817 if (!o->cur.source)
2818 {
2819 pixels = o->engine_data;
2820 imagew = o->cur.image.w;
2821 imageh = o->cur.image.h;
2822 uvw = imagew;
2823 uvh = imageh;
2824 }
2825 else if (o->cur.source->proxy.surface && !o->cur.source->proxy.redraw)
2826 {
2827 pixels = o->cur.source->proxy.surface;
2828 imagew = o->cur.source->proxy.w;
2829 imageh = o->cur.source->proxy.h;
2830 uvw = imagew;
2831 uvh = imageh;
2832 }
2833 else if (o->cur.source->type == o_type &&
2834 ((Evas_Object_Image *)o->cur.source->object_data)->engine_data)
2835 {
2836 Evas_Object_Image *oi;
2837 oi = o->cur.source->object_data;
2838 pixels = oi->engine_data;
2839 imagew = oi->cur.image.w;
2840 imageh = oi->cur.image.h;
2841 uvw = o->cur.source->cur.geometry.w;
2842 uvh = o->cur.source->cur.geometry.h;
2843 }
2844 else
2845 {
2846 o->proxyrendering = 1;
2847 _proxy_subrender(obj->layer->evas, o->cur.source);
2848 pixels = o->cur.source->proxy.surface;
2849 imagew = o->cur.source->proxy.w;
2850 imageh = o->cur.source->proxy.h;
2851 uvw = imagew;
2852 uvh = imageh;
2853 o->proxyrendering = 0;
2854 }
2855
2856#if 0 // filtering disabled
2857 /* Now check/update filter */
2858 if (obj->filter && obj->filter->filter)
2859 {
2860 Filtered_Image *fi = NULL;
2861 //printf("%p has filter: %s\n", obj,obj->filter->dirty?"dirty":"clean");
2862 if (obj->filter->dirty)
2863 {
2864 if (obj->filter->mode != EVAS_FILTER_MODE_BELOW)
2865 {
2866 uint32_t len;
2867 uint8_t *key;
2868
2869 if (obj->filter->key) free(obj->filter->key);
2870 obj->filter->key = NULL;
2871 obj->filter->len = 0;
2872 key = evas_filter_key_get(obj->filter, &len);
2873 if (key)
2874 {
2875 obj->filter->key = key;
2876 obj->filter->len = len;
2877 fi = obj->layer->evas->engine.func->image_filtered_get
2878 (o->engine_data, key, len);
2879 if (obj->filter->cached && fi != obj->filter->cached)
2880 {
2881 obj->layer->evas->engine.func->image_filtered_free
2882 (o->engine_data, obj->filter->cached);
2883 obj->filter->cached = NULL;
2884 }
2885 }
2886 }
2887 else if (obj->filter->cached)
2888 {
2889 obj->layer->evas->engine.func->image_filtered_free
2890 (o->engine_data, obj->filter->cached);
2891 }
2892 if (!fi)
2893 fi = image_filter_update(obj->layer->evas, obj, pixels,
2894 imagew, imageh, &imagew, &imageh);
2895 pixels = fi->image;
2896 obj->filter->dirty = 0;
2897 obj->filter->cached = fi;
2898 }
2899 else
2900 {
2901 fi = obj->filter->cached;
2902 pixels = fi->image;
2903 }
2904 }
2905#endif
2906
2907 if (pixels)
2908 {
2909 Evas_Coord idw, idh, idx, idy;
2910 int ix, iy, iw, ih;
2911 int img_set = 0;
2912
2913 if (o->dirty_pixels)
2914 {
2915 if (o->func.get_pixels)
2916 {
2917 // Set img object for direct rendering optimization
2918 // Check for image w/h against image geometry w/h
2919 // Check for image color r,g,b,a = {255,255,255,255}
2920 // Check and make sure that there are no maps.
2921 if ( (obj->cur.geometry.w == o->cur.image.w) &&
2922 (obj->cur.geometry.h == o->cur.image.h) &&
2923 (obj->cur.color.r == 255) &&
2924 (obj->cur.color.g == 255) &&
2925 (obj->cur.color.b == 255) &&
2926 (obj->cur.color.a == 255) &&
2927 (!obj->cur.map) )
2928 {
2929 if (obj->layer->evas->engine.func->gl_img_obj_set)
2930 {
2931 obj->layer->evas->engine.func->gl_img_obj_set(output, obj, o->cur.has_alpha);
2932 img_set = 1;
2933 }
2934 }
2935
2936 o->func.get_pixels(o->func.get_pixels_data, obj);
2937 if (o->engine_data != pixels)
2938 pixels = o->engine_data;
2939 o->engine_data = obj->layer->evas->engine.func->image_dirty_region
2940 (obj->layer->evas->engine.data.output, o->engine_data,
2941 0, 0, o->cur.image.w, o->cur.image.h);
2942 }
2943 o->dirty_pixels = 0;
2944 }
2945 if ((obj->cur.map) && (obj->cur.map->count > 3) && (obj->cur.usemap))
2946 {
2947 const Evas_Map_Point *p, *p_end;
2948 RGBA_Map_Point pts[obj->cur.map->count], *pt;
2949
2950 p = obj->cur.map->points;
2951 p_end = p + obj->cur.map->count;
2952 pt = pts;
2953
2954 pts[0].px = obj->cur.map->persp.px << FP;
2955 pts[0].py = obj->cur.map->persp.py << FP;
2956 pts[0].foc = obj->cur.map->persp.foc << FP;
2957 pts[0].z0 = obj->cur.map->persp.z0 << FP;
2958 // draw geom +x +y
2959 for (; p < p_end; p++, pt++)
2960 {
2961 pt->x = (lround(p->x) + x) * FP1;
2962 pt->y = (lround(p->y) + y) * FP1;
2963 pt->z = (lround(p->z) ) * FP1;
2964 pt->fx = p->px;
2965 pt->fy = p->py;
2966 pt->fz = p->z;
2967 pt->u = ((lround(p->u) * imagew) / uvw) * FP1;
2968 pt->v = ((lround(p->v) * imageh) / uvh) * FP1;
2969 if (pt->u < 0) pt->u = 0;
2970 else if (pt->u > (imagew * FP1)) pt->u = (imagew * FP1);
2971 if (pt->v < 0) pt->v = 0;
2972 else if (pt->v > (imageh * FP1)) pt->v = (imageh * FP1);
2973 pt->col = ARGB_JOIN(p->a, p->r, p->g, p->b);
2974 }
2975 if (obj->cur.map->count & 0x1)
2976 {
2977 pts[obj->cur.map->count] = pts[obj->cur.map->count -1];
2978 }
2979
2980 obj->layer->evas->engine.func->image_map_draw
2981 (output, context, surface, pixels, obj->cur.map->count,
2982 pts, o->cur.smooth_scale | obj->cur.map->smooth, 0);
2983 }
2984 else
2985 {
2986 obj->layer->evas->engine.func->image_scale_hint_set(output,
2987 pixels,
2988 o->scale_hint);
2989 /* This is technically a bug here: If the value is recreated
2990 * (which is returned)it may be a new object, however exactly 0
2991 * of all the evas engines do this. */
2992 obj->layer->evas->engine.func->image_border_set(output, pixels,
2993 o->cur.border.l, o->cur.border.r,
2994 o->cur.border.t, o->cur.border.b);
2995 idx = evas_object_image_figure_x_fill(obj, o->cur.fill.x, o->cur.fill.w, &idw);
2996 idy = evas_object_image_figure_y_fill(obj, o->cur.fill.y, o->cur.fill.h, &idh);
2997 if (idw < 1) idw = 1;
2998 if (idh < 1) idh = 1;
2999 if (idx > 0) idx -= idw;
3000 if (idy > 0) idy -= idh;
3001 while ((int)idx < obj->cur.geometry.w)
3002 {
3003 Evas_Coord ydy;
3004 int dobreak_w = 0;
3005
3006 ydy = idy;
3007 ix = idx;
3008 if ((o->cur.fill.w == obj->cur.geometry.w) &&
3009 (o->cur.fill.x == 0))
3010 {
3011 dobreak_w = 1;
3012 iw = obj->cur.geometry.w;
3013 }
3014 else
3015 iw = ((int)(idx + idw)) - ix;
3016 while ((int)idy < obj->cur.geometry.h)
3017 {
3018 int dobreak_h = 0;
3019
3020 iy = idy;
3021 if ((o->cur.fill.h == obj->cur.geometry.h) &&
3022 (o->cur.fill.y == 0))
3023 {
3024 ih = obj->cur.geometry.h;
3025 dobreak_h = 1;
3026 }
3027 else
3028 ih = ((int)(idy + idh)) - iy;
3029 if ((o->cur.border.l == 0) &&
3030 (o->cur.border.r == 0) &&
3031 (o->cur.border.t == 0) &&
3032 (o->cur.border.b == 0) &&
3033 (o->cur.border.fill != 0))
3034 obj->layer->evas->engine.func->image_draw(output,
3035 context,
3036 surface,
3037 pixels,
3038 0, 0,
3039 imagew,
3040 imageh,
3041 obj->cur.geometry.x + ix + x,
3042 obj->cur.geometry.y + iy + y,
3043 iw, ih,
3044 o->cur.smooth_scale);
3045 else
3046 {
3047 int inx, iny, inw, inh, outx, outy, outw, outh;
3048 int bl, br, bt, bb, bsl, bsr, bst, bsb;
3049 int imw, imh, ox, oy;
3050
3051 ox = obj->cur.geometry.x + ix + x;
3052 oy = obj->cur.geometry.y + iy + y;
3053 imw = imagew;
3054 imh = imageh;
3055 bl = o->cur.border.l;
3056 br = o->cur.border.r;
3057 bt = o->cur.border.t;
3058 bb = o->cur.border.b;
3059 if ((bl + br) > iw)
3060 {
3061 bl = iw / 2;
3062 br = iw - bl;
3063 }
3064 if ((bl + br) > imw)
3065 {
3066 bl = imw / 2;
3067 br = imw - bl;
3068 }
3069 if ((bt + bb) > ih)
3070 {
3071 bt = ih / 2;
3072 bb = ih - bt;
3073 }
3074 if ((bt + bb) > imh)
3075 {
3076 bt = imh / 2;
3077 bb = imh - bt;
3078 }
3079 if (o->cur.border.scale != 1.0)
3080 {
3081 bsl = ((double)bl * o->cur.border.scale);
3082 bsr = ((double)br * o->cur.border.scale);
3083 bst = ((double)bt * o->cur.border.scale);
3084 bsb = ((double)bb * o->cur.border.scale);
3085 }
3086 else
3087 {
3088 bsl = bl; bsr = br; bst = bt; bsb = bb;
3089 }
3090 // #--
3091 // |
3092 inx = 0; iny = 0;
3093 inw = bl; inh = bt;
3094 outx = ox; outy = oy;
3095 outw = bsl; outh = bst;
3096 obj->layer->evas->engine.func->image_draw(output, context, surface, pixels, inx, iny, inw, inh, outx, outy, outw, outh, o->cur.smooth_scale);
3097 // .##
3098 // |
3099 inx = bl; iny = 0;
3100 inw = imw - bl - br; inh = bt;
3101 outx = ox + bsl; outy = oy;
3102 outw = iw - bsl - bsr; outh = bst;
3103 obj->layer->evas->engine.func->image_draw(output, context, surface, pixels, inx, iny, inw, inh, outx, outy, outw, outh, o->cur.smooth_scale);
3104 // --#
3105 // |
3106 inx = imw - br; iny = 0;
3107 inw = br; inh = bt;
3108 outx = ox + iw - bsr; outy = oy;
3109 outw = bsr; outh = bst;
3110 obj->layer->evas->engine.func->image_draw(output, context, surface, pixels, inx, iny, inw, inh, outx, outy, outw, outh, o->cur.smooth_scale);
3111 // .--
3112 // #
3113 inx = 0; iny = bt;
3114 inw = bl; inh = imh - bt - bb;
3115 outx = ox; outy = oy + bst;
3116 outw = bsl; outh = ih - bst - bsb;
3117 obj->layer->evas->engine.func->image_draw(output, context, surface, pixels, inx, iny, inw, inh, outx, outy, outw, outh, o->cur.smooth_scale);
3118 // .--.
3119 // |##|
3120 if (o->cur.border.fill > EVAS_BORDER_FILL_NONE)
3121 {
3122 inx = bl; iny = bt;
3123 inw = imw - bl - br; inh = imh - bt - bb;
3124 outx = ox + bsl; outy = oy + bst;
3125 outw = iw - bsl - bsr; outh = ih - bst - bsb;
3126 if ((o->cur.border.fill == EVAS_BORDER_FILL_SOLID) &&
3127 (obj->cur.cache.clip.a == 255) &&
3128 (obj->cur.render_op == EVAS_RENDER_BLEND))
3129 {
3130 obj->layer->evas->engine.func->context_render_op_set(output, context,
3131 EVAS_RENDER_COPY);
3132 obj->layer->evas->engine.func->image_draw(output, context, surface, pixels, inx, iny, inw, inh, outx, outy, outw, outh, o->cur.smooth_scale);
3133 obj->layer->evas->engine.func->context_render_op_set(output, context,
3134 obj->cur.render_op);
3135 }
3136 else
3137 obj->layer->evas->engine.func->image_draw(output, context, surface, pixels, inx, iny, inw, inh, outx, outy, outw, outh, o->cur.smooth_scale);
3138 }
3139 // --.
3140 // #
3141 inx = imw - br; iny = bt;
3142 inw = br; inh = imh - bt - bb;
3143 outx = ox + iw - bsr; outy = oy + bst;
3144 outw = bsr; outh = ih - bst - bsb;
3145 obj->layer->evas->engine.func->image_draw(output, context, surface, pixels, inx, iny, inw, inh, outx, outy, outw, outh, o->cur.smooth_scale);
3146 // |
3147 // #--
3148 inx = 0; iny = imh - bb;
3149 inw = bl; inh = bb;
3150 outx = ox; outy = oy + ih - bsb;
3151 outw = bsl; outh = bsb;
3152 obj->layer->evas->engine.func->image_draw(output, context, surface, pixels, inx, iny, inw, inh, outx, outy, outw, outh, o->cur.smooth_scale);
3153 // |
3154 // .##
3155 inx = bl; iny = imh - bb;
3156 inw = imw - bl - br; inh = bb;
3157 outx = ox + bsl; outy = oy + ih - bsb;
3158 outw = iw - bsl - bsr; outh = bsb;
3159 obj->layer->evas->engine.func->image_draw(output, context, surface, pixels, inx, iny, inw, inh, outx, outy, outw, outh, o->cur.smooth_scale);
3160 // |
3161 // --#
3162 inx = imw - br; iny = imh - bb;
3163 inw = br; inh = bb;
3164 outx = ox + iw - bsr; outy = oy + ih - bsb;
3165 outw = bsr; outh = bsb;
3166 obj->layer->evas->engine.func->image_draw(output, context, surface, pixels, inx, iny, inw, inh, outx, outy, outw, outh, o->cur.smooth_scale);
3167 }
3168 idy += idh;
3169 if (dobreak_h) break;
3170 }
3171 idx += idw;
3172 idy = ydy;
3173 if (dobreak_w) break;
3174 }
3175 }
3176
3177 // Unset img object
3178 if (img_set)
3179 {
3180 if (obj->layer->evas->engine.func->gl_img_obj_set)
3181 {
3182 obj->layer->evas->engine.func->gl_img_obj_set(output, NULL, 0);
3183 img_set = 0;
3184 }
3185 }
3186 }
3187}
3188
3189static void
3190evas_object_image_render_pre(Evas_Object *obj)
3191{
3192 Evas_Object_Image *o;
3193 int is_v = 0, was_v = 0;
3194 Evas *e;
3195
3196 /* dont pre-render the obj twice! */
3197 if (obj->pre_render_done) return;
3198 obj->pre_render_done = 1;
3199 /* pre-render phase. this does anything an object needs to do just before */
3200 /* rendering. this could mean loading the image data, retrieving it from */
3201 /* elsewhere, decoding video etc. */
3202 /* then when this is done the object needs to figure if it changed and */
3203 /* if so what and where and add the appropriate redraw rectangles */
3204 o = (Evas_Object_Image *)(obj->object_data);
3205 e = obj->layer->evas;
3206
3207 if ((o->cur.fill.w < 1) || (o->cur.fill.h < 1))
3208 {
3209 ERR("%p has invalid fill size: %dx%d. Ignored",
3210 obj, o->cur.fill.w, o->cur.fill.h);
3211 return;
3212 }
3213
3214 /* if someone is clipping this obj - go calculate the clipper */
3215 if (obj->cur.clipper)
3216 {
3217 if (obj->cur.cache.clip.dirty)
3218 evas_object_clip_recalc(obj->cur.clipper);
3219 obj->cur.clipper->func->render_pre(obj->cur.clipper);
3220 }
3221 /* Proxy: Do it early */
3222 if (o->cur.source &&
3223 (o->cur.source->proxy.redraw || o->cur.source->changed))
3224 {
3225 /* XXX: Do I need to sort out the map here? */
3226 evas_object_render_pre_prev_cur_add(&e->clip_changes, obj);
3227 goto done;
3228 }
3229
3230 /* now figure what changed and add draw rects */
3231 /* if it just became visible or invisible */
3232 is_v = evas_object_is_visible(obj);
3233 was_v = evas_object_was_visible(obj);
3234 if (is_v != was_v)
3235 {
3236 evas_object_render_pre_visible_change(&e->clip_changes, obj, is_v, was_v);
3237 if (!o->pixel_updates) goto done;
3238 }
3239 if ((obj->cur.map != obj->prev.map) ||
3240 (obj->cur.usemap != obj->prev.usemap))
3241 {
3242 evas_object_render_pre_prev_cur_add(&e->clip_changes, obj);
3243 goto done;
3244 }
3245 /* it's not visible - we accounted for it appearing or not so just abort */
3246 if (!is_v) goto done;
3247 /* clipper changed this is in addition to anything else for obj */
3248 evas_object_render_pre_clipper_change(&e->clip_changes, obj);
3249 /* if we restacked (layer or just within a layer) and don't clip anyone */
3250 if (obj->restack)
3251 {
3252 evas_object_render_pre_prev_cur_add(&e->clip_changes, obj);
3253 if (!o->pixel_updates) goto done;
3254 }
3255 /* if it changed color */
3256 if ((obj->cur.color.r != obj->prev.color.r) ||
3257 (obj->cur.color.g != obj->prev.color.g) ||
3258 (obj->cur.color.b != obj->prev.color.b) ||
3259 (obj->cur.color.a != obj->prev.color.a))
3260 {
3261 evas_object_render_pre_prev_cur_add(&e->clip_changes, obj);
3262 if (!o->pixel_updates) goto done;
3263 }
3264 /* if it changed render op */
3265 if (obj->cur.render_op != obj->prev.render_op)
3266 {
3267 evas_object_render_pre_prev_cur_add(&e->clip_changes, obj);
3268 if (!o->pixel_updates) goto done;
3269 }
3270 /* if it changed anti_alias */
3271 if (obj->cur.anti_alias != obj->prev.anti_alias)
3272 {
3273 evas_object_render_pre_prev_cur_add(&e->clip_changes, obj);
3274 if (!o->pixel_updates) goto done;
3275 }
3276 if (o->changed)
3277 {
3278 if (((o->cur.file) && (!o->prev.file)) ||
3279 ((!o->cur.file) && (o->prev.file)) ||
3280 ((o->cur.key) && (!o->prev.key)) ||
3281 ((!o->cur.key) && (o->prev.key))
3282 )
3283 {
3284 evas_object_render_pre_prev_cur_add(&e->clip_changes, obj);
3285 if (!o->pixel_updates) goto done;
3286 }
3287 if ((o->cur.image.w != o->prev.image.w) ||
3288 (o->cur.image.h != o->prev.image.h) ||
3289 (o->cur.has_alpha != o->prev.has_alpha) ||
3290 (o->cur.cspace != o->prev.cspace) ||
3291 (o->cur.smooth_scale != o->prev.smooth_scale))
3292 {
3293 evas_object_render_pre_prev_cur_add(&e->clip_changes, obj);
3294 if (!o->pixel_updates) goto done;
3295 }
3296 if ((o->cur.border.l != o->prev.border.l) ||
3297 (o->cur.border.r != o->prev.border.r) ||
3298 (o->cur.border.t != o->prev.border.t) ||
3299 (o->cur.border.b != o->prev.border.b) ||
3300 (o->cur.border.fill != o->prev.border.fill) ||
3301 (o->cur.border.scale != o->prev.border.scale))
3302 {
3303 evas_object_render_pre_prev_cur_add(&e->clip_changes, obj);
3304 if (!o->pixel_updates) goto done;
3305 }
3306 if (o->dirty_pixels)
3307 {
3308 evas_object_render_pre_prev_cur_add(&e->clip_changes, obj);
3309 if (!o->pixel_updates) goto done;
3310 }
3311 if (o->cur.frame != o->prev.frame)
3312 {
3313 evas_object_render_pre_prev_cur_add(&e->clip_changes, obj);
3314 if (!o->pixel_updates) goto done;
3315 }
3316
3317 }
3318 /* if it changed geometry - and obviously not visibility or color */
3319 /* calculate differences since we have a constant color fill */
3320 /* we really only need to update the differences */
3321#if 0 // XXX: maybe buggy?
3322 if (((obj->cur.geometry.x != obj->prev.geometry.x) ||
3323 (obj->cur.geometry.y != obj->prev.geometry.y) ||
3324 (obj->cur.geometry.w != obj->prev.geometry.w) ||
3325 (obj->cur.geometry.h != obj->prev.geometry.h)) &&
3326 (o->cur.fill.w == o->prev.fill.w) &&
3327 (o->cur.fill.h == o->prev.fill.h) &&
3328 ((o->cur.fill.x + obj->cur.geometry.x) == (o->prev.fill.x + obj->prev.geometry.x)) &&
3329 ((o->cur.fill.y + obj->cur.geometry.y) == (o->prev.fill.y + obj->prev.geometry.y)) &&
3330 (!o->pixel_updates)
3331 )
3332 {
3333 evas_rects_return_difference_rects(&e->clip_changes,
3334 obj->cur.geometry.x,
3335 obj->cur.geometry.y,
3336 obj->cur.geometry.w,
3337 obj->cur.geometry.h,
3338 obj->prev.geometry.x,
3339 obj->prev.geometry.y,
3340 obj->prev.geometry.w,
3341 obj->prev.geometry.h);
3342 if (!o->pixel_updates) goto done;
3343 }
3344#endif
3345 if (((obj->cur.geometry.x != obj->prev.geometry.x) ||
3346 (obj->cur.geometry.y != obj->prev.geometry.y) ||
3347 (obj->cur.geometry.w != obj->prev.geometry.w) ||
3348 (obj->cur.geometry.h != obj->prev.geometry.h))
3349 )
3350 {
3351 evas_object_render_pre_prev_cur_add(&e->clip_changes, obj);
3352 if (!o->pixel_updates) goto done;
3353 }
3354 if (o->changed)
3355 {
3356 if ((o->cur.fill.x != o->prev.fill.x) ||
3357 (o->cur.fill.y != o->prev.fill.y) ||
3358 (o->cur.fill.w != o->prev.fill.w) ||
3359 (o->cur.fill.h != o->prev.fill.h))
3360 {
3361 evas_object_render_pre_prev_cur_add(&e->clip_changes, obj);
3362 if (!o->pixel_updates) goto done;
3363 }
3364 if (o->pixel_updates)
3365 {
3366 if ((o->cur.border.l == 0) &&
3367 (o->cur.border.r == 0) &&
3368 (o->cur.border.t == 0) &&
3369 (o->cur.border.b == 0) &&
3370 (o->cur.image.w > 0) &&
3371 (o->cur.image.h > 0) &&
3372 (!((obj->cur.map) && (obj->cur.usemap))))
3373 {
3374 Eina_Rectangle *rr;
3375
3376 EINA_LIST_FREE(o->pixel_updates, rr)
3377 {
3378 Evas_Coord idw, idh, idx, idy;
3379 int x, y, w, h;
3380
3381 e->engine.func->image_dirty_region(e->engine.data.output, o->engine_data, rr->x, rr->y, rr->w, rr->h);
3382
3383 idx = evas_object_image_figure_x_fill(obj, o->cur.fill.x, o->cur.fill.w, &idw);
3384 idy = evas_object_image_figure_y_fill(obj, o->cur.fill.y, o->cur.fill.h, &idh);
3385
3386 if (idw < 1) idw = 1;
3387 if (idh < 1) idh = 1;
3388 if (idx > 0) idx -= idw;
3389 if (idy > 0) idy -= idh;
3390 while (idx < obj->cur.geometry.w)
3391 {
3392 Evas_Coord ydy;
3393
3394 ydy = idy;
3395 x = idx;
3396 w = ((int)(idx + idw)) - x;
3397 while (idy < obj->cur.geometry.h)
3398 {
3399 Eina_Rectangle r;
3400
3401 y = idy;
3402 h = ((int)(idy + idh)) - y;
3403
3404 r.x = (rr->x * w) / o->cur.image.w;
3405 r.y = (rr->y * h) / o->cur.image.h;
3406 r.w = ((rr->w * w) + (o->cur.image.w * 2) - 1) / o->cur.image.w;
3407 r.h = ((rr->h * h) + (o->cur.image.h * 2) - 1) / o->cur.image.h;
3408 r.x += obj->cur.geometry.x + x;
3409 r.y += obj->cur.geometry.y + y;
3410 RECTS_CLIP_TO_RECT(r.x, r.y, r.w, r.h,
3411 obj->cur.cache.clip.x, obj->cur.cache.clip.y,
3412 obj->cur.cache.clip.w, obj->cur.cache.clip.h);
3413 evas_add_rect(&e->clip_changes, r.x, r.y, r.w, r.h);
3414 idy += h;
3415 }
3416 idx += idw;
3417 idy = ydy;
3418 }
3419 eina_rectangle_free(rr);
3420 }
3421 goto done;
3422 }
3423 else
3424 {
3425 Eina_Rectangle *r;
3426
3427 EINA_LIST_FREE(o->pixel_updates, r)
3428 eina_rectangle_free(r);
3429 e->engine.func->image_dirty_region(e->engine.data.output, o->engine_data, 0, 0, o->cur.image.w, o->cur.image.h);
3430 evas_object_render_pre_prev_cur_add(&e->clip_changes, obj);
3431 goto done;
3432 }
3433 }
3434 }
3435#if 0 // filtering disabled
3436 if (obj->filter && obj->filter->dirty)
3437 {
3438 evas_object_render_pre_prev_cur_add(&e->clip_changes, obj);
3439 }
3440#endif
3441 /* it obviously didn't change - add a NO obscure - this "unupdates" this */
3442 /* area so if there were updates for it they get wiped. don't do it if we */
3443 /* aren't fully opaque and we are visible */
3444 if (evas_object_is_visible(obj) &&
3445 evas_object_is_opaque(obj))
3446 {
3447 Evas_Coord x, y, w, h;
3448
3449 x = obj->cur.cache.clip.x;
3450 y = obj->cur.cache.clip.y;
3451 w = obj->cur.cache.clip.w;
3452 h = obj->cur.cache.clip.h;
3453 if (obj->cur.clipper)
3454 {
3455 RECTS_CLIP_TO_RECT(x, y, w, h,
3456 obj->cur.clipper->cur.cache.clip.x,
3457 obj->cur.clipper->cur.cache.clip.y,
3458 obj->cur.clipper->cur.cache.clip.w,
3459 obj->cur.clipper->cur.cache.clip.h);
3460 }
3461 e->engine.func->output_redraws_rect_del(e->engine.data.output,
3462 x, y, w, h);
3463 }
3464 done:
3465 evas_object_render_pre_effect_updates(&e->clip_changes, obj, is_v, was_v);
3466}
3467
3468static void
3469evas_object_image_render_post(Evas_Object *obj)
3470{
3471 Evas_Object_Image *o;
3472 Eina_Rectangle *r;
3473
3474 /* this moves the current data to the previous state parts of the object */
3475 /* in whatever way is safest for the object. also if we don't need object */
3476 /* data anymore we can free it if the object deems this is a good idea */
3477 o = (Evas_Object_Image *)(obj->object_data);
3478 /* remove those pesky changes */
3479 evas_object_clip_changes_clean(obj);
3480 EINA_LIST_FREE(o->pixel_updates, r)
3481 eina_rectangle_free(r);
3482 /* move cur to prev safely for object data */
3483 obj->prev = obj->cur;
3484 o->prev = o->cur;
3485 o->changed = 0;
3486 /* FIXME: copy strings across */
3487}
3488
3489static unsigned int evas_object_image_id_get(Evas_Object *obj)
3490{
3491 Evas_Object_Image *o;
3492
3493 o = (Evas_Object_Image *)(obj->object_data);
3494 if (!o) return 0;
3495 return MAGIC_OBJ_IMAGE;
3496}
3497
3498static unsigned int evas_object_image_visual_id_get(Evas_Object *obj)
3499{
3500 Evas_Object_Image *o;
3501
3502 o = (Evas_Object_Image *)(obj->object_data);
3503 if (!o) return 0;
3504 return MAGIC_OBJ_IMAGE;
3505}
3506
3507static void *evas_object_image_engine_data_get(Evas_Object *obj)
3508{
3509 Evas_Object_Image *o;
3510
3511 o = (Evas_Object_Image *)(obj->object_data);
3512 if (!o) return NULL;
3513 return o->engine_data;
3514}
3515
3516static int
3517evas_object_image_is_opaque(Evas_Object *obj)
3518{
3519 Evas_Object_Image *o;
3520
3521 /* this returns 1 if the internal object data implies that the object is */
3522 /* currently fully opaque over the entire rectangle it occupies */
3523 o = (Evas_Object_Image *)(obj->object_data);
3524/* disable caching due tyo maps screwing with this
3525 o->cur.opaque_valid = 0;
3526 if (o->cur.opaque_valid)
3527 {
3528 if (!o->cur.opaque) return 0;
3529 }
3530 else
3531*/
3532 {
3533 o->cur.opaque = 0;
3534/* disable caching */
3535/* o->cur.opaque_valid = 1; */
3536 if ((o->cur.fill.w < 1) || (o->cur.fill.h < 1))
3537 return o->cur.opaque;
3538 if (((o->cur.border.l != 0) ||
3539 (o->cur.border.r != 0) ||
3540 (o->cur.border.t != 0) ||
3541 (o->cur.border.b != 0)) &&
3542 (!o->cur.border.fill)) return o->cur.opaque;
3543 if (!o->engine_data) return o->cur.opaque;
3544 o->cur.opaque = 1;
3545 }
3546 // FIXME: use proxy
3547 if (o->cur.source)
3548 {
3549 o->cur.opaque = evas_object_is_opaque(o->cur.source);
3550 return o->cur.opaque; /* FIXME: Should go poke at the object */
3551 }
3552 if (o->cur.has_alpha)
3553 {
3554 o->cur.opaque = 0;
3555 return o->cur.opaque;
3556 }
3557 if ((obj->cur.map) && (obj->cur.usemap))
3558 {
3559 Evas_Map *m = obj->cur.map;
3560
3561 if ((m->points[0].a == 255) &&
3562 (m->points[1].a == 255) &&
3563 (m->points[2].a == 255) &&
3564 (m->points[3].a == 255))
3565 {
3566 if (
3567 ((m->points[0].x == m->points[3].x) &&
3568 (m->points[1].x == m->points[2].x) &&
3569 (m->points[0].y == m->points[1].y) &&
3570 (m->points[2].y == m->points[3].y))
3571 ||
3572 ((m->points[0].x == m->points[1].x) &&
3573 (m->points[2].x == m->points[3].x) &&
3574 (m->points[0].y == m->points[3].y) &&
3575 (m->points[1].y == m->points[2].y))
3576 )
3577 {
3578 if ((m->points[0].x == obj->cur.geometry.x) &&
3579 (m->points[0].y == obj->cur.geometry.y) &&
3580 (m->points[2].x == (obj->cur.geometry.x + obj->cur.geometry.w)) &&
3581 (m->points[2].y == (obj->cur.geometry.y + obj->cur.geometry.h)))
3582 return o->cur.opaque;
3583 }
3584 }
3585 o->cur.opaque = 0;
3586 return o->cur.opaque;
3587 }
3588 if (obj->cur.render_op == EVAS_RENDER_COPY) return o->cur.opaque;
3589 return o->cur.opaque;
3590}
3591
3592static int
3593evas_object_image_was_opaque(Evas_Object *obj)
3594{
3595 Evas_Object_Image *o;
3596
3597 /* this returns 1 if the internal object data implies that the object was */
3598 /* previously fully opaque over the entire rectangle it occupies */
3599 o = (Evas_Object_Image *)(obj->object_data);
3600 if (o->prev.opaque_valid)
3601 {
3602 if (!o->prev.opaque) return 0;
3603 }
3604 else
3605 {
3606 o->prev.opaque = 0;
3607 o->prev.opaque_valid = 1;
3608 if ((o->prev.fill.w < 1) || (o->prev.fill.h < 1))
3609 return 0;
3610 if (((o->prev.border.l != 0) ||
3611 (o->prev.border.r != 0) ||
3612 (o->prev.border.t != 0) ||
3613 (o->prev.border.b != 0)) &&
3614 (!o->prev.border.fill)) return 0;
3615 if (!o->engine_data) return 0;
3616 o->prev.opaque = 1;
3617 }
3618 // FIXME: use proxy
3619 if (o->prev.source) return 0; /* FIXME: Should go poke at the object */
3620 if (obj->prev.usemap) return 0;
3621 if (obj->prev.render_op == EVAS_RENDER_COPY) return 1;
3622 if (o->prev.has_alpha) return 0;
3623 if (obj->prev.render_op != EVAS_RENDER_BLEND) return 0;
3624 return 1;
3625}
3626
3627static int
3628evas_object_image_is_inside(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
3629{
3630 Evas_Object_Image *o;
3631 DATA32 *data;
3632 int w, h, stride, iw, ih;
3633 int a;
3634
3635 o = (Evas_Object_Image *)(obj->object_data);
3636
3637 x -= obj->cur.cache.clip.x;
3638 y -= obj->cur.cache.clip.y;
3639 w = obj->cur.cache.clip.w;
3640 h = obj->cur.cache.clip.h;
3641 iw = o->cur.image.w;
3642 ih = o->cur.image.h;
3643
3644 if ((x < 0) || (y < 0) || (x >= w) || (y >= h)) return 0;
3645 if (!o->cur.has_alpha) return 1;
3646
3647 // FIXME: proxy needs to be honored
3648 if (obj->cur.map)
3649 {
3650 x = obj->cur.map->mx;
3651 y = obj->cur.map->my;
3652 }
3653 else
3654 {
3655 int bl, br, bt, bb, bsl, bsr, bst, bsb;
3656
3657 bl = o->cur.border.l;
3658 br = o->cur.border.r;
3659 bt = o->cur.border.t;
3660 bb = o->cur.border.b;
3661 if ((bl + br) > iw)
3662 {
3663 bl = iw / 2;
3664 br = iw - bl;
3665 }
3666 if ((bl + br) > iw)
3667 {
3668 bl = iw / 2;
3669 br = iw - bl;
3670 }
3671 if ((bt + bb) > ih)
3672 {
3673 bt = ih / 2;
3674 bb = ih - bt;
3675 }
3676 if ((bt + bb) > ih)
3677 {
3678 bt = ih / 2;
3679 bb = ih - bt;
3680 }
3681 if (o->cur.border.scale != 1.0)
3682 {
3683 bsl = ((double)bl * o->cur.border.scale);
3684 bsr = ((double)br * o->cur.border.scale);
3685 bst = ((double)bt * o->cur.border.scale);
3686 bsb = ((double)bb * o->cur.border.scale);
3687 }
3688 else
3689 {
3690 bsl = bl; bsr = br; bst = bt; bsb = bb;
3691 }
3692
3693 w = o->cur.fill.w;
3694 h = o->cur.fill.h;
3695 x -= o->cur.fill.x;
3696 y -= o->cur.fill.y;
3697 x %= w;
3698 y %= h;
3699
3700 if (x < 0) x += w;
3701 if (y < 0) y += h;
3702
3703 if (o->cur.border.fill != EVAS_BORDER_FILL_DEFAULT)
3704 {
3705 if ((x > bsl) && (x < (w - bsr)) &&
3706 (y > bst) && (y < (h - bsb)))
3707 {
3708 if (o->cur.border.fill == EVAS_BORDER_FILL_SOLID) return 1;
3709 return 0;
3710 }
3711 }
3712
3713 if (x < bsl) x = (x * bl) / bsl;
3714 else if (x > (w - bsr)) x = iw - (((w - x) * br) / bsr);
3715 else if ((bsl + bsr) < w) x = bl + (((x - bsl) * (iw - bl - br)) / (w - bsl - bsr));
3716 else return 1;
3717
3718 if (y < bst) y = (y * bt) / bst;
3719 else if (y > (h - bsb)) y = ih - (((h - y) * bb) / bsb);
3720 else if ((bst + bsb) < h) y = bt + (((y - bst) * (ih - bt - bb)) / (h - bst - bsb));
3721 else return 1;
3722 }
3723
3724 if (x < 0) x = 0;
3725 if (y < 0) y = 0;
3726 if (x >= iw) x = iw - 1;
3727 if (y >= ih) y = ih - 1;
3728
3729 stride = o->cur.image.stride;
3730
3731 o->engine_data = obj->layer->evas->engine.func->image_data_get
3732 (obj->layer->evas->engine.data.output,
3733 o->engine_data,
3734 0,
3735 &data,
3736 &o->load_error);
3737 if (!data)
3738 return 0;
3739
3740 switch (o->cur.cspace)
3741 {
3742 case EVAS_COLORSPACE_ARGB8888:
3743 data = ((DATA32*)(data) + ((y * (stride >> 2)) + x));
3744 a = (*((DATA32*)(data)) >> 24) & 0xff;
3745 break;
3746 case EVAS_COLORSPACE_RGB565_A5P:
3747 data = (void*) ((DATA16*)(data) + (h * (stride >> 1)));
3748 data = (void*) ((DATA8*)(data) + ((y * (stride >> 1)) + x));
3749 a = (*((DATA8*)(data))) & 0x1f;
3750 break;
3751 default:
3752 return 1;
3753 break;
3754 }
3755
3756 return (a != 0);
3757}
3758
3759static int
3760evas_object_image_has_opaque_rect(Evas_Object *obj)
3761{
3762 Evas_Object_Image *o;
3763
3764 o = (Evas_Object_Image *)(obj->object_data);
3765 if ((obj->cur.map) && (obj->cur.usemap)) return 0;
3766 if (((o->cur.border.l | o->cur.border.r | o->cur.border.t | o->cur.border.b) != 0) &&
3767 (o->cur.border.fill == EVAS_BORDER_FILL_SOLID) &&
3768 (obj->cur.render_op == EVAS_RENDER_BLEND) &&
3769 (obj->cur.cache.clip.a == 255) &&
3770 (o->cur.fill.x == 0) &&
3771 (o->cur.fill.y == 0) &&
3772 (o->cur.fill.w == obj->cur.geometry.w) &&
3773 (o->cur.fill.h == obj->cur.geometry.h)
3774 ) return 1;
3775 return 0;
3776}
3777
3778static int
3779evas_object_image_get_opaque_rect(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h)
3780{
3781 Evas_Object_Image *o;
3782
3783 o = (Evas_Object_Image *)(obj->object_data);
3784 if (o->cur.border.scale == 1.0)
3785 {
3786 *x = obj->cur.geometry.x + o->cur.border.l;
3787 *y = obj->cur.geometry.y + o->cur.border.t;
3788 *w = obj->cur.geometry.w - (o->cur.border.l + o->cur.border.r);
3789 if (*w < 0) *w = 0;
3790 *h = obj->cur.geometry.h - (o->cur.border.t + o->cur.border.b);
3791 if (*h < 0) *h = 0;
3792 }
3793 else
3794 {
3795 *x = obj->cur.geometry.x + (o->cur.border.l * o->cur.border.scale);
3796 *y = obj->cur.geometry.y + (o->cur.border.t * o->cur.border.scale);
3797 *w = obj->cur.geometry.w - ((o->cur.border.l * o->cur.border.scale) + (o->cur.border.r * o->cur.border.scale));
3798 if (*w < 0) *w = 0;
3799 *h = obj->cur.geometry.h - ((o->cur.border.t * o->cur.border.scale) + (o->cur.border.b * o->cur.border.scale));
3800 if (*h < 0) *h = 0;
3801 }
3802 return 1;
3803}
3804
3805static int
3806evas_object_image_can_map(Evas_Object *obj __UNUSED__)
3807{
3808 return 1;
3809}
3810
3811static void *
3812evas_object_image_data_convert_internal(Evas_Object_Image *o, void *data, Evas_Colorspace to_cspace)
3813{
3814 void *out = NULL;
3815
3816 if (!data)
3817 return NULL;
3818
3819 switch (o->cur.cspace)
3820 {
3821 case EVAS_COLORSPACE_ARGB8888:
3822 out = evas_common_convert_argb8888_to(data,
3823 o->cur.image.w,
3824 o->cur.image.h,
3825 o->cur.image.stride >> 2,
3826 o->cur.has_alpha,
3827 to_cspace);
3828 break;
3829 case EVAS_COLORSPACE_RGB565_A5P:
3830 out = evas_common_convert_rgb565_a5p_to(data,
3831 o->cur.image.w,
3832 o->cur.image.h,
3833 o->cur.image.stride >> 1,
3834 o->cur.has_alpha,
3835 to_cspace);
3836 break;
3837 case EVAS_COLORSPACE_YCBCR422601_PL:
3838 out = evas_common_convert_yuv_422_601_to(data,
3839 o->cur.image.w,
3840 o->cur.image.h,
3841 to_cspace);
3842 break;
3843 case EVAS_COLORSPACE_YCBCR422P601_PL:
3844 out = evas_common_convert_yuv_422P_601_to(data,
3845 o->cur.image.w,
3846 o->cur.image.h,
3847 to_cspace);
3848 break;
3849 case EVAS_COLORSPACE_YCBCR420NV12601_PL:
3850 out = evas_common_convert_yuv_420_601_to(data,
3851 o->cur.image.w,
3852 o->cur.image.h,
3853 to_cspace);
3854 break;
3855 case EVAS_COLORSPACE_YCBCR420TM12601_PL:
3856 out = evas_common_convert_yuv_420T_601_to(data,
3857 o->cur.image.w,
3858 o->cur.image.h,
3859 to_cspace);
3860 break;
3861 default:
3862 WRN("unknow colorspace: %i\n", o->cur.cspace);
3863 break;
3864 }
3865
3866 return out;
3867}
3868
3869static void
3870evas_object_image_filled_resize_listener(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *einfo __UNUSED__)
3871{
3872 Evas_Coord w, h;
3873
3874 evas_object_geometry_get(obj, NULL, NULL, &w, &h);
3875 evas_object_image_fill_set(obj, 0, 0, w, h);
3876}
3877
3878
3879Eina_Bool
3880_evas_object_image_preloading_get(const Evas_Object *obj)
3881{
3882 Evas_Object_Image *o = (Evas_Object_Image *)(obj->object_data);
3883 if (!o) return EINA_FALSE;
3884 MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
3885 return EINA_FALSE;
3886 MAGIC_CHECK_END();
3887 return o->preloading;
3888}
3889
3890void
3891_evas_object_image_preloading_set(Evas_Object *obj, Eina_Bool preloading)
3892{
3893 Evas_Object_Image *o = (Evas_Object_Image *)(obj->object_data);
3894 o->preloading = preloading;
3895}
3896
3897void
3898_evas_object_image_preloading_check(Evas_Object *obj)
3899{
3900 Evas_Object_Image *o = (Evas_Object_Image *)(obj->object_data);
3901 if (obj->layer->evas->engine.func->image_load_error_get)
3902 o->load_error = obj->layer->evas->engine.func->image_load_error_get
3903 (obj->layer->evas->engine.data.output, o->engine_data);
3904}
3905
3906Evas_Object *
3907_evas_object_image_video_parent_get(Evas_Object *obj)
3908{
3909 Evas_Object_Image *o = (Evas_Object_Image *)(obj->object_data);
3910
3911 return o->video_surface ? o->video.parent : NULL;
3912}
3913
3914void
3915_evas_object_image_video_overlay_show(Evas_Object *obj)
3916{
3917 Evas_Object_Image *o = (Evas_Object_Image *)(obj->object_data);
3918
3919 if (obj->cur.cache.clip.x != obj->prev.cache.clip.x ||
3920 obj->cur.cache.clip.y != obj->prev.cache.clip.y ||
3921 o->created || !o->video_visible)
3922 o->video.move(o->video.data, obj, &o->video, obj->cur.cache.clip.x, obj->cur.cache.clip.y);
3923 if (obj->cur.cache.clip.w != obj->prev.cache.clip.w ||
3924 obj->cur.cache.clip.h != obj->prev.cache.clip.h ||
3925 o->created || !o->video_visible)
3926 o->video.resize(o->video.data, obj, &o->video, obj->cur.cache.clip.w, obj->cur.cache.clip.h);
3927 if (!o->video_visible || o->created)
3928 {
3929 o->video.show(o->video.data, obj, &o->video);
3930 }
3931 else
3932 {
3933 /* Cancel dirty on the image */
3934 Eina_Rectangle *r;
3935
3936 o->dirty_pixels = 0;
3937 EINA_LIST_FREE(o->pixel_updates, r)
3938 eina_rectangle_free(r);
3939 }
3940 o->video_visible = EINA_TRUE;
3941 o->created = EINA_FALSE;
3942}
3943
3944void
3945_evas_object_image_video_overlay_hide(Evas_Object *obj)
3946{
3947 Evas_Object_Image *o = (Evas_Object_Image *)(obj->object_data);
3948
3949 if (o->video_visible || o->created)
3950 o->video.hide(o->video.data, obj, &o->video);
3951 if (evas_object_is_visible(obj))
3952 o->video.update_pixels(o->video.data, obj, &o->video);
3953 o->video_visible = EINA_FALSE;
3954 o->created = EINA_FALSE;
3955}
3956
3957/* vim:set ts=8 sw=3 sts=3 expandtab cino=>5n-2f0^-2{2(0W1st0 :*/
diff --git a/libraries/evas/src/lib/canvas/evas_object_inform.c b/libraries/evas/src/lib/canvas/evas_object_inform.c
deleted file mode 100644
index 302da42..0000000
--- a/libraries/evas/src/lib/canvas/evas_object_inform.c
+++ /dev/null
@@ -1,79 +0,0 @@
1#include "evas_common.h"
2#include "evas_private.h"
3
4/* local calls */
5
6void
7evas_object_inform_call_show(Evas_Object *obj)
8{
9 _evas_object_event_new();
10
11 evas_object_event_callback_call(obj, EVAS_CALLBACK_SHOW, NULL, _evas_event_counter);
12 _evas_post_event_callback_call(obj->layer->evas);
13}
14
15void
16evas_object_inform_call_hide(Evas_Object *obj)
17{
18 _evas_object_event_new();
19
20 evas_object_event_callback_call(obj, EVAS_CALLBACK_HIDE, NULL, _evas_event_counter);
21 _evas_post_event_callback_call(obj->layer->evas);
22}
23
24void
25evas_object_inform_call_move(Evas_Object *obj)
26{
27 _evas_object_event_new();
28
29 evas_object_event_callback_call(obj, EVAS_CALLBACK_MOVE, NULL, _evas_event_counter);
30 _evas_post_event_callback_call(obj->layer->evas);
31}
32
33void
34evas_object_inform_call_resize(Evas_Object *obj)
35{
36 _evas_object_event_new();
37
38 evas_object_event_callback_call(obj, EVAS_CALLBACK_RESIZE, NULL, _evas_event_counter);
39 _evas_post_event_callback_call(obj->layer->evas);
40}
41
42void
43evas_object_inform_call_restack(Evas_Object *obj)
44{
45 _evas_object_event_new();
46
47 evas_object_event_callback_call(obj, EVAS_CALLBACK_RESTACK, NULL, _evas_event_counter);
48 _evas_post_event_callback_call(obj->layer->evas);
49}
50
51void
52evas_object_inform_call_changed_size_hints(Evas_Object *obj)
53{
54 _evas_object_event_new();
55
56 evas_object_event_callback_call(obj, EVAS_CALLBACK_CHANGED_SIZE_HINTS, NULL, _evas_event_counter);
57 _evas_post_event_callback_call(obj->layer->evas);
58}
59
60void
61evas_object_inform_call_image_preloaded(Evas_Object *obj)
62{
63 if (!_evas_object_image_preloading_get(obj)) return;
64 _evas_object_image_preloading_check(obj);
65 _evas_object_image_preloading_set(obj, 0);
66 _evas_object_event_new();
67
68 evas_object_event_callback_call(obj, EVAS_CALLBACK_IMAGE_PRELOADED, NULL, _evas_event_counter);
69 _evas_post_event_callback_call(obj->layer->evas);
70}
71
72void
73evas_object_inform_call_image_unloaded(Evas_Object *obj)
74{
75 _evas_object_event_new();
76
77 evas_object_event_callback_call(obj, EVAS_CALLBACK_IMAGE_UNLOADED, NULL, _evas_event_counter);
78 _evas_post_event_callback_call(obj->layer->evas);
79}
diff --git a/libraries/evas/src/lib/canvas/evas_object_intercept.c b/libraries/evas/src/lib/canvas/evas_object_intercept.c
deleted file mode 100644
index 54f7265..0000000
--- a/libraries/evas/src/lib/canvas/evas_object_intercept.c
+++ /dev/null
@@ -1,585 +0,0 @@
1#include "evas_common.h"
2#include "evas_private.h"
3
4/* local calls */
5
6static void evas_object_intercept_init(Evas_Object *obj);
7static void evas_object_intercept_deinit(Evas_Object *obj);
8
9static void
10evas_object_intercept_init(Evas_Object *obj)
11{
12 if (!obj->interceptors)
13 obj->interceptors = evas_mem_calloc(sizeof(Evas_Intercept_Func));
14}
15
16static void
17evas_object_intercept_deinit(Evas_Object *obj)
18{
19 if (!obj->interceptors) return;
20 if ((obj->interceptors->show.func) ||
21 (obj->interceptors->hide.func) ||
22 (obj->interceptors->move.func) ||
23 (obj->interceptors->resize.func) ||
24 (obj->interceptors->raise.func) ||
25 (obj->interceptors->lower.func) ||
26 (obj->interceptors->stack_above.func) ||
27 (obj->interceptors->stack_below.func) ||
28 (obj->interceptors->layer_set.func) ||
29 (obj->interceptors->color_set.func) ||
30 (obj->interceptors->clip_set.func) ||
31 (obj->interceptors->clip_unset.func))
32 return;
33 free(obj->interceptors);
34 obj->interceptors = NULL;
35}
36
37/* private calls */
38
39void
40evas_object_intercept_cleanup(Evas_Object *obj)
41{
42 if (obj->interceptors) free(obj->interceptors);
43}
44
45int
46evas_object_intercept_call_show(Evas_Object *obj)
47{
48 int ret;
49
50 if (!obj->interceptors) return 0;
51 if (obj->intercepted) return 0;
52 obj->intercepted = EINA_TRUE;
53 ret = !!(obj->interceptors->show.func);
54 if (ret)
55 obj->interceptors->show.func(obj->interceptors->show.data, obj);
56 obj->intercepted = EINA_FALSE;
57 return ret;
58}
59
60int
61evas_object_intercept_call_hide(Evas_Object *obj)
62{
63 int ret;
64
65 if (!obj->interceptors) return 0;
66 if (obj->intercepted) return 0;
67 obj->intercepted = EINA_TRUE;
68 ret = !!(obj->interceptors->hide.func);
69 if (ret)
70 obj->interceptors->hide.func(obj->interceptors->hide.data, obj);
71 obj->intercepted = EINA_FALSE;
72 return ret;
73}
74
75int
76evas_object_intercept_call_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
77{
78 int ret;
79
80 if (!obj->interceptors) return 0;
81 if (obj->intercepted) return 0;
82 obj->intercepted = EINA_TRUE;
83 ret = !!(obj->interceptors->move.func);
84 if (ret)
85 obj->interceptors->move.func(obj->interceptors->move.data, obj, x, y);
86 obj->intercepted = EINA_FALSE;
87 return ret;
88}
89
90int
91evas_object_intercept_call_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h)
92{
93 int ret;
94
95 if (!obj->interceptors) return 0;
96 if (obj->intercepted) return 0;
97 obj->intercepted = EINA_TRUE;
98 ret = !!(obj->interceptors->resize.func);
99 if (ret)
100 obj->interceptors->resize.func(obj->interceptors->resize.data, obj, w, h);
101 obj->intercepted = EINA_FALSE;
102 return ret;
103}
104
105int
106evas_object_intercept_call_raise(Evas_Object *obj)
107{
108 int ret;
109
110 if (!obj->interceptors) return 0;
111 if (obj->intercepted) return 0;
112 obj->intercepted = EINA_TRUE;
113 ret = !!(obj->interceptors->raise.func);
114 if (ret)
115 obj->interceptors->raise.func(obj->interceptors->raise.data, obj);
116 obj->intercepted = EINA_FALSE;
117 return ret;
118}
119
120int
121evas_object_intercept_call_lower(Evas_Object *obj)
122{
123 int ret;
124
125 if (!obj->interceptors) return 0;
126 if (obj->intercepted) return 0;
127 obj->intercepted = EINA_TRUE;
128 ret = !!(obj->interceptors->lower.func);
129 if (ret)
130 obj->interceptors->lower.func(obj->interceptors->lower.data, obj);
131 obj->intercepted = EINA_FALSE;
132 return ret;
133}
134
135int
136evas_object_intercept_call_stack_above(Evas_Object *obj, Evas_Object *above)
137{
138 int ret;
139
140 if (!obj->interceptors) return 0;
141 if (obj->intercepted) return 0;
142 obj->intercepted = EINA_TRUE;
143 ret = !!(obj->interceptors->stack_above.func);
144 if (ret)
145 obj->interceptors->stack_above.func(obj->interceptors->stack_above.data, obj, above);
146 obj->intercepted = EINA_FALSE;
147 return ret;
148}
149
150int
151evas_object_intercept_call_stack_below(Evas_Object *obj, Evas_Object *below)
152{
153 int ret;
154
155 if (!obj->interceptors) return 0;
156 if (obj->intercepted) return 0;
157 obj->intercepted = EINA_TRUE;
158 ret = !!(obj->interceptors->stack_below.func);
159 if (ret)
160 obj->interceptors->stack_below.func(obj->interceptors->stack_below.data, obj, below);
161 obj->intercepted = EINA_FALSE;
162 return ret;
163}
164
165int
166evas_object_intercept_call_layer_set(Evas_Object *obj, int l)
167{
168 int ret;
169
170 if (!obj->interceptors) return 0;
171 if (obj->intercepted) return 0;
172 obj->intercepted = EINA_TRUE;
173 ret = !!(obj->interceptors->layer_set.func);
174 if (ret)
175 obj->interceptors->layer_set.func(obj->interceptors->layer_set.data, obj, l);
176 obj->intercepted = EINA_FALSE;
177 return ret;
178}
179
180int
181evas_object_intercept_call_color_set(Evas_Object *obj, int r, int g, int b, int a)
182{
183 int ret;
184
185 if (!obj->interceptors) return 0;
186 if (obj->intercepted) return 0;
187 obj->intercepted = EINA_TRUE;
188 ret = !!(obj->interceptors->color_set.func);
189 if (ret)
190 obj->interceptors->color_set.func(obj->interceptors->color_set.data, obj, r, g, b, a);
191 obj->intercepted = EINA_FALSE;
192 return ret;
193}
194
195int
196evas_object_intercept_call_clip_set(Evas_Object *obj, Evas_Object *clip)
197{
198 int ret;
199
200 if (!obj->interceptors) return 0;
201 if (obj->intercepted) return 0;
202 obj->intercepted = EINA_TRUE;
203 ret = !!(obj->interceptors->clip_set.func);
204 if (ret)
205 obj->interceptors->clip_set.func(obj->interceptors->clip_set.data, obj, clip);
206 obj->intercepted = EINA_FALSE;
207 return ret;
208}
209
210int
211evas_object_intercept_call_clip_unset(Evas_Object *obj)
212{
213 int ret;
214
215 if (!obj->interceptors) return 0;
216 if (obj->intercepted) return 0;
217 obj->intercepted = EINA_TRUE;
218 ret = !!(obj->interceptors->clip_unset.func);
219 if (ret)
220 obj->interceptors->clip_unset.func(obj->interceptors->clip_unset.data, obj);
221 obj->intercepted = EINA_FALSE;
222 return ret;
223}
224
225/* public calls */
226
227EAPI void
228evas_object_intercept_show_callback_add(Evas_Object *obj, Evas_Object_Intercept_Show_Cb func, const void *data)
229{
230 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
231 return;
232 MAGIC_CHECK_END();
233 if (!func) return;
234 evas_object_intercept_init(obj);
235 if (!obj->interceptors) return;
236 obj->interceptors->show.func = func;
237 obj->interceptors->show.data = (void *)data;
238}
239
240EAPI void *
241evas_object_intercept_show_callback_del(Evas_Object *obj, Evas_Object_Intercept_Show_Cb func)
242{
243 void *data;
244
245 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
246 return NULL;
247 MAGIC_CHECK_END();
248 if (!func) return NULL;
249 if (!obj->interceptors) return NULL;
250 obj->interceptors->show.func = NULL;
251 data = obj->interceptors->show.data;
252 obj->interceptors->show.data = NULL;
253 evas_object_intercept_deinit(obj);
254 return data;
255}
256
257EAPI void
258evas_object_intercept_hide_callback_add(Evas_Object *obj, Evas_Object_Intercept_Hide_Cb func, const void *data)
259{
260 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
261 return;
262 MAGIC_CHECK_END();
263 if (!func) return;
264 evas_object_intercept_init(obj);
265 if (!obj->interceptors) return;
266 obj->interceptors->hide.func = func;
267 obj->interceptors->hide.data = (void *)data;
268}
269
270EAPI void *
271evas_object_intercept_hide_callback_del(Evas_Object *obj, Evas_Object_Intercept_Hide_Cb func)
272{
273 void *data;
274
275 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
276 return NULL;
277 MAGIC_CHECK_END();
278 if (!func) return NULL;
279 if (!obj->interceptors) return NULL;
280 obj->interceptors->hide.func = NULL;
281 data = obj->interceptors->hide.data;
282 obj->interceptors->hide.data = NULL;
283 evas_object_intercept_deinit(obj);
284 return data;
285}
286
287EAPI void
288evas_object_intercept_move_callback_add(Evas_Object *obj, Evas_Object_Intercept_Move_Cb func, const void *data)
289{
290 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
291 return;
292 MAGIC_CHECK_END();
293 if (!func) return;
294 evas_object_intercept_init(obj);
295 if (!obj->interceptors) return;
296 obj->interceptors->move.func = func;
297 obj->interceptors->move.data = (void *)data;
298}
299
300EAPI void *
301evas_object_intercept_move_callback_del(Evas_Object *obj, Evas_Object_Intercept_Move_Cb func)
302{
303 void *data;
304
305 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
306 return NULL;
307 MAGIC_CHECK_END();
308 if (!func) return NULL;
309 if (!obj->interceptors) return NULL;
310 obj->interceptors->move.func = NULL;
311 data = obj->interceptors->move.data;
312 obj->interceptors->move.data = NULL;
313 evas_object_intercept_deinit(obj);
314 return data;
315}
316
317EAPI void
318evas_object_intercept_resize_callback_add(Evas_Object *obj, Evas_Object_Intercept_Resize_Cb func, const void *data)
319{
320 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
321 return;
322 MAGIC_CHECK_END();
323 if (!func) return;
324 evas_object_intercept_init(obj);
325 if (!obj->interceptors) return;
326 obj->interceptors->resize.func = func;
327 obj->interceptors->resize.data = (void *)data;
328}
329
330EAPI void *
331evas_object_intercept_resize_callback_del(Evas_Object *obj, Evas_Object_Intercept_Resize_Cb func)
332{
333 void *data;
334
335 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
336 return NULL;
337 MAGIC_CHECK_END();
338 if (!func) return NULL;
339 if (!obj->interceptors) return NULL;
340 obj->interceptors->resize.func = NULL;
341 data = obj->interceptors->resize.data;
342 obj->interceptors->resize.data = NULL;
343 evas_object_intercept_deinit(obj);
344 return data;
345}
346
347EAPI void
348evas_object_intercept_raise_callback_add(Evas_Object *obj, Evas_Object_Intercept_Raise_Cb func, const void *data)
349{
350 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
351 return;
352 MAGIC_CHECK_END();
353 if (!func) return;
354 evas_object_intercept_init(obj);
355 if (!obj->interceptors) return;
356 obj->interceptors->raise.func = func;
357 obj->interceptors->raise.data = (void *)data;
358}
359
360EAPI void *
361evas_object_intercept_raise_callback_del(Evas_Object *obj, Evas_Object_Intercept_Raise_Cb func)
362{
363 void *data;
364
365 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
366 return NULL;
367 MAGIC_CHECK_END();
368 if (!func) return NULL;
369 if (!obj->interceptors) return NULL;
370 obj->interceptors->raise.func = NULL;
371 data = obj->interceptors->raise.data;
372 obj->interceptors->raise.data = NULL;
373 evas_object_intercept_deinit(obj);
374 return data;
375}
376
377EAPI void
378evas_object_intercept_lower_callback_add(Evas_Object *obj, Evas_Object_Intercept_Lower_Cb func, const void *data)
379{
380 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
381 return;
382 MAGIC_CHECK_END();
383 if (!func) return;
384 evas_object_intercept_init(obj);
385 if (!obj->interceptors) return;
386 obj->interceptors->lower.func = func;
387 obj->interceptors->lower.data = (void *)data;
388}
389
390EAPI void *
391evas_object_intercept_lower_callback_del(Evas_Object *obj, Evas_Object_Intercept_Lower_Cb func)
392{
393 void *data;
394
395 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
396 return NULL;
397 MAGIC_CHECK_END();
398 if (!func) return NULL;
399 if (!obj->interceptors) return NULL;
400 obj->interceptors->lower.func = NULL;
401 data = obj->interceptors->lower.data;
402 obj->interceptors->lower.data = NULL;
403 evas_object_intercept_deinit(obj);
404 return data;
405}
406
407EAPI void
408evas_object_intercept_stack_above_callback_add(Evas_Object *obj, Evas_Object_Intercept_Stack_Above_Cb func, const void *data)
409{
410 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
411 return;
412 MAGIC_CHECK_END();
413 if (!func) return;
414 evas_object_intercept_init(obj);
415 if (!obj->interceptors) return;
416 obj->interceptors->stack_above.func = func;
417 obj->interceptors->stack_above.data = (void *)data;
418}
419
420EAPI void *
421evas_object_intercept_stack_above_callback_del(Evas_Object *obj, Evas_Object_Intercept_Stack_Above_Cb func)
422{
423 void *data;
424
425 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
426 return NULL;
427 MAGIC_CHECK_END();
428 if (!func) return NULL;
429 if (!obj->interceptors) return NULL;
430 obj->interceptors->stack_above.func = NULL;
431 data = obj->interceptors->stack_above.data;
432 obj->interceptors->stack_above.data = NULL;
433 evas_object_intercept_deinit(obj);
434 return data;
435}
436
437EAPI void
438evas_object_intercept_stack_below_callback_add(Evas_Object *obj, Evas_Object_Intercept_Stack_Below_Cb func, const void *data)
439{
440 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
441 return;
442 MAGIC_CHECK_END();
443 if (!func) return;
444 evas_object_intercept_init(obj);
445 if (!obj->interceptors) return;
446 obj->interceptors->stack_below.func = func;
447 obj->interceptors->stack_below.data = (void *)data;
448}
449
450EAPI void *
451evas_object_intercept_stack_below_callback_del(Evas_Object *obj, Evas_Object_Intercept_Stack_Below_Cb func)
452{
453 void *data;
454
455 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
456 return NULL;
457 MAGIC_CHECK_END();
458 if (!func) return NULL;
459 if (!obj->interceptors) return NULL;
460 obj->interceptors->stack_below.func = NULL;
461 data = obj->interceptors->stack_below.data;
462 obj->interceptors->stack_below.data = NULL;
463 evas_object_intercept_deinit(obj);
464 return data;
465}
466
467EAPI void
468evas_object_intercept_layer_set_callback_add(Evas_Object *obj, Evas_Object_Intercept_Layer_Set_Cb func, const void *data)
469{
470 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
471 return;
472 MAGIC_CHECK_END();
473 if (!func) return;
474 evas_object_intercept_init(obj);
475 if (!obj->interceptors) return;
476 obj->interceptors->layer_set.func = func;
477 obj->interceptors->layer_set.data = (void *)data;
478}
479
480EAPI void *
481evas_object_intercept_layer_set_callback_del(Evas_Object *obj, Evas_Object_Intercept_Layer_Set_Cb func)
482{
483 void *data;
484
485 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
486 return NULL;
487 MAGIC_CHECK_END();
488 if (!func) return NULL;
489 if (!obj->interceptors) return NULL;
490 obj->interceptors->layer_set.func = NULL;
491 data = obj->interceptors->layer_set.data;
492 obj->interceptors->layer_set.data = NULL;
493 evas_object_intercept_deinit(obj);
494 return data;
495}
496
497EAPI void
498evas_object_intercept_color_set_callback_add(Evas_Object *obj, Evas_Object_Intercept_Color_Set_Cb func, const void *data)
499{
500 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
501 return;
502 MAGIC_CHECK_END();
503 if (!func) return;
504 evas_object_intercept_init(obj);
505 if (!obj->interceptors) return;
506 obj->interceptors->color_set.func = func;
507 obj->interceptors->color_set.data = (void *)data;
508}
509
510EAPI void *
511evas_object_intercept_color_set_callback_del(Evas_Object *obj, Evas_Object_Intercept_Color_Set_Cb func)
512{
513 void *data;
514
515 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
516 return NULL;
517 MAGIC_CHECK_END();
518 if (!func) return NULL;
519 if (!obj->interceptors) return NULL;
520 obj->interceptors->color_set.func = NULL;
521 data = obj->interceptors->color_set.data;
522 obj->interceptors->color_set.data = NULL;
523 evas_object_intercept_deinit(obj);
524 return data;
525}
526
527EAPI void
528evas_object_intercept_clip_set_callback_add(Evas_Object *obj, Evas_Object_Intercept_Clip_Set_Cb func, const void *data)
529{
530 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
531 return;
532 MAGIC_CHECK_END();
533 if (!func) return;
534 evas_object_intercept_init(obj);
535 if (!obj->interceptors) return;
536 obj->interceptors->clip_set.func = func;
537 obj->interceptors->clip_set.data = (void *)data;
538}
539
540EAPI void *
541evas_object_intercept_clip_set_callback_del(Evas_Object *obj, Evas_Object_Intercept_Clip_Set_Cb func)
542{
543 void *data;
544
545 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
546 return NULL;
547 MAGIC_CHECK_END();
548 if (!func) return NULL;
549 if (!obj->interceptors) return NULL;
550 obj->interceptors->clip_set.func = NULL;
551 data = obj->interceptors->clip_set.data;
552 obj->interceptors->clip_set.data = NULL;
553 evas_object_intercept_deinit(obj);
554 return data;
555}
556
557EAPI void
558evas_object_intercept_clip_unset_callback_add(Evas_Object *obj, Evas_Object_Intercept_Clip_Unset_Cb func, const void *data)
559{
560 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
561 return;
562 MAGIC_CHECK_END();
563 if (!func) return;
564 evas_object_intercept_init(obj);
565 if (!obj->interceptors) return;
566 obj->interceptors->clip_unset.func = func;
567 obj->interceptors->clip_unset.data = (void *)data;
568}
569
570EAPI void *
571evas_object_intercept_clip_unset_callback_del(Evas_Object *obj, Evas_Object_Intercept_Clip_Unset_Cb func)
572{
573 void *data;
574
575 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
576 return NULL;
577 MAGIC_CHECK_END();
578 if (!func) return NULL;
579 if (!obj->interceptors) return NULL;
580 obj->interceptors->clip_unset.func = NULL;
581 data = obj->interceptors->clip_unset.data;
582 obj->interceptors->clip_unset.data = NULL;
583 evas_object_intercept_deinit(obj);
584 return data;
585}
diff --git a/libraries/evas/src/lib/canvas/evas_object_line.c b/libraries/evas/src/lib/canvas/evas_object_line.c
deleted file mode 100644
index b09a6e2..0000000
--- a/libraries/evas/src/lib/canvas/evas_object_line.c
+++ /dev/null
@@ -1,461 +0,0 @@
1#include "evas_common.h"
2#include "evas_private.h"
3
4/* private magic number for line objects */
5static const char o_type[] = "line";
6
7/* private struct for line object internal data */
8typedef struct _Evas_Object_Line Evas_Object_Line;
9
10struct _Evas_Object_Line
11{
12 DATA32 magic;
13 struct {
14 struct {
15 int x1, y1, x2, y2;
16 struct {
17 Evas_Coord w, h;
18 } object;
19 } cache;
20 Evas_Coord x1, y1, x2, y2;
21 } cur, prev;
22
23 void *engine_data;
24
25 char changed : 1;
26};
27
28/* private methods for line objects */
29static void evas_object_line_init(Evas_Object *obj);
30static void *evas_object_line_new(void);
31static void evas_object_line_render(Evas_Object *obj, void *output, void *context, void *surface, int x, int y);
32static void evas_object_line_free(Evas_Object *obj);
33static void evas_object_line_render_pre(Evas_Object *obj);
34static void evas_object_line_render_post(Evas_Object *obj);
35
36static unsigned int evas_object_line_id_get(Evas_Object *obj);
37static unsigned int evas_object_line_visual_id_get(Evas_Object *obj);
38static void *evas_object_line_engine_data_get(Evas_Object *obj);
39
40static int evas_object_line_is_opaque(Evas_Object *obj);
41static int evas_object_line_was_opaque(Evas_Object *obj);
42static int evas_object_line_is_inside(Evas_Object *obj, Evas_Coord x, Evas_Coord y);
43static int evas_object_line_was_inside(Evas_Object *obj, Evas_Coord x, Evas_Coord y);
44static void evas_object_line_coords_recalc(Evas_Object *obj);
45
46static const Evas_Object_Func object_func =
47{
48 /* methods (compulsory) */
49 evas_object_line_free,
50 evas_object_line_render,
51 evas_object_line_render_pre,
52 evas_object_line_render_post,
53 evas_object_line_id_get,
54 evas_object_line_visual_id_get,
55 evas_object_line_engine_data_get,
56 /* these are optional. NULL = nothing */
57 NULL,
58 NULL,
59 NULL,
60 NULL,
61 evas_object_line_is_opaque,
62 evas_object_line_was_opaque,
63 evas_object_line_is_inside,
64 evas_object_line_was_inside,
65 evas_object_line_coords_recalc,
66 NULL,
67 NULL,
68 NULL,
69 NULL
70};
71
72/* the actual api call to add a rect */
73/* it has no other api calls as all properties are standard */
74
75EVAS_MEMPOOL(_mp_obj);
76
77EAPI Evas_Object *
78evas_object_line_add(Evas *e)
79{
80 Evas_Object *obj;
81
82 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
83 return NULL;
84 MAGIC_CHECK_END();
85 obj = evas_object_new(e);
86 evas_object_line_init(obj);
87 evas_object_inject(obj, e);
88 return obj;
89}
90
91EAPI void
92evas_object_line_xy_set(Evas_Object *obj, Evas_Coord x1, Evas_Coord y1, Evas_Coord x2, Evas_Coord y2)
93{
94 Evas_Object_Line *o;
95 Evas_Coord min_x, max_x, min_y, max_y;
96 int is, was = 0;
97
98 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
99 return;
100 MAGIC_CHECK_END();
101 o = (Evas_Object_Line *)(obj->object_data);
102 MAGIC_CHECK(o, Evas_Object_Line, MAGIC_OBJ_LINE);
103 return;
104 MAGIC_CHECK_END();
105 if ((x1 == o->cur.x1) && (y1 == o->cur.y1) &&
106 (x2 == o->cur.x2) && (y2 == o->cur.y2)) return;
107 if (obj->layer->evas->events_frozen <= 0)
108 {
109 if (!evas_event_passes_through(obj) &&
110 !evas_event_freezes_through(obj))
111 was = evas_object_is_in_output_rect(obj,
112 obj->layer->evas->pointer.x,
113 obj->layer->evas->pointer.y,
114 1, 1);
115 }
116 if (x1 < x2)
117 {
118 min_x = x1;
119 max_x = x2;
120 }
121 else
122 {
123 min_x = x2;
124 max_x = x1;
125 }
126 if (y1 < y2)
127 {
128 min_y = y1;
129 max_y = y2;
130 }
131 else
132 {
133 min_y = y2;
134 max_y = y1;
135 }
136 obj->cur.geometry.x = min_x;
137 obj->cur.geometry.y = min_y;
138 obj->cur.geometry.w = max_x - min_x + 2;
139 obj->cur.geometry.h = max_y - min_y + 2;
140//// obj->cur.cache.geometry.validity = 0;
141 o->cur.x1 = x1 - min_x;
142 o->cur.y1 = y1 - min_y;
143 o->cur.x2 = x2 - min_x;
144 o->cur.y2 = y2 - min_y;
145 o->changed = 1;
146 evas_object_change(obj);
147 evas_object_coords_recalc(obj);
148 evas_object_clip_dirty(obj);
149 if (obj->layer->evas->events_frozen <= 0)
150 {
151 is = evas_object_is_in_output_rect(obj,
152 obj->layer->evas->pointer.x,
153 obj->layer->evas->pointer.y, 1, 1);
154 if (!evas_event_passes_through(obj) &&
155 !evas_event_freezes_through(obj))
156 {
157 if ((is ^ was) && obj->cur.visible)
158 evas_event_feed_mouse_move(obj->layer->evas,
159 obj->layer->evas->pointer.x,
160 obj->layer->evas->pointer.y,
161 obj->layer->evas->last_timestamp,
162 NULL);
163 }
164 }
165 evas_object_inform_call_move(obj);
166 evas_object_inform_call_resize(obj);
167}
168
169EAPI void
170evas_object_line_xy_get(const Evas_Object *obj, Evas_Coord *x1, Evas_Coord *y1, Evas_Coord *x2, Evas_Coord *y2)
171{
172 Evas_Object_Line *o;
173
174 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
175 if (x1) *x1 = 0;
176 if (y1) *y1 = 0;
177 if (x2) *x2 = 0;
178 if (y2) *y2 = 0;
179 return;
180 MAGIC_CHECK_END();
181 o = (Evas_Object_Line *)(obj->object_data);
182 MAGIC_CHECK(o, Evas_Object_Line, MAGIC_OBJ_LINE);
183 if (x1) *x1 = 0;
184 if (y1) *y1 = 0;
185 if (x2) *x2 = 0;
186 if (y2) *y2 = 0;
187 return;
188 MAGIC_CHECK_END();
189 if (x1) *x1 = obj->cur.geometry.x + o->cur.x1;
190 if (y1) *y1 = obj->cur.geometry.y + o->cur.y1;
191 if (x2) *x2 = obj->cur.geometry.x + o->cur.x2;
192 if (y2) *y2 = obj->cur.geometry.y + o->cur.y2;
193}
194
195/* all nice and private */
196static void
197evas_object_line_init(Evas_Object *obj)
198{
199 /* alloc image ob, setup methods and default values */
200 obj->object_data = evas_object_line_new();
201 /* set up default settings for this kind of object */
202 obj->cur.color.r = 255;
203 obj->cur.color.g = 255;
204 obj->cur.color.b = 255;
205 obj->cur.color.a = 255;
206 obj->cur.geometry.x = 0;
207 obj->cur.geometry.y = 0;
208 obj->cur.geometry.w = 0;
209 obj->cur.geometry.h = 0;
210 obj->cur.layer = 0;
211 obj->cur.anti_alias = 1;
212 obj->cur.render_op = EVAS_RENDER_BLEND;
213 /* set up object-specific settings */
214 obj->prev = obj->cur;
215 /* set up methods (compulsory) */
216 obj->func = &object_func;
217 obj->type = o_type;
218}
219
220static void *
221evas_object_line_new(void)
222{
223 Evas_Object_Line *o;
224
225 /* alloc obj private data */
226 EVAS_MEMPOOL_INIT(_mp_obj, "evas_object_line", Evas_Object_Line, 16, NULL);
227 o = EVAS_MEMPOOL_ALLOC(_mp_obj, Evas_Object_Line);
228 if (!o) return NULL;
229 EVAS_MEMPOOL_PREP(_mp_obj, o, Evas_Object_Line);
230 o->magic = MAGIC_OBJ_LINE;
231 o->cur.x1 = 0;
232 o->cur.y1 = 0;
233 o->cur.x2 = 31;
234 o->cur.y2 = 31;
235 o->prev = o->cur;
236 return o;
237}
238
239static void
240evas_object_line_free(Evas_Object *obj)
241{
242 Evas_Object_Line *o;
243
244 /* frees private object data. very simple here */
245 o = (Evas_Object_Line *)(obj->object_data);
246 MAGIC_CHECK(o, Evas_Object_Line, MAGIC_OBJ_LINE);
247 return;
248 MAGIC_CHECK_END();
249 /* free obj */
250 o->magic = 0;
251 EVAS_MEMPOOL_FREE(_mp_obj, o);
252}
253
254static void
255evas_object_line_render(Evas_Object *obj, void *output, void *context, void *surface, int x, int y)
256{
257 Evas_Object_Line *o;
258
259 /* render object to surface with context, and offxet by x,y */
260 o = (Evas_Object_Line *)(obj->object_data);
261 obj->layer->evas->engine.func->context_color_set(output,
262 context,
263 obj->cur.cache.clip.r,
264 obj->cur.cache.clip.g,
265 obj->cur.cache.clip.b,
266 obj->cur.cache.clip.a);
267 obj->layer->evas->engine.func->context_multiplier_unset(output,
268 context);
269 obj->layer->evas->engine.func->context_anti_alias_set(output, context,
270 obj->cur.anti_alias);
271 obj->layer->evas->engine.func->context_render_op_set(output, context,
272 obj->cur.render_op);
273 obj->layer->evas->engine.func->line_draw(output,
274 context,
275 surface,
276 o->cur.cache.x1 + x,
277 o->cur.cache.y1 + y,
278 o->cur.cache.x2 + x,
279 o->cur.cache.y2 + y);
280}
281
282static void
283evas_object_line_render_pre(Evas_Object *obj)
284{
285 Evas_Object_Line *o;
286 int is_v, was_v;
287
288 /* dont pre-render the obj twice! */
289 if (obj->pre_render_done) return;
290 obj->pre_render_done = 1;
291 /* pre-render phase. this does anything an object needs to do just before */
292 /* rendering. this could mean loading the image data, retrieving it from */
293 /* elsewhere, decoding video etc. */
294 /* then when this is done the object needs to figure if it changed and */
295 /* if so what and where and add the appropriate redraw lines */
296 o = (Evas_Object_Line *)(obj->object_data);
297 /* if someone is clipping this obj - go calculate the clipper */
298 if (obj->cur.clipper)
299 {
300 if (obj->cur.cache.clip.dirty)
301 evas_object_clip_recalc(obj->cur.clipper);
302 obj->cur.clipper->func->render_pre(obj->cur.clipper);
303 }
304 /* now figure what changed and add draw rects */
305 /* if it just became visible or invisible */
306 is_v = evas_object_is_visible(obj);
307 was_v = evas_object_was_visible(obj);
308 if (is_v != was_v)
309 {
310 evas_object_render_pre_visible_change(&obj->layer->evas->clip_changes, obj, is_v, was_v);
311 goto done;
312 }
313 if ((obj->cur.map != obj->prev.map) ||
314 (obj->cur.usemap != obj->prev.usemap))
315 {
316 evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes, obj);
317 goto done;
318 }
319 /* it's not visible - we accounted for it appearing or not so just abort */
320 if (!is_v) goto done;
321 /* clipper changed this is in addition to anything else for obj */
322 evas_object_render_pre_clipper_change(&obj->layer->evas->clip_changes, obj);
323 /* if we restacked (layer or just within a layer) */
324 if (obj->restack)
325 {
326 evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes, obj);
327 goto done;
328 }
329 /* if it changed anti_alias */
330 if (obj->cur.anti_alias != obj->prev.anti_alias)
331 {
332 evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes, obj);
333 goto done;
334 }
335 /* if it changed render op */
336 if (obj->cur.render_op != obj->prev.render_op)
337 {
338 evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes, obj);
339 goto done;
340 }
341 /* if it changed color */
342 if ((obj->cur.color.r != obj->prev.color.r) ||
343 (obj->cur.color.g != obj->prev.color.g) ||
344 (obj->cur.color.b != obj->prev.color.b) ||
345 (obj->cur.color.a != obj->prev.color.a))
346 {
347 evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes, obj);
348 goto done;
349 }
350 /* if it changed geometry - and obviously not visibility or color */
351 /* calculate differences since we have a constant color fill */
352 /* we really only need to update the differences */
353 if ((obj->cur.geometry.x != obj->prev.geometry.x) ||
354 (obj->cur.geometry.y != obj->prev.geometry.y) ||
355 (obj->cur.geometry.w != obj->prev.geometry.w) ||
356 (obj->cur.geometry.h != obj->prev.geometry.h) ||
357 ((o->changed) &&
358 ((o->cur.x1 != o->prev.x1) ||
359 (o->cur.y1 != o->prev.y1) ||
360 (o->cur.x2 != o->prev.x2) ||
361 (o->cur.y2 != o->prev.y2)))
362 )
363 {
364 evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes, obj);
365 goto done;
366 }
367 done:
368 evas_object_render_pre_effect_updates(&obj->layer->evas->clip_changes, obj, is_v, was_v);
369}
370
371static void
372evas_object_line_render_post(Evas_Object *obj)
373{
374 Evas_Object_Line *o;
375
376 /* this moves the current data to the previous state parts of the object */
377 /* in whatever way is safest for the object. also if we don't need object */
378 /* data anymore we can free it if the object deems this is a good idea */
379 o = (Evas_Object_Line *)(obj->object_data);
380 /* remove those pesky changes */
381 evas_object_clip_changes_clean(obj);
382 /* move cur to prev safely for object data */
383 obj->prev = obj->cur;
384 o->prev = o->cur;
385 o->changed = 0;
386}
387
388static unsigned int evas_object_line_id_get(Evas_Object *obj)
389{
390 Evas_Object_Line *o;
391
392 o = (Evas_Object_Line *)(obj->object_data);
393 if (!o) return 0;
394 return MAGIC_OBJ_LINE;
395}
396
397static unsigned int evas_object_line_visual_id_get(Evas_Object *obj)
398{
399 Evas_Object_Line *o;
400
401 o = (Evas_Object_Line *)(obj->object_data);
402 if (!o) return 0;
403 return MAGIC_OBJ_SHAPE;
404}
405
406static void *evas_object_line_engine_data_get(Evas_Object *obj)
407{
408 Evas_Object_Line *o;
409
410 o = (Evas_Object_Line *)(obj->object_data);
411 if (!o) return NULL;
412 return o->engine_data;
413}
414
415static int
416evas_object_line_is_opaque(Evas_Object *obj __UNUSED__)
417{
418 /* this returns 1 if the internal object data implies that the object is */
419 /* currently fully opaque over the entire line it occupies */
420 return 0;
421}
422
423static int
424evas_object_line_was_opaque(Evas_Object *obj __UNUSED__)
425{
426 /* this returns 1 if the internal object data implies that the object was */
427 /* previously fully opaque over the entire line it occupies */
428 return 0;
429}
430
431static int
432evas_object_line_is_inside(Evas_Object *obj __UNUSED__, Evas_Coord x __UNUSED__, Evas_Coord y __UNUSED__)
433{
434 /* this returns 1 if the canvas co-ordinates are inside the object based */
435 /* on object private data. not much use for rects, but for polys, images */
436 /* and other complex objects it might be */
437 return 1;
438}
439
440static int
441evas_object_line_was_inside(Evas_Object *obj __UNUSED__, Evas_Coord x __UNUSED__, Evas_Coord y __UNUSED__)
442{
443 /* this returns 1 if the canvas co-ordinates were inside the object based */
444 /* on object private data. not much use for rects, but for polys, images */
445 /* and other complex objects it might be */
446 return 1;
447}
448
449static void
450evas_object_line_coords_recalc(Evas_Object *obj)
451{
452 Evas_Object_Line *o;
453
454 o = (Evas_Object_Line *)(obj->object_data);
455 o->cur.cache.x1 = obj->cur.geometry.x + o->cur.x1;
456 o->cur.cache.y1 = obj->cur.geometry.y + o->cur.y1;
457 o->cur.cache.x2 = obj->cur.geometry.x + o->cur.x2;
458 o->cur.cache.y2 = obj->cur.geometry.y + o->cur.y2;
459 o->cur.cache.object.w = obj->cur.geometry.w;
460 o->cur.cache.object.h = obj->cur.geometry.h;
461}
diff --git a/libraries/evas/src/lib/canvas/evas_object_main.c b/libraries/evas/src/lib/canvas/evas_object_main.c
deleted file mode 100644
index 81fc858..0000000
--- a/libraries/evas/src/lib/canvas/evas_object_main.c
+++ /dev/null
@@ -1,1398 +0,0 @@
1#include "evas_common.h"
2#include "evas_private.h"
3
4EVAS_MEMPOOL(_mp_obj);
5EVAS_MEMPOOL(_mp_sh);
6
7static Eina_Inlist *
8get_layer_objects(Evas_Layer *l)
9{
10 if ((!l) || (!l->objects)) return NULL;
11 return (EINA_INLIST_GET(l->objects));
12}
13
14/* evas internal stuff */
15Evas_Object *
16evas_object_new(Evas *e __UNUSED__)
17{
18 Evas_Object *obj;
19
20 EVAS_MEMPOOL_INIT(_mp_obj, "evas_object", Evas_Object, 512, NULL);
21 obj = EVAS_MEMPOOL_ALLOC(_mp_obj, Evas_Object);
22 if (!obj) return NULL;
23 EVAS_MEMPOOL_PREP(_mp_obj, obj, Evas_Object);
24
25 obj->magic = MAGIC_OBJ;
26 obj->cur.scale = 1.0;
27 obj->prev.scale = 1.0;
28 obj->is_frame = EINA_FALSE;
29
30 return obj;
31}
32
33void
34evas_object_free(Evas_Object *obj, int clean_layer)
35{
36 int was_smart_child = 0;
37
38#if 0 // filtering disabled
39 evas_filter_free(obj);
40#endif
41 if (!strcmp(obj->type, "image")) evas_object_image_video_surface_set(obj, NULL);
42 evas_object_map_set(obj, NULL);
43 evas_object_grabs_cleanup(obj);
44 evas_object_intercept_cleanup(obj);
45 if (obj->smart.parent) was_smart_child = 1;
46 evas_object_smart_cleanup(obj);
47 obj->func->free(obj);
48 if (!was_smart_child) evas_object_release(obj, clean_layer);
49 if (obj->clip.clipees)
50 eina_list_free(obj->clip.clipees);
51 evas_object_clip_changes_clean(obj);
52 evas_object_event_callback_all_del(obj);
53 evas_object_event_callback_cleanup(obj);
54 while (obj->data.elements)
55 {
56 Evas_Data_Node *node;
57
58 node = obj->data.elements->data;
59 obj->data.elements = eina_list_remove(obj->data.elements, node);
60 free(node);
61 }
62 obj->magic = 0;
63 if (obj->size_hints)
64 {
65 EVAS_MEMPOOL_FREE(_mp_sh, obj->size_hints);
66 }
67 EVAS_MEMPOOL_FREE(_mp_obj, obj);
68}
69
70void
71evas_object_change(Evas_Object *obj)
72{
73 Eina_List *l;
74 Evas_Object *obj2;
75 Eina_Bool movch = 0;
76
77 if (obj->layer->evas->nochange)
78 {
79// printf("nochange %p\n", obj);
80 return;
81 }
82// else
83// printf("ch %p\n", obj);
84 obj->layer->evas->changed = 1;
85 if (obj->changed_move)
86 {
87 movch = 1;
88 obj->changed_move = 0;
89 if (!obj->changed_nomove) obj->changed_move_only = 1;
90 if (obj->changed) return;
91 }
92 else
93 {
94 obj->changed_move_only = 0;
95 obj->changed_nomove = 1;
96 if (obj->changed) return;
97 }
98// obj->changed = 1;
99 evas_render_object_recalc(obj);
100 /* set changed flag on all objects this one clips too */
101 if (!((movch) && (obj->is_static_clip)))
102 {
103 EINA_LIST_FOREACH(obj->clip.clipees, l, obj2)
104 evas_object_change(obj2);
105 }
106 EINA_LIST_FOREACH(obj->proxy.proxies, l, obj2)
107 {
108 evas_object_change(obj2);
109 }
110 if (obj->smart.parent) evas_object_change(obj->smart.parent);
111}
112
113void
114evas_object_render_pre_visible_change(Eina_Array *rects, Evas_Object *obj, int is_v, int was_v)
115{
116 if (obj->smart.smart) return;
117 if (is_v == was_v) return;
118 if (is_v)
119 {
120 evas_add_rect(rects,
121 obj->cur.cache.clip.x,
122 obj->cur.cache.clip.y,
123 obj->cur.cache.clip.w,
124 obj->cur.cache.clip.h);
125 }
126 else
127 {
128 evas_add_rect(rects,
129 obj->prev.cache.clip.x,
130 obj->prev.cache.clip.y,
131 obj->prev.cache.clip.w,
132 obj->prev.cache.clip.h);
133 }
134}
135
136void
137evas_object_render_pre_clipper_change(Eina_Array *rects, Evas_Object *obj)
138{
139 if (obj->smart.smart) return;
140 if (obj->cur.clipper == obj->prev.clipper) return;
141 if ((obj->cur.clipper) && (obj->prev.clipper))
142 {
143 /* get difference rects between clippers */
144 evas_rects_return_difference_rects(rects,
145 obj->cur.clipper->cur.cache.clip.x,
146 obj->cur.clipper->cur.cache.clip.y,
147 obj->cur.clipper->cur.cache.clip.w,
148 obj->cur.clipper->cur.cache.clip.h,
149 obj->prev.clipper->prev.cache.clip.x,
150 obj->prev.clipper->prev.cache.clip.y,
151 obj->prev.clipper->prev.cache.clip.w,
152 obj->prev.clipper->prev.cache.clip.h);
153 }
154 else if (obj->cur.clipper)
155 {
156 evas_rects_return_difference_rects(rects,
157 obj->cur.geometry.x,
158 obj->cur.geometry.y,
159 obj->cur.geometry.w,
160 obj->cur.geometry.h,
161//// rl = evas_rects_return_difference_rects(obj->cur.cache.geometry.x,
162//// obj->cur.cache.geometry.y,
163//// obj->cur.cache.geometry.w,
164//// obj->cur.cache.geometry.h,
165 obj->cur.clipper->cur.cache.clip.x,
166 obj->cur.clipper->cur.cache.clip.y,
167 obj->cur.clipper->cur.cache.clip.w,
168 obj->cur.clipper->cur.cache.clip.h);
169 }
170 else if (obj->prev.clipper)
171 {
172 evas_rects_return_difference_rects(rects,
173 obj->prev.geometry.x,
174 obj->prev.geometry.y,
175 obj->prev.geometry.w,
176 obj->prev.geometry.h,
177//// rl = evas_rects_return_difference_rects(obj->prev.cache.geometry.x,
178//// obj->prev.cache.geometry.y,
179//// obj->prev.cache.geometry.w,
180//// obj->prev.cache.geometry.h,
181 obj->prev.clipper->prev.cache.clip.x,
182 obj->prev.clipper->prev.cache.clip.y,
183 obj->prev.clipper->prev.cache.clip.w,
184 obj->prev.clipper->prev.cache.clip.h);
185 }
186}
187
188void
189evas_object_render_pre_prev_cur_add(Eina_Array *rects, Evas_Object *obj)
190{
191 evas_add_rect(rects,
192 obj->cur.cache.clip.x,
193 obj->cur.cache.clip.y,
194 obj->cur.cache.clip.w,
195 obj->cur.cache.clip.h);
196 evas_add_rect(rects,
197 obj->prev.cache.clip.x,
198 obj->prev.cache.clip.y,
199 obj->prev.cache.clip.w,
200 obj->prev.cache.clip.h);
201/*
202 evas_add_rect(rects,
203 obj->cur.geometry.x,
204 obj->cur.geometry.y,
205 obj->cur.geometry.w,
206 obj->cur.geometry.h);
207//// obj->cur.cache.geometry.x,
208//// obj->cur.cache.geometry.y,
209//// obj->cur.cache.geometry.w,
210//// obj->cur.cache.geometry.h);
211 evas_add_rect(rects,
212 obj->prev.geometry.x,
213 obj->prev.geometry.y,
214 obj->prev.geometry.w,
215 obj->prev.geometry.h);
216//// obj->prev.cache.geometry.x,
217//// obj->prev.cache.geometry.y,
218//// obj->prev.cache.geometry.w,
219//// obj->prev.cache.geometry.h);
220*/
221}
222
223void
224evas_object_clip_changes_clean(Evas_Object *obj)
225{
226 Eina_Rectangle *r;
227
228 EINA_LIST_FREE(obj->clip.changes, r)
229 eina_rectangle_free(r);
230}
231
232void
233evas_object_render_pre_effect_updates(Eina_Array *rects, Evas_Object *obj, int is_v, int was_v __UNUSED__)
234{
235 Eina_Rectangle *r;
236 Evas_Object *clipper;
237 Eina_List *l;
238 unsigned int i;
239 Eina_Array_Iterator it;
240 int x, y, w, h;
241
242 if (obj->smart.smart) goto end;
243 /* FIXME: was_v isn't used... why? */
244 if (!obj->clip.clipees)
245 {
246 EINA_ARRAY_ITER_NEXT(rects, i, r, it)
247 {
248 /* get updates and clip to current clip */
249 x = r->x;
250 y = r->y;
251 w = r->w;
252 h = r->h;
253 RECTS_CLIP_TO_RECT(x, y, w, h,
254 obj->cur.cache.clip.x,
255 obj->cur.cache.clip.y,
256 obj->cur.cache.clip.w,
257 obj->cur.cache.clip.h);
258 if ((w > 0) && (h > 0))
259 obj->layer->evas->engine.func->output_redraws_rect_add(obj->layer->evas->engine.data.output,
260 x, y, w, h);
261 /* get updates and clip to previous clip */
262 x = r->x;
263 y = r->y;
264 w = r->w;
265 h = r->h;
266 RECTS_CLIP_TO_RECT(x, y, w, h,
267 obj->prev.cache.clip.x,
268 obj->prev.cache.clip.y,
269 obj->prev.cache.clip.w,
270 obj->prev.cache.clip.h);
271 if ((w > 0) && (h > 0))
272 obj->layer->evas->engine.func->output_redraws_rect_add(obj->layer->evas->engine.data.output,
273 x, y, w, h);
274 }
275 /* if the object is actually visible, take any parent clip changes */
276 if (is_v)
277 {
278 clipper = obj->cur.clipper;
279 while (clipper)
280 {
281 EINA_LIST_FOREACH(clipper->clip.changes, l, r)
282 {
283 /* get updates and clip to current clip */
284 x = r->x; y = r->y; w = r->w; h = r->h;
285 RECTS_CLIP_TO_RECT(x, y, w, h,
286 obj->cur.cache.clip.x,
287 obj->cur.cache.clip.y,
288 obj->cur.cache.clip.w,
289 obj->cur.cache.clip.h);
290 if ((w > 0) && (h > 0))
291 obj->layer->evas->engine.func->output_redraws_rect_add(obj->layer->evas->engine.data.output,
292 x, y, w, h);
293 /* get updates and clip to previous clip */
294 x = r->x; y = r->y; w = r->w; h = r->h;
295 RECTS_CLIP_TO_RECT(x, y, w, h,
296 obj->prev.cache.clip.x,
297 obj->prev.cache.clip.y,
298 obj->prev.cache.clip.w,
299 obj->prev.cache.clip.h);
300 if ((w > 0) && (h > 0))
301 obj->layer->evas->engine.func->output_redraws_rect_add(obj->layer->evas->engine.data.output,
302 x, y, w, h);
303 }
304 clipper = clipper->cur.clipper;
305 }
306 }
307 }
308 else
309 {
310 evas_object_clip_changes_clean(obj);
311 EINA_ARRAY_ITER_NEXT(rects, i, r, it)
312 obj->clip.changes = eina_list_append(obj->clip.changes, r);
313 eina_array_clean(rects);
314 }
315
316 end:
317 EINA_ARRAY_ITER_NEXT(rects, i, r, it)
318 eina_rectangle_free(r);
319 eina_array_clean(rects);
320}
321
322int
323evas_object_was_in_output_rect(Evas_Object *obj, int x, int y, int w, int h)
324{
325 if (obj->smart.smart) return 0;
326 /* assumes coords have been recalced */
327 if ((RECTS_INTERSECT(x, y, w, h,
328 obj->prev.cache.clip.x,
329 obj->prev.cache.clip.y,
330 obj->prev.cache.clip.w,
331 obj->prev.cache.clip.h)))
332 return 1;
333 return 0;
334}
335
336int
337evas_object_was_opaque(Evas_Object *obj)
338{
339 if (obj->smart.smart) return 0;
340 if (obj->prev.cache.clip.a == 255)
341 {
342 if (obj->func->was_opaque)
343 return obj->func->was_opaque(obj);
344 return 1;
345 }
346 return 0;
347}
348
349int
350evas_object_is_inside(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
351{
352 if (obj->smart.smart) return 0;
353 if (obj->func->is_inside)
354 return obj->func->is_inside(obj, x, y);
355 return 0;
356}
357
358int
359evas_object_was_inside(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
360{
361 if (obj->smart.smart) return 0;
362 if (obj->func->was_inside)
363 return obj->func->was_inside(obj, x, y);
364 return 0;
365}
366/* routines apps will call */
367
368EAPI void
369evas_object_ref(Evas_Object *obj)
370{
371 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
372 return;
373 MAGIC_CHECK_END();
374 obj->ref++;
375 if (obj->ref == 0) obj->ref--;
376}
377
378EAPI void
379evas_object_unref(Evas_Object *obj)
380{
381 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
382 return;
383 MAGIC_CHECK_END();
384 if (obj->ref == 0) return;
385 obj->ref--;
386 if ((obj->del_ref) && (obj->ref == 0)) evas_object_del(obj);
387}
388
389EAPI void
390evas_object_del(Evas_Object *obj)
391{
392 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
393 return;
394 MAGIC_CHECK_END();
395
396 if (obj->delete_me) return;
397
398 if (obj->ref > 0)
399 {
400 obj->del_ref = 1;
401 return;
402 }
403#ifdef EVAS_FRAME_QUEUING
404 evas_common_frameq_flush();
405#endif
406
407 evas_object_hide(obj);
408 if (obj->focused)
409 {
410 obj->focused = 0;
411 obj->layer->evas->focused = NULL;
412 _evas_object_event_new();
413 evas_object_event_callback_call(obj, EVAS_CALLBACK_FOCUS_OUT, NULL, _evas_event_counter);
414 _evas_post_event_callback_call(obj->layer->evas);
415 }
416 _evas_object_event_new();
417 evas_object_event_callback_call(obj, EVAS_CALLBACK_DEL, NULL, _evas_event_counter);
418 _evas_post_event_callback_call(obj->layer->evas);
419 if (obj->mouse_grabbed > 0)
420 obj->layer->evas->pointer.mouse_grabbed -= obj->mouse_grabbed;
421 if ((obj->mouse_in) || (obj->mouse_grabbed > 0))
422 obj->layer->evas->pointer.object.in = eina_list_remove(obj->layer->evas->pointer.object.in, obj);
423 obj->mouse_grabbed = 0;
424 obj->mouse_in = 0;
425 if (obj->name) evas_object_name_set(obj, NULL);
426 if (!obj->layer)
427 {
428 evas_object_free(obj, 1);
429 return;
430 }
431 evas_object_grabs_cleanup(obj);
432 while (obj->clip.clipees)
433 evas_object_clip_unset(obj->clip.clipees->data);
434 while (obj->proxy.proxies)
435 evas_object_image_source_unset(obj->proxy.proxies->data);
436 if (obj->cur.clipper) evas_object_clip_unset(obj);
437 if (obj->smart.smart) evas_object_smart_del(obj);
438 evas_object_map_set(obj, NULL);
439 _evas_object_event_new();
440 evas_object_event_callback_call(obj, EVAS_CALLBACK_FREE, NULL, _evas_event_counter);
441 _evas_post_event_callback_call(obj->layer->evas);
442 evas_object_smart_cleanup(obj);
443 obj->delete_me = 1;
444 evas_object_change(obj);
445}
446
447EAPI void
448evas_object_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
449{
450 int is, was = 0, pass = 0, freeze = 0;
451 int nx = 0, ny = 0;
452
453 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
454 return;
455 MAGIC_CHECK_END();
456 if (obj->delete_me) return;
457
458 nx = x;
459 ny = y;
460
461 if (!obj->is_frame)
462 {
463 int fx, fy;
464
465 evas_output_framespace_get(obj->layer->evas, &fx, &fy, NULL, NULL);
466 if (!obj->smart.parent)
467 {
468 nx += fx;
469 ny += fy;
470 }
471 }
472
473 if (evas_object_intercept_call_move(obj, nx, ny)) return;
474
475 if (obj->doing.in_move > 0)
476 {
477 WRN("evas_object_move() called on object %p when in the middle of moving the same object", obj);
478 return;
479 }
480
481 if ((obj->cur.geometry.x == nx) && (obj->cur.geometry.y == ny)) return;
482
483 if (obj->layer->evas->events_frozen <= 0)
484 {
485 pass = evas_event_passes_through(obj);
486 freeze = evas_event_freezes_through(obj);
487 if ((!pass) && (!freeze))
488 was = evas_object_is_in_output_rect(obj,
489 obj->layer->evas->pointer.x,
490 obj->layer->evas->pointer.y, 1, 1);
491 }
492 obj->doing.in_move++;
493
494 if (obj->smart.smart)
495 {
496 if (obj->smart.smart->smart_class->move)
497 obj->smart.smart->smart_class->move(obj, nx, ny);
498 }
499
500 obj->cur.geometry.x = nx;
501 obj->cur.geometry.y = ny;
502
503//// obj->cur.cache.geometry.validity = 0;
504 obj->changed_move = 1;
505 evas_object_change(obj);
506 evas_object_clip_dirty(obj);
507 obj->doing.in_move--;
508 if (obj->layer->evas->events_frozen <= 0)
509 {
510 evas_object_recalc_clippees(obj);
511 if (!pass)
512 {
513 if (!obj->smart.smart)
514 {
515 is = evas_object_is_in_output_rect(obj,
516 obj->layer->evas->pointer.x,
517 obj->layer->evas->pointer.y, 1, 1);
518 if ((is ^ was) && obj->cur.visible)
519 evas_event_feed_mouse_move(obj->layer->evas,
520 obj->layer->evas->pointer.x,
521 obj->layer->evas->pointer.y,
522 obj->layer->evas->last_timestamp,
523 NULL);
524 }
525 }
526 }
527 evas_object_inform_call_move(obj);
528}
529
530EAPI void
531evas_object_resize(Evas_Object *obj, Evas_Coord w, Evas_Coord h)
532{
533 int is, was = 0, pass = 0, freeze =0;
534 int nw = 0, nh = 0;
535
536 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
537 return;
538 MAGIC_CHECK_END();
539 if (obj->delete_me) return;
540 if (w < 0) w = 0; if (h < 0) h = 0;
541
542 nw = w;
543 nh = h;
544 if (!obj->is_frame)
545 {
546 int fw, fh;
547
548 evas_output_framespace_get(obj->layer->evas, NULL, NULL, &fw, &fh);
549 if (!obj->smart.parent)
550 {
551 nw = w - fw;
552 nh = h - fh;
553 if (nw < 0) nw = 0;
554 if (nh < 0) nh = 0;
555 }
556 }
557
558 if (evas_object_intercept_call_resize(obj, nw, nh)) return;
559
560 if (obj->doing.in_resize > 0)
561 {
562 WRN("evas_object_resize() called on object %p when in the middle of resizing the same object", obj);
563 return;
564 }
565
566 if ((obj->cur.geometry.w == nw) && (obj->cur.geometry.h == nh)) return;
567
568 if (obj->layer->evas->events_frozen <= 0)
569 {
570 pass = evas_event_passes_through(obj);
571 freeze = evas_event_freezes_through(obj);
572 if ((!pass) && (!freeze))
573 was = evas_object_is_in_output_rect(obj,
574 obj->layer->evas->pointer.x,
575 obj->layer->evas->pointer.y, 1, 1);
576 }
577 obj->doing.in_resize++;
578
579 if (obj->smart.smart)
580 {
581 if (obj->smart.smart->smart_class->resize)
582 obj->smart.smart->smart_class->resize(obj, nw, nh);
583 }
584
585 obj->cur.geometry.w = nw;
586 obj->cur.geometry.h = nh;
587
588//// obj->cur.cache.geometry.validity = 0;
589 evas_object_change(obj);
590 evas_object_clip_dirty(obj);
591 obj->doing.in_resize--;
592 /* NB: evas_object_recalc_clippees was here previously ( < 08/07/2009) */
593 if (obj->layer->evas->events_frozen <= 0)
594 {
595 /* NB: If this creates glitches on screen then move to above position */
596 evas_object_recalc_clippees(obj);
597
598 // if (obj->func->coords_recalc) obj->func->coords_recalc(obj);
599 if (!pass)
600 {
601 if (!obj->smart.smart)
602 {
603 is = evas_object_is_in_output_rect(obj,
604 obj->layer->evas->pointer.x,
605 obj->layer->evas->pointer.y, 1, 1);
606 if ((is ^ was) && (obj->cur.visible))
607 evas_event_feed_mouse_move(obj->layer->evas,
608 obj->layer->evas->pointer.x,
609 obj->layer->evas->pointer.y,
610 obj->layer->evas->last_timestamp,
611 NULL);
612 }
613 }
614 }
615 evas_object_inform_call_resize(obj);
616}
617
618EAPI void
619evas_object_geometry_get(const Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h)
620{
621 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
622 if (x) *x = 0; if (y) *y = 0; if (w) *w = 0; if (h) *h = 0;
623 return;
624 MAGIC_CHECK_END();
625 if (obj->delete_me)
626 {
627 if (x) *x = 0; if (y) *y = 0; if (w) *w = 0; if (h) *h = 0;
628 return;
629 }
630
631 if (x) *x = obj->cur.geometry.x;
632 if (y) *y = obj->cur.geometry.y;
633 if (w) *w = obj->cur.geometry.w;
634 if (h) *h = obj->cur.geometry.h;
635}
636
637static void
638_evas_object_size_hint_alloc(Evas_Object *obj)
639{
640 if (obj->size_hints) return;
641
642 EVAS_MEMPOOL_INIT(_mp_sh, "evas_size_hints", Evas_Size_Hints, 512, );
643 obj->size_hints = EVAS_MEMPOOL_ALLOC(_mp_sh, Evas_Size_Hints);
644 if (!obj->size_hints) return;
645 EVAS_MEMPOOL_PREP(_mp_sh, obj->size_hints, Evas_Size_Hints);
646 obj->size_hints->max.w = -1;
647 obj->size_hints->max.h = -1;
648 obj->size_hints->align.x = 0.5;
649 obj->size_hints->align.y = 0.5;
650}
651
652EAPI void
653evas_object_size_hint_min_get(const Evas_Object *obj, Evas_Coord *w, Evas_Coord *h)
654{
655 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
656 if (w) *w = 0; if (h) *h = 0;
657 return;
658 MAGIC_CHECK_END();
659 if ((!obj->size_hints) || obj->delete_me)
660 {
661 if (w) *w = 0; if (h) *h = 0;
662 return;
663 }
664 if (w) *w = obj->size_hints->min.w;
665 if (h) *h = obj->size_hints->min.h;
666}
667
668EAPI void
669evas_object_size_hint_min_set(Evas_Object *obj, Evas_Coord w, Evas_Coord h)
670{
671 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
672 return;
673 MAGIC_CHECK_END();
674 if (obj->delete_me)
675 return;
676 _evas_object_size_hint_alloc(obj);
677 if ((obj->size_hints->min.w == w) && (obj->size_hints->min.h == h)) return;
678 obj->size_hints->min.w = w;
679 obj->size_hints->min.h = h;
680
681 evas_object_inform_call_changed_size_hints(obj);
682}
683
684EAPI void
685evas_object_size_hint_max_get(const Evas_Object *obj, Evas_Coord *w, Evas_Coord *h)
686{
687 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
688 if (w) *w = -1; if (h) *h = -1;
689 return;
690 MAGIC_CHECK_END();
691 if ((!obj->size_hints) || obj->delete_me)
692 {
693 if (w) *w = -1; if (h) *h = -1;
694 return;
695 }
696 if (w) *w = obj->size_hints->max.w;
697 if (h) *h = obj->size_hints->max.h;
698}
699
700EAPI void
701evas_object_size_hint_max_set(Evas_Object *obj, Evas_Coord w, Evas_Coord h)
702{
703 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
704 return;
705 MAGIC_CHECK_END();
706 if (obj->delete_me)
707 return;
708 _evas_object_size_hint_alloc(obj);
709 if ((obj->size_hints->max.w == w) && (obj->size_hints->max.h == h)) return;
710 obj->size_hints->max.w = w;
711 obj->size_hints->max.h = h;
712
713 evas_object_inform_call_changed_size_hints(obj);
714}
715
716EAPI void
717evas_object_size_hint_request_get(const Evas_Object *obj, Evas_Coord *w, Evas_Coord *h)
718{
719 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
720 if (w) *w = 0; if (h) *h = 0;
721 return;
722 MAGIC_CHECK_END();
723 if ((!obj->size_hints) || obj->delete_me)
724 {
725 if (w) *w = 0; if (h) *h = 0;
726 return;
727 }
728 if (w) *w = obj->size_hints->request.w;
729 if (h) *h = obj->size_hints->request.h;
730}
731
732EAPI void
733evas_object_size_hint_request_set(Evas_Object *obj, Evas_Coord w, Evas_Coord h)
734{
735 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
736 return;
737 MAGIC_CHECK_END();
738 if (obj->delete_me)
739 return;
740 _evas_object_size_hint_alloc(obj);
741 if ((obj->size_hints->request.w == w) && (obj->size_hints->request.h == h)) return;
742 obj->size_hints->request.w = w;
743 obj->size_hints->request.h = h;
744
745 evas_object_inform_call_changed_size_hints(obj);
746}
747
748EAPI void
749evas_object_size_hint_aspect_get(const Evas_Object *obj, Evas_Aspect_Control *aspect, Evas_Coord *w, Evas_Coord *h)
750{
751 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
752 if (aspect) *aspect = EVAS_ASPECT_CONTROL_NONE;
753 if (w) *w = 0; if (h) *h = 0;
754 return;
755 MAGIC_CHECK_END();
756 if ((!obj->size_hints) || obj->delete_me)
757 {
758 if (aspect) *aspect = EVAS_ASPECT_CONTROL_NONE;
759 if (w) *w = 0; if (h) *h = 0;
760 return;
761 }
762 if (aspect) *aspect = obj->size_hints->aspect.mode;
763 if (w) *w = obj->size_hints->aspect.size.w;
764 if (h) *h = obj->size_hints->aspect.size.h;
765}
766
767EAPI void
768evas_object_size_hint_aspect_set(Evas_Object *obj, Evas_Aspect_Control aspect, Evas_Coord w, Evas_Coord h)
769{
770 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
771 return;
772 MAGIC_CHECK_END();
773 if (obj->delete_me)
774 return;
775 _evas_object_size_hint_alloc(obj);
776 if ((obj->size_hints->aspect.mode == aspect) && (obj->size_hints->aspect.size.w == w) && (obj->size_hints->aspect.size.h == h)) return;
777 obj->size_hints->aspect.mode = aspect;
778 obj->size_hints->aspect.size.w = w;
779 obj->size_hints->aspect.size.h = h;
780
781 evas_object_inform_call_changed_size_hints(obj);
782}
783
784EAPI void
785evas_object_size_hint_align_get(const Evas_Object *obj, double *x, double *y)
786{
787 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
788 if (x) *x = 0.5; if (y) *y = 0.5;
789 return;
790 MAGIC_CHECK_END();
791 if ((!obj->size_hints) || obj->delete_me)
792 {
793 if (x) *x = 0.5; if (y) *y = 0.5;
794 return;
795 }
796 if (x) *x = obj->size_hints->align.x;
797 if (y) *y = obj->size_hints->align.y;
798}
799
800EAPI void
801evas_object_size_hint_align_set(Evas_Object *obj, double x, double y)
802{
803 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
804 return;
805 MAGIC_CHECK_END();
806 if (obj->delete_me)
807 return;
808 _evas_object_size_hint_alloc(obj);
809 if ((obj->size_hints->align.x == x) && (obj->size_hints->align.y == y)) return;
810 obj->size_hints->align.x = x;
811 obj->size_hints->align.y = y;
812
813 evas_object_inform_call_changed_size_hints(obj);
814}
815
816EAPI void
817evas_object_size_hint_weight_get(const Evas_Object *obj, double *x, double *y)
818{
819 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
820 if (x) *x = 0.0; if (y) *y = 0.0;
821 return;
822 MAGIC_CHECK_END();
823 if ((!obj->size_hints) || obj->delete_me)
824 {
825 if (x) *x = 0.0; if (y) *y = 0.0;
826 return;
827 }
828 if (x) *x = obj->size_hints->weight.x;
829 if (y) *y = obj->size_hints->weight.y;
830}
831
832EAPI void
833evas_object_size_hint_weight_set(Evas_Object *obj, double x, double y)
834{
835 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
836 return;
837 MAGIC_CHECK_END();
838 if (obj->delete_me)
839 return;
840 _evas_object_size_hint_alloc(obj);
841 if ((obj->size_hints->weight.x == x) && (obj->size_hints->weight.y == y)) return;
842 obj->size_hints->weight.x = x;
843 obj->size_hints->weight.y = y;
844
845 evas_object_inform_call_changed_size_hints(obj);
846}
847
848EAPI void
849evas_object_size_hint_padding_get(const Evas_Object *obj, Evas_Coord *l, Evas_Coord *r, Evas_Coord *t, Evas_Coord *b)
850{
851 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
852 if (l) *l = 0; if (r) *r = 0;
853 if (t) *t = 0; if (b) *b = 0;
854 return;
855 MAGIC_CHECK_END();
856 if ((!obj->size_hints) || obj->delete_me)
857 {
858 if (l) *l = 0; if (r) *r = 0;
859 if (t) *t = 0; if (b) *b = 0;
860 return;
861 }
862 if (l) *l = obj->size_hints->padding.l;
863 if (r) *r = obj->size_hints->padding.r;
864 if (t) *t = obj->size_hints->padding.t;
865 if (b) *b = obj->size_hints->padding.b;
866}
867
868EAPI void
869evas_object_size_hint_padding_set(Evas_Object *obj, Evas_Coord l, Evas_Coord r, Evas_Coord t, Evas_Coord b)
870{
871 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
872 return;
873 MAGIC_CHECK_END();
874 if (obj->delete_me)
875 return;
876 _evas_object_size_hint_alloc(obj);
877 if ((obj->size_hints->padding.l == l) && (obj->size_hints->padding.r == r) && (obj->size_hints->padding.t == t) && (obj->size_hints->padding.b == b)) return;
878 obj->size_hints->padding.l = l;
879 obj->size_hints->padding.r = r;
880 obj->size_hints->padding.t = t;
881 obj->size_hints->padding.b = b;
882
883 evas_object_inform_call_changed_size_hints(obj);
884}
885
886EAPI void
887evas_object_show(Evas_Object *obj)
888{
889 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
890 return;
891 MAGIC_CHECK_END();
892 if (obj->delete_me) return;
893 if (evas_object_intercept_call_show(obj)) return;
894 if (obj->smart.smart)
895 {
896 if (obj->smart.smart->smart_class->show)
897 obj->smart.smart->smart_class->show(obj);
898 }
899 if (obj->cur.visible)
900 {
901 return;
902 }
903 obj->cur.visible = 1;
904 evas_object_change(obj);
905 evas_object_clip_dirty(obj);
906 if (obj->layer->evas->events_frozen <= 0)
907 {
908 evas_object_clip_across_clippees_check(obj);
909 evas_object_recalc_clippees(obj);
910 if ((!evas_event_passes_through(obj)) &&
911 (!evas_event_freezes_through(obj)))
912 {
913 if (!obj->smart.smart)
914 {
915 if (evas_object_is_in_output_rect(obj,
916 obj->layer->evas->pointer.x,
917 obj->layer->evas->pointer.y, 1, 1))
918 evas_event_feed_mouse_move(obj->layer->evas,
919 obj->layer->evas->pointer.x,
920 obj->layer->evas->pointer.y,
921 obj->layer->evas->last_timestamp,
922 NULL);
923 }
924 }
925 }
926 evas_object_inform_call_show(obj);
927}
928
929EAPI void
930evas_object_hide(Evas_Object *obj)
931{
932 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
933 return;
934 MAGIC_CHECK_END();
935 if (obj->delete_me) return;
936 if (evas_object_intercept_call_hide(obj)) return;
937 if (obj->smart.smart)
938 {
939 if (obj->smart.smart->smart_class->hide)
940 obj->smart.smart->smart_class->hide(obj);
941 }
942 if (!obj->cur.visible)
943 {
944 return;
945 }
946 obj->cur.visible = 0;
947 evas_object_change(obj);
948 evas_object_clip_dirty(obj);
949 if (obj->layer->evas->events_frozen <= 0)
950 {
951 evas_object_clip_across_clippees_check(obj);
952 evas_object_recalc_clippees(obj);
953 if ((!evas_event_passes_through(obj)) &&
954 (!evas_event_freezes_through(obj)))
955 {
956 if ((!obj->smart.smart) ||
957 ((obj->cur.map) && (obj->cur.map->count == 4) && (obj->cur.usemap)))
958 {
959 if (!obj->mouse_grabbed)
960 {
961 if (evas_object_is_in_output_rect(obj,
962 obj->layer->evas->pointer.x,
963 obj->layer->evas->pointer.y, 1, 1))
964 evas_event_feed_mouse_move(obj->layer->evas,
965 obj->layer->evas->pointer.x,
966 obj->layer->evas->pointer.y,
967 obj->layer->evas->last_timestamp,
968 NULL);
969 }
970/* this is at odds to handling events when an obj is moved out of the mouse
971 * ore resized out or clipped out. if mouse is grabbed - regardless of
972 * visibility, mouse move events should keep happening and mouse up.
973 * for better or worse it's at least consistent.
974 if (obj->delete_me) return;
975 if (obj->mouse_grabbed > 0)
976 obj->layer->evas->pointer.mouse_grabbed -= obj->mouse_grabbed;
977 if ((obj->mouse_in) || (obj->mouse_grabbed > 0))
978 obj->layer->evas->pointer.object.in = eina_list_remove(obj->layer->evas->pointer.object.in, obj);
979 obj->mouse_grabbed = 0;
980 if (obj->layer->evas->events_frozen > 0)
981 {
982 obj->mouse_in = 0;
983 return;
984 }
985 if (obj->mouse_in)
986 {
987 Evas_Event_Mouse_Out ev;
988
989 _evas_object_event_new();
990
991 obj->mouse_in = 0;
992 ev.buttons = obj->layer->evas->pointer.button;
993 ev.output.x = obj->layer->evas->pointer.x;
994 ev.output.y = obj->layer->evas->pointer.y;
995 ev.canvas.x = obj->layer->evas->pointer.x;
996 ev.canvas.y = obj->layer->evas->pointer.y;
997 ev.data = NULL;
998 ev.modifiers = &(obj->layer->evas->modifiers);
999 ev.locks = &(obj->layer->evas->locks);
1000 ev.timestamp = obj->layer->evas->last_timestamp;
1001 ev.event_flags = EVAS_EVENT_FLAG_NONE;
1002 evas_object_event_callback_call(obj, EVAS_CALLBACK_MOUSE_OUT, &ev);
1003 _evas_post_event_callback_call(obj->layer->evas);
1004 }
1005 */
1006 }
1007 }
1008 }
1009 else
1010 {
1011/*
1012 if (obj->mouse_grabbed > 0)
1013 obj->layer->evas->pointer.mouse_grabbed -= obj->mouse_grabbed;
1014 if ((obj->mouse_in) || (obj->mouse_grabbed > 0))
1015 obj->layer->evas->pointer.object.in = eina_list_remove(obj->layer->evas->pointer.object.in, obj);
1016 obj->mouse_grabbed = 0;
1017 obj->mouse_in = 0;
1018 */
1019 }
1020 evas_object_inform_call_hide(obj);
1021}
1022
1023EAPI Eina_Bool
1024evas_object_visible_get(const Evas_Object *obj)
1025{
1026 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1027 return 0;
1028 MAGIC_CHECK_END();
1029 if (obj->delete_me) return 0;
1030 return obj->cur.visible;
1031}
1032
1033EAPI void
1034evas_object_color_set(Evas_Object *obj, int r, int g, int b, int a)
1035{
1036 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1037 return;
1038 MAGIC_CHECK_END();
1039 if (obj->delete_me) return;
1040 if (r > 255) r = 255; if (r < 0) r = 0;
1041 if (g > 255) g = 255; if (g < 0) g = 0;
1042 if (b > 255) b = 255; if (b < 0) b = 0;
1043 if (a > 255) a = 255; if (a < 0) a = 0;
1044 if (r > a)
1045 {
1046 r = a;
1047 ERR("Evas only handle pre multiplied color !");
1048 }
1049 if (g > a)
1050 {
1051 g = a;
1052 ERR("Evas only handle pre multiplied color !");
1053 }
1054 if (b > a)
1055 {
1056 b = a;
1057 ERR("Evas only handle pre multiplied color !");
1058 }
1059
1060 if (evas_object_intercept_call_color_set(obj, r, g, b, a)) return;
1061 if (obj->smart.smart)
1062 {
1063 if (obj->smart.smart->smart_class->color_set)
1064 obj->smart.smart->smart_class->color_set(obj, r, g, b, a);
1065 }
1066 if ((obj->cur.color.r == r) &&
1067 (obj->cur.color.g == g) &&
1068 (obj->cur.color.b == b) &&
1069 (obj->cur.color.a == a)) return;
1070 obj->cur.color.r = r;
1071 obj->cur.color.g = g;
1072 obj->cur.color.b = b;
1073 evas_object_clip_dirty(obj);
1074 if ((obj->cur.color.a == 0) && (a == 0) && (obj->cur.render_op == EVAS_RENDER_BLEND)) return;
1075 obj->cur.color.a = a;
1076 evas_object_change(obj);
1077}
1078
1079EAPI void
1080evas_object_color_get(const Evas_Object *obj, int *r, int *g, int *b, int *a)
1081{
1082 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1083 if (r) *r = 0; if (g) *g = 0; if (b) *b = 0; if (a) *a = 0;
1084 return;
1085 MAGIC_CHECK_END();
1086 if (obj->delete_me)
1087 {
1088 if (r) *r = 0; if (g) *g = 0; if (b) *b = 0; if (a) *a = 0;
1089 return;
1090 }
1091 if (r) *r = obj->cur.color.r;
1092 if (g) *g = obj->cur.color.g;
1093 if (b) *b = obj->cur.color.b;
1094 if (a) *a = obj->cur.color.a;
1095}
1096
1097EAPI void
1098evas_object_anti_alias_set(Evas_Object *obj, Eina_Bool anti_alias)
1099{
1100 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1101 return;
1102 MAGIC_CHECK_END();
1103 if (obj->delete_me) return;
1104 anti_alias = !!anti_alias;
1105 if (obj->cur.anti_alias == anti_alias)return;
1106 obj->cur.anti_alias = anti_alias;
1107 evas_object_change(obj);
1108}
1109
1110EAPI Eina_Bool
1111evas_object_anti_alias_get(const Evas_Object *obj)
1112{
1113 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1114 return 0;
1115 MAGIC_CHECK_END();
1116 if (obj->delete_me) return 0;
1117 return obj->cur.anti_alias;
1118}
1119
1120EAPI void
1121evas_object_scale_set(Evas_Object *obj, double scale)
1122{
1123 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1124 return;
1125 MAGIC_CHECK_END();
1126 if (obj->delete_me) return;
1127 if (obj->cur.scale == scale) return;
1128 obj->cur.scale = scale;
1129 evas_object_change(obj);
1130 if (obj->func->scale_update) obj->func->scale_update(obj);
1131}
1132
1133EAPI double
1134evas_object_scale_get(const Evas_Object *obj)
1135{
1136 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1137 return 0;
1138 MAGIC_CHECK_END();
1139 if (obj->delete_me) return 1.0;
1140 return obj->cur.scale;
1141}
1142
1143EAPI void
1144evas_object_render_op_set(Evas_Object *obj, Evas_Render_Op render_op)
1145{
1146 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1147 return;
1148 MAGIC_CHECK_END();
1149 if (obj->delete_me) return;
1150 if (obj->cur.render_op == render_op) return;
1151 obj->cur.render_op = render_op;
1152 evas_object_change(obj);
1153}
1154
1155EAPI Evas_Render_Op
1156evas_object_render_op_get(const Evas_Object *obj)
1157{
1158 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1159 return 0;
1160 MAGIC_CHECK_END();
1161 if (obj->delete_me) return EVAS_RENDER_BLEND;
1162 return obj->cur.render_op;
1163}
1164
1165EAPI Evas *
1166evas_object_evas_get(const Evas_Object *obj)
1167{
1168 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1169 return NULL;
1170 MAGIC_CHECK_END();
1171 if (obj->delete_me) return NULL;
1172 return obj->layer->evas;
1173}
1174
1175EAPI Evas_Object *
1176evas_object_top_at_xy_get(const Evas *e, Evas_Coord x, Evas_Coord y, Eina_Bool include_pass_events_objects, Eina_Bool include_hidden_objects)
1177{
1178 Evas_Layer *lay;
1179 int xx, yy;
1180
1181 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1182 return NULL;
1183 MAGIC_CHECK_END();
1184 xx = x;
1185 yy = y;
1186//// xx = evas_coord_world_x_to_screen(e, x);
1187//// yy = evas_coord_world_y_to_screen(e, y);
1188 EINA_INLIST_REVERSE_FOREACH((EINA_INLIST_GET(e->layers)), lay)
1189 {
1190 Evas_Object *obj;
1191
1192 EINA_INLIST_REVERSE_FOREACH(get_layer_objects(lay), obj)
1193 {
1194 if (obj->delete_me) continue;
1195 if ((!include_pass_events_objects) &&
1196 (evas_event_passes_through(obj))) continue;
1197 if ((!include_hidden_objects) && (!obj->cur.visible)) continue;
1198 evas_object_clip_recalc(obj);
1199 if ((evas_object_is_in_output_rect(obj, xx, yy, 1, 1)) &&
1200 (!obj->clip.clipees))
1201 return obj;
1202 }
1203 }
1204 return NULL;
1205}
1206
1207EAPI Evas_Object *
1208evas_object_top_at_pointer_get(const Evas *e)
1209{
1210 return evas_object_top_at_xy_get(e, e->pointer.x, e->pointer.y, EINA_TRUE,
1211 EINA_TRUE);
1212}
1213
1214EAPI Evas_Object *
1215evas_object_top_in_rectangle_get(const Evas *e, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h, Eina_Bool include_pass_events_objects, Eina_Bool include_hidden_objects)
1216{
1217 Evas_Layer *lay;
1218 int xx, yy, ww, hh;
1219
1220 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1221 return NULL;
1222 MAGIC_CHECK_END();
1223 xx = x;
1224 yy = y;
1225 ww = w;
1226 hh = h;
1227//// xx = evas_coord_world_x_to_screen(e, x);
1228//// yy = evas_coord_world_y_to_screen(e, y);
1229//// ww = evas_coord_world_x_to_screen(e, w);
1230//// hh = evas_coord_world_y_to_screen(e, h);
1231 if (ww < 1) ww = 1;
1232 if (hh < 1) hh = 1;
1233 EINA_INLIST_REVERSE_FOREACH((EINA_INLIST_GET(e->layers)), lay)
1234 {
1235 Evas_Object *obj;
1236
1237 EINA_INLIST_REVERSE_FOREACH(get_layer_objects(lay), obj)
1238 {
1239 if (obj->delete_me) continue;
1240 if ((!include_pass_events_objects) &&
1241 (evas_event_passes_through(obj))) continue;
1242 if ((!include_hidden_objects) && (!obj->cur.visible)) continue;
1243 evas_object_clip_recalc(obj);
1244 if ((evas_object_is_in_output_rect(obj, xx, yy, ww, hh)) &&
1245 (!obj->clip.clipees))
1246 return obj;
1247 }
1248 }
1249 return NULL;
1250}
1251
1252EAPI Eina_List *
1253evas_objects_at_xy_get(const Evas *e, Evas_Coord x, Evas_Coord y, Eina_Bool include_pass_events_objects, Eina_Bool include_hidden_objects)
1254{
1255 Eina_List *in = NULL;
1256 Evas_Layer *lay;
1257 int xx, yy;
1258
1259 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1260 return NULL;
1261 MAGIC_CHECK_END();
1262 xx = x;
1263 yy = y;
1264//// xx = evas_coord_world_x_to_screen(e, x);
1265//// yy = evas_coord_world_y_to_screen(e, y);
1266 EINA_INLIST_REVERSE_FOREACH((EINA_INLIST_GET(e->layers)), lay)
1267 {
1268 Evas_Object *obj;
1269
1270 EINA_INLIST_REVERSE_FOREACH(get_layer_objects(lay), obj)
1271 {
1272 if (obj->delete_me) continue;
1273 if ((!include_pass_events_objects) &&
1274 (evas_event_passes_through(obj))) continue;
1275 if ((!include_hidden_objects) && (!obj->cur.visible)) continue;
1276 evas_object_clip_recalc(obj);
1277 if ((evas_object_is_in_output_rect(obj, xx, yy, 1, 1)) &&
1278 (!obj->clip.clipees))
1279 in = eina_list_prepend(in, obj);
1280 }
1281 }
1282 return in;
1283}
1284
1285/**
1286 * Retrieves the objects in the given rectangle region
1287 * @param e The given evas object.
1288 * @param x The horizontal coordinate.
1289 * @param y The vertical coordinate.
1290 * @param w The width size.
1291 * @param h The height size.
1292 * @param include_pass_events_objects Boolean Flag to include or not pass events objects
1293 * @param include_hidden_objects Boolean Flag to include or not hidden objects
1294 * @return The list of evas object in the rectangle region.
1295 *
1296 */
1297EAPI Eina_List *
1298evas_objects_in_rectangle_get(const Evas *e, Evas_Coord x, Evas_Coord y, Evas_Coord w, Evas_Coord h, Eina_Bool include_pass_events_objects, Eina_Bool include_hidden_objects)
1299{
1300 Eina_List *in = NULL;
1301 Evas_Layer *lay;
1302 int xx, yy, ww, hh;
1303
1304 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1305 return NULL;
1306 MAGIC_CHECK_END();
1307 xx = x;
1308 yy = y;
1309 ww = w;
1310 hh = h;
1311//// xx = evas_coord_world_x_to_screen(e, x);
1312//// yy = evas_coord_world_y_to_screen(e, y);
1313//// ww = evas_coord_world_x_to_screen(e, w);
1314//// hh = evas_coord_world_y_to_screen(e, h);
1315 if (ww < 1) ww = 1;
1316 if (hh < 1) hh = 1;
1317 EINA_INLIST_REVERSE_FOREACH((EINA_INLIST_GET(e->layers)), lay)
1318 {
1319 Evas_Object *obj;
1320
1321 EINA_INLIST_REVERSE_FOREACH(get_layer_objects(lay), obj)
1322 {
1323 if (obj->delete_me) continue;
1324 if ((!include_pass_events_objects) &&
1325 (evas_event_passes_through(obj))) continue;
1326 if ((!include_hidden_objects) && (!obj->cur.visible)) continue;
1327 evas_object_clip_recalc(obj);
1328 if ((evas_object_is_in_output_rect(obj, xx, yy, ww, hh)) &&
1329 (!obj->clip.clipees))
1330 in = eina_list_prepend(in, obj);
1331 }
1332 }
1333 return in;
1334}
1335
1336EAPI const char *
1337evas_object_type_get(const Evas_Object *obj)
1338{
1339 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1340 return NULL;
1341 MAGIC_CHECK_END();
1342 if (obj->delete_me) return "";
1343 return obj->type;
1344}
1345
1346EAPI void
1347evas_object_precise_is_inside_set(Evas_Object *obj, Eina_Bool precise)
1348{
1349 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1350 return;
1351 MAGIC_CHECK_END();
1352 obj->precise_is_inside = precise;
1353}
1354
1355EAPI Eina_Bool
1356evas_object_precise_is_inside_get(const Evas_Object *obj)
1357{
1358 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1359 return 0;
1360 MAGIC_CHECK_END();
1361 return obj->precise_is_inside;
1362}
1363
1364EAPI void
1365evas_object_static_clip_set(Evas_Object *obj, Eina_Bool is_static_clip)
1366{
1367 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1368 return;
1369 MAGIC_CHECK_END();
1370 obj->is_static_clip = is_static_clip;
1371}
1372
1373EAPI Eina_Bool
1374evas_object_static_clip_get(const Evas_Object *obj)
1375{
1376 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1377 return 0;
1378 MAGIC_CHECK_END();
1379 return obj->is_static_clip;
1380}
1381
1382EAPI void
1383evas_object_is_frame_object_set(Evas_Object *obj, Eina_Bool is_frame)
1384{
1385 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1386 return;
1387 MAGIC_CHECK_END();
1388 obj->is_frame = is_frame;
1389}
1390
1391EAPI Eina_Bool
1392evas_object_is_frame_object_get(Evas_Object *obj)
1393{
1394 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1395 return EINA_FALSE;
1396 MAGIC_CHECK_END();
1397 return obj->is_frame;
1398}
diff --git a/libraries/evas/src/lib/canvas/evas_object_polygon.c b/libraries/evas/src/lib/canvas/evas_object_polygon.c
deleted file mode 100644
index cbc1802..0000000
--- a/libraries/evas/src/lib/canvas/evas_object_polygon.c
+++ /dev/null
@@ -1,554 +0,0 @@
1#include "evas_common.h"
2#include "evas_private.h"
3
4/* private magic number for polygon objects */
5static const char o_type[] = "polygon";
6
7/* private struct for line object internal data */
8typedef struct _Evas_Object_Polygon Evas_Object_Polygon;
9typedef struct _Evas_Polygon_Point Evas_Polygon_Point;
10
11struct _Evas_Object_Polygon
12{
13 DATA32 magic;
14 Eina_List *points;
15 void *engine_data;
16 struct {
17 int x, y;
18 } offset;
19 Evas_Coord_Rectangle geometry;
20 char changed : 1;
21};
22
23struct _Evas_Polygon_Point
24{
25 Evas_Coord x, y;
26};
27
28/* private methods for polygon objects */
29static void evas_object_polygon_init(Evas_Object *obj);
30static void *evas_object_polygon_new(void);
31static void evas_object_polygon_render(Evas_Object *obj, void *output, void *context, void *surface, int x, int y);
32static void evas_object_polygon_free(Evas_Object *obj);
33static void evas_object_polygon_render_pre(Evas_Object *obj);
34static void evas_object_polygon_render_post(Evas_Object *obj);
35
36static unsigned int evas_object_polygon_id_get(Evas_Object *obj);
37static unsigned int evas_object_polygon_visual_id_get(Evas_Object *obj);
38static void *evas_object_polygon_engine_data_get(Evas_Object *obj);
39
40static int evas_object_polygon_is_opaque(Evas_Object *obj);
41static int evas_object_polygon_was_opaque(Evas_Object *obj);
42static int evas_object_polygon_is_inside(Evas_Object *obj, Evas_Coord x, Evas_Coord y);
43static int evas_object_polygon_was_inside(Evas_Object *obj, Evas_Coord x, Evas_Coord y);
44
45static const Evas_Object_Func object_func =
46{
47 /* methods (compulsory) */
48 evas_object_polygon_free,
49 evas_object_polygon_render,
50 evas_object_polygon_render_pre,
51 evas_object_polygon_render_post,
52 evas_object_polygon_id_get,
53 evas_object_polygon_visual_id_get,
54 evas_object_polygon_engine_data_get,
55 /* these are optional. NULL = nothing */
56 NULL,
57 NULL,
58 NULL,
59 NULL,
60 evas_object_polygon_is_opaque,
61 evas_object_polygon_was_opaque,
62 evas_object_polygon_is_inside,
63 evas_object_polygon_was_inside,
64 NULL,
65 NULL,
66 NULL,
67 NULL,
68 NULL
69};
70
71/* the actual api call to add a rect */
72/* it has no other api calls as all properties are standard */
73
74EVAS_MEMPOOL(_mp_obj);
75
76EAPI Evas_Object *
77evas_object_polygon_add(Evas *e)
78{
79 Evas_Object *obj;
80
81 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
82 return NULL;
83 MAGIC_CHECK_END();
84 obj = evas_object_new(e);
85 evas_object_polygon_init(obj);
86 evas_object_inject(obj, e);
87 return obj;
88}
89
90EAPI void
91evas_object_polygon_point_add(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
92{
93 Evas_Object_Polygon *o;
94 Evas_Polygon_Point *p;
95 Evas_Coord min_x, max_x, min_y, max_y;
96 int is, was = 0;
97
98 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
99 return;
100 MAGIC_CHECK_END();
101 o = (Evas_Object_Polygon *)(obj->object_data);
102 MAGIC_CHECK(o, Evas_Object_Polygon, MAGIC_OBJ_POLYGON);
103 return;
104 MAGIC_CHECK_END();
105
106 if (obj->layer->evas->events_frozen <= 0)
107 {
108 if (!evas_event_passes_through(obj) &&
109 !evas_event_freezes_through(obj))
110 was = evas_object_is_in_output_rect(obj,
111 obj->layer->evas->pointer.x,
112 obj->layer->evas->pointer.y,
113 1, 1);
114 }
115 if (!o->points)
116 {
117 o->offset.x = obj->cur.geometry.x;
118 o->offset.y = obj->cur.geometry.y;
119 }
120 else
121 {
122 /* Update all points and take offset into account. */
123 Eina_List *over;
124
125 EINA_LIST_FOREACH(o->points, over, p)
126 {
127 p->x += o->offset.x;
128 p->y += o->offset.y;
129 }
130 }
131
132 p = malloc(sizeof(Evas_Polygon_Point));
133 if (!p) return;
134 p->x = x + o->offset.x;
135 p->y = y + o->offset.y;
136
137 if (!o->points)
138 {
139 obj->cur.geometry.x = p->x;
140 obj->cur.geometry.y = p->y;
141 obj->cur.geometry.w = 2;
142 obj->cur.geometry.h = 2;
143 }
144 else
145 {
146 if (p->x < obj->cur.geometry.x) min_x = p->x;
147 else min_x = obj->cur.geometry.x;
148 if (p->x > (obj->cur.geometry.x + obj->cur.geometry.w - 2))
149 max_x = p->x;
150 else max_x = obj->cur.geometry.x + obj->cur.geometry.w - 2;
151 if (p->y < obj->cur.geometry.y) min_y = p->y;
152 else min_y = obj->cur.geometry.y;
153 if (p->y > (obj->cur.geometry.y + obj->cur.geometry.h - 2))
154 max_y = p->y;
155 else max_y = obj->cur.geometry.y + obj->cur.geometry.h - 2;
156 obj->cur.geometry.x = min_x;
157 obj->cur.geometry.y = min_y;
158 obj->cur.geometry.w = max_x - min_x + 2;
159 obj->cur.geometry.h = max_y - min_y + 2;
160 }
161 o->points = eina_list_append(o->points, p);
162
163 o->geometry = obj->cur.geometry;
164 o->offset.x = 0;
165 o->offset.y = 0;
166
167 //// obj->cur.cache.geometry.validity = 0;
168 o->changed = EINA_TRUE;
169 evas_object_change(obj);
170 evas_object_clip_dirty(obj);
171 evas_object_coords_recalc(obj);
172 if (obj->layer->evas->events_frozen <= 0)
173 {
174 is = evas_object_is_in_output_rect(obj,
175 obj->layer->evas->pointer.x,
176 obj->layer->evas->pointer.y, 1, 1);
177 if (!evas_event_passes_through(obj) &&
178 !evas_event_freezes_through(obj) )
179 {
180 if ((is ^ was) && obj->cur.visible)
181 evas_event_feed_mouse_move(obj->layer->evas,
182 obj->layer->evas->pointer.x,
183 obj->layer->evas->pointer.y,
184 obj->layer->evas->last_timestamp,
185 NULL);
186 }
187 }
188 evas_object_inform_call_move(obj);
189 evas_object_inform_call_resize(obj);
190}
191
192EAPI void
193evas_object_polygon_points_clear(Evas_Object *obj)
194{
195 Evas_Object_Polygon *o;
196 int is, was;
197
198 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
199 return;
200 MAGIC_CHECK_END();
201 o = (Evas_Object_Polygon *)(obj->object_data);
202 MAGIC_CHECK(o, Evas_Object_Polygon, MAGIC_OBJ_POLYGON);
203 return;
204 MAGIC_CHECK_END();
205 was = evas_object_is_in_output_rect(obj,
206 obj->layer->evas->pointer.x,
207 obj->layer->evas->pointer.y, 1, 1);
208 while (o->points)
209 {
210 free(o->points->data);
211 o->points = eina_list_remove(o->points, o->points->data);
212 }
213 obj->cur.geometry.x = 0;
214 obj->cur.geometry.y = 0;
215 obj->cur.geometry.w = 0;
216 obj->cur.geometry.h = 0;
217 //// obj->cur.cache.geometry.validity = 0;
218 o->changed = EINA_TRUE;
219 evas_object_change(obj);
220 evas_object_clip_dirty(obj);
221 evas_object_coords_recalc(obj);
222 is = evas_object_is_in_output_rect(obj,
223 obj->layer->evas->pointer.x,
224 obj->layer->evas->pointer.y, 1, 1);
225 if ((is || was) && obj->cur.visible)
226 evas_event_feed_mouse_move(obj->layer->evas,
227 obj->layer->evas->pointer.x,
228 obj->layer->evas->pointer.y,
229 obj->layer->evas->last_timestamp,
230 NULL);
231 evas_object_inform_call_move(obj);
232 evas_object_inform_call_resize(obj);
233}
234
235/* all nice and private */
236static void
237evas_object_polygon_init(Evas_Object *obj)
238{
239 /* alloc image ob, setup methods and default values */
240 obj->object_data = evas_object_polygon_new();
241 /* set up default settings for this kind of object */
242 obj->cur.color.r = 255;
243 obj->cur.color.g = 255;
244 obj->cur.color.b = 255;
245 obj->cur.color.a = 255;
246 obj->cur.geometry.x = 0;
247 obj->cur.geometry.y = 0;
248 obj->cur.geometry.w = 0;
249 obj->cur.geometry.h = 0;
250 obj->cur.layer = 0;
251 /* set up object-specific settings */
252 obj->prev = obj->cur;
253 /* set up methods (compulsory) */
254 obj->func = &object_func;
255 obj->type = o_type;
256}
257
258static void *
259evas_object_polygon_new(void)
260{
261 Evas_Object_Polygon *o;
262
263 /* alloc obj private data */
264 EVAS_MEMPOOL_INIT(_mp_obj, "evas_object_polygon", Evas_Object_Polygon, 32, NULL);
265 o = EVAS_MEMPOOL_ALLOC(_mp_obj, Evas_Object_Polygon);
266 if (!o) return NULL;
267 EVAS_MEMPOOL_PREP(_mp_obj, o, Evas_Object_Polygon);
268 o->magic = MAGIC_OBJ_POLYGON;
269 return o;
270}
271
272static void
273evas_object_polygon_free(Evas_Object *obj)
274{
275 Evas_Object_Polygon *o;
276
277 /* frees private object data. very simple here */
278 o = (Evas_Object_Polygon *)(obj->object_data);
279 MAGIC_CHECK(o, Evas_Object_Polygon, MAGIC_OBJ_POLYGON);
280 return;
281 MAGIC_CHECK_END();
282 /* free obj */
283 while (o->points)
284 {
285 free(o->points->data);
286 o->points = eina_list_remove(o->points, o->points->data);
287 }
288 o->engine_data = obj->layer->evas->engine.func->polygon_points_clear(obj->layer->evas->engine.data.output,
289 obj->layer->evas->engine.data.context,
290 o->engine_data);
291 o->magic = 0;
292 EVAS_MEMPOOL_FREE(_mp_obj, o);
293}
294
295static void
296evas_object_polygon_render(Evas_Object *obj, void *output, void *context, void *surface, int x, int y)
297{
298 Evas_Object_Polygon *o;
299 Eina_List *l;
300 Evas_Polygon_Point *p;
301
302 /* render object to surface with context, and offxet by x,y */
303 o = (Evas_Object_Polygon *)(obj->object_data);
304 obj->layer->evas->engine.func->context_color_set(output,
305 context,
306 obj->cur.cache.clip.r,
307 obj->cur.cache.clip.g,
308 obj->cur.cache.clip.b,
309 obj->cur.cache.clip.a);
310 obj->layer->evas->engine.func->context_multiplier_unset(output,
311 context);
312 obj->layer->evas->engine.func->context_render_op_set(output, context,
313 obj->cur.render_op);
314 if (o->changed)
315 {
316 o->engine_data = obj->layer->evas->engine.func->polygon_points_clear(obj->layer->evas->engine.data.output,
317 obj->layer->evas->engine.data.context,
318 o->engine_data);
319 EINA_LIST_FOREACH(o->points, l, p)
320 {
321 //px = evas_coord_world_x_to_screen(obj->layer->evas, p->x);
322 //py = evas_coord_world_y_to_screen(obj->layer->evas, p->y);
323 o->engine_data = obj->layer->evas->engine.func->polygon_point_add(obj->layer->evas->engine.data.output,
324 obj->layer->evas->engine.data.context,
325 o->engine_data,
326 p->x, p->y);
327 }
328 }
329
330 if (o->engine_data)
331 obj->layer->evas->engine.func->polygon_draw(output,
332 context,
333 surface,
334 o->engine_data,
335 o->offset.x + x, o->offset.y + y);
336}
337
338static void
339evas_object_polygon_render_pre(Evas_Object *obj)
340{
341 Evas_Object_Polygon *o;
342 int is_v, was_v;
343
344 /* dont pre-render the obj twice! */
345 if (obj->pre_render_done) return;
346 obj->pre_render_done = 1;
347 /* pre-render phase. this does anything an object needs to do just before */
348 /* rendering. this could mean loading the image data, retrieving it from */
349 /* elsewhere, decoding video etc. */
350 /* then when this is done the object needs to figure if it changed and */
351 /* if so what and where and add the appropriate redraw lines */
352 o = (Evas_Object_Polygon *)(obj->object_data);
353 /* if someone is clipping this obj - go calculate the clipper */
354 if (obj->cur.clipper)
355 {
356 if (obj->cur.cache.clip.dirty)
357 evas_object_clip_recalc(obj->cur.clipper);
358 obj->cur.clipper->func->render_pre(obj->cur.clipper);
359 }
360 /* now figure what changed and add draw rects */
361 /* if it just became visible or invisible */
362 is_v = evas_object_is_visible(obj);
363 was_v = evas_object_was_visible(obj);
364 if (is_v != was_v)
365 {
366 evas_object_render_pre_visible_change(&obj->layer->evas->clip_changes, obj, is_v, was_v);
367 goto done;
368 }
369 if ((obj->cur.map != obj->prev.map) ||
370 (obj->cur.usemap != obj->prev.usemap))
371 {
372 evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes, obj);
373 goto done;
374 }
375 /* it's not visible - we accounted for it appearing or not so just abort */
376 if (!is_v) goto done;
377 /* clipper changed this is in addition to anything else for obj */
378 evas_object_render_pre_clipper_change(&obj->layer->evas->clip_changes, obj);
379 /* if we restacked (layer or just within a layer) */
380 if (obj->restack)
381 {
382 evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes, obj);
383 goto done;
384 }
385 /* if it changed render op */
386 if (obj->cur.render_op != obj->prev.render_op)
387 {
388 evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes, obj);
389 goto done;
390 }
391 /* if it changed color */
392 if ((obj->cur.color.r != obj->prev.color.r) ||
393 (obj->cur.color.g != obj->prev.color.g) ||
394 (obj->cur.color.b != obj->prev.color.b) ||
395 (obj->cur.color.a != obj->prev.color.a))
396 {
397 evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes, obj);
398 goto done;
399 }
400 /* if it changed geometry - and obviously not visibility or color */
401 /* calculate differences since we have a constant color fill */
402 /* we really only need to update the differences */
403 if ((obj->cur.geometry.x != obj->prev.geometry.x) ||
404 (obj->cur.geometry.y != obj->prev.geometry.y) ||
405 (obj->cur.geometry.w != obj->prev.geometry.w) ||
406 (obj->cur.geometry.h != obj->prev.geometry.h) ||
407 (o->changed))
408 {
409 evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes, obj);
410 goto done;
411 }
412 done:
413 if ((obj->cur.geometry.x != obj->prev.geometry.x) ||
414 (obj->cur.geometry.y != obj->prev.geometry.y))
415 {
416 if (!o->changed)
417 {
418 o->offset.x += obj->cur.geometry.x - obj->prev.geometry.x;
419 o->offset.y += obj->cur.geometry.y - obj->prev.geometry.y;
420 }
421 else
422 {
423 o->offset.x += obj->cur.geometry.x - o->geometry.x;
424 o->offset.y += obj->cur.geometry.y - o->geometry.y;
425 }
426 }
427 evas_object_render_pre_effect_updates(&obj->layer->evas->clip_changes, obj, is_v, was_v);
428}
429
430static void
431evas_object_polygon_render_post(Evas_Object *obj)
432{
433 Evas_Object_Polygon *o;
434
435 /* this moves the current data to the previous state parts of the object */
436 /* in whatever way is safest for the object. also if we don't need object */
437 /* data anymore we can free it if the object deems this is a good idea */
438 o = (Evas_Object_Polygon *)(obj->object_data);
439 /* remove those pesky changes */
440 evas_object_clip_changes_clean(obj);
441 /* move cur to prev safely for object data */
442 obj->prev = obj->cur;
443 o->changed = 0;
444}
445
446static unsigned int evas_object_polygon_id_get(Evas_Object *obj)
447{
448 Evas_Object_Polygon *o;
449
450 o = (Evas_Object_Polygon *)(obj->object_data);
451 if (!o) return 0;
452 return MAGIC_OBJ_POLYGON;
453}
454
455static unsigned int evas_object_polygon_visual_id_get(Evas_Object *obj)
456{
457 Evas_Object_Polygon *o;
458
459 o = (Evas_Object_Polygon *)(obj->object_data);
460 if (!o) return 0;
461 return MAGIC_OBJ_SHAPE;
462}
463
464static void *evas_object_polygon_engine_data_get(Evas_Object *obj)
465{
466 Evas_Object_Polygon *o;
467
468 o = (Evas_Object_Polygon *)(obj->object_data);
469 if (!o) return NULL;
470 return o->engine_data;
471}
472
473static int
474evas_object_polygon_is_opaque(Evas_Object *obj __UNUSED__)
475{
476 /* this returns 1 if the internal object data implies that the object is */
477 /* currently fully opaque over the entire line it occupies */
478 return 0;
479}
480
481static int
482evas_object_polygon_was_opaque(Evas_Object *obj __UNUSED__)
483{
484 /* this returns 1 if the internal object data implies that the object was */
485 /* previously fully opaque over the entire line it occupies */
486 return 0;
487}
488
489/* We count the number of edges a "ray" 90 degs upwards from our point
490 * intersects with. If it's even, we are outside of the polygon, if it's odd,
491 * we are inside of it. */
492static int
493evas_object_polygon_is_inside(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
494{
495 Evas_Object_Polygon *o;
496 int num_edges = 0; /* Number of edges we crossed */
497 Eina_List *itr;
498 Evas_Polygon_Point *p;
499
500 o = (Evas_Object_Polygon *)(obj->object_data);
501 if (!o) return 0;
502 if (!o->points) return 0;
503
504 /* Adjust X and Y according to current geometry */
505 x -= o->offset.x;
506 y -= o->offset.y;
507
508 if (eina_list_count(o->points) == 1)
509 {
510 p = eina_list_data_get(o->points);
511 return ((p->x == x) && (p->y == y));
512 }
513
514 EINA_LIST_FOREACH(o->points, itr, p)
515 {
516 Evas_Coord line_y;
517 Eina_List *next = eina_list_next(itr);
518 Evas_Polygon_Point *p_next;
519 /* Get the next, or if there's no next, take the first */
520 if (next)
521 {
522 p_next = eina_list_data_get(next);
523 }
524 else
525 {
526 p_next = eina_list_data_get(o->points);
527 }
528
529 /* Make sure that we are directly below the edge,
530 * and that p->x != p_next->x */
531 if (((p->x < p_next->x) && (p->x <= x) && (x < p_next->x)) ||
532 ((p->x > p_next->x) && (p_next->x < x) && (x <= p->x)))
533 {
534 line_y = ((double) (p->y - p_next->y) /
535 (double) (p->x - p_next->x)) *
536 (x - p_next->x) + p_next->y;
537 /* We crossed that edge if the line is directly above us */
538 if (line_y < y)
539 num_edges++;
540 }
541 }
542
543 /* Return true if num_edges is odd */
544 return ((num_edges % 2) == 1);
545}
546
547static int
548evas_object_polygon_was_inside(Evas_Object *obj __UNUSED__, Evas_Coord x __UNUSED__, Evas_Coord y __UNUSED__)
549{
550 /* this returns 1 if the canvas co-ordinates were inside the object based */
551 /* on object private data. not much use for rects, but for polys, images */
552 /* and other complex objects it might be */
553 return 1;
554}
diff --git a/libraries/evas/src/lib/canvas/evas_object_rectangle.c b/libraries/evas/src/lib/canvas/evas_object_rectangle.c
deleted file mode 100644
index 36678e7..0000000
--- a/libraries/evas/src/lib/canvas/evas_object_rectangle.c
+++ /dev/null
@@ -1,387 +0,0 @@
1#include "evas_common.h"
2#include "evas_private.h"
3
4/* private magic number for rectangle objects */
5static const char o_type[] = "rectangle";
6
7const char *o_rect_type = o_type;
8
9/* private struct for rectangle object internal data */
10typedef struct _Evas_Object_Rectangle Evas_Object_Rectangle;
11
12struct _Evas_Object_Rectangle
13{
14 DATA32 magic;
15 void *engine_data;
16};
17
18/* private methods for rectangle objects */
19static void evas_object_rectangle_init(Evas_Object *obj);
20static void *evas_object_rectangle_new(void);
21static void evas_object_rectangle_render(Evas_Object *obj, void *output, void *context, void *surface, int x, int y);
22static void evas_object_rectangle_free(Evas_Object *obj);
23static void evas_object_rectangle_render_pre(Evas_Object *obj);
24static void evas_object_rectangle_render_post(Evas_Object *obj);
25
26static unsigned int evas_object_rectangle_id_get(Evas_Object *obj);
27static unsigned int evas_object_rectangle_visual_id_get(Evas_Object *obj);
28static void *evas_object_rectangle_engine_data_get(Evas_Object *obj);
29
30static int evas_object_rectangle_is_opaque(Evas_Object *obj);
31static int evas_object_rectangle_was_opaque(Evas_Object *obj);
32
33#if 0 /* usless calls for a rect object. much more useful for images etc. */
34static void evas_object_rectangle_store(Evas_Object *obj);
35static void evas_object_rectangle_unstore(Evas_Object *obj);
36static int evas_object_rectangle_is_visible(Evas_Object *obj);
37static int evas_object_rectangle_was_visible(Evas_Object *obj);
38static int evas_object_rectangle_is_inside(Evas_Object *obj, double x, double y);
39static int evas_object_rectangle_was_inside(Evas_Object *obj, double x, double y);
40#endif
41
42static const Evas_Object_Func object_func =
43{
44 /* methods (compulsory) */
45 evas_object_rectangle_free,
46 evas_object_rectangle_render,
47 evas_object_rectangle_render_pre,
48 evas_object_rectangle_render_post,
49 evas_object_rectangle_id_get,
50 evas_object_rectangle_visual_id_get,
51 evas_object_rectangle_engine_data_get,
52 /* these are optional. NULL = nothing */
53 NULL,
54 NULL,
55 NULL,
56 NULL,
57 evas_object_rectangle_is_opaque,
58 evas_object_rectangle_was_opaque,
59 NULL,
60 NULL,
61 NULL,
62 NULL,
63 NULL,
64 NULL,
65 NULL
66};
67
68/* the actual api call to add a rect */
69/* it has no other api calls as all properties are standard */
70
71EVAS_MEMPOOL(_mp_obj);
72
73EAPI Evas_Object *
74evas_object_rectangle_add(Evas *e)
75{
76 Evas_Object *obj;
77
78 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
79 return NULL;
80 MAGIC_CHECK_END();
81 obj = evas_object_new(e);
82 evas_object_rectangle_init(obj);
83 evas_object_inject(obj, e);
84 return obj;
85}
86
87/* all nice and private */
88static void
89evas_object_rectangle_init(Evas_Object *obj)
90{
91 /* alloc image ob, setup methods and default values */
92 obj->object_data = evas_object_rectangle_new();
93 /* set up default settings for this kind of object */
94 obj->cur.color.r = 255;
95 obj->cur.color.g = 255;
96 obj->cur.color.b = 255;
97 obj->cur.color.a = 255;
98 obj->cur.geometry.x = 0;
99 obj->cur.geometry.y = 0;
100 obj->cur.geometry.w = 0;
101 obj->cur.geometry.h = 0;
102 obj->cur.layer = 0;
103 obj->cur.render_op = EVAS_RENDER_BLEND;
104 /* set up object-specific settings */
105 obj->prev = obj->cur;
106 /* set up methods (compulsory) */
107 obj->func = &object_func;
108 obj->type = o_type;
109}
110
111static void *
112evas_object_rectangle_new(void)
113{
114 Evas_Object_Rectangle *o;
115
116 /* alloc obj private data */
117 EVAS_MEMPOOL_INIT(_mp_obj, "evas_object_rectangle", Evas_Object_Rectangle, 256, NULL);
118 o = EVAS_MEMPOOL_ALLOC(_mp_obj, Evas_Object_Rectangle);
119 if (!o) return NULL;
120 EVAS_MEMPOOL_PREP(_mp_obj, o, Evas_Object_Rectangle);
121 o->magic = MAGIC_OBJ_RECTANGLE;
122 return o;
123}
124
125static void
126evas_object_rectangle_free(Evas_Object *obj)
127{
128 Evas_Object_Rectangle *o;
129
130 /* frees private object data. very simple here */
131 o = (Evas_Object_Rectangle *)(obj->object_data);
132 MAGIC_CHECK(o, Evas_Object_Rectangle, MAGIC_OBJ_RECTANGLE);
133 return;
134 MAGIC_CHECK_END();
135 /* free obj */
136 o->magic = 0;
137 EVAS_MEMPOOL_FREE(_mp_obj, o);
138}
139
140static void
141evas_object_rectangle_render(Evas_Object *obj, void *output, void *context, void *surface, int x, int y)
142{
143 /* render object to surface with context, and offxet by x,y */
144 obj->layer->evas->engine.func->context_color_set(output,
145 context,
146 obj->cur.cache.clip.r,
147 obj->cur.cache.clip.g,
148 obj->cur.cache.clip.b,
149 obj->cur.cache.clip.a);
150 obj->layer->evas->engine.func->context_multiplier_unset(output,
151 context);
152 obj->layer->evas->engine.func->context_render_op_set(output, context,
153 obj->cur.render_op);
154 obj->layer->evas->engine.func->rectangle_draw(output,
155 context,
156 surface,
157 obj->cur.geometry.x + x,
158 obj->cur.geometry.y + y,
159 obj->cur.geometry.w,
160 obj->cur.geometry.h);
161//// obj->cur.cache.geometry.x + x,
162//// obj->cur.cache.geometry.y + y,
163//// obj->cur.cache.geometry.w,
164//// obj->cur.cache.geometry.h);
165}
166
167static void
168evas_object_rectangle_render_pre(Evas_Object *obj)
169{
170 int is_v, was_v;
171
172 /* dont pre-render the obj twice! */
173 if (obj->pre_render_done) return;
174 obj->pre_render_done = 1;
175 /* pre-render phase. this does anything an object needs to do just before */
176 /* rendering. this could mean loading the image data, retrieving it from */
177 /* elsewhere, decoding video etc. */
178 /* then when this is done the object needs to figure if it changed and */
179 /* if so what and where and add the appropriate redraw rectangles */
180 /* if someone is clipping this obj - go calculate the clipper */
181 if (obj->cur.clipper)
182 {
183 if (obj->cur.cache.clip.dirty)
184 evas_object_clip_recalc(obj->cur.clipper);
185 obj->cur.clipper->func->render_pre(obj->cur.clipper);
186 }
187 /* now figure what changed and add draw rects */
188 /* if it just became visible or invisible */
189 is_v = evas_object_is_visible(obj);
190 was_v = evas_object_was_visible(obj);
191 if (!(is_v | was_v)) goto done;
192 if (is_v != was_v)
193 {
194 evas_object_render_pre_visible_change(&obj->layer->evas->clip_changes, obj, is_v, was_v);
195 goto done;
196 }
197 if ((obj->cur.map != obj->prev.map) ||
198 (obj->cur.usemap != obj->prev.usemap))
199 {
200 evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes, obj);
201 goto done;
202 }
203 /* it's not visible - we accounted for it appearing or not so just abort */
204 if (!is_v) goto done;
205 /* clipper changed this is in addition to anything else for obj */
206 evas_object_render_pre_clipper_change(&obj->layer->evas->clip_changes, obj);
207 /* if we restacked (layer or just within a layer) and don't clip anyone */
208 if ((obj->restack) && (!obj->clip.clipees))
209 {
210 evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes, obj);
211 goto done;
212 }
213 /* if it changed render op */
214 if (obj->cur.render_op != obj->prev.render_op)
215 {
216 evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes, obj);
217 goto done;
218 }
219 /* if it changed color */
220 if ((obj->cur.color.r != obj->prev.color.r) ||
221 (obj->cur.color.g != obj->prev.color.g) ||
222 (obj->cur.color.b != obj->prev.color.b) ||
223 (obj->cur.color.a != obj->prev.color.a))
224 {
225 evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes, obj);
226 goto done;
227 }
228 /* if it changed geometry - and obviously not visibility or color */
229 /* calculate differences since we have a constant color fill */
230 /* we really only need to update the differences */
231 if ((obj->cur.geometry.x != obj->prev.geometry.x) ||
232 (obj->cur.geometry.y != obj->prev.geometry.y) ||
233 (obj->cur.geometry.w != obj->prev.geometry.w) ||
234 (obj->cur.geometry.h != obj->prev.geometry.h))
235 {
236 evas_rects_return_difference_rects(&obj->layer->evas->clip_changes,
237 obj->cur.geometry.x,
238 obj->cur.geometry.y,
239 obj->cur.geometry.w,
240 obj->cur.geometry.h,
241 obj->prev.geometry.x,
242 obj->prev.geometry.y,
243 obj->prev.geometry.w,
244 obj->prev.geometry.h);
245//// rl = evas_rects_return_difference_rects(obj->cur.cache.geometry.x,
246//// obj->cur.cache.geometry.y,
247//// obj->cur.cache.geometry.w,
248//// obj->cur.cache.geometry.h,
249//// obj->prev.cache.geometry.x,
250//// obj->prev.cache.geometry.y,
251//// obj->prev.cache.geometry.w,
252//// obj->prev.cache.geometry.h);
253 goto done;
254 }
255 /* it obviously didn't change - add a NO obscure - this "unupdates" this */
256 /* area so if there were updates for it they get wiped. don't do it if we */
257 /* arent fully opaque and we are visible */
258 /*
259 if (evas_object_is_visible(obj) &&
260 evas_object_is_opaque(obj) &&
261 (!obj->clip.clipees))
262 obj->layer->evas->engine.func->output_redraws_rect_del(obj->layer->evas->engine.data.output,
263 obj->cur.cache.clip.x,
264 obj->cur.cache.clip.y,
265 obj->cur.cache.clip.w,
266 obj->cur.cache.clip.h);
267 */
268 done:
269 evas_object_render_pre_effect_updates(&obj->layer->evas->clip_changes, obj, is_v, was_v);
270}
271
272static void
273evas_object_rectangle_render_post(Evas_Object *obj)
274{
275
276 /* this moves the current data to the previous state parts of the object */
277 /* in whatever way is safest for the object. also if we don't need object */
278 /* data anymore we can free it if the object deems this is a good idea */
279 /* remove those pesky changes */
280 evas_object_clip_changes_clean(obj);
281 /* move cur to prev safely for object data */
282 obj->prev = obj->cur;
283}
284
285static int
286evas_object_rectangle_is_opaque(Evas_Object *obj)
287{
288 /* this returns 1 if the internal object data implies that the object is */
289 /* currently fully opaque over the entire rectangle it occupies */
290 if ((obj->cur.map) && (obj->cur.usemap)) return 0;
291 if (obj->cur.render_op == EVAS_RENDER_COPY)
292 return 1;
293 if (obj->cur.render_op != EVAS_RENDER_BLEND)
294 return 0;
295 return 1;
296}
297
298static int
299evas_object_rectangle_was_opaque(Evas_Object *obj)
300{
301 /* this returns 1 if the internal object data implies that the object was */
302 /* previously fully opaque over the entire rectangle it occupies */
303 if (obj->prev.render_op == EVAS_RENDER_COPY)
304 return 1;
305 if (obj->prev.render_op != EVAS_RENDER_BLEND)
306 return 0;
307 return 1;
308}
309
310static unsigned int evas_object_rectangle_id_get(Evas_Object *obj)
311{
312 Evas_Object_Rectangle *o;
313
314 o = (Evas_Object_Rectangle *)(obj->object_data);
315 if (!o) return 0;
316 return MAGIC_OBJ_RECTANGLE;
317}
318
319static unsigned int evas_object_rectangle_visual_id_get(Evas_Object *obj)
320{
321 Evas_Object_Rectangle *o;
322
323 o = (Evas_Object_Rectangle *)(obj->object_data);
324 if (!o) return 0;
325 return MAGIC_OBJ_SHAPE;
326}
327
328static void *evas_object_rectangle_engine_data_get(Evas_Object *obj)
329{
330 Evas_Object_Rectangle *o;
331
332 o = (Evas_Object_Rectangle *)(obj->object_data);
333 if (!o) return NULL;
334 return o->engine_data;
335}
336
337
338#if 0 /* usless calls for a rect object. much more useful for images etc. */
339static void
340evas_object_rectangle_store(Evas_Object *obj)
341{
342 /* store... nothing for rectangle objects... it's a bit silly */
343 /* but for others that may have expensive caluclations to do to */
344 /* generate the object data, hint that they might want to be pre-calced */
345 /* once and stored */
346}
347
348static void
349evas_object_rectangle_unstore(Evas_Object *obj)
350{
351 /* store... nothing for rectangle objects... it's a bit silly */
352}
353
354static int
355evas_object_rectangle_is_visible(Evas_Object *obj)
356{
357 /* this returns 1 if the internal object data would imply that it is */
358 /* visible (ie drawing it draws something. this is not to do with events */
359 return 1;
360}
361
362static int
363evas_object_rectangle_was_visible(Evas_Object *obj)
364{
365 /* this returns 1 if the internal object data would imply that it was */
366 /* visible (ie drawing it draws something. this is not to do with events */
367 return 1;
368}
369
370static int
371evas_object_rectangle_is_inside(Evas_Object *obj, double x, double y)
372{
373 /* this returns 1 if the canvas co-ordinates are inside the object based */
374 /* on object private data. not much use for rects, but for polys, images */
375 /* and other complex objects it might be */
376 return 1;
377}
378
379static int
380evas_object_rectangle_was_inside(Evas_Object *obj, double x, double y)
381{
382 /* this returns 1 if the canvas co-ordinates were inside the object based */
383 /* on object private data. not much use for rects, but for polys, images */
384 /* and other complex objects it might be */
385 return 1;
386}
387#endif
diff --git a/libraries/evas/src/lib/canvas/evas_object_smart.c b/libraries/evas/src/lib/canvas/evas_object_smart.c
deleted file mode 100644
index 69d7f3b..0000000
--- a/libraries/evas/src/lib/canvas/evas_object_smart.c
+++ /dev/null
@@ -1,951 +0,0 @@
1#include "evas_common.h"
2#include "evas_private.h"
3
4typedef struct _Evas_Object_Smart Evas_Object_Smart;
5typedef struct _Evas_Smart_Callback Evas_Smart_Callback;
6
7struct _Evas_Object_Smart
8{
9 DATA32 magic;
10 void *engine_data;
11 void *data;
12 Eina_List *callbacks;
13 Eina_Inlist *contained;
14 Evas_Smart_Cb_Description_Array callbacks_descriptions;
15 int walking_list;
16 Eina_Bool deletions_waiting : 1;
17 Eina_Bool need_recalculate : 1;
18};
19
20struct _Evas_Smart_Callback
21{
22 const char *event;
23 Evas_Smart_Cb func;
24 void *func_data;
25 Evas_Callback_Priority priority;
26 char delete_me : 1;
27};
28
29/* private methods for smart objects */
30static void evas_object_smart_callbacks_clear(Evas_Object *obj);
31static void evas_object_smart_init(Evas_Object *obj);
32static void *evas_object_smart_new(void);
33static void evas_object_smart_render(Evas_Object *obj, void *output, void *context, void *surface, int x, int y);
34static void evas_object_smart_free(Evas_Object *obj);
35static void evas_object_smart_render_pre(Evas_Object *obj);
36static void evas_object_smart_render_post(Evas_Object *obj);
37
38static unsigned int evas_object_smart_id_get(Evas_Object *obj);
39static unsigned int evas_object_smart_visual_id_get(Evas_Object *obj);
40static void *evas_object_smart_engine_data_get(Evas_Object *obj);
41
42static const Evas_Object_Func object_func =
43{
44 /* methods (compulsory) */
45 evas_object_smart_free,
46 evas_object_smart_render,
47 evas_object_smart_render_pre,
48 evas_object_smart_render_post,
49 evas_object_smart_id_get,
50 evas_object_smart_visual_id_get,
51 evas_object_smart_engine_data_get,
52 /* these are optional. NULL = nothing */
53 NULL,
54 NULL,
55 NULL,
56 NULL,
57 NULL,
58 NULL,
59 NULL,
60 NULL,
61 NULL,
62 NULL,
63 NULL,
64 NULL,
65 NULL
66};
67
68EVAS_MEMPOOL(_mp_obj);
69EVAS_MEMPOOL(_mp_cb);
70
71/* public funcs */
72EAPI void
73evas_object_smart_data_set(Evas_Object *obj, void *data)
74{
75 Evas_Object_Smart *o;
76
77 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
78 return;
79 MAGIC_CHECK_END();
80 o = (Evas_Object_Smart *)(obj->object_data);
81 MAGIC_CHECK(o, Evas_Object_Smart, MAGIC_OBJ_SMART);
82 return;
83 MAGIC_CHECK_END();
84 o->data = data;
85}
86
87EAPI void *
88evas_object_smart_data_get(const Evas_Object *obj)
89{
90 Evas_Object_Smart *o;
91
92 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
93 return NULL;
94 MAGIC_CHECK_END();
95 o = (Evas_Object_Smart *)(obj->object_data);
96 if (!o) return NULL;
97 return o->data;
98}
99
100EAPI Evas_Smart *
101evas_object_smart_smart_get(const Evas_Object *obj)
102{
103 Evas_Object_Smart *o;
104
105 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
106 return NULL;
107 MAGIC_CHECK_END();
108 o = (Evas_Object_Smart *)(obj->object_data);
109 MAGIC_CHECK(o, Evas_Object_Smart, MAGIC_OBJ_SMART);
110 return NULL;
111 MAGIC_CHECK_END();
112 return obj->smart.smart;
113}
114
115EAPI void
116evas_object_smart_member_add(Evas_Object *obj, Evas_Object *smart_obj)
117{
118 Evas_Object_Smart *o;
119
120 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
121 return;
122 MAGIC_CHECK_END();
123 MAGIC_CHECK(smart_obj, Evas_Object, MAGIC_OBJ);
124 return;
125 MAGIC_CHECK_END();
126 o = (Evas_Object_Smart *)(smart_obj->object_data);
127 MAGIC_CHECK(o, Evas_Object_Smart, MAGIC_OBJ_SMART);
128 return;
129 MAGIC_CHECK_END();
130
131 if (obj->delete_me)
132 {
133 CRIT("Adding deleted object %p to smart obj %p", obj, smart_obj);
134 abort();
135 return;
136 }
137 if (smart_obj->delete_me)
138 {
139 CRIT("Adding object %p to deleted smart obj %p", obj, smart_obj);
140 abort();
141 return;
142 }
143 if (!smart_obj->layer)
144 {
145 CRIT("No evas surface associated with smart object (%p)", smart_obj);
146 abort();
147 return;
148 }
149 if ((obj->layer && smart_obj->layer) &&
150 (obj->layer->evas != smart_obj->layer->evas))
151 {
152 CRIT("Adding object %p from Evas (%p) from another Evas (%p)", obj, obj->layer->evas, smart_obj->layer->evas);
153 abort();
154 return;
155 }
156
157 if (obj->smart.parent == smart_obj) return;
158
159 if (obj->smart.parent) evas_object_smart_member_del(obj);
160
161 evas_object_release(obj, 1);
162 obj->layer = smart_obj->layer;
163 obj->cur.layer = obj->layer->layer;
164 obj->layer->usage++;
165 obj->smart.parent = smart_obj;
166 o->contained = eina_inlist_append(o->contained, EINA_INLIST_GET(obj));
167 evas_object_smart_member_cache_invalidate(obj, EINA_TRUE, EINA_TRUE);
168 obj->restack = 1;
169 evas_object_change(obj);
170 evas_object_mapped_clip_across_mark(obj);
171 if (smart_obj->smart.smart->smart_class->member_add)
172 smart_obj->smart.smart->smart_class->member_add(smart_obj, obj);
173}
174
175EAPI void
176evas_object_smart_member_del(Evas_Object *obj)
177{
178 Evas_Object_Smart *o;
179 Evas_Object *smart_obj;
180
181 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
182 return;
183 MAGIC_CHECK_END();
184
185 if (!obj->smart.parent) return;
186
187 smart_obj = obj->smart.parent;
188 if (smart_obj->smart.smart->smart_class->member_del)
189 smart_obj->smart.smart->smart_class->member_del(smart_obj, obj);
190
191 o = (Evas_Object_Smart *)(obj->smart.parent->object_data);
192 o->contained = eina_inlist_remove(o->contained, EINA_INLIST_GET(obj));
193 obj->smart.parent = NULL;
194 evas_object_smart_member_cache_invalidate(obj, EINA_TRUE, EINA_TRUE);
195 obj->layer->usage--;
196 obj->cur.layer = obj->layer->layer;
197 evas_object_inject(obj, obj->layer->evas);
198 obj->restack = 1;
199 evas_object_change(obj);
200 evas_object_mapped_clip_across_mark(obj);
201}
202
203EAPI Evas_Object *
204evas_object_smart_parent_get(const Evas_Object *obj)
205{
206 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
207 return NULL;
208 MAGIC_CHECK_END();
209
210 return obj->smart.parent;
211}
212
213EAPI Eina_Bool
214evas_object_smart_type_check(const Evas_Object *obj, const char *type)
215{
216 const Evas_Smart_Class *sc;
217
218 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
219 return EINA_FALSE;
220 MAGIC_CHECK_END();
221
222 if (!obj->smart.smart)
223 return EINA_FALSE;
224 sc = obj->smart.smart->smart_class;
225 while (sc)
226 {
227 if (!strcmp(sc->name, type))
228 return EINA_TRUE;
229 sc = sc->parent;
230 }
231
232 return EINA_FALSE;
233}
234
235EAPI Eina_Bool
236evas_object_smart_type_check_ptr(const Evas_Object *obj, const char *type)
237{
238 const Evas_Smart_Class *sc;
239
240 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
241 return EINA_FALSE;
242 MAGIC_CHECK_END();
243
244 if (!obj->smart.smart)
245 return EINA_FALSE;
246 sc = obj->smart.smart->smart_class;
247 while (sc)
248 {
249 if (sc->name == type)
250 return EINA_TRUE;
251 sc = sc->parent;
252 }
253
254 return EINA_FALSE;
255}
256
257EAPI Eina_List *
258evas_object_smart_members_get(const Evas_Object *obj)
259{
260 Evas_Object_Smart *o;
261 Eina_List *members;
262 Eina_Inlist *member;
263
264 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
265 return NULL;
266 MAGIC_CHECK_END();
267 o = (Evas_Object_Smart *)(obj->object_data);
268 MAGIC_CHECK(o, Evas_Object_Smart, MAGIC_OBJ_SMART);
269 return NULL;
270 MAGIC_CHECK_END();
271
272 members = NULL;
273 for (member = o->contained; member; member = member->next)
274 members = eina_list_append(members, member);
275
276 return members;
277}
278
279const Eina_Inlist *
280evas_object_smart_members_get_direct(const Evas_Object *obj)
281{
282 Evas_Object_Smart *o;
283
284 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
285 return NULL;
286 MAGIC_CHECK_END();
287 o = (Evas_Object_Smart *)(obj->object_data);
288 MAGIC_CHECK(o, Evas_Object_Smart, MAGIC_OBJ_SMART);
289 return NULL;
290 MAGIC_CHECK_END();
291 return o->contained;
292}
293
294void
295_evas_object_smart_members_all_del(Evas_Object *obj)
296{
297 Evas_Object_Smart *o = (Evas_Object_Smart *)(obj->object_data);
298 while (o->contained)
299 evas_object_del((Evas_Object *)(o->contained));
300}
301
302EAPI Evas_Object *
303evas_object_smart_add(Evas *e, Evas_Smart *s)
304{
305 Evas_Object *obj;
306
307 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
308 return NULL;
309 MAGIC_CHECK_END();
310 MAGIC_CHECK(s, Evas_Smart, MAGIC_SMART);
311 return NULL;
312 MAGIC_CHECK_END();
313
314 obj = evas_object_new(e);
315 if (!obj) return NULL;
316 obj->smart.smart = s;
317 obj->type = s->smart_class->name;
318 evas_object_smart_init(obj);
319 evas_object_inject(obj, e);
320
321 evas_object_smart_use(s);
322
323 if (s->smart_class->add) s->smart_class->add(obj);
324
325 return obj;
326}
327
328static int
329_callback_priority_cmp(const void *_a, const void *_b)
330{
331 const Evas_Smart_Callback *a, *b;
332 a = (const Evas_Smart_Callback *) _a;
333 b = (const Evas_Smart_Callback *) _b;
334 if (a->priority < b->priority)
335 return -1;
336 else
337 return 1;
338}
339
340EAPI void
341evas_object_smart_callback_add(Evas_Object *obj, const char *event, Evas_Smart_Cb func, const void *data)
342{
343 evas_object_smart_callback_priority_add(obj, event,
344 EVAS_CALLBACK_PRIORITY_DEFAULT, func, data);
345}
346
347EAPI void
348evas_object_smart_callback_priority_add(Evas_Object *obj, const char *event, Evas_Callback_Priority priority, Evas_Smart_Cb func, const void *data)
349{
350 Evas_Object_Smart *o;
351 Evas_Smart_Callback *cb;
352
353 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
354 return;
355 MAGIC_CHECK_END();
356 o = (Evas_Object_Smart *)(obj->object_data);
357 MAGIC_CHECK(o, Evas_Object_Smart, MAGIC_OBJ_SMART);
358 return;
359 MAGIC_CHECK_END();
360 if (!event) return;
361 if (!func) return;
362 EVAS_MEMPOOL_INIT(_mp_cb, "evas_smart_callback", Evas_Smart_Callback, 512, );
363 cb = EVAS_MEMPOOL_ALLOC(_mp_cb, Evas_Smart_Callback);
364 if (!cb) return;
365 EVAS_MEMPOOL_PREP(_mp_cb, cb, Evas_Smart_Callback);
366 cb->event = eina_stringshare_add(event);
367 cb->func = func;
368 cb->func_data = (void *)data;
369 cb->priority = priority;
370 o->callbacks = eina_list_sorted_insert(o->callbacks, _callback_priority_cmp,
371 cb);
372}
373
374EAPI void *
375evas_object_smart_callback_del(Evas_Object *obj, const char *event, Evas_Smart_Cb func)
376{
377 Evas_Object_Smart *o;
378 Eina_List *l;
379 Evas_Smart_Callback *cb;
380
381 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
382 return NULL;
383 MAGIC_CHECK_END();
384 o = (Evas_Object_Smart *)(obj->object_data);
385 MAGIC_CHECK(o, Evas_Object_Smart, MAGIC_OBJ_SMART);
386 return NULL;
387 MAGIC_CHECK_END();
388 if (!event) return NULL;
389 EINA_LIST_FOREACH(o->callbacks, l, cb)
390 {
391 if ((!strcmp(cb->event, event)) && (cb->func == func))
392 {
393 void *data;
394
395 data = cb->func_data;
396 cb->delete_me = 1;
397 o->deletions_waiting = 1;
398 evas_object_smart_callbacks_clear(obj);
399 return data;
400 }
401 }
402 return NULL;
403}
404
405EAPI void *
406evas_object_smart_callback_del_full(Evas_Object *obj, const char *event, Evas_Smart_Cb func, const void *data)
407{
408 Evas_Object_Smart *o;
409 Eina_List *l;
410 Evas_Smart_Callback *cb;
411
412 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
413 return NULL;
414 MAGIC_CHECK_END();
415 o = (Evas_Object_Smart *)(obj->object_data);
416 MAGIC_CHECK(o, Evas_Object_Smart, MAGIC_OBJ_SMART);
417 return NULL;
418 MAGIC_CHECK_END();
419 if (!event) return NULL;
420 EINA_LIST_FOREACH(o->callbacks, l, cb)
421 {
422 if ((!strcmp(cb->event, event)) && (cb->func == func) && (cb->func_data == data))
423 {
424 void *ret;
425
426 ret = cb->func_data;
427 cb->delete_me = 1;
428 o->deletions_waiting = 1;
429 evas_object_smart_callbacks_clear(obj);
430 return ret;
431 }
432 }
433 return NULL;
434}
435
436EAPI void
437evas_object_smart_callback_call(Evas_Object *obj, const char *event, void *event_info)
438{
439 Evas_Object_Smart *o;
440 Eina_List *l;
441 Evas_Smart_Callback *cb;
442 const char *strshare;
443
444 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
445 return;
446 MAGIC_CHECK_END();
447 o = (Evas_Object_Smart *)(obj->object_data);
448 MAGIC_CHECK(o, Evas_Object_Smart, MAGIC_OBJ_SMART);
449 return;
450 MAGIC_CHECK_END();
451 if (!event) return;
452 if (obj->delete_me) return;
453 o->walking_list++;
454 strshare = eina_stringshare_add(event);
455 EINA_LIST_FOREACH(o->callbacks, l, cb)
456 {
457 if (!cb->delete_me)
458 {
459 if (cb->event == strshare)
460 cb->func(cb->func_data, obj, event_info);
461 }
462 if (obj->delete_me)
463 break;
464 }
465 eina_stringshare_del(strshare);
466 o->walking_list--;
467 evas_object_smart_callbacks_clear(obj);
468}
469
470EAPI Eina_Bool
471evas_object_smart_callbacks_descriptions_set(Evas_Object *obj, const Evas_Smart_Cb_Description *descriptions)
472{
473 const Evas_Smart_Cb_Description *d;
474 Evas_Object_Smart *o;
475 unsigned int i, count = 0;
476
477 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
478 return EINA_FALSE;
479 MAGIC_CHECK_END();
480 o = (Evas_Object_Smart *)(obj->object_data);
481 MAGIC_CHECK(o, Evas_Object_Smart, MAGIC_OBJ_SMART);
482 return EINA_FALSE;
483 MAGIC_CHECK_END();
484
485 if ((!descriptions) || (!descriptions->name))
486 {
487 evas_smart_cb_descriptions_resize(&o->callbacks_descriptions, 0);
488 return EINA_TRUE;
489 }
490
491 for (count = 0, d = descriptions; d->name; d++)
492 count++;
493
494 evas_smart_cb_descriptions_resize(&o->callbacks_descriptions, count);
495 if (count == 0) return EINA_TRUE;
496
497 for (i = 0, d = descriptions; i < count; d++, i++)
498 o->callbacks_descriptions.array[i] = d;
499
500 evas_smart_cb_descriptions_fix(&o->callbacks_descriptions);
501
502 return EINA_TRUE;
503}
504
505EAPI void
506evas_object_smart_callbacks_descriptions_get(const Evas_Object *obj, const Evas_Smart_Cb_Description ***class_descriptions, unsigned int *class_count, const Evas_Smart_Cb_Description ***instance_descriptions, unsigned int *instance_count)
507{
508 Evas_Object_Smart *o;
509
510 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
511 if (class_descriptions) *class_descriptions = NULL;
512 if (class_count) *class_count = 0;
513 if (instance_descriptions) *instance_descriptions = NULL;
514 if (instance_count) *instance_count = 0;
515 return;
516 MAGIC_CHECK_END();
517 o = (Evas_Object_Smart *)(obj->object_data);
518 MAGIC_CHECK(o, Evas_Object_Smart, MAGIC_OBJ_SMART);
519 if (class_descriptions) *class_descriptions = NULL;
520 if (class_count) *class_count = 0;
521 if (instance_descriptions) *instance_descriptions = NULL;
522 if (instance_count) *instance_count = 0;
523 return;
524 MAGIC_CHECK_END();
525
526 if (class_descriptions)
527 *class_descriptions = obj->smart.smart->callbacks.array;
528 if (class_count)
529 *class_count = obj->smart.smart->callbacks.size;
530
531 if (instance_descriptions)
532 *instance_descriptions = o->callbacks_descriptions.array;
533 if (instance_count)
534 *instance_count = o->callbacks_descriptions.size;
535}
536
537EAPI void
538evas_object_smart_callback_description_find(const Evas_Object *obj, const char *name, const Evas_Smart_Cb_Description **class_description, const Evas_Smart_Cb_Description **instance_description)
539{
540 Evas_Object_Smart *o;
541
542 if (!name)
543 {
544 if (class_description) *class_description = NULL;
545 if (instance_description) *instance_description = NULL;
546 return;
547 }
548
549 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
550 if (class_description) *class_description = NULL;
551 if (instance_description) *instance_description = NULL;
552 return;
553 MAGIC_CHECK_END();
554 o = (Evas_Object_Smart *)(obj->object_data);
555 MAGIC_CHECK(o, Evas_Object_Smart, MAGIC_OBJ_SMART);
556 if (class_description) *class_description = NULL;
557 if (instance_description) *instance_description = NULL;
558 return;
559 MAGIC_CHECK_END();
560
561 if (class_description)
562 *class_description = evas_smart_cb_description_find
563 (&obj->smart.smart->callbacks, name);
564
565 if (instance_description)
566 *instance_description = evas_smart_cb_description_find
567 (&o->callbacks_descriptions, name);
568}
569
570EAPI void
571evas_object_smart_need_recalculate_set(Evas_Object *obj, Eina_Bool value)
572{
573 Evas_Object_Smart *o;
574 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
575 return;
576 MAGIC_CHECK_END();
577 o = obj->object_data;
578 MAGIC_CHECK(o, Evas_Object_Smart, MAGIC_OBJ_SMART);
579 return;
580 MAGIC_CHECK_END();
581
582 // XXX: do i need this?
583 if (obj->delete_me) return;
584
585 /* remove this entry from calc_list or processed list */
586 if (eina_clist_element_is_linked(&obj->calc_entry))
587 eina_clist_remove(&obj->calc_entry);
588
589 value = !!value;
590 if (value)
591 eina_clist_add_tail(&obj->layer->evas->calc_list, &obj->calc_entry);
592 else
593 eina_clist_add_tail(&obj->layer->evas->calc_done, &obj->calc_entry);
594
595 if (o->need_recalculate == value) return;
596
597 if (obj->recalculate_cycle > 254)
598 {
599 ERR("Object %p is not stable during recalc loop", obj);
600 return;
601 }
602 if (obj->layer->evas->in_smart_calc) obj->recalculate_cycle++;
603 o->need_recalculate = value;
604}
605
606EAPI Eina_Bool
607evas_object_smart_need_recalculate_get(const Evas_Object *obj)
608{
609 Evas_Object_Smart *o;
610 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
611 return EINA_FALSE;
612 MAGIC_CHECK_END();
613 o = obj->object_data;
614 MAGIC_CHECK(o, Evas_Object_Smart, MAGIC_OBJ_SMART);
615 return EINA_FALSE;
616 MAGIC_CHECK_END();
617
618 return o->need_recalculate;
619}
620
621EAPI void
622evas_object_smart_calculate(Evas_Object *obj)
623{
624 Evas_Object_Smart *o;
625 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
626 return;
627 MAGIC_CHECK_END();
628 o = obj->object_data;
629 MAGIC_CHECK(o, Evas_Object_Smart, MAGIC_OBJ_SMART);
630 return;
631 MAGIC_CHECK_END();
632
633 if (!obj->smart.smart->smart_class->calculate)
634 return;
635
636 o->need_recalculate = 0;
637 obj->smart.smart->smart_class->calculate(obj);
638}
639
640EAPI void
641evas_smart_objects_calculate(Evas *e)
642{
643 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
644 return;
645 MAGIC_CHECK_END();
646 evas_call_smarts_calculate(e);
647}
648
649EAPI int
650evas_smart_objects_calculate_count_get(const Evas *e)
651{
652 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
653 return 0;
654 MAGIC_CHECK_END();
655 return e->smart_calc_count;
656}
657
658/**
659 * Call calculate() on all smart objects that need_recalculate.
660 *
661 * @internal
662 */
663void
664evas_call_smarts_calculate(Evas *e)
665{
666 Eina_Clist *elem;
667 Evas_Object *obj;
668
669// printf("+CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALC-----------v\n");
670 evas_event_freeze(e);
671 e->in_smart_calc++;
672
673 while (NULL != (elem = eina_clist_head(&e->calc_list)))
674 {
675 Evas_Object_Smart *o;
676
677 /* move the item to the processed list */
678 obj = EINA_CLIST_ENTRY(elem, Evas_Object, calc_entry);
679 eina_clist_remove(&obj->calc_entry);
680 if (obj->delete_me) continue;
681 eina_clist_add_tail(&e->calc_done, &obj->calc_entry);
682
683 o = obj->object_data;
684
685 if (o->need_recalculate)
686 {
687 o->need_recalculate = 0;
688 obj->smart.smart->smart_class->calculate(obj);
689 }
690 }
691
692 while (NULL != (elem = eina_clist_head(&e->calc_done)))
693 {
694 obj = EINA_CLIST_ENTRY(elem, Evas_Object, calc_entry);
695 obj->recalculate_cycle = 0;
696 eina_clist_remove(&obj->calc_entry);
697 }
698
699 e->in_smart_calc--;
700 if (e->in_smart_calc == 0) e->smart_calc_count++;
701 evas_event_thaw(e);
702 evas_event_thaw_eval(e);
703}
704
705EAPI void
706evas_object_smart_changed(Evas_Object *obj)
707{
708 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
709 return;
710 MAGIC_CHECK_END();
711 evas_object_change(obj);
712 evas_object_smart_need_recalculate_set(obj, 1);
713}
714
715/* internal calls */
716static void
717evas_object_smart_callbacks_clear(Evas_Object *obj)
718{
719 Evas_Object_Smart *o;
720 Eina_List *l;
721 Evas_Smart_Callback *cb;
722
723 o = (Evas_Object_Smart *)(obj->object_data);
724
725 if (o->walking_list) return;
726 if (!o->deletions_waiting) return;
727 for (l = o->callbacks; l;)
728 {
729 cb = eina_list_data_get(l);
730 l = eina_list_next(l);
731 if (cb->delete_me)
732 {
733 o->callbacks = eina_list_remove(o->callbacks, cb);
734 if (cb->event) eina_stringshare_del(cb->event);
735 EVAS_MEMPOOL_FREE(_mp_cb, cb);
736 }
737 }
738}
739
740void
741evas_object_smart_del(Evas_Object *obj)
742{
743 Evas_Smart *s;
744
745 if (obj->delete_me) return;
746 s = obj->smart.smart;
747 if ((s) && (s->smart_class->del)) s->smart_class->del(obj);
748 if (obj->smart.parent) evas_object_smart_member_del(obj);
749 if (s) evas_object_smart_unuse(s);
750}
751
752void
753evas_object_smart_cleanup(Evas_Object *obj)
754{
755 Evas_Object_Smart *o;
756
757 if (obj->smart.parent)
758 evas_object_smart_member_del(obj);
759
760 o = (Evas_Object_Smart *)(obj->object_data);
761 if (o->magic == MAGIC_OBJ_SMART)
762 {
763 if (obj->calc_entry.next)
764 eina_clist_remove(&obj->calc_entry);
765
766 while (o->contained)
767 evas_object_smart_member_del((Evas_Object *)o->contained);
768
769 while (o->callbacks)
770 {
771 Evas_Smart_Callback *cb = o->callbacks->data;
772 o->callbacks = eina_list_remove(o->callbacks, cb);
773 if (cb->event) eina_stringshare_del(cb->event);
774 EVAS_MEMPOOL_FREE(_mp_cb, cb);
775 }
776
777 evas_smart_cb_descriptions_resize(&o->callbacks_descriptions, 0);
778 o->data = NULL;
779 }
780
781 obj->smart.parent = NULL;
782 obj->smart.smart = NULL;
783}
784
785void
786evas_object_smart_member_cache_invalidate(Evas_Object *obj,
787 Eina_Bool pass_events,
788 Eina_Bool freeze_events)
789{
790 Evas_Object_Smart *o;
791 Evas_Object *member;
792
793 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
794 return;
795 MAGIC_CHECK_END();
796
797 if (pass_events)
798 obj->parent_cache.pass_events_valid = EINA_FALSE;
799 if (freeze_events)
800 obj->parent_cache.freeze_events_valid = EINA_FALSE;
801
802 o = obj->object_data;
803 if (o->magic != MAGIC_OBJ_SMART) return;
804
805 EINA_INLIST_FOREACH(o->contained, member)
806 evas_object_smart_member_cache_invalidate(member,
807 pass_events,
808 freeze_events);
809}
810
811void
812evas_object_smart_member_raise(Evas_Object *member)
813{
814 Evas_Object_Smart *o;
815
816 o = (Evas_Object_Smart *)(member->smart.parent->object_data);
817 o->contained = eina_inlist_demote(o->contained, EINA_INLIST_GET(member));
818}
819
820void
821evas_object_smart_member_lower(Evas_Object *member)
822{
823 Evas_Object_Smart *o;
824
825 o = (Evas_Object_Smart *)(member->smart.parent->object_data);
826 o->contained = eina_inlist_promote(o->contained, EINA_INLIST_GET(member));
827}
828
829void
830evas_object_smart_member_stack_above(Evas_Object *member, Evas_Object *other)
831{
832 Evas_Object_Smart *o;
833
834 o = (Evas_Object_Smart *)(member->smart.parent->object_data);
835 o->contained = eina_inlist_remove(o->contained, EINA_INLIST_GET(member));
836 o->contained = eina_inlist_append_relative(o->contained, EINA_INLIST_GET(member), EINA_INLIST_GET(other));
837}
838
839void
840evas_object_smart_member_stack_below(Evas_Object *member, Evas_Object *other)
841{
842 Evas_Object_Smart *o;
843
844 o = (Evas_Object_Smart *)(member->smart.parent->object_data);
845 o->contained = eina_inlist_remove(o->contained, EINA_INLIST_GET(member));
846 o->contained = eina_inlist_prepend_relative(o->contained, EINA_INLIST_GET(member), EINA_INLIST_GET(other));
847}
848
849/* all nice and private */
850static void
851evas_object_smart_init(Evas_Object *obj)
852{
853 /* alloc smart obj, setup methods and default values */
854 obj->object_data = evas_object_smart_new();
855 /* set up default settings for this kind of object */
856 obj->cur.color.r = 255;
857 obj->cur.color.g = 255;
858 obj->cur.color.b = 255;
859 obj->cur.color.a = 255;
860 obj->cur.geometry.x = 0;
861 obj->cur.geometry.y = 0;
862 obj->cur.geometry.w = 0;
863 obj->cur.geometry.h = 0;
864 obj->cur.layer = 0;
865 /* set up object-specific settings */
866 obj->prev = obj->cur;
867 /* set up methods (compulsory) */
868 obj->func = &object_func;
869}
870
871static void *
872evas_object_smart_new(void)
873{
874 Evas_Object_Smart *o;
875
876 /* alloc obj private data */
877 EVAS_MEMPOOL_INIT(_mp_obj, "evas_object_smart", Evas_Object_Smart, 256, NULL);
878 o = EVAS_MEMPOOL_ALLOC(_mp_obj, Evas_Object_Smart);
879 if (!o) return NULL;
880 EVAS_MEMPOOL_PREP(_mp_obj, o, Evas_Object_Smart);
881 o->magic = MAGIC_OBJ_SMART;
882 return o;
883}
884
885static void
886evas_object_smart_free(Evas_Object *obj)
887{
888 Evas_Object_Smart *o;
889
890 /* frees private object data. very simple here */
891 o = (Evas_Object_Smart *)(obj->object_data);
892 MAGIC_CHECK(o, Evas_Object_Smart, MAGIC_OBJ_SMART);
893 return;
894 MAGIC_CHECK_END();
895 /* free obj */
896 o->magic = 0;
897 EVAS_MEMPOOL_FREE(_mp_obj, o);
898}
899
900static void
901evas_object_smart_render(Evas_Object *obj __UNUSED__, void *output __UNUSED__, void *context __UNUSED__, void *surface __UNUSED__, int x __UNUSED__, int y __UNUSED__)
902{
903 return;
904}
905
906static void
907evas_object_smart_render_pre(Evas_Object *obj)
908{
909 if (obj->pre_render_done) return;
910 if ((obj->cur.map != obj->prev.map) ||
911 (obj->cur.usemap != obj->prev.usemap))
912 {
913 evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes, obj);
914 goto done;
915 }
916done:
917 obj->pre_render_done = 1;
918}
919
920static void
921evas_object_smart_render_post(Evas_Object *obj)
922{
923 obj->prev = obj->cur;
924}
925
926static unsigned int evas_object_smart_id_get(Evas_Object *obj)
927{
928 Evas_Object_Smart *o;
929
930 o = (Evas_Object_Smart *)(obj->object_data);
931 if (!o) return 0;
932 return MAGIC_OBJ_SMART;
933}
934
935static unsigned int evas_object_smart_visual_id_get(Evas_Object *obj)
936{
937 Evas_Object_Smart *o;
938
939 o = (Evas_Object_Smart *)(obj->object_data);
940 if (!o) return 0;
941 return MAGIC_OBJ_CONTAINER;
942}
943
944static void *evas_object_smart_engine_data_get(Evas_Object *obj)
945{
946 Evas_Object_Smart *o;
947
948 o = (Evas_Object_Smart *)(obj->object_data);
949 if (!o) return NULL;
950 return o->engine_data;
951}
diff --git a/libraries/evas/src/lib/canvas/evas_object_smart_clipped.c b/libraries/evas/src/lib/canvas/evas_object_smart_clipped.c
deleted file mode 100644
index 9b9fa6d..0000000
--- a/libraries/evas/src/lib/canvas/evas_object_smart_clipped.c
+++ /dev/null
@@ -1,183 +0,0 @@
1#include "evas_common.h"
2#include "evas_private.h"
3
4#define CSO_DATA_GET_OR_RETURN(obj, ptr) \
5 Evas_Object_Smart_Clipped_Data *ptr = evas_object_smart_data_get(obj); \
6 if (!ptr) return;
7
8EAPI void
9evas_object_smart_move_children_relative(Evas_Object *obj, Evas_Coord dx, Evas_Coord dy)
10{
11 const Eina_Inlist *lst;
12 Evas_Object *child;
13
14 if ((dx == 0) && (dy == 0))
15 return;
16
17 lst = evas_object_smart_members_get_direct(obj);
18 EINA_INLIST_FOREACH(lst, child)
19 {
20 Evas_Coord orig_x, orig_y;
21
22// shortcut as we are in evas
23// evas_object_geometry_get(child, &orig_x, &orig_y, NULL, NULL);
24 if (child->delete_me) continue;
25 if (child->is_static_clip) continue;
26 orig_x = child->cur.geometry.x;
27 orig_y = child->cur.geometry.y;
28 evas_object_move(child, orig_x + dx, orig_y + dy);
29 }
30}
31
32EAPI Evas_Object *
33evas_object_smart_clipped_clipper_get(Evas_Object *obj)
34{
35 Evas_Object_Smart_Clipped_Data *cso = evas_object_smart_data_get(obj);
36 if (!cso)
37 return NULL;
38
39 return cso->clipper;
40}
41
42static void
43evas_object_smart_clipped_smart_add(Evas_Object *obj)
44{
45 Evas_Object_Smart_Clipped_Data *cso;
46 Evas_Object *clipper;
47
48 cso = evas_object_smart_data_get(obj);
49 if (!cso)
50 cso = calloc(1, sizeof(*cso)); /* users can provide it or realloc() later */
51
52 cso->evas = evas_object_evas_get(obj);
53 clipper = evas_object_rectangle_add(cso->evas);
54 evas_object_static_clip_set(clipper, 1);
55 cso->clipper = NULL;
56 evas_object_smart_member_add(clipper, obj);
57 cso->clipper = clipper;
58 evas_object_color_set(cso->clipper, 255, 255, 255, 255);
59 evas_object_move(cso->clipper, -100000, -100000);
60 evas_object_resize(cso->clipper, 200000, 200000);
61 evas_object_pass_events_set(cso->clipper, 1);
62 evas_object_hide(cso->clipper); /* show when have something clipped to it */
63
64 evas_object_smart_data_set(obj, cso);
65}
66
67static void
68evas_object_smart_clipped_smart_del(Evas_Object *obj)
69{
70 CSO_DATA_GET_OR_RETURN(obj, cso);
71
72 if (cso->clipper)
73 {
74 Evas_Object *clipper = cso->clipper;
75 cso->clipper = NULL;
76 evas_object_del(clipper);
77 }
78
79 _evas_object_smart_members_all_del(obj);
80
81 free(cso);
82 evas_object_smart_data_set(obj, NULL);
83}
84
85static void
86evas_object_smart_clipped_smart_move(Evas_Object *obj, Evas_Coord x, Evas_Coord y)
87{
88 Evas_Coord orig_x, orig_y;
89
90 evas_object_geometry_get(obj, &orig_x, &orig_y, NULL, NULL);
91 evas_object_smart_move_children_relative(obj, x - orig_x, y - orig_y);
92}
93
94static void
95evas_object_smart_clipped_smart_show(Evas_Object *obj)
96{
97 CSO_DATA_GET_OR_RETURN(obj, cso);
98 if (evas_object_clipees_get(cso->clipper))
99 evas_object_show(cso->clipper); /* just show if clipper being used */
100}
101
102static void
103evas_object_smart_clipped_smart_hide(Evas_Object *obj)
104{
105 CSO_DATA_GET_OR_RETURN(obj, cso);
106 evas_object_hide(cso->clipper);
107}
108
109static void
110evas_object_smart_clipped_smart_color_set(Evas_Object *obj, int r, int g, int b, int a)
111{
112 CSO_DATA_GET_OR_RETURN(obj, cso);
113 evas_object_color_set(cso->clipper, r, g, b, a);
114}
115
116static void
117evas_object_smart_clipped_smart_clip_set(Evas_Object *obj, Evas_Object *clip)
118{
119 CSO_DATA_GET_OR_RETURN(obj, cso);
120 evas_object_clip_set(cso->clipper, clip);
121}
122
123static void
124evas_object_smart_clipped_smart_clip_unset(Evas_Object *obj)
125{
126 CSO_DATA_GET_OR_RETURN(obj, cso);
127 evas_object_clip_unset(cso->clipper);
128}
129
130static void
131evas_object_smart_clipped_smart_member_add(Evas_Object *obj, Evas_Object *member)
132{
133 CSO_DATA_GET_OR_RETURN(obj, cso);
134 if (!cso->clipper)
135 return;
136 evas_object_clip_set(member, cso->clipper);
137 if (evas_object_visible_get(obj))
138 evas_object_show(cso->clipper);
139}
140
141static void
142evas_object_smart_clipped_smart_member_del(Evas_Object *obj, Evas_Object *member)
143{
144 CSO_DATA_GET_OR_RETURN(obj, cso);
145 if (!cso->clipper)
146 return;
147 evas_object_clip_unset(member);
148 if (!evas_object_clipees_get(cso->clipper))
149 evas_object_hide(cso->clipper);
150}
151
152EAPI void
153evas_object_smart_clipped_smart_set(Evas_Smart_Class *sc)
154{
155 if (!sc)
156 return;
157
158 sc->add = evas_object_smart_clipped_smart_add;
159 sc->del = evas_object_smart_clipped_smart_del;
160 sc->move = evas_object_smart_clipped_smart_move;
161 sc->show = evas_object_smart_clipped_smart_show;
162 sc->hide = evas_object_smart_clipped_smart_hide;
163 sc->color_set = evas_object_smart_clipped_smart_color_set;
164 sc->clip_set = evas_object_smart_clipped_smart_clip_set;
165 sc->clip_unset = evas_object_smart_clipped_smart_clip_unset;
166 sc->calculate = NULL;
167 sc->member_add = evas_object_smart_clipped_smart_member_add;
168 sc->member_del = evas_object_smart_clipped_smart_member_del;
169}
170
171EAPI const Evas_Smart_Class *
172evas_object_smart_clipped_class_get(void)
173{
174 static Evas_Smart_Class _sc = EVAS_SMART_CLASS_INIT_NAME_VERSION("EvasObjectSmartClipped");
175 static const Evas_Smart_Class *class = NULL;
176
177 if (class)
178 return class;
179
180 evas_object_smart_clipped_smart_set(&_sc);
181 class = &_sc;
182 return class;
183}
diff --git a/libraries/evas/src/lib/canvas/evas_object_table.c b/libraries/evas/src/lib/canvas/evas_object_table.c
deleted file mode 100644
index cdfa07f..0000000
--- a/libraries/evas/src/lib/canvas/evas_object_table.c
+++ /dev/null
@@ -1,1373 +0,0 @@
1#include "evas_common.h"
2#include <errno.h>
3
4typedef struct _Evas_Object_Table_Data Evas_Object_Table_Data;
5typedef struct _Evas_Object_Table_Option Evas_Object_Table_Option;
6typedef struct _Evas_Object_Table_Cache Evas_Object_Table_Cache;
7typedef struct _Evas_Object_Table_Iterator Evas_Object_Table_Iterator;
8typedef struct _Evas_Object_Table_Accessor Evas_Object_Table_Accessor;
9
10struct _Evas_Object_Table_Option
11{
12 Evas_Object *obj;
13 unsigned short col, row, colspan, rowspan, end_col, end_row;
14 struct {
15 Evas_Coord w, h;
16 } min, max;
17 struct {
18 double h, v;
19 } align;
20 struct {
21 Evas_Coord l, r, t, b;
22 } pad;
23 Eina_Bool expand_h : 1; /* XXX required? */
24 Eina_Bool expand_v : 1; /* XXX required? */
25 Eina_Bool fill_h : 1;
26 Eina_Bool fill_v : 1;
27};
28
29struct _Evas_Object_Table_Cache
30{
31 struct {
32 struct {
33 double h, v;
34 } weights;
35 struct {
36 int h, v;
37 } expands;
38 struct {
39 Evas_Coord w, h;
40 } min;
41 } total;
42 struct {
43 double *h, *v;
44 } weights;
45 struct {
46 Evas_Coord *h, *v;
47 } sizes;
48 struct {
49 Eina_Bool *h, *v;
50 } expands;
51 double ___pad; // padding to make sure doubles at end can be aligned
52};
53
54struct _Evas_Object_Table_Data
55{
56 Evas_Object_Smart_Clipped_Data base;
57 Eina_List *children;
58 struct {
59 Evas_Coord h, v;
60 } pad;
61 struct {
62 double h, v;
63 } align;
64 struct {
65 int cols, rows;
66 } size;
67 Evas_Object_Table_Cache *cache;
68 Evas_Object_Table_Homogeneous_Mode homogeneous;
69 Eina_Bool hints_changed : 1;
70 Eina_Bool expand_h : 1;
71 Eina_Bool expand_v : 1;
72 Eina_Bool is_mirrored : 1;
73};
74
75struct _Evas_Object_Table_Iterator
76{
77 Eina_Iterator iterator;
78
79 Eina_Iterator *real_iterator;
80 const Evas_Object *table;
81};
82
83struct _Evas_Object_Table_Accessor
84{
85 Eina_Accessor accessor;
86
87 Eina_Accessor *real_accessor;
88 const Evas_Object *table;
89};
90
91#define EVAS_OBJECT_TABLE_DATA_GET(o, ptr) \
92 Evas_Object_Table_Data *ptr = evas_object_smart_data_get(o)
93
94#define EVAS_OBJECT_TABLE_DATA_GET_OR_RETURN(o, ptr) \
95 EVAS_OBJECT_TABLE_DATA_GET(o, ptr); \
96 if (!ptr) \
97 { \
98 CRIT("no widget data for object %p (%s)", \
99 o, evas_object_type_get(o)); \
100 abort(); \
101 return; \
102}
103
104#define EVAS_OBJECT_TABLE_DATA_GET_OR_RETURN_VAL(o, ptr, val) \
105 EVAS_OBJECT_TABLE_DATA_GET(o, ptr); \
106 if (!ptr) \
107 { \
108 CRIT("No widget data for object %p (%s)", \
109 o, evas_object_type_get(o)); \
110 abort(); \
111 return val; \
112 }
113
114static const char EVAS_OBJECT_TABLE_OPTION_KEY[] = "|EvTb";
115
116static Eina_Bool
117_evas_object_table_iterator_next(Evas_Object_Table_Iterator *it, void **data)
118{
119 Evas_Object_Table_Option *opt;
120
121 if (!eina_iterator_next(it->real_iterator, (void **)&opt))
122 return EINA_FALSE;
123 if (data) *data = opt->obj;
124 return EINA_TRUE;
125}
126
127static Evas_Object *
128_evas_object_table_iterator_get_container(Evas_Object_Table_Iterator *it)
129{
130 return (Evas_Object *)it->table;
131}
132
133static void
134_evas_object_table_iterator_free(Evas_Object_Table_Iterator *it)
135{
136 eina_iterator_free(it->real_iterator);
137 free(it);
138}
139
140static Eina_Bool
141_evas_object_table_accessor_get_at(Evas_Object_Table_Accessor *it, unsigned int idx, void **data)
142{
143 Evas_Object_Table_Option *opt = NULL;
144
145 if (!eina_accessor_data_get(it->real_accessor, idx, (void **)&opt))
146 return EINA_FALSE;
147 if (data) *data = opt->obj;
148 return EINA_TRUE;
149}
150
151static Evas_Object *
152_evas_object_table_accessor_get_container(Evas_Object_Table_Accessor *it)
153{
154 return (Evas_Object *)it->table;
155}
156
157static void
158_evas_object_table_accessor_free(Evas_Object_Table_Accessor *it)
159{
160 eina_accessor_free(it->real_accessor);
161 free(it);
162}
163
164static Evas_Object_Table_Cache *
165_evas_object_table_cache_alloc(int cols, int rows)
166{
167 Evas_Object_Table_Cache *cache;
168 int size;
169
170 size = sizeof(Evas_Object_Table_Cache) +
171 ((cols + rows) *
172 (sizeof(double) + sizeof(Evas_Coord) + sizeof(Eina_Bool)));
173 cache = malloc(size);
174 if (!cache)
175 {
176 ERR("Could not allocate table cache %dx%d (%d bytes): %s",
177 cols, rows, size, strerror(errno));
178 return NULL;
179 }
180
181 cache->weights.h = (double *)(cache + 1);
182 cache->weights.v = (double *)(cache->weights.h + cols);
183 cache->sizes.h = (Evas_Coord *)(cache->weights.v + rows);
184 cache->sizes.v = (Evas_Coord *)(cache->sizes.h + cols);
185 cache->expands.h = (Eina_Bool *)(cache->sizes.v + rows);
186 cache->expands.v = (Eina_Bool *)(cache->expands.h + cols);
187
188 return cache;
189}
190
191static void
192_evas_object_table_cache_free(Evas_Object_Table_Cache *cache)
193{
194 free(cache);
195}
196
197static void
198_evas_object_table_cache_reset(Evas_Object_Table_Data *priv)
199{
200 Evas_Object_Table_Cache *c = priv->cache;
201 int size;
202
203 c->total.expands.v = 0;
204 c->total.expands.h = 0;
205 c->total.min.w = 0;
206 c->total.min.h = 0;
207
208 size = ((priv->size.rows + priv->size.cols) *
209 (sizeof(double) + sizeof(Evas_Coord) + sizeof(Eina_Bool)));
210 memset(c + 1, 0, size);
211}
212
213static void
214_evas_object_table_cache_invalidate(Evas_Object_Table_Data *priv)
215{
216 priv->hints_changed = 1;
217 if (priv->cache)
218 {
219 _evas_object_table_cache_free(priv->cache);
220 priv->cache = NULL;
221 }
222}
223
224static Evas_Object_Table_Option *
225_evas_object_table_option_get(Evas_Object *o)
226{
227 return evas_object_data_get(o, EVAS_OBJECT_TABLE_OPTION_KEY);
228}
229
230static void
231_evas_object_table_option_set(Evas_Object *o, const Evas_Object_Table_Option *opt)
232{
233 evas_object_data_set(o, EVAS_OBJECT_TABLE_OPTION_KEY, opt);
234}
235
236static Evas_Object_Table_Option *
237_evas_object_table_option_del(Evas_Object *o)
238{
239 return evas_object_data_del(o, EVAS_OBJECT_TABLE_OPTION_KEY);
240}
241
242static void
243_on_child_del(void *data, Evas *evas __UNUSED__, Evas_Object *child, void *einfo __UNUSED__)
244{
245 Evas_Object *table = data;
246 evas_object_table_unpack(table, child);
247}
248
249static void
250_on_child_hints_changed(void *data, Evas *evas __UNUSED__, Evas_Object *child __UNUSED__, void *einfo __UNUSED__)
251{
252 Evas_Object *table = data;
253 EVAS_OBJECT_TABLE_DATA_GET_OR_RETURN(table, priv);
254 _evas_object_table_cache_invalidate(priv);
255 evas_object_smart_changed(table);
256}
257
258static void
259_evas_object_table_child_connect(Evas_Object *o, Evas_Object *child)
260{
261 evas_object_event_callback_add
262 (child, EVAS_CALLBACK_DEL, _on_child_del, o);
263 evas_object_event_callback_add
264 (child, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _on_child_hints_changed, o);
265}
266
267static void
268_evas_object_table_child_disconnect(Evas_Object *o, Evas_Object *child)
269{
270 evas_object_event_callback_del_full
271 (child, EVAS_CALLBACK_DEL, _on_child_del, o);
272 evas_object_event_callback_del_full
273 (child, EVAS_CALLBACK_CHANGED_SIZE_HINTS, _on_child_hints_changed, o);
274}
275
276static void
277_evas_object_table_calculate_cell(const Evas_Object_Table_Option *opt, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h)
278{
279 Evas_Coord cw, ch;
280
281 *w -= opt->pad.l + opt->pad.r;
282 if (*w < opt->min.w)
283 cw = opt->min.w;
284 else if ((opt->max.w > -1) && (*w > opt->max.w))
285 cw = opt->max.w;
286 else if (opt->fill_h)
287 cw = *w;
288 else
289 cw = opt->min.w;
290
291 *h -= opt->pad.t + opt->pad.b;
292 if (*h < opt->min.h)
293 ch = opt->min.h;
294 else if ((opt->max.h > -1) && (*h > opt->max.h))
295 ch = opt->max.h;
296 else if (opt->fill_v)
297 ch = *h;
298 else
299 ch = opt->min.h;
300
301 *x += opt->pad.l;
302 if (cw != *w)
303 {
304 *x += (*w - cw) * opt->align.h;
305 *w = cw;
306 }
307
308 *y += opt->pad.t;
309 if (ch != *h)
310 {
311 *y += (*h - ch) * opt->align.v;
312 *h = ch;
313 }
314}
315
316static void
317_evas_object_table_calculate_hints_homogeneous(Evas_Object *o, Evas_Object_Table_Data *priv)
318{
319 Eina_List *l;
320 Evas_Object_Table_Option *opt;
321 Evas_Coord minw, minh, o_minw, o_minh;
322 Eina_Bool expand_h, expand_v;
323
324 o_minw = 0;
325 o_minh = 0;
326 minw = 0;
327 minh = 0;
328 expand_h = 0;
329 expand_v = 0;
330
331 EINA_LIST_FOREACH(priv->children, l, opt)
332 {
333 Evas_Object *child = opt->obj;
334 Evas_Coord child_minw, child_minh, cell_minw, cell_minh;
335 double weightw, weighth;
336
337 evas_object_size_hint_min_get(child, &opt->min.w, &opt->min.h);
338 evas_object_size_hint_max_get(child, &opt->max.w, &opt->max.h);
339 evas_object_size_hint_padding_get
340 (child, &opt->pad.l, &opt->pad.r, &opt->pad.t, &opt->pad.b);
341 evas_object_size_hint_align_get(child, &opt->align.h, &opt->align.v);
342 evas_object_size_hint_weight_get(child, &weightw, &weighth);
343
344 child_minw = opt->min.w + opt->pad.l + opt->pad.r;
345 child_minh = opt->min.h + opt->pad.t + opt->pad.b;
346
347 cell_minw = (child_minw + opt->colspan - 1) / opt->colspan;
348 cell_minh = (child_minh + opt->rowspan - 1) / opt->rowspan;
349
350 opt->expand_h = 0;
351 if ((weightw > 0.0) &&
352 ((opt->max.w < 0) ||
353 ((opt->max.w > -1) && (opt->min.w < opt->max.w))))
354 {
355 opt->expand_h = 1;
356 expand_h = 1;
357 }
358
359 opt->expand_v = 0;
360 if ((weighth > 0.0) &&
361 ((opt->max.h < 0) ||
362 ((opt->max.h > -1) && (opt->min.h < opt->max.h))))
363 {
364 opt->expand_v = 1;
365 expand_v = 1;
366 }
367
368 opt->fill_h = 0;
369 if (opt->align.h < 0.0)
370 {
371 opt->align.h = 0.5;
372 opt->fill_h = 1;
373 }
374 opt->fill_v = 0;
375 if (opt->align.v < 0.0)
376 {
377 opt->align.v = 0.5;
378 opt->fill_v = 1;
379 }
380
381 /* greatest mininum values, with paddings */
382 if (minw < cell_minw)
383 minw = cell_minw;
384 if (minh < cell_minh)
385 minh = cell_minh;
386 /* greatest mininum values, without paddings */
387 if (o_minw < opt->min.w)
388 o_minw = opt->min.w;
389 if (o_minh < opt->min.h)
390 o_minh = opt->min.h;
391 }
392
393 if (priv->homogeneous == EVAS_OBJECT_TABLE_HOMOGENEOUS_ITEM)
394 {
395 if (o_minw < 1)
396 {
397 ERR("homogeneous table based on item size but no "
398 "horizontal mininum size specified! Using expand.");
399 expand_h = 1;
400 }
401 if (o_minh < 1)
402 {
403 ERR("homogeneous table based on item size but no "
404 "vertical mininum size specified! Using expand.");
405 expand_v = 1;
406 }
407 }
408
409 minw = priv->size.cols * (minw + priv->pad.h) - priv->pad.h;
410 minh = priv->size.rows * (minh + priv->pad.v) - priv->pad.v;
411
412 priv->hints_changed = 0;
413 priv->expand_h = expand_h;
414 priv->expand_v = expand_v;
415
416 if ((minw > 0 ) || (minh > 0))
417 evas_object_size_hint_min_set(o, minw, minh);
418
419 // XXX hint max?
420}
421
422static void
423_evas_object_table_calculate_layout_homogeneous_sizes_item(const Evas_Object *o, const Evas_Object_Table_Data *priv, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h)
424{
425 Evas_Coord minw, minh;
426 Eina_Bool expand_h, expand_v;
427
428 evas_object_size_hint_min_get(o, &minw, &minh);
429 expand_h = priv->expand_h;
430 expand_v = priv->expand_v;
431
432 if (*w < minw)
433 expand_h = 0;
434 if (!expand_h)
435 {
436 *x += (*w - minw) * priv->align.h;
437 *w = minw;
438 }
439
440 if (*h < minh)
441 expand_v = 0;
442 if (!expand_v)
443 {
444 *y += (*h - minh) * priv->align.v;
445 *h = minh;
446 }
447}
448
449static void
450_evas_object_table_calculate_layout_homogeneous_sizes(const Evas_Object *o, const Evas_Object_Table_Data *priv, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h, Evas_Coord *cellw, Evas_Coord *cellh)
451{
452 evas_object_geometry_get(o, x, y, w, h);
453 if (priv->homogeneous == EVAS_OBJECT_TABLE_HOMOGENEOUS_ITEM)
454 _evas_object_table_calculate_layout_homogeneous_sizes_item
455 (o, priv, x, y, w, h);
456
457 *cellw = (*w + priv->size.cols - 1) / priv->size.cols;
458 *cellh = (*h + priv->size.rows - 1) / priv->size.rows;
459}
460
461static void
462_evas_object_table_calculate_layout_homogeneous(Evas_Object *o, Evas_Object_Table_Data *priv)
463{
464 Evas_Coord x = 0, y = 0, w = 0, h = 0, ww, hh, cellw = 0, cellh = 0;
465 Eina_List *l;
466 Evas_Object_Table_Option *opt;
467
468 _evas_object_table_calculate_layout_homogeneous_sizes
469 (o, priv, &x, &y, &w, &h, &cellw, &cellh);
470
471 ww = w - ((priv->size.cols - 1) * priv->pad.h);
472 hh = h - ((priv->size.rows - 1) * priv->pad.v);
473
474 if (ww < 0) ww = 0;
475 if (ww < 0) ww = 0;
476
477 EINA_LIST_FOREACH(priv->children, l, opt)
478 {
479 Evas_Object *child = opt->obj;
480 Evas_Coord cx, cy, cw, ch, cox, coy, cow, coh;
481
482 cx = x + ((opt->col * ww) / priv->size.cols);
483 cw = x + (((opt->col + opt->colspan) * ww) / priv->size.cols) - cx;
484 cy = y + ((opt->row * hh) / priv->size.rows);
485 ch = y + (((opt->row + opt->rowspan) * hh) / priv->size.rows) - cy;
486
487 cx += (opt->col) * priv->pad.h;
488 cy += (opt->row) * priv->pad.v;
489
490 cox = cx;
491 coy = cy;
492 cow = cw;
493 coh = ch;
494
495 _evas_object_table_calculate_cell(opt, &cx, &cy, &cw, &ch);
496 if (cw > cow)
497 {
498 cx = cox;
499 cw = cow;
500 }
501 if (ch > coh)
502 {
503 cy = coy;
504 ch = coh;
505 }
506
507 if (priv->is_mirrored)
508 {
509 evas_object_move(opt->obj, x + w - (cx - x + cw), cy);
510 }
511 else
512 {
513 evas_object_move(child, cx, cy);
514 }
515 evas_object_resize(child, cw, ch);
516 }
517}
518
519static void
520_evas_object_table_smart_calculate_homogeneous(Evas_Object *o, Evas_Object_Table_Data *priv)
521{
522 if (priv->hints_changed)
523 _evas_object_table_calculate_hints_homogeneous(o, priv);
524 _evas_object_table_calculate_layout_homogeneous(o, priv);
525}
526
527static int
528_evas_object_table_count_expands(const Eina_Bool *expands, int start, int end)
529{
530 const Eina_Bool *itr = expands + start, *itr_end = expands + end;
531 int count = 0;
532
533 for (; itr < itr_end; itr++)
534 {
535 if (*itr)
536 count++;
537 }
538
539 return count;
540}
541
542static Evas_Coord
543_evas_object_table_sum_sizes(const Evas_Coord *sizes, int start, int end)
544{
545 const Evas_Coord *itr = sizes + start, *itr_end = sizes + end;
546 Evas_Coord sum = 0;
547
548 for (; itr < itr_end; itr++)
549 sum += *itr;
550
551 return sum;
552}
553
554static void
555_evas_object_table_sizes_calc_noexpand(Evas_Coord *sizes, int start, int end, Evas_Coord space)
556{
557 Evas_Coord *itr = sizes + start, *itr_end = sizes + end - 1;
558 Evas_Coord step;
559 int units;
560
561 /* XXX move to fixed point math and spread errors among cells */
562 units = end - start;
563 step = space / units;
564 for (; itr < itr_end; itr++)
565 *itr += step;
566
567 *itr += space - step * (units - 1);
568}
569
570static void
571_evas_object_table_sizes_calc_expand(Evas_Coord *sizes, int start, int end, Evas_Coord space, const Eina_Bool *expands, int expand_count, double *weights, double weighttot)
572{
573 Evas_Coord *itr = sizes + start, *itr_end = sizes + end;
574 const Eina_Bool *itr_expand = expands + start;
575 Evas_Coord step = 0, last_space = 0;
576 int total = 0, i = start;
577
578 /* XXX move to fixed point math and spread errors among cells */
579 if (weighttot > 0.0)
580 {
581 step = space / expand_count;
582 last_space = space - step * (expand_count - 1);
583 }
584
585 for (; itr < itr_end; itr++, itr_expand++, i++)
586 {
587 if (weighttot <= 0.0)
588 {
589 if (*itr_expand)
590 {
591 expand_count--;
592 if (expand_count > 0)
593 *itr += step;
594 else
595 {
596 *itr += last_space;
597 break;
598 }
599 }
600 }
601 else
602 {
603 if (*itr_expand)
604 {
605 expand_count--;
606 if (expand_count > 0)
607 {
608 step = (weights[i] / weighttot) * space;
609 *itr += step;
610 total += step;
611 }
612 else
613 {
614 *itr += space - total;
615 break;
616 }
617 }
618 }
619 }
620}
621
622static void
623_evas_object_table_calculate_hints_regular(Evas_Object *o, Evas_Object_Table_Data *priv)
624{
625 Evas_Object_Table_Option *opt;
626 Evas_Object_Table_Cache *c;
627 Eina_List *l;
628 double totweightw = 0.0, totweighth = 0.0;
629 int i;
630
631 if (!priv->cache)
632 {
633 priv->cache = _evas_object_table_cache_alloc
634 (priv->size.cols, priv->size.rows);
635 if (!priv->cache)
636 return;
637 }
638 c = priv->cache;
639 _evas_object_table_cache_reset(priv);
640
641 /* cache interesting data */
642 memset(c->expands.h, 1, priv->size.cols);
643 memset(c->expands.v, 1, priv->size.rows);
644 memset(c->weights.h, 0, priv->size.cols);
645 memset(c->weights.v, 0, priv->size.rows);
646 EINA_LIST_FOREACH(priv->children, l, opt)
647 {
648 Evas_Object *child = opt->obj;
649 double weightw, weighth;
650
651 evas_object_size_hint_min_get(child, &opt->min.w, &opt->min.h);
652 evas_object_size_hint_max_get(child, &opt->max.w, &opt->max.h);
653 evas_object_size_hint_padding_get
654 (child, &opt->pad.l, &opt->pad.r, &opt->pad.t, &opt->pad.b);
655 evas_object_size_hint_align_get(child, &opt->align.h, &opt->align.v);
656 evas_object_size_hint_weight_get(child, &weightw, &weighth);
657
658 opt->expand_h = 0;
659 if ((weightw > 0.0) &&
660 ((opt->max.w < 0) ||
661 ((opt->max.w > -1) && (opt->min.w < opt->max.w))))
662 opt->expand_h = 1;
663
664 opt->expand_v = 0;
665 if ((weighth > 0.0) &&
666 ((opt->max.h < 0) ||
667 ((opt->max.h > -1) && (opt->min.h < opt->max.h))))
668 opt->expand_v = 1;
669
670 opt->fill_h = 0;
671 if (opt->align.h < 0.0)
672 {
673 opt->align.h = 0.5;
674 opt->fill_h = 1;
675 }
676 opt->fill_v = 0;
677 if (opt->align.v < 0.0)
678 {
679 opt->align.v = 0.5;
680 opt->fill_v = 1;
681 }
682
683 if (!opt->expand_h)
684 memset(c->expands.h + opt->col, 0, opt->colspan);
685 else
686 {
687 for (i = opt->col; i < opt->col + opt->colspan; i++)
688 c->weights.h[i] += (weightw / (double)opt->colspan);
689 }
690 if (!opt->expand_v)
691 memset(c->expands.v + opt->row, 0, opt->rowspan);
692 else
693 {
694 for (i = opt->row; i < opt->row + opt->rowspan; i++)
695 c->weights.v[i] += (weighth / (double)opt->rowspan);
696 }
697 }
698 for (i = 0; i < priv->size.cols; i++) totweightw += c->weights.h[i];
699 for (i = 0; i < priv->size.rows; i++) totweighth += c->weights.v[i];
700
701 /* calculate sizes for each row and column */
702 EINA_LIST_FOREACH(priv->children, l, opt)
703 {
704 Evas_Coord tot, need;
705
706 /* handle horizontal */
707 tot = _evas_object_table_sum_sizes(c->sizes.h, opt->col, opt->end_col);
708 need = opt->min.w + opt->pad.l + opt->pad.r;
709 if (tot < need)
710 {
711 Evas_Coord space = need - tot;
712 int count;
713
714 count = _evas_object_table_count_expands
715 (c->expands.h, opt->col, opt->end_col);
716
717 if (count > 0)
718 _evas_object_table_sizes_calc_expand
719 (c->sizes.h, opt->col, opt->end_col, space,
720 c->expands.h, count, c->weights.h, totweightw);
721 else
722 _evas_object_table_sizes_calc_noexpand
723 (c->sizes.h, opt->col, opt->end_col, space);
724 }
725
726 /* handle vertical */
727 tot = _evas_object_table_sum_sizes(c->sizes.v, opt->row, opt->end_row);
728 need = opt->min.h + opt->pad.t + opt->pad.b;
729 if (tot < opt->min.h)
730 {
731 Evas_Coord space = need - tot;
732 int count;
733
734 count = _evas_object_table_count_expands
735 (c->expands.v, opt->row, opt->end_row);
736
737 if (count > 0)
738 _evas_object_table_sizes_calc_expand
739 (c->sizes.v, opt->row, opt->end_row, space,
740 c->expands.v, count, c->weights.v, totweighth);
741 else
742 _evas_object_table_sizes_calc_noexpand
743 (c->sizes.v, opt->row, opt->end_row, space);
744 }
745 }
746
747 c->total.weights.h = totweightw;
748 c->total.weights.v = totweighth;
749
750 c->total.expands.h = _evas_object_table_count_expands
751 (c->expands.h, 0, priv->size.cols);
752 c->total.expands.v = _evas_object_table_count_expands
753 (c->expands.v, 0, priv->size.rows);
754
755 c->total.min.w = _evas_object_table_sum_sizes
756 (c->sizes.h, 0, priv->size.cols);
757 c->total.min.h = _evas_object_table_sum_sizes
758 (c->sizes.v, 0, priv->size.rows);
759
760 c->total.min.w += priv->pad.h * (priv->size.cols - 1);
761 c->total.min.h += priv->pad.v * (priv->size.rows - 1);
762
763 if ((c->total.min.w > 0) || (c->total.min.h > 0))
764 evas_object_size_hint_min_set(o, c->total.min.w, c->total.min.h);
765
766 // XXX hint max?
767}
768
769static void
770_evas_object_table_calculate_layout_regular(Evas_Object *o, Evas_Object_Table_Data *priv)
771{
772 Evas_Object_Table_Option *opt;
773 Evas_Object_Table_Cache *c;
774 Eina_List *l;
775 Evas_Coord *cols = NULL, *rows = NULL;
776 Evas_Coord x, y, w, h;
777
778 evas_object_geometry_get(o, &x, &y, &w, &h);
779 c = priv->cache;
780
781 /* handle horizontal */
782 if ((c->total.expands.h <= 0) || (c->total.min.w >= w))
783 {
784 x += (w - c->total.min.w) * priv->align.h;
785 w = c->total.min.w;
786 cols = c->sizes.h;
787 }
788 else
789 {
790 int size = priv->size.cols * sizeof(Evas_Coord);
791 cols = malloc(size);
792 if (!cols)
793 {
794 ERR("Could not allocate temp columns (%d bytes): %s",
795 size, strerror(errno));
796 goto end;
797 }
798 memcpy(cols, c->sizes.h, size);
799 _evas_object_table_sizes_calc_expand
800 (cols, 0, priv->size.cols, w - c->total.min.w,
801 c->expands.h, c->total.expands.h, c->weights.h, c->total.weights.h);
802 }
803
804 /* handle vertical */
805 if ((c->total.expands.v <= 0) || (c->total.min.h >= h))
806 {
807 y += (h - c->total.min.h) * priv->align.v;
808 h = c->total.min.h;
809 rows = c->sizes.v;
810 }
811 else
812 {
813 int size = priv->size.rows * sizeof(Evas_Coord);
814 rows = malloc(size);
815 if (!rows)
816 {
817 ERR("could not allocate temp rows (%d bytes): %s",
818 size, strerror(errno));
819 goto end;
820 }
821 memcpy(rows, c->sizes.v, size);
822 _evas_object_table_sizes_calc_expand
823 (rows, 0, priv->size.rows, h - c->total.min.h,
824 c->expands.v, c->total.expands.v, c->weights.v, c->total.weights.v);
825 }
826
827 EINA_LIST_FOREACH(priv->children, l, opt)
828 {
829 Evas_Object *child = opt->obj;
830 Evas_Coord cx, cy, cw, ch;
831
832 cx = x + opt->col * (priv->pad.h);
833 cx += _evas_object_table_sum_sizes(cols, 0, opt->col);
834 cw = _evas_object_table_sum_sizes(cols, opt->col, opt->end_col);
835
836 cy = y + opt->row * (priv->pad.v);
837 cy += _evas_object_table_sum_sizes(rows, 0, opt->row);
838 ch = _evas_object_table_sum_sizes(rows, opt->row, opt->end_row);
839
840 _evas_object_table_calculate_cell(opt, &cx, &cy, &cw, &ch);
841
842 if (priv->is_mirrored)
843 {
844 evas_object_move(opt->obj, x + w - (cx - x + cw), cy);
845 }
846 else
847 {
848 evas_object_move(child, cx, cy);
849 }
850 evas_object_resize(child, cw, ch);
851 }
852
853 end:
854 if (cols != c->sizes.h)
855 {
856 if (cols) free(cols);
857 }
858 if (rows != c->sizes.v)
859 {
860 if (rows) free(rows);
861 }
862}
863
864static void
865_evas_object_table_smart_calculate_regular(Evas_Object *o, Evas_Object_Table_Data *priv)
866{
867 if (priv->hints_changed)
868 _evas_object_table_calculate_hints_regular(o, priv);
869 _evas_object_table_calculate_layout_regular(o, priv);
870}
871
872EVAS_SMART_SUBCLASS_NEW("Evas_Object_Table", _evas_object_table,
873 Evas_Smart_Class, Evas_Smart_Class,
874 evas_object_smart_clipped_class_get, NULL)
875
876static void
877_evas_object_table_smart_add(Evas_Object *o)
878{
879 EVAS_SMART_DATA_ALLOC(o, Evas_Object_Table_Data)
880
881 priv->pad.h = 0;
882 priv->pad.v = 0;
883 priv->align.h = 0.5;
884 priv->align.v = 0.5;
885 priv->size.cols = 0;
886 priv->size.rows = 0;
887 priv->cache = NULL;
888 priv->homogeneous = EVAS_OBJECT_TABLE_HOMOGENEOUS_NONE;
889 priv->hints_changed = 1;
890 priv->expand_h = 0;
891 priv->expand_v = 0;
892
893 _evas_object_table_parent_sc->add(o);
894}
895
896static void
897_evas_object_table_smart_del(Evas_Object *o)
898{
899 EVAS_OBJECT_TABLE_DATA_GET(o, priv);
900 Eina_List *l;
901
902 l = priv->children;
903 while (l)
904 {
905 Evas_Object_Table_Option *opt = l->data;
906 _evas_object_table_child_disconnect(o, opt->obj);
907 _evas_object_table_option_del(opt->obj);
908 free(opt);
909 l = eina_list_remove_list(l, l);
910 }
911
912 if (priv->cache)
913 {
914 _evas_object_table_cache_free(priv->cache);
915 priv->cache = NULL;
916 }
917
918 _evas_object_table_parent_sc->del(o);
919}
920
921static void
922_evas_object_table_smart_resize(Evas_Object *o, Evas_Coord w, Evas_Coord h)
923{
924 Evas_Coord ow, oh;
925 evas_object_geometry_get(o, NULL, NULL, &ow, &oh);
926 if ((ow == w) && (oh == h)) return;
927 evas_object_smart_changed(o);
928}
929
930static void
931_evas_object_table_smart_calculate(Evas_Object *o)
932{
933 EVAS_OBJECT_TABLE_DATA_GET_OR_RETURN(o, priv);
934
935 if ((priv->size.cols < 1) || (priv->size.rows < 1))
936 {
937 DBG("Nothing to do: cols=%d, rows=%d",
938 priv->size.cols, priv->size.rows);
939 return;
940 }
941
942 if (priv->homogeneous)
943 _evas_object_table_smart_calculate_homogeneous(o, priv);
944 else
945 _evas_object_table_smart_calculate_regular(o, priv);
946}
947
948static void
949_evas_object_table_smart_set_user(Evas_Smart_Class *sc)
950{
951 sc->add = _evas_object_table_smart_add;
952 sc->del = _evas_object_table_smart_del;
953 sc->resize = _evas_object_table_smart_resize;
954 sc->calculate = _evas_object_table_smart_calculate;
955}
956
957EAPI Evas_Object *
958evas_object_table_add(Evas *evas)
959{
960 return evas_object_smart_add(evas, _evas_object_table_smart_class_new());
961}
962
963EAPI Evas_Object *
964evas_object_table_add_to(Evas_Object *parent)
965{
966 Evas *evas;
967 Evas_Object *o;
968
969 evas = evas_object_evas_get(parent);
970 o = evas_object_table_add(evas);
971 evas_object_smart_member_add(o, parent);
972 return o;
973}
974
975EAPI void
976evas_object_table_homogeneous_set(Evas_Object *o, Evas_Object_Table_Homogeneous_Mode homogeneous)
977{
978 EVAS_OBJECT_TABLE_DATA_GET_OR_RETURN(o, priv);
979 if (priv->homogeneous == homogeneous)
980 return;
981 priv->homogeneous = homogeneous;
982 _evas_object_table_cache_invalidate(priv);
983 evas_object_smart_changed(o);
984}
985
986EAPI Evas_Object_Table_Homogeneous_Mode
987evas_object_table_homogeneous_get(const Evas_Object *o)
988{
989 EVAS_OBJECT_TABLE_DATA_GET_OR_RETURN_VAL(o, priv, 0);
990 return priv->homogeneous;
991}
992
993EAPI void
994evas_object_table_align_set(Evas_Object *o, double horizontal, double vertical)
995{
996 EVAS_OBJECT_TABLE_DATA_GET_OR_RETURN(o, priv);
997 if (priv->align.h == horizontal && priv->align.v == vertical)
998 return;
999 priv->align.h = horizontal;
1000 priv->align.v = vertical;
1001 evas_object_smart_changed(o);
1002}
1003
1004EAPI void
1005evas_object_table_align_get(const Evas_Object *o, double *horizontal, double *vertical)
1006{
1007 EVAS_OBJECT_TABLE_DATA_GET(o, priv);
1008 if (priv)
1009 {
1010 if (horizontal) *horizontal = priv->align.h;
1011 if (vertical) *vertical = priv->align.v;
1012 }
1013 else
1014 {
1015 if (horizontal) *horizontal = 0.5;
1016 if (vertical) *vertical = 0.5;
1017 }
1018}
1019
1020EAPI void
1021evas_object_table_padding_set(Evas_Object *o, Evas_Coord horizontal, Evas_Coord vertical)
1022{
1023 EVAS_OBJECT_TABLE_DATA_GET_OR_RETURN(o, priv);
1024 if (priv->pad.h == horizontal && priv->pad.v == vertical)
1025 return;
1026 priv->pad.h = horizontal;
1027 priv->pad.v = vertical;
1028 _evas_object_table_cache_invalidate(priv);
1029 evas_object_smart_changed(o);
1030}
1031
1032EAPI void
1033evas_object_table_padding_get(const Evas_Object *o, Evas_Coord *horizontal, Evas_Coord *vertical)
1034{
1035 EVAS_OBJECT_TABLE_DATA_GET(o, priv);
1036 if (priv)
1037 {
1038 if (horizontal) *horizontal = priv->pad.h;
1039 if (vertical) *vertical = priv->pad.v;
1040 }
1041 else
1042 {
1043 if (horizontal) *horizontal = 0;
1044 if (vertical) *vertical = 0;
1045 }
1046}
1047
1048EAPI Eina_Bool
1049evas_object_table_pack_get(Evas_Object *o, Evas_Object *child, unsigned short *col, unsigned short *row, unsigned short *colspan, unsigned short *rowspan)
1050{
1051 Evas_Object_Table_Option *opt;
1052
1053 EVAS_OBJECT_TABLE_DATA_GET_OR_RETURN_VAL(o, priv, 0);
1054 opt = _evas_object_table_option_get(child);
1055 if (!opt)
1056 {
1057 if (col) *col = 0;
1058 if (row) *row = 0;
1059 if (colspan) *colspan = 0;
1060 if (rowspan) *rowspan = 0;
1061 return EINA_FALSE;
1062 }
1063 if (col) *col = opt->col;
1064 if (row) *row = opt->row;
1065 if (colspan) *colspan = opt->colspan;
1066 if (rowspan) *rowspan = opt->rowspan;
1067 return EINA_TRUE;
1068}
1069
1070EAPI Eina_Bool
1071evas_object_table_pack(Evas_Object *o, Evas_Object *child, unsigned short col, unsigned short row, unsigned short colspan, unsigned short rowspan)
1072{
1073 Evas_Object_Table_Option *opt;
1074
1075 EVAS_OBJECT_TABLE_DATA_GET_OR_RETURN_VAL(o, priv, 0);
1076
1077 if (rowspan < 1)
1078 {
1079 ERR("rowspan < 1");
1080 return EINA_FALSE;
1081 }
1082 if (colspan < 1)
1083 {
1084 ERR("colspan < 1");
1085 return EINA_FALSE;
1086 }
1087
1088 opt = _evas_object_table_option_get(child);
1089 if (!opt)
1090 {
1091 opt = malloc(sizeof(*opt));
1092 if (!opt)
1093 {
1094 ERR("could not allocate table option data.");
1095 return EINA_FALSE;
1096 }
1097 }
1098
1099 opt->obj = child;
1100 opt->col = col;
1101 opt->row = row;
1102 opt->colspan = colspan;
1103 opt->rowspan = rowspan;
1104 opt->end_col = col + colspan;
1105 opt->end_row = row + rowspan;
1106
1107 if (evas_object_smart_parent_get(child) == o)
1108 {
1109 Eina_Bool need_shrink = EINA_FALSE;
1110
1111 if (priv->size.cols < opt->end_col)
1112 priv->size.cols = opt->end_col;
1113 else
1114 need_shrink = EINA_TRUE;
1115 if (priv->size.rows < opt->end_row)
1116 priv->size.rows = opt->end_row;
1117 else
1118 need_shrink = EINA_TRUE;
1119
1120 if (need_shrink)
1121 {
1122 Eina_List *l;
1123 Evas_Object_Table_Option *opt2;
1124 int max_row = 0, max_col = 0;
1125
1126 EINA_LIST_FOREACH(priv->children, l, opt2)
1127 {
1128 if (max_col < opt2->end_col) max_col = opt2->end_col;
1129 if (max_row < opt2->end_row) max_row = opt2->end_row;
1130 }
1131 priv->size.cols = max_col;
1132 priv->size.rows = max_row;
1133 }
1134 }
1135 else
1136 {
1137 opt->min.w = 0;
1138 opt->min.h = 0;
1139 opt->max.w = 0;
1140 opt->max.h = 0;
1141 opt->align.h = 0.5;
1142 opt->align.v = 0.5;
1143 opt->pad.l = 0;
1144 opt->pad.r = 0;
1145 opt->pad.t = 0;
1146 opt->pad.b = 0;
1147 opt->expand_h = 0;
1148 opt->expand_v = 0;
1149
1150 priv->children = eina_list_append(priv->children, opt);
1151
1152 if (priv->size.cols < opt->end_col)
1153 priv->size.cols = opt->end_col;
1154 if (priv->size.rows < opt->end_row)
1155 priv->size.rows = opt->end_row;
1156
1157 _evas_object_table_option_set(child, opt);
1158 evas_object_smart_member_add(child, o);
1159 _evas_object_table_child_connect(o, child);
1160 }
1161 _evas_object_table_cache_invalidate(priv);
1162 evas_object_smart_changed(o);
1163 return EINA_TRUE;
1164}
1165
1166static void
1167_evas_object_table_remove_opt(Evas_Object_Table_Data *priv, Evas_Object_Table_Option *opt)
1168{
1169 Eina_List *l;
1170 int max_row, max_col, was_greatest;
1171
1172 max_row = 0;
1173 max_col = 0;
1174 was_greatest = 0;
1175 l = priv->children;
1176 while (l)
1177 {
1178 Evas_Object_Table_Option *cur_opt = l->data;
1179
1180 if (cur_opt != opt)
1181 {
1182 if (max_col < cur_opt->end_col)
1183 max_col = cur_opt->end_col;
1184 if (max_row < cur_opt->end_row)
1185 max_row = cur_opt->end_row;
1186
1187 l = l->next;
1188 }
1189 else
1190 {
1191 Eina_List *tmp = l->next;
1192 priv->children = eina_list_remove_list(priv->children, l);
1193
1194 if ((priv->size.cols > opt->end_col) &&
1195 (priv->size.rows > opt->end_row))
1196 break;
1197 else
1198 {
1199 was_greatest = 1;
1200 l = tmp;
1201 }
1202 }
1203 }
1204
1205 if (was_greatest)
1206 {
1207 priv->size.cols = max_col;
1208 priv->size.rows = max_row;
1209 }
1210}
1211
1212EAPI Eina_Bool
1213evas_object_table_unpack(Evas_Object *o, Evas_Object *child)
1214{
1215 Evas_Object_Table_Option *opt;
1216
1217 EVAS_OBJECT_TABLE_DATA_GET_OR_RETURN_VAL(o, priv, 0);
1218
1219 if (o != evas_object_smart_parent_get(child))
1220 {
1221 ERR("cannot unpack child from incorrect table!");
1222 return EINA_FALSE;
1223 }
1224
1225 opt = _evas_object_table_option_del(child);
1226 if (!opt)
1227 {
1228 ERR("cannot unpack child with no packing option!");
1229 return EINA_FALSE;
1230 }
1231
1232 _evas_object_table_child_disconnect(o, child);
1233 _evas_object_table_remove_opt(priv, opt);
1234 evas_object_smart_member_del(child);
1235 free(opt);
1236 _evas_object_table_cache_invalidate(priv);
1237 evas_object_smart_changed(o);
1238
1239 return EINA_TRUE;
1240}
1241
1242EAPI void
1243evas_object_table_clear(Evas_Object *o, Eina_Bool clear)
1244{
1245 Evas_Object_Table_Option *opt;
1246
1247 EVAS_OBJECT_TABLE_DATA_GET_OR_RETURN(o, priv);
1248
1249 EINA_LIST_FREE(priv->children, opt)
1250 {
1251 _evas_object_table_child_disconnect(o, opt->obj);
1252 _evas_object_table_option_del(opt->obj);
1253 evas_object_smart_member_del(opt->obj);
1254 if (clear)
1255 evas_object_del(opt->obj);
1256 free(opt);
1257 }
1258 priv->size.cols = 0;
1259 priv->size.rows = 0;
1260 _evas_object_table_cache_invalidate(priv);
1261 evas_object_smart_changed(o);
1262}
1263
1264EAPI void
1265evas_object_table_col_row_size_get(const Evas_Object *o, int *cols, int *rows)
1266{
1267 EVAS_OBJECT_TABLE_DATA_GET(o, priv);
1268 if (priv)
1269 {
1270 if (cols) *cols = priv->size.cols;
1271 if (rows) *rows = priv->size.rows;
1272 }
1273 else
1274 {
1275 if (cols) *cols = -1;
1276 if (rows) *rows = -1;
1277 }
1278}
1279
1280EAPI Eina_Iterator *
1281evas_object_table_iterator_new(const Evas_Object *o)
1282{
1283 Evas_Object_Table_Iterator *it;
1284
1285 EVAS_OBJECT_TABLE_DATA_GET_OR_RETURN_VAL(o, priv, NULL);
1286
1287 if (!priv->children) return NULL;
1288
1289 it = calloc(1, sizeof(Evas_Object_Table_Iterator));
1290 if (!it) return NULL;
1291
1292 EINA_MAGIC_SET(&it->iterator, EINA_MAGIC_ITERATOR);
1293
1294 it->real_iterator = eina_list_iterator_new(priv->children);
1295 it->table = o;
1296
1297 it->iterator.next = FUNC_ITERATOR_NEXT(_evas_object_table_iterator_next);
1298 it->iterator.get_container = FUNC_ITERATOR_GET_CONTAINER(_evas_object_table_iterator_get_container);
1299 it->iterator.free = FUNC_ITERATOR_FREE(_evas_object_table_iterator_free);
1300
1301 return &it->iterator;
1302}
1303
1304EAPI Eina_Accessor *
1305evas_object_table_accessor_new(const Evas_Object *o)
1306{
1307 Evas_Object_Table_Accessor *it;
1308
1309 EVAS_OBJECT_TABLE_DATA_GET_OR_RETURN_VAL(o, priv, NULL);
1310
1311 if (!priv->children) return NULL;
1312
1313 it = calloc(1, sizeof(Evas_Object_Table_Accessor));
1314 if (!it) return NULL;
1315
1316 EINA_MAGIC_SET(&it->accessor, EINA_MAGIC_ACCESSOR);
1317
1318 it->real_accessor = eina_list_accessor_new(priv->children);
1319 it->table = o;
1320
1321 it->accessor.get_at = FUNC_ACCESSOR_GET_AT(_evas_object_table_accessor_get_at);
1322 it->accessor.get_container = FUNC_ACCESSOR_GET_CONTAINER(_evas_object_table_accessor_get_container);
1323 it->accessor.free = FUNC_ACCESSOR_FREE(_evas_object_table_accessor_free);
1324
1325 return &it->accessor;
1326}
1327
1328EAPI Eina_List *
1329evas_object_table_children_get(const Evas_Object *o)
1330{
1331 Eina_List *new_list = NULL, *l;
1332 Evas_Object_Table_Option *opt;
1333
1334 EVAS_OBJECT_TABLE_DATA_GET_OR_RETURN_VAL(o, priv, NULL);
1335
1336 EINA_LIST_FOREACH(priv->children, l, opt)
1337 new_list = eina_list_append(new_list, opt->obj);
1338
1339 return new_list;
1340}
1341
1342Evas_Object *
1343evas_object_table_child_get(const Evas_Object *o, unsigned short col, unsigned short row)
1344{
1345 Eina_List *l;
1346 Evas_Object_Table_Option *opt;
1347
1348 EVAS_OBJECT_TABLE_DATA_GET_OR_RETURN_VAL(o, priv, NULL);
1349
1350 EINA_LIST_FOREACH(priv->children, l, opt)
1351 if (opt->col == col && opt->row == row)
1352 return opt->obj;
1353 return NULL;
1354}
1355
1356EAPI Eina_Bool
1357evas_object_table_mirrored_get(const Evas_Object *obj)
1358{
1359 EVAS_OBJECT_TABLE_DATA_GET_OR_RETURN_VAL(obj, priv, EINA_FALSE);
1360
1361 return priv->is_mirrored;
1362}
1363
1364EAPI void
1365evas_object_table_mirrored_set(Evas_Object *obj, Eina_Bool mirrored)
1366{
1367 EVAS_OBJECT_TABLE_DATA_GET_OR_RETURN(obj, priv);
1368 if (priv->is_mirrored != mirrored)
1369 {
1370 priv->is_mirrored = mirrored;
1371 _evas_object_table_smart_calculate(obj);
1372 }
1373}
diff --git a/libraries/evas/src/lib/canvas/evas_object_text.c b/libraries/evas/src/lib/canvas/evas_object_text.c
deleted file mode 100644
index dbe5e08..0000000
--- a/libraries/evas/src/lib/canvas/evas_object_text.c
+++ /dev/null
@@ -1,1943 +0,0 @@
1#include "evas_common.h" /* Includes evas_bidi_utils stuff. */
2#include "evas_private.h"
3
4/* save typing */
5#define ENFN obj->layer->evas->engine.func
6#define ENDT obj->layer->evas->engine.data.output
7
8/* private magic number for text objects */
9static const char o_type[] = "text";
10
11/* private struct for text object internal data */
12typedef struct _Evas_Object_Text Evas_Object_Text;
13typedef struct _Evas_Object_Text_Item Evas_Object_Text_Item;
14
15struct _Evas_Object_Text
16{
17 DATA32 magic;
18
19 struct {
20 const char *utf8_text; /* The text exposed to the API */
21 const char *font;
22 Evas_Font_Description *fdesc;
23 const char *source;
24 Evas_Font_Size size;
25 struct {
26 unsigned char r, g, b, a;
27 } outline, shadow, glow, glow2;
28
29 unsigned char style;
30 } cur, prev;
31
32 float ascent, descent;
33 float max_ascent, max_descent;
34 Evas_BiDi_Paragraph_Props *bidi_par_props;
35 const char *bidi_delimiters;
36 Evas_Object_Text_Item *items;
37
38 Evas_Font_Set *font;
39
40 char changed : 1;
41};
42
43struct _Evas_Object_Text_Item
44{
45 EINA_INLIST;
46
47 size_t text_pos;
48 size_t visual_pos;
49 Evas_Text_Props text_props;
50 Evas_Coord x, w, h, adv;
51};
52
53/* private methods for text objects */
54static void evas_object_text_init(Evas_Object *obj);
55static void *evas_object_text_new(void);
56static void evas_object_text_render(Evas_Object *obj, void *output, void *context, void *surface, int x, int y);
57static void evas_object_text_free(Evas_Object *obj);
58static void evas_object_text_render_pre(Evas_Object *obj);
59static void evas_object_text_render_post(Evas_Object *obj);
60
61static unsigned int evas_object_text_id_get(Evas_Object *obj);
62static unsigned int evas_object_text_visual_id_get(Evas_Object *obj);
63static void *evas_object_text_engine_data_get(Evas_Object *obj);
64
65static int evas_object_text_is_opaque(Evas_Object *obj);
66static int evas_object_text_was_opaque(Evas_Object *obj);
67
68static void evas_object_text_scale_update(Evas_Object *obj);
69static void _evas_object_text_recalc(Evas_Object *obj);
70
71static const Evas_Object_Func object_func =
72{
73 /* methods (compulsory) */
74 evas_object_text_free,
75 evas_object_text_render,
76 evas_object_text_render_pre,
77 evas_object_text_render_post,
78 evas_object_text_id_get,
79 evas_object_text_visual_id_get,
80 evas_object_text_engine_data_get,
81 /* these are optional. NULL = nothing */
82 NULL,
83 NULL,
84 NULL,
85 NULL,
86 evas_object_text_is_opaque,
87 evas_object_text_was_opaque,
88 NULL,
89 NULL,
90 NULL,
91 evas_object_text_scale_update,
92 NULL,
93 NULL,
94 NULL
95};
96
97/* the actual api call to add a rect */
98/* it has no other api calls as all properties are standard */
99
100EVAS_MEMPOOL(_mp_obj);
101
102static int
103_evas_object_text_char_coords_get(const Evas_Object *obj,
104 const Evas_Object_Text *o,
105 size_t pos, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h)
106{
107 Evas_Object_Text_Item *it;
108
109 EINA_INLIST_FOREACH(EINA_INLIST_GET(o->items), it)
110 {
111 if ((it->text_pos <= pos) &&
112 (pos < (it->text_pos + it->text_props.text_len)))
113 {
114 int ret;
115 ret = ENFN->font_char_coords_get(ENDT, o->font,
116 &it->text_props, pos - it->text_pos, x, y, w, h);
117 if (x) *x += it->x;
118 return ret;
119 }
120 }
121 return 0;
122}
123
124static void
125_evas_object_text_item_clean(Evas_Object_Text_Item *it)
126{
127 evas_common_text_props_content_unref(&it->text_props);
128}
129
130static void
131_evas_object_text_items_clear(Evas_Object_Text *o)
132{
133 Evas_Object_Text_Item *it;
134
135 while (o->items)
136 {
137 it = o->items;
138 o->items = (Evas_Object_Text_Item *) eina_inlist_remove(
139 EINA_INLIST_GET(o->items),
140 EINA_INLIST_GET(it));
141 _evas_object_text_item_clean(it);
142 free(it);
143 }
144}
145
146#ifdef BIDI_SUPPORT
147static int
148_evas_object_text_it_compare_logical(const void *_it1, const void *_it2)
149{
150 const Evas_Object_Text_Item *it1 = _it1, *it2 = _it2;
151 if (it1->text_pos < it2->text_pos)
152 return -1;
153 else if (it1->text_pos == it2->text_pos)
154 return 0;
155 else
156 return 1;
157
158}
159#endif
160
161static int
162_evas_object_text_last_up_to_pos(const Evas_Object *obj,
163 const Evas_Object_Text *o, Evas_Coord cx, Evas_Coord cy)
164{
165 Evas_Object_Text_Item *it;
166
167#ifdef BIDI_SUPPORT
168 /*FIXME: not very efficient, sort the items arrays. */
169 /* Reorder if it's a bidi text */
170 if (o->bidi_par_props)
171 {
172 Eina_List *logical_it = NULL;
173 Evas_Object_Text_Item *i;
174 Eina_List *itr;
175 Evas_Coord x = 0;
176 /* Insert all to the logical list */
177 EINA_INLIST_FOREACH(o->items, i)
178 {
179 logical_it = eina_list_sorted_insert(logical_it,
180 _evas_object_text_it_compare_logical, i);
181 }
182 EINA_LIST_FOREACH(logical_it, itr, it)
183 {
184 if ((x <= cx) && (cx < x + it->adv))
185 {
186 return it->text_pos + ENFN->font_last_up_to_pos(ENDT,
187 o->font,
188 &it->text_props,
189 cx - x,
190 cy);
191 }
192 x += it->adv;
193 }
194 eina_list_free(logical_it);
195 }
196 else
197#endif
198 {
199 EINA_INLIST_FOREACH(EINA_INLIST_GET(o->items), it)
200 {
201 if ((it->x <= cx) && (cx < it->x + it->adv))
202 {
203 return it->text_pos + ENFN->font_last_up_to_pos(ENDT,
204 o->font,
205 &it->text_props,
206 cx - it->x,
207 cy);
208 }
209 }
210 }
211 return -1;
212}
213
214static int
215_evas_object_text_char_at_coords(const Evas_Object *obj,
216 const Evas_Object_Text *o, Evas_Coord cx, Evas_Coord cy,
217 Evas_Coord *rx, Evas_Coord *ry, Evas_Coord *rw, Evas_Coord *rh)
218{
219 Evas_Object_Text_Item *it;
220
221 EINA_INLIST_FOREACH(EINA_INLIST_GET(o->items), it)
222 {
223 if ((it->x <= cx) && (cx < it->x + it->adv))
224 {
225 return it->text_pos + ENFN->font_char_at_coords_get(ENDT,
226 o->font,
227 &it->text_props,
228 cx - it->x,
229 cy,
230 rx, ry,
231 rw, rh);
232 }
233 }
234 return -1;
235}
236
237static Evas_Coord
238_evas_object_text_horiz_advance_get(const Evas_Object *obj,
239 const Evas_Object_Text *o)
240{
241 Evas_Object_Text_Item *it;
242 Evas_Coord adv;
243 (void) obj;
244
245 adv = 0;
246 EINA_INLIST_FOREACH(EINA_INLIST_GET(o->items), it)
247 {
248 adv += it->adv;
249 }
250 return adv;
251}
252
253static Evas_Coord
254_evas_object_text_vert_advance_get(const Evas_Object *obj __UNUSED__,
255 const Evas_Object_Text *o)
256{
257 return o->max_ascent + o->max_descent;
258}
259
260EAPI Evas_Object *
261evas_object_text_add(Evas *e)
262{
263 Evas_Object *obj;
264
265 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
266 return NULL;
267 MAGIC_CHECK_END();
268 obj = evas_object_new(e);
269 evas_object_text_init(obj);
270 evas_object_inject(obj, e);
271 return obj;
272}
273
274EAPI void
275evas_object_text_font_source_set(Evas_Object *obj, const char *font_source)
276{
277 Evas_Object_Text *o;
278
279 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
280 return;
281 MAGIC_CHECK_END();
282 o = (Evas_Object_Text *)(obj->object_data);
283 MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
284 return;
285 MAGIC_CHECK_END();
286
287 if ((o->cur.source) && (font_source) &&
288 (!strcmp(o->cur.source, font_source)))
289 return;
290 /*
291 if (o->cur.source) eina_stringshare_del(o->cur.source);
292 if (font_source) o->cur.source = eina_stringshare_add(font_source);
293 else o->cur.source = NULL;
294 */
295 eina_stringshare_replace(&o->cur.source, font_source);
296}
297
298EAPI const char *
299evas_object_text_font_source_get(const Evas_Object *obj)
300{
301 Evas_Object_Text *o;
302
303 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
304 return NULL;
305 MAGIC_CHECK_END();
306 o = (Evas_Object_Text *)(obj->object_data);
307 MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
308 return NULL;
309 MAGIC_CHECK_END();
310 return o->cur.source;
311}
312
313EAPI void
314evas_object_text_font_set(Evas_Object *obj, const char *font, Evas_Font_Size size)
315{
316 Evas_Object_Text *o;
317 int is, was = 0, pass = 0, freeze = 0;
318 Evas_Font_Description *fdesc;
319
320 if ((!font) || (size <= 0)) return;
321 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
322 return;
323 MAGIC_CHECK_END();
324 o = (Evas_Object_Text *)(obj->object_data);
325 MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
326 return;
327 MAGIC_CHECK_END();
328
329 fdesc = evas_font_desc_new();
330 evas_font_name_parse(fdesc, font);
331 if (o->cur.fdesc && !evas_font_desc_cmp(fdesc, o->cur.fdesc) &&
332 (size == o->cur.size))
333 {
334 evas_font_desc_unref(fdesc);
335 return;
336 }
337
338 if (o->cur.fdesc) evas_font_desc_unref(o->cur.fdesc);
339 o->cur.fdesc = fdesc;
340
341 o->cur.size = size;
342 eina_stringshare_replace(&o->cur.font, font);
343 o->prev.font = NULL;
344
345 if (obj->layer->evas->events_frozen <= 0)
346 {
347 pass = evas_event_passes_through(obj);
348 freeze = evas_event_freezes_through(obj);
349 if ((!pass) && (!freeze))
350 was = evas_object_is_in_output_rect(obj,
351 obj->layer->evas->pointer.x,
352 obj->layer->evas->pointer.y, 1, 1);
353 }
354
355#ifdef EVAS_FRAME_QUEUING
356 if (o->font)
357 evas_common_pipe_op_text_flush((RGBA_Font *) o->font);
358#endif
359
360 /* DO IT */
361 if (o->font)
362 {
363 evas_font_free(obj->layer->evas, o->font);
364 o->font = NULL;
365 }
366
367 o->font = evas_font_load(obj->layer->evas, o->cur.fdesc, o->cur.source,
368 (int)(((double) o->cur.size) * obj->cur.scale));
369 if (o->font)
370 {
371 o->ascent = ENFN->font_ascent_get(ENDT, o->font);
372 o->descent = ENFN->font_descent_get(ENDT, o->font);
373 o->max_ascent = ENFN->font_max_ascent_get(ENDT, o->font);
374 o->max_descent = ENFN->font_max_descent_get(ENDT, o->font);
375 }
376 else
377 {
378 o->ascent = 0;
379 o->descent = 0;
380 o->max_ascent = 0;
381 o->max_descent = 0;
382 }
383 _evas_object_text_recalc(obj);
384 o->changed = 1;
385 evas_object_change(obj);
386 evas_object_clip_dirty(obj);
387 evas_object_coords_recalc(obj);
388 if (obj->layer->evas->events_frozen <= 0)
389 {
390 if ((!pass) && (!freeze))
391 {
392 is = evas_object_is_in_output_rect(obj,
393 obj->layer->evas->pointer.x,
394 obj->layer->evas->pointer.y,
395 1, 1);
396 if ((is ^ was) && obj->cur.visible)
397 evas_event_feed_mouse_move(obj->layer->evas,
398 obj->layer->evas->pointer.x,
399 obj->layer->evas->pointer.y,
400 obj->layer->evas->last_timestamp,
401 NULL);
402 }
403 }
404 evas_object_inform_call_resize(obj);
405}
406
407EAPI void
408evas_object_text_font_get(const Evas_Object *obj, const char **font, Evas_Font_Size *size)
409{
410 Evas_Object_Text *o;
411
412 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
413 if (font) *font = "";
414 if (size) *size = 0;
415 return;
416 MAGIC_CHECK_END();
417 o = (Evas_Object_Text *)(obj->object_data);
418 MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
419 if (font) *font = "";
420 if (size) *size = 0;
421 return;
422 MAGIC_CHECK_END();
423 if (font) *font = o->cur.font;
424 if (size) *size = o->cur.size;
425}
426
427
428/**
429 * @internal
430 * Create a new text layout item from the string and the format.
431 *
432 * @param c the context to work on - Not NULL.
433 * @param fmt the format to use.
434 * @param str the string to use.
435 */
436static Evas_Object_Text_Item *
437_evas_object_text_item_new(Evas_Object *obj, Evas_Object_Text *o,
438 Evas_Font_Instance *fi, const Eina_Unicode *str, Evas_Script_Type script,
439 size_t pos, size_t visual_pos, size_t len)
440{
441 Evas_Object_Text_Item *it;
442
443 it = calloc(1, sizeof(Evas_Object_Text_Item));
444 it->text_pos = pos;
445 it->visual_pos = visual_pos;
446 evas_common_text_props_bidi_set(&it->text_props, o->bidi_par_props,
447 it->text_pos);
448 evas_common_text_props_script_set(&it->text_props, script);
449
450 if (fi)
451 {
452 ENFN->font_text_props_info_create(ENDT,
453 fi, str + pos, &it->text_props,
454 o->bidi_par_props, it->text_pos, len);
455
456 ENFN->font_string_size_get(ENDT,
457 o->font,
458 &it->text_props,
459 &it->w, &it->h);
460 it->adv = ENFN->font_h_advance_get(ENDT, o->font,
461 &it->text_props);
462 }
463 o->items = (Evas_Object_Text_Item *)
464 eina_inlist_append(EINA_INLIST_GET(o->items), EINA_INLIST_GET(it));
465 return it;
466}
467
468/**
469 * @internal
470 * Orders o->items according to the visual position.
471 *
472 * @param obj the evas object
473 * @param o the text object
474 */
475static void
476_evas_object_text_item_order(Evas_Object *obj, Evas_Object_Text *o)
477{
478 (void) obj;
479#ifdef BIDI_SUPPORT
480 /*FIXME: not very efficient, sort the items arrays. */
481 /* Reorder if it's a bidi text */
482 if (o->bidi_par_props)
483 {
484 Evas_Object_Text_Item *i, *j, *min;
485 i = o->items;
486 while (i)
487 {
488 min = i;
489 EINA_INLIST_FOREACH(i, j)
490 {
491 if (j->visual_pos < min->visual_pos)
492 {
493 min = j;
494 }
495 }
496 if (min != i)
497 {
498 o->items = (Evas_Object_Text_Item *) eina_inlist_remove(EINA_INLIST_GET(o->items), EINA_INLIST_GET(min));
499 o->items = (Evas_Object_Text_Item *) eina_inlist_prepend_relative(EINA_INLIST_GET(o->items), EINA_INLIST_GET(min), EINA_INLIST_GET(i));
500 }
501
502 i = (Evas_Object_Text_Item *) EINA_INLIST_GET(min)->next;
503 }
504 }
505#endif
506
507 /* calculate the positions according to the order. */
508 {
509 Evas_Object_Text_Item *it = o->items;
510 Evas_Coord x = 0;
511
512 while (it)
513 {
514 it->x = x;
515 x += it->adv;
516 it = (Evas_Object_Text_Item *) EINA_INLIST_GET(it)->next;
517 }
518 }
519}
520
521/**
522 * @internal
523 * Populates o->items with the items of the text according to text
524 *
525 * @param obj the evas object
526 * @param o the text object
527 * @param text the text to layout
528 */
529static void
530_evas_object_text_layout(Evas_Object *obj, Evas_Object_Text *o, const Eina_Unicode *text)
531{
532 EvasBiDiStrIndex *v_to_l = NULL;
533 size_t pos, visual_pos;
534 int len = eina_unicode_strlen(text);
535#ifdef BIDI_SUPPORT
536 int par_len = len;
537 int *segment_idxs = NULL;
538 if (o->bidi_delimiters)
539 segment_idxs = evas_bidi_segment_idxs_get(text, o->bidi_delimiters);
540 evas_bidi_paragraph_props_unref(o->bidi_par_props);
541 o->bidi_par_props = evas_bidi_paragraph_props_get(text, len, segment_idxs);
542 evas_bidi_props_reorder_line(NULL, 0, len, o->bidi_par_props, &v_to_l);
543 if (segment_idxs) free(segment_idxs);
544#endif
545 visual_pos = pos = 0;
546
547 while (len > 0)
548 {
549 Evas_Font_Instance *script_fi = NULL;
550 int script_len = len, tmp_cut;
551 Evas_Script_Type script;
552 tmp_cut = evas_common_language_script_end_of_run_get(
553 text + pos,
554 o->bidi_par_props,
555 pos, len);
556 if (tmp_cut > 0)
557 script_len = tmp_cut;
558
559 script = evas_common_language_script_type_get(text, script_len);
560
561 while (script_len > 0)
562 {
563 Evas_Font_Instance *cur_fi = NULL;
564 int run_len = script_len;
565 if (o->font)
566 {
567 run_len = ENFN->font_run_end_get(ENDT,
568 o->font, &script_fi, &cur_fi,
569 script, text + pos, script_len);
570 }
571#ifdef BIDI_SUPPORT
572 visual_pos = evas_bidi_position_logical_to_visual(
573 v_to_l, par_len, pos);
574#else
575 visual_pos = pos;
576#endif
577 _evas_object_text_item_new(obj, o, cur_fi, text, script,
578 pos, visual_pos, run_len);
579
580 pos += run_len;
581 script_len -= run_len;
582 len -= run_len;
583 }
584 }
585
586 _evas_object_text_item_order(obj, o);
587
588 if (v_to_l) free(v_to_l);
589}
590
591
592EAPI void
593evas_object_text_text_set(Evas_Object *obj, const char *_text)
594{
595 Evas_Object_Text *o;
596 int is, was, len;
597 Eina_Unicode *text;
598
599 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
600 return;
601 MAGIC_CHECK_END();
602 o = (Evas_Object_Text *)(obj->object_data);
603 MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
604 return;
605 MAGIC_CHECK_END();
606
607 if ((o->cur.utf8_text) && (_text) && (!strcmp(o->cur.utf8_text, _text)))
608 return;
609 text = eina_unicode_utf8_to_unicode(_text, &len);
610
611 if (!text) text = eina_unicode_strdup(EINA_UNICODE_EMPTY_STRING);
612 was = evas_object_is_in_output_rect(obj,
613 obj->layer->evas->pointer.x,
614 obj->layer->evas->pointer.y, 1, 1);
615 /* DO II */
616 /*Update bidi_props*/
617
618 if (o->items) _evas_object_text_items_clear(o);
619
620 if ((text) && (*text))
621 {
622 _evas_object_text_layout(obj, o, text);
623 eina_stringshare_replace(&o->cur.utf8_text, _text);
624 o->prev.utf8_text = NULL;
625 }
626 else
627 {
628 eina_stringshare_replace(&o->cur.utf8_text, NULL);
629 }
630 if (text)
631 {
632 free(text);
633 text = NULL;
634 }
635 _evas_object_text_recalc(obj);
636 o->changed = 1;
637 evas_object_change(obj);
638 evas_object_clip_dirty(obj);
639 evas_object_coords_recalc(obj);
640 is = evas_object_is_in_output_rect(obj,
641 obj->layer->evas->pointer.x,
642 obj->layer->evas->pointer.y, 1, 1);
643 if ((is || was) && obj->cur.visible)
644 evas_event_feed_mouse_move(obj->layer->evas,
645 obj->layer->evas->pointer.x,
646 obj->layer->evas->pointer.y,
647 obj->layer->evas->last_timestamp,
648 NULL);
649 evas_object_inform_call_resize(obj);
650 if (text) free(text);
651}
652
653EAPI void
654evas_object_text_bidi_delimiters_set(Evas_Object *obj, const char *delim)
655{
656 Evas_Object_Text *o;
657
658 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
659 return;
660 MAGIC_CHECK_END();
661 o = (Evas_Object_Text *)(obj->object_data);
662 MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
663 return;
664 MAGIC_CHECK_END();
665
666 eina_stringshare_replace(&o->bidi_delimiters, delim);
667}
668
669EAPI const char *
670evas_object_text_bidi_delimiters_get(const Evas_Object *obj)
671{
672 Evas_Object_Text *o;
673
674 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
675 return NULL;
676 MAGIC_CHECK_END();
677 o = (Evas_Object_Text *)(obj->object_data);
678 MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
679 return NULL;
680 MAGIC_CHECK_END();
681
682 return o->bidi_delimiters;
683}
684
685
686EAPI const char *
687evas_object_text_text_get(const Evas_Object *obj)
688{
689 Evas_Object_Text *o;
690
691 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
692 return NULL;
693 MAGIC_CHECK_END();
694 o = (Evas_Object_Text *)(obj->object_data);
695 MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
696 return NULL;
697 MAGIC_CHECK_END();
698 return o->cur.utf8_text;
699}
700
701EAPI Evas_BiDi_Direction
702evas_object_text_direction_get(const Evas_Object *obj)
703{
704 Evas_Object_Text *o;
705
706 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
707 return EVAS_BIDI_DIRECTION_NEUTRAL;
708 MAGIC_CHECK_END();
709 o = (Evas_Object_Text *)(obj->object_data);
710 MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
711 return EVAS_BIDI_DIRECTION_NEUTRAL;
712 MAGIC_CHECK_END();
713 if (o->items)
714 {
715 return o->items->text_props.bidi.dir;
716 }
717 return EVAS_BIDI_DIRECTION_NEUTRAL;
718}
719
720EAPI Evas_Coord
721evas_object_text_ascent_get(const Evas_Object *obj)
722{
723 Evas_Object_Text *o;
724
725 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
726 return 0;
727 MAGIC_CHECK_END();
728 o = (Evas_Object_Text *)(obj->object_data);
729 MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
730 return 0;
731 MAGIC_CHECK_END();
732 return o->ascent;
733}
734
735EAPI Evas_Coord
736evas_object_text_descent_get(const Evas_Object *obj)
737{
738 Evas_Object_Text *o;
739
740 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
741 return 0;
742 MAGIC_CHECK_END();
743 o = (Evas_Object_Text *)(obj->object_data);
744 MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
745 return 0;
746 MAGIC_CHECK_END();
747 return o->descent;
748}
749
750EAPI Evas_Coord
751evas_object_text_max_ascent_get(const Evas_Object *obj)
752{
753 Evas_Object_Text *o;
754
755 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
756 return 0;
757 MAGIC_CHECK_END();
758 o = (Evas_Object_Text *)(obj->object_data);
759 MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
760 return 0;
761 MAGIC_CHECK_END();
762 return o->max_ascent;
763}
764
765EAPI Evas_Coord
766evas_object_text_max_descent_get(const Evas_Object *obj)
767{
768 Evas_Object_Text *o;
769
770 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
771 return 0;
772 MAGIC_CHECK_END();
773 o = (Evas_Object_Text *)(obj->object_data);
774 MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
775 return 0;
776 MAGIC_CHECK_END();
777 return o->max_descent;
778}
779
780EAPI Evas_Coord
781evas_object_text_inset_get(const Evas_Object *obj)
782{
783 Evas_Object_Text *o;
784
785 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
786 return 0;
787 MAGIC_CHECK_END();
788 o = (Evas_Object_Text *)(obj->object_data);
789 MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
790 return 0;
791 MAGIC_CHECK_END();
792 if (!o->font) return 0;
793 if (!o->items) return 0;
794 return ENFN->font_inset_get(ENDT, o->font, &o->items->text_props);
795}
796
797EAPI Evas_Coord
798evas_object_text_horiz_advance_get(const Evas_Object *obj)
799{
800 Evas_Object_Text *o;
801
802 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
803 return 0;
804 MAGIC_CHECK_END();
805 o = (Evas_Object_Text *)(obj->object_data);
806 MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
807 return 0;
808 MAGIC_CHECK_END();
809 if (!o->font) return 0;
810 if (!o->items) return 0;
811 return _evas_object_text_horiz_advance_get(obj, o);
812}
813
814EAPI Evas_Coord
815evas_object_text_vert_advance_get(const Evas_Object *obj)
816{
817 Evas_Object_Text *o;
818
819 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
820 return 0;
821 MAGIC_CHECK_END();
822 o = (Evas_Object_Text *)(obj->object_data);
823 MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
824 return 0;
825 MAGIC_CHECK_END();
826 if (!o->font) return 0;
827 if (!o->items) return o->ascent + o->descent;
828 return _evas_object_text_vert_advance_get(obj, o);
829}
830
831EAPI Eina_Bool
832evas_object_text_char_pos_get(const Evas_Object *obj, int pos, Evas_Coord *cx, Evas_Coord *cy, Evas_Coord *cw, Evas_Coord *ch)
833{
834 Evas_Object_Text *o;
835 int l = 0, r = 0, t = 0, b = 0;
836 int ret, x = 0, y = 0, w = 0, h = 0;
837
838 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
839 return EINA_FALSE;
840 MAGIC_CHECK_END();
841 o = (Evas_Object_Text *)(obj->object_data);
842 MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
843 return EINA_FALSE;
844 MAGIC_CHECK_END();
845 if (!o->font) return EINA_FALSE;
846 if (!o->items || (pos < 0)) return EINA_FALSE;
847 ret = _evas_object_text_char_coords_get(obj, o, (size_t) pos,
848 &x, &y, &w, &h);
849 evas_text_style_pad_get(o->cur.style, &l, &r, &t, &b);
850 y += o->max_ascent - t;
851 x -= l;
852 if (x < 0)
853 {
854 w += x;
855 x = 0;
856 }
857 if ((x + w) > obj->cur.geometry.w) w = obj->cur.geometry.w - x;
858 if (w < 0) w = 0;
859 if (y < 0)
860 {
861 h += y;
862 y = 0;
863 }
864 if ((y + h) > obj->cur.geometry.h) h = obj->cur.geometry.h - y;
865 if (h < 0) h = 0;
866 if (cx) *cx = x;
867 if (cy) *cy = y;
868 if (cw) *cw = w + l + r;
869 if (ch) *ch = h + t + b;
870 return ret;
871}
872
873
874EAPI int
875evas_object_text_last_up_to_pos(const Evas_Object *obj, Evas_Coord x, Evas_Coord y)
876{
877 Evas_Object_Text *o;
878
879 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
880 return -1;
881 MAGIC_CHECK_END();
882 o = (Evas_Object_Text *)(obj->object_data);
883 MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
884 return -1;
885 MAGIC_CHECK_END();
886 if (!o->font) return -1;
887 if (!o->items) return -1;
888 return _evas_object_text_last_up_to_pos(obj, o, x, y - o->max_ascent);
889}
890
891EAPI int
892evas_object_text_char_coords_get(const Evas_Object *obj, Evas_Coord x, Evas_Coord y, Evas_Coord *cx, Evas_Coord *cy, Evas_Coord *cw, Evas_Coord *ch)
893{
894 Evas_Object_Text *o;
895 int l = 0, r = 0, t = 0, b = 0;
896 int ret, rx = 0, ry = 0, rw = 0, rh = 0;
897
898 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
899 return -1;
900 MAGIC_CHECK_END();
901 o = (Evas_Object_Text *)(obj->object_data);
902 MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
903 return -1;
904 MAGIC_CHECK_END();
905 if (!o->font) return -1;
906 if (!o->items) return -1;
907 ret = _evas_object_text_char_at_coords(obj, o, x, y - o->max_ascent,
908 &rx, &ry, &rw, &rh);
909 evas_text_style_pad_get(o->cur.style, &l, &r, &t, &b);
910 ry += o->max_ascent - t;
911 rx -= l;
912 if (rx < 0)
913 {
914 rw += rx;
915 rx = 0;
916 }
917 if ((rx + rw) > obj->cur.geometry.w) rw = obj->cur.geometry.w - rx;
918 if (rw < 0) rw = 0;
919 if (ry < 0)
920 {
921 rh += ry;
922 ry = 0;
923 }
924 if ((ry + rh) > obj->cur.geometry.h) rh = obj->cur.geometry.h - ry;
925 if (rh < 0) rh = 0;
926 if (cx) *cx = rx;
927 if (cy) *cy = ry;
928 if (cw) *cw = rw + l + r;
929 if (ch) *ch = rh + t + b;
930 return ret;
931}
932
933EAPI void
934evas_object_text_style_set(Evas_Object *obj, Evas_Text_Style_Type style)
935{
936 Evas_Object_Text *o;
937 int pl = 0, pr = 0, pt = 0, pb = 0, l = 0, r = 0, t = 0, b = 0;
938
939 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
940 return;
941 MAGIC_CHECK_END();
942 o = (Evas_Object_Text *)(obj->object_data);
943 MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
944 return;
945 MAGIC_CHECK_END();
946 if (o->cur.style == style) return;
947 evas_text_style_pad_get(o->cur.style, &pl, &pr, &pt, &pb);
948 o->cur.style = style;
949 evas_text_style_pad_get(o->cur.style, &l, &r, &t, &b);
950 if (o->items)
951 obj->cur.geometry.w += (l - pl) + (r - pr);
952 else
953 obj->cur.geometry.w = 0;
954 obj->cur.geometry.h += (t - pt) + (b - pb);
955 evas_object_change(obj);
956 evas_object_clip_dirty(obj);
957}
958
959EAPI Evas_Text_Style_Type
960evas_object_text_style_get(const Evas_Object *obj)
961{
962 Evas_Object_Text *o;
963
964 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
965 return EVAS_TEXT_STYLE_PLAIN;
966 MAGIC_CHECK_END();
967 o = (Evas_Object_Text *)(obj->object_data);
968 MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
969 return EVAS_TEXT_STYLE_PLAIN;
970 MAGIC_CHECK_END();
971 return o->cur.style;
972}
973
974EAPI void
975evas_object_text_shadow_color_set(Evas_Object *obj, int r, int g, int b, int a)
976{
977 Evas_Object_Text *o;
978
979 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
980 return;
981 MAGIC_CHECK_END();
982 o = (Evas_Object_Text *)(obj->object_data);
983 MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
984 return;
985 MAGIC_CHECK_END();
986 if ((o->cur.shadow.r == r) && (o->cur.shadow.g == g) &&
987 (o->cur.shadow.b == b) && (o->cur.shadow.a == a))
988 return;
989 o->cur.shadow.r = r;
990 o->cur.shadow.g = g;
991 o->cur.shadow.b = b;
992 o->cur.shadow.a = a;
993 o->changed = 1;
994 evas_object_change(obj);
995}
996
997EAPI void
998evas_object_text_shadow_color_get(const Evas_Object *obj, int *r, int *g, int *b, int *a)
999{
1000 Evas_Object_Text *o;
1001
1002 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1003 if (r) *r = 0;
1004 if (g) *g = 0;
1005 if (b) *b = 0;
1006 if (a) *a = 0;
1007 return;
1008 MAGIC_CHECK_END();
1009 o = (Evas_Object_Text *)(obj->object_data);
1010 MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
1011 if (r) *r = 0;
1012 if (g) *g = 0;
1013 if (b) *b = 0;
1014 if (a) *a = 0;
1015 return;
1016 MAGIC_CHECK_END();
1017 if (r) *r = o->cur.shadow.r;
1018 if (g) *g = o->cur.shadow.g;
1019 if (b) *b = o->cur.shadow.b;
1020 if (a) *a = o->cur.shadow.a;
1021}
1022
1023EAPI void
1024evas_object_text_glow_color_set(Evas_Object *obj, int r, int g, int b, int a)
1025{
1026 Evas_Object_Text *o;
1027
1028 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1029 return;
1030 MAGIC_CHECK_END();
1031 o = (Evas_Object_Text *)(obj->object_data);
1032 MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
1033 return;
1034 MAGIC_CHECK_END();
1035 if ((o->cur.glow.r == r) && (o->cur.glow.g == g) &&
1036 (o->cur.glow.b == b) && (o->cur.glow.a == a))
1037 return;
1038 o->cur.glow.r = r;
1039 o->cur.glow.g = g;
1040 o->cur.glow.b = b;
1041 o->cur.glow.a = a;
1042 o->changed = 1;
1043 evas_object_change(obj);
1044}
1045
1046EAPI void
1047evas_object_text_glow_color_get(const Evas_Object *obj, int *r, int *g, int *b, int *a)
1048{
1049 Evas_Object_Text *o;
1050
1051 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1052 if (r) *r = 0;
1053 if (g) *g = 0;
1054 if (b) *b = 0;
1055 if (a) *a = 0;
1056 return;
1057 MAGIC_CHECK_END();
1058 o = (Evas_Object_Text *)(obj->object_data);
1059 MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
1060 if (r) *r = 0;
1061 if (g) *g = 0;
1062 if (b) *b = 0;
1063 if (a) *a = 0;
1064 return;
1065 MAGIC_CHECK_END();
1066 if (r) *r = o->cur.glow.r;
1067 if (g) *g = o->cur.glow.g;
1068 if (b) *b = o->cur.glow.b;
1069 if (a) *a = o->cur.glow.a;
1070}
1071
1072EAPI void
1073evas_object_text_glow2_color_set(Evas_Object *obj, int r, int g, int b, int a)
1074{
1075 Evas_Object_Text *o;
1076
1077 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1078 return;
1079 MAGIC_CHECK_END();
1080 o = (Evas_Object_Text *)(obj->object_data);
1081 MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
1082 return;
1083 MAGIC_CHECK_END();
1084 if ((o->cur.glow2.r == r) && (o->cur.glow2.g == g) &&
1085 (o->cur.glow2.b == b) && (o->cur.glow2.a == a))
1086 return;
1087 o->cur.glow2.r = r;
1088 o->cur.glow2.g = g;
1089 o->cur.glow2.b = b;
1090 o->cur.glow2.a = a;
1091 o->changed = 1;
1092 evas_object_change(obj);
1093}
1094
1095EAPI void
1096evas_object_text_glow2_color_get(const Evas_Object *obj, int *r, int *g, int *b, int *a)
1097{
1098 Evas_Object_Text *o;
1099
1100 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1101 if (r) *r = 0;
1102 if (g) *g = 0;
1103 if (b) *b = 0;
1104 if (a) *a = 0;
1105 return;
1106 MAGIC_CHECK_END();
1107 o = (Evas_Object_Text *)(obj->object_data);
1108 MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
1109 if (r) *r = 0;
1110 if (g) *g = 0;
1111 if (b) *b = 0;
1112 if (a) *a = 0;
1113 return;
1114 MAGIC_CHECK_END();
1115 if (r) *r = o->cur.glow2.r;
1116 if (g) *g = o->cur.glow2.g;
1117 if (b) *b = o->cur.glow2.b;
1118 if (a) *a = o->cur.glow2.a;
1119}
1120
1121EAPI void
1122evas_object_text_outline_color_set(Evas_Object *obj, int r, int g, int b, int a)
1123{
1124 Evas_Object_Text *o;
1125
1126 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1127 return;
1128 MAGIC_CHECK_END();
1129 o = (Evas_Object_Text *)(obj->object_data);
1130 MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
1131 return;
1132 MAGIC_CHECK_END();
1133 if ((o->cur.outline.r == r) && (o->cur.outline.g == g) &&
1134 (o->cur.outline.b == b) && (o->cur.outline.a == a))
1135 return;
1136 o->cur.outline.r = r;
1137 o->cur.outline.g = g;
1138 o->cur.outline.b = b;
1139 o->cur.outline.a = a;
1140 o->changed = 1;
1141 evas_object_change(obj);
1142}
1143
1144EAPI void
1145evas_object_text_outline_color_get(const Evas_Object *obj, int *r, int *g, int *b, int *a)
1146{
1147 Evas_Object_Text *o;
1148
1149 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1150 if (r) *r = 0;
1151 if (g) *g = 0;
1152 if (b) *b = 0;
1153 if (a) *a = 0;
1154 return;
1155 MAGIC_CHECK_END();
1156 o = (Evas_Object_Text *)(obj->object_data);
1157 MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
1158 if (r) *r = 0;
1159 if (g) *g = 0;
1160 if (b) *b = 0;
1161 if (a) *a = 0;
1162 return;
1163 MAGIC_CHECK_END();
1164 if (r) *r = o->cur.outline.r;
1165 if (g) *g = o->cur.outline.g;
1166 if (b) *b = o->cur.outline.b;
1167 if (a) *a = o->cur.outline.a;
1168}
1169
1170EAPI void
1171evas_object_text_style_pad_get(const Evas_Object *obj, int *l, int *r, int *t, int *b)
1172{
1173 int sl = 0, sr = 0, st = 0, sb = 0;
1174 Evas_Object_Text *o;
1175
1176 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1177 if (l) *l = 0;
1178 if (r) *r = 0;
1179 if (t) *t = 0;
1180 if (b) *b = 0;
1181 return;
1182 MAGIC_CHECK_END();
1183 o = (Evas_Object_Text *)(obj->object_data);
1184 MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
1185 if (l) *l = 0;
1186 if (r) *r = 0;
1187 if (t) *t = 0;
1188 if (b) *b = 0;
1189 return;
1190 MAGIC_CHECK_END();
1191 /* use temps to be certain we have initialized values */
1192 evas_text_style_pad_get(o->cur.style, &sl, &sr, &st, &sb);
1193 if (l) *l = sl;
1194 if (r) *r = sr;
1195 if (t) *t = st;
1196 if (b) *b = sb;
1197}
1198
1199
1200
1201
1202EAPI int
1203evas_string_char_next_get(const char *str, int pos, int *decoded)
1204{
1205 int p, d;
1206
1207 if (decoded) *decoded = 0;
1208 if ((!str) || (pos < 0)) return 0;
1209 p = pos;
1210 d = eina_unicode_utf8_get_next(str, &p);
1211 if (decoded) *decoded = d;
1212 return p;
1213}
1214
1215EAPI int
1216evas_string_char_prev_get(const char *str, int pos, int *decoded)
1217{
1218 int p, d;
1219
1220 if (decoded) *decoded = 0;
1221 if ((!str) || (pos < 1)) return 0;
1222 p = pos;
1223 d = eina_unicode_utf8_get_prev(str, &p);
1224 if (decoded) *decoded = d;
1225 return p;
1226}
1227
1228EAPI int
1229evas_string_char_len_get(const char *str)
1230{
1231 if (!str) return 0;
1232 return eina_unicode_utf8_get_len(str);
1233}
1234
1235void
1236evas_text_style_pad_get(Evas_Text_Style_Type style, int *l, int *r, int *t, int *b)
1237{
1238 int sl = 0, sr = 0, st = 0, sb = 0;
1239
1240 /* Don't calc anything if there's no style. */
1241 if (style != EVAS_TEXT_STYLE_PLAIN)
1242 {
1243 int shad_sz = 0, shad_dst = 0, out_sz = 0;
1244 int dx = 0, minx = 0, maxx = 0;
1245 int dy = 0, miny = 0, maxy = 0;
1246 Eina_Bool have_shadow = EINA_FALSE;
1247
1248 switch (style & EVAS_TEXT_STYLE_MASK_BASIC)
1249 {
1250 case EVAS_TEXT_STYLE_SHADOW:
1251 shad_dst = 1;
1252 have_shadow = EINA_TRUE;
1253 break;
1254 case EVAS_TEXT_STYLE_OUTLINE_SHADOW:
1255 case EVAS_TEXT_STYLE_FAR_SHADOW:
1256 shad_dst = 2;
1257 out_sz = 1;
1258 have_shadow = EINA_TRUE;
1259 break;
1260 case EVAS_TEXT_STYLE_OUTLINE_SOFT_SHADOW:
1261 shad_dst = 1;
1262 shad_sz = 2;
1263 out_sz = 1;
1264 have_shadow = EINA_TRUE;
1265 break;
1266 case EVAS_TEXT_STYLE_FAR_SOFT_SHADOW:
1267 shad_dst = 2;
1268 shad_sz = 2;
1269 have_shadow = EINA_TRUE;
1270 break;
1271 case EVAS_TEXT_STYLE_SOFT_SHADOW:
1272 shad_dst = 1;
1273 shad_sz = 2;
1274 have_shadow = EINA_TRUE;
1275 break;
1276 case EVAS_TEXT_STYLE_GLOW:
1277 case EVAS_TEXT_STYLE_SOFT_OUTLINE:
1278 out_sz = 2;
1279 break;
1280 case EVAS_TEXT_STYLE_OUTLINE:
1281 out_sz = 1;
1282 break;
1283 default:
1284 break;
1285 }
1286
1287 minx = -out_sz;
1288 maxx = out_sz;
1289 miny = -out_sz;
1290 maxy = out_sz;
1291 if (have_shadow)
1292 {
1293 int shx1, shx2, shy1, shy2;
1294 switch (style & EVAS_TEXT_STYLE_MASK_SHADOW_DIRECTION)
1295 {
1296 case EVAS_TEXT_STYLE_SHADOW_DIRECTION_BOTTOM_RIGHT:
1297 dx = 1;
1298 dy = 1;
1299 break;
1300 case EVAS_TEXT_STYLE_SHADOW_DIRECTION_BOTTOM:
1301 dx = 0;
1302 dy = 1;
1303 break;
1304 case EVAS_TEXT_STYLE_SHADOW_DIRECTION_BOTTOM_LEFT:
1305 dx = -1;
1306 dy = 1;
1307 break;
1308 case EVAS_TEXT_STYLE_SHADOW_DIRECTION_LEFT:
1309 dx = -1;
1310 dy = 0;
1311 break;
1312 case EVAS_TEXT_STYLE_SHADOW_DIRECTION_TOP_LEFT:
1313 dx = -1;
1314 dy = -1;
1315 break;
1316 case EVAS_TEXT_STYLE_SHADOW_DIRECTION_TOP:
1317 dx = 0;
1318 dy = -1;
1319 break;
1320 case EVAS_TEXT_STYLE_SHADOW_DIRECTION_TOP_RIGHT:
1321 dx = 1;
1322 dy = -1;
1323 break;
1324 case EVAS_TEXT_STYLE_SHADOW_DIRECTION_RIGHT:
1325 dx = 1;
1326 dy = 0;
1327 default:
1328 break;
1329 }
1330 shx1 = dx * shad_dst;
1331 shx1 -= shad_sz;
1332 shx2 = dx * shad_dst;
1333 shx2 += shad_sz;
1334 if (shx1 < minx) minx = shx1;
1335 if (shx2 > maxx) maxx = shx2;
1336
1337 shy1 = dy * shad_dst;
1338 shy1 -= shad_sz;
1339 shy2 = dy * shad_dst;
1340 shy2 += shad_sz;
1341 if (shy1 < miny) miny = shy1;
1342 if (shy2 > maxy) maxy = shy2;
1343 }
1344
1345 if (l) sl = *l;
1346 if (r) sr = *r;
1347 if (t) st = *t;
1348 if (b) sb = *b;
1349
1350 if (sr < maxx) sr = maxx;
1351 if (sl < -minx) sl = -minx;
1352 if (sb < maxy) sb = maxy;
1353 if (st < -miny) st = -miny;
1354 }
1355
1356 if (l) *l = sl;
1357 if (r) *r = sr;
1358 if (t) *t = st;
1359 if (b) *b = sb;
1360}
1361
1362/* all nice and private */
1363static void
1364evas_object_text_init(Evas_Object *obj)
1365{
1366 /* alloc text ob, setup methods and default values */
1367 obj->object_data = evas_object_text_new();
1368 /* set up default settings for this kind of object */
1369 obj->cur.color.r = 255;
1370 obj->cur.color.g = 255;
1371 obj->cur.color.b = 255;
1372 obj->cur.color.a = 255;
1373 obj->cur.geometry.x = 0;
1374 obj->cur.geometry.y = 0;
1375 obj->cur.geometry.w = 0;
1376 obj->cur.geometry.h = 0;
1377 obj->cur.layer = 0;
1378 /* set up object-specific settings */
1379 obj->prev = obj->cur;
1380 /* set up methods (compulsory) */
1381 obj->func = &object_func;
1382 obj->type = o_type;
1383}
1384
1385static void *
1386evas_object_text_new(void)
1387{
1388 Evas_Object_Text *o;
1389
1390 /* alloc obj private data */
1391 EVAS_MEMPOOL_INIT(_mp_obj, "evas_object_text", Evas_Object_Text, 128, NULL);
1392 o = EVAS_MEMPOOL_ALLOC(_mp_obj, Evas_Object_Text);
1393 if (!o) return NULL;
1394 EVAS_MEMPOOL_PREP(_mp_obj, o, Evas_Object_Text);
1395 o->magic = MAGIC_OBJ_TEXT;
1396 o->prev = o->cur;
1397#ifdef BIDI_SUPPORT
1398 o->bidi_par_props = evas_bidi_paragraph_props_new();
1399#endif
1400 return o;
1401}
1402
1403static void
1404evas_object_text_free(Evas_Object *obj)
1405{
1406 Evas_Object_Text *o;
1407
1408 /* frees private object data. very simple here */
1409 o = (Evas_Object_Text *)(obj->object_data);
1410 MAGIC_CHECK(o, Evas_Object_Text, MAGIC_OBJ_TEXT);
1411 return;
1412 MAGIC_CHECK_END();
1413 /* free obj */
1414 if (o->items) _evas_object_text_items_clear(o);
1415 if (o->cur.utf8_text) eina_stringshare_del(o->cur.utf8_text);
1416 if (o->cur.font) eina_stringshare_del(o->cur.font);
1417 if (o->cur.fdesc) evas_font_desc_unref(o->cur.fdesc);
1418 if (o->cur.source) eina_stringshare_del(o->cur.source);
1419 if (o->font) evas_font_free(obj->layer->evas, o->font);
1420#ifdef BIDI_SUPPORT
1421 evas_bidi_paragraph_props_unref(o->bidi_par_props);
1422#endif
1423 o->magic = 0;
1424 EVAS_MEMPOOL_FREE(_mp_obj, o);
1425}
1426
1427static void
1428evas_object_text_render(Evas_Object *obj, void *output, void *context, void *surface, int x, int y)
1429{
1430 int i, j;
1431 Evas_Object_Text *o;
1432 Evas_Object_Text_Item *it;
1433 const char vals[5][5] =
1434 {
1435 {0, 1, 2, 1, 0},
1436 {1, 3, 4, 3, 1},
1437 {2, 4, 5, 4, 2},
1438 {1, 3, 4, 3, 1},
1439 {0, 1, 2, 1, 0}
1440 };
1441 int sl = 0, st = 0;
1442 int shad_dst, shad_sz, dx, dy, haveshad;
1443
1444 /* render object to surface with context, and offxet by x,y */
1445 o = (Evas_Object_Text *)(obj->object_data);
1446 evas_text_style_pad_get(o->cur.style, &sl, NULL, &st, NULL);
1447 ENFN->context_multiplier_unset(output, context);
1448 ENFN->context_render_op_set(output, context, obj->cur.render_op);
1449 /* FIXME: This clipping is just until we fix inset handling correctly. */
1450 ENFN->context_clip_clip(output, context,
1451 obj->cur.geometry.x + x,
1452 obj->cur.geometry.y + y,
1453 obj->cur.geometry.w,
1454 obj->cur.geometry.h);
1455/*
1456 ENFN->context_color_set(output,
1457 context,
1458 230, 160, 30, 100);
1459 ENFN->rectangle_draw(output,
1460 context,
1461 surface,
1462 obj->cur.geometry.x + x,
1463 obj->cur.geometry.y + y,
1464 obj->cur.geometry.w,
1465 obj->cur.geometry.h);
1466 */
1467#define COLOR_ONLY_SET(object, sub, col) \
1468 ENFN->context_color_set(output, context, \
1469 object->sub.col.r, \
1470 object->sub.col.g, \
1471 object->sub.col.b, \
1472 object->sub.col.a);
1473
1474#define COLOR_SET(object, sub, col) \
1475 if (obj->cur.clipper)\
1476 ENFN->context_color_set(output, context, \
1477 ((int)object->sub.col.r * ((int)obj->cur.clipper->cur.cache.clip.r + 1)) >> 8, \
1478 ((int)object->sub.col.g * ((int)obj->cur.clipper->cur.cache.clip.g + 1)) >> 8, \
1479 ((int)object->sub.col.b * ((int)obj->cur.clipper->cur.cache.clip.b + 1)) >> 8, \
1480 ((int)object->sub.col.a * ((int)obj->cur.clipper->cur.cache.clip.a + 1)) >> 8); \
1481 else\
1482 ENFN->context_color_set(output, context, \
1483 object->sub.col.r, \
1484 object->sub.col.g, \
1485 object->sub.col.b, \
1486 object->sub.col.a);
1487
1488#define COLOR_SET_AMUL(object, sub, col, amul) \
1489 if (obj->cur.clipper) \
1490 ENFN->context_color_set(output, context, \
1491 (((int)object->sub.col.r) * ((int)obj->cur.clipper->cur.cache.clip.r) * (amul)) / 65025, \
1492 (((int)object->sub.col.g) * ((int)obj->cur.clipper->cur.cache.clip.g) * (amul)) / 65025, \
1493 (((int)object->sub.col.b) * ((int)obj->cur.clipper->cur.cache.clip.b) * (amul)) / 65025, \
1494 (((int)object->sub.col.a) * ((int)obj->cur.clipper->cur.cache.clip.a) * (amul)) / 65025); \
1495 else \
1496 ENFN->context_color_set(output, context, \
1497 (((int)object->sub.col.r) * (amul)) / 255, \
1498 (((int)object->sub.col.g) * (amul)) / 255, \
1499 (((int)object->sub.col.b) * (amul)) / 255, \
1500 (((int)object->sub.col.a) * (amul)) / 255);
1501
1502#define DRAW_TEXT(ox, oy) \
1503 if ((o->font) && (it->text_props.len > 0)) \
1504 ENFN->font_draw(output, \
1505 context, \
1506 surface, \
1507 o->font, \
1508 obj->cur.geometry.x + x + sl + ox + it->x, \
1509 obj->cur.geometry.y + y + st + oy + \
1510 (int) \
1511 (((o->max_ascent * obj->cur.geometry.h) / obj->cur.geometry.h) - 0.5), \
1512 obj->cur.geometry.w, \
1513 obj->cur.geometry.h, \
1514 obj->cur.geometry.w, \
1515 obj->cur.geometry.h, \
1516 &it->text_props);
1517
1518 /* shadows */
1519 shad_dst = shad_sz = dx = dy = haveshad = 0;
1520 switch (o->cur.style & EVAS_TEXT_STYLE_MASK_BASIC)
1521 {
1522 case EVAS_TEXT_STYLE_SHADOW:
1523 case EVAS_TEXT_STYLE_OUTLINE_SOFT_SHADOW:
1524 shad_dst = 1;
1525 haveshad = 1;
1526 break;
1527 case EVAS_TEXT_STYLE_OUTLINE_SHADOW:
1528 case EVAS_TEXT_STYLE_FAR_SHADOW:
1529 shad_dst = 2;
1530 haveshad = 1;
1531 break;
1532 case EVAS_TEXT_STYLE_FAR_SOFT_SHADOW:
1533 shad_dst = 2;
1534 shad_sz = 2;
1535 haveshad = 1;
1536 break;
1537 case EVAS_TEXT_STYLE_SOFT_SHADOW:
1538 shad_dst = 1;
1539 shad_sz = 2;
1540 haveshad = 1;
1541 break;
1542 default:
1543 break;
1544 }
1545 if (haveshad)
1546 {
1547 if (shad_dst > 0)
1548 {
1549 switch (o->cur.style & EVAS_TEXT_STYLE_MASK_SHADOW_DIRECTION)
1550 {
1551 case EVAS_TEXT_STYLE_SHADOW_DIRECTION_BOTTOM_RIGHT:
1552 dx = 1;
1553 dy = 1;
1554 break;
1555 case EVAS_TEXT_STYLE_SHADOW_DIRECTION_BOTTOM:
1556 dx = 0;
1557 dy = 1;
1558 break;
1559 case EVAS_TEXT_STYLE_SHADOW_DIRECTION_BOTTOM_LEFT:
1560 dx = -1;
1561 dy = 1;
1562 break;
1563 case EVAS_TEXT_STYLE_SHADOW_DIRECTION_LEFT:
1564 dx = -1;
1565 dy = 0;
1566 break;
1567 case EVAS_TEXT_STYLE_SHADOW_DIRECTION_TOP_LEFT:
1568 dx = -1;
1569 dy = -1;
1570 break;
1571 case EVAS_TEXT_STYLE_SHADOW_DIRECTION_TOP:
1572 dx = 0;
1573 dy = -1;
1574 break;
1575 case EVAS_TEXT_STYLE_SHADOW_DIRECTION_TOP_RIGHT:
1576 dx = 1;
1577 dy = -1;
1578 break;
1579 case EVAS_TEXT_STYLE_SHADOW_DIRECTION_RIGHT:
1580 dx = 1;
1581 dy = 0;
1582 default:
1583 break;
1584 }
1585 dx *= shad_dst;
1586 dy *= shad_dst;
1587 }
1588 }
1589 EINA_INLIST_FOREACH(EINA_INLIST_GET(o->items), it)
1590 {
1591 /* Shadows */
1592 if (haveshad)
1593 {
1594 switch (shad_sz)
1595 {
1596 case 0:
1597 COLOR_SET(o, cur, shadow);
1598 DRAW_TEXT(dx, dy);
1599 break;
1600 case 2:
1601 for (j = 0; j < 5; j++)
1602 {
1603 for (i = 0; i < 5; i++)
1604 {
1605 if (vals[i][j] != 0)
1606 {
1607 COLOR_SET_AMUL(o, cur, shadow, vals[i][j] * 50);
1608 DRAW_TEXT(i - 2 + dx, j - 2 + dy);
1609 }
1610 }
1611 }
1612 break;
1613 default:
1614 break;
1615 }
1616 }
1617
1618 /* glows */
1619 if (o->cur.style == EVAS_TEXT_STYLE_GLOW)
1620 {
1621 for (j = 0; j < 5; j++)
1622 {
1623 for (i = 0; i < 5; i++)
1624 {
1625 if (vals[i][j] != 0)
1626 {
1627 COLOR_SET_AMUL(o, cur, glow, vals[i][j] * 50);
1628 DRAW_TEXT(i - 2, j - 2);
1629 }
1630 }
1631 }
1632 COLOR_SET(o, cur, glow2);
1633 DRAW_TEXT(-1, 0);
1634 DRAW_TEXT(1, 0);
1635 DRAW_TEXT(0, -1);
1636 DRAW_TEXT(0, 1);
1637 }
1638
1639 /* outlines */
1640 if ((o->cur.style == EVAS_TEXT_STYLE_OUTLINE) ||
1641 (o->cur.style == EVAS_TEXT_STYLE_OUTLINE_SHADOW) ||
1642 (o->cur.style == EVAS_TEXT_STYLE_OUTLINE_SOFT_SHADOW))
1643 {
1644 COLOR_SET(o, cur, outline);
1645 DRAW_TEXT(-1, 0);
1646 DRAW_TEXT(1, 0);
1647 DRAW_TEXT(0, -1);
1648 DRAW_TEXT(0, 1);
1649 }
1650 else if (o->cur.style == EVAS_TEXT_STYLE_SOFT_OUTLINE)
1651 {
1652 for (j = 0; j < 5; j++)
1653 {
1654 for (i = 0; i < 5; i++)
1655 {
1656 if (((i != 2) || (j != 2)) && (vals[i][j] != 0))
1657 {
1658 COLOR_SET_AMUL(o, cur, outline, vals[i][j] * 50);
1659 DRAW_TEXT(i - 2, j - 2);
1660 }
1661 }
1662 }
1663 }
1664
1665 /* normal text */
1666 COLOR_ONLY_SET(obj, cur.cache, clip);
1667 DRAW_TEXT(0, 0);
1668 }
1669}
1670
1671static void
1672evas_object_text_render_pre(Evas_Object *obj)
1673{
1674 Evas_Object_Text *o;
1675 int is_v, was_v;
1676
1677 /* dont pre-render the obj twice! */
1678 if (obj->pre_render_done) return;
1679 obj->pre_render_done = 1;
1680 /* pre-render phase. this does anything an object needs to do just before
1681 rendering. This could mean loading the image data, retrieving it from
1682 elsewhere, decoding video etc.
1683 Then when this is done the object needs to figure if it changed and
1684 if so what and where and add the appropriate redraw rectangles */
1685 o = (Evas_Object_Text *)(obj->object_data);
1686 /* if someone is clipping this obj - go calculate the clipper */
1687 if (obj->cur.clipper)
1688 {
1689 if (obj->cur.cache.clip.dirty)
1690 evas_object_clip_recalc(obj->cur.clipper);
1691 obj->cur.clipper->func->render_pre(obj->cur.clipper);
1692 }
1693 /* now figure what changed and add draw rects
1694 if it just became visible or invisible */
1695 is_v = evas_object_is_visible(obj);
1696 was_v = evas_object_was_visible(obj);
1697 if (is_v != was_v)
1698 {
1699 evas_object_render_pre_visible_change(&obj->layer->evas->clip_changes,
1700 obj, is_v, was_v);
1701 goto done;
1702 }
1703 if ((obj->cur.map != obj->prev.map) ||
1704 (obj->cur.usemap != obj->prev.usemap))
1705 {
1706 evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes,
1707 obj);
1708 goto done;
1709 }
1710 /* its not visible - we accounted for it appearing or not so just abort */
1711 if (!is_v) goto done;
1712 /* clipper changed this is in addition to anything else for obj */
1713 evas_object_render_pre_clipper_change(&obj->layer->evas->clip_changes, obj);
1714 /* if we restacked (layer or just within a layer) and dont clip anyone */
1715 if (obj->restack)
1716 {
1717 evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes,
1718 obj);
1719 goto done;
1720 }
1721 /* if it changed color */
1722 if ((obj->cur.color.r != obj->prev.color.r) ||
1723 (obj->cur.color.g != obj->prev.color.g) ||
1724 (obj->cur.color.b != obj->prev.color.b) ||
1725 (obj->cur.color.a != obj->prev.color.a))
1726 {
1727 evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes,
1728 obj);
1729 goto done;
1730 }
1731 /* if it changed geometry - and obviously not visibility or color
1732 calculate differences since we have a constant color fill
1733 we really only need to update the differences */
1734 if ((obj->cur.geometry.x != obj->prev.geometry.x) ||
1735 (obj->cur.geometry.y != obj->prev.geometry.y) ||
1736 (obj->cur.geometry.w != obj->prev.geometry.w) ||
1737 (obj->cur.geometry.h != obj->prev.geometry.h))
1738 {
1739 evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes,
1740 obj);
1741 goto done;
1742 }
1743 if (obj->cur.render_op != obj->prev.render_op)
1744 {
1745 evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes,
1746 obj);
1747 goto done;
1748 }
1749 if (obj->cur.scale != obj->prev.scale)
1750 {
1751 evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes,
1752 obj);
1753 goto done;
1754 }
1755 if (o->changed)
1756 {
1757 if ((o->cur.size != o->prev.size) ||
1758 ((o->cur.font != o->prev.font)) ||
1759 ((o->cur.utf8_text != o->prev.utf8_text)) ||
1760 ((o->cur.style != o->prev.style)) ||
1761 ((o->cur.shadow.r != o->prev.shadow.r)) ||
1762 ((o->cur.shadow.g != o->prev.shadow.g)) ||
1763 ((o->cur.shadow.b != o->prev.shadow.b)) ||
1764 ((o->cur.shadow.a != o->prev.shadow.a)) ||
1765 ((o->cur.outline.r != o->prev.outline.r)) ||
1766 ((o->cur.outline.g != o->prev.outline.g)) ||
1767 ((o->cur.outline.b != o->prev.outline.b)) ||
1768 ((o->cur.outline.a != o->prev.outline.a)) ||
1769 ((o->cur.glow.r != o->prev.glow.r)) ||
1770 ((o->cur.glow.g != o->prev.glow.g)) ||
1771 ((o->cur.glow.b != o->prev.glow.b)) ||
1772 ((o->cur.glow.a != o->prev.glow.a)) ||
1773 ((o->cur.glow2.r != o->prev.glow2.r)) ||
1774 ((o->cur.glow2.g != o->prev.glow2.g)) ||
1775 ((o->cur.glow2.b != o->prev.glow2.b)) ||
1776 ((o->cur.glow2.a != o->prev.glow2.a)))
1777 {
1778 evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes,
1779 obj);
1780 goto done;
1781 }
1782 }
1783 done:
1784 evas_object_render_pre_effect_updates(&obj->layer->evas->clip_changes,
1785 obj, is_v, was_v);
1786}
1787
1788static void
1789evas_object_text_render_post(Evas_Object *obj)
1790{
1791 Evas_Object_Text *o;
1792
1793 /* this moves the current data to the previous state parts of the object
1794 in whatever way is safest for the object. also if we don't need object
1795 data anymore we can free it if the object deems this is a good idea */
1796 o = (Evas_Object_Text *)(obj->object_data);
1797 /* remove those pesky changes */
1798 evas_object_clip_changes_clean(obj);
1799 /* move cur to prev safely for object data */
1800 obj->prev = obj->cur;
1801 o->prev = o->cur;
1802 o->changed = 0;
1803}
1804
1805static unsigned int
1806evas_object_text_id_get(Evas_Object *obj)
1807{
1808 Evas_Object_Text *o;
1809
1810 o = (Evas_Object_Text *)(obj->object_data);
1811 if (!o) return 0;
1812 return MAGIC_OBJ_TEXT;
1813}
1814
1815static unsigned int
1816evas_object_text_visual_id_get(Evas_Object *obj)
1817{
1818 Evas_Object_Text *o;
1819
1820 o = (Evas_Object_Text *)(obj->object_data);
1821 if (!o) return 0;
1822 return MAGIC_OBJ_SHAPE;
1823}
1824
1825static void *
1826evas_object_text_engine_data_get(Evas_Object *obj)
1827{
1828 Evas_Object_Text *o;
1829
1830 o = (Evas_Object_Text *)(obj->object_data);
1831 if (!o) return NULL;
1832 return o->font;
1833}
1834
1835static int
1836evas_object_text_is_opaque(Evas_Object *obj __UNUSED__)
1837{
1838 /* this returns 1 if the internal object data implies that the object is
1839 currently fully opaque over the entire gradient it occupies */
1840 return 0;
1841}
1842
1843static int
1844evas_object_text_was_opaque(Evas_Object *obj __UNUSED__)
1845{
1846 /* this returns 1 if the internal object data implies that the object was
1847 currently fully opaque over the entire gradient it occupies */
1848 return 0;
1849}
1850
1851static void
1852evas_object_text_scale_update(Evas_Object *obj)
1853{
1854 Evas_Object_Text *o;
1855 int size;
1856 const char *font;
1857
1858 o = (Evas_Object_Text *)(obj->object_data);
1859 font = eina_stringshare_add(o->cur.font);
1860 size = o->cur.size;
1861 if (o->cur.font) eina_stringshare_del(o->cur.font);
1862 o->cur.font = NULL;
1863 o->prev.font = NULL;
1864 o->cur.size = 0;
1865 o->prev.size = 0;
1866 evas_object_text_font_set(obj, font, size);
1867}
1868
1869void
1870_evas_object_text_rehint(Evas_Object *obj)
1871{
1872 Evas_Object_Text *o;
1873 int is, was;
1874
1875 o = (Evas_Object_Text *)(obj->object_data);
1876 if (!o->font) return;
1877#ifdef EVAS_FRAME_QUEUING
1878 evas_common_pipe_op_text_flush((RGBA_Font *) o->font);
1879#endif
1880 evas_font_load_hinting_set(obj->layer->evas, o->font,
1881 obj->layer->evas->hinting);
1882 was = evas_object_is_in_output_rect(obj,
1883 obj->layer->evas->pointer.x,
1884 obj->layer->evas->pointer.y, 1, 1);
1885 /* DO II */
1886 _evas_object_text_recalc(obj);
1887 o->changed = 1;
1888 evas_object_change(obj);
1889 evas_object_clip_dirty(obj);
1890 evas_object_coords_recalc(obj);
1891 is = evas_object_is_in_output_rect(obj,
1892 obj->layer->evas->pointer.x,
1893 obj->layer->evas->pointer.y, 1, 1);
1894 if ((is || was) && obj->cur.visible)
1895 evas_event_feed_mouse_move(obj->layer->evas,
1896 obj->layer->evas->pointer.x,
1897 obj->layer->evas->pointer.y,
1898 obj->layer->evas->last_timestamp,
1899 NULL);
1900 evas_object_inform_call_resize(obj);
1901}
1902
1903static void
1904_evas_object_text_recalc(Evas_Object *obj)
1905{
1906 Evas_Object_Text *o;
1907 Eina_Unicode *text = NULL;
1908 o = (Evas_Object_Text *)(obj->object_data);
1909
1910 if (o->items) _evas_object_text_items_clear(o);
1911 if (o->cur.utf8_text)
1912 text = eina_unicode_utf8_to_unicode(o->cur.utf8_text,
1913 NULL);
1914
1915 if (!text) text = eina_unicode_strdup(EINA_UNICODE_EMPTY_STRING);
1916
1917 _evas_object_text_layout(obj, o, text);
1918
1919 if (text) free(text);
1920
1921 if ((o->font) && (o->items))
1922 {
1923 int w, h;
1924 int l = 0, r = 0, t = 0, b = 0;
1925
1926 w = _evas_object_text_horiz_advance_get(obj, o);
1927 h = _evas_object_text_vert_advance_get(obj, o);
1928 evas_text_style_pad_get(o->cur.style, &l, &r, &t, &b);
1929 obj->cur.geometry.w = w + l + r;
1930 obj->cur.geometry.h = h + t + b;
1931//// obj->cur.cache.geometry.validity = 0;
1932 }
1933 else
1934 {
1935 int t = 0, b = 0;
1936
1937 evas_text_style_pad_get(o->cur.style, NULL, NULL, &t, &b);
1938 obj->cur.geometry.w = 0;
1939 obj->cur.geometry.h = o->max_ascent + o->max_descent + t + b;
1940//// obj->cur.cache.geometry.validity = 0;
1941 }
1942}
1943
diff --git a/libraries/evas/src/lib/canvas/evas_object_textblock.c b/libraries/evas/src/lib/canvas/evas_object_textblock.c
deleted file mode 100644
index ee07e20..0000000
--- a/libraries/evas/src/lib/canvas/evas_object_textblock.c
+++ /dev/null
@@ -1,10052 +0,0 @@
1/**
2 * @internal
3 * @section Evas_Object_Textblock_Internal Internal Textblock Object Tutorial
4 *
5 * This explains the internal design of the Evas Textblock Object, it's assumed
6 * that the reader of this section has already read @ref Evas_Object_Textblock_Tutorial "Textblock's usage docs.".
7 *
8 * @subsection textblock_internal_intro Introduction
9 * There are two main parts to the textblock object, the first being the node
10 * system, and the second being the layout system. The former is just an
11 * internal representation of the markup text, while the latter is the internal
12 * visual representation of the text (i.e positioning, sizing, fonts and etc).
13 *
14 * @subsection textblock_nodes The Nodes system
15 * The nodes mechanism consists of two main data types:
16 * ::Evas_Object_Textblock_Node_Text and ::Evas_Object_Textblock_Node_Format
17 * the former is for Text nodes and the latter is for format nodes.
18 * There's always at least one text node, even if there are only formats.
19 *
20 * @subsection textblock_nodes_text Text nodes
21 * Each text node is essentially a paragraph, it includes an @ref Eina_UStrbuf
22 * that stores the actual paragraph text, a utf8 string to store the paragraph
23 * text in utf8 (which is not used internally at all), A pointer to it's
24 * main @ref textblock_nodes_format_internal "Format Node" and the paragraph's
25 * @ref evas_bidi_props "BiDi properties". The pointer to the format node may be
26 * NULL if there's no format node anywhere before the end of the text node,
27 * not even in previous text nodes. If not NULL, it points to the first format
28 * node pointing to text inside of the text node, or if there is none, it points
29 * to the previous's text nodes format node. Each paragraph has a format node
30 * representing a paragraph separator pointing to it's last position except
31 * for the last paragraph, which has no such constraint. This constraint
32 * happens because text nodes are paragraphs and paragraphs are delimited by
33 * paragraph separators.
34 *
35 * @subsection textblock_nodes_format_internal Format Nodes - Internal
36 * Each format node stores a group of format information, for example the
37 * markup: \<font=Vera,Kochi font_size=10 align=left\> will all be inserted
38 * inside the same format node, altohugh it consists of different formatting
39 * commands.
40 * Each node has a pointer to it's text node, this pointer is NEVER NULL, even
41 * if there's only one format, and no text, a text node is created. Each format
42 * node includes an offset from the last format node of the same text node. For
43 * example, the markup "0<b>12</b>" will create two format nodes, the first
44 * having an offset of 1 and the second an offset of 2. Each format node also
45 * includes a @ref Eina_Strbuf that includes the textual representation of the
46 * format, and a boolean stating if the format is a visible format or not, see
47 * @ref textblock_nodes_format_visible
48 *
49 * @subsection textblock_nodes_format_visible Visible Format Nodes
50 * There are two types of format nodes, visible and invisible. They are the same
51 * in every way, except for the representation in the text node. While invisible
52 * format nodes have no representation in the text node, the visible ones do.
53 * The Uniceode object replacement character (0xFFFC) is inserted to every place
54 * a visible format node points to. This makes it very easy to treat visible
55 * formats as items in the text, both for BiDi purposes and cursor handling
56 * purposes.
57 * Here are a few example visible an invisible formats:
58 * Visible: newline char, tab, paragraph separator and an embedded item.
59 * Invisible: setting the color, font or alignment of the text.
60 *
61 * @subsection textblock_layout The layout system
62 * @todo write @ref textblock_layout
63 */
64#include "evas_common.h"
65#include "evas_private.h"
66#include <stdlib.h>
67
68#ifdef HAVE_LINEBREAK
69#include "linebreak.h"
70#include "wordbreak.h"
71#endif
72
73/* save typing */
74#define ENFN obj->layer->evas->engine.func
75#define ENDT obj->layer->evas->engine.data.output
76
77/* private magic number for textblock objects */
78static const char o_type[] = "textblock";
79
80/* The char to be inserted instead of visible formats */
81#define _REPLACEMENT_CHAR 0xFFFC
82#define _PARAGRAPH_SEPARATOR 0x2029
83#define _NEWLINE '\n'
84#define _TAB '\t'
85
86#define _REPLACEMENT_CHAR_UTF8 "\xEF\xBF\xBC"
87#define _PARAGRAPH_SEPARATOR_UTF8 "\xE2\x80\xA9"
88#define _NEWLINE_UTF8 "\n"
89#define _TAB_UTF8 "\t"
90#define EVAS_TEXTBLOCK_IS_VISIBLE_FORMAT_CHAR(ch) \
91 (((ch) == _REPLACEMENT_CHAR) || \
92 ((ch) == _NEWLINE) || \
93 ((ch) == _TAB) || \
94 ((ch) == _PARAGRAPH_SEPARATOR))
95
96/* private struct for textblock object internal data */
97/**
98 * @internal
99 * @typedef Evas_Object_Textblock
100 * The actual textblock object.
101 */
102typedef struct _Evas_Object_Textblock Evas_Object_Textblock;
103/**
104 * @internal
105 * @typedef Evas_Object_Style_Tag
106 * The structure used for finding style tags.
107 */
108typedef struct _Evas_Object_Style_Tag Evas_Object_Style_Tag;
109/**
110 * @internal
111 * @typedef Evas_Object_Style_Tag
112 * The structure used for finding style tags.
113 */
114typedef struct _Evas_Object_Style_Tag_Base Evas_Object_Style_Tag_Base;
115/**
116 * @internal
117 * @typedef Evas_Object_Textblock_Node_Text
118 * A text node.
119 */
120typedef struct _Evas_Object_Textblock_Node_Text Evas_Object_Textblock_Node_Text;
121/*
122 * Defined in Evas.h
123typedef struct _Evas_Object_Textblock_Node_Format Evas_Object_Textblock_Node_Format;
124*/
125
126/**
127 * @internal
128 * @typedef Evas_Object_Textblock_Paragraph
129 * A layouting paragraph.
130 */
131typedef struct _Evas_Object_Textblock_Paragraph Evas_Object_Textblock_Paragraph;
132/**
133 * @internal
134 * @typedef Evas_Object_Textblock_Line
135 * A layouting line.
136 */
137typedef struct _Evas_Object_Textblock_Line Evas_Object_Textblock_Line;
138/**
139 * @internal
140 * @typedef Evas_Object_Textblock_Item
141 * A layouting item.
142 */
143typedef struct _Evas_Object_Textblock_Item Evas_Object_Textblock_Item;
144/**
145 * @internal
146 * @typedef Evas_Object_Textblock_Item
147 * A layouting text item.
148 */
149typedef struct _Evas_Object_Textblock_Text_Item Evas_Object_Textblock_Text_Item;
150/**
151 * @internal
152 * @typedef Evas_Object_Textblock_Format_Item
153 * A layouting format item.
154 */
155typedef struct _Evas_Object_Textblock_Format_Item Evas_Object_Textblock_Format_Item;
156/**
157 * @internal
158 * @typedef Evas_Object_Textblock_Format
159 * A textblock format.
160 */
161typedef struct _Evas_Object_Textblock_Format Evas_Object_Textblock_Format;
162
163/**
164 * @internal
165 * @def IS_AT_END(ti, ind)
166 * Return true if ind is at the end of the text item, false otherwise.
167 */
168#define IS_AT_END(ti, ind) (ind == ti->text_props.text_len)
169
170/**
171 * @internal
172 * @def MOVE_PREV_UNTIL(limit, ind)
173 * This decrements ind as long as ind > limit.
174 */
175#define MOVE_PREV_UNTIL(limit, ind) \
176 do \
177 { \
178 if ((limit) < (ind)) \
179 (ind)--; \
180 } \
181 while (0)
182
183/**
184 * @internal
185 * @def MOVE_NEXT_UNTIL(limit, ind)
186 * This increments ind as long as ind < limit
187 */
188#define MOVE_NEXT_UNTIL(limit, ind) \
189 do \
190 { \
191 if ((ind) < (limit)) \
192 (ind)++; \
193 } \
194 while (0)
195
196/**
197 * @internal
198 * @def GET_ITEM_TEXT(ti)
199 * Returns a const reference to the text of the ti (not null terminated).
200 */
201#define GET_ITEM_TEXT(ti) \
202 (((ti)->parent.text_node) ? \
203 (eina_ustrbuf_string_get((ti)->parent.text_node->unicode) + \
204 (ti)->parent.text_pos) : EINA_UNICODE_EMPTY_STRING)
205/**
206 * @internal
207 * @def _FORMAT_IS_CLOSER_OF(base, closer, closer_len)
208 * Returns true if closer is the closer of base.
209 */
210#define _FORMAT_IS_CLOSER_OF(base, closer, closer_len) \
211 (!strncmp(base, closer, closer_len) && \
212 (!base[closer_len] || \
213 (base[closer_len] == '=') || \
214 _is_white(base[closer_len])))
215
216/*FIXME: document the structs and struct items. */
217struct _Evas_Object_Style_Tag_Base
218{
219 char *tag;
220 char *replace;
221 size_t tag_len;
222 size_t replace_len;
223};
224
225struct _Evas_Object_Style_Tag
226{
227 EINA_INLIST;
228 Evas_Object_Style_Tag_Base tag;
229};
230
231struct _Evas_Object_Textblock_Node_Text
232{
233 EINA_INLIST;
234 Eina_UStrbuf *unicode;
235 char *utf8;
236 Evas_Object_Textblock_Node_Format *format_node;
237 Evas_Object_Textblock_Paragraph *par;
238 Eina_Bool dirty : 1;
239 Eina_Bool is_new : 1;
240};
241
242struct _Evas_Object_Textblock_Node_Format
243{
244 EINA_INLIST;
245 const char *format;
246 const char *orig_format;
247 Evas_Object_Textblock_Node_Text *text_node;
248 size_t offset;
249 unsigned char anchor : 2;
250 Eina_Bool opener : 1;
251 Eina_Bool own_closer : 1;
252 Eina_Bool visible : 1;
253 Eina_Bool format_change : 1;
254 Eina_Bool is_new : 1;
255};
256
257/* The default tags to use */
258static const Evas_Object_Style_Tag_Base default_tags[] = {
259 { "b", "+ font_weight=Bold", 1, 18 },
260 { "i", "+ font_style=Italic", 1, 19 }};
261
262#define ANCHOR_NONE 0
263#define ANCHOR_A 1
264#define ANCHOR_ITEM 2
265
266/**
267 * @internal
268 * @def _NODE_TEXT(x)
269 * A convinience macro for casting to a text node.
270 */
271#define _NODE_TEXT(x) ((Evas_Object_Textblock_Node_Text *) (x))
272/**
273 * @internal
274 * @def _NODE_FORMAT(x)
275 * A convinience macro for casting to a format node.
276 */
277#define _NODE_FORMAT(x) ((Evas_Object_Textblock_Node_Format *) (x))
278/**
279 * @internal
280 * @def _ITEM(x)
281 * A convinience macro for casting to a generic item.
282 */
283#define _ITEM(x) ((Evas_Object_Textblock_Item *) (x))
284/**
285 * @internal
286 * @def _ITEM_TEXT(x)
287 * A convinience macro for casting to a text item.
288 */
289#define _ITEM_TEXT(x) ((Evas_Object_Textblock_Text_Item *) (x))
290/**
291 * @internal
292 * @def _ITEM_FORMAT(x)
293 * A convinience macro for casting to a format item.
294 */
295#define _ITEM_FORMAT(x) ((Evas_Object_Textblock_Format_Item *) (x))
296
297struct _Evas_Object_Textblock_Paragraph
298{
299 EINA_INLIST;
300 Evas_Object_Textblock_Line *lines;
301 Evas_Object_Textblock_Node_Text *text_node;
302 Eina_List *logical_items;
303 Evas_BiDi_Paragraph_Props *bidi_props; /* Only valid during layout */
304 Evas_BiDi_Direction direction;
305 Evas_Coord y, w, h;
306 int line_no;
307 Eina_Bool is_bidi : 1;
308 Eina_Bool visible : 1;
309 Eina_Bool rendered : 1;
310};
311
312struct _Evas_Object_Textblock_Line
313{
314 EINA_INLIST;
315 Evas_Object_Textblock_Item *items;
316 Evas_Object_Textblock_Paragraph *par;
317 Evas_Coord x, y, w, h;
318 int baseline;
319 int line_no;
320};
321
322typedef enum _Evas_Textblock_Item_Type
323{
324 EVAS_TEXTBLOCK_ITEM_TEXT,
325 EVAS_TEXTBLOCK_ITEM_FORMAT,
326} Evas_Textblock_Item_Type;
327
328struct _Evas_Object_Textblock_Item
329{
330 EINA_INLIST;
331 Evas_Textblock_Item_Type type;
332 Evas_Object_Textblock_Node_Text *text_node;
333 Evas_Object_Textblock_Format *format;
334 size_t text_pos;
335#ifdef BIDI_SUPPORT
336 size_t visual_pos;
337#endif
338 Evas_Coord adv, x, w, h;
339 Eina_Bool merge : 1; /* Indicates whether this
340 item should merge to the
341 previous item or not */
342 Eina_Bool visually_deleted : 1;
343 /* Indicates whether this
344 item is used in the visual
345 layout or not. */
346};
347
348struct _Evas_Object_Textblock_Text_Item
349{
350 Evas_Object_Textblock_Item parent;
351 Evas_Text_Props text_props;
352 Evas_Coord inset;
353 Evas_Coord x_adjustment; /* Used to indicate by how
354 much we adjusted sizes */
355};
356
357struct _Evas_Object_Textblock_Format_Item
358{
359 Evas_Object_Textblock_Item parent;
360 Evas_BiDi_Direction bidi_dir;
361 const char *item;
362 int y;
363 unsigned char vsize : 2;
364 unsigned char size : 2;
365 Eina_Bool formatme : 1;
366};
367
368struct _Evas_Object_Textblock_Format
369{
370 Evas_Object_Textblock_Node_Format *fnode;
371 double halign;
372 double valign;
373 struct {
374 Evas_Font_Description *fdesc;
375 const char *source;
376 Evas_Font_Set *font;
377 Evas_Font_Size size;
378 } font;
379 struct {
380 struct {
381 unsigned char r, g, b, a;
382 } normal, underline, underline2, underline_dash, outline, shadow, glow, glow2, backing,
383 strikethrough;
384 } color;
385 struct {
386 int l, r;
387 } margin;
388 int ref;
389 int tabstops;
390 int linesize;
391 int linegap;
392 int underline_dash_width;
393 int underline_dash_gap;
394 double linerelsize;
395 double linerelgap;
396 double linefill;
397 double ellipsis;
398 unsigned char style;
399 Eina_Bool wrap_word : 1;
400 Eina_Bool wrap_char : 1;
401 Eina_Bool wrap_mixed : 1;
402 Eina_Bool underline : 1;
403 Eina_Bool underline2 : 1;
404 Eina_Bool underline_dash : 1;
405 Eina_Bool strikethrough : 1;
406 Eina_Bool backing : 1;
407 Eina_Bool password : 1;
408 Eina_Bool halign_auto : 1;
409};
410
411struct _Evas_Textblock_Style
412{
413 const char *style_text;
414 char *default_tag;
415 Evas_Object_Style_Tag *tags;
416 Eina_List *objects;
417 Eina_Bool delete_me : 1;
418};
419
420struct _Evas_Textblock_Cursor
421{
422 Evas_Object *obj;
423 size_t pos;
424 Evas_Object_Textblock_Node_Text *node;
425};
426
427/* Size of the index array */
428#define TEXTBLOCK_PAR_INDEX_SIZE 10
429struct _Evas_Object_Textblock
430{
431 DATA32 magic;
432 Evas_Textblock_Style *style;
433 Evas_Textblock_Style *style_user;
434 Evas_Textblock_Cursor *cursor;
435 Eina_List *cursors;
436 Evas_Object_Textblock_Node_Text *text_nodes;
437 Evas_Object_Textblock_Node_Format *format_nodes;
438
439 int num_paragraphs;
440 Evas_Object_Textblock_Paragraph *paragraphs;
441 Evas_Object_Textblock_Paragraph *par_index[TEXTBLOCK_PAR_INDEX_SIZE];
442
443 Evas_Object_Textblock_Text_Item *ellip_ti;
444 Eina_List *anchors_a;
445 Eina_List *anchors_item;
446 int last_w, last_h;
447 struct {
448 int l, r, t, b;
449 } style_pad;
450 double valign;
451 char *markup_text;
452 void *engine_data;
453 const char *repch;
454 const char *bidi_delimiters;
455 struct {
456 int w, h;
457 Eina_Bool valid : 1;
458 } formatted, native;
459 Eina_Bool redraw : 1;
460 Eina_Bool changed : 1;
461 Eina_Bool content_changed : 1;
462 Eina_Bool format_changed : 1;
463 Eina_Bool have_ellipsis : 1;
464 Eina_Bool legacy_newline : 1;
465};
466
467/* private methods for textblock objects */
468static void evas_object_textblock_init(Evas_Object *obj);
469static void *evas_object_textblock_new(void);
470static void evas_object_textblock_render(Evas_Object *obj, void *output, void *context, void *surface, int x, int y);
471static void evas_object_textblock_free(Evas_Object *obj);
472static void evas_object_textblock_render_pre(Evas_Object *obj);
473static void evas_object_textblock_render_post(Evas_Object *obj);
474
475static unsigned int evas_object_textblock_id_get(Evas_Object *obj);
476static unsigned int evas_object_textblock_visual_id_get(Evas_Object *obj);
477static void *evas_object_textblock_engine_data_get(Evas_Object *obj);
478
479static int evas_object_textblock_is_opaque(Evas_Object *obj);
480static int evas_object_textblock_was_opaque(Evas_Object *obj);
481
482static void evas_object_textblock_coords_recalc(Evas_Object *obj);
483
484static void evas_object_textblock_scale_update(Evas_Object *obj);
485
486static const Evas_Object_Func object_func =
487{
488 /* methods (compulsory) */
489 evas_object_textblock_free,
490 evas_object_textblock_render,
491 evas_object_textblock_render_pre,
492 evas_object_textblock_render_post,
493 evas_object_textblock_id_get,
494 evas_object_textblock_visual_id_get,
495 evas_object_textblock_engine_data_get,
496 /* these are optional. NULL = nothing */
497 NULL,
498 NULL,
499 NULL,
500 NULL,
501 evas_object_textblock_is_opaque,
502 evas_object_textblock_was_opaque,
503 NULL,
504 NULL,
505 evas_object_textblock_coords_recalc,
506 evas_object_textblock_scale_update,
507 NULL,
508 NULL,
509 NULL
510};
511
512/* the actual api call to add a textblock */
513
514#define TB_HEAD() \
515 Evas_Object_Textblock *o; \
516 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ); \
517 return; \
518 MAGIC_CHECK_END(); \
519 o = (Evas_Object_Textblock *)(obj->object_data); \
520 MAGIC_CHECK(o, Evas_Object_Textblock, MAGIC_OBJ_TEXTBLOCK); \
521 return; \
522 MAGIC_CHECK_END();
523
524#define TB_HEAD_RETURN(x) \
525 Evas_Object_Textblock *o; \
526 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ); \
527 return (x); \
528 MAGIC_CHECK_END(); \
529 o = (Evas_Object_Textblock *)(obj->object_data); \
530 MAGIC_CHECK(o, Evas_Object_Textblock, MAGIC_OBJ_TEXTBLOCK); \
531 return (x); \
532 MAGIC_CHECK_END();
533
534
535
536static Eina_Bool _evas_textblock_cursor_is_at_the_end(const Evas_Textblock_Cursor *cur);
537static void _evas_textblock_node_text_remove(Evas_Object_Textblock *o, Evas_Object_Textblock_Node_Text *n);
538static void _evas_textblock_node_text_remove_formats_between(Evas_Object_Textblock *o, Evas_Object_Textblock_Node_Text *n, int start, int end);
539static Evas_Object_Textblock_Node_Format *_evas_textblock_cursor_node_format_before_or_at_pos_get(const Evas_Textblock_Cursor *cur);
540static size_t _evas_textblock_node_format_pos_get(const Evas_Object_Textblock_Node_Format *fmt);
541static void _evas_textblock_node_format_remove(Evas_Object_Textblock *o, Evas_Object_Textblock_Node_Format *n, int visual_adjustment);
542static void _evas_textblock_node_format_free(Evas_Object_Textblock *o, Evas_Object_Textblock_Node_Format *n);
543static void _evas_textblock_node_text_free(Evas_Object_Textblock_Node_Text *n);
544static void _evas_textblock_changed(Evas_Object_Textblock *o, Evas_Object *obj);
545static void _evas_textblock_invalidate_all(Evas_Object_Textblock *o);
546static void _evas_textblock_cursors_update_offset(const Evas_Textblock_Cursor *cur, const Evas_Object_Textblock_Node_Text *n, size_t start, int offset);
547static void _evas_textblock_cursors_set_node(Evas_Object_Textblock *o, const Evas_Object_Textblock_Node_Text *n, Evas_Object_Textblock_Node_Text *new_node);
548
549/* styles */
550/**
551 * @internal
552 * Clears the textblock style passed except for the style_text which is replaced.
553 * @param ts The ts to be cleared. Must not be NULL.
554 * @param style_text the style's text.
555 */
556static void
557_style_replace(Evas_Textblock_Style *ts, const char *style_text)
558{
559 eina_stringshare_replace(&ts->style_text, style_text);
560 if (ts->default_tag) free(ts->default_tag);
561 while (ts->tags)
562 {
563 Evas_Object_Style_Tag *tag;
564
565 tag = (Evas_Object_Style_Tag *)ts->tags;
566 ts->tags = (Evas_Object_Style_Tag *)eina_inlist_remove(EINA_INLIST_GET(ts->tags), EINA_INLIST_GET(tag));
567 free(tag->tag.tag);
568 free(tag->tag.replace);
569 free(tag);
570 }
571 ts->default_tag = NULL;
572 ts->tags = NULL;
573}
574
575/**
576 * @internal
577 * Clears the textblock style passed.
578 * @param ts The ts to be cleared. Must not be NULL.
579 */
580static void
581_style_clear(Evas_Textblock_Style *ts)
582{
583 _style_replace(ts, NULL);
584}
585
586/**
587 * @internal
588 * Searches inside the tags stored in the style for the tag matching s.
589 * @param ts The ts to be cleared. Must not be NULL.
590 * @param s The tag to be matched.
591 * @param tag_len the length of the tag string.
592 * @param[out] replace_len The length of the replcaement found. - Must not be NULL.
593 * @return The replacement string found.
594 */
595static inline const char *
596_style_match_tag(const Evas_Textblock_Style *ts, const char *s, size_t tag_len, size_t *replace_len)
597{
598 Evas_Object_Style_Tag *tag;
599
600 /* Try the style tags */
601 EINA_INLIST_FOREACH(ts->tags, tag)
602 {
603 if (tag->tag.tag_len != tag_len) continue;
604 if (!strncmp(tag->tag.tag, s, tag_len))
605 {
606 *replace_len = tag->tag.replace_len;
607 return tag->tag.replace;
608 }
609 }
610
611 /* Try the default tags */
612 {
613 size_t i;
614 const Evas_Object_Style_Tag_Base *btag;
615 for (btag = default_tags, i = 0 ;
616 i < (sizeof(default_tags) / sizeof(default_tags[0])) ;
617 btag++, i++)
618 {
619 if (btag->tag_len != tag_len) continue;
620 if (!strncmp(btag->tag, s, tag_len))
621 {
622 *replace_len = btag->replace_len;
623 return btag->replace;
624 }
625 }
626 }
627
628 *replace_len = 0;
629 return NULL;
630}
631
632/**
633 * @internal
634 * Clears all the nodes (text and format) of the textblock object.
635 * @param obj The evas object, must not be NULL.
636 */
637static void
638_nodes_clear(const Evas_Object *obj)
639{
640 Evas_Object_Textblock *o;
641
642 o = (Evas_Object_Textblock *)(obj->object_data);
643 while (o->text_nodes)
644 {
645 Evas_Object_Textblock_Node_Text *n;
646
647 n = o->text_nodes;
648 o->text_nodes = _NODE_TEXT(eina_inlist_remove(
649 EINA_INLIST_GET(o->text_nodes), EINA_INLIST_GET(n)));
650 _evas_textblock_node_text_free(n);
651 }
652 while (o->format_nodes)
653 {
654 Evas_Object_Textblock_Node_Format *n;
655
656 n = o->format_nodes;
657 o->format_nodes = _NODE_FORMAT(eina_inlist_remove(EINA_INLIST_GET(o->format_nodes), EINA_INLIST_GET(n)));
658 _evas_textblock_node_format_free(o, n);
659 }
660}
661
662/**
663 * @internal
664 * Unrefs and frees (if needed) a textblock format.
665 * @param obj The Evas_Object, Must not be NULL.
666 * @param fmt the format to be cleaned, must not be NULL.
667 */
668static void
669_format_unref_free(const Evas_Object *obj, Evas_Object_Textblock_Format *fmt)
670{
671 fmt->ref--;
672 if (fmt->ref > 0) return;
673 if (fmt->font.fdesc) evas_font_desc_unref(fmt->font.fdesc);
674 if (fmt->font.source) eina_stringshare_del(fmt->font.source);
675 evas_font_free(obj->layer->evas, fmt->font.font);
676 free(fmt);
677}
678
679/**
680 * @internal
681 * Free a layout item
682 * @param obj The evas object, must not be NULL.
683 * @param ln the layout line on which the item is in, must not be NULL.
684 * @param it the layout item to be freed
685 */
686static void
687_item_free(const Evas_Object *obj, Evas_Object_Textblock_Line *ln, Evas_Object_Textblock_Item *it)
688{
689 if (it->type == EVAS_TEXTBLOCK_ITEM_TEXT)
690 {
691 Evas_Object_Textblock_Text_Item *ti = _ITEM_TEXT(it);
692
693 evas_common_text_props_content_unref(&ti->text_props);
694 }
695 else
696 {
697 Evas_Object_Textblock_Format_Item *fi = _ITEM_FORMAT(it);
698
699 if (fi->item) eina_stringshare_del(fi->item);
700 }
701 _format_unref_free(obj, it->format);
702 if (ln)
703 {
704 ln->items = (Evas_Object_Textblock_Item *) eina_inlist_remove(
705 EINA_INLIST_GET(ln->items), EINA_INLIST_GET(ln->items));
706 }
707 free(it);
708}
709
710/**
711 * @internal
712 * Free a layout line.
713 * @param obj The evas object, must not be NULL.
714 * @param ln the layout line to be freed, must not be NULL.
715 */
716static void
717_line_free(Evas_Object_Textblock_Line *ln)
718{
719 /* Items are freed from the logical list, except for the ellip item */
720 if (ln) free(ln);
721}
722
723/* table of html escapes (that i can find) this should be ordered with the
724 * most common first as it's a linear search to match - no hash for this.
725 *
726 * these are stored as one large string and one additional array that
727 * contains the offsets to the tokens for space efficiency.
728 */
729/**
730 * @internal
731 * @var escape_strings[]
732 * This string consists of NULL terminated pairs of strings, the first of
733 * every pair is an escape and the second is the value of the escape.
734 */
735static const char escape_strings[] =
736/* most common escaped stuff */
737"&quot;\0" "\x22\0"
738"&amp;\0" "\x26\0"
739"&lt;\0" "\x3c\0"
740"&gt;\0" "\x3e\0"
741/* all the rest */
742"&nbsp;\0" "\xc2\xa0\0"
743"&iexcl;\0" "\xc2\xa1\0"
744"&cent;\0" "\xc2\xa2\0"
745"&pound;\0" "\xc2\xa3\0"
746"&curren;\0" "\xc2\xa4\0"
747"&yen;\0" "\xc2\xa5\0"
748"&brvbar;\0" "\xc2\xa6\0"
749"&sect;\0" "\xc2\xa7\0"
750"&uml;\0" "\xc2\xa8\0"
751"&copy;\0" "\xc2\xa9\0"
752"&ordf;\0" "\xc2\xaa\0"
753"&laquo;\0" "\xc2\xab\0"
754"&not;\0" "\xc2\xac\0"
755"&reg;\0" "\xc2\xae\0"
756"&macr;\0" "\xc2\xaf\0"
757"&deg;\0" "\xc2\xb0\0"
758"&plusmn;\0" "\xc2\xb1\0"
759"&sup2;\0" "\xc2\xb2\0"
760"&sup3;\0" "\xc2\xb3\0"
761"&acute;\0" "\xc2\xb4\0"
762"&micro;\0" "\xc2\xb5\0"
763"&para;\0" "\xc2\xb6\0"
764"&middot;\0" "\xc2\xb7\0"
765"&cedil;\0" "\xc2\xb8\0"
766"&sup1;\0" "\xc2\xb9\0"
767"&ordm;\0" "\xc2\xba\0"
768"&raquo;\0" "\xc2\xbb\0"
769"&frac14;\0" "\xc2\xbc\0"
770"&frac12;\0" "\xc2\xbd\0"
771"&frac34;\0" "\xc2\xbe\0"
772"&iquest;\0" "\xc2\xbf\0"
773"&Agrave;\0" "\xc3\x80\0"
774"&Aacute;\0" "\xc3\x81\0"
775"&Acirc;\0" "\xc3\x82\0"
776"&Atilde;\0" "\xc3\x83\0"
777"&Auml;\0" "\xc3\x84\0"
778"&Aring;\0" "\xc3\x85\0"
779"&Aelig;\0" "\xc3\x86\0"
780"&Ccedil;\0" "\xc3\x87\0"
781"&Egrave;\0" "\xc3\x88\0"
782"&Eacute;\0" "\xc3\x89\0"
783"&Ecirc;\0" "\xc3\x8a\0"
784"&Euml;\0" "\xc3\x8b\0"
785"&Igrave;\0" "\xc3\x8c\0"
786"&Iacute;\0" "\xc3\x8d\0"
787"&Icirc;\0" "\xc3\x8e\0"
788"&Iuml;\0" "\xc3\x8f\0"
789"&Eth;\0" "\xc3\x90\0"
790"&Ntilde;\0" "\xc3\x91\0"
791"&Ograve;\0" "\xc3\x92\0"
792"&Oacute;\0" "\xc3\x93\0"
793"&Ocirc;\0" "\xc3\x94\0"
794"&Otilde;\0" "\xc3\x95\0"
795"&Ouml;\0" "\xc3\x96\0"
796"&times;\0" "\xc3\x97\0"
797"&Oslash;\0" "\xc3\x98\0"
798"&Ugrave;\0" "\xc3\x99\0"
799"&Uacute;\0" "\xc3\x9a\0"
800"&Ucirc;\0" "\xc3\x9b\0"
801"&Yacute;\0" "\xc3\x9d\0"
802"&Thorn;\0" "\xc3\x9e\0"
803"&szlig;\0" "\xc3\x9f\0"
804"&agrave;\0" "\xc3\xa0\0"
805"&aacute;\0" "\xc3\xa1\0"
806"&acirc;\0" "\xc3\xa2\0"
807"&atilde;\0" "\xc3\xa3\0"
808"&auml;\0" "\xc3\xa4\0"
809"&aring;\0" "\xc3\xa5\0"
810"&aelig;\0" "\xc3\xa6\0"
811"&ccedil;\0" "\xc3\xa7\0"
812"&egrave;\0" "\xc3\xa8\0"
813"&eacute;\0" "\xc3\xa9\0"
814"&ecirc;\0" "\xc3\xaa\0"
815"&euml;\0" "\xc3\xab\0"
816"&igrave;\0" "\xc3\xac\0"
817"&iacute;\0" "\xc3\xad\0"
818"&icirc;\0" "\xc3\xae\0"
819"&iuml;\0" "\xc3\xaf\0"
820"&eth;\0" "\xc3\xb0\0"
821"&ntilde;\0" "\xc3\xb1\0"
822"&ograve;\0" "\xc3\xb2\0"
823"&oacute;\0" "\xc3\xb3\0"
824"&ocirc;\0" "\xc3\xb4\0"
825"&otilde;\0" "\xc3\xb5\0"
826"&ouml;\0" "\xc3\xb6\0"
827"&divide;\0" "\xc3\xb7\0"
828"&oslash;\0" "\xc3\xb8\0"
829"&ugrave;\0" "\xc3\xb9\0"
830"&uacute;\0" "\xc3\xba\0"
831"&ucirc;\0" "\xc3\xbb\0"
832"&uuml;\0" "\xc3\xbc\0"
833"&yacute;\0" "\xc3\xbd\0"
834"&thorn;\0" "\xc3\xbe\0"
835"&yuml;\0" "\xc3\xbf\0"
836"&alpha;\0" "\xce\x91\0"
837"&beta;\0" "\xce\x92\0"
838"&gamma;\0" "\xce\x93\0"
839"&delta;\0" "\xce\x94\0"
840"&epsilon;\0" "\xce\x95\0"
841"&zeta;\0" "\xce\x96\0"
842"&eta;\0" "\xce\x97\0"
843"&theta;\0" "\xce\x98\0"
844"&iota;\0" "\xce\x99\0"
845"&kappa;\0" "\xce\x9a\0"
846"&lambda;\0" "\xce\x9b\0"
847"&mu;\0" "\xce\x9c\0"
848"&nu;\0" "\xce\x9d\0"
849"&xi;\0" "\xce\x9e\0"
850"&omicron;\0" "\xce\x9f\0"
851"&pi;\0" "\xce\xa0\0"
852"&rho;\0" "\xce\xa1\0"
853"&sigma;\0" "\xce\xa3\0"
854"&tau;\0" "\xce\xa4\0"
855"&upsilon;\0" "\xce\xa5\0"
856"&phi;\0" "\xce\xa6\0"
857"&chi;\0" "\xce\xa7\0"
858"&psi;\0" "\xce\xa8\0"
859"&omega;\0" "\xce\xa9\0"
860"&hellip;\0" "\xe2\x80\xa6\0"
861"&euro;\0" "\xe2\x82\xac\0"
862"&larr;\0" "\xe2\x86\x90\0"
863"&uarr;\0" "\xe2\x86\x91\0"
864"&rarr;\0" "\xe2\x86\x92\0"
865"&darr;\0" "\xe2\x86\x93\0"
866"&harr;\0" "\xe2\x86\x94\0"
867"&larr;\0" "\xe2\x87\x90\0"
868"&rarr;\0" "\xe2\x87\x92\0"
869"&forall;\0" "\xe2\x88\x80\0"
870"&exist;\0" "\xe2\x88\x83\0"
871"&nabla;\0" "\xe2\x88\x87\0"
872"&prod;\0" "\xe2\x88\x8f\0"
873"&sum;\0" "\xe2\x88\x91\0"
874"&and;\0" "\xe2\x88\xa7\0"
875"&or;\0" "\xe2\x88\xa8\0"
876"&int;\0" "\xe2\x88\xab\0"
877"&ne;\0" "\xe2\x89\xa0\0"
878"&equiv;\0" "\xe2\x89\xa1\0"
879"&oplus;\0" "\xe2\x8a\x95\0"
880"&perp;\0" "\xe2\x8a\xa5\0"
881"&dagger;\0" "\xe2\x80\xa0\0"
882"&Dagger;\0" "\xe2\x80\xa1\0"
883"&bull;\0" "\xe2\x80\xa2\0"
884;
885
886EVAS_MEMPOOL(_mp_obj);
887
888/**
889 * @internal
890 * Checks if a char is a whitespace.
891 * @param c the unicode codepoint.
892 * @return EINA_TRUE if the unicode codepoint is a whitespace, EINA_FALSE otherwise.
893 */
894static Eina_Bool
895_is_white(Eina_Unicode c)
896{
897 /*
898 * unicode list of whitespace chars
899 *
900 * 0009..000D <control-0009>..<control-000D>
901 * 0020 SPACE
902 * 0085 <control-0085>
903 * 00A0 NO-BREAK SPACE
904 * 1680 OGHAM SPACE MARK
905 * 180E MONGOLIAN VOWEL SEPARATOR
906 * 2000..200A EN QUAD..HAIR SPACE
907 * 2028 LINE SEPARATOR
908 * 2029 PARAGRAPH SEPARATOR
909 * 202F NARROW NO-BREAK SPACE
910 * 205F MEDIUM MATHEMATICAL SPACE
911 * 3000 IDEOGRAPHIC SPACE
912 */
913 if (
914 (c == 0x20) ||
915 ((c >= 0x9) && (c <= 0xd)) ||
916 (c == 0x85) ||
917 (c == 0xa0) ||
918 (c == 0x1680) ||
919 (c == 0x180e) ||
920 ((c >= 0x2000) && (c <= 0x200a)) ||
921 (c == 0x2028) ||
922 (c == 0x2029) ||
923 (c == 0x202f) ||
924 (c == 0x205f) ||
925 (c == 0x3000)
926 )
927 return EINA_TRUE;
928 return EINA_FALSE;
929}
930
931/**
932 * @internal
933 * Prepends the text between s and p to the main cursor of the object.
934 *
935 * @param cur the cursor to prepend to.
936 * @param[in] s start of the string
937 * @param[in] p end of the string
938 */
939static void
940_prepend_text_run(Evas_Textblock_Cursor *cur, const char *s, const char *p)
941{
942 if ((s) && (p > s))
943 {
944 char *ts;
945
946 ts = alloca(p - s + 1);
947 strncpy(ts, s, p - s);
948 ts[p - s] = 0;
949 evas_textblock_cursor_text_prepend(cur, ts);
950 }
951}
952
953
954/**
955 * @internal
956 * Returns the numeric value of HEX chars for example for ch = 'A'
957 * the function will return 10.
958 *
959 * @param ch The HEX char.
960 * @return numeric value of HEX.
961 */
962static int
963_hex_string_get(char ch)
964{
965 if ((ch >= '0') && (ch <= '9')) return (ch - '0');
966 else if ((ch >= 'A') && (ch <= 'F')) return (ch - 'A' + 10);
967 else if ((ch >= 'a') && (ch <= 'f')) return (ch - 'a' + 10);
968 return 0;
969}
970
971/**
972 * @internal
973 * Parses a string of one of the formas:
974 * 1. "#RRGGBB"
975 * 2. "#RRGGBBAA"
976 * 3. "#RGB"
977 * 4. "#RGBA"
978 * To the rgba values.
979 *
980 * @param[in] str The string to parse - NOT NULL.
981 * @param[out] r The Red value - NOT NULL.
982 * @param[out] g The Green value - NOT NULL.
983 * @param[out] b The Blue value - NOT NULL.
984 * @param[out] a The Alpha value - NOT NULL.
985 */
986static void
987_format_color_parse(const char *str, unsigned char *r, unsigned char *g, unsigned char *b, unsigned char *a)
988{
989 int slen;
990
991 slen = strlen(str);
992 *r = *g = *b = *a = 0;
993
994 if (slen == 7) /* #RRGGBB */
995 {
996 *r = (_hex_string_get(str[1]) << 4) | (_hex_string_get(str[2]));
997 *g = (_hex_string_get(str[3]) << 4) | (_hex_string_get(str[4]));
998 *b = (_hex_string_get(str[5]) << 4) | (_hex_string_get(str[6]));
999 *a = 0xff;
1000 }
1001 else if (slen == 9) /* #RRGGBBAA */
1002 {
1003 *r = (_hex_string_get(str[1]) << 4) | (_hex_string_get(str[2]));
1004 *g = (_hex_string_get(str[3]) << 4) | (_hex_string_get(str[4]));
1005 *b = (_hex_string_get(str[5]) << 4) | (_hex_string_get(str[6]));
1006 *a = (_hex_string_get(str[7]) << 4) | (_hex_string_get(str[8]));
1007 }
1008 else if (slen == 4) /* #RGB */
1009 {
1010 *r = _hex_string_get(str[1]);
1011 *r = (*r << 4) | *r;
1012 *g = _hex_string_get(str[2]);
1013 *g = (*g << 4) | *g;
1014 *b = _hex_string_get(str[3]);
1015 *b = (*b << 4) | *b;
1016 *a = 0xff;
1017 }
1018 else if (slen == 5) /* #RGBA */
1019 {
1020 *r = _hex_string_get(str[1]);
1021 *r = (*r << 4) | *r;
1022 *g = _hex_string_get(str[2]);
1023 *g = (*g << 4) | *g;
1024 *b = _hex_string_get(str[3]);
1025 *b = (*b << 4) | *b;
1026 *a = _hex_string_get(str[4]);
1027 *a = (*a << 4) | *a;
1028 }
1029 *r = (*r * *a) / 255;
1030 *g = (*g * *a) / 255;
1031 *b = (*b * *a) / 255;
1032}
1033
1034/* The refcount for the formats. */
1035static int format_refcount = 0;
1036/* Holders for the stringshares */
1037static const char *fontstr = NULL;
1038static const char *font_fallbacksstr = NULL;
1039static const char *font_sizestr = NULL;
1040static const char *font_sourcestr = NULL;
1041static const char *font_weightstr = NULL;
1042static const char *font_stylestr = NULL;
1043static const char *font_widthstr = NULL;
1044static const char *langstr = NULL;
1045static const char *colorstr = NULL;
1046static const char *underline_colorstr = NULL;
1047static const char *underline2_colorstr = NULL;
1048static const char *underline_dash_colorstr = NULL;
1049static const char *outline_colorstr = NULL;
1050static const char *shadow_colorstr = NULL;
1051static const char *glow_colorstr = NULL;
1052static const char *glow2_colorstr = NULL;
1053static const char *backing_colorstr = NULL;
1054static const char *strikethrough_colorstr = NULL;
1055static const char *alignstr = NULL;
1056static const char *valignstr = NULL;
1057static const char *wrapstr = NULL;
1058static const char *left_marginstr = NULL;
1059static const char *right_marginstr = NULL;
1060static const char *underlinestr = NULL;
1061static const char *strikethroughstr = NULL;
1062static const char *backingstr = NULL;
1063static const char *stylestr = NULL;
1064static const char *tabstopsstr = NULL;
1065static const char *linesizestr = NULL;
1066static const char *linerelsizestr = NULL;
1067static const char *linegapstr = NULL;
1068static const char *linerelgapstr = NULL;
1069static const char *itemstr = NULL;
1070static const char *linefillstr = NULL;
1071static const char *ellipsisstr = NULL;
1072static const char *passwordstr = NULL;
1073static const char *underline_dash_widthstr = NULL;
1074static const char *underline_dash_gapstr = NULL;
1075
1076/**
1077 * @internal
1078 * Init the format strings.
1079 */
1080static void
1081_format_command_init(void)
1082{
1083 if (format_refcount == 0)
1084 {
1085 fontstr = eina_stringshare_add("font");
1086 font_fallbacksstr = eina_stringshare_add("font_fallbacks");
1087 font_sizestr = eina_stringshare_add("font_size");
1088 font_sourcestr = eina_stringshare_add("font_source");
1089 font_weightstr = eina_stringshare_add("font_weight");
1090 font_stylestr = eina_stringshare_add("font_style");
1091 font_widthstr = eina_stringshare_add("font_width");
1092 langstr = eina_stringshare_add("lang");
1093 colorstr = eina_stringshare_add("color");
1094 underline_colorstr = eina_stringshare_add("underline_color");
1095 underline2_colorstr = eina_stringshare_add("underline2_color");
1096 underline_dash_colorstr = eina_stringshare_add("underline_dash_color");
1097 outline_colorstr = eina_stringshare_add("outline_color");
1098 shadow_colorstr = eina_stringshare_add("shadow_color");
1099 glow_colorstr = eina_stringshare_add("glow_color");
1100 glow2_colorstr = eina_stringshare_add("glow2_color");
1101 backing_colorstr = eina_stringshare_add("backing_color");
1102 strikethrough_colorstr = eina_stringshare_add("strikethrough_color");
1103 alignstr = eina_stringshare_add("align");
1104 valignstr = eina_stringshare_add("valign");
1105 wrapstr = eina_stringshare_add("wrap");
1106 left_marginstr = eina_stringshare_add("left_margin");
1107 right_marginstr = eina_stringshare_add("right_margin");
1108 underlinestr = eina_stringshare_add("underline");
1109 strikethroughstr = eina_stringshare_add("strikethrough");
1110 backingstr = eina_stringshare_add("backing");
1111 stylestr = eina_stringshare_add("style");
1112 tabstopsstr = eina_stringshare_add("tabstops");
1113 linesizestr = eina_stringshare_add("linesize");
1114 linerelsizestr = eina_stringshare_add("linerelsize");
1115 linegapstr = eina_stringshare_add("linegap");
1116 linerelgapstr = eina_stringshare_add("linerelgap");
1117 itemstr = eina_stringshare_add("item");
1118 linefillstr = eina_stringshare_add("linefill");
1119 ellipsisstr = eina_stringshare_add("ellipsis");
1120 passwordstr = eina_stringshare_add("password");
1121 underline_dash_widthstr = eina_stringshare_add("underline_dash_width");
1122 underline_dash_gapstr = eina_stringshare_add("underline_dash_gap");
1123 }
1124 format_refcount++;
1125}
1126
1127/**
1128 * @internal
1129 * Shutdown the format strings.
1130 */
1131static void
1132_format_command_shutdown(void)
1133{
1134 if (--format_refcount > 0) return;
1135
1136 eina_stringshare_del(fontstr);
1137 eina_stringshare_del(font_fallbacksstr);
1138 eina_stringshare_del(font_sizestr);
1139 eina_stringshare_del(font_sourcestr);
1140 eina_stringshare_del(font_weightstr);
1141 eina_stringshare_del(font_stylestr);
1142 eina_stringshare_del(font_widthstr);
1143 eina_stringshare_del(langstr);
1144 eina_stringshare_del(colorstr);
1145 eina_stringshare_del(underline_colorstr);
1146 eina_stringshare_del(underline2_colorstr);
1147 eina_stringshare_del(underline_dash_colorstr);
1148 eina_stringshare_del(outline_colorstr);
1149 eina_stringshare_del(shadow_colorstr);
1150 eina_stringshare_del(glow_colorstr);
1151 eina_stringshare_del(glow2_colorstr);
1152 eina_stringshare_del(backing_colorstr);
1153 eina_stringshare_del(strikethrough_colorstr);
1154 eina_stringshare_del(alignstr);
1155 eina_stringshare_del(valignstr);
1156 eina_stringshare_del(wrapstr);
1157 eina_stringshare_del(left_marginstr);
1158 eina_stringshare_del(right_marginstr);
1159 eina_stringshare_del(underlinestr);
1160 eina_stringshare_del(strikethroughstr);
1161 eina_stringshare_del(backingstr);
1162 eina_stringshare_del(stylestr);
1163 eina_stringshare_del(tabstopsstr);
1164 eina_stringshare_del(linesizestr);
1165 eina_stringshare_del(linerelsizestr);
1166 eina_stringshare_del(linegapstr);
1167 eina_stringshare_del(linerelgapstr);
1168 eina_stringshare_del(itemstr);
1169 eina_stringshare_del(linefillstr);
1170 eina_stringshare_del(ellipsisstr);
1171 eina_stringshare_del(passwordstr);
1172 eina_stringshare_del(underline_dash_widthstr);
1173 eina_stringshare_del(underline_dash_gapstr);
1174}
1175
1176/**
1177 * @internal
1178 * Copies str to dst while removing the \\ char, i.e unescape the escape sequences.
1179 *
1180 * @param[out] dst the destination string - Should not be NULL.
1181 * @param[in] src the source string - Should not be NULL.
1182 */
1183static void
1184_format_clean_param(char *dst, const char *src)
1185{
1186 const char *ss;
1187 char *ds;
1188
1189 ds = dst;
1190 for (ss = src; *ss; ss++, ds++)
1191 {
1192 if ((*ss == '\\') && *(ss + 1)) ss++;
1193 *ds = *ss;
1194 }
1195 *ds = 0;
1196}
1197
1198/**
1199 * @internal
1200 * Parses the cmd and parameter and adds the parsed format to fmt.
1201 *
1202 * @param obj the evas object - should not be NULL.
1203 * @param fmt The format to populate - should not be NULL.
1204 * @param[in] cmd the command to process, should be stringshared.
1205 * @param[in] param the parameter of the command.
1206 */
1207static void
1208_format_command(Evas_Object *obj, Evas_Object_Textblock_Format *fmt, const char *cmd, const char *param)
1209{
1210 int len;
1211 char *tmp_param;
1212
1213 len = strlen(param);
1214 tmp_param = alloca(len + 1);
1215
1216 _format_clean_param(tmp_param, param);
1217
1218 /* If we are changing the font, create the fdesc. */
1219 if ((cmd == font_weightstr) || (cmd == font_widthstr) ||
1220 (cmd == font_stylestr) || (cmd == langstr) ||
1221 (cmd == fontstr) || (cmd == font_fallbacksstr))
1222 {
1223 if (!fmt->font.fdesc)
1224 {
1225 fmt->font.fdesc = evas_font_desc_new();
1226 }
1227 else if (!fmt->font.fdesc->is_new)
1228 {
1229 Evas_Font_Description *old = fmt->font.fdesc;
1230 fmt->font.fdesc = evas_font_desc_dup(fmt->font.fdesc);
1231 if (old) evas_font_desc_unref(old);
1232 }
1233 }
1234
1235
1236 if (cmd == fontstr)
1237 {
1238 evas_font_name_parse(fmt->font.fdesc, tmp_param);
1239 }
1240 else if (cmd == font_fallbacksstr)
1241 {
1242 eina_stringshare_replace(&(fmt->font.fdesc->fallbacks), tmp_param);
1243 }
1244 else if (cmd == font_sizestr)
1245 {
1246 int v;
1247
1248 v = atoi(tmp_param);
1249 if (v != fmt->font.size)
1250 {
1251 fmt->font.size = v;
1252 }
1253 }
1254 else if (cmd == font_sourcestr)
1255 {
1256 if ((!fmt->font.source) ||
1257 ((fmt->font.source) && (strcmp(fmt->font.source, tmp_param))))
1258 {
1259 if (fmt->font.source) eina_stringshare_del(fmt->font.source);
1260 fmt->font.source = eina_stringshare_add(tmp_param);
1261 }
1262 }
1263 else if (cmd == font_weightstr)
1264 {
1265 fmt->font.fdesc->weight = evas_font_style_find(tmp_param,
1266 tmp_param + strlen(tmp_param), EVAS_FONT_STYLE_WEIGHT);
1267 }
1268 else if (cmd == font_stylestr)
1269 {
1270 fmt->font.fdesc->slant = evas_font_style_find(tmp_param,
1271 tmp_param + strlen(tmp_param), EVAS_FONT_STYLE_SLANT);
1272 }
1273 else if (cmd == font_widthstr)
1274 {
1275 fmt->font.fdesc->width = evas_font_style_find(tmp_param,
1276 tmp_param + strlen(tmp_param), EVAS_FONT_STYLE_WIDTH);
1277 }
1278 else if (cmd == langstr)
1279 {
1280 eina_stringshare_replace(&(fmt->font.fdesc->lang), tmp_param);
1281 }
1282 else if (cmd == colorstr)
1283 _format_color_parse(tmp_param,
1284 &(fmt->color.normal.r), &(fmt->color.normal.g),
1285 &(fmt->color.normal.b), &(fmt->color.normal.a));
1286 else if (cmd == underline_colorstr)
1287 _format_color_parse(tmp_param,
1288 &(fmt->color.underline.r), &(fmt->color.underline.g),
1289 &(fmt->color.underline.b), &(fmt->color.underline.a));
1290 else if (cmd == underline2_colorstr)
1291 _format_color_parse(tmp_param,
1292 &(fmt->color.underline2.r), &(fmt->color.underline2.g),
1293 &(fmt->color.underline2.b), &(fmt->color.underline2.a));
1294 else if (cmd == underline_dash_colorstr)
1295 _format_color_parse(tmp_param,
1296 &(fmt->color.underline_dash.r), &(fmt->color.underline_dash.g),
1297 &(fmt->color.underline_dash.b), &(fmt->color.underline_dash.a));
1298 else if (cmd == outline_colorstr)
1299 _format_color_parse(tmp_param,
1300 &(fmt->color.outline.r), &(fmt->color.outline.g),
1301 &(fmt->color.outline.b), &(fmt->color.outline.a));
1302 else if (cmd == shadow_colorstr)
1303 _format_color_parse(tmp_param,
1304 &(fmt->color.shadow.r), &(fmt->color.shadow.g),
1305 &(fmt->color.shadow.b), &(fmt->color.shadow.a));
1306 else if (cmd == glow_colorstr)
1307 _format_color_parse(tmp_param,
1308 &(fmt->color.glow.r), &(fmt->color.glow.g),
1309 &(fmt->color.glow.b), &(fmt->color.glow.a));
1310 else if (cmd == glow2_colorstr)
1311 _format_color_parse(tmp_param,
1312 &(fmt->color.glow2.r), &(fmt->color.glow2.g),
1313 &(fmt->color.glow2.b), &(fmt->color.glow2.a));
1314 else if (cmd == backing_colorstr)
1315 _format_color_parse(tmp_param,
1316 &(fmt->color.backing.r), &(fmt->color.backing.g),
1317 &(fmt->color.backing.b), &(fmt->color.backing.a));
1318 else if (cmd == strikethrough_colorstr)
1319 _format_color_parse(tmp_param,
1320 &(fmt->color.strikethrough.r), &(fmt->color.strikethrough.g),
1321 &(fmt->color.strikethrough.b), &(fmt->color.strikethrough.a));
1322 else if (cmd == alignstr)
1323 {
1324 if (!strcmp(tmp_param, "auto"))
1325 {
1326 fmt->halign_auto = EINA_TRUE;
1327 }
1328 else
1329 {
1330 if (!strcmp(tmp_param, "middle")) fmt->halign = 0.5;
1331 else if (!strcmp(tmp_param, "center")) fmt->halign = 0.5;
1332 else if (!strcmp(tmp_param, "left")) fmt->halign = 0.0;
1333 else if (!strcmp(tmp_param, "right")) fmt->halign = 1.0;
1334 else
1335 {
1336 char *endptr = NULL;
1337 double val = strtod(tmp_param, &endptr);
1338 if (endptr)
1339 {
1340 while (*endptr && _is_white(*endptr))
1341 endptr++;
1342 if (*endptr == '%')
1343 val /= 100.0;
1344 }
1345 fmt->halign = val;
1346 if (fmt->halign < 0.0) fmt->halign = 0.0;
1347 else if (fmt->halign > 1.0) fmt->halign = 1.0;
1348 }
1349 fmt->halign_auto = EINA_FALSE;
1350 }
1351 }
1352 else if (cmd == valignstr)
1353 {
1354 if (!strcmp(tmp_param, "top")) fmt->valign = 0.0;
1355 else if (!strcmp(tmp_param, "middle")) fmt->valign = 0.5;
1356 else if (!strcmp(tmp_param, "center")) fmt->valign = 0.5;
1357 else if (!strcmp(tmp_param, "bottom")) fmt->valign = 1.0;
1358 else if (!strcmp(tmp_param, "baseline")) fmt->valign = -1.0;
1359 else if (!strcmp(tmp_param, "base")) fmt->valign = -1.0;
1360 else
1361 {
1362 char *endptr = NULL;
1363 double val = strtod(tmp_param, &endptr);
1364 if (endptr)
1365 {
1366 while (*endptr && _is_white(*endptr))
1367 endptr++;
1368 if (*endptr == '%')
1369 val /= 100.0;
1370 }
1371 fmt->valign = val;
1372 if (fmt->valign < 0.0) fmt->valign = 0.0;
1373 else if (fmt->valign > 1.0) fmt->valign = 1.0;
1374 }
1375 }
1376 else if (cmd == wrapstr)
1377 {
1378 if (!strcmp(tmp_param, "word"))
1379 {
1380 fmt->wrap_word = 1;
1381 fmt->wrap_char = fmt->wrap_mixed = 0;
1382 }
1383 else if (!strcmp(tmp_param, "char"))
1384 {
1385 fmt->wrap_word = fmt->wrap_mixed = 0;
1386 fmt->wrap_char = 1;
1387 }
1388 else if (!strcmp(tmp_param, "mixed"))
1389 {
1390 fmt->wrap_word = fmt->wrap_char = 0;
1391 fmt->wrap_mixed = 1;
1392 }
1393 else
1394 {
1395 fmt->wrap_word = fmt->wrap_mixed = fmt->wrap_char = 0;
1396 }
1397 }
1398 else if (cmd == left_marginstr)
1399 {
1400 if (!strcmp(tmp_param, "reset"))
1401 fmt->margin.l = 0;
1402 else
1403 {
1404 if (tmp_param[0] == '+')
1405 fmt->margin.l += atoi(&(tmp_param[1]));
1406 else if (tmp_param[0] == '-')
1407 fmt->margin.l -= atoi(&(tmp_param[1]));
1408 else
1409 fmt->margin.l = atoi(tmp_param);
1410 if (fmt->margin.l < 0) fmt->margin.l = 0;
1411 }
1412 }
1413 else if (cmd == right_marginstr)
1414 {
1415 if (!strcmp(tmp_param, "reset"))
1416 fmt->margin.r = 0;
1417 else
1418 {
1419 if (tmp_param[0] == '+')
1420 fmt->margin.r += atoi(&(tmp_param[1]));
1421 else if (tmp_param[0] == '-')
1422 fmt->margin.r -= atoi(&(tmp_param[1]));
1423 else
1424 fmt->margin.r = atoi(tmp_param);
1425 if (fmt->margin.r < 0) fmt->margin.r = 0;
1426 }
1427 }
1428 else if (cmd == underlinestr)
1429 {
1430 if (!strcmp(tmp_param, "off"))
1431 {
1432 fmt->underline = 0;
1433 fmt->underline2 = 0;
1434 }
1435 else if ((!strcmp(tmp_param, "on")) ||
1436 (!strcmp(tmp_param, "single")))
1437 {
1438 fmt->underline = 1;
1439 fmt->underline2 = 0;
1440 }
1441 else if (!strcmp(tmp_param, "double"))
1442 {
1443 fmt->underline = 1;
1444 fmt->underline2 = 1;
1445 }
1446 else if (!strcmp(tmp_param, "dashed"))
1447 fmt->underline_dash = 1;
1448 }
1449 else if (cmd == strikethroughstr)
1450 {
1451 if (!strcmp(tmp_param, "off"))
1452 fmt->strikethrough = 0;
1453 else if (!strcmp(tmp_param, "on"))
1454 fmt->strikethrough = 1;
1455 }
1456 else if (cmd == backingstr)
1457 {
1458 if (!strcmp(tmp_param, "off"))
1459 fmt->backing = 0;
1460 else if (!strcmp(tmp_param, "on"))
1461 fmt->backing = 1;
1462 }
1463 else if (cmd == stylestr)
1464 {
1465 char *p1, *p2, *p, *pp;
1466
1467 p1 = alloca(len + 1);
1468 *p1 = 0;
1469 p2 = alloca(len + 1);
1470 *p2 = 0;
1471 /* no comma */
1472 if (!strstr(tmp_param, ",")) p1 = tmp_param;
1473 else
1474 {
1475 /* split string "str1,str2" into p1 and p2 (if we have more than
1476 * 1 str2 eg "str1,str2,str3,str4" then we don't care. p2 just
1477 * ends up being the last one as right now it's only valid to have
1478 * 1 comma and 2 strings */
1479 pp = p1;
1480 for (p = tmp_param; *p; p++)
1481 {
1482 if (*p == ',')
1483 {
1484 *pp = 0;
1485 pp = p2;
1486 continue;
1487 }
1488 *pp = *p;
1489 pp++;
1490 }
1491 *pp = 0;
1492 }
1493 if (!strcmp(p1, "off")) fmt->style = EVAS_TEXT_STYLE_PLAIN;
1494 else if (!strcmp(p1, "none")) fmt->style = EVAS_TEXT_STYLE_PLAIN;
1495 else if (!strcmp(p1, "plain")) fmt->style = EVAS_TEXT_STYLE_PLAIN;
1496 else if (!strcmp(p1, "shadow")) fmt->style = EVAS_TEXT_STYLE_SHADOW;
1497 else if (!strcmp(p1, "outline")) fmt->style = EVAS_TEXT_STYLE_OUTLINE;
1498 else if (!strcmp(p1, "soft_outline")) fmt->style = EVAS_TEXT_STYLE_SOFT_OUTLINE;
1499 else if (!strcmp(p1, "outline_shadow")) fmt->style = EVAS_TEXT_STYLE_OUTLINE_SHADOW;
1500 else if (!strcmp(p1, "outline_soft_shadow")) fmt->style = EVAS_TEXT_STYLE_OUTLINE_SOFT_SHADOW;
1501 else if (!strcmp(p1, "glow")) fmt->style = EVAS_TEXT_STYLE_GLOW;
1502 else if (!strcmp(p1, "far_shadow")) fmt->style = EVAS_TEXT_STYLE_FAR_SHADOW;
1503 else if (!strcmp(p1, "soft_shadow")) fmt->style = EVAS_TEXT_STYLE_SOFT_SHADOW;
1504 else if (!strcmp(p1, "far_soft_shadow")) fmt->style = EVAS_TEXT_STYLE_FAR_SOFT_SHADOW;
1505 else fmt->style = EVAS_TEXT_STYLE_PLAIN;
1506
1507 if (*p2)
1508 {
1509 if (!strcmp(p2, "bottom_right")) EVAS_TEXT_STYLE_SHADOW_DIRECTION_SET(fmt->style, EVAS_TEXT_STYLE_SHADOW_DIRECTION_BOTTOM_RIGHT);
1510 else if (!strcmp(p2, "bottom")) EVAS_TEXT_STYLE_SHADOW_DIRECTION_SET(fmt->style, EVAS_TEXT_STYLE_SHADOW_DIRECTION_BOTTOM);
1511 else if (!strcmp(p2, "bottom_left")) EVAS_TEXT_STYLE_SHADOW_DIRECTION_SET(fmt->style, EVAS_TEXT_STYLE_SHADOW_DIRECTION_BOTTOM_LEFT);
1512 else if (!strcmp(p2, "left")) EVAS_TEXT_STYLE_SHADOW_DIRECTION_SET(fmt->style, EVAS_TEXT_STYLE_SHADOW_DIRECTION_LEFT);
1513 else if (!strcmp(p2, "top_left")) EVAS_TEXT_STYLE_SHADOW_DIRECTION_SET(fmt->style, EVAS_TEXT_STYLE_SHADOW_DIRECTION_TOP_LEFT);
1514 else if (!strcmp(p2, "top")) EVAS_TEXT_STYLE_SHADOW_DIRECTION_SET(fmt->style, EVAS_TEXT_STYLE_SHADOW_DIRECTION_TOP);
1515 else if (!strcmp(p2, "top_right")) EVAS_TEXT_STYLE_SHADOW_DIRECTION_SET(fmt->style, EVAS_TEXT_STYLE_SHADOW_DIRECTION_TOP_RIGHT);
1516 else if (!strcmp(p2, "right")) EVAS_TEXT_STYLE_SHADOW_DIRECTION_SET(fmt->style, EVAS_TEXT_STYLE_SHADOW_DIRECTION_RIGHT);
1517 else EVAS_TEXT_STYLE_SHADOW_DIRECTION_SET(fmt->style, EVAS_TEXT_STYLE_SHADOW_DIRECTION_BOTTOM_RIGHT);
1518 }
1519 }
1520 else if (cmd == tabstopsstr)
1521 {
1522 fmt->tabstops = atoi(tmp_param);
1523 if (fmt->tabstops < 1) fmt->tabstops = 1;
1524 }
1525 else if (cmd == linesizestr)
1526 {
1527 fmt->linesize = atoi(tmp_param);
1528 fmt->linerelsize = 0.0;
1529 }
1530 else if (cmd == linerelsizestr)
1531 {
1532 char *endptr = NULL;
1533 double val = strtod(tmp_param, &endptr);
1534 if (endptr)
1535 {
1536 while (*endptr && _is_white(*endptr))
1537 endptr++;
1538 if (*endptr == '%')
1539 {
1540 fmt->linerelsize = val / 100.0;
1541 fmt->linesize = 0;
1542 if (fmt->linerelsize < 0.0) fmt->linerelsize = 0.0;
1543 }
1544 }
1545 }
1546 else if (cmd == linegapstr)
1547 {
1548 fmt->linegap = atoi(tmp_param);
1549 fmt->linerelgap = 0.0;
1550 }
1551 else if (cmd == linerelgapstr)
1552 {
1553 char *endptr = NULL;
1554 double val = strtod(tmp_param, &endptr);
1555 if (endptr)
1556 {
1557 while (*endptr && _is_white(*endptr))
1558 endptr++;
1559 if (*endptr == '%')
1560 {
1561 fmt->linerelgap = val / 100.0;
1562 fmt->linegap = 0;
1563 if (fmt->linerelgap < 0.0) fmt->linerelgap = 0.0;
1564 }
1565 }
1566 }
1567 else if (cmd == itemstr)
1568 {
1569 // itemstr == replacement object items in textblock - inline imges
1570 // for example
1571 }
1572 else if (cmd == linefillstr)
1573 {
1574 char *endptr = NULL;
1575 double val = strtod(tmp_param, &endptr);
1576 if (endptr)
1577 {
1578 while (*endptr && _is_white(*endptr))
1579 endptr++;
1580 if (*endptr == '%')
1581 {
1582 fmt->linefill = val / 100.0;
1583 if (fmt->linefill < 0.0) fmt->linefill = 0.0;
1584 }
1585 }
1586 }
1587 else if (cmd == ellipsisstr)
1588 {
1589 char *endptr = NULL;
1590 fmt->ellipsis = strtod(tmp_param, &endptr);
1591 if ((fmt->ellipsis < 0.0) || (fmt->ellipsis > 1.0))
1592 fmt->ellipsis = -1.0;
1593 else
1594 {
1595 Evas_Object_Textblock *o;
1596
1597 o = (Evas_Object_Textblock *)(obj->object_data);
1598 o->have_ellipsis = 1;
1599 }
1600 }
1601 else if (cmd == passwordstr)
1602 {
1603 if (!strcmp(tmp_param, "off"))
1604 fmt->password = 0;
1605 else if (!strcmp(tmp_param, "on"))
1606 fmt->password = 1;
1607 }
1608 else if (cmd == underline_dash_widthstr)
1609 {
1610 fmt->underline_dash_width = atoi(tmp_param);
1611 if (fmt->underline_dash_width <= 0) fmt->underline_dash_width = 1;
1612 }
1613 else if (cmd == underline_dash_gapstr)
1614 {
1615 fmt->underline_dash_gap = atoi(tmp_param);
1616 if (fmt->underline_dash_gap <= 0) fmt->underline_dash_gap = 1;
1617 }
1618}
1619
1620/**
1621 * @internal
1622 * Returns #EINA_TRUE if the item is a format parameter, #EINA_FALSE otherwise.
1623 *
1624 * @param[in] item the item to check - Not NULL.
1625 */
1626static Eina_Bool
1627_format_is_param(const char *item)
1628{
1629 if (strchr(item, '=')) return EINA_TRUE;
1630 return EINA_FALSE;
1631}
1632
1633/**
1634 * @internal
1635 * Parse the format item and populate key and val with the stringshares that
1636 * corrospond to the formats parsed.
1637 * It expects item to be of the structure:
1638 * "key=val"
1639 *
1640 * @param[in] item the item to parse - Not NULL.
1641 * @param[out] key where to store the key at - Not NULL.
1642 * @param[out] val where to store the value at - Not NULL.
1643 */
1644static void
1645_format_param_parse(const char *item, const char **key, const char **val)
1646{
1647 const char *start, *end, *quote;
1648
1649 start = strchr(item, '=');
1650 *key = eina_stringshare_add_length(item, start - item);
1651 start++; /* Advance after the '=' */
1652 /* If we can find a quote, our new delimiter is a quote, not a space. */
1653 if ((quote = strchr(start, '\'')))
1654 {
1655 start = quote + 1;
1656 end = strchr(start, '\'');
1657 }
1658 else
1659 {
1660 end = strchr(start, ' ');
1661 }
1662
1663 /* Null terminate before the spaces */
1664 if (end)
1665 {
1666 *val = eina_stringshare_add_length(start, end - start);
1667 }
1668 else
1669 {
1670 *val = eina_stringshare_add(start);
1671 }
1672}
1673
1674/**
1675 * @internal
1676 * This function parses the format passed in *s and advances s to point to the
1677 * next format item, while returning the current one as the return value.
1678 * @param s The current and returned position in the format string.
1679 * @return the current item parsed from the string.
1680 */
1681static const char *
1682_format_parse(const char **s)
1683{
1684 const char *p;
1685 const char *s1 = NULL, *s2 = NULL;
1686 Eina_Bool quote = EINA_FALSE;;
1687
1688 p = *s;
1689 if (*p == 0) return NULL;
1690 for (;;)
1691 {
1692 if (!s1)
1693 {
1694 if (*p != ' ') s1 = p;
1695 if (*p == 0) break;
1696 }
1697 else if (!s2)
1698 {
1699 if (*p == '\'')
1700 {
1701 quote = !quote;
1702 }
1703
1704 if ((p > *s) && (p[-1] != '\\') && (!quote))
1705 {
1706 if (*p == ' ') s2 = p;
1707 }
1708 if (*p == 0) s2 = p;
1709 }
1710 p++;
1711 if (s1 && s2)
1712 {
1713 *s = s2;
1714 return s1;
1715 }
1716 }
1717 *s = p;
1718 return NULL;
1719}
1720
1721/**
1722 * @internal
1723 * Parse the format str and populate fmt with the formats found.
1724 *
1725 * @param obj The evas object - Not NULL.
1726 * @param[out] fmt The format to populate - Not NULL.
1727 * @param[in] str the string to parse.- Not NULL.
1728 */
1729static void
1730_format_fill(Evas_Object *obj, Evas_Object_Textblock_Format *fmt, const char *str)
1731{
1732 const char *s;
1733 const char *item;
1734
1735 s = str;
1736
1737 /* get rid of any spaces at the start of the string */
1738 while (*s == ' ') s++;
1739
1740 while ((item = _format_parse(&s)))
1741 {
1742 if (_format_is_param(item))
1743 {
1744 const char *key = NULL, *val = NULL;
1745
1746 _format_param_parse(item, &key, &val);
1747 _format_command(obj, fmt, key, val);
1748 eina_stringshare_del(key);
1749 eina_stringshare_del(val);
1750 }
1751 else
1752 {
1753 /* immediate - not handled here */
1754 }
1755 }
1756}
1757
1758/**
1759 * @internal
1760 * Duplicate a format and return the duplicate.
1761 *
1762 * @param obj The evas object - Not NULL.
1763 * @param[in] fmt The format to duplicate - Not NULL.
1764 * @return the copy of the format.
1765 */
1766static Evas_Object_Textblock_Format *
1767_format_dup(Evas_Object *obj, const Evas_Object_Textblock_Format *fmt)
1768{
1769 Evas_Object_Textblock_Format *fmt2;
1770
1771 fmt2 = calloc(1, sizeof(Evas_Object_Textblock_Format));
1772 memcpy(fmt2, fmt, sizeof(Evas_Object_Textblock_Format));
1773 fmt2->ref = 1;
1774 fmt2->font.fdesc = evas_font_desc_ref(fmt->font.fdesc);
1775
1776 if (fmt->font.source) fmt2->font.source = eina_stringshare_add(fmt->font.source);
1777
1778 /* FIXME: just ref the font here... */
1779 fmt2->font.font = evas_font_load(obj->layer->evas, fmt2->font.fdesc,
1780 fmt2->font.source, (int)(((double) fmt2->font.size) * obj->cur.scale));
1781 return fmt2;
1782}
1783
1784
1785
1786
1787/**
1788 * @internal
1789 * @typedef Ctxt
1790 *
1791 * A pack of information that needed to be passed around in the layout engine,
1792 * packed for easier access.
1793 */
1794typedef struct _Ctxt Ctxt;
1795
1796struct _Ctxt
1797{
1798 Evas_Object *obj;
1799 Evas_Object_Textblock *o;
1800
1801 Evas_Object_Textblock_Paragraph *paragraphs;
1802 Evas_Object_Textblock_Paragraph *par;
1803 Evas_Object_Textblock_Line *ln;
1804
1805
1806 Eina_List *format_stack;
1807 Evas_Object_Textblock_Format *fmt;
1808
1809 int x, y;
1810 int w, h;
1811 int wmax, hmax;
1812 int maxascent, maxdescent;
1813 int marginl, marginr;
1814 int line_no;
1815 int underline_extend;
1816 int have_underline, have_underline2;
1817 double align, valign;
1818 Eina_Bool align_auto : 1;
1819 Eina_Bool width_changed : 1;
1820};
1821
1822static void _layout_text_add_logical_item(Ctxt *c, Evas_Object_Textblock_Text_Item *ti, Eina_List *rel);
1823static void _text_item_update_sizes(Ctxt *c, Evas_Object_Textblock_Text_Item *ti);
1824static void _layout_do_format(const Evas_Object *obj, Ctxt *c, Evas_Object_Textblock_Format **_fmt, Evas_Object_Textblock_Node_Format *n, int *style_pad_l, int *style_pad_r, int *style_pad_t, int *style_pad_b, Eina_Bool create_item);
1825/**
1826 * @internal
1827 * Adjust the ascent/descent of the format and context.
1828 *
1829 * @param maxascent The ascent to update - Not NUL.
1830 * @param maxdescent The descent to update - Not NUL.
1831 * @param fmt The format to adjust - NOT NULL.
1832 */
1833static void
1834_layout_format_ascent_descent_adjust(const Evas_Object *obj,
1835 Evas_Coord *maxascent, Evas_Coord *maxdescent,
1836 Evas_Object_Textblock_Format *fmt)
1837{
1838 int ascent, descent;
1839
1840 if (fmt->font.font)
1841 {
1842 // ascent = c->ENFN->font_max_ascent_get(c->ENDT, fmt->font.font);
1843 // descent = c->ENFN->font_max_descent_get(c->ENDT, fmt->font.font);
1844 ascent = ENFN->font_ascent_get(ENDT, fmt->font.font);
1845 descent = ENFN->font_descent_get(ENDT, fmt->font.font);
1846 if (fmt->linesize > 0)
1847 {
1848 if ((ascent + descent) < fmt->linesize)
1849 {
1850 ascent = ((fmt->linesize * ascent) / (ascent + descent));
1851 descent = fmt->linesize - ascent;
1852 }
1853 }
1854 else if (fmt->linerelsize > 0.0)
1855 {
1856 descent = descent * fmt->linerelsize;
1857 ascent = ascent * fmt->linerelsize;
1858 }
1859 descent += fmt->linegap;
1860 descent += ((ascent + descent) * fmt->linerelgap);
1861 if (*maxascent < ascent) *maxascent = ascent;
1862 if (*maxdescent < descent) *maxdescent = descent;
1863 if (fmt->linefill > 0.0)
1864 {
1865 int dh;
1866
1867 dh = obj->cur.geometry.h - (*maxascent + *maxdescent);
1868 if (dh < 0) dh = 0;
1869 dh = fmt->linefill * dh;
1870 *maxdescent += dh / 2;
1871 *maxascent += dh - (dh / 2);
1872 // FIXME: set flag that says "if heigh changes - reformat"
1873 }
1874 }
1875}
1876
1877/**
1878 * @internal
1879 * Create a new line using the info from the format and update the format
1880 * and context.
1881 *
1882 * @param c The context to work on - Not NULL.
1883 * @param fmt The format to use info from - NOT NULL.
1884 */
1885static void
1886_layout_line_new(Ctxt *c, Evas_Object_Textblock_Format *fmt)
1887{
1888 c->ln = calloc(1, sizeof(Evas_Object_Textblock_Line));
1889 c->align = fmt->halign;
1890 c->align_auto = fmt->halign_auto;
1891 c->marginl = fmt->margin.l;
1892 c->marginr = fmt->margin.r;
1893 c->par->lines = (Evas_Object_Textblock_Line *)eina_inlist_append(EINA_INLIST_GET(c->par->lines), EINA_INLIST_GET(c->ln));
1894 c->x = 0;
1895 c->maxascent = c->maxdescent = 0;
1896 c->ln->line_no = -1;
1897 c->ln->par = c->par;
1898}
1899
1900static inline Evas_Object_Textblock_Paragraph *
1901_layout_find_paragraph_by_y(Evas_Object_Textblock *o, Evas_Coord y)
1902{
1903 Evas_Object_Textblock_Paragraph *start, *par;
1904 int i;
1905
1906 start = o->paragraphs;
1907
1908 for (i = 0 ; i < TEXTBLOCK_PAR_INDEX_SIZE ; i++)
1909 {
1910 if (!o->par_index[i] || (o->par_index[i]->y > y))
1911 {
1912 break;
1913 }
1914 start = o->par_index[i];
1915 }
1916
1917 EINA_INLIST_FOREACH(start, par)
1918 {
1919 if ((par->y <= y) && (y < par->y + par->h))
1920 return par;
1921 }
1922
1923 return NULL;
1924}
1925
1926static inline Evas_Object_Textblock_Paragraph *
1927_layout_find_paragraph_by_line_no(Evas_Object_Textblock *o, int line_no)
1928{
1929 Evas_Object_Textblock_Paragraph *start, *par;
1930 int i;
1931
1932 start = o->paragraphs;
1933
1934 for (i = 0 ; i < TEXTBLOCK_PAR_INDEX_SIZE ; i++)
1935 {
1936 if (!o->par_index[i] || (o->par_index[i]->line_no > line_no))
1937 {
1938 break;
1939 }
1940 start = o->par_index[i];
1941 }
1942
1943 EINA_INLIST_FOREACH(start, par)
1944 {
1945 Evas_Object_Textblock_Paragraph *npar =
1946 (Evas_Object_Textblock_Paragraph *) EINA_INLIST_GET(par)->next;
1947 if ((par->line_no <= line_no) &&
1948 (!npar || (line_no < npar->line_no)))
1949 return par;
1950 }
1951
1952 return NULL;
1953}
1954/* End of rbtree index functios */
1955
1956/**
1957 * @internal
1958 * Create a new layout paragraph.
1959 * If c->par is not NULL, the paragraph is appended/prepended according
1960 * to the append parameter. If it is NULL, the paragraph is appended at
1961 * the end of the list.
1962 *
1963 * @param c The context to work on - Not NULL.
1964 * @param n the associated text node
1965 * @param append true to append, false to prpend.
1966 */
1967static void
1968_layout_paragraph_new(Ctxt *c, Evas_Object_Textblock_Node_Text *n,
1969 Eina_Bool append)
1970{
1971 Evas_Object_Textblock_Paragraph *rel_par = c->par;
1972 c->par = calloc(1, sizeof(Evas_Object_Textblock_Paragraph));
1973 if (append || !rel_par)
1974 c->paragraphs = (Evas_Object_Textblock_Paragraph *)
1975 eina_inlist_append_relative(EINA_INLIST_GET(c->paragraphs),
1976 EINA_INLIST_GET(c->par),
1977 EINA_INLIST_GET(rel_par));
1978 else
1979 c->paragraphs = (Evas_Object_Textblock_Paragraph *)
1980 eina_inlist_prepend_relative(EINA_INLIST_GET(c->paragraphs),
1981 EINA_INLIST_GET(c->par),
1982 EINA_INLIST_GET(rel_par));
1983
1984 c->ln = NULL;
1985 c->par->text_node = n;
1986 if (n)
1987 n->par = c->par;
1988 c->par->line_no = -1;
1989 c->par->visible = 1;
1990 c->o->num_paragraphs++;
1991}
1992
1993#ifdef BIDI_SUPPORT
1994/**
1995 * @internal
1996 * Update bidi paragraph props.
1997 *
1998 * @param par The paragraph to update
1999 */
2000static inline void
2001_layout_update_bidi_props(const Evas_Object_Textblock *o,
2002 Evas_Object_Textblock_Paragraph *par)
2003{
2004 if (par->text_node)
2005 {
2006 const Eina_Unicode *text;
2007 int *segment_idxs = NULL;
2008 text = eina_ustrbuf_string_get(par->text_node->unicode);
2009
2010 if (o->bidi_delimiters)
2011 segment_idxs = evas_bidi_segment_idxs_get(text, o->bidi_delimiters);
2012
2013 evas_bidi_paragraph_props_unref(par->bidi_props);
2014 par->bidi_props = evas_bidi_paragraph_props_get(text,
2015 eina_ustrbuf_length_get(par->text_node->unicode),
2016 segment_idxs);
2017 par->direction = EVAS_BIDI_PARAGRAPH_DIRECTION_IS_RTL(par->bidi_props) ?
2018 EVAS_BIDI_DIRECTION_RTL : EVAS_BIDI_DIRECTION_LTR;
2019 par->is_bidi = !!par->bidi_props;
2020 if (segment_idxs) free(segment_idxs);
2021 }
2022}
2023#endif
2024
2025
2026/**
2027 * @internal
2028 * Free the visual lines in the paragraph (logical items are kept)
2029 */
2030static void
2031_paragraph_clear(const Evas_Object *obj __UNUSED__,
2032 Evas_Object_Textblock_Paragraph *par)
2033{
2034 while (par->lines)
2035 {
2036 Evas_Object_Textblock_Line *ln;
2037
2038 ln = (Evas_Object_Textblock_Line *) par->lines;
2039 par->lines = (Evas_Object_Textblock_Line *)eina_inlist_remove(EINA_INLIST_GET(par->lines), EINA_INLIST_GET(par->lines));
2040 _line_free(ln);
2041 }
2042}
2043
2044/**
2045 * @internal
2046 * Free the layout paragraph and all of it's lines and logical items.
2047 */
2048static void
2049_paragraph_free(const Evas_Object *obj, Evas_Object_Textblock_Paragraph *par)
2050{
2051 Evas_Object_Textblock *o;
2052 o = (Evas_Object_Textblock *)(obj->object_data);
2053 _paragraph_clear(obj, par);
2054
2055 {
2056 Eina_List *i, *i_prev;
2057 Evas_Object_Textblock_Item *it;
2058 EINA_LIST_FOREACH_SAFE(par->logical_items, i, i_prev, it)
2059 {
2060 _item_free(obj, NULL, it);
2061 }
2062 eina_list_free(par->logical_items);
2063 }
2064#ifdef BIDI_SUPPORT
2065 if (par->bidi_props)
2066 evas_bidi_paragraph_props_unref(par->bidi_props);
2067#endif
2068 /* If we are the active par of the text node, set to NULL */
2069 if (par->text_node && (par->text_node->par == par))
2070 par->text_node->par = NULL;
2071
2072 o->num_paragraphs--;
2073
2074 free(par);
2075}
2076
2077/**
2078 * @internal
2079 * Clear all the paragraphs from the inlist pars.
2080 *
2081 * @param obj the evas object - Not NULL.
2082 * @param pars the paragraphs to clean - Not NULL.
2083 */
2084static void
2085_paragraphs_clear(const Evas_Object *obj, Evas_Object_Textblock_Paragraph *pars)
2086{
2087 Evas_Object_Textblock_Paragraph *par;
2088
2089 EINA_INLIST_FOREACH(EINA_INLIST_GET(pars), par)
2090 {
2091 _paragraph_clear(obj, par);
2092 }
2093}
2094
2095/**
2096 * @internal
2097 * Free the paragraphs from the inlist pars, the difference between this and
2098 * _paragraphs_clear is that the latter keeps the logical items and the par
2099 * items, while the former frees them as well.
2100 *
2101 * @param obj the evas object - Not NULL.
2102 * @param pars the paragraphs to clean - Not NULL.
2103 */
2104static void
2105_paragraphs_free(const Evas_Object *obj, Evas_Object_Textblock_Paragraph *pars)
2106{
2107 Evas_Object_Textblock *o;
2108 o = (Evas_Object_Textblock *)(obj->object_data);
2109
2110 o->num_paragraphs = 0;
2111
2112 while (pars)
2113 {
2114 Evas_Object_Textblock_Paragraph *par;
2115
2116 par = (Evas_Object_Textblock_Paragraph *) pars;
2117 pars = (Evas_Object_Textblock_Paragraph *)eina_inlist_remove(EINA_INLIST_GET(pars), EINA_INLIST_GET(par));
2118 _paragraph_free(obj, par);
2119 }
2120}
2121
2122/**
2123 * @internal
2124 * Push fmt to the format stack, if fmt is NULL, will fush a default item.
2125 *
2126 * @param c the context to work on - Not NULL.
2127 * @param fmt the format to push.
2128 * @see _layout_format_pop()
2129 */
2130static Evas_Object_Textblock_Format *
2131_layout_format_push(Ctxt *c, Evas_Object_Textblock_Format *fmt,
2132 Evas_Object_Textblock_Node_Format *fnode)
2133{
2134 if (fmt)
2135 {
2136 fmt = _format_dup(c->obj, fmt);
2137 c->format_stack = eina_list_prepend(c->format_stack, fmt);
2138 fmt->fnode = fnode;
2139 }
2140 else
2141 {
2142 fmt = calloc(1, sizeof(Evas_Object_Textblock_Format));
2143 c->format_stack = eina_list_prepend(c->format_stack, fmt);
2144 fmt->ref = 1;
2145 fmt->halign = 0.0;
2146 fmt->halign_auto = EINA_TRUE;
2147 fmt->valign = -1.0;
2148 fmt->style = EVAS_TEXT_STYLE_PLAIN;
2149 fmt->tabstops = 32;
2150 fmt->linesize = 0;
2151 fmt->linerelsize = 0.0;
2152 fmt->linegap = 0;
2153 fmt->underline_dash_width = 6;
2154 fmt->underline_dash_gap = 2;
2155 fmt->linerelgap = 0.0;
2156 fmt->password = 1;
2157 }
2158 return fmt;
2159}
2160
2161/**
2162 * @internal
2163 * Pop fmt to the format stack, if there's something in the stack free fmt
2164 * and set it to point to the next item instead, else return fmt.
2165 *
2166 * @param c the context to work on - Not NULL.
2167 * @param format - the text of the format to free (assured to start with '-').
2168 * @return the next format in the stack, or format if there's none.
2169 * @see _layout_format_push()
2170 */
2171static Evas_Object_Textblock_Format *
2172_layout_format_pop(Ctxt *c, const char *format)
2173{
2174 Evas_Object_Textblock_Format *fmt = eina_list_data_get(c->format_stack);
2175
2176 if ((c->format_stack) && (c->format_stack->next))
2177 {
2178 Eina_List *redo_nodes = NULL;
2179
2180 /* Generic pop, should just pop. */
2181 if (((format[0] == ' ') && !format[1]) ||
2182 !format[0])
2183 {
2184 _format_unref_free(c->obj, fmt);
2185 c->format_stack =
2186 eina_list_remove_list(c->format_stack, c->format_stack);
2187 }
2188 else
2189 {
2190 size_t len = strlen(format);
2191 Eina_List *i, *i_next;
2192 /* Remove only the matching format. */
2193 EINA_LIST_FOREACH_SAFE(c->format_stack, i, i_next, fmt)
2194 {
2195 /* Stop when we reach the base item */
2196 if (!i_next)
2197 break;
2198
2199 c->format_stack =
2200 eina_list_remove_list(c->format_stack, c->format_stack);
2201
2202 /* Make sure the ending tag matches the starting tag.
2203 * I.e whole of the ending tag matches the start of the
2204 * starting tag, and the starting tag's next char is either
2205 * NULL or white. Skip the starting '+'. */
2206 if (_FORMAT_IS_CLOSER_OF(
2207 fmt->fnode->orig_format, format, len))
2208 {
2209 _format_unref_free(c->obj, fmt);
2210 break;
2211 }
2212 else
2213 {
2214 redo_nodes = eina_list_prepend(redo_nodes, fmt->fnode);
2215 _format_unref_free(c->obj, fmt);
2216 }
2217 }
2218 }
2219
2220 /* Redo all the nodes needed to be redone */
2221 {
2222 Evas_Object_Textblock_Node_Format *fnode;
2223 Eina_List *i, *i_next;
2224
2225 EINA_LIST_FOREACH_SAFE(redo_nodes, i, i_next, fnode)
2226 {
2227 /* FIXME: Actually do something with the new acquired padding,
2228 * the can be different and affect our padding! */
2229 Evas_Coord style_pad_l, style_pad_r, style_pad_t, style_pad_b;
2230 style_pad_l = style_pad_r = style_pad_t = style_pad_b = 0;
2231 redo_nodes = eina_list_remove_list(redo_nodes, i);
2232 fmt = eina_list_data_get(c->format_stack);
2233 _layout_do_format(c->obj, c, &fmt, fnode,
2234 &style_pad_l, &style_pad_r,
2235 &style_pad_t, &style_pad_b, EINA_FALSE);
2236 }
2237 }
2238
2239 fmt = eina_list_data_get(c->format_stack);
2240 }
2241 return fmt;
2242}
2243
2244/**
2245 * @internal
2246 * Parse item and fill fmt with the item.
2247 *
2248 * @param c the context to work on - Not NULL.
2249 * @param fmt the format to fill - not null.
2250 */
2251static void
2252_layout_format_value_handle(Ctxt *c, Evas_Object_Textblock_Format *fmt, const char *item)
2253{
2254 const char *key = NULL, *val = NULL;
2255
2256 _format_param_parse(item, &key, &val);
2257 if ((key) && (val)) _format_command(c->obj, fmt, key, val);
2258 if (key) eina_stringshare_del(key);
2259 if (val) eina_stringshare_del(val);
2260 c->align = fmt->halign;
2261 c->align_auto = fmt->halign_auto;
2262 c->marginl = fmt->margin.l;
2263 c->marginr = fmt->margin.r;
2264}
2265
2266#define VSIZE_FULL 0
2267#define VSIZE_ASCENT 1
2268
2269#define SIZE 0
2270#define SIZE_ABS 1
2271#define SIZE_REL 2
2272
2273/**
2274 * @internal
2275 * Get the current line's alignment from the context.
2276 *
2277 * @param c the context to work on - Not NULL.
2278 */
2279static inline double
2280_layout_line_align_get(Ctxt *c)
2281{
2282#ifdef BIDI_SUPPORT
2283 if (c->align_auto && c->ln)
2284 {
2285 if (c->ln->items && c->ln->items->text_node &&
2286 (c->ln->par->direction == EVAS_BIDI_DIRECTION_RTL))
2287 {
2288 /* Align right*/
2289 return 1.0;
2290 }
2291 else
2292 {
2293 /* Align left */
2294 return 0.0;
2295 }
2296 }
2297#endif
2298 return c->align;
2299}
2300
2301#ifdef BIDI_SUPPORT
2302/**
2303 * @internal
2304 * Reorder the items in visual order
2305 *
2306 * @param line the line to reorder
2307 */
2308static void
2309_layout_line_reorder(Evas_Object_Textblock_Line *line)
2310{
2311 /*FIXME: do it a bit more efficient - not very efficient ATM. */
2312 Evas_Object_Textblock_Item *it;
2313 EvasBiDiStrIndex *v_to_l = NULL;
2314 Evas_Coord x;
2315 size_t start, end;
2316 size_t len;
2317
2318 if (line->items && line->items->text_node &&
2319 line->par->bidi_props)
2320 {
2321 Evas_BiDi_Paragraph_Props *props;
2322 props = line->par->bidi_props;
2323 start = end = line->items->text_pos;
2324
2325 /* Find the first and last positions in the line */
2326
2327 EINA_INLIST_FOREACH(line->items, it)
2328 {
2329 if (it->text_pos < start)
2330 {
2331 start = it->text_pos;
2332 }
2333 else
2334 {
2335 int tlen;
2336 tlen = (it->type == EVAS_TEXTBLOCK_ITEM_TEXT) ?
2337 _ITEM_TEXT(it)->text_props.text_len : 1;
2338 if (it->text_pos + tlen > end)
2339 {
2340 end = it->text_pos + tlen;
2341 }
2342 }
2343 }
2344
2345 len = end - start;
2346 evas_bidi_props_reorder_line(NULL, start, len, props, &v_to_l);
2347
2348 /* Update visual pos */
2349 {
2350 Evas_Object_Textblock_Item *i;
2351 i = line->items;
2352 while (i)
2353 {
2354 i->visual_pos = evas_bidi_position_logical_to_visual(
2355 v_to_l, len, i->text_pos - start);
2356 i = (Evas_Object_Textblock_Item *) EINA_INLIST_GET(i)->next;
2357 }
2358 }
2359
2360 /*FIXME: not very efficient, sort the items arrays. Anyhow, should only
2361 * reorder if it's a bidi paragraph */
2362 {
2363 Evas_Object_Textblock_Item *i, *j, *min;
2364 i = line->items;
2365 while (i)
2366 {
2367 min = i;
2368 EINA_INLIST_FOREACH(i, j)
2369 {
2370 if (j->visual_pos < min->visual_pos)
2371 {
2372 min = j;
2373 }
2374 }
2375 if (min != i)
2376 {
2377 line->items = (Evas_Object_Textblock_Item *) eina_inlist_remove(EINA_INLIST_GET(line->items), EINA_INLIST_GET(min));
2378 line->items = (Evas_Object_Textblock_Item *) eina_inlist_prepend_relative(EINA_INLIST_GET(line->items), EINA_INLIST_GET(min), EINA_INLIST_GET(i));
2379 }
2380
2381 i = (Evas_Object_Textblock_Item *) EINA_INLIST_GET(min)->next;
2382 }
2383 }
2384 }
2385
2386 if (v_to_l) free(v_to_l);
2387 x = 0;
2388 EINA_INLIST_FOREACH(line->items, it)
2389 {
2390 it->x = x;
2391 x += it->adv;
2392 }
2393}
2394#endif
2395
2396/* FIXME: doc */
2397static void
2398_layout_calculate_format_item_size(const Evas_Object *obj,
2399 const Evas_Object_Textblock_Format_Item *fi,
2400 Evas_Coord *maxascent, Evas_Coord *maxdescent,
2401 Evas_Coord *_y, Evas_Coord *_w, Evas_Coord *_h)
2402{
2403 /* Adjust sizes according to current line height/scale */
2404 Evas_Coord w, h;
2405 const char *p, *s;
2406
2407 s = fi->item;
2408 w = fi->parent.w;
2409 h = fi->parent.h;
2410 switch (fi->size)
2411 {
2412 case SIZE:
2413 p = strstr(s, " size=");
2414 if (p)
2415 {
2416 p += 6;
2417 if (sscanf(p, "%ix%i", &w, &h) == 2)
2418 {
2419 w = w * obj->cur.scale;
2420 h = h * obj->cur.scale;
2421 }
2422 }
2423 break;
2424 case SIZE_REL:
2425 p = strstr((char *) s, " relsize=");
2426 p += 9;
2427 if (sscanf(p, "%ix%i", &w, &h) == 2)
2428 {
2429 int sz = 1;
2430 if (fi->vsize == VSIZE_FULL)
2431 {
2432 sz = *maxdescent + *maxascent;
2433 }
2434 else if (fi->vsize == VSIZE_ASCENT)
2435 {
2436 sz = *maxascent;
2437 }
2438 w = (w * sz) / h;
2439 h = sz;
2440 }
2441 break;
2442 case SIZE_ABS:
2443 /* Nothing to do */
2444 default:
2445 break;
2446 }
2447
2448 switch (fi->size)
2449 {
2450 case SIZE:
2451 case SIZE_ABS:
2452 switch (fi->vsize)
2453 {
2454 case VSIZE_FULL:
2455 if (h > (*maxdescent + *maxascent))
2456 {
2457 *maxascent += h - (*maxdescent + *maxascent);
2458 *_y = -*maxascent;
2459 }
2460 else
2461 *_y = -(h - *maxdescent);
2462 break;
2463 case VSIZE_ASCENT:
2464 if (h > *maxascent)
2465 {
2466 *maxascent = h;
2467 *_y = -h;
2468 }
2469 else
2470 *_y = -h;
2471 break;
2472 default:
2473 break;
2474 }
2475 break;
2476 case SIZE_REL:
2477 switch (fi->vsize)
2478 {
2479 case VSIZE_FULL:
2480 case VSIZE_ASCENT:
2481 *_y = -*maxascent;
2482 break;
2483 default:
2484 break;
2485 }
2486 break;
2487 default:
2488 break;
2489 }
2490
2491 *_w = w;
2492 *_h = h;
2493}
2494
2495/**
2496 * @internal
2497 * Order the items in the line, update it's properties and update it's
2498 * corresponding paragraph.
2499 *
2500 * @param c the context to work on - Not NULL.
2501 * @param fmt the format to use.
2502 * @param add_line true if we should create a line, false otherwise.
2503 */
2504static void
2505_layout_line_finalize(Ctxt *c, Evas_Object_Textblock_Format *fmt)
2506{
2507 Evas_Object_Textblock_Item *it;
2508 Evas_Coord x = 0;
2509
2510 /* If there are no text items yet, calc ascent/descent
2511 * according to the current format. */
2512 if (c->maxascent + c->maxdescent == 0)
2513 _layout_format_ascent_descent_adjust(c->obj, &c->maxascent,
2514 &c->maxdescent, fmt);
2515
2516 /* Adjust all the item sizes according to the final line size,
2517 * and update the x positions of all the items of the line. */
2518 EINA_INLIST_FOREACH(c->ln->items, it)
2519 {
2520 if (it->type == EVAS_TEXTBLOCK_ITEM_FORMAT)
2521 {
2522 Evas_Object_Textblock_Format_Item *fi = _ITEM_FORMAT(it);
2523 if (!fi->formatme) goto loop_advance;
2524 _layout_calculate_format_item_size(c->obj, fi, &c->maxascent,
2525 &c->maxdescent, &fi->y, &fi->parent.w, &fi->parent.h);
2526 fi->parent.adv = fi->parent.w;
2527 }
2528
2529loop_advance:
2530 it->x = x;
2531 x += it->adv;
2532
2533 if ((it->x + it->adv) > c->ln->w) c->ln->w = it->x + it->adv;
2534 }
2535
2536 c->ln->y = (c->y - c->par->y) + c->o->style_pad.t;
2537 c->ln->h = c->maxascent + c->maxdescent;
2538 c->ln->baseline = c->maxascent;
2539 if (c->have_underline2)
2540 {
2541 if (c->maxdescent < 4) c->underline_extend = 4 - c->maxdescent;
2542 }
2543 else if (c->have_underline)
2544 {
2545 if (c->maxdescent < 2) c->underline_extend = 2 - c->maxdescent;
2546 }
2547 c->ln->line_no = c->line_no - c->ln->par->line_no;
2548 c->line_no++;
2549 c->y += c->maxascent + c->maxdescent;
2550 if (c->w >= 0)
2551 {
2552 c->ln->x = c->marginl + c->o->style_pad.l +
2553 ((c->w - c->ln->w -
2554 c->o->style_pad.l - c->o->style_pad.r -
2555 c->marginl - c->marginr) * _layout_line_align_get(c));
2556 }
2557 else
2558 {
2559 c->ln->x = c->marginl + c->o->style_pad.l;
2560 }
2561
2562 c->par->h = c->ln->y + c->ln->h;
2563 if (c->ln->w > c->par->w)
2564 c->par->w = c->ln->w;
2565
2566 {
2567 Evas_Coord new_wmax = c->ln->w +
2568 c->marginl + c->marginr - (c->o->style_pad.l + c->o->style_pad.r);
2569 if (new_wmax > c->wmax)
2570 c->wmax = new_wmax;
2571 }
2572}
2573
2574/**
2575 * @internal
2576 * Create a new line and append it to the lines in the context.
2577 *
2578 * @param c the context to work on - Not NULL.
2579 * @param fmt the format to use.
2580 * @param add_line true if we should create a line, false otherwise.
2581 */
2582static void
2583_layout_line_advance(Ctxt *c, Evas_Object_Textblock_Format *fmt)
2584{
2585 _layout_line_finalize(c, fmt);
2586 _layout_line_new(c, fmt);
2587}
2588
2589/**
2590 * @internal
2591 * Create a new text layout item from the string and the format.
2592 *
2593 * @param c the context to work on - Not NULL.
2594 * @param fmt the format to use.
2595 * @param str the string to use.
2596 * @param len the length of the string.
2597 */
2598static Evas_Object_Textblock_Text_Item *
2599_layout_text_item_new(Ctxt *c __UNUSED__, Evas_Object_Textblock_Format *fmt)
2600{
2601 Evas_Object_Textblock_Text_Item *ti;
2602
2603 ti = calloc(1, sizeof(Evas_Object_Textblock_Text_Item));
2604 ti->parent.format = fmt;
2605 ti->parent.format->ref++;
2606 ti->parent.type = EVAS_TEXTBLOCK_ITEM_TEXT;
2607 return ti;
2608}
2609
2610/**
2611 * @internal
2612 * Return the cutoff of the text in the text item.
2613 *
2614 * @param c the context to work on - Not NULL.
2615 * @param fmt the format to use. - Not NULL.
2616 * @param it the item to check - Not null.
2617 * @return -1 if there is no cutoff (either because there is really none,
2618 * or because of an error), cutoff index on success.
2619 */
2620static int
2621_layout_text_cutoff_get(Ctxt *c, Evas_Object_Textblock_Format *fmt,
2622 const Evas_Object_Textblock_Text_Item *ti)
2623{
2624 if (fmt->font.font)
2625 {
2626 Evas_Coord x;
2627 x = c->w - c->o->style_pad.l - c->o->style_pad.r - c->marginl -
2628 c->marginr - c->x - ti->x_adjustment;
2629 if (x < 0)
2630 x = 0;
2631 return c->ENFN->font_last_up_to_pos(c->ENDT, fmt->font.font,
2632 &ti->text_props, x, 0);
2633 }
2634 return -1;
2635}
2636
2637/**
2638 * @internal
2639 * Split before cut, and strip if str[cut - 1] is a whitespace.
2640 *
2641 * @param c the context to work on - Not NULL.
2642 * @param ti the item to cut - not null.
2643 * @param lti the logical list item of the item.
2644 * @param cut the cut index.
2645 * @return the second (newly created) item.
2646 */
2647static Evas_Object_Textblock_Text_Item *
2648_layout_item_text_split_strip_white(Ctxt *c,
2649 Evas_Object_Textblock_Text_Item *ti, Eina_List *lti, size_t cut)
2650{
2651 const Eina_Unicode *ts;
2652 Evas_Object_Textblock_Text_Item *new_ti = NULL, *white_ti = NULL;
2653
2654 ts = GET_ITEM_TEXT(ti);
2655
2656 if (!IS_AT_END(ti, cut) && (ti->text_props.text_len > 0))
2657 {
2658 new_ti = _layout_text_item_new(c, ti->parent.format);
2659 new_ti->parent.text_node = ti->parent.text_node;
2660 new_ti->parent.text_pos = ti->parent.text_pos + cut;
2661 new_ti->parent.merge = EINA_TRUE;
2662
2663 evas_common_text_props_split(&ti->text_props,
2664 &new_ti->text_props, cut);
2665 _layout_text_add_logical_item(c, new_ti, lti);
2666 }
2667
2668 /* Strip the previous white if needed */
2669 if ((cut >= 1) && _is_white(ts[cut - 1]) && (ti->text_props.text_len > 0))
2670 {
2671 if (cut - 1 > 0)
2672 {
2673 size_t white_cut = cut - 1;
2674 white_ti = _layout_text_item_new(c, ti->parent.format);
2675 white_ti->parent.text_node = ti->parent.text_node;
2676 white_ti->parent.text_pos = ti->parent.text_pos + white_cut;
2677 white_ti->parent.merge = EINA_TRUE;
2678 white_ti->parent.visually_deleted = EINA_TRUE;
2679
2680 evas_common_text_props_split(&ti->text_props,
2681 &white_ti->text_props, white_cut);
2682 _layout_text_add_logical_item(c, white_ti, lti);
2683 }
2684 else
2685 {
2686 /* Mark this one as the visually deleted. */
2687 ti->parent.visually_deleted = EINA_TRUE;
2688 }
2689 }
2690
2691 if (new_ti || white_ti)
2692 {
2693 _text_item_update_sizes(c, ti);
2694 }
2695 return new_ti;
2696}
2697
2698/**
2699 * @internal
2700 * Merge item2 into item1 and free item2.
2701 *
2702 * @param c the context to work on - Not NULL.
2703 * @param item1 the item to copy to
2704 * @param item2 the item to copy from
2705 */
2706static void
2707_layout_item_merge_and_free(Ctxt *c,
2708 Evas_Object_Textblock_Text_Item *item1,
2709 Evas_Object_Textblock_Text_Item *item2)
2710{
2711 evas_common_text_props_merge(&item1->text_props,
2712 &item2->text_props);
2713
2714 _text_item_update_sizes(c, item1);
2715
2716 item1->parent.merge = EINA_FALSE;
2717 item1->parent.visually_deleted = EINA_FALSE;
2718
2719 _item_free(c->obj, NULL, _ITEM(item2));
2720}
2721
2722/**
2723 * @internal
2724 * Calculates an item's size.
2725 *
2726 * @param c the context
2727 * @param it the item itself.
2728 */
2729static void
2730_text_item_update_sizes(Ctxt *c, Evas_Object_Textblock_Text_Item *ti)
2731{
2732 int tw, th, inset, advw;
2733 const Evas_Object_Textblock_Format *fmt = ti->parent.format;
2734 int shad_sz = 0, shad_dst = 0, out_sz = 0;
2735 int dx = 0, minx = 0, maxx = 0, shx1, shx2;
2736
2737 tw = th = 0;
2738 if (fmt->font.font)
2739 c->ENFN->font_string_size_get(c->ENDT, fmt->font.font,
2740 &ti->text_props, &tw, &th);
2741 inset = 0;
2742 if (fmt->font.font)
2743 inset = c->ENFN->font_inset_get(c->ENDT, fmt->font.font,
2744 &ti->text_props);
2745 advw = 0;
2746 if (fmt->font.font)
2747 advw = c->ENFN->font_h_advance_get(c->ENDT, fmt->font.font,
2748 &ti->text_props);
2749
2750
2751 /* These adjustments are calculated and thus heavily linked to those in
2752 * textblock_render!!! Don't change one without the other. */
2753
2754 switch (ti->parent.format->style & EVAS_TEXT_STYLE_MASK_BASIC)
2755 {
2756 case EVAS_TEXT_STYLE_SHADOW:
2757 shad_dst = 1;
2758 break;
2759 case EVAS_TEXT_STYLE_OUTLINE_SHADOW:
2760 case EVAS_TEXT_STYLE_FAR_SHADOW:
2761 shad_dst = 2;
2762 out_sz = 1;
2763 break;
2764 case EVAS_TEXT_STYLE_OUTLINE_SOFT_SHADOW:
2765 shad_dst = 1;
2766 shad_sz = 2;
2767 out_sz = 1;
2768 break;
2769 case EVAS_TEXT_STYLE_FAR_SOFT_SHADOW:
2770 shad_dst = 2;
2771 shad_sz = 2;
2772 break;
2773 case EVAS_TEXT_STYLE_SOFT_SHADOW:
2774 shad_dst = 1;
2775 shad_sz = 2;
2776 break;
2777 case EVAS_TEXT_STYLE_GLOW:
2778 case EVAS_TEXT_STYLE_SOFT_OUTLINE:
2779 out_sz = 2;
2780 break;
2781 case EVAS_TEXT_STYLE_OUTLINE:
2782 out_sz = 1;
2783 break;
2784 default:
2785 break;
2786 }
2787 switch (ti->parent.format->style & EVAS_TEXT_STYLE_MASK_SHADOW_DIRECTION)
2788 {
2789 case EVAS_TEXT_STYLE_SHADOW_DIRECTION_BOTTOM_LEFT:
2790 case EVAS_TEXT_STYLE_SHADOW_DIRECTION_LEFT:
2791 case EVAS_TEXT_STYLE_SHADOW_DIRECTION_TOP_LEFT:
2792 dx = -1;
2793 break;
2794 case EVAS_TEXT_STYLE_SHADOW_DIRECTION_BOTTOM_RIGHT:
2795 case EVAS_TEXT_STYLE_SHADOW_DIRECTION_TOP_RIGHT:
2796 case EVAS_TEXT_STYLE_SHADOW_DIRECTION_RIGHT:
2797 dx = 1;
2798 case EVAS_TEXT_STYLE_SHADOW_DIRECTION_TOP:
2799 case EVAS_TEXT_STYLE_SHADOW_DIRECTION_BOTTOM:
2800 default:
2801 dx = 0;
2802 break;
2803 }
2804 minx = -out_sz;
2805 maxx = out_sz;
2806 shx1 = dx * shad_dst;
2807 shx1 -= shad_sz;
2808 shx2 = dx * shad_dst;
2809 shx2 += shad_sz;
2810 if (shx1 < minx) minx = shx1;
2811 if (shx2 > maxx) maxx = shx2;
2812 inset += -minx;
2813 ti->x_adjustment = maxx - minx;
2814
2815 ti->inset = inset;
2816 ti->parent.w = tw + ti->x_adjustment;
2817 ti->parent.h = th;
2818 ti->parent.adv = advw;
2819 ti->parent.x = 0;
2820}
2821
2822/**
2823 * @internal
2824 * Adds the item to the list, updates the item's properties (e.g, x,w,h)
2825 *
2826 * @param c the context
2827 * @param it the item itself.
2828 * @param rel item ti will be appened after, NULL = last.
2829 */
2830static void
2831_layout_text_add_logical_item(Ctxt *c, Evas_Object_Textblock_Text_Item *ti,
2832 Eina_List *rel)
2833{
2834 _text_item_update_sizes(c, ti);
2835
2836 c->par->logical_items = eina_list_append_relative_list(
2837 c->par->logical_items, ti, rel);
2838}
2839
2840/**
2841 * @internal
2842 * Appends the text from node n starting at start ending at off to the layout.
2843 * It uses the fmt for the formatting.
2844 *
2845 * @param c the current context- NOT NULL.
2846 * @param fmt the format to use.
2847 * @param n the text node. - Not null.
2848 * @param start the start position. - in range.
2849 * @param off the offset - start + offset in range. if offset is -1, it'll add everything to the end of the string if offset = 0 it'll return with doing nothing.
2850 * @param repch a replacement char to print instead of the original string, for example, * when working with passwords.
2851 */
2852static void
2853_layout_text_append(Ctxt *c, Evas_Object_Textblock_Format *fmt, Evas_Object_Textblock_Node_Text *n, int start, int off, const char *repch)
2854{
2855 const Eina_Unicode *str = EINA_UNICODE_EMPTY_STRING;
2856 const Eina_Unicode *tbase;
2857 Evas_Object_Textblock_Text_Item *ti;
2858 size_t cur_len = 0;
2859 Eina_Unicode urepch = 0;
2860
2861 /* prepare a working copy of the string, either filled by the repch or
2862 * filled with the true values */
2863 if (n)
2864 {
2865 int len;
2866 int orig_off = off;
2867
2868 /* Figure out if we want to bail, work with an empty string,
2869 * or continue with a slice of the passed string */
2870 len = eina_ustrbuf_length_get(n->unicode);
2871 if (off == 0) return;
2872 else if (off < 0) off = len - start;
2873
2874 if (start < 0)
2875 {
2876 start = 0;
2877 }
2878 else if ((start == 0) && (off == 0) && (orig_off == -1))
2879 {
2880 /* Special case that means that we need to add an empty
2881 * item */
2882 str = EINA_UNICODE_EMPTY_STRING;
2883 goto skip;
2884 }
2885 else if ((start >= len) || (start + off > len))
2886 {
2887 return;
2888 }
2889
2890 /* If we work with a replacement char, create a string which is the same
2891 * but with replacement chars instead of regular chars. */
2892 if ((fmt->password) && (repch) && (eina_ustrbuf_length_get(n->unicode)))
2893 {
2894 int i, ind;
2895 Eina_Unicode *ptr;
2896
2897 tbase = str = ptr = alloca((off + 1) * sizeof(Eina_Unicode));
2898 ind = 0;
2899 urepch = eina_unicode_utf8_get_next(repch, &ind);
2900 for (i = 0 ; i < off; ptr++, i++)
2901 *ptr = urepch;
2902 *ptr = 0;
2903 }
2904 /* Use the string, just cut the relevant parts */
2905 else
2906 {
2907 str = eina_ustrbuf_string_get(n->unicode) + start;
2908 }
2909
2910 cur_len = off;
2911 }
2912
2913skip:
2914 tbase = str;
2915
2916 /* If there's no parent text node, only create an empty item */
2917 if (!n)
2918 {
2919 ti = _layout_text_item_new(c, fmt);
2920 ti->parent.text_node = NULL;
2921 ti->parent.text_pos = 0;
2922 _layout_text_add_logical_item(c, ti, NULL);
2923
2924 return;
2925 }
2926
2927 while (cur_len > 0)
2928 {
2929 Evas_Font_Instance *script_fi = NULL;
2930 int script_len, tmp_cut;
2931 Evas_Script_Type script;
2932
2933 script_len = cur_len;
2934
2935 tmp_cut = evas_common_language_script_end_of_run_get(str,
2936 c->par->bidi_props, start + str - tbase, script_len);
2937 if (tmp_cut > 0)
2938 {
2939 script_len = tmp_cut;
2940 }
2941 cur_len -= script_len;
2942
2943 script = evas_common_language_script_type_get(str, script_len);
2944
2945
2946 while (script_len > 0)
2947 {
2948 Evas_Font_Instance *cur_fi = NULL;
2949 int run_len = script_len;
2950 ti = _layout_text_item_new(c, fmt);
2951 ti->parent.text_node = n;
2952 ti->parent.text_pos = start + str - tbase;
2953
2954 if (ti->parent.format->font.font)
2955 {
2956 run_len = c->ENFN->font_run_end_get(c->ENDT,
2957 ti->parent.format->font.font, &script_fi, &cur_fi,
2958 script, str, script_len);
2959 }
2960
2961 evas_common_text_props_bidi_set(&ti->text_props,
2962 c->par->bidi_props, ti->parent.text_pos);
2963 evas_common_text_props_script_set(&ti->text_props, script);
2964
2965 if (cur_fi)
2966 {
2967 c->ENFN->font_text_props_info_create(c->ENDT,
2968 cur_fi, str, &ti->text_props, c->par->bidi_props,
2969 ti->parent.text_pos, run_len);
2970 }
2971 str += run_len;
2972 script_len -= run_len;
2973
2974 _layout_text_add_logical_item(c, ti, NULL);
2975 }
2976 }
2977}
2978
2979/**
2980 * @internal
2981 * Add a format item from the format node n and the item item.
2982 *
2983 * @param c the current context- NOT NULL.
2984 * @param n the source format node - not null.
2985 * @param item the format text.
2986 *
2987 * @return the new format item.
2988 */
2989static Evas_Object_Textblock_Format_Item *
2990_layout_format_item_add(Ctxt *c, Evas_Object_Textblock_Node_Format *n, const char *item, Evas_Object_Textblock_Format *fmt)
2991{
2992 Evas_Object_Textblock_Format_Item *fi;
2993
2994 fi = calloc(1, sizeof(Evas_Object_Textblock_Format_Item));
2995 fi->item = eina_stringshare_add(item);
2996 fi->parent.type = EVAS_TEXTBLOCK_ITEM_FORMAT;
2997 fi->parent.format = fmt;
2998 fi->parent.format->ref++;
2999 c->par->logical_items = eina_list_append(c->par->logical_items, fi);
3000 if (n)
3001 {
3002 fi->parent.text_node = n->text_node;
3003 /* FIXME: make it more efficient */
3004 fi->parent.text_pos = _evas_textblock_node_format_pos_get(n);
3005#ifdef BIDI_SUPPORT
3006 fi->bidi_dir = (evas_bidi_is_rtl_char(
3007 c->par->bidi_props,
3008 0,
3009 fi->parent.text_pos)) ?
3010 EVAS_BIDI_DIRECTION_RTL : EVAS_BIDI_DIRECTION_LTR;
3011#else
3012 fi->bidi_dir = EVAS_BIDI_DIRECTION_LTR;
3013#endif
3014 }
3015 return fi;
3016}
3017
3018/**
3019 * @internal
3020 * Should be call after we finish filling a format.
3021 * FIXME: doc.
3022 */
3023static void
3024_format_finalize(Evas_Object *obj, Evas_Object_Textblock_Format *fmt)
3025{
3026 void *of;
3027
3028 of = fmt->font.font;
3029
3030 fmt->font.font = evas_font_load(obj->layer->evas, fmt->font.fdesc,
3031 fmt->font.source, (int)(((double) fmt->font.size) * obj->cur.scale));
3032 if (of) evas_font_free(obj->layer->evas, of);
3033}
3034
3035/**
3036 * @internal
3037 * Returns true if the item is a tab
3038 * @def _IS_TAB(item)
3039 */
3040#define _IS_TAB(item) \
3041 (!strcmp(item, "tab") || !strcmp(item, "\t") || !strcmp(item, "\\t"))
3042/**
3043 * @internal
3044 * Returns true if the item is a line spearator, false otherwise
3045 * @def _IS_LINE_SEPARATOR(item)
3046 */
3047#define _IS_LINE_SEPARATOR(item) \
3048 (!strcmp(item, "br") || !strcmp(item, "\n") || !strcmp(item, "\\n"))
3049/**
3050 * @internal
3051 * Returns true if the item is a paragraph separator, false otherwise
3052 * @def _IS_PARAGRAPH_SEPARATOR(item)
3053 */
3054#define _IS_PARAGRAPH_SEPARATOR_SIMPLE(item) \
3055 (!strcmp(item, "ps"))
3056/**
3057 * @internal
3058 * Returns true if the item is a paragraph separator, false otherwise
3059 * takes legacy mode into account.
3060 * @def _IS_PARAGRAPH_SEPARATOR(item)
3061 */
3062#define _IS_PARAGRAPH_SEPARATOR(o, item) \
3063 (_IS_PARAGRAPH_SEPARATOR_SIMPLE(item) || \
3064 (o->legacy_newline && _IS_LINE_SEPARATOR(item))) /* Paragraph separator */
3065
3066/**
3067 * @internal
3068 * Handles a format by processing a format node. It returns the relevant format
3069 * through _fmt and updates the padding through style_pad_*. If needed,
3070 * it creates a format item.
3071 *
3072 * @param obj the evas object - NOT NULL.
3073 * @param c the current context- NOT NULL.
3074 * @param _fmt the format that holds the result.
3075 * @param n the source format node - not null.
3076 * @param style_pad_l the pad to update.
3077 * @param style_pad_r the pad to update.
3078 * @param style_pad_t the pad to update.
3079 * @param style_pad_b the pad to update.
3080 * @param create_item Create a new format item if true, only process otherwise.
3081 */
3082static void
3083_layout_do_format(const Evas_Object *obj __UNUSED__, Ctxt *c,
3084 Evas_Object_Textblock_Format **_fmt, Evas_Object_Textblock_Node_Format *n,
3085 int *style_pad_l, int *style_pad_r, int *style_pad_t, int *style_pad_b,
3086 Eina_Bool create_item)
3087{
3088 Evas_Object_Textblock_Format *fmt = *_fmt;
3089 /* FIXME: comment the algo */
3090
3091 const char *s;
3092 const char *item;
3093 int handled = 0;
3094
3095 s = n->format;
3096 if (!strncmp(s, "item ", 5))
3097 {
3098 // one of:
3099 // item size=20x10 href=name
3100 // item relsize=20x10 href=name
3101 // item abssize=20x10 href=name
3102 //
3103 // optional arguments:
3104 // vsize=full
3105 // vsize=ascent
3106 //
3107 // size == item size (modifies line size) - can be multiplied by
3108 // scale factor
3109 // relsize == relative size (height is current font height, width
3110 // modified accordingly keeping aspect)
3111 // abssize == absolute size (modifies line size) - never mulitplied by
3112 // scale factor
3113 // href == name of item - to be found and matched later and used for
3114 // positioning
3115 Evas_Object_Textblock_Format_Item *fi;
3116 int w = 1, h = 1;
3117 int vsize = 0, size = 0;
3118 char *p;
3119
3120 // don't care
3121 //href = strstr(s, " href=");
3122 p = strstr(s, " vsize=");
3123 if (p)
3124 {
3125 p += 7;
3126 if (!strncmp(p, "full", 4)) vsize = VSIZE_FULL;
3127 else if (!strncmp(p, "ascent", 6)) vsize = VSIZE_ASCENT;
3128 }
3129 p = strstr(s, " size=");
3130 if (p)
3131 {
3132 p += 6;
3133 if (sscanf(p, "%ix%i", &w, &h) == 2)
3134 {
3135 /* this is handled somewhere else because it depends
3136 * on the current scaling factor of the object which
3137 * may change and break because the results of this
3138 * function are cached */
3139 size = SIZE;
3140 }
3141 }
3142 else
3143 {
3144 p = strstr(s, " absize=");
3145 if (p)
3146 {
3147 p += 8;
3148 if (sscanf(p, "%ix%i", &w, &h) == 2)
3149 {
3150 size = SIZE_ABS;
3151 }
3152 }
3153 else
3154 {
3155 p = strstr(s, " relsize=");
3156 if (p)
3157 {
3158 /* this is handled somewhere else because it depends
3159 * on the line it resides in, which is not defined
3160 * at this point and will change anyway, which will
3161 * break because the results of this function are
3162 * cached */
3163 size = SIZE_REL;
3164 }
3165 }
3166 }
3167
3168 if (create_item)
3169 {
3170 fi = _layout_format_item_add(c, n, s, fmt);
3171 fi->vsize = vsize;
3172 fi->size = size;
3173 fi->formatme = 1;
3174 /* For formats items it's usually
3175 the same, we don't handle the
3176 special cases yet. */
3177 fi->parent.w = fi->parent.adv = w;
3178 fi->parent.h = h;
3179 }
3180 /* Not sure if it's the best handling, but will do it for now. */
3181 fmt = _layout_format_push(c, fmt, n);
3182 handled = 1;
3183 }
3184
3185 if (!handled)
3186 {
3187 Eina_Bool push_fmt = EINA_FALSE;
3188 if (n->opener && !n->own_closer)
3189 {
3190 fmt = _layout_format_push(c, fmt, n);
3191 push_fmt = EINA_TRUE;
3192 }
3193 else if (!n->opener)
3194 {
3195 fmt = _layout_format_pop(c, n->orig_format);
3196 }
3197 while ((item = _format_parse(&s)))
3198 {
3199 if (_format_is_param(item))
3200 {
3201 /* Only handle it if it's a push format, otherwise,
3202 * don't let overwrite the format stack.. */
3203 if (push_fmt)
3204 {
3205 _layout_format_value_handle(c, fmt, item);
3206 }
3207 }
3208 else if (create_item)
3209 {
3210 if ((_IS_PARAGRAPH_SEPARATOR(c->o, item)) ||
3211 (_IS_LINE_SEPARATOR(item)))
3212 {
3213 Evas_Object_Textblock_Format_Item *fi;
3214
3215 fi = _layout_format_item_add(c, n, item, fmt);
3216
3217 fi->parent.w = fi->parent.adv = 0;
3218 }
3219 else if (_IS_TAB(item))
3220 {
3221 Evas_Object_Textblock_Format_Item *fi;
3222
3223 fi = _layout_format_item_add(c, n, item, fmt);
3224 fi->parent.w = fi->parent.adv = fmt->tabstops;
3225 fi->formatme = 1;
3226 }
3227 }
3228 }
3229 _format_finalize(c->obj, fmt);
3230 }
3231
3232 {
3233 Evas_Coord pad_l, pad_r, pad_t, pad_b;
3234 pad_l = pad_r = pad_t = pad_b = 0;
3235 evas_text_style_pad_get(fmt->style, &pad_l, &pad_r, &pad_t, &pad_b);
3236 if (pad_l > *style_pad_l) *style_pad_l = pad_l;
3237 if (pad_r > *style_pad_r) *style_pad_r = pad_r;
3238 if (pad_t > *style_pad_t) *style_pad_t = pad_t;
3239 if (pad_b > *style_pad_b) *style_pad_b = pad_b;
3240 }
3241
3242 if (fmt->underline2)
3243 c->have_underline2 = 1;
3244 else if (fmt->underline || fmt->underline_dash)
3245 c->have_underline = 1;
3246 *_fmt = fmt;
3247}
3248
3249static void
3250_layout_update_par(Ctxt *c)
3251{
3252 Evas_Object_Textblock_Paragraph *last_par;
3253 last_par = (Evas_Object_Textblock_Paragraph *)
3254 EINA_INLIST_GET(c->par)->prev;
3255 if (last_par)
3256 {
3257 c->par->y = last_par->y + last_par->h;
3258 }
3259 else
3260 {
3261 c->par->y = 0;
3262 }
3263}
3264
3265/* -1 means no wrap */
3266static int
3267_layout_get_charwrap(Ctxt *c, Evas_Object_Textblock_Format *fmt,
3268 const Evas_Object_Textblock_Item *it, size_t line_start,
3269 const char *breaks)
3270{
3271 int wrap;
3272 size_t uwrap;
3273 size_t len = eina_ustrbuf_length_get(it->text_node->unicode);
3274 /* Currently not being used, because it doesn't contain relevant
3275 * information */
3276 (void) breaks;
3277
3278 {
3279 if (it->type == EVAS_TEXTBLOCK_ITEM_FORMAT)
3280 wrap = 0;
3281 else
3282 wrap = _layout_text_cutoff_get(c, fmt, _ITEM_TEXT(it));
3283
3284 if (wrap < 0)
3285 return -1;
3286 uwrap = (size_t) wrap + it->text_pos;
3287 }
3288
3289
3290 if ((uwrap == line_start) && (it->type == EVAS_TEXTBLOCK_ITEM_TEXT))
3291 {
3292 uwrap = it->text_pos +
3293 (size_t) evas_common_text_props_cluster_next(
3294 &_ITEM_TEXT(it)->text_props, wrap);
3295 }
3296 if ((uwrap <= line_start) || (uwrap > len))
3297 return -1;
3298
3299 return uwrap;
3300}
3301
3302/* -1 means no wrap */
3303#ifdef HAVE_LINEBREAK
3304
3305/* Allow break means: if we can break after the current char */
3306#define ALLOW_BREAK(i) \
3307 (breaks[i] <= LINEBREAK_ALLOWBREAK)
3308
3309#else
3310
3311#define ALLOW_BREAK(i) \
3312 (_is_white(str[i]))
3313
3314#endif
3315static int
3316_layout_get_word_mixwrap_common(Ctxt *c, Evas_Object_Textblock_Format *fmt,
3317 const Evas_Object_Textblock_Item *it, Eina_Bool mixed_wrap,
3318 size_t line_start, const char *breaks)
3319{
3320 Eina_Bool wrap_after = EINA_FALSE;
3321 size_t wrap;
3322 size_t orig_wrap;
3323 const Eina_Unicode *str = eina_ustrbuf_string_get(
3324 it->text_node->unicode);
3325 int item_start = it->text_pos;
3326 size_t len = eina_ustrbuf_length_get(it->text_node->unicode);
3327#ifndef HAVE_LINEBREAK
3328 /* Not used without liblinebreak ATM. */
3329 (void) breaks;
3330#endif
3331
3332 {
3333 int swrap = -1;
3334 if (it->type == EVAS_TEXTBLOCK_ITEM_FORMAT)
3335 swrap = 0;
3336 else
3337 swrap = _layout_text_cutoff_get(c, fmt, _ITEM_TEXT(it));
3338 /* Avoiding too small textblocks to even contain one char.
3339 * FIXME: This can cause breaking inside ligatures. */
3340
3341 if (swrap < 0)
3342 return -1;
3343
3344 orig_wrap = wrap = swrap + item_start;
3345 }
3346
3347 if (wrap > line_start)
3348 {
3349 /* The wrapping point found is the first char of the next string
3350 the rest works on the last char of the previous string.
3351 If it's a whitespace, then it's ok, and no need to go back
3352 because we'll remove it anyway. */
3353 if (!_is_white(str[wrap]))
3354 MOVE_PREV_UNTIL(line_start, wrap);
3355 /* If there's a breakable point inside the text, scan backwards until
3356 * we find it */
3357 while (wrap > line_start)
3358 {
3359 if (ALLOW_BREAK(wrap))
3360 break;
3361 wrap--;
3362 }
3363
3364 if ((wrap > line_start) ||
3365 ((wrap == line_start) && (ALLOW_BREAK(wrap)) && (wrap < len)))
3366 {
3367 /* We found a suitable wrapping point, break here. */
3368 MOVE_NEXT_UNTIL(len, wrap);
3369 return wrap;
3370 }
3371 else
3372 {
3373 if (mixed_wrap)
3374 {
3375 return ((orig_wrap >= line_start) && (orig_wrap < len)) ?
3376 ((int) orig_wrap) : -1;
3377 }
3378 else
3379 {
3380 /* Scan forward to find the next wrapping point */
3381 wrap = orig_wrap;
3382 wrap_after = EINA_TRUE;
3383 }
3384 }
3385 }
3386
3387 /* If we need to find the position after the cutting point */
3388 if ((wrap == line_start) || (wrap_after))
3389 {
3390 if (mixed_wrap)
3391 {
3392 return _layout_get_charwrap(c, fmt, it,
3393 line_start, breaks);
3394 }
3395 else
3396 {
3397 while (wrap < len)
3398 {
3399 if (ALLOW_BREAK(wrap))
3400 break;
3401 wrap++;
3402 }
3403
3404
3405 if ((wrap < len) && (wrap > line_start))
3406 {
3407 MOVE_NEXT_UNTIL(len, wrap);
3408 return wrap;
3409 }
3410 else
3411 {
3412 return -1;
3413 }
3414 }
3415 }
3416
3417 return -1;
3418}
3419
3420/* -1 means no wrap */
3421static int
3422_layout_get_wordwrap(Ctxt *c, Evas_Object_Textblock_Format *fmt,
3423 const Evas_Object_Textblock_Item *it, size_t line_start,
3424 const char *breaks)
3425{
3426 return _layout_get_word_mixwrap_common(c, fmt, it, EINA_FALSE, line_start,
3427 breaks);
3428}
3429
3430/* -1 means no wrap */
3431static int
3432_layout_get_mixedwrap(Ctxt *c, Evas_Object_Textblock_Format *fmt,
3433 const Evas_Object_Textblock_Item *it, size_t line_start,
3434 const char *breaks)
3435{
3436 return _layout_get_word_mixwrap_common(c, fmt, it, EINA_TRUE, line_start,
3437 breaks);
3438}
3439
3440/* Should be moved inside _layout_ellipsis_item_new once we fix the hack in
3441 * textblock render */
3442static const Eina_Unicode _ellip_str[2] = { 0x2026, '\0' };
3443
3444static Evas_Object_Textblock_Text_Item *
3445_layout_ellipsis_item_new(Ctxt *c, const Evas_Object_Textblock_Item *cur_it)
3446{
3447 Evas_Object_Textblock_Text_Item *ellip_ti;
3448 Evas_Script_Type script;
3449 Evas_Font_Instance *script_fi = NULL, *cur_fi;
3450 size_t len = 1; /* The length of _ellip_str */
3451
3452 /* We can free it here, cause there's only one ellipsis item per tb. */
3453 if (c->o->ellip_ti) _item_free(c->obj, NULL, _ITEM(c->o->ellip_ti));
3454 c->o->ellip_ti = ellip_ti = _layout_text_item_new(c,
3455 eina_list_data_get(eina_list_last(c->format_stack)));
3456 ellip_ti->parent.text_node = cur_it->text_node;
3457 ellip_ti->parent.text_pos = cur_it->text_pos;
3458 script = evas_common_language_script_type_get(_ellip_str, len);
3459
3460 evas_common_text_props_bidi_set(&ellip_ti->text_props,
3461 c->par->bidi_props, ellip_ti->parent.text_pos);
3462 evas_common_text_props_script_set (&ellip_ti->text_props, script);
3463
3464 if (ellip_ti->parent.format->font.font)
3465 {
3466 /* It's only 1 char anyway, we don't need the run end. */
3467 (void) c->ENFN->font_run_end_get(c->ENDT,
3468 ellip_ti->parent.format->font.font, &script_fi, &cur_fi,
3469 script, _ellip_str, len);
3470
3471 c->ENFN->font_text_props_info_create(c->ENDT,
3472 cur_fi, _ellip_str, &ellip_ti->text_props,
3473 c->par->bidi_props, ellip_ti->parent.text_pos, len);
3474 }
3475
3476 _text_item_update_sizes(c, ellip_ti);
3477
3478 if (cur_it->type == EVAS_TEXTBLOCK_ITEM_TEXT)
3479 {
3480 ellip_ti->parent.text_pos += _ITEM_TEXT(cur_it)->text_props.text_len
3481 - 1;
3482 }
3483 else
3484 {
3485 ellip_ti->parent.text_pos++;
3486 }
3487
3488 return ellip_ti;
3489}
3490
3491/**
3492 * @internel
3493 * Handle ellipsis
3494 */
3495static inline void
3496_layout_handle_ellipsis(Ctxt *c, Evas_Object_Textblock_Item *it, Eina_List *i)
3497{
3498 Evas_Object_Textblock_Text_Item *ellip_ti;
3499 Evas_Object_Textblock_Item *last_it;
3500 Evas_Coord save_cx;
3501 int wrap;
3502 ellip_ti = _layout_ellipsis_item_new(c, it);
3503 last_it = it;
3504
3505 save_cx = c->x;
3506 c->w -= ellip_ti->parent.w;
3507
3508 if (it->type == EVAS_TEXTBLOCK_ITEM_TEXT)
3509 {
3510 Evas_Object_Textblock_Text_Item *ti = _ITEM_TEXT(it);
3511
3512 wrap = _layout_text_cutoff_get(c, last_it->format, ti);
3513 if ((wrap > 0) && !IS_AT_END(ti, (size_t) wrap))
3514 {
3515 _layout_item_text_split_strip_white(c, ti, i, wrap);
3516 }
3517 else if ((wrap == 0) && (c->ln->items))
3518 {
3519 last_it = _ITEM(EINA_INLIST_GET(c->ln->items)->last);
3520 }
3521 }
3522 else if (it->type == EVAS_TEXTBLOCK_ITEM_FORMAT)
3523 {
3524 /* We don't want to add this format item. */
3525 last_it = NULL;
3526 }
3527
3528 c->x = save_cx;
3529 c->w += ellip_ti->parent.w;
3530 /* If we should add this item, do it */
3531 if (last_it == it)
3532 {
3533 c->ln->items = (Evas_Object_Textblock_Item *)
3534 eina_inlist_append(EINA_INLIST_GET(c->ln->items),
3535 EINA_INLIST_GET(it));
3536 if (it->type == EVAS_TEXTBLOCK_ITEM_FORMAT)
3537 {
3538 Evas_Object_Textblock_Format_Item *fi;
3539 fi = _ITEM_FORMAT(it);
3540 fi->y = c->y;
3541 }
3542 }
3543 c->ln->items = (Evas_Object_Textblock_Item *)
3544 eina_inlist_append(EINA_INLIST_GET(c->ln->items),
3545 EINA_INLIST_GET(_ITEM(ellip_ti)));
3546 _layout_line_finalize(c, ellip_ti->parent.format);
3547}
3548
3549#ifdef BIDI_SUPPORT
3550static void
3551_layout_paragraph_reorder_lines(Evas_Object_Textblock_Paragraph *par)
3552{
3553 Evas_Object_Textblock_Line *ln;
3554
3555 EINA_INLIST_FOREACH(EINA_INLIST_GET(par->lines), ln)
3556 {
3557 _layout_line_reorder(ln);
3558 }
3559}
3560#endif
3561
3562static void
3563_layout_paragraph_render(Evas_Object_Textblock *o,
3564 Evas_Object_Textblock_Paragraph *par)
3565{
3566 if (par->rendered)
3567 return;
3568 par->rendered = EINA_TRUE;
3569
3570#ifdef BIDI_SUPPORT
3571 if (par->is_bidi)
3572 {
3573 _layout_update_bidi_props(o, par);
3574 _layout_paragraph_reorder_lines(par);
3575 /* Clear the bidi props because we don't need them anymore. */
3576 if (par->bidi_props)
3577 {
3578 evas_bidi_paragraph_props_unref(par->bidi_props);
3579 par->bidi_props = NULL;
3580 }
3581 }
3582#else
3583 (void) o;
3584#endif
3585}
3586
3587/* 0 means go ahead, 1 means break without an error, 2 means
3588 * break with an error, should probably clean this a bit (enum/macro)
3589 * FIXME ^ */
3590static int
3591_layout_par(Ctxt *c)
3592{
3593 Evas_Object_Textblock_Item *it;
3594 Eina_List *i;
3595 int ret = 0;
3596 int wrap = -1;
3597 char *line_breaks = NULL;
3598
3599 if (!c->par->logical_items)
3600 return 2;
3601
3602 /* We want to show it. */
3603 c->par->visible = 1;
3604
3605 /* Check if we need to skip this paragraph because it's already layouted
3606 * correctly, and mark handled nodes as dirty. */
3607 c->par->line_no = c->line_no;
3608
3609 if (c->par->text_node)
3610 {
3611 /* Skip this paragraph if width is the same, there is no ellipsis
3612 * and we aren't just calculating. */
3613 if (!c->par->text_node->is_new && !c->par->text_node->dirty &&
3614 !c->width_changed && c->par->lines &&
3615 !c->o->have_ellipsis)
3616 {
3617 Evas_Object_Textblock_Line *ln;
3618 /* Update c->line_no */
3619 ln = (Evas_Object_Textblock_Line *)
3620 EINA_INLIST_GET(c->par->lines)->last;
3621 if (ln)
3622 c->line_no = c->par->line_no + ln->line_no + 1;
3623 return 0;
3624 }
3625 c->par->text_node->dirty = EINA_FALSE;
3626 c->par->text_node->is_new = EINA_FALSE;
3627 c->par->rendered = EINA_FALSE;
3628
3629 /* Merge back and clear the paragraph */
3630 {
3631 Eina_List *itr, *itr_next;
3632 Evas_Object_Textblock_Item *ititr, *prev_it = NULL;
3633 _paragraph_clear(c->obj, c->par);
3634 EINA_LIST_FOREACH_SAFE(c->par->logical_items, itr, itr_next, ititr)
3635 {
3636 if (ititr->merge && prev_it &&
3637 (prev_it->type == EVAS_TEXTBLOCK_ITEM_TEXT) &&
3638 (ititr->type == EVAS_TEXTBLOCK_ITEM_TEXT))
3639 {
3640 _layout_item_merge_and_free(c, _ITEM_TEXT(prev_it),
3641 _ITEM_TEXT(ititr));
3642 c->par->logical_items =
3643 eina_list_remove_list(c->par->logical_items, itr);
3644 }
3645 else
3646 {
3647 prev_it = ititr;
3648 }
3649 }
3650 }
3651 }
3652
3653 c->y = c->par->y;
3654
3655 it = _ITEM(eina_list_data_get(c->par->logical_items));
3656 _layout_line_new(c, it->format);
3657 /* We walk on our own because we want to be able to add items from
3658 * inside the list and then walk them on the next iteration. */
3659 for (i = c->par->logical_items ; i ; )
3660 {
3661 int adv_line = 0;
3662 int redo_item = 0;
3663 it = _ITEM(eina_list_data_get(i));
3664 /* Skip visually deleted items */
3665 if (it->visually_deleted)
3666 {
3667 i = eina_list_next(i);
3668 continue;
3669 }
3670
3671 if (it->type == EVAS_TEXTBLOCK_ITEM_TEXT)
3672 {
3673 Evas_Object_Textblock_Text_Item *ti = _ITEM_TEXT(it);
3674 _layout_format_ascent_descent_adjust(c->obj, &c->maxascent,
3675 &c->maxdescent, ti->parent.format);
3676 }
3677 else
3678 {
3679 Evas_Object_Textblock_Format_Item *fi = _ITEM_FORMAT(it);
3680 if (fi->formatme)
3681 {
3682 /* If there are no text items yet, calc ascent/descent
3683 * according to the current format. */
3684 if (c->maxascent + c->maxdescent == 0)
3685 _layout_format_ascent_descent_adjust(c->obj, &c->maxascent,
3686 &c->maxdescent, it->format);
3687
3688 _layout_calculate_format_item_size(c->obj, fi, &c->maxascent,
3689 &c->maxdescent, &fi->y, &fi->parent.w, &fi->parent.h);
3690 fi->parent.adv = fi->parent.w;
3691 }
3692 }
3693
3694
3695 /* Check if we need to wrap, i.e the text is bigger than the width,
3696 or we already found a wrap point. */
3697 if ((c->w >= 0) &&
3698 (((c->x + it->adv) >
3699 (c->w - c->o->style_pad.l - c->o->style_pad.r -
3700 c->marginl - c->marginr)) || (wrap > 0)))
3701 {
3702 /* Handle ellipsis here. If we don't have more width left
3703 * and no height left, or no more width left and no wrapping. */
3704 if ((it->format->ellipsis == 1.0) && (c->h >= 0) &&
3705 ((2 * it->h + c->y >
3706 c->h - c->o->style_pad.t - c->o->style_pad.b) ||
3707 (!it->format->wrap_word && !it->format->wrap_char &&
3708 !it->format->wrap_mixed)))
3709 {
3710 _layout_handle_ellipsis(c, it, i);
3711 ret = 1;
3712 goto end;
3713 }
3714 /* If we want to wrap and it's worth checking for wrapping
3715 * (i.e there's actually text). */
3716 else if ((it->format->wrap_word || it->format->wrap_char ||
3717 it->format->wrap_mixed) && it->text_node)
3718 {
3719 size_t line_start;
3720 size_t it_len;
3721
3722 it_len = (it->type == EVAS_TEXTBLOCK_ITEM_FORMAT) ?
3723 1 : _ITEM_TEXT(it)->text_props.text_len;
3724
3725
3726#ifdef HAVE_LINEBREAK
3727 /* If we haven't calculated the linebreaks yet,
3728 * do */
3729 if (!line_breaks)
3730 {
3731 /* Only relevant in those cases */
3732 if (it->format->wrap_word || it->format->wrap_mixed)
3733 {
3734 const char *lang;
3735 lang = (it->format->font.fdesc) ?
3736 it->format->font.fdesc->lang : "";
3737 size_t len =
3738 eina_ustrbuf_length_get(
3739 it->text_node->unicode);
3740 line_breaks = malloc(len);
3741 set_linebreaks_utf32((const utf32_t *)
3742 eina_ustrbuf_string_get(
3743 it->text_node->unicode),
3744 len, lang, line_breaks);
3745 }
3746 }
3747#endif
3748 if (c->ln->items)
3749 line_start = c->ln->items->text_pos;
3750 else
3751 line_start = it->text_pos;
3752
3753 adv_line = 1;
3754 /* If we don't already have a wrap point from before */
3755 if (wrap < 0)
3756 {
3757 if (it->format->wrap_word)
3758 wrap = _layout_get_wordwrap(c, it->format, it,
3759 line_start, line_breaks);
3760 else if (it->format->wrap_char)
3761 wrap = _layout_get_charwrap(c, it->format, it,
3762 line_start, line_breaks);
3763 else if (it->format->wrap_mixed)
3764 wrap = _layout_get_mixedwrap(c, it->format, it,
3765 line_start, line_breaks);
3766 else
3767 wrap = -1;
3768 }
3769
3770 /* If it's before the item, rollback and apply.
3771 if it's in the item, cut.
3772 If it's after the item, delay the cut */
3773 if (wrap > 0)
3774 {
3775 size_t uwrap = (size_t) wrap;
3776 if (uwrap < it->text_pos)
3777 {
3778 /* Rollback latest additions, and cut that
3779 item */
3780 i = eina_list_prev(i);
3781 it = eina_list_data_get(i);
3782 while (uwrap < it->text_pos)
3783 {
3784 c->ln->items = _ITEM(
3785 eina_inlist_remove(
3786 EINA_INLIST_GET(c->ln->items),
3787 EINA_INLIST_GET(it)));
3788 i = eina_list_prev(i);
3789 it = eina_list_data_get(i);
3790 }
3791 c->x = it->x;
3792 c->ln->items = _ITEM(
3793 eina_inlist_remove(
3794 EINA_INLIST_GET(c->ln->items),
3795 EINA_INLIST_GET(it)));
3796 continue;
3797 }
3798 /* If it points to the end, it means the previous
3799 * char is a whitespace we should remove, so this
3800 * is a wanted cutting point. */
3801 else if (uwrap > it->text_pos + it_len)
3802 {
3803 /* FIXME: Should redo the ellipsis handling.
3804 * If we can do ellipsis, just cut here. */
3805 if (it->format->ellipsis == 1.0)
3806 {
3807 _layout_handle_ellipsis(c, it, i);
3808 ret = 1;
3809 goto end;
3810 }
3811 else
3812 {
3813 /* Delay the cut in a smart way i.e use the
3814 item_pos as the line_start, because
3815 there's already no cut before*/
3816 wrap = -1;
3817 }
3818 }
3819 else
3820 wrap -= it->text_pos; /* Cut here */
3821 }
3822
3823 if (wrap > 0)
3824 {
3825 if (it->type == EVAS_TEXTBLOCK_ITEM_TEXT)
3826 {
3827 _layout_item_text_split_strip_white(c,
3828 _ITEM_TEXT(it), i, wrap);
3829 }
3830 }
3831 else if (wrap == 0)
3832 {
3833 /* Should wrap before the item */
3834 adv_line = 0;
3835 redo_item = 1;
3836 _layout_line_advance(c, it->format);
3837 }
3838 /* Reset wrap */
3839 wrap = -1;
3840 }
3841 }
3842
3843 if (!redo_item && !it->visually_deleted)
3844 {
3845 c->ln->items = (Evas_Object_Textblock_Item *)
3846 eina_inlist_append(EINA_INLIST_GET(c->ln->items),
3847 EINA_INLIST_GET(it));
3848 if (it->type == EVAS_TEXTBLOCK_ITEM_FORMAT)
3849 {
3850 Evas_Object_Textblock_Format_Item *fi;
3851 fi = _ITEM_FORMAT(it);
3852 fi->y = c->y;
3853 /* If it's a newline, and we are not in newline compat
3854 * mode, or we are in newline compat mode, and this is
3855 * not used as a paragraph separator, advance */
3856 if (fi->item && _IS_LINE_SEPARATOR(fi->item) &&
3857 (!c->o->legacy_newline ||
3858 eina_list_next(i)))
3859 {
3860 adv_line = 1;
3861 }
3862 }
3863 c->x += it->adv;
3864 i = eina_list_next(i);
3865 }
3866 if (adv_line)
3867 {
3868 /* Each line is according to the first item in it, and here
3869 * i is already the next item (or the current if we redo it) */
3870 if (i)
3871 {
3872 it = _ITEM(eina_list_data_get(i));
3873 }
3874 _layout_line_advance(c, it->format);
3875 }
3876 }
3877 if (c->ln->items)
3878 {
3879 /* Here 'it' is the last format used */
3880 _layout_line_finalize(c, it->format);
3881 }
3882
3883end:
3884#ifdef HAVE_LINEBREAK
3885 if (line_breaks)
3886 free(line_breaks);
3887#endif
3888
3889 return ret;
3890}
3891
3892/**
3893 * @internal
3894 * Invalidate text nodes according to format changes
3895 * This goes through all the new format changes and marks the text nodes
3896 * that should be invalidated because of format changes.
3897 *
3898 * @param c the working context.
3899 */
3900static inline void
3901_format_changes_invalidate_text_nodes(Ctxt *c)
3902{
3903 Evas_Object_Textblock_Node_Format *fnode = c->o->format_nodes;
3904 Evas_Object_Textblock_Node_Text *start_n = NULL;
3905 Eina_List *fstack = NULL;
3906 int balance = 0;
3907 while (fnode)
3908 {
3909 if (fnode->is_new)
3910 {
3911 const char *fstr = fnode->orig_format;
3912 /* balance < 0 means we gave up and everything should be
3913 * invalidated */
3914 if (fnode->opener && !fnode->own_closer)
3915 {
3916 balance++;
3917 if (!fstack)
3918 start_n = fnode->text_node;
3919 fstack = eina_list_prepend(fstack, fnode);
3920 }
3921 else if (!fnode->opener)
3922 {
3923 size_t fstr_len;
3924 fstr_len = strlen(fstr);
3925 /* Generic popper, just pop */
3926 if (((fstr[0] == ' ') && !fstr[1]) || !fstr[0])
3927 {
3928 fstack = eina_list_remove_list(fstack, fstack);
3929 balance--;
3930 }
3931 /* Find the matching format and pop it, if the matching format
3932 * is out format, i.e the last one, pop and break. */
3933 else
3934 {
3935 Eina_List *i;
3936 Evas_Object_Textblock_Node_Format *fnode2;
3937 EINA_LIST_FOREACH(fstack, i, fnode2)
3938 {
3939 if (_FORMAT_IS_CLOSER_OF(
3940 fnode2->orig_format, fstr, fstr_len))
3941 {
3942 fstack = eina_list_remove_list(fstack, i);
3943 break;
3944 }
3945 }
3946 balance--;
3947 }
3948
3949 if (!fstack)
3950 {
3951 Evas_Object_Textblock_Node_Text *f_tnode =
3952 fnode->text_node;
3953 while (start_n)
3954 {
3955 start_n->dirty = EINA_TRUE;
3956 if (start_n == f_tnode)
3957 break;
3958 start_n =
3959 _NODE_TEXT(EINA_INLIST_GET(start_n)->next);
3960 }
3961 start_n = NULL;
3962 }
3963 }
3964 else if (!fnode->visible)
3965 balance = -1;
3966
3967 if (balance < 0)
3968 {
3969 /* if we don't already have a starting point, use the
3970 * current paragraph. */
3971 if (!start_n)
3972 start_n = fnode->text_node;
3973 break;
3974 }
3975 }
3976 fnode = _NODE_FORMAT(EINA_INLIST_GET(fnode)->next);
3977 }
3978
3979 if (balance != 0)
3980 {
3981 while (start_n)
3982 {
3983 start_n->dirty = EINA_TRUE;
3984 start_n = _NODE_TEXT(EINA_INLIST_GET(start_n)->next);
3985 }
3986 }
3987}
3988
3989
3990/** FIXME: Document */
3991static void
3992_layout_pre(Ctxt *c, int *style_pad_l, int *style_pad_r, int *style_pad_t,
3993 int *style_pad_b)
3994{
3995 Evas_Object *obj = c->obj;
3996 Evas_Object_Textblock *o = c->o;
3997 /* Mark text nodes as dirty if format have changed. */
3998 if (c->o->format_changed)
3999 {
4000 _format_changes_invalidate_text_nodes(c);
4001 }
4002
4003 if (o->content_changed)
4004 {
4005 Evas_Object_Textblock_Node_Text *n;
4006 c->o->have_ellipsis = 0;
4007 c->par = c->paragraphs = o->paragraphs;
4008 /* Go through all the text nodes to create the logical layout */
4009 EINA_INLIST_FOREACH(c->o->text_nodes, n)
4010 {
4011 Evas_Object_Textblock_Node_Format *fnode;
4012 size_t start;
4013 int off;
4014
4015 /* If it's not a new paragraph, either update it or skip it.
4016 * Remove all the paragraphs that were deleted */
4017 if (!n->is_new)
4018 {
4019 /* Remove all the deleted paragraphs at this point */
4020 while (c->par->text_node != n)
4021 {
4022 Evas_Object_Textblock_Paragraph *tmp_par =
4023 (Evas_Object_Textblock_Paragraph *)
4024 EINA_INLIST_GET(c->par)->next;
4025
4026 c->paragraphs = (Evas_Object_Textblock_Paragraph *)
4027 eina_inlist_remove(EINA_INLIST_GET(c->paragraphs),
4028 EINA_INLIST_GET(c->par));
4029 _paragraph_free(obj, c->par);
4030
4031 c->par = tmp_par;
4032 }
4033
4034 /* If it's dirty, remove and recreate, if it's clean,
4035 * skip to the next. */
4036 if (n->dirty)
4037 {
4038 Evas_Object_Textblock_Paragraph *prev_par = c->par;
4039
4040 _layout_paragraph_new(c, n, EINA_TRUE);
4041
4042 c->paragraphs = (Evas_Object_Textblock_Paragraph *)
4043 eina_inlist_remove(EINA_INLIST_GET(c->paragraphs),
4044 EINA_INLIST_GET(prev_par));
4045 _paragraph_free(obj, prev_par);
4046 }
4047 else
4048 {
4049 c->par = (Evas_Object_Textblock_Paragraph *)
4050 EINA_INLIST_GET(c->par)->next;
4051
4052 /* Update the format stack according to the node's
4053 * formats */
4054 fnode = n->format_node;
4055 while (fnode && (fnode->text_node == n))
4056 {
4057 /* Only do this if this actually changes format */
4058 if (fnode->format_change)
4059 _layout_do_format(obj, c, &c->fmt, fnode,
4060 style_pad_l, style_pad_r,
4061 style_pad_t, style_pad_b, EINA_FALSE);
4062 fnode = _NODE_FORMAT(EINA_INLIST_GET(fnode)->next);
4063 }
4064 continue;
4065 }
4066 }
4067 else
4068 {
4069 /* If it's a new paragraph, just add it. */
4070 _layout_paragraph_new(c, n, EINA_FALSE);
4071 }
4072
4073#ifdef BIDI_SUPPORT
4074 _layout_update_bidi_props(c->o, c->par);
4075#endif
4076
4077 /* For each text node to thorugh all of it's format nodes
4078 * append text from the start to the offset of the next format
4079 * using the last format got. if needed it also creates format
4080 * items this is the core algorithm of the layout mechanism.
4081 * Skip the unicode replacement chars when there are because
4082 * we don't want to print them. */
4083 fnode = n->format_node;
4084 start = off = 0;
4085 while (fnode && (fnode->text_node == n))
4086 {
4087 off += fnode->offset;
4088 /* No need to skip on the first run, or a non-visible one */
4089 _layout_text_append(c, c->fmt, n, start, off, o->repch);
4090 _layout_do_format(obj, c, &c->fmt, fnode, style_pad_l,
4091 style_pad_r, style_pad_t, style_pad_b, EINA_TRUE);
4092 if ((c->have_underline2) || (c->have_underline))
4093 {
4094 if (*style_pad_b < c->underline_extend)
4095 *style_pad_b = c->underline_extend;
4096 c->have_underline = 0;
4097 c->have_underline2 = 0;
4098 c->underline_extend = 0;
4099 }
4100 start += off;
4101 if (fnode->visible)
4102 {
4103 off = -1;
4104 start++;
4105 }
4106 else
4107 {
4108 off = 0;
4109 }
4110 fnode->is_new = EINA_FALSE;
4111 fnode = _NODE_FORMAT(EINA_INLIST_GET(fnode)->next);
4112 }
4113 _layout_text_append(c, c->fmt, n, start, -1, o->repch);
4114#ifdef BIDI_SUPPORT
4115 /* Clear the bidi props because we don't need them anymore. */
4116 if (c->par->bidi_props)
4117 {
4118 evas_bidi_paragraph_props_unref(c->par->bidi_props);
4119 c->par->bidi_props = NULL;
4120 }
4121#endif
4122 c->par = (Evas_Object_Textblock_Paragraph *)
4123 EINA_INLIST_GET(c->par)->next;
4124 }
4125
4126 /* Delete the rest of the layout paragraphs */
4127 while (c->par)
4128 {
4129 Evas_Object_Textblock_Paragraph *tmp_par =
4130 (Evas_Object_Textblock_Paragraph *)
4131 EINA_INLIST_GET(c->par)->next;
4132
4133 c->paragraphs = (Evas_Object_Textblock_Paragraph *)
4134 eina_inlist_remove(EINA_INLIST_GET(c->paragraphs),
4135 EINA_INLIST_GET(c->par));
4136 _paragraph_free(obj, c->par);
4137
4138 c->par = tmp_par;
4139 }
4140 o->paragraphs = c->paragraphs;
4141 c->par = NULL;
4142 }
4143
4144}
4145
4146/**
4147 * @internal
4148 * Create the layout from the nodes.
4149 *
4150 * @param obj the evas object - NOT NULL.
4151 * @param calc_only true if should only calc sizes false if should also create the layout.. It assumes native size is being calculated, doesn't support formatted size atm.
4152 * @param w the object's w, -1 means no wrapping (i.e infinite size)
4153 * @param h the object's h, -1 means inifinte size.
4154 * @param w_ret the object's calculated w.
4155 * @param h_ret the object's calculated h.
4156 */
4157static void
4158_layout(const Evas_Object *obj, int w, int h, int *w_ret, int *h_ret)
4159{
4160 Evas_Object_Textblock *o;
4161 Ctxt ctxt, *c;
4162 int style_pad_l = 0, style_pad_r = 0, style_pad_t = 0, style_pad_b = 0;
4163
4164 /* setup context */
4165 o = (Evas_Object_Textblock *)(obj->object_data);
4166 c = &ctxt;
4167 c->obj = (Evas_Object *)obj;
4168 c->o = o;
4169 c->paragraphs = c->par = NULL;
4170 c->format_stack = NULL;
4171 c->fmt = NULL;
4172 c->x = c->y = 0;
4173 c->w = w;
4174 c->h = h;
4175 c->wmax = c->hmax = 0;
4176 c->maxascent = c->maxdescent = 0;
4177 c->marginl = c->marginr = 0;
4178 c->have_underline = 0;
4179 c->have_underline2 = 0;
4180 c->underline_extend = 0;
4181 c->line_no = 0;
4182 c->align = 0.0;
4183 c->align_auto = EINA_TRUE;
4184 c->ln = NULL;
4185 c->width_changed = (obj->cur.geometry.w != o->last_w);
4186
4187 /* Start of logical layout creation */
4188 /* setup default base style */
4189 {
4190 Eina_Bool finalize = EINA_FALSE;
4191 if ((c->o->style) && (c->o->style->default_tag))
4192 {
4193 c->fmt = _layout_format_push(c, NULL, NULL);
4194 _format_fill(c->obj, c->fmt, c->o->style->default_tag);
4195 finalize = EINA_TRUE;
4196 }
4197
4198 if ((c->o->style_user) && (c->o->style_user->default_tag))
4199 {
4200 if (!c->fmt)
4201 {
4202 c->fmt = _layout_format_push(c, NULL, NULL);
4203 }
4204 _format_fill(c->obj, c->fmt, c->o->style_user->default_tag);
4205 finalize = EINA_TRUE;
4206 }
4207
4208 if (finalize)
4209 _format_finalize(c->obj, c->fmt);
4210 }
4211 if (!c->fmt)
4212 {
4213 if (w_ret) *w_ret = 0;
4214 if (h_ret) *h_ret = 0;
4215 return;
4216 }
4217
4218 _layout_pre(c, &style_pad_l, &style_pad_r, &style_pad_t, &style_pad_b);
4219 c->paragraphs = o->paragraphs;
4220
4221 /* If there are no paragraphs, create the minimum needed,
4222 * if the last paragraph has no lines/text, create that as well */
4223 if (!c->paragraphs)
4224 {
4225 _layout_paragraph_new(c, NULL, EINA_TRUE);
4226 o->paragraphs = c->paragraphs;
4227 }
4228 c->par = (Evas_Object_Textblock_Paragraph *)
4229 EINA_INLIST_GET(c->paragraphs)->last;
4230 if (!c->par->logical_items)
4231 {
4232 Evas_Object_Textblock_Text_Item *ti;
4233 ti = _layout_text_item_new(c, c->fmt);
4234 ti->parent.text_node = c->par->text_node;
4235 ti->parent.text_pos = 0;
4236 _layout_text_add_logical_item(c, ti, NULL);
4237 }
4238
4239 /* End of logical layout creation */
4240
4241 /* Start of visual layout creation */
4242 {
4243 Evas_Object_Textblock_Paragraph *last_vis_par = NULL;
4244 int par_index_step = o->num_paragraphs / TEXTBLOCK_PAR_INDEX_SIZE;
4245 int par_count = 1; /* Force it to take the first one */
4246 int par_index_pos = 0;
4247
4248 if (par_index_step == 0) par_index_step = 1;
4249
4250 /* Clear all of the index */
4251 memset(o->par_index, 0, sizeof(o->par_index));
4252
4253 EINA_INLIST_FOREACH(c->paragraphs, c->par)
4254 {
4255 _layout_update_par(c);
4256
4257 /* Break if we should stop here. */
4258 if (_layout_par(c))
4259 {
4260 last_vis_par = c->par;
4261 break;
4262 }
4263
4264 if ((par_index_pos < TEXTBLOCK_PAR_INDEX_SIZE) && (--par_count == 0))
4265 {
4266 par_count = par_index_step;
4267
4268 o->par_index[par_index_pos++] = c->par;
4269 }
4270 }
4271
4272 /* Mark all the rest of the paragraphs as invisible */
4273 if (c->par)
4274 {
4275 c->par = (Evas_Object_Textblock_Paragraph *)
4276 EINA_INLIST_GET(c->par)->next;
4277 while (c->par)
4278 {
4279 c->par->visible = 0;
4280 c->par = (Evas_Object_Textblock_Paragraph *)
4281 EINA_INLIST_GET(c->par)->next;
4282 }
4283 }
4284
4285 /* Get the last visible paragraph in the layout */
4286 if (!last_vis_par && c->paragraphs)
4287 last_vis_par = (Evas_Object_Textblock_Paragraph *)
4288 EINA_INLIST_GET(c->paragraphs)->last;
4289
4290 if (last_vis_par)
4291 c->hmax = last_vis_par->y + last_vis_par->h;
4292 }
4293
4294 /* Clean the rest of the format stack */
4295 while (c->format_stack)
4296 {
4297 c->fmt = c->format_stack->data;
4298 c->format_stack = eina_list_remove_list(c->format_stack, c->format_stack);
4299 _format_unref_free(c->obj, c->fmt);
4300 }
4301
4302 if (w_ret) *w_ret = c->wmax;
4303 if (h_ret) *h_ret = c->hmax;
4304
4305 /* Vertically align the textblock */
4306 if ((o->valign > 0.0) && (c->h > c->hmax))
4307 {
4308 Evas_Coord adjustment = (c->h - c->hmax) * o->valign;
4309 Evas_Object_Textblock_Paragraph *par;
4310 EINA_INLIST_FOREACH(c->paragraphs, par)
4311 {
4312 par->y += adjustment;
4313 }
4314 }
4315
4316 if ((o->style_pad.l != style_pad_l) || (o->style_pad.r != style_pad_r) ||
4317 (o->style_pad.t != style_pad_t) || (o->style_pad.b != style_pad_b))
4318 {
4319 o->style_pad.l = style_pad_l;
4320 o->style_pad.r = style_pad_r;
4321 o->style_pad.t = style_pad_t;
4322 o->style_pad.b = style_pad_b;
4323 _paragraphs_clear(obj, c->paragraphs);
4324 _layout(obj, w, h, w_ret, h_ret);
4325 }
4326}
4327
4328/*
4329 * @internal
4330 * Relayout the object according to current object size.
4331 *
4332 * @param obj the evas object - NOT NULL.
4333 */
4334static void
4335_relayout(const Evas_Object *obj)
4336{
4337 Evas_Object_Textblock *o;
4338
4339 o = (Evas_Object_Textblock *)(obj->object_data);
4340 _layout(obj, obj->cur.geometry.w, obj->cur.geometry.h,
4341 &o->formatted.w, &o->formatted.h);
4342 o->formatted.valid = 1;
4343 o->last_w = obj->cur.geometry.w;
4344 o->last_h = obj->cur.geometry.h;
4345 o->changed = 0;
4346 o->content_changed = 0;
4347 o->format_changed = EINA_FALSE;
4348 o->redraw = 1;
4349}
4350
4351/**
4352 * @internal
4353 * Find the layout item and line that match the text node and position passed.
4354 *
4355 * @param obj the evas object - NOT NULL.
4356 * @param n the text node - Not null.
4357 * @param pos the position to look for - valid.
4358 * @param[out] lnr the line found - not null.
4359 * @param[out] tir the item found - not null.
4360 * @see _find_layout_format_item_line_match()
4361 */
4362static void
4363_find_layout_item_line_match(Evas_Object *obj, Evas_Object_Textblock_Node_Text *n, int pos, Evas_Object_Textblock_Line **lnr, Evas_Object_Textblock_Item **itr)
4364{
4365 Evas_Object_Textblock_Paragraph *found_par;
4366 Evas_Object_Textblock_Line *ln;
4367 Evas_Object_Textblock *o;
4368
4369 o = (Evas_Object_Textblock *)(obj->object_data);
4370 if (!o->formatted.valid) _relayout(obj);
4371
4372 found_par = n->par;
4373 if (found_par)
4374 {
4375 _layout_paragraph_render(o, found_par);
4376 EINA_INLIST_FOREACH(found_par->lines, ln)
4377 {
4378 Evas_Object_Textblock_Item *it;
4379
4380 EINA_INLIST_FOREACH(ln->items, it)
4381 {
4382 /* FIXME: p should be size_t, same goes for pos */
4383 int p = (int) it->text_pos;
4384
4385 if (it->type == EVAS_TEXTBLOCK_ITEM_TEXT)
4386 {
4387 Evas_Object_Textblock_Text_Item *ti =
4388 _ITEM_TEXT(it);
4389
4390 p += (int) ti->text_props.text_len;
4391 }
4392 else
4393 {
4394 p++;
4395 }
4396
4397 if (((pos >= (int) it->text_pos) && (pos < p)))
4398 {
4399 *lnr = ln;
4400 *itr = it;
4401 return;
4402 }
4403 else if (p == pos)
4404 {
4405 *lnr = ln;
4406 *itr = it;
4407 }
4408 }
4409 }
4410 }
4411}
4412
4413/**
4414 * @internal
4415 * Return the line number 'line'.
4416 *
4417 * @param obj the evas object - NOT NULL.
4418 * @param line the line to find
4419 * @return the line of line number or NULL if no line found.
4420 */
4421static Evas_Object_Textblock_Line *
4422_find_layout_line_num(const Evas_Object *obj, int line)
4423{
4424 Evas_Object_Textblock_Paragraph *par;
4425 Evas_Object_Textblock_Line *ln;
4426 Evas_Object_Textblock *o;
4427
4428 o = (Evas_Object_Textblock *)(obj->object_data);
4429
4430 par = _layout_find_paragraph_by_line_no(o, line);
4431 if (par)
4432 {
4433 _layout_paragraph_render(o, par);
4434 EINA_INLIST_FOREACH(par->lines, ln)
4435 {
4436 if (par->line_no + ln->line_no == line) return ln;
4437 }
4438 }
4439 return NULL;
4440}
4441
4442EAPI Evas_Object *
4443evas_object_textblock_add(Evas *e)
4444{
4445 Evas_Object *obj;
4446
4447 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
4448 return NULL;
4449 MAGIC_CHECK_END();
4450 obj = evas_object_new(e);
4451 evas_object_textblock_init(obj);
4452 evas_object_inject(obj, e);
4453 return obj;
4454}
4455
4456EAPI Evas_Textblock_Style *
4457evas_textblock_style_new(void)
4458{
4459 Evas_Textblock_Style *ts;
4460
4461 ts = calloc(1, sizeof(Evas_Textblock_Style));
4462 return ts;
4463}
4464
4465EAPI void
4466evas_textblock_style_free(Evas_Textblock_Style *ts)
4467{
4468 if (!ts) return;
4469 if (ts->objects)
4470 {
4471 ts->delete_me = 1;
4472 return;
4473 }
4474 _style_clear(ts);
4475 free(ts);
4476}
4477
4478EAPI void
4479evas_textblock_style_set(Evas_Textblock_Style *ts, const char *text)
4480{
4481 Eina_List *l;
4482 Evas_Object *obj;
4483
4484 if (!ts) return;
4485 /* If the style wasn't really changed, abort. */
4486 if ((!ts->style_text && !text) ||
4487 (ts->style_text && text && !strcmp(text, ts->style_text)))
4488 return;
4489
4490 EINA_LIST_FOREACH(ts->objects, l, obj)
4491 {
4492 Evas_Object_Textblock *o;
4493
4494 o = (Evas_Object_Textblock *)(obj->object_data);
4495 _evas_textblock_invalidate_all(o);
4496 _evas_textblock_changed(o, obj);
4497 }
4498
4499 _style_replace(ts, text);
4500
4501 if (ts->style_text)
4502 {
4503 // format MUST be KEY='VALUE'[KEY='VALUE']...
4504 const char *p;
4505 const char *key_start, *key_stop, *val_start;
4506
4507 key_start = key_stop = val_start = NULL;
4508 p = ts->style_text;
4509 while (*p)
4510 {
4511 if (!key_start)
4512 {
4513 if (!isspace((unsigned char)(*p)))
4514 key_start = p;
4515 }
4516 else if (!key_stop)
4517 {
4518 if ((*p == '=') || (isspace((unsigned char)(*p))))
4519 key_stop = p;
4520 }
4521 else if (!val_start)
4522 {
4523 if (((*p) == '\'') && (*(p + 1)))
4524 {
4525 val_start = ++p;
4526 }
4527 }
4528 if ((key_start) && (key_stop) && (val_start))
4529 {
4530 char *tags, *replaces = NULL;
4531 Evas_Object_Style_Tag *tag;
4532 const char *val_stop = NULL;
4533 size_t tag_len;
4534 size_t replace_len;
4535
4536 {
4537 Eina_Strbuf *buf = eina_strbuf_new();
4538 val_stop = val_start;
4539 while(*p)
4540 {
4541 if (*p == '\'')
4542 {
4543 /* Break if we found the tag end */
4544 if (p[-1] != '\\')
4545 {
4546 eina_strbuf_append_length(buf, val_stop,
4547 p - val_stop);
4548 break;
4549 }
4550 else
4551 {
4552 eina_strbuf_append_length(buf, val_stop,
4553 p - val_stop - 1);
4554 eina_strbuf_append_char(buf, '\'');
4555 val_stop = p + 1;
4556 }
4557 }
4558 p++;
4559 }
4560 replaces = eina_strbuf_string_steal(buf);
4561 eina_strbuf_free(buf);
4562 }
4563 /* If we didn't find an end, just aboart. */
4564 if (!*p)
4565 {
4566 if (replaces) free(replaces);
4567 break;
4568 }
4569
4570 tag_len = key_stop - key_start;
4571 replace_len = val_stop - val_start;
4572
4573 tags = malloc(tag_len + 1);
4574 if (tags)
4575 {
4576 memcpy(tags, key_start, tag_len);
4577 tags[tag_len] = 0;
4578 }
4579
4580 if ((tags) && (replaces))
4581 {
4582 if (!strcmp(tags, "DEFAULT"))
4583 {
4584 ts->default_tag = replaces;
4585 free(tags);
4586 }
4587 else
4588 {
4589 tag = calloc(1, sizeof(Evas_Object_Style_Tag));
4590 if (tag)
4591 {
4592 tag->tag.tag = tags;
4593 tag->tag.replace = replaces;
4594 tag->tag.tag_len = tag_len;
4595 tag->tag.replace_len = replace_len;
4596 ts->tags = (Evas_Object_Style_Tag *)eina_inlist_append(EINA_INLIST_GET(ts->tags), EINA_INLIST_GET(tag));
4597 }
4598 else
4599 {
4600 free(tags);
4601 free(replaces);
4602 }
4603 }
4604 }
4605 else
4606 {
4607 if (tags) free(tags);
4608 if (replaces) free(replaces);
4609 }
4610 key_start = key_stop = val_start = NULL;
4611 }
4612 p++;
4613 }
4614 }
4615}
4616
4617EAPI const char *
4618evas_textblock_style_get(const Evas_Textblock_Style *ts)
4619{
4620 if (!ts) return NULL;
4621 return ts->style_text;
4622}
4623
4624/* textblock styles */
4625
4626static void
4627_textblock_style_generic_set(Evas_Object *obj, Evas_Textblock_Style *ts,
4628 Evas_Textblock_Style **obj_ts)
4629{
4630 TB_HEAD();
4631 if (ts == *obj_ts) return;
4632 if ((ts) && (ts->delete_me)) return;
4633 if (*obj_ts)
4634 {
4635 Evas_Textblock_Style *old_ts;
4636 if (o->markup_text)
4637 {
4638 free(o->markup_text);
4639 o->markup_text = NULL;
4640 }
4641
4642 old_ts = *obj_ts;
4643 old_ts->objects = eina_list_remove(old_ts->objects, obj);
4644 if ((old_ts->delete_me) && (!old_ts->objects))
4645 evas_textblock_style_free(old_ts);
4646 }
4647 if (ts)
4648 {
4649 ts->objects = eina_list_append(ts->objects, obj);
4650 }
4651 *obj_ts = ts;
4652
4653 _evas_textblock_invalidate_all(o);
4654 _evas_textblock_changed(o, obj);
4655}
4656
4657EAPI void
4658evas_object_textblock_style_set(Evas_Object *obj, Evas_Textblock_Style *ts)
4659{
4660 TB_HEAD();
4661 _textblock_style_generic_set(obj, ts, &(o->style));
4662}
4663
4664EAPI const Evas_Textblock_Style *
4665evas_object_textblock_style_get(const Evas_Object *obj)
4666{
4667 TB_HEAD_RETURN(NULL);
4668 return o->style;
4669}
4670
4671EAPI void
4672evas_object_textblock_style_user_push(Evas_Object *obj, Evas_Textblock_Style *ts)
4673{
4674 TB_HEAD();
4675 _textblock_style_generic_set(obj, ts, &(o->style_user));
4676}
4677
4678EAPI const Evas_Textblock_Style *
4679evas_object_textblock_style_user_peek(const Evas_Object *obj)
4680{
4681 TB_HEAD_RETURN(NULL);
4682 return o->style_user;
4683}
4684
4685EAPI void
4686evas_object_textblock_style_user_pop(Evas_Object *obj)
4687{
4688 TB_HEAD();
4689 _textblock_style_generic_set(obj, NULL, &(o->style_user));
4690}
4691
4692EAPI void
4693evas_object_textblock_replace_char_set(Evas_Object *obj, const char *ch)
4694{
4695 TB_HEAD();
4696 if (o->repch) eina_stringshare_del(o->repch);
4697 if (ch) o->repch = eina_stringshare_add(ch);
4698 else o->repch = NULL;
4699 _evas_textblock_invalidate_all(o);
4700 _evas_textblock_changed(o, obj);
4701}
4702
4703EAPI void
4704evas_object_textblock_legacy_newline_set(Evas_Object *obj, Eina_Bool mode)
4705{
4706 TB_HEAD();
4707 if (o->legacy_newline == mode)
4708 return;
4709
4710 o->legacy_newline = mode;
4711 /* FIXME: Should recreate all the textnodes... For now, it's just
4712 * for new text inserted. */
4713}
4714
4715EAPI Eina_Bool
4716evas_object_textblock_legacy_newline_get(const Evas_Object *obj)
4717{
4718 TB_HEAD_RETURN(EINA_FALSE);
4719 return o->legacy_newline;
4720}
4721
4722EAPI void
4723evas_object_textblock_valign_set(Evas_Object *obj, double align)
4724{
4725 TB_HEAD();
4726 if (align < 0.0) align = 0.0;
4727 else if (align > 1.0) align = 1.0;
4728 if (o->valign == align) return;
4729 o->valign = align;
4730 _evas_textblock_changed(o, obj);
4731}
4732
4733EAPI double
4734evas_object_textblock_valign_get(const Evas_Object *obj)
4735{
4736 TB_HEAD_RETURN(0.0);
4737 return o->valign;
4738}
4739
4740EAPI void
4741evas_object_textblock_bidi_delimiters_set(Evas_Object *obj, const char *delim)
4742{
4743 TB_HEAD();
4744 eina_stringshare_replace(&o->bidi_delimiters, delim);
4745}
4746
4747EAPI const char *
4748evas_object_textblock_bidi_delimiters_get(const Evas_Object *obj)
4749{
4750 TB_HEAD_RETURN(NULL);
4751 return o->bidi_delimiters;
4752}
4753
4754EAPI const char *
4755evas_object_textblock_replace_char_get(Evas_Object *obj)
4756{
4757 TB_HEAD_RETURN(NULL);
4758 return o->repch;
4759}
4760
4761/**
4762 * @internal
4763 * Advance p_buff to point after the end of the string. It's used with the
4764 * @ref escaped_strings[] variable.
4765 *
4766 * @param p_buff the pointer to the current string.
4767 */
4768static inline void
4769_escaped_advance_after_end_of_string(const char **p_buf)
4770{
4771 while (**p_buf != 0) (*p_buf)++;
4772 (*p_buf)++;
4773}
4774
4775/**
4776 * @internal
4777 * Advance p_buff to point after the end of the string. It's used with the
4778 * @ref escaped_strings[] variable. Also chec if matches.
4779 * FIXME: doc.
4780 *
4781 * @param p_buff the pointer to the current string.
4782 */
4783static inline int
4784_escaped_is_eq_and_advance(const char *s, const char *s_end,
4785 const char **p_m, const char *m_end)
4786{
4787 Eina_Bool reached_end;
4788 for (;((s < s_end) && (*p_m < m_end)); s++, (*p_m)++)
4789 {
4790 if (*s != **p_m)
4791 {
4792 _escaped_advance_after_end_of_string(p_m);
4793 return 0;
4794 }
4795 }
4796
4797 reached_end = !**p_m;
4798 if (*p_m < m_end)
4799 _escaped_advance_after_end_of_string(p_m);
4800
4801 return ((s == s_end) && reached_end);
4802}
4803
4804/**
4805 * @internal
4806 *
4807 * @param s the string to match
4808 */
4809static inline const char *
4810_escaped_char_match(const char *s, int *adv)
4811{
4812 const char *map_itr, *map_end, *mc, *sc;
4813
4814 map_itr = escape_strings;
4815 map_end = map_itr + sizeof(escape_strings);
4816
4817 while (map_itr < map_end)
4818 {
4819 const char *escape;
4820 int match;
4821
4822 escape = map_itr;
4823 _escaped_advance_after_end_of_string(&map_itr);
4824 if (map_itr >= map_end) break;
4825
4826 mc = map_itr;
4827 sc = s;
4828 match = 1;
4829 while ((*mc) && (*sc))
4830 {
4831 if ((unsigned char)*sc < (unsigned char)*mc) return NULL;
4832 if (*sc != *mc)
4833 {
4834 match = 0;
4835 break;
4836 }
4837 mc++;
4838 sc++;
4839 }
4840 if (match)
4841 {
4842 *adv = mc - map_itr;
4843 return escape;
4844 }
4845 _escaped_advance_after_end_of_string(&map_itr);
4846 }
4847 return NULL;
4848}
4849
4850/**
4851 * @internal
4852 * FIXME: TBD.
4853 *
4854 * @param s the string to match
4855 */
4856static inline const char *
4857_escaped_char_get(const char *s, const char *s_end)
4858{
4859 /* Handle numeric escape codes. */
4860 if (s[1] == '#')
4861 {
4862 static char utf8_escape[7]; /* Support up to 6 bytes utf8 */
4863 char ustr[10];
4864 Eina_Unicode uchar[2] = { 0, 0 };
4865 char *utf8_char;
4866 size_t len = 0;
4867 int base = 10;
4868 s += 2; /* Skip "&#" */
4869
4870 if (tolower((unsigned char)(*s)) == 'x')
4871 {
4872 s++;
4873 base = 16;
4874 }
4875
4876 len = s_end - s;
4877 if (len >= sizeof(ustr) + 1)
4878 len = sizeof(ustr);
4879
4880 memcpy(ustr, s, len);
4881 ustr[len] = '\0';
4882 uchar[0] = strtol(ustr, NULL, base);
4883
4884 if (uchar[0] == 0)
4885 return NULL;
4886
4887 utf8_char = eina_unicode_unicode_to_utf8(uchar, NULL);
4888 strcpy(utf8_escape, utf8_char);
4889 free(utf8_char);
4890
4891 return utf8_escape;
4892 }
4893 else
4894 {
4895 const char *map_itr, *map_end;
4896
4897 map_itr = escape_strings;
4898 map_end = map_itr + sizeof(escape_strings);
4899
4900 while (map_itr < map_end)
4901 {
4902 if (_escaped_is_eq_and_advance(s, s_end, &map_itr, map_end))
4903 return map_itr;
4904 if (map_itr < map_end)
4905 _escaped_advance_after_end_of_string(&map_itr);
4906 }
4907 }
4908
4909 return NULL;
4910}
4911
4912EAPI const char *
4913evas_textblock_escape_string_get(const char *escape)
4914{
4915 /* &amp; -> & */
4916 return _escaped_char_get(escape, escape + strlen(escape));
4917}
4918
4919EAPI const char *
4920evas_textblock_escape_string_range_get(const char *escape_start, const char *escape_end)
4921{
4922 return _escaped_char_get(escape_start, escape_end);
4923}
4924
4925EAPI const char *
4926evas_textblock_string_escape_get(const char *string, int *len_ret)
4927{
4928 /* & -> &amp; */
4929 return _escaped_char_match(string, len_ret);
4930}
4931
4932/**
4933 * @internal
4934 * Appends the escaped char beteewn s and s_end to the curosr
4935 *
4936 *
4937 * @param s the start of the string
4938 * @param s_end the end of the string.
4939 */
4940static inline void
4941_append_escaped_char(Evas_Textblock_Cursor *cur, const char *s,
4942 const char *s_end)
4943{
4944 const char *escape;
4945
4946 escape = _escaped_char_get(s, s_end);
4947 if (escape)
4948 evas_textblock_cursor_text_append(cur, escape);
4949}
4950
4951/**
4952 * @internal
4953 * prepends the escaped char beteewn s and s_end to the curosr
4954 *
4955 *
4956 * @param s the start of the string
4957 * @param s_end the end of the string.
4958 */
4959static inline void
4960_prepend_escaped_char(Evas_Textblock_Cursor *cur, const char *s,
4961 const char *s_end)
4962{
4963 const char *escape;
4964
4965 escape = _escaped_char_get(s, s_end);
4966 if (escape)
4967 evas_textblock_cursor_text_prepend(cur, escape);
4968}
4969
4970
4971EAPI void
4972evas_object_textblock_text_markup_set(Evas_Object *obj, const char *text)
4973{
4974 TB_HEAD();
4975 if ((text != o->markup_text) && (o->markup_text))
4976 {
4977 free(o->markup_text);
4978 o->markup_text = NULL;
4979 }
4980 _nodes_clear(obj);
4981 if (!o->style && !o->style_user)
4982 {
4983 if (text != o->markup_text)
4984 {
4985 if (text) o->markup_text = strdup(text);
4986 }
4987 return;
4988 }
4989 evas_textblock_cursor_paragraph_first(o->cursor);
4990
4991 evas_object_textblock_text_markup_prepend(o->cursor, text);
4992 /* Point all the cursors to the starrt */
4993 {
4994 Eina_List *l;
4995 Evas_Textblock_Cursor *data;
4996
4997 evas_textblock_cursor_paragraph_first(o->cursor);
4998 EINA_LIST_FOREACH(o->cursors, l, data)
4999 evas_textblock_cursor_paragraph_first(data);
5000 }
5001}
5002
5003EAPI void
5004evas_object_textblock_text_markup_prepend(Evas_Textblock_Cursor *cur, const char *text)
5005{
5006 Evas_Object *obj = cur->obj;
5007 TB_HEAD();
5008 if (text)
5009 {
5010 char *s, *p;
5011 char *tag_start, *tag_end, *esc_start, *esc_end;
5012
5013 tag_start = tag_end = esc_start = esc_end = NULL;
5014 p = (char *)text;
5015 s = p;
5016 /* This loop goes through all of the mark up text until it finds format
5017 * tags, escape sequences or the terminating NULL. When it finds either
5018 * of those, it appends the text found up until that point to the textblock
5019 * proccesses whatever found. It repeats itself until the termainating
5020 * NULL is reached. */
5021 for (;;)
5022 {
5023 size_t text_len;
5024 /* If we got to the end of string or just finished/started tag
5025 * or escape sequence handling. */
5026 if ((*p == 0) ||
5027 (tag_end) || (esc_end) ||
5028 (tag_start) || (esc_start))
5029 {
5030 if (tag_end)
5031 {
5032 /* If we reached to a tag ending, analyze the tag */
5033 char *ttag;
5034 size_t ttag_len = tag_end - tag_start;
5035
5036
5037 ttag = malloc(ttag_len + 1);
5038 if (ttag)
5039 {
5040 memcpy(ttag, tag_start, ttag_len);
5041 ttag[ttag_len] = 0;
5042 evas_textblock_cursor_format_prepend(cur, ttag);
5043 free(ttag);
5044 }
5045 tag_start = tag_end = NULL;
5046 }
5047 else if (esc_end)
5048 {
5049 _prepend_escaped_char(cur, esc_start, esc_end + 1);
5050 esc_start = esc_end = NULL;
5051 }
5052 else if (*p == 0)
5053 {
5054 _prepend_text_run(cur, s, p);
5055 s = NULL;
5056 }
5057 if (*p == 0)
5058 break;
5059 }
5060 if (*p == '<')
5061 {
5062 if (!esc_start)
5063 {
5064 /* Append the text prior to this to the textblock and mark
5065 * the start of the tag */
5066 tag_start = p;
5067 tag_end = NULL;
5068 _prepend_text_run(cur, s, p);
5069 s = NULL;
5070 }
5071 }
5072 else if (*p == '>')
5073 {
5074 if (tag_start)
5075 {
5076 tag_end = p + 1;
5077 s = p + 1;
5078 }
5079 }
5080 else if (*p == '&')
5081 {
5082 if (!tag_start)
5083 {
5084 /* Append the text prior to this to the textblock and mark
5085 * the start of the escape sequence */
5086 esc_start = p;
5087 esc_end = NULL;
5088 _prepend_text_run(cur, s, p);
5089 s = NULL;
5090 }
5091 }
5092 else if (*p == ';')
5093 {
5094 if (esc_start)
5095 {
5096 esc_end = p;
5097 s = p + 1;
5098 }
5099 }
5100 /* Unicode object replcament char */
5101 else if (!strncmp(_REPLACEMENT_CHAR_UTF8, p,
5102 text_len = strlen(_REPLACEMENT_CHAR_UTF8)) ||
5103 !strncmp(_NEWLINE_UTF8, p,
5104 text_len = strlen(_NEWLINE_UTF8)) ||
5105 !strncmp(_TAB_UTF8, p,
5106 text_len = strlen(_TAB_UTF8)) ||
5107 !strncmp(_PARAGRAPH_SEPARATOR_UTF8, p,
5108 text_len = strlen(_PARAGRAPH_SEPARATOR_UTF8)))
5109 {
5110 /*FIXME: currently just remove them, maybe do something
5111 * fancier in the future, atm it breaks if this char
5112 * is inside <> */
5113 _prepend_text_run(cur, s, p);
5114 /* it's also advanced later in this loop need +text_len
5115 in total*/
5116 p += text_len - 1;
5117 s = p + 1; /* One after the end of the replacement char */
5118 }
5119 p++;
5120 }
5121 }
5122 _evas_textblock_changed(o, obj);
5123}
5124
5125
5126/**
5127 * @internal
5128 * An helper function to markup get. Appends the format from fnode to the strbugf txt.
5129 *
5130 * @param o the textblock object.
5131 * @param txt the strbuf to append to.
5132 * @param fnode the format node to process.
5133 */
5134static void
5135_markup_get_format_append(Eina_Strbuf *txt, Evas_Object_Textblock_Node_Format *fnode)
5136{
5137 eina_strbuf_append_char(txt, '<');
5138 {
5139 const char *s;
5140
5141 // FIXME: need to escape
5142 s = fnode->orig_format;
5143 if (!fnode->opener && !fnode->own_closer)
5144 eina_strbuf_append_char(txt, '/');
5145 eina_strbuf_append(txt, s);
5146 if (fnode->own_closer)
5147 eina_strbuf_append_char(txt, '/');
5148 }
5149 eina_strbuf_append_char(txt, '>');
5150}
5151
5152/**
5153 * @internal
5154 * An helper function to markup get. Appends the text in text.
5155 *
5156 * @param txt the strbuf to append to.
5157 * @param text the text to process.
5158 */
5159static void
5160_markup_get_text_append(Eina_Strbuf *txt, const Eina_Unicode *text)
5161{
5162 char *p = eina_unicode_unicode_to_utf8(text, NULL);
5163 char *base = p;
5164 while (*p)
5165 {
5166 const char *escape;
5167 int adv;
5168
5169 escape = _escaped_char_match(p, &adv);
5170 if (escape)
5171 {
5172 p += adv;
5173 eina_strbuf_append(txt, escape);
5174 }
5175 else
5176 {
5177 eina_strbuf_append_char(txt, *p);
5178 p++;
5179 }
5180 }
5181 free(base);
5182}
5183EAPI const char *
5184evas_object_textblock_text_markup_get(const Evas_Object *obj)
5185{
5186 Evas_Object_Textblock_Node_Text *n;
5187 Eina_Strbuf *txt = NULL;
5188
5189 TB_HEAD_RETURN(NULL);
5190 if (o->markup_text) return(o->markup_text);
5191 txt = eina_strbuf_new();
5192 EINA_INLIST_FOREACH(o->text_nodes, n)
5193 {
5194 Evas_Object_Textblock_Node_Format *fnode;
5195 Eina_Unicode *text_base, *text;
5196 int off;
5197
5198 /* For each text node to thorugh all of it's format nodes
5199 * append text from the start to the offset of the next format
5200 * using the last format got. if needed it also creates format items
5201 * this is the core algorithm of the layout mechanism.
5202 * Skip the unicode replacement chars when there are because
5203 * we don't want to print them. */
5204 text_base = text =
5205 eina_unicode_strndup(eina_ustrbuf_string_get(n->unicode),
5206 eina_ustrbuf_length_get(n->unicode));
5207 fnode = n->format_node;
5208 off = 0;
5209 while (fnode && (fnode->text_node == n))
5210 {
5211 Eina_Unicode tmp_ch;
5212 off += fnode->offset;
5213 /* No need to skip on the first run */
5214 tmp_ch = text[off];
5215 text[off] = 0; /* Null terminate the part of the string */
5216 _markup_get_text_append(txt, text);
5217 _markup_get_format_append(txt, fnode);
5218 text[off] = tmp_ch; /* Restore the char */
5219 text += off;
5220 if (fnode->visible)
5221 {
5222 off = -1;
5223 text++;
5224 }
5225 else
5226 {
5227 off = 0;
5228 }
5229 fnode = _NODE_FORMAT(EINA_INLIST_GET(fnode)->next);
5230 }
5231 /* Add the rest, skip replacement */
5232 _markup_get_text_append(txt, text);
5233 free(text_base);
5234 }
5235
5236
5237 o->markup_text = eina_strbuf_string_steal(txt);
5238 eina_strbuf_free(txt);
5239 return o->markup_text;
5240}
5241
5242EAPI char *
5243evas_textblock_text_markup_to_utf8(const Evas_Object *obj, const char *text)
5244{
5245 /* FIXME: Redundant and awful, should be merged with markup_prepend */
5246 Eina_Strbuf *sbuf;
5247 char *s, *p, *ret;
5248 char *tag_start, *tag_end, *esc_start, *esc_end;
5249
5250 if (!text) return NULL;
5251
5252
5253 tag_start = tag_end = esc_start = esc_end = NULL;
5254 sbuf = eina_strbuf_new();
5255 p = (char *)text;
5256 s = p;
5257 /* This loop goes through all of the mark up text until it finds format
5258 * tags, escape sequences or the terminating NULL. When it finds either
5259 * of those, it appends the text found up until that point to the textblock
5260 * proccesses whatever found. It repeats itself until the termainating
5261 * NULL is reached. */
5262 for (;;)
5263 {
5264 /* If we got to the end of string or just finished/started tag
5265 * or escape sequence handling. */
5266 if ((*p == 0) ||
5267 (tag_end) || (esc_end) ||
5268 (tag_start) || (esc_start))
5269 {
5270 if (tag_end)
5271 {
5272 /* If we reached to a tag ending, analyze the tag */
5273 char *ttag;
5274 size_t ttag_len;
5275
5276 tag_start++; /* Skip the < */
5277 tag_end--; /* Skip the > */
5278 if ((tag_end > tag_start) && (*(tag_end - 1) == '/'))
5279 {
5280 tag_end --; /* Skip the terminating '/' */
5281 while (*(tag_end - 1) == ' ')
5282 tag_end--; /* skip trailing ' ' */
5283 }
5284
5285 ttag_len = tag_end - tag_start;
5286
5287 ttag = malloc(ttag_len + 1);
5288 if (ttag)
5289 {
5290 const char *match = NULL;
5291 size_t replace_len;
5292 memcpy(ttag, tag_start, ttag_len);
5293 ttag[ttag_len] = 0;
5294
5295
5296 if (obj)
5297 {
5298 match = _style_match_tag(
5299 evas_object_textblock_style_get(obj),
5300 ttag, ttag_len, &replace_len);
5301 }
5302
5303 if (!match) match = ttag;
5304
5305 if (_IS_PARAGRAPH_SEPARATOR_SIMPLE(match))
5306 eina_strbuf_append(sbuf, _PARAGRAPH_SEPARATOR_UTF8);
5307 else if (_IS_LINE_SEPARATOR(match))
5308 eina_strbuf_append(sbuf, _NEWLINE_UTF8);
5309 else if (_IS_TAB(match))
5310 eina_strbuf_append(sbuf, _TAB_UTF8);
5311 else if (!strncmp(match, "item", 4))
5312 eina_strbuf_append(sbuf, _REPLACEMENT_CHAR_UTF8);
5313
5314 free(ttag);
5315 }
5316 tag_start = tag_end = NULL;
5317 }
5318 else if (esc_end)
5319 {
5320 const char *escape;
5321
5322 escape = _escaped_char_get(esc_start, esc_end + 1);
5323 if (escape) eina_strbuf_append(sbuf, escape);
5324 esc_start = esc_end = NULL;
5325 }
5326 else if (*p == 0)
5327 {
5328 eina_strbuf_append_length(sbuf, s, p - s);
5329 s = NULL;
5330 }
5331 if (*p == 0)
5332 break;
5333 }
5334 if (*p == '<')
5335 {
5336 if (!esc_start)
5337 {
5338 /* Append the text prior to this to the textblock and
5339 * mark the start of the tag */
5340 tag_start = p;
5341 tag_end = NULL;
5342 eina_strbuf_append_length(sbuf, s, p - s);
5343 s = NULL;
5344 }
5345 }
5346 else if (*p == '>')
5347 {
5348 if (tag_start)
5349 {
5350 tag_end = p + 1;
5351 s = p + 1;
5352 }
5353 }
5354 else if (*p == '&')
5355 {
5356 if (!tag_start)
5357 {
5358 /* Append the text prior to this to the textblock and mark
5359 * the start of the escape sequence */
5360 esc_start = p;
5361 esc_end = NULL;
5362 eina_strbuf_append_length(sbuf, s, p - s);
5363 s = NULL;
5364 }
5365 }
5366 else if (*p == ';')
5367 {
5368 if (esc_start)
5369 {
5370 esc_end = p;
5371 s = p + 1;
5372 }
5373 }
5374 p++;
5375 }
5376
5377 ret = eina_strbuf_string_steal(sbuf);
5378 eina_strbuf_free(sbuf);
5379 return ret;
5380}
5381
5382EAPI char *
5383evas_textblock_text_utf8_to_markup(const Evas_Object *obj, const char *text)
5384{
5385 Eina_Strbuf *sbuf;
5386 char *str = NULL;
5387 int ch, pos = 0, pos2 = 0;
5388
5389 (void) obj;
5390
5391 if (!text) return NULL;
5392
5393 sbuf = eina_strbuf_new();
5394
5395 for (;;)
5396 {
5397 pos = pos2;
5398 pos2 = evas_string_char_next_get(text, pos2, &ch);
5399 if ((ch <= 0) || (pos2 <= 0)) break;
5400
5401 if (ch == _NEWLINE)
5402 eina_strbuf_append(sbuf, "<br/>");
5403 else if (ch == _TAB)
5404 eina_strbuf_append(sbuf, "<tab/>");
5405 else if (ch == '<')
5406 eina_strbuf_append(sbuf, "&lt;");
5407 else if (ch == '>')
5408 eina_strbuf_append(sbuf, "&gt;");
5409 else if (ch == '&')
5410 eina_strbuf_append(sbuf, "&amp;");
5411 else if (ch == _PARAGRAPH_SEPARATOR)
5412 eina_strbuf_append(sbuf, "<ps/>");
5413 else if (ch == _REPLACEMENT_CHAR)
5414 eina_strbuf_append(sbuf, "&#xfffc;");
5415 else
5416 {
5417 eina_strbuf_append_length(sbuf, text + pos, pos2 - pos);
5418 }
5419 }
5420 str = eina_strbuf_string_steal(sbuf);
5421 eina_strbuf_free(sbuf);
5422 return str;
5423
5424}
5425
5426/* cursors */
5427
5428/**
5429 * @internal
5430 * Merge the current node with the next, no need to remove PS, already
5431 * not there.
5432 *
5433 * @param o the text block object.
5434 * @param to merge into to.
5435 */
5436static void
5437_evas_textblock_nodes_merge(Evas_Object_Textblock *o, Evas_Object_Textblock_Node_Text *to)
5438{
5439 Evas_Object_Textblock_Node_Format *itr;
5440 Evas_Object_Textblock_Node_Format *pnode;
5441 Evas_Object_Textblock_Node_Text *from;
5442 const Eina_Unicode *text;
5443 int to_len, len;
5444
5445 if (!to) return;
5446 from = _NODE_TEXT(EINA_INLIST_GET(to)->next);
5447
5448 to_len = eina_ustrbuf_length_get(to->unicode);
5449 text = eina_ustrbuf_string_get(from->unicode);
5450 len = eina_ustrbuf_length_get(from->unicode);
5451 eina_ustrbuf_append_length(to->unicode, text, len);
5452
5453 itr = from->format_node;
5454 if (itr && (itr->text_node == from))
5455 {
5456 pnode = _NODE_FORMAT(EINA_INLIST_GET(itr)->prev);
5457 if (pnode && (pnode->text_node == to))
5458 {
5459 itr->offset += to_len - _evas_textblock_node_format_pos_get(pnode);
5460 }
5461 else
5462 {
5463 itr->offset += to_len;
5464 }
5465 }
5466
5467 while (itr && (itr->text_node == from))
5468 {
5469 itr->text_node = to;
5470 itr = _NODE_FORMAT(EINA_INLIST_GET(itr)->next);
5471 }
5472 if (!to->format_node || (to->format_node->text_node != to))
5473 {
5474 to->format_node = from->format_node;
5475 }
5476
5477 /* When it comes to how we handle it, merging is like removing both nodes
5478 * and creating a new one, se we need to do the needed cleanups. */
5479 if (to->par)
5480 to->par->text_node = NULL;
5481 to->par = NULL;
5482
5483 to->is_new = EINA_TRUE;
5484
5485 _evas_textblock_cursors_set_node(o, from, to);
5486 _evas_textblock_node_text_remove(o, from);
5487}
5488
5489/**
5490 * @internal
5491 * Merge the current node with the next, no need to remove PS, already
5492 * not there.
5493 *
5494 * @param cur the cursor that points to the current node
5495 */
5496static void
5497_evas_textblock_cursor_nodes_merge(Evas_Textblock_Cursor *cur)
5498{
5499 Evas_Object_Textblock_Node_Text *nnode;
5500 Evas_Object_Textblock *o;
5501 int len;
5502 if (!cur) return;
5503
5504 len = eina_ustrbuf_length_get(cur->node->unicode);
5505
5506 o = (Evas_Object_Textblock *)(cur->obj->object_data);
5507 nnode = _NODE_TEXT(EINA_INLIST_GET(cur->node)->next);
5508 _evas_textblock_nodes_merge(o, cur->node);
5509 _evas_textblock_cursors_update_offset(cur, nnode, 0, len);
5510 _evas_textblock_cursors_set_node(o, nnode, cur->node);
5511 if (nnode == o->cursor->node)
5512 {
5513 o->cursor->node = cur->node;
5514 o->cursor->pos += len;
5515 }
5516}
5517
5518/**
5519 * @internal
5520 * Return the format at a specific position.
5521 *
5522 * @param cur the cursor to the position.
5523 * @return the format node at the specific position or NULL if not found.
5524 */
5525static Evas_Object_Textblock_Node_Format *
5526_evas_textblock_cursor_node_format_at_pos_get(const Evas_Textblock_Cursor *cur)
5527{
5528 Evas_Object_Textblock_Node_Format *node;
5529 Evas_Object_Textblock_Node_Format *itr;
5530 int position = 0;
5531
5532 if (!cur->node) return NULL;
5533
5534 node = cur->node->format_node;
5535 if (!node) return NULL;
5536 /* If there is no exclusive format node to this paragraph return the
5537 * previous's node */
5538 /* Find the main format node */
5539 EINA_INLIST_FOREACH(node, itr)
5540 {
5541 if (itr->text_node != cur->node)
5542 {
5543 return NULL;
5544 }
5545 if ((position + itr->offset) == cur->pos)
5546 {
5547 return itr;
5548 }
5549 position += itr->offset;
5550 }
5551 return NULL;
5552}
5553
5554/**
5555 * @internal
5556 * Return the last format node at the position of the format node n.
5557 *
5558 * @param n a format node at the position.
5559 * @return the last format node at the position of n.
5560 */
5561static Evas_Object_Textblock_Node_Format *
5562_evas_textblock_node_format_last_at_off(const Evas_Object_Textblock_Node_Format *n)
5563{
5564 const Evas_Object_Textblock_Node_Format *nnode;
5565 const Evas_Object_Textblock_Node_Text *tnode;
5566 if (!n) return NULL;
5567 nnode = n;
5568 tnode = n->text_node;
5569 do
5570 {
5571 n = nnode;
5572 nnode = _NODE_FORMAT(EINA_INLIST_GET(nnode)->next);
5573 }
5574 while (nnode && (nnode->text_node == tnode) && (nnode->offset == 0));
5575
5576 return (Evas_Object_Textblock_Node_Format *) n;
5577}
5578
5579/**
5580 * @internal
5581 * Returns the visible format at a specific location.
5582 *
5583 * @param n a format at the specific position.
5584 * @return the format node at the specific position or NULL if not found.
5585 */
5586static Evas_Object_Textblock_Node_Format *
5587_evas_textblock_node_visible_at_pos_get(const Evas_Object_Textblock_Node_Format *n)
5588{
5589 const Evas_Object_Textblock_Node_Format *nnode;
5590 if (!n) return NULL;
5591 /* The visible format is the last one, because it inserts a replacement
5592 * char that advances the next formats. */
5593
5594 nnode = n;
5595 do
5596 {
5597 n = nnode;
5598 if (n->visible) return (Evas_Object_Textblock_Node_Format *) n;
5599 nnode = _NODE_FORMAT(EINA_INLIST_GET(nnode)->next);
5600 }
5601 while (nnode && (nnode->offset == 0));
5602
5603 return NULL;
5604}
5605
5606/**
5607 * @internal
5608 * Return the last format that applies to a specific cursor or at the specific
5609 * position the cursor points to. This means either a cursor at or before the
5610 * position of the cursor in the text node is returned or the previous's text
5611 * node's format node.
5612 *
5613 * @param cur the position to look at.
5614 * @return the format node found.
5615 */
5616static Evas_Object_Textblock_Node_Format *
5617_evas_textblock_cursor_node_format_before_or_at_pos_get(const Evas_Textblock_Cursor *cur)
5618{
5619 Evas_Object_Textblock_Node_Format *node, *pitr = NULL;
5620 Evas_Object_Textblock_Node_Format *itr;
5621 size_t position = 0;
5622
5623 if (!cur->node) return NULL;
5624
5625 node = cur->node->format_node;
5626 if (!node) return NULL;
5627 /* If there is no exclusive format node to this paragraph return the
5628 * previous's node */
5629 if (node->text_node != cur->node)
5630 {
5631 return node;
5632 }
5633 else if (node->offset > cur->pos)
5634 {
5635 return _NODE_FORMAT(EINA_INLIST_GET(node)->prev);
5636 }
5637 /* Find the main format node */
5638 pitr = _NODE_FORMAT(EINA_INLIST_GET(node)->prev);
5639 EINA_INLIST_FOREACH(node, itr)
5640 {
5641 if ((itr->text_node != cur->node) ||
5642 ((position + itr->offset) > cur->pos))
5643 {
5644 return pitr;
5645 }
5646 else if ((position + itr->offset) == cur->pos)
5647 {
5648 return itr;
5649 }
5650 pitr = itr;
5651 position += itr->offset;
5652 }
5653 return pitr;
5654}
5655
5656/**
5657 * @internal
5658 * Find the layout item and line that match the cursor.
5659 *
5660 * @param cur the cursor we are currently at. - NOT NULL.
5661 * @param[out] lnr the line found - not null.
5662 * @param[out] itr the item found - not null.
5663 * @return EINA_TRUE if we matched the previous format, EINA_FALSE otherwise.
5664 */
5665static Eina_Bool
5666_find_layout_item_match(const Evas_Textblock_Cursor *cur, Evas_Object_Textblock_Line **lnr, Evas_Object_Textblock_Item **itr)
5667{
5668 Evas_Textblock_Cursor cur2;
5669 Eina_Bool previous_format = EINA_FALSE;
5670
5671 cur2.obj = cur->obj;
5672 evas_textblock_cursor_copy(cur, &cur2);
5673 if (cur2.pos > 0)
5674 {
5675 cur2.pos--;
5676 }
5677
5678 if (_evas_textblock_cursor_is_at_the_end(cur) &&
5679 evas_textblock_cursor_format_is_visible_get(&cur2))
5680 {
5681 _find_layout_item_line_match(cur2.obj, cur2.node, cur2.pos, lnr, itr);
5682 previous_format = EINA_TRUE;
5683 }
5684 else
5685 {
5686 _find_layout_item_line_match(cur->obj, cur->node, cur->pos, lnr, itr);
5687 }
5688 return previous_format;
5689}
5690
5691EAPI Evas_Textblock_Cursor *
5692evas_object_textblock_cursor_get(const Evas_Object *obj)
5693{
5694 TB_HEAD_RETURN(NULL);
5695 return o->cursor;
5696}
5697
5698EAPI Evas_Textblock_Cursor *
5699evas_object_textblock_cursor_new(const Evas_Object *obj)
5700{
5701 Evas_Textblock_Cursor *cur;
5702
5703 TB_HEAD_RETURN(NULL);
5704 cur = calloc(1, sizeof(Evas_Textblock_Cursor));
5705 cur->obj = (Evas_Object *) obj;
5706 cur->node = o->text_nodes;
5707 cur->pos = 0;
5708
5709 o->cursors = eina_list_append(o->cursors, cur);
5710 return cur;
5711}
5712
5713EAPI void
5714evas_textblock_cursor_free(Evas_Textblock_Cursor *cur)
5715{
5716 Evas_Object_Textblock *o;
5717
5718 if (!cur) return;
5719 o = (Evas_Object_Textblock *)(cur->obj->object_data);
5720 if (cur == o->cursor) return;
5721 o->cursors = eina_list_remove(o->cursors, cur);
5722 free(cur);
5723}
5724
5725EAPI Eina_Bool
5726evas_textblock_cursor_is_format(const Evas_Textblock_Cursor *cur)
5727{
5728 if (!cur || !cur->node) return EINA_FALSE;
5729 return (_evas_textblock_cursor_node_format_at_pos_get(cur)) ?
5730 EINA_TRUE : EINA_FALSE;
5731}
5732
5733EAPI const Eina_List *
5734evas_textblock_node_format_list_get(const Evas_Object *obj, const char *anchor)
5735{
5736 TB_HEAD_RETURN(NULL);
5737 if (!strcmp(anchor, "a"))
5738 return o->anchors_a;
5739 else if (!strcmp(anchor, "item"))
5740 return o->anchors_item;
5741
5742 return NULL;
5743}
5744
5745EAPI const Evas_Object_Textblock_Node_Format *
5746evas_textblock_node_format_first_get(const Evas_Object *obj)
5747{
5748 TB_HEAD_RETURN(NULL);
5749 return o->format_nodes;
5750}
5751
5752EAPI const Evas_Object_Textblock_Node_Format *
5753evas_textblock_node_format_last_get(const Evas_Object *obj)
5754{
5755 TB_HEAD_RETURN(NULL);
5756 if (o->format_nodes)
5757 {
5758 return _NODE_FORMAT(EINA_INLIST_GET(o->format_nodes)->last);
5759 }
5760 return NULL;
5761}
5762
5763EAPI const Evas_Object_Textblock_Node_Format *
5764evas_textblock_node_format_next_get(const Evas_Object_Textblock_Node_Format *n)
5765{
5766 return _NODE_FORMAT(EINA_INLIST_GET(n)->next);
5767}
5768
5769EAPI const Evas_Object_Textblock_Node_Format *
5770evas_textblock_node_format_prev_get(const Evas_Object_Textblock_Node_Format *n)
5771{
5772 return _NODE_FORMAT(EINA_INLIST_GET(n)->prev);
5773}
5774
5775EAPI void
5776evas_textblock_node_format_remove_pair(Evas_Object *obj,
5777 Evas_Object_Textblock_Node_Format *n)
5778{
5779 Evas_Object_Textblock_Node_Text *tnode1;
5780 Evas_Object_Textblock_Node_Format *fmt, *found_node = NULL;
5781 Eina_List *fstack = NULL;
5782 TB_HEAD();
5783
5784 if (!n) return;
5785
5786 fmt = n;
5787
5788 do
5789 {
5790 const char *fstr = fmt->orig_format;
5791
5792 if (fmt->opener && !fmt->own_closer)
5793 {
5794 fstack = eina_list_prepend(fstack, fmt);
5795 }
5796 else if (fstr && !fmt->opener)
5797 {
5798 size_t fstr_len;
5799 fstr_len = strlen(fstr);
5800 /* Generic popper, just pop */
5801 if (((fstr[0] == ' ') && !fstr[1]) || !fstr[0])
5802 {
5803 fstack = eina_list_remove_list(fstack, fstack);
5804 if (!fstack)
5805 {
5806 found_node = fmt;
5807 goto found;
5808 }
5809 }
5810 /* Find the matching format and pop it, if the matching format
5811 * is out format, i.e the last one, pop and break. */
5812 else
5813 {
5814 Eina_List *i;
5815 Evas_Object_Textblock_Node_Format *fnode;
5816 EINA_LIST_FOREACH(fstack, i, fnode)
5817 {
5818 if (_FORMAT_IS_CLOSER_OF(
5819 fnode->orig_format, fstr, fstr_len))
5820 {
5821 /* Last one, this is our item! */
5822 if (!eina_list_next(i))
5823 {
5824 found_node = fmt;
5825 goto found;
5826 }
5827 fstack = eina_list_remove_list(fstack, i);
5828 break;
5829 }
5830 }
5831 }
5832 }
5833
5834 fmt = _NODE_FORMAT(EINA_INLIST_GET(fmt)->next);
5835 }
5836 while (fmt && fstack);
5837
5838found:
5839
5840 fstack = eina_list_free(fstack);
5841
5842 if (n->visible)
5843 {
5844 size_t ind = _evas_textblock_node_format_pos_get(n);
5845 const char *format = n->format;
5846 Evas_Textblock_Cursor cur;
5847 cur.obj = obj;
5848
5849 eina_ustrbuf_remove(n->text_node->unicode, ind, ind + 1);
5850 if (format && _IS_PARAGRAPH_SEPARATOR(o, format))
5851 {
5852 evas_textblock_cursor_at_format_set(&cur, n);
5853 _evas_textblock_cursor_nodes_merge(&cur);
5854 }
5855 _evas_textblock_cursors_update_offset(&cur, n->text_node, ind, -1);
5856 }
5857 tnode1 = n->text_node;
5858 _evas_textblock_node_format_remove(o, n, 0);
5859 if (found_node && (found_node != n))
5860 {
5861 Evas_Object_Textblock_Node_Text *tnode2;
5862 tnode2 = found_node->text_node;
5863 /* found_node can never be visible! (it's the closing format) */
5864 _evas_textblock_node_format_remove(o, found_node, 0);
5865
5866 /* FIXME: Should be unified in the layout, for example, added to a list
5867 * that checks this kind of removals. But until then, this is very fast
5868 * and works. */
5869 /* Mark all the text nodes in between the removed formats as dirty. */
5870 while (tnode1)
5871 {
5872 tnode1->dirty = EINA_TRUE;
5873 if (tnode1 == tnode2)
5874 break;
5875 tnode1 =
5876 _NODE_TEXT(EINA_INLIST_GET(tnode1)->next);
5877 }
5878 }
5879
5880 _evas_textblock_changed(o, obj);
5881}
5882
5883EAPI void
5884evas_textblock_cursor_paragraph_first(Evas_Textblock_Cursor *cur)
5885{
5886 Evas_Object_Textblock *o;
5887 if (!cur) return;
5888 o = (Evas_Object_Textblock *)(cur->obj->object_data);
5889 cur->node = o->text_nodes;
5890 cur->pos = 0;
5891
5892}
5893
5894EAPI void
5895evas_textblock_cursor_paragraph_last(Evas_Textblock_Cursor *cur)
5896{
5897 Evas_Object_Textblock *o;
5898 Evas_Object_Textblock_Node_Text *node;
5899
5900 if (!cur) return;
5901 o = (Evas_Object_Textblock *)(cur->obj->object_data);
5902 node = o->text_nodes;
5903 if (node)
5904 {
5905 node = _NODE_TEXT(EINA_INLIST_GET(node)->last);
5906 cur->node = node;
5907 cur->pos = 0;
5908
5909 evas_textblock_cursor_paragraph_char_last(cur);
5910 }
5911 else
5912 {
5913 cur->node = NULL;
5914 cur->pos = 0;
5915
5916 }
5917}
5918
5919EAPI Eina_Bool
5920evas_textblock_cursor_paragraph_next(Evas_Textblock_Cursor *cur)
5921{
5922 if (!cur) return EINA_FALSE;
5923 if (!cur->node) return EINA_FALSE;
5924 /* If there is a current text node, return the next text node (if exists)
5925 * otherwise, just return False. */
5926 if (cur->node)
5927 {
5928 Evas_Object_Textblock_Node_Text *nnode;
5929 nnode = _NODE_TEXT(EINA_INLIST_GET(cur->node)->next);
5930 if (nnode)
5931 {
5932 cur->node = nnode;
5933 cur->pos = 0;
5934
5935 return EINA_TRUE;
5936 }
5937 }
5938 return EINA_FALSE;
5939}
5940
5941EAPI Eina_Bool
5942evas_textblock_cursor_paragraph_prev(Evas_Textblock_Cursor *cur)
5943{
5944 Evas_Object_Textblock_Node_Text *node;
5945 if (!cur) return EINA_FALSE;
5946 if (!cur->node) return EINA_FALSE;
5947 /* If the current node is a text node, just get the prev if any,
5948 * if it's a format, get the current text node out of the format and return
5949 * the prev text node if any. */
5950 node = cur->node;
5951 /* If there is a current text node, return the prev text node
5952 * (if exists) otherwise, just return False. */
5953 if (node)
5954 {
5955 Evas_Object_Textblock_Node_Text *pnode;
5956 pnode = _NODE_TEXT(EINA_INLIST_GET(cur->node)->prev);
5957 if (pnode)
5958 {
5959 cur->node = pnode;
5960 evas_textblock_cursor_paragraph_char_last(cur);
5961 return EINA_TRUE;
5962 }
5963 }
5964 return EINA_FALSE;
5965}
5966
5967EAPI void
5968evas_textblock_cursor_set_at_format(Evas_Textblock_Cursor *cur, const Evas_Object_Textblock_Node_Format *n)
5969{
5970 evas_textblock_cursor_at_format_set(cur, n);
5971}
5972
5973EAPI Eina_Bool
5974evas_textblock_cursor_format_next(Evas_Textblock_Cursor *cur)
5975{
5976 Evas_Object_Textblock_Node_Format *node;
5977
5978 if (!cur) return EINA_FALSE;
5979 if (!cur->node) return EINA_FALSE;
5980 /* If the current node is a format node, just get the next if any,
5981 * if it's a text, get the current format node out of the text and return
5982 * the next format node if any. */
5983 node = _evas_textblock_cursor_node_format_before_or_at_pos_get(cur);
5984 node = _evas_textblock_node_format_last_at_off(node);
5985 if (!node)
5986 {
5987 if (cur->node->format_node)
5988 {
5989 cur->pos = _evas_textblock_node_format_pos_get(node);
5990 return EINA_TRUE;
5991 }
5992 }
5993 /* If there is a current text node, return the next format node (if exists)
5994 * otherwise, just return False. */
5995 else
5996 {
5997 Evas_Object_Textblock_Node_Format *nnode;
5998 nnode = _NODE_FORMAT(EINA_INLIST_GET(node)->next);
5999 if (nnode)
6000 {
6001 cur->node = nnode->text_node;
6002 cur->pos = _evas_textblock_node_format_pos_get(nnode);
6003
6004 return EINA_TRUE;
6005 }
6006 }
6007 return EINA_FALSE;
6008}
6009
6010EAPI Eina_Bool
6011evas_textblock_cursor_format_prev(Evas_Textblock_Cursor *cur)
6012{
6013 const Evas_Object_Textblock_Node_Format *node;
6014 if (!cur) return EINA_FALSE;
6015 if (!cur->node) return EINA_FALSE;
6016 node = evas_textblock_cursor_format_get(cur);
6017 if (!node)
6018 {
6019 node = _evas_textblock_cursor_node_format_before_or_at_pos_get(cur);
6020 if (node)
6021 {
6022 cur->node = node->text_node;
6023 cur->pos = _evas_textblock_node_format_pos_get(node);
6024
6025 return EINA_TRUE;
6026 }
6027 }
6028 /* If there is a current text node, return the next text node (if exists)
6029 * otherwise, just return False. */
6030 if (node)
6031 {
6032 Evas_Object_Textblock_Node_Format *pnode;
6033 pnode = _NODE_FORMAT(EINA_INLIST_GET(node)->prev);
6034 if (pnode)
6035 {
6036 cur->node = pnode->text_node;
6037 cur->pos = _evas_textblock_node_format_pos_get(pnode);
6038
6039 return EINA_TRUE;
6040 }
6041 }
6042 return EINA_FALSE;
6043}
6044
6045#ifdef HAVE_LINEBREAK
6046
6047/* BREAK_AFTER: true if we can break after the current char.
6048 * Both macros assume str[i] is not the terminating nul */
6049#define BREAK_AFTER(i) \
6050 (breaks[i] == WORDBREAK_BREAK)
6051
6052#else
6053
6054#define BREAK_AFTER(i) \
6055 ((!text[i + 1]) || \
6056 (_is_white(text[i]) && !_is_white(text[i + 1])) || \
6057 (!_is_white(text[i]) && _is_white(text[i + 1])))
6058
6059#endif
6060
6061EAPI Eina_Bool
6062evas_textblock_cursor_word_start(Evas_Textblock_Cursor *cur)
6063{
6064 const Eina_Unicode *text;
6065 size_t i;
6066#ifdef HAVE_LINEBREAK
6067 char *breaks;
6068#endif
6069
6070 if (!cur) return EINA_FALSE;
6071 if (!cur->node) return EINA_FALSE;
6072
6073 text = eina_ustrbuf_string_get(cur->node->unicode);
6074
6075#ifdef HAVE_LINEBREAK
6076 {
6077 const char *lang = ""; /* FIXME: get lang */
6078 size_t len = eina_ustrbuf_length_get(cur->node->unicode);
6079 breaks = malloc(len);
6080 set_wordbreaks_utf32((const utf32_t *) text, len, lang, breaks);
6081 }
6082#endif
6083
6084 i = cur->pos;
6085
6086 /* Skip the first one. This ensures we don't point to the nul, and also
6087 * we just don't care about it anyway. */
6088 if (i > 0) i--;
6089
6090 for ( ; i > 0 ; i--)
6091 {
6092 if (BREAK_AFTER(i))
6093 {
6094 /* Advance to the current char */
6095 i++;
6096 break;
6097 }
6098 }
6099
6100 cur->pos = i;
6101
6102#ifdef HAVE_LINEBREAK
6103 free(breaks);
6104#endif
6105 return EINA_TRUE;
6106}
6107
6108EAPI Eina_Bool
6109evas_textblock_cursor_word_end(Evas_Textblock_Cursor *cur)
6110{
6111 const Eina_Unicode *text;
6112 size_t i;
6113#ifdef HAVE_LINEBREAK
6114 char *breaks;
6115#endif
6116
6117 if (!cur) return EINA_FALSE;
6118 if (!cur->node) return EINA_FALSE;
6119
6120 text = eina_ustrbuf_string_get(cur->node->unicode);
6121
6122#ifdef HAVE_LINEBREAK
6123 {
6124 const char *lang = ""; /* FIXME: get lang */
6125 size_t len = eina_ustrbuf_length_get(cur->node->unicode);
6126 breaks = malloc(len);
6127 set_wordbreaks_utf32((const utf32_t *) text, len, lang, breaks);
6128 }
6129#endif
6130
6131 i = cur->pos;
6132
6133 for ( ; text[i] ; i++)
6134 {
6135 if (BREAK_AFTER(i))
6136 {
6137 /* This is the one to break after. */
6138 break;
6139 }
6140 }
6141
6142 cur->pos = i;
6143
6144#ifdef HAVE_LINEBREAK
6145 free(breaks);
6146#endif
6147 return EINA_TRUE;;
6148}
6149
6150EAPI Eina_Bool
6151evas_textblock_cursor_char_next(Evas_Textblock_Cursor *cur)
6152{
6153 int ind;
6154 const Eina_Unicode *text;
6155
6156 if (!cur) return EINA_FALSE;
6157 if (!cur->node) return EINA_FALSE;
6158
6159 ind = cur->pos;
6160 text = eina_ustrbuf_string_get(cur->node->unicode);
6161 if (text[ind]) ind++;
6162 /* Only allow pointing a null if it's the last paragraph.
6163 * because we don't have a PS there. */
6164 if (text[ind])
6165 {
6166 cur->pos = ind;
6167 return EINA_TRUE;
6168 }
6169 else
6170 {
6171 if (!evas_textblock_cursor_paragraph_next(cur))
6172 {
6173 /* If we already were at the end, that means we don't have
6174 * where to go next we should return FALSE */
6175 if (cur->pos == (size_t) ind)
6176 return EINA_FALSE;
6177
6178 cur->pos = ind;
6179 return EINA_TRUE;
6180 }
6181 else
6182 {
6183 return EINA_TRUE;
6184 }
6185 }
6186}
6187
6188EAPI Eina_Bool
6189evas_textblock_cursor_char_prev(Evas_Textblock_Cursor *cur)
6190{
6191 if (!cur) return EINA_FALSE;
6192 if (!cur->node) return EINA_FALSE;
6193
6194 if (cur->pos != 0)
6195 {
6196 cur->pos--;
6197 return EINA_TRUE;
6198 }
6199 return evas_textblock_cursor_paragraph_prev(cur);
6200}
6201
6202EAPI void
6203evas_textblock_cursor_paragraph_char_first(Evas_Textblock_Cursor *cur)
6204{
6205 if (!cur) return;
6206 cur->pos = 0;
6207
6208}
6209
6210EAPI void
6211evas_textblock_cursor_paragraph_char_last(Evas_Textblock_Cursor *cur)
6212{
6213 int ind;
6214
6215 if (!cur) return;
6216 if (!cur->node) return;
6217 ind = eina_ustrbuf_length_get(cur->node->unicode);
6218 /* If it's not the last paragraph, go back one, because we want to point
6219 * to the PS, not the NULL */
6220 if (EINA_INLIST_GET(cur->node)->next)
6221 ind--;
6222
6223 if (ind >= 0)
6224 cur->pos = ind;
6225 else
6226 cur->pos = 0;
6227
6228}
6229
6230EAPI void
6231evas_textblock_cursor_line_char_first(Evas_Textblock_Cursor *cur)
6232{
6233 Evas_Object_Textblock *o;
6234 Evas_Object_Textblock_Line *ln = NULL;
6235 Evas_Object_Textblock_Item *it = NULL;
6236
6237 if (!cur) return;
6238 if (!cur->node) return;
6239 o = (Evas_Object_Textblock *)(cur->obj->object_data);
6240 if (!o->formatted.valid) _relayout(cur->obj);
6241
6242 _find_layout_item_match(cur, &ln, &it);
6243
6244 if (!ln) return;
6245 if (ln->items)
6246 {
6247 Evas_Object_Textblock_Item *i;
6248 it = ln->items;
6249 EINA_INLIST_FOREACH(ln->items, i)
6250 {
6251 if (it->text_pos > i->text_pos)
6252 {
6253 it = i;
6254 }
6255 }
6256 }
6257 if (it)
6258 {
6259 cur->pos = it->text_pos;
6260 cur->node = it->text_node;
6261 }
6262}
6263
6264EAPI void
6265evas_textblock_cursor_line_char_last(Evas_Textblock_Cursor *cur)
6266{
6267 Evas_Object_Textblock *o;
6268 Evas_Object_Textblock_Line *ln = NULL;
6269 Evas_Object_Textblock_Item *it = NULL;
6270
6271 if (!cur) return;
6272 if (!cur->node) return;
6273 o = (Evas_Object_Textblock *)(cur->obj->object_data);
6274 if (!o->formatted.valid) _relayout(cur->obj);
6275
6276 _find_layout_item_match(cur, &ln, &it);
6277
6278 if (!ln) return;
6279 if (ln->items)
6280 {
6281 Evas_Object_Textblock_Item *i;
6282 it = ln->items;
6283 EINA_INLIST_FOREACH(ln->items, i)
6284 {
6285 if (it->text_pos < i->text_pos)
6286 {
6287 it = i;
6288 }
6289 }
6290 }
6291 if (it)
6292 {
6293 size_t ind;
6294
6295 cur->node = it->text_node;
6296 cur->pos = it->text_pos;
6297 if (it->type == EVAS_TEXTBLOCK_ITEM_TEXT)
6298 {
6299 ind = _ITEM_TEXT(it)->text_props.text_len - 1;
6300 if (!IS_AT_END(_ITEM_TEXT(it), ind)) ind++;
6301 cur->pos += ind;
6302 }
6303 else if (!EINA_INLIST_GET(ln)->next && !EINA_INLIST_GET(ln->par)->next)
6304 {
6305 cur->pos++;
6306 }
6307 }
6308}
6309
6310/**
6311 * @internal
6312 * checks if a format (as a string) is visible/changes format and sets the
6313 * fnode properties accordingly.
6314 *
6315 * @param fnode the format node
6316 * @param s the string.
6317 */
6318static void
6319_evas_textblock_format_is_visible(Evas_Object_Textblock_Node_Format *fnode,
6320 const char *s)
6321{
6322 const char *item;
6323 Eina_Bool is_opener = EINA_TRUE;
6324
6325 fnode->visible = fnode->format_change = EINA_FALSE;
6326 fnode->anchor = ANCHOR_NONE;
6327 if (!s) return;
6328
6329 if (!fnode->own_closer)
6330 {
6331 is_opener = fnode->opener;
6332 fnode->format_change = EINA_TRUE;
6333 }
6334
6335 while ((item = _format_parse(&s)))
6336 {
6337 int itlen = s - item;
6338 /* We care about all of the formats even after a - except for
6339 * item which we don't care after a - because it's just a standard
6340 * closing */
6341 if ((!strncmp(item, "\n", itlen) || !strncmp(item, "\\n", itlen)) ||
6342 (!strncmp(item, "\t", itlen) || !strncmp(item, "\\t", itlen)) ||
6343 (!strncmp(item, "br", itlen) && (itlen >= 2)) ||
6344 (!strncmp(item, "tab", itlen) && (itlen >= 3)) ||
6345 (!strncmp(item, "ps", itlen) && (itlen >= 2)) ||
6346 (!strncmp(item, "item", itlen) && (itlen >= 4) && is_opener))
6347 {
6348 fnode->visible = EINA_TRUE;
6349 }
6350
6351 if (is_opener && !strncmp(item, "a", itlen))
6352 {
6353 fnode->anchor = ANCHOR_A;
6354 }
6355 else if (is_opener && !strncmp(item, "item", itlen) && (itlen >= 4))
6356 {
6357 fnode->anchor = ANCHOR_ITEM;
6358 }
6359 }
6360}
6361
6362/**
6363 * Sets the cursor to the position of where the fmt points to.
6364 *
6365 * @param cur the cursor to update.
6366 * @param fmt the format to set according to.
6367 * @return nothing.
6368 */
6369static void __UNUSED__
6370_evas_textblock_cursor_node_text_at_format(Evas_Textblock_Cursor *cur, Evas_Object_Textblock_Node_Format *fmt)
6371{
6372 Evas_Object_Textblock_Node_Text *text;
6373 Evas_Object_Textblock_Node_Format *base_format;
6374 Evas_Object_Textblock_Node_Format *itr;
6375 size_t position = 0;
6376
6377 if (!cur || !fmt) return;
6378 /* Find the main format node */
6379 text = fmt->text_node;
6380 cur->node = text;
6381 base_format = text->format_node;
6382 EINA_INLIST_FOREACH(base_format, itr)
6383 {
6384 if (itr == fmt)
6385 {
6386 break;
6387 }
6388 position += itr->offset;
6389 }
6390 cur->pos = position;
6391
6392}
6393
6394
6395/**
6396 * @internal
6397 * Remove pairs of + and - formats and also remove formats without + or -
6398 * i.e formats that pair to themselves. Only removes invisible formats
6399 * that pair themselves, if you want to remove invisible formats that pair
6400 * themselves, please first change fmt->visible to EINA_FALSE.
6401 *
6402 * @param o the textblock object.
6403 * @param fmt the current format.
6404 */
6405static void
6406_evas_textblock_node_format_remove_matching(Evas_Object_Textblock *o,
6407 Evas_Object_Textblock_Node_Format *fmt)
6408{
6409 Evas_Object_Textblock_Node_Text *tnode;
6410 Eina_List *formats = NULL;
6411 size_t offset = 0;
6412
6413 if (!fmt) return;
6414
6415 tnode = fmt->text_node;
6416
6417 do
6418 {
6419 Evas_Object_Textblock_Node_Format *nnode;
6420 const char *fstr = fmt->orig_format;
6421
6422 nnode = _NODE_FORMAT(EINA_INLIST_GET(fmt)->next);
6423 if (nnode)
6424 {
6425 offset = nnode->offset;
6426 }
6427
6428
6429 if (fmt->opener && !fmt->own_closer)
6430 {
6431 formats = eina_list_prepend(formats, fmt);
6432 }
6433 else if (fstr && !fmt->opener)
6434 {
6435 Evas_Object_Textblock_Node_Format *fnode;
6436 size_t fstr_len;
6437 fstr_len = strlen(fstr);
6438 /* Generic popper, just pop (if there's anything to pop). */
6439 if (formats && (((fstr[0] == ' ') && !fstr[1]) || !fstr[0]))
6440 {
6441 fnode = eina_list_data_get(formats);
6442 formats = eina_list_remove_list(formats, formats);
6443 _evas_textblock_node_format_remove(o, fnode, 0);
6444 _evas_textblock_node_format_remove(o, fmt, 0);
6445 }
6446 /* Find the matching format and pop it, if the matching format
6447 * is our format, i.e the last one, pop and break. */
6448 else
6449 {
6450 Eina_List *i, *next;
6451 EINA_LIST_FOREACH_SAFE(formats, i, next, fnode)
6452 {
6453 if (_FORMAT_IS_CLOSER_OF(
6454 fnode->orig_format, fstr, fstr_len))
6455 {
6456 fnode = eina_list_data_get(i);
6457 formats = eina_list_remove_list(formats, i);
6458 _evas_textblock_node_format_remove(o, fnode, 0);
6459 _evas_textblock_node_format_remove(o, fmt, 0);
6460 break;
6461 }
6462 }
6463 }
6464 }
6465 else if (!fmt->visible)
6466 {
6467 _evas_textblock_node_format_remove(o, fmt, 0);
6468 }
6469 fmt = nnode;
6470 }
6471 while (fmt && (offset == 0) && (fmt->text_node == tnode));
6472 eina_list_free(formats);
6473}
6474/**
6475 * @internal
6476 * Add the offset (may be negative) to the first node after fmt which is
6477 * pointing to the text node tnode or to o->format_nodes if fmt is null
6478 * and it points to tnode.
6479 *
6480 * @param o the textblock object.
6481 * @param tnode the text node the format should point to.
6482 * @param fmt the current format.
6483 * @param offset the offest to add (may be negative).
6484 */
6485static void
6486_evas_textblock_node_format_adjust_offset(Evas_Object_Textblock *o,
6487 Evas_Object_Textblock_Node_Text *tnode,
6488 Evas_Object_Textblock_Node_Format *fmt, int offset)
6489{
6490 if (fmt)
6491 {
6492 fmt = _NODE_FORMAT(EINA_INLIST_GET(fmt)->next);
6493 }
6494 else
6495 {
6496 fmt = o->format_nodes;
6497 }
6498 if (fmt && (tnode == fmt->text_node))
6499 {
6500 fmt->offset += offset;
6501 }
6502}
6503
6504/**
6505 * @internal
6506 * Removes a format node updating the offset of the next format node and the
6507 * text nodes pointing to this node.
6508 *
6509 * @param o the textblock object.
6510 * @param n the fromat node to remove
6511 */
6512static void
6513_evas_textblock_node_format_remove(Evas_Object_Textblock *o, Evas_Object_Textblock_Node_Format *n, int visible_adjustment)
6514{
6515 /* Update the text nodes about the change */
6516 {
6517 Evas_Object_Textblock_Node_Format *nnode;
6518 nnode = _NODE_FORMAT(EINA_INLIST_GET(n)->next);
6519 /* If there's a next node that belongs to the same text node
6520 * and the curret node was the main one, advance the format node */
6521 if (nnode && (nnode->text_node == n->text_node))
6522 {
6523 if (nnode->text_node->format_node == n)
6524 {
6525 nnode->text_node->format_node = nnode;
6526 }
6527 }
6528 else
6529 {
6530 Evas_Object_Textblock_Node_Text *tnode;
6531 /* If there's no next one update the text nodes */
6532 nnode = _NODE_FORMAT(EINA_INLIST_GET(n)->prev);
6533 tnode = n->text_node;
6534 /* Even if it's not the current text_node's main node
6535 * it can still be the next's. */
6536 if (tnode && (tnode->format_node != n))
6537 {
6538 tnode = _NODE_TEXT(EINA_INLIST_GET(tnode)->next);
6539 }
6540 while (tnode && (tnode->format_node == n))
6541 {
6542 tnode->format_node = nnode;
6543 tnode = _NODE_TEXT(EINA_INLIST_GET(tnode)->next);
6544 }
6545 }
6546 }
6547 _evas_textblock_node_format_adjust_offset(o, n->text_node, n,
6548 n->offset - visible_adjustment);
6549
6550 o->format_nodes = _NODE_FORMAT(eina_inlist_remove(
6551 EINA_INLIST_GET(o->format_nodes), EINA_INLIST_GET(n)));
6552 _evas_textblock_node_format_free(o, n);
6553}
6554
6555/**
6556 * @internal
6557 * Sets all the offsets of the format nodes between start and end in the text
6558 * node n to 0 and sets visibility to EINA_FALSE.
6559 * If end == -1 end means the end of the string.
6560 * Assumes there is a prev node or the current node will be preserved.
6561 *
6562 * @param n the text node the positinos refer to.
6563 * @param start the start of where to delete from.
6564 * @param end the end of the section to delete, if end == -1 it means the end of the string.
6565 * @returns #EINA_TRUE if removed a PS, false otherwise.
6566 */
6567static Eina_Bool
6568_evas_textblock_node_text_adjust_offsets_to_start(Evas_Object_Textblock *o,
6569 Evas_Object_Textblock_Node_Text *n, size_t start, int end)
6570{
6571 Evas_Object_Textblock_Node_Format *last_node, *itr;
6572 Evas_Object_Textblock_Node_Text *new_node;
6573 int use_end = 1;
6574 int delta = 0;
6575 int first = 1;
6576 int update_format_node;
6577 size_t pos = 0;
6578 int orig_end;
6579
6580 itr = n->format_node;
6581 if (!itr || (itr->text_node != n)) return EINA_FALSE;
6582
6583 orig_end = end;
6584 if ((end < 0) || ((size_t) end == eina_ustrbuf_length_get(n->unicode)))
6585 {
6586 use_end = 0;
6587 }
6588 else if (end > 0)
6589 {
6590 /* We don't want the last one */
6591 end--;
6592 }
6593
6594 /* If we are not removing the text node, all should stay in this text
6595 * node, otherwise, everything should move to the previous node */
6596 if ((start == 0) && !use_end)
6597 {
6598 new_node = _NODE_TEXT(EINA_INLIST_GET(n)->prev);
6599 if (!new_node)
6600 {
6601 new_node = n;
6602 }
6603 }
6604 else
6605 {
6606 new_node = n;
6607 }
6608
6609 /* Find the first node after start */
6610 while (itr && (itr->text_node == n))
6611 {
6612 pos += itr->offset;
6613 if (pos >= start)
6614 {
6615 break;
6616 }
6617 itr = _NODE_FORMAT(EINA_INLIST_GET(itr)->next);
6618 }
6619
6620 if (!itr || (itr->text_node != n))
6621 {
6622 return EINA_FALSE;
6623 }
6624
6625 update_format_node = ((itr == n->format_node) && (new_node != n));
6626 delta = orig_end - pos;
6627 itr->offset -= pos - start;
6628
6629 while (itr && (itr->text_node == n))
6630 {
6631 last_node = itr;
6632 itr = _NODE_FORMAT(EINA_INLIST_GET(itr)->next);
6633
6634 if (!first)
6635 {
6636 pos += last_node->offset;
6637 }
6638
6639 /* start is negative when this gets relevant */
6640 if (use_end && (pos > (size_t) end))
6641 {
6642 last_node->offset -= delta;
6643 break;
6644 }
6645
6646 delta = orig_end - pos;
6647 if (!first)
6648 {
6649 last_node->offset = 0;
6650 }
6651 else
6652 {
6653 first = 0;
6654 }
6655 last_node->visible = EINA_FALSE;
6656
6657 if (!itr || (itr && (itr->text_node != n)))
6658 {
6659 /* Remove the PS, and return since it's the end of the node */
6660 if (_IS_PARAGRAPH_SEPARATOR(o, last_node->format))
6661 {
6662 _evas_textblock_node_format_remove(o, last_node, 0);
6663 return EINA_TRUE;
6664 }
6665
6666 }
6667 last_node->text_node = new_node;
6668 if (update_format_node)
6669 {
6670 n->format_node = last_node;
6671 }
6672 }
6673
6674 return EINA_FALSE;
6675}
6676
6677/**
6678 * @internal
6679 * Removes all the format nodes between start and end in the text node n.
6680 * This function updates the offset of the next format node and the
6681 * text nodes pointing to it. if end == -1 end means the end of the string.
6682 *
6683 * @param o the textblock object.
6684 * @param n the text node the positinos refer to.
6685 * @param start the start of where to delete from.
6686 * @param end the end of the section to delete, if end == -1 it means the end of the string.
6687 */
6688static void
6689_evas_textblock_node_text_remove_formats_between(Evas_Object_Textblock *o,
6690 Evas_Object_Textblock_Node_Text *n, int start, int end)
6691{
6692 Evas_Object_Textblock_Node_Format *itr;
6693 int use_end = 1;
6694 int offset = end - start;
6695 itr = n->format_node;
6696
6697 if (itr)
6698 start -= itr->offset;
6699 if (offset < 0) offset = 0;
6700 if (end < 0) use_end = 0;
6701 while (itr && (itr->text_node == n))
6702 {
6703 Evas_Object_Textblock_Node_Format *nnode;
6704 int tmp_offset = 0;
6705
6706 /* start is negative when this gets relevant */
6707 if ((offset + start < 0) && use_end)
6708 {
6709 break;
6710 }
6711 nnode = _NODE_FORMAT(EINA_INLIST_GET(itr)->next);
6712 if (nnode)
6713 {
6714 tmp_offset = nnode->offset;
6715 }
6716 if (start <= 0)
6717 {
6718 /* Don't do visible adjustments because we are removing the visual
6719 * chars anyway and taking those into account */
6720 _evas_textblock_node_format_remove(o, itr, 0);
6721 }
6722 start -= tmp_offset;
6723 itr = nnode;
6724 }
6725}
6726
6727/**
6728 * @internal
6729 * Returns the first format in the range between start and end in the textblock
6730 * n.
6731 *
6732 * @param o the textblock object.
6733 * @param n the text node the positinos refer to.
6734 * @param start the start of where to delete from.
6735 * @param end the end of the section to delete, if end == -1 it means the end of the string.
6736 */
6737static Evas_Object_Textblock_Node_Format *
6738_evas_textblock_node_text_get_first_format_between(
6739 Evas_Object_Textblock_Node_Text *n, int start, int end)
6740{
6741 Evas_Object_Textblock_Node_Format *itr;
6742 int use_end = 1;
6743 itr = n->format_node;
6744 if (end < 0) use_end = 0;
6745 while (itr && (itr->text_node == n))
6746 {
6747 start -= itr->offset;
6748 end -= itr->offset;
6749 if ((end <= 0) && use_end)
6750 {
6751 break;
6752 }
6753 if (start <= 0)
6754 {
6755 return itr;
6756 }
6757 itr = _NODE_FORMAT(EINA_INLIST_GET(itr)->next);
6758 }
6759 return NULL;
6760}
6761
6762/**
6763 * Removes a text node and the corresponding format nodes.
6764 *
6765 * @param o the textblock objec.t
6766 * @param n the node to remove.
6767 */
6768static void
6769_evas_textblock_node_text_remove(Evas_Object_Textblock *o, Evas_Object_Textblock_Node_Text *n)
6770{
6771 _evas_textblock_node_text_adjust_offsets_to_start(o, n, 0, -1);
6772
6773 o->text_nodes = _NODE_TEXT(eina_inlist_remove(
6774 EINA_INLIST_GET(o->text_nodes), EINA_INLIST_GET(n)));
6775 _evas_textblock_node_text_free(n);
6776}
6777
6778/**
6779 * @internal
6780 * Return the position where the formats starts at.
6781 *
6782 * @param fmt the format to return the position of.
6783 * @return the position of the format in the text node it points to.
6784 */
6785static size_t
6786_evas_textblock_node_format_pos_get(const Evas_Object_Textblock_Node_Format *fmt)
6787{
6788 Evas_Object_Textblock_Node_Text *text;
6789 Evas_Object_Textblock_Node_Format *base_format;
6790 Evas_Object_Textblock_Node_Format *itr;
6791 size_t position = 0;
6792
6793 if (!fmt) return 0;
6794 /* Find the main format node */
6795 text = fmt->text_node;
6796 base_format = text->format_node;
6797 EINA_INLIST_FOREACH(base_format, itr)
6798 {
6799 if (itr == fmt)
6800 {
6801 break;
6802 }
6803 position += itr->offset;
6804 }
6805 return position + fmt->offset;
6806}
6807
6808EAPI int
6809evas_textblock_cursor_pos_get(const Evas_Textblock_Cursor *cur)
6810{
6811 Evas_Object_Textblock *o;
6812 Evas_Object_Textblock_Node_Text *n;
6813 size_t npos = 0;
6814
6815 if (!cur) return -1;
6816 if (!cur->node) return 0;
6817 o = (Evas_Object_Textblock *)(cur->obj->object_data);
6818 n = o->text_nodes;
6819 while (n != cur->node)
6820 {
6821 npos += eina_ustrbuf_length_get(n->unicode);
6822 n = _NODE_TEXT(EINA_INLIST_GET(n)->next);
6823 }
6824 return npos + cur->pos;
6825}
6826
6827EAPI void
6828evas_textblock_cursor_pos_set(Evas_Textblock_Cursor *cur, int _pos)
6829{
6830 Evas_Object_Textblock *o;
6831 Evas_Object_Textblock_Node_Text *n;
6832 size_t pos;
6833
6834 if (!cur) return;
6835 o = (Evas_Object_Textblock *)(cur->obj->object_data);
6836
6837 if (_pos < 0)
6838 {
6839 pos = 0;
6840 }
6841 else
6842 {
6843 pos = (size_t) _pos;
6844 }
6845
6846 n = o->text_nodes;
6847 while (n && (pos >= eina_ustrbuf_length_get(n->unicode)))
6848 {
6849 pos -= eina_ustrbuf_length_get(n->unicode);
6850 n = _NODE_TEXT(EINA_INLIST_GET(n)->next);
6851 }
6852
6853 if (n)
6854 {
6855 cur->node = n;
6856 cur->pos = pos;
6857 }
6858 else if (o->text_nodes)
6859 {
6860 /* In case we went pass the last node, we need to put the cursor
6861 * at the absolute end. */
6862 Evas_Object_Textblock_Node_Text *last_n;
6863
6864 last_n = _NODE_TEXT(EINA_INLIST_GET(o->text_nodes)->last);
6865 pos = eina_ustrbuf_length_get(last_n->unicode);
6866
6867 cur->node = last_n;
6868 cur->pos = pos;
6869 }
6870
6871}
6872
6873EAPI Eina_Bool
6874evas_textblock_cursor_line_set(Evas_Textblock_Cursor *cur, int line)
6875{
6876 Evas_Object_Textblock *o;
6877 Evas_Object_Textblock_Line *ln;
6878 Evas_Object_Textblock_Item *it;
6879
6880 if (!cur) return EINA_FALSE;
6881 o = (Evas_Object_Textblock *)(cur->obj->object_data);
6882 if (!o->formatted.valid) _relayout(cur->obj);
6883
6884 ln = _find_layout_line_num(cur->obj, line);
6885 if (!ln) return EINA_FALSE;
6886 it = (Evas_Object_Textblock_Item *)ln->items;
6887 if (it)
6888 {
6889 cur->pos = it->text_pos;
6890 cur->node = it->text_node;
6891 }
6892 else
6893 {
6894 cur->pos = 0;
6895
6896 cur->node = o->text_nodes;
6897 }
6898 return EINA_TRUE;
6899}
6900
6901EAPI int
6902evas_textblock_cursor_compare(const Evas_Textblock_Cursor *cur1, const Evas_Textblock_Cursor *cur2)
6903{
6904 Eina_Inlist *l1, *l2;
6905
6906 if (!cur1) return 0;
6907 if (!cur2) return 0;
6908 if (cur1->obj != cur2->obj) return 0;
6909 if ((!cur1->node) || (!cur2->node)) return 0;
6910 if (cur1->node == cur2->node)
6911 {
6912 if (cur1->pos < cur2->pos) return -1; /* cur1 < cur2 */
6913 else if (cur1->pos > cur2->pos) return 1; /* cur2 < cur1 */
6914 return 0;
6915 }
6916 for (l1 = EINA_INLIST_GET(cur1->node),
6917 l2 = EINA_INLIST_GET(cur1->node); (l1) || (l2);)
6918 {
6919 if (l1 == EINA_INLIST_GET(cur2->node)) return 1; /* cur2 < cur 1 */
6920 else if (l2 == EINA_INLIST_GET(cur2->node)) return -1; /* cur1 < cur 2 */
6921 else if (!l1) return -1; /* cur1 < cur 2 */
6922 else if (!l2) return 1; /* cur2 < cur 1 */
6923 l1 = l1->prev;
6924 l2 = l2->next;
6925 }
6926 return 0;
6927}
6928
6929EAPI void
6930evas_textblock_cursor_copy(const Evas_Textblock_Cursor *cur, Evas_Textblock_Cursor *cur_dest)
6931{
6932 if (!cur) return;
6933 if (!cur_dest) return;
6934 if (cur->obj != cur_dest->obj) return;
6935 cur_dest->pos = cur->pos;
6936 cur_dest->node = cur->node;
6937
6938}
6939
6940
6941/* text controls */
6942/**
6943 * @internal
6944 * Free a text node. Shouldn't be used usually, it's better to use
6945 * @ref _evas_textblock_node_text_remove for most cases .
6946 *
6947 * @param n the text node to free
6948 * @see _evas_textblock_node_text_remove
6949 */
6950static void
6951_evas_textblock_node_text_free(Evas_Object_Textblock_Node_Text *n)
6952{
6953 if (!n) return;
6954 eina_ustrbuf_free(n->unicode);
6955 if (n->utf8)
6956 free(n->utf8);
6957 if (n->par)
6958 n->par->text_node = NULL;
6959 free(n);
6960}
6961
6962/**
6963 * @internal
6964 * Create a new text node
6965 *
6966 * @return the new text node.
6967 */
6968static Evas_Object_Textblock_Node_Text *
6969_evas_textblock_node_text_new(void)
6970{
6971 Evas_Object_Textblock_Node_Text *n;
6972
6973 n = calloc(1, sizeof(Evas_Object_Textblock_Node_Text));
6974 n->unicode = eina_ustrbuf_new();
6975 /* We want to layout each paragraph at least once. */
6976 n->dirty = EINA_TRUE;
6977 n->is_new = EINA_TRUE;
6978
6979 return n;
6980}
6981
6982/**
6983 * @internal
6984 * Break a paragraph. This does not add a PS but only splits the paragraph
6985 * where a ps was just added!
6986 *
6987 * @param cur the cursor to break at.
6988 * @param fnode the format node of the PS just added.
6989 * @return Returns no value.
6990 */
6991static void
6992_evas_textblock_cursor_break_paragraph(Evas_Textblock_Cursor *cur,
6993 Evas_Object_Textblock_Node_Format *fnode)
6994{
6995 Evas_Object_Textblock *o;
6996 Evas_Object_Textblock_Node_Text *n;
6997
6998 if (!cur) return;
6999 o = (Evas_Object_Textblock *)(cur->obj->object_data);
7000
7001 n = _evas_textblock_node_text_new();
7002 o->text_nodes = _NODE_TEXT(eina_inlist_append_relative(
7003 EINA_INLIST_GET(o->text_nodes),
7004 EINA_INLIST_GET(n),
7005 EINA_INLIST_GET(cur->node)));
7006 /* Handle text and format changes. */
7007 if (cur->node)
7008 {
7009 Evas_Object_Textblock_Node_Format *nnode;
7010 size_t len, start;
7011 const Eina_Unicode *text;
7012
7013 /* If there was a format node in the delete range,
7014 * make it our format and update the text_node fields,
7015 * otherwise, use the paragraph separator
7016 * of the previous paragraph. */
7017 nnode = _NODE_FORMAT(EINA_INLIST_GET(fnode)->next);
7018 if (nnode && (nnode->text_node == cur->node))
7019 {
7020 n->format_node = nnode;
7021 nnode->offset--; /* We don't have to take the replacement char
7022 into account anymore */
7023 while (nnode && (nnode->text_node == cur->node))
7024 {
7025 nnode->text_node = n;
7026 nnode = _NODE_FORMAT(EINA_INLIST_GET(nnode)->next);
7027 }
7028 }
7029 else
7030 {
7031 n->format_node = fnode;
7032 }
7033
7034 /* cur->pos now points to the PS, move after. */
7035 start = cur->pos + 1;
7036 len = eina_ustrbuf_length_get(cur->node->unicode) - start;
7037 if (len > 0)
7038 {
7039 text = eina_ustrbuf_string_get(cur->node->unicode);
7040 eina_ustrbuf_append_length(n->unicode, text + start, len);
7041 eina_ustrbuf_remove(cur->node->unicode, start, start + len);
7042 cur->node->dirty = EINA_TRUE;
7043 }
7044 }
7045 else
7046 {
7047 fnode = o->format_nodes;
7048 if (fnode)
7049 {
7050 fnode = _NODE_FORMAT(EINA_INLIST_GET(fnode)->last);
7051 }
7052 n->format_node = fnode;
7053 }
7054}
7055
7056/**
7057 * @internal
7058 * Set the node and offset of all the curs after cur.
7059 *
7060 * @param cur the cursor.
7061 * @param n the current textblock node.
7062 * @param new_node the new node to set.
7063 */
7064static void
7065_evas_textblock_cursors_set_node(Evas_Object_Textblock *o,
7066 const Evas_Object_Textblock_Node_Text *n,
7067 Evas_Object_Textblock_Node_Text *new_node)
7068{
7069 Eina_List *l;
7070 Evas_Textblock_Cursor *data;
7071
7072 if (n == o->cursor->node)
7073 {
7074 o->cursor->pos = 0;
7075 o->cursor->node = new_node;
7076 }
7077 EINA_LIST_FOREACH(o->cursors, l, data)
7078 {
7079 if (n == data->node)
7080 {
7081 data->pos = 0;
7082 data->node = new_node;
7083 }
7084 }
7085}
7086
7087/**
7088 * @internal
7089 * Update the offset of all the cursors after cur.
7090 *
7091 * @param cur the cursor.
7092 * @param n the current textblock node.
7093 * @param start the starting pos.
7094 * @param offset how much to adjust (can be negative).
7095 */
7096static void
7097_evas_textblock_cursors_update_offset(const Evas_Textblock_Cursor *cur,
7098 const Evas_Object_Textblock_Node_Text *n,
7099 size_t start, int offset)
7100{
7101 Eina_List *l;
7102 Evas_Textblock_Cursor *data;
7103 Evas_Object_Textblock *o;
7104 o = (Evas_Object_Textblock *)(cur->obj->object_data);
7105
7106 if (cur != o->cursor)
7107 {
7108 if ((n == o->cursor->node) &&
7109 (o->cursor->pos > start))
7110 {
7111 if ((offset < 0) && (o->cursor->pos <= (size_t) (-1 * offset)))
7112 {
7113 o->cursor->pos = 0;
7114 }
7115 else
7116 {
7117 o->cursor->pos += offset;
7118 }
7119 }
7120 }
7121 EINA_LIST_FOREACH(o->cursors, l, data)
7122 {
7123 if (data != cur)
7124 {
7125 if ((n == data->node) &&
7126 (data->pos > start))
7127 {
7128 if ((offset < 0) && (data->pos <= (size_t) (-1 * offset)))
7129 {
7130 data->pos = 0;
7131 }
7132 else
7133 {
7134 data->pos += offset;
7135 }
7136 }
7137 else if (!data->node)
7138 {
7139 data->node = o->text_nodes;
7140 data->pos = 0;
7141 }
7142 }
7143 }
7144}
7145
7146/**
7147 * @internal
7148 * Mark that the textblock has changed.
7149 *
7150 * @param o the textblock object.
7151 * @param obj the evas object.
7152 */
7153static void
7154_evas_textblock_changed(Evas_Object_Textblock *o, Evas_Object *obj)
7155{
7156 o->formatted.valid = 0;
7157 o->native.valid = 0;
7158 o->content_changed = 1;
7159 if (o->markup_text)
7160 {
7161 free(o->markup_text);
7162 o->markup_text = NULL;
7163 }
7164
7165 evas_object_change(obj);
7166}
7167
7168static void
7169_evas_textblock_invalidate_all(Evas_Object_Textblock *o)
7170{
7171 Evas_Object_Textblock_Node_Text *n;
7172
7173 EINA_INLIST_FOREACH(o->text_nodes, n)
7174 {
7175 n->dirty = EINA_TRUE;
7176 }
7177}
7178
7179EAPI int
7180evas_textblock_cursor_text_append(Evas_Textblock_Cursor *cur, const char *_text)
7181{
7182 Evas_Object_Textblock *o;
7183 Evas_Object_Textblock_Node_Text *n;
7184 Evas_Object_Textblock_Node_Format *fnode = NULL;
7185 Eina_Unicode *text;
7186 int len = 0;
7187
7188 if (!cur) return 0;
7189 text = eina_unicode_utf8_to_unicode(_text, &len);
7190 o = (Evas_Object_Textblock *)(cur->obj->object_data);
7191
7192 n = cur->node;
7193 if (n)
7194 {
7195 Evas_Object_Textblock_Node_Format *nnode;
7196 fnode = _evas_textblock_cursor_node_format_before_or_at_pos_get(cur);
7197 fnode = _evas_textblock_node_format_last_at_off(fnode);
7198 /* find the node after the current in the same paragraph
7199 * either we find one and then take the next, or we try to get
7200 * the first for the paragraph which must be after our position */
7201 if (fnode)
7202 {
7203 if (!evas_textblock_cursor_format_is_visible_get(cur))
7204 {
7205 nnode = _NODE_FORMAT(EINA_INLIST_GET(fnode)->next);
7206 if (nnode && (nnode->text_node == n))
7207 {
7208 fnode = nnode;
7209 }
7210 else
7211 {
7212 fnode = NULL;
7213 }
7214 }
7215 }
7216 else
7217 {
7218 fnode = n->format_node;
7219 }
7220 }
7221 else if (o->text_nodes)
7222 {
7223 n = cur->node = o->text_nodes;
7224 cur->pos = 0;
7225 }
7226 else
7227 {
7228 n = _evas_textblock_node_text_new();
7229 o->text_nodes = _NODE_TEXT(eina_inlist_append(
7230 EINA_INLIST_GET(o->text_nodes),
7231 EINA_INLIST_GET(n)));
7232 cur->node = n;
7233 }
7234
7235 eina_ustrbuf_insert_length(n->unicode, text, len, cur->pos);
7236 /* Advance the formats */
7237 if (fnode && (fnode->text_node == cur->node))
7238 fnode->offset += len;
7239
7240 /* Update all the cursors after our position. */
7241 _evas_textblock_cursors_update_offset(cur, cur->node, cur->pos, len);
7242
7243 _evas_textblock_changed(o, cur->obj);
7244 n->dirty = EINA_TRUE;
7245 free(text);
7246
7247 if (!o->cursor->node)
7248 o->cursor->node = o->text_nodes;
7249 return len;
7250}
7251
7252EAPI int
7253evas_textblock_cursor_text_prepend(Evas_Textblock_Cursor *cur, const char *_text)
7254{
7255 int len;
7256 /*append is essentially prepend without advancing */
7257 len = evas_textblock_cursor_text_append(cur, _text);
7258 cur->pos += len; /*Advance */
7259 return len;
7260}
7261
7262/**
7263 * @internal
7264 * Free a format node
7265 *
7266 * @param o the textblock object
7267 * @param n the format node to free
7268 */
7269static void
7270_evas_textblock_node_format_free(Evas_Object_Textblock *o,
7271 Evas_Object_Textblock_Node_Format *n)
7272{
7273 if (!n) return;
7274 eina_stringshare_del(n->format);
7275 eina_stringshare_del(n->orig_format);
7276 if (n->anchor == ANCHOR_ITEM)
7277 o->anchors_item = eina_list_remove(o->anchors_item, n);
7278 else if (n->anchor == ANCHOR_A)
7279 o->anchors_a = eina_list_remove(o->anchors_a, n);
7280 free(n);
7281}
7282
7283/**
7284 * @internal
7285 * Create a new format node.
7286 *
7287 * @param format the text to create the format node from.
7288 * @param o the textblock object.
7289 * @return Returns the new format node
7290 */
7291static Evas_Object_Textblock_Node_Format *
7292_evas_textblock_node_format_new(Evas_Object_Textblock *o, const char *_format)
7293{
7294 Evas_Object_Textblock_Node_Format *n;
7295 const char *format = _format;
7296 const char *pre_stripped_format = NULL;
7297
7298 n = calloc(1, sizeof(Evas_Object_Textblock_Node_Format));
7299 /* Create orig_format and format */
7300 if (format[0] == '<')
7301 {
7302 const char *match;
7303 size_t format_len;
7304 size_t replace_len;
7305
7306 format++; /* Advance after '<' */
7307 format_len = strlen(format);
7308 if ((format_len > 0) && format[format_len - 1] == '>')
7309 {
7310 format_len--; /* We don't care about '>' */
7311 /* Check if it closes itself. Skip the </> case. */
7312 if ((format_len > 1) && format[format_len - 1] == '/')
7313 {
7314 format_len--; /* We don't care about '/' */
7315 n->own_closer = EINA_TRUE;
7316 }
7317 }
7318
7319 if (!o->style_user || !(match = _style_match_tag(o->style_user, format,
7320 format_len, &replace_len)))
7321 {
7322 match = _style_match_tag(o->style, format, format_len,
7323 &replace_len);
7324 }
7325
7326 if (match)
7327 {
7328 if (match[0] != '-')
7329 {
7330 n->opener = EINA_TRUE;
7331 if (match[0] != '+')
7332 {
7333 n->own_closer = EINA_TRUE;
7334 }
7335 }
7336
7337 pre_stripped_format = match;
7338 }
7339 else
7340 {
7341 if (format[0] == '/')
7342 {
7343 format++;
7344 format_len--;
7345 }
7346 else
7347 {
7348 n->opener = EINA_TRUE;
7349 }
7350 }
7351
7352 n->orig_format = eina_stringshare_add_length(format, format_len);
7353
7354 if (!pre_stripped_format)
7355 pre_stripped_format = n->orig_format;
7356 }
7357 /* Just use as is, it's a special format. */
7358 else
7359 {
7360 const char *tmp = format;
7361 if (format[0] != '-')
7362 {
7363 n->opener = EINA_TRUE;
7364 if (format[0] != '+')
7365 {
7366 n->own_closer = EINA_TRUE;
7367 }
7368 }
7369 if ((*tmp == '+') || (*tmp == '-'))
7370 {
7371 tmp++;
7372 while (*tmp == ' ') tmp++;
7373 }
7374 n->orig_format = eina_stringshare_add(tmp);
7375 pre_stripped_format = n->orig_format;
7376 }
7377
7378 /* Strip format */
7379 {
7380 const char *tmp = pre_stripped_format;
7381 if ((*tmp == '+') || (*tmp == '-'))
7382 {
7383 tmp++;
7384 while (*tmp == ' ') tmp++;
7385 }
7386 n->format = eina_stringshare_add(tmp);
7387 }
7388 format = n->format;
7389
7390 _evas_textblock_format_is_visible(n, format);
7391 if (n->anchor == ANCHOR_A)
7392 {
7393 o->anchors_a = eina_list_append(o->anchors_a, n);
7394 }
7395 else if (n->anchor == ANCHOR_ITEM)
7396 {
7397 o->anchors_item = eina_list_append(o->anchors_item, n);
7398 }
7399 n->is_new = EINA_TRUE;
7400
7401 return n;
7402}
7403
7404static Eina_Bool
7405_evas_textblock_cursor_is_at_the_end(const Evas_Textblock_Cursor *cur)
7406{
7407 const Eina_Unicode *text;
7408
7409 if (!cur) return EINA_FALSE;
7410 if (!cur->node) return EINA_FALSE;
7411 text = eina_ustrbuf_string_get(cur->node->unicode);
7412 return ((text[cur->pos] == 0) && (!EINA_INLIST_GET(cur->node)->next)) ?
7413 EINA_TRUE : EINA_FALSE;
7414}
7415
7416EAPI Eina_Bool
7417evas_textblock_cursor_format_append(Evas_Textblock_Cursor *cur, const char *format)
7418{
7419 Evas_Object_Textblock *o;
7420 Evas_Object_Textblock_Node_Format *n;
7421 Eina_Bool is_visible;
7422
7423 if (!cur) return EINA_FALSE;
7424 if ((!format) || (format[0] == 0)) return EINA_FALSE;
7425 o = (Evas_Object_Textblock *)(cur->obj->object_data);
7426 /* We should always have at least one text node */
7427 if (!o->text_nodes)
7428 {
7429 evas_textblock_cursor_text_prepend(cur, "");
7430 }
7431
7432 n = _evas_textblock_node_format_new(o, format);
7433 is_visible = n->visible;
7434 format = n->format;
7435 if (!cur->node)
7436 {
7437 o->format_nodes = _NODE_FORMAT(eina_inlist_append(
7438 EINA_INLIST_GET(o->format_nodes),
7439 EINA_INLIST_GET(n)));
7440 cur->pos = 0;
7441 n->text_node = (EINA_INLIST_GET(n)->prev) ?
7442 _NODE_FORMAT(EINA_INLIST_GET(n)->prev)->text_node :
7443 o->text_nodes;
7444 cur->node = n->text_node;
7445 }
7446 else
7447 {
7448 Evas_Object_Textblock_Node_Format *fmt;
7449 fmt = _evas_textblock_cursor_node_format_before_or_at_pos_get(cur);
7450 n->text_node = cur->node;
7451 if (!fmt)
7452 {
7453 o->format_nodes = _NODE_FORMAT(eina_inlist_prepend(
7454 EINA_INLIST_GET(o->format_nodes),
7455 EINA_INLIST_GET(n)));
7456 n->offset = cur->pos;
7457 }
7458 else
7459 {
7460 if (evas_textblock_cursor_format_is_visible_get(cur))
7461 {
7462 o->format_nodes = _NODE_FORMAT(eina_inlist_prepend_relative(
7463 EINA_INLIST_GET(o->format_nodes),
7464 EINA_INLIST_GET(n),
7465 EINA_INLIST_GET(fmt)
7466 ));
7467 n->offset = fmt->offset;
7468 if (fmt->text_node->format_node == fmt)
7469 {
7470 fmt->text_node->format_node = n;
7471 }
7472 }
7473 else
7474 {
7475 fmt = _evas_textblock_node_format_last_at_off(fmt);
7476 o->format_nodes = _NODE_FORMAT(eina_inlist_append_relative(
7477 EINA_INLIST_GET(o->format_nodes),
7478 EINA_INLIST_GET(n),
7479 EINA_INLIST_GET(fmt)
7480 ));
7481 if (fmt->text_node != cur->node)
7482 {
7483 n->offset = cur->pos;
7484 }
7485 else
7486 {
7487 n->offset = cur->pos -
7488 _evas_textblock_node_format_pos_get(fmt);
7489 }
7490 }
7491 }
7492 /* Adjust differently if we insert a format char */
7493 if (is_visible)
7494 {
7495 _evas_textblock_node_format_adjust_offset(o, cur->node, n,
7496 -(n->offset - 1));
7497 }
7498 else
7499 {
7500 _evas_textblock_node_format_adjust_offset(o, cur->node, n,
7501 -n->offset);
7502 }
7503
7504 if (!fmt || (fmt->text_node != cur->node))
7505 {
7506 cur->node->format_node = n;
7507 }
7508 }
7509 if (is_visible && cur->node)
7510 {
7511 Eina_Unicode insert_char;
7512 /* Insert a visual representation according to the type of the
7513 format */
7514 if (_IS_PARAGRAPH_SEPARATOR(o, format))
7515 insert_char = _PARAGRAPH_SEPARATOR;
7516 else if (_IS_LINE_SEPARATOR(format))
7517 insert_char = _NEWLINE;
7518 else if (_IS_TAB(format))
7519 insert_char = _TAB;
7520 else
7521 insert_char = _REPLACEMENT_CHAR;
7522
7523 eina_ustrbuf_insert_char(cur->node->unicode, insert_char, cur->pos);
7524
7525 /* Advance all the cursors after our cursor */
7526 _evas_textblock_cursors_update_offset(cur, cur->node, cur->pos, 1);
7527 if (_IS_PARAGRAPH_SEPARATOR(o, format))
7528 {
7529 _evas_textblock_cursor_break_paragraph(cur, n);
7530 }
7531 else
7532 {
7533 /* Handle visible format nodes here */
7534 cur->node->dirty = EINA_TRUE;
7535 n->is_new = EINA_FALSE;
7536 }
7537 }
7538 else
7539 {
7540 o->format_changed = EINA_TRUE;
7541 }
7542
7543 _evas_textblock_changed(o, cur->obj);
7544
7545 if (!o->cursor->node)
7546 o->cursor->node = o->text_nodes;
7547 return is_visible;
7548}
7549
7550EAPI Eina_Bool
7551evas_textblock_cursor_format_prepend(Evas_Textblock_Cursor *cur, const char *format)
7552{
7553 Eina_Bool is_visible;
7554 /* append is essentially prepend without advancing */
7555 is_visible = evas_textblock_cursor_format_append(cur, format);
7556 if (is_visible)
7557 {
7558 /* Advance after the replacement char */
7559 evas_textblock_cursor_char_next(cur);
7560 }
7561
7562 return is_visible;
7563}
7564
7565
7566EAPI void
7567evas_textblock_cursor_char_delete(Evas_Textblock_Cursor *cur)
7568{
7569 Evas_Object_Textblock *o;
7570 Evas_Object_Textblock_Node_Text *n, *n2;
7571 const Eina_Unicode *text;
7572 int chr, ind, ppos;
7573
7574 if (!cur || !cur->node) return;
7575 o = (Evas_Object_Textblock *)(cur->obj->object_data);
7576 n = cur->node;
7577
7578 text = eina_ustrbuf_string_get(n->unicode);
7579 ind = cur->pos;
7580 if (text[ind])
7581 chr = text[ind++];
7582 else
7583 chr = 0;
7584
7585 if (chr == 0) return;
7586 ppos = cur->pos;
7587 eina_ustrbuf_remove(n->unicode, cur->pos, ind);
7588 /* Remove a format node if needed, and remove the char only if the
7589 * fmt node is not visible */
7590 {
7591 Eina_Bool should_merge = EINA_FALSE;
7592 Evas_Object_Textblock_Node_Format *fmt, *fmt2;
7593 fmt = _evas_textblock_cursor_node_format_at_pos_get(cur);
7594 if (fmt)
7595 {
7596 const char *format = NULL;
7597 Evas_Object_Textblock_Node_Format *last_fmt;
7598 /* If there's a PS it must be the last become it delimits paragraphs */
7599 last_fmt = _evas_textblock_node_format_last_at_off(fmt);
7600 format = last_fmt->format;
7601 if (format && _IS_PARAGRAPH_SEPARATOR(o, format))
7602 {
7603 /* If it was a paragraph separator, we should merge the
7604 * current with the next, there must be a next. */
7605 should_merge = EINA_TRUE;
7606 }
7607 /* If a singnular, mark as invisible, so we'll delete it. */
7608 if (!format || last_fmt->own_closer)
7609 {
7610 last_fmt->visible = EINA_FALSE;
7611 }
7612 }
7613
7614 fmt2 = _evas_textblock_cursor_node_format_before_or_at_pos_get(cur);
7615 fmt2 = _evas_textblock_node_format_last_at_off(fmt2);
7616 _evas_textblock_node_format_adjust_offset(o, cur->node, fmt2,
7617 -(ind - cur->pos));
7618
7619 if (should_merge)
7620 {
7621 _evas_textblock_cursor_nodes_merge(cur);
7622 }
7623
7624 _evas_textblock_node_format_remove_matching(o, fmt);
7625 }
7626
7627 if (cur->pos == eina_ustrbuf_length_get(n->unicode))
7628 {
7629 n2 = _NODE_TEXT(EINA_INLIST_GET(n)->next);
7630 if (n2)
7631 {
7632 cur->node = n2;
7633 cur->pos = 0;
7634 }
7635 }
7636
7637 _evas_textblock_cursors_update_offset(cur, n, ppos, -(ind - ppos));
7638 _evas_textblock_changed(o, cur->obj);
7639 cur->node->dirty = EINA_TRUE;
7640}
7641
7642EAPI void
7643evas_textblock_cursor_range_delete(Evas_Textblock_Cursor *cur1, Evas_Textblock_Cursor *cur2)
7644{
7645 Evas_Object_Textblock_Node_Format *fnode = NULL;
7646 Evas_Object_Textblock *o;
7647 Evas_Object_Textblock_Node_Text *n1, *n2;
7648 Eina_Bool should_merge = EINA_FALSE, reset_cursor = EINA_FALSE;
7649
7650 if (!cur1 || !cur1->node) return;
7651 if (!cur2 || !cur2->node) return;
7652 if (cur1->obj != cur2->obj) return;
7653 o = (Evas_Object_Textblock *)(cur1->obj->object_data);
7654 if (evas_textblock_cursor_compare(cur1, cur2) > 0)
7655 {
7656 Evas_Textblock_Cursor *tc;
7657
7658 tc = cur1;
7659 cur1 = cur2;
7660 cur2 = tc;
7661 }
7662 n1 = cur1->node;
7663 n2 = cur2->node;
7664 if ((evas_textblock_cursor_compare(o->cursor, cur1) >= 0) &&
7665 (evas_textblock_cursor_compare(cur2, o->cursor) >= 0))
7666 {
7667 reset_cursor = EINA_TRUE;
7668 }
7669
7670
7671 if (n1 == n2)
7672 {
7673 if ((cur1->pos == 0) &&
7674 (cur2->pos == eina_ustrbuf_length_get(n1->unicode)))
7675 {
7676 _evas_textblock_node_text_remove_formats_between(o, n1, 0, -1);
7677 }
7678 else
7679 {
7680 should_merge = _evas_textblock_node_text_adjust_offsets_to_start(o,
7681 n1, cur1->pos, cur2->pos);
7682 }
7683 eina_ustrbuf_remove(n1->unicode, cur1->pos, cur2->pos);
7684 _evas_textblock_cursors_update_offset(cur1, cur1->node, cur1->pos, - (cur2->pos - cur1->pos));
7685 }
7686 else
7687 {
7688 Evas_Object_Textblock_Node_Text *n;
7689 int len;
7690 _evas_textblock_node_text_adjust_offsets_to_start(o, n1, cur1->pos, -1);
7691 n = _NODE_TEXT(EINA_INLIST_GET(n1)->next);
7692 /* Remove all the text nodes between */
7693 while (n && (n != n2))
7694 {
7695 Evas_Object_Textblock_Node_Text *nnode;
7696
7697 nnode = _NODE_TEXT(EINA_INLIST_GET(n)->next);
7698 _evas_textblock_cursors_set_node(o, n, n1);
7699 _evas_textblock_node_text_remove(o, n);
7700 n = nnode;
7701 }
7702 should_merge = _evas_textblock_node_text_adjust_offsets_to_start(o, n2,
7703 0, cur2->pos);
7704
7705 /* Remove the formats and the strings in the first and last nodes */
7706 len = eina_ustrbuf_length_get(n1->unicode);
7707 eina_ustrbuf_remove(n1->unicode, cur1->pos, len);
7708 eina_ustrbuf_remove(n2->unicode, 0, cur2->pos);
7709 /* Merge the nodes because we removed the PS */
7710 _evas_textblock_cursors_update_offset(cur1, cur1->node, cur1->pos,
7711 - cur1->pos);
7712 _evas_textblock_cursors_update_offset(cur2, cur2->node, 0, - cur2->pos);
7713 _evas_textblock_nodes_merge(o, n1);
7714 }
7715 fnode = _evas_textblock_cursor_node_format_at_pos_get(cur1);
7716
7717 n1->dirty = n2->dirty = EINA_TRUE;
7718 if (should_merge)
7719 {
7720 /* We call this function instead of the cursor one because we already
7721 * updated the cursors */
7722 _evas_textblock_nodes_merge(o, n1);
7723 }
7724 _evas_textblock_node_format_remove_matching(o, fnode);
7725
7726 evas_textblock_cursor_copy(cur1, cur2);
7727 if (reset_cursor)
7728 evas_textblock_cursor_copy(cur1, o->cursor);
7729
7730 _evas_textblock_changed(o, cur1->obj);
7731}
7732
7733
7734EAPI char *
7735evas_textblock_cursor_content_get(const Evas_Textblock_Cursor *cur)
7736{
7737 if (!cur || !cur->node) return NULL;
7738 if (evas_textblock_cursor_format_is_visible_get(cur))
7739 {
7740 Eina_Strbuf *buf;
7741 Evas_Object_Textblock_Node_Format *fnode;
7742 char *ret;
7743 fnode = _evas_textblock_node_visible_at_pos_get(
7744 evas_textblock_cursor_format_get(cur));
7745
7746 buf = eina_strbuf_new();
7747 _markup_get_format_append(buf, fnode);
7748 ret = eina_strbuf_string_steal(buf);
7749 eina_strbuf_free(buf);
7750
7751 return ret;
7752 }
7753 else
7754 {
7755 const Eina_Unicode *ustr;
7756 Eina_Unicode buf[2];
7757 char *s;
7758
7759 ustr = eina_ustrbuf_string_get(cur->node->unicode);
7760 buf[0] = ustr[cur->pos];
7761 buf[1] = 0;
7762 s = eina_unicode_unicode_to_utf8(buf, NULL);
7763
7764 return s;
7765 }
7766}
7767
7768static char *
7769_evas_textblock_cursor_range_text_markup_get(const Evas_Textblock_Cursor *cur1, const Evas_Textblock_Cursor *_cur2)
7770{
7771 Evas_Object_Textblock_Node_Text *tnode;
7772 Eina_Strbuf *buf;
7773 Evas_Textblock_Cursor *cur2;
7774 buf = eina_strbuf_new();
7775
7776 if (!cur1 || !cur1->node) return NULL;
7777 if (!_cur2 || !_cur2->node) return NULL;
7778 if (cur1->obj != _cur2->obj) return NULL;
7779 if (evas_textblock_cursor_compare(cur1, _cur2) > 0)
7780 {
7781 const Evas_Textblock_Cursor *tc;
7782
7783 tc = cur1;
7784 cur1 = _cur2;
7785 _cur2 = tc;
7786 }
7787 /* Work on a local copy of the cur */
7788 cur2 = alloca(sizeof(Evas_Textblock_Cursor));
7789 cur2->obj = _cur2->obj;
7790 evas_textblock_cursor_copy(_cur2, cur2);
7791
7792 /* Parse the text between the cursors. */
7793 for (tnode = cur1->node ; tnode ;
7794 tnode = _NODE_TEXT(EINA_INLIST_GET(tnode)->next))
7795 {
7796 Evas_Object_Textblock_Node_Format *fnode;
7797 Eina_Unicode *text_base, *text;
7798 int off = 0;
7799
7800 text_base = text =
7801 eina_unicode_strndup(eina_ustrbuf_string_get(tnode->unicode),
7802 eina_ustrbuf_length_get(tnode->unicode));
7803 if (tnode == cur2->node)
7804 {
7805 fnode = _evas_textblock_node_text_get_first_format_between(tnode,
7806 cur1->pos, cur2->pos);
7807 }
7808 else if (tnode == cur1->node)
7809 {
7810 fnode = _evas_textblock_node_text_get_first_format_between(tnode,
7811 cur1->pos, -1);
7812 }
7813 else
7814 {
7815 fnode = _evas_textblock_node_text_get_first_format_between(tnode,
7816 0, -1);
7817 }
7818 /* Init the offset so the first one will count starting from cur1->pos
7819 * and not the previous format node */
7820 if (tnode == cur1->node)
7821 {
7822 if (fnode)
7823 {
7824 off = _evas_textblock_node_format_pos_get(fnode) -
7825 cur1->pos - fnode->offset;
7826 }
7827 text += cur1->pos;
7828 }
7829 else
7830 {
7831 off = 0;
7832 }
7833 while (fnode && (fnode->text_node == tnode))
7834 {
7835 Eina_Unicode tmp_ch;
7836 off += fnode->offset;
7837 if ((tnode == cur2->node) &&
7838 ((size_t) (text - text_base + off) >= cur2->pos))
7839 {
7840 break;
7841 }
7842 /* No need to skip on the first run */
7843 tmp_ch = text[off];
7844 text[off] = 0; /* Null terminate the part of the string */
7845 _markup_get_text_append(buf, text);
7846 _markup_get_format_append(buf, fnode);
7847 text[off] = tmp_ch; /* Restore the char */
7848 text += off;
7849 if (fnode->visible)
7850 {
7851 off = -1;
7852 text++;
7853 }
7854 else
7855 {
7856 off = 0;
7857 }
7858 fnode = _NODE_FORMAT(EINA_INLIST_GET(fnode)->next);
7859 }
7860 /* If we got to the last node, stop and add the rest outside */
7861 if (cur2->node == tnode)
7862 {
7863 /* Add the rest, skip replacement */
7864 /* Don't go past the second cursor pos */
7865 text_base[cur2->pos] = '\0';
7866 _markup_get_text_append(buf, text);
7867 free(text_base);
7868 break;
7869 }
7870 else
7871 {
7872 /* Add the rest, skip replacement */
7873 _markup_get_text_append(buf, text);
7874 free(text_base);
7875 }
7876 }
7877 /* return the string */
7878 {
7879 char *ret;
7880 ret = eina_strbuf_string_steal(buf);
7881 eina_strbuf_free(buf);
7882 return ret;
7883 }
7884}
7885
7886static char *
7887_evas_textblock_cursor_range_text_plain_get(const Evas_Textblock_Cursor *cur1, const Evas_Textblock_Cursor *_cur2)
7888{
7889 Eina_UStrbuf *buf;
7890 Evas_Object_Textblock_Node_Text *n1, *n2;
7891 Evas_Textblock_Cursor *cur2;
7892
7893 buf = eina_ustrbuf_new();
7894
7895 if (!cur1 || !cur1->node) return NULL;
7896 if (!_cur2 || !_cur2->node) return NULL;
7897 if (cur1->obj != _cur2->obj) return NULL;
7898 if (evas_textblock_cursor_compare(cur1, _cur2) > 0)
7899 {
7900 const Evas_Textblock_Cursor *tc;
7901
7902 tc = cur1;
7903 cur1 = _cur2;
7904 _cur2 = tc;
7905 }
7906 n1 = cur1->node;
7907 n2 = _cur2->node;
7908 /* Work on a local copy of the cur */
7909 cur2 = alloca(sizeof(Evas_Textblock_Cursor));
7910 cur2->obj = _cur2->obj;
7911 evas_textblock_cursor_copy(_cur2, cur2);
7912
7913
7914 if (n1 == n2)
7915 {
7916 const Eina_Unicode *tmp;
7917 tmp = eina_ustrbuf_string_get(n1->unicode);
7918 eina_ustrbuf_append_length(buf, tmp + cur1->pos, cur2->pos - cur1->pos);
7919 }
7920 else
7921 {
7922 const Eina_Unicode *tmp;
7923 tmp = eina_ustrbuf_string_get(n1->unicode);
7924 eina_ustrbuf_append(buf, tmp + cur1->pos);
7925 n1 = _NODE_TEXT(EINA_INLIST_GET(n1)->next);
7926 while (n1 != n2)
7927 {
7928 tmp = eina_ustrbuf_string_get(n1->unicode);
7929 eina_ustrbuf_append_length(buf, tmp,
7930 eina_ustrbuf_length_get(n1->unicode));
7931 n1 = _NODE_TEXT(EINA_INLIST_GET(n1)->next);
7932 }
7933 tmp = eina_ustrbuf_string_get(n2->unicode);
7934 eina_ustrbuf_append_length(buf, tmp, cur2->pos);
7935 }
7936
7937 /* Free and return */
7938 {
7939 char *ret;
7940 ret = eina_unicode_unicode_to_utf8(eina_ustrbuf_string_get(buf), NULL);
7941 eina_ustrbuf_free(buf);
7942 return ret;
7943 }
7944}
7945
7946EAPI Eina_List *
7947evas_textblock_cursor_range_formats_get(const Evas_Textblock_Cursor *cur1, const Evas_Textblock_Cursor *cur2)
7948{
7949 Evas_Object *obj = cur1->obj;
7950 Eina_List *ret = NULL;
7951 Evas_Object_Textblock_Node_Text *n1, *n2;
7952 Evas_Object_Textblock_Node_Format *first, *last;
7953 TB_HEAD_RETURN(NULL);
7954 if (!cur1 || !cur1->node) return NULL;
7955 if (!cur2 || !cur2->node) return NULL;
7956 if (cur1->obj != cur2->obj) return NULL;
7957 if (evas_textblock_cursor_compare(cur1, cur2) > 0)
7958 {
7959 const Evas_Textblock_Cursor *tc;
7960
7961 tc = cur1;
7962 cur1 = cur2;
7963 cur2 = tc;
7964 }
7965 n1 = cur1->node;
7966 n2 = cur2->node;
7967
7968 /* FIXME: Change first and last getting to format_before_or_at_pos_get */
7969
7970 last = n2->format_node;
7971
7972 /* If n2->format_node is NULL, we don't have formats in the tb/range. */
7973 if (!last)
7974 return NULL;
7975 /* If the found format is on our text node, we should go to the last
7976 * one, otherwise, the one we found is good enough. */
7977 if (last->text_node == n2)
7978 {
7979 Evas_Object_Textblock_Node_Format *fnode = last;
7980 while (fnode && (fnode->text_node == n2))
7981 {
7982 last = fnode;
7983 fnode = _NODE_FORMAT(EINA_INLIST_GET(fnode)->next);
7984 }
7985 }
7986
7987 /* If the first format node is within the range (i.e points to n1) or if
7988 * we have other formats in the range, go through them */
7989 first = n1->format_node;
7990 if ((first->text_node == n1) || (first != last))
7991 {
7992 Evas_Object_Textblock_Node_Format *fnode = first;
7993 /* Go to the first one in the range */
7994 if (first->text_node != n1)
7995 {
7996 first = _NODE_FORMAT(EINA_INLIST_GET(first)->next);
7997 }
7998
7999 while (fnode)
8000 {
8001 ret = eina_list_append(ret, fnode);
8002 if (fnode == last)
8003 break;
8004 fnode = _NODE_FORMAT(EINA_INLIST_GET(fnode)->next);
8005 }
8006 }
8007
8008 return ret;
8009
8010}
8011
8012EAPI char *
8013evas_textblock_cursor_range_text_get(const Evas_Textblock_Cursor *cur1, const Evas_Textblock_Cursor *cur2, Evas_Textblock_Text_Type format)
8014{
8015 if (format == EVAS_TEXTBLOCK_TEXT_MARKUP)
8016 return _evas_textblock_cursor_range_text_markup_get(cur1, cur2);
8017 else if (format == EVAS_TEXTBLOCK_TEXT_PLAIN)
8018 return _evas_textblock_cursor_range_text_plain_get(cur1, cur2);
8019 else
8020 return NULL; /* Not yet supported */
8021}
8022
8023EAPI const char *
8024evas_textblock_cursor_paragraph_text_get(const Evas_Textblock_Cursor *cur)
8025{
8026 Evas_Textblock_Cursor cur1, cur2;
8027 if (!cur) return NULL;
8028 if (!cur->node) return NULL;
8029 if (cur->node->utf8)
8030 {
8031 free(cur->node->utf8);
8032 }
8033 cur1.obj = cur2.obj = cur->obj;
8034 cur1.node = cur2.node = cur->node;
8035 evas_textblock_cursor_paragraph_char_first(&cur1);
8036 evas_textblock_cursor_paragraph_char_last(&cur2);
8037
8038 cur->node->utf8 = evas_textblock_cursor_range_text_get(&cur1, &cur2,
8039 EVAS_TEXTBLOCK_TEXT_MARKUP);
8040 return cur->node->utf8;
8041}
8042
8043EAPI int
8044evas_textblock_cursor_paragraph_text_length_get(const Evas_Textblock_Cursor *cur)
8045{
8046 int len;
8047 if (!cur) return -1;
8048 if (!cur->node) return -1;
8049 len = eina_ustrbuf_length_get(cur->node->unicode);
8050
8051 if (EINA_INLIST_GET(cur->node)->next)
8052 return len - 1; /* Remove the paragraph separator */
8053 else
8054 return len;
8055}
8056
8057EAPI const Evas_Object_Textblock_Node_Format *
8058evas_textblock_cursor_format_get(const Evas_Textblock_Cursor *cur)
8059{
8060 if (!cur) return NULL;
8061 if (!cur->node) return NULL;
8062 return _evas_textblock_cursor_node_format_at_pos_get(cur);
8063}
8064
8065EAPI const char *
8066evas_textblock_node_format_text_get(const Evas_Object_Textblock_Node_Format *fmt)
8067{
8068 static char *ret = NULL;
8069 char *tmp;
8070
8071 if (!fmt) return NULL;
8072
8073 if (ret) free(ret);
8074 ret = malloc(strlen(fmt->orig_format) + 2 + 1);
8075 tmp = ret;
8076
8077 if (fmt->opener && !fmt->own_closer)
8078 {
8079 *(tmp++) = '+';
8080 *(tmp++) = ' ';
8081 }
8082 else if (!fmt->opener)
8083 {
8084 *(tmp++) = '-';
8085 *(tmp++) = ' ';
8086 }
8087 strcpy(tmp, fmt->orig_format);
8088 return ret;
8089}
8090
8091EAPI void
8092evas_textblock_cursor_at_format_set(Evas_Textblock_Cursor *cur, const Evas_Object_Textblock_Node_Format *fmt)
8093{
8094 if (!fmt || !cur) return;
8095 cur->node = fmt->text_node;
8096 cur->pos = _evas_textblock_node_format_pos_get(fmt);
8097}
8098
8099EAPI Eina_Bool
8100evas_textblock_cursor_format_is_visible_get(const Evas_Textblock_Cursor *cur)
8101{
8102 const Eina_Unicode *text;
8103
8104 if (!cur) return EINA_FALSE;
8105 if (!cur->node) return EINA_FALSE;
8106 if (!evas_textblock_cursor_is_format(cur)) return EINA_FALSE;
8107 text = eina_ustrbuf_string_get(cur->node->unicode);
8108 return EVAS_TEXTBLOCK_IS_VISIBLE_FORMAT_CHAR(text[cur->pos]);
8109}
8110
8111EAPI int
8112evas_textblock_cursor_geometry_get(const Evas_Textblock_Cursor *cur, Evas_Coord *cx, Evas_Coord *cy, Evas_Coord *cw, Evas_Coord *ch, Evas_BiDi_Direction *dir, Evas_Textblock_Cursor_Type ctype)
8113{
8114 int ret = -1;
8115 const Evas_Textblock_Cursor *dir_cur;
8116 Evas_Textblock_Cursor cur2;
8117 Evas_Object_Textblock *o;
8118 o = (Evas_Object_Textblock *)(cur->obj->object_data);
8119 if (!o->formatted.valid) _relayout(cur->obj);
8120
8121 dir_cur = cur;
8122 if (ctype == EVAS_TEXTBLOCK_CURSOR_UNDER)
8123 {
8124 ret = evas_textblock_cursor_pen_geometry_get(cur, cx, cy, cw, ch);
8125 }
8126 else if (ctype == EVAS_TEXTBLOCK_CURSOR_BEFORE)
8127 {
8128 /* In the case of a "before cursor", we should get the coordinates
8129 * of just after the previous char (which in bidi text may not be
8130 * just before the current char). */
8131 Evas_Coord x, y, h, w;
8132 Evas_Object_Textblock_Node_Format *fmt;
8133
8134 /* If it's at the end of the line, we want to get the position, not
8135 * the position of the previous */
8136 if ((cur->pos > 0) && !_evas_textblock_cursor_is_at_the_end(cur))
8137 {
8138#ifdef BIDI_SUPPORT
8139 Eina_Bool before_char = EINA_FALSE;
8140#endif
8141 cur2.obj = cur->obj;
8142 evas_textblock_cursor_copy(cur, &cur2);
8143 evas_textblock_cursor_char_prev(&cur2);
8144
8145 fmt = _evas_textblock_cursor_node_format_at_pos_get(&cur2);
8146
8147 if (!fmt || !_IS_LINE_SEPARATOR(fmt->format))
8148 {
8149 dir_cur = &cur2;
8150#ifdef BIDI_SUPPORT
8151 before_char = EINA_FALSE;
8152#endif
8153 }
8154#ifdef BIDI_SUPPORT
8155 else
8156 {
8157 before_char = EINA_TRUE;
8158 }
8159#endif
8160 ret = evas_textblock_cursor_pen_geometry_get(
8161 dir_cur, &x, &y, &w, &h);
8162#ifdef BIDI_SUPPORT
8163 /* Adjust if the char is an rtl char */
8164 if (ret >= 0)
8165 {
8166 Eina_Bool is_rtl = EINA_FALSE;
8167 if (dir_cur->node->par->is_bidi)
8168 {
8169 Evas_Object_Textblock_Line *ln;
8170 Evas_Object_Textblock_Item *it;
8171 _find_layout_item_match(dir_cur, &ln, &it);
8172 if ((it->type == EVAS_TEXTBLOCK_ITEM_TEXT) &&
8173 (_ITEM_TEXT(it)->text_props.bidi.dir ==
8174 EVAS_BIDI_DIRECTION_RTL))
8175 is_rtl = EINA_TRUE;
8176 else if ((it->type == EVAS_TEXTBLOCK_ITEM_FORMAT) &&
8177 (_ITEM_FORMAT(it)->bidi_dir ==
8178 EVAS_BIDI_DIRECTION_RTL))
8179 is_rtl = EINA_TRUE;
8180 }
8181
8182 if ((!before_char && is_rtl) ||
8183 (before_char && !is_rtl))
8184 {
8185 /* Just don't advance the width */
8186 w = 0;
8187 }
8188 }
8189#endif
8190 }
8191 else if (cur->pos == 0)
8192 {
8193 ret = evas_textblock_cursor_pen_geometry_get(
8194 dir_cur, &x, &y, &w, &h);
8195#ifdef BIDI_SUPPORT
8196 Eina_Bool is_rtl = EINA_FALSE;
8197 if (dir_cur->node && dir_cur->node->par->is_bidi)
8198 {
8199 Evas_Object_Textblock_Line *ln;
8200 Evas_Object_Textblock_Item *it;
8201 _find_layout_item_match(dir_cur, &ln, &it);
8202 if ((it->type == EVAS_TEXTBLOCK_ITEM_TEXT) &&
8203 (_ITEM_TEXT(it)->text_props.bidi.dir ==
8204 EVAS_BIDI_DIRECTION_RTL))
8205 is_rtl = EINA_TRUE;
8206 else if ((it->type == EVAS_TEXTBLOCK_ITEM_FORMAT) &&
8207 (_ITEM_FORMAT(it)->bidi_dir ==
8208 EVAS_BIDI_DIRECTION_RTL))
8209 is_rtl = EINA_TRUE;
8210 }
8211
8212 /* Adjust if the char is an rtl char */
8213 if ((ret >= 0) && (!is_rtl))
8214 {
8215 /* Just don't advance the width */
8216 w = 0;
8217 }
8218#endif
8219 }
8220 else
8221 {
8222 ret = evas_textblock_cursor_pen_geometry_get(
8223 dir_cur, &x, &y, &w, &h);
8224 }
8225 if (ret >= 0)
8226 {
8227 if (cx) *cx = x + w;
8228 if (cy) *cy = y;
8229 if (cw) *cw = 0;
8230 if (ch) *ch = h;
8231 }
8232 }
8233
8234 if (dir && dir_cur && dir_cur->node)
8235 {
8236#ifdef BIDI_SUPPORT
8237 Eina_Bool is_rtl = EINA_FALSE;
8238 if (dir_cur->node->par->is_bidi)
8239 {
8240 Evas_Object_Textblock_Line *ln;
8241 Evas_Object_Textblock_Item *it;
8242 _find_layout_item_match(dir_cur, &ln, &it);
8243 if ((it->type == EVAS_TEXTBLOCK_ITEM_TEXT) &&
8244 (_ITEM_TEXT(it)->text_props.bidi.dir ==
8245 EVAS_BIDI_DIRECTION_RTL))
8246 is_rtl = EINA_TRUE;
8247 else if ((it->type == EVAS_TEXTBLOCK_ITEM_FORMAT) &&
8248 (_ITEM_FORMAT(it)->bidi_dir ==
8249 EVAS_BIDI_DIRECTION_RTL))
8250 is_rtl = EINA_TRUE;
8251 }
8252
8253 if (_evas_textblock_cursor_is_at_the_end(dir_cur) && (dir_cur->pos > 0))
8254 {
8255 *dir = (is_rtl) ?
8256 EVAS_BIDI_DIRECTION_RTL : EVAS_BIDI_DIRECTION_LTR;
8257 }
8258 else if (dir_cur->pos > 0)
8259 {
8260 *dir = (is_rtl) ?
8261 EVAS_BIDI_DIRECTION_RTL : EVAS_BIDI_DIRECTION_LTR;
8262 }
8263 else
8264#endif
8265 {
8266 *dir = EVAS_BIDI_DIRECTION_LTR;
8267 }
8268 }
8269 return ret;
8270}
8271
8272/**
8273 * @internal
8274 * Returns the geometry/pen position (depending on query_func) of the char
8275 * at pos.
8276 *
8277 * @param cur the position of the char.
8278 * @param query_func the query function to use.
8279 * @param cx the x of the char (or pen_x in the case of pen position).
8280 * @param cy the y of the char.
8281 * @param cw the w of the char (or advance in the case pen position).
8282 * @param ch the h of the char.
8283 * @return line number of the char on success, -1 on error.
8284 */
8285static int
8286_evas_textblock_cursor_char_pen_geometry_common_get(int (*query_func) (void *data, Evas_Font_Set *font, const Evas_Text_Props *intl_props, int pos, int *cx, int *cy, int *cw, int *ch), const Evas_Textblock_Cursor *cur, Evas_Coord *cx, Evas_Coord *cy, Evas_Coord *cw, Evas_Coord *ch)
8287{
8288 Evas_Object_Textblock *o;
8289 Evas_Object_Textblock_Line *ln = NULL;
8290 Evas_Object_Textblock_Item *it = NULL;
8291 Evas_Object_Textblock_Text_Item *ti = NULL;
8292 Evas_Object_Textblock_Format_Item *fi = NULL;
8293 int x = 0, y = 0, w = 0, h = 0;
8294 int pos;
8295 Eina_Bool previous_format;
8296
8297 if (!cur) return -1;
8298 o = (Evas_Object_Textblock *)(cur->obj->object_data);
8299 if (!o->formatted.valid) _relayout(cur->obj);
8300
8301 if (!cur->node)
8302 {
8303 if (!o->text_nodes)
8304 {
8305 if (!o->paragraphs) return -1;
8306 ln = o->paragraphs->lines;
8307 if (!ln) return -1;
8308 if (cx) *cx = ln->x;
8309 if (cy) *cy = ln->par->y + ln->y;
8310 if (cw) *cw = ln->w;
8311 if (ch) *ch = ln->h;
8312 return ln->par->line_no + ln->line_no;
8313 }
8314 else
8315 return -1;
8316 }
8317
8318 previous_format = _find_layout_item_match(cur, &ln, &it);
8319 if (!it)
8320 {
8321 return -1;
8322 }
8323 if (it->type == EVAS_TEXTBLOCK_ITEM_TEXT)
8324 {
8325 ti = _ITEM_TEXT(it);
8326 }
8327 else
8328 {
8329 fi = _ITEM_FORMAT(it);
8330 }
8331
8332 if (ln && ti)
8333 {
8334 pos = cur->pos - ti->parent.text_pos;
8335
8336 if (pos < 0) pos = 0;
8337 if (ti->parent.format->font.font)
8338 {
8339 query_func(cur->ENDT,
8340 ti->parent.format->font.font,
8341 &ti->text_props,
8342 pos,
8343 &x, &y, &w, &h);
8344 }
8345
8346 x += ln->x + _ITEM(ti)->x;
8347
8348 if (x < ln->x)
8349 {
8350 x = ln->x;
8351 }
8352 y = ln->par->y + ln->y;
8353 h = ln->h;
8354 }
8355 else if (ln && fi)
8356 {
8357 if (previous_format)
8358 {
8359 if (_IS_LINE_SEPARATOR(fi->item))
8360 {
8361 x = 0;
8362 y = ln->par->y + ln->y + ln->h;
8363 }
8364 else
8365 {
8366#ifdef BIDI_SUPPORT
8367 if (ln->par->direction == EVAS_BIDI_DIRECTION_RTL)
8368 {
8369 x = ln->x;
8370 }
8371 else
8372#endif
8373 {
8374 x = ln->x + ln->w;
8375 }
8376 y = ln->par->y + ln->y;
8377 }
8378 w = 0;
8379 h = ln->h;
8380 }
8381 else
8382 {
8383 x = ln->x + _ITEM(fi)->x;
8384 y = ln->par->y + ln->y;
8385 w = _ITEM(fi)->w;
8386 h = ln->h;
8387 }
8388 }
8389 else
8390 {
8391 return -1;
8392 }
8393 if (cx) *cx = x;
8394 if (cy) *cy = y;
8395 if (cw) *cw = w;
8396 if (ch) *ch = h;
8397 return ln->par->line_no + ln->line_no;
8398}
8399
8400EAPI int
8401evas_textblock_cursor_char_geometry_get(const Evas_Textblock_Cursor *cur, Evas_Coord *cx, Evas_Coord *cy, Evas_Coord *cw, Evas_Coord *ch)
8402{
8403 return _evas_textblock_cursor_char_pen_geometry_common_get(
8404 cur->ENFN->font_char_coords_get, cur, cx, cy, cw, ch);
8405}
8406
8407EAPI int
8408evas_textblock_cursor_pen_geometry_get(const Evas_Textblock_Cursor *cur, Evas_Coord *cx, Evas_Coord *cy, Evas_Coord *cw, Evas_Coord *ch)
8409{
8410 return _evas_textblock_cursor_char_pen_geometry_common_get(
8411 cur->ENFN->font_pen_coords_get, cur, cx, cy, cw, ch);
8412}
8413
8414EAPI int
8415evas_textblock_cursor_line_geometry_get(const Evas_Textblock_Cursor *cur, Evas_Coord *cx, Evas_Coord *cy, Evas_Coord *cw, Evas_Coord *ch)
8416{
8417 Evas_Object_Textblock *o;
8418 Evas_Object_Textblock_Line *ln = NULL;
8419 Evas_Object_Textblock_Item *it = NULL;
8420 int x, y, w, h;
8421
8422 if (!cur) return -1;
8423 o = (Evas_Object_Textblock *)(cur->obj->object_data);
8424 if (!o->formatted.valid) _relayout(cur->obj);
8425 if (!cur->node)
8426 {
8427 ln = o->paragraphs->lines;
8428 }
8429 else
8430 {
8431 _find_layout_item_match(cur, &ln, &it);
8432 }
8433 if (!ln) return -1;
8434 x = ln->x;
8435 y = ln->par->y + ln->y;
8436 w = ln->w;
8437 h = ln->h;
8438 if (cx) *cx = x;
8439 if (cy) *cy = y;
8440 if (cw) *cw = w;
8441 if (ch) *ch = h;
8442 return ln->par->line_no + ln->line_no;
8443}
8444
8445EAPI Eina_Bool
8446evas_textblock_cursor_visible_range_get(Evas_Textblock_Cursor *start, Evas_Textblock_Cursor *end)
8447{
8448 Evas *e;
8449 Evas_Coord cy, ch;
8450 Evas_Object *obj = start->obj;
8451 TB_HEAD_RETURN(EINA_FALSE);
8452 e = evas_object_evas_get(obj);
8453 cy = 0 - obj->cur.geometry.y;
8454 ch = e->viewport.h;
8455 evas_textblock_cursor_line_coord_set(start, cy);
8456 evas_textblock_cursor_line_coord_set(end, cy + ch);
8457 evas_textblock_cursor_line_char_last(end);
8458
8459 return EINA_TRUE;
8460}
8461
8462EAPI Eina_Bool
8463evas_textblock_cursor_char_coord_set(Evas_Textblock_Cursor *cur, Evas_Coord x, Evas_Coord y)
8464{
8465 Evas_Object_Textblock *o;
8466 Evas_Object_Textblock_Paragraph *found_par;
8467 Evas_Object_Textblock_Line *ln;
8468 Evas_Object_Textblock_Item *it = NULL;
8469
8470 if (!cur) return EINA_FALSE;
8471 o = (Evas_Object_Textblock *)(cur->obj->object_data);
8472 if (!o->formatted.valid) _relayout(cur->obj);
8473 x += o->style_pad.l;
8474 y += o->style_pad.t;
8475
8476 found_par = _layout_find_paragraph_by_y(o, y);
8477 if (found_par)
8478 {
8479 _layout_paragraph_render(o, found_par);
8480 EINA_INLIST_FOREACH(found_par->lines, ln)
8481 {
8482 if (ln->par->y + ln->y > y) break;
8483 if ((ln->par->y + ln->y <= y) && ((ln->par->y + ln->y + ln->h) > y))
8484 {
8485 /* If before or after the line, go to start/end according
8486 * to paragraph direction. */
8487 if (x < ln->x)
8488 {
8489 cur->pos = ln->items->text_pos;
8490 cur->node = found_par->text_node;
8491 if (found_par->direction == EVAS_BIDI_DIRECTION_RTL)
8492 {
8493 evas_textblock_cursor_line_char_last(cur);
8494 }
8495 else
8496 {
8497 evas_textblock_cursor_line_char_first(cur);
8498 }
8499 return EINA_TRUE;
8500 }
8501 else if (x >= ln->x + ln->w)
8502 {
8503 cur->pos = ln->items->text_pos;
8504 cur->node = found_par->text_node;
8505 if (found_par->direction == EVAS_BIDI_DIRECTION_RTL)
8506 {
8507 evas_textblock_cursor_line_char_first(cur);
8508 }
8509 else
8510 {
8511 evas_textblock_cursor_line_char_last(cur);
8512 }
8513 return EINA_TRUE;
8514 }
8515
8516 EINA_INLIST_FOREACH(ln->items, it)
8517 {
8518 if (((it->x + ln->x) <= x) && (((it->x + ln->x) + it->adv) > x))
8519 {
8520 if (it->type == EVAS_TEXTBLOCK_ITEM_TEXT)
8521 {
8522 int pos;
8523 int cx, cy, cw, ch;
8524 Evas_Object_Textblock_Text_Item *ti;
8525 ti = _ITEM_TEXT(it);
8526
8527 pos = -1;
8528 if (ti->parent.format->font.font)
8529 pos = cur->ENFN->font_char_at_coords_get(
8530 cur->ENDT,
8531 ti->parent.format->font.font,
8532 &ti->text_props,
8533 x - it->x - ln->x, 0,
8534 &cx, &cy, &cw, &ch);
8535 if (pos < 0)
8536 return EINA_FALSE;
8537 cur->pos = pos + it->text_pos;
8538 cur->node = it->text_node;
8539 return EINA_TRUE;
8540 }
8541 else
8542 {
8543 Evas_Object_Textblock_Format_Item *fi;
8544 fi = _ITEM_FORMAT(it);
8545 cur->pos = fi->parent.text_pos;
8546 cur->node = found_par->text_node;
8547 return EINA_TRUE;
8548 }
8549 }
8550 }
8551 }
8552 }
8553 }
8554 else if (o->paragraphs && (y >= o->paragraphs->y + o->formatted.h))
8555 {
8556 /* If we are after the last paragraph, use the last position in the
8557 * text. */
8558 evas_textblock_cursor_paragraph_last(cur);
8559 return EINA_TRUE;
8560 }
8561 else if (o->paragraphs && (y < o->paragraphs->y))
8562 {
8563 evas_textblock_cursor_paragraph_first(cur);
8564 return EINA_TRUE;
8565 }
8566
8567 return EINA_FALSE;
8568}
8569
8570EAPI int
8571evas_textblock_cursor_line_coord_set(Evas_Textblock_Cursor *cur, Evas_Coord y)
8572{
8573 Evas_Object_Textblock *o;
8574 Evas_Object_Textblock_Paragraph *found_par;
8575 Evas_Object_Textblock_Line *ln;
8576
8577 if (!cur) return -1;
8578 o = (Evas_Object_Textblock *)(cur->obj->object_data);
8579 if (!o->formatted.valid) _relayout(cur->obj);
8580 y += o->style_pad.t;
8581
8582 found_par = _layout_find_paragraph_by_y(o, y);
8583
8584 if (found_par)
8585 {
8586 _layout_paragraph_render(o, found_par);
8587 EINA_INLIST_FOREACH(found_par->lines, ln)
8588 {
8589 if (ln->par->y + ln->y > y) break;
8590 if ((ln->par->y + ln->y <= y) && ((ln->par->y + ln->y + ln->h) > y))
8591 {
8592 evas_textblock_cursor_line_set(cur, ln->par->line_no +
8593 ln->line_no);
8594 return ln->par->line_no + ln->line_no;
8595 }
8596 }
8597 }
8598 else if (o->paragraphs && (y >= o->paragraphs->y + o->formatted.h))
8599 {
8600 int line_no = 0;
8601 /* If we are after the last paragraph, use the last position in the
8602 * text. */
8603 evas_textblock_cursor_paragraph_last(cur);
8604 if (cur->node && cur->node->par)
8605 {
8606 line_no = cur->node->par->line_no;
8607 if (cur->node->par->lines)
8608 {
8609 line_no += ((Evas_Object_Textblock_Line *)
8610 EINA_INLIST_GET(cur->node->par->lines)->last)->line_no;
8611 }
8612 }
8613 return line_no;
8614 }
8615 else if (o->paragraphs && (y < o->paragraphs->y))
8616 {
8617 int line_no = 0;
8618 evas_textblock_cursor_paragraph_first(cur);
8619 if (cur->node && cur->node->par)
8620 {
8621 line_no = cur->node->par->line_no;
8622 }
8623 return line_no;
8624 }
8625 return -1;
8626}
8627
8628/**
8629 * @internal
8630 * Updates x and w according to the text direction, position in text and
8631 * if it's a special case switch
8632 *
8633 * @param ti the text item we are working on
8634 * @param x the current x (we get) and the x we return
8635 * @param w the current w (we get) and the w we return
8636 * @param start if this is the first item or not
8637 * @param switch_items toogles item switching (rtl cases)
8638 */
8639static void
8640_evas_textblock_range_calc_x_w(const Evas_Object_Textblock_Item *it,
8641 Evas_Coord *x, Evas_Coord *w, Eina_Bool start, Eina_Bool switch_items)
8642{
8643 if ((start && !switch_items) || (!start && switch_items))
8644 {
8645#ifdef BIDI_SUPPORT
8646 if (((it->type == EVAS_TEXTBLOCK_ITEM_TEXT) &&
8647 _ITEM_TEXT(it)->text_props.bidi.dir == EVAS_BIDI_DIRECTION_RTL)
8648 ||
8649 ((it->type == EVAS_TEXTBLOCK_ITEM_FORMAT) &&
8650 _ITEM_FORMAT(it)->bidi_dir == EVAS_BIDI_DIRECTION_RTL))
8651 {
8652 *w = *x + *w;
8653 *x = 0;
8654 }
8655 else
8656#endif
8657 {
8658 *w = it->adv - *x;
8659 }
8660 }
8661 else
8662 {
8663#ifdef BIDI_SUPPORT
8664 if (((it->type == EVAS_TEXTBLOCK_ITEM_TEXT) &&
8665 _ITEM_TEXT(it)->text_props.bidi.dir == EVAS_BIDI_DIRECTION_RTL)
8666 ||
8667 ((it->type == EVAS_TEXTBLOCK_ITEM_FORMAT) &&
8668 _ITEM_FORMAT(it)->bidi_dir == EVAS_BIDI_DIRECTION_RTL))
8669 {
8670 *x = *x + *w;
8671 *w = it->adv - *x;
8672 }
8673 else
8674#endif
8675 {
8676 *w = *x;
8677 *x = 0;
8678 }
8679 }
8680
8681}
8682
8683/**
8684 * @internal
8685 * Returns the geometry of the range in line ln. Cur1 is the start cursor,
8686 * cur2 is the end cursor, NULL means from the start or to the end accordingly.
8687 * Assumes that ln is valid, and that at least one of cur1 and cur2 is not NULL.
8688 *
8689 * @param ln the line to work on.
8690 * @param cur1 the start cursor
8691 * @param cur2 the end cursor
8692 * @return Returns the geometry of the range
8693 */
8694static Eina_List *
8695_evas_textblock_cursor_range_in_line_geometry_get(
8696 const Evas_Object_Textblock_Line *ln, const Evas_Textblock_Cursor *cur1,
8697 const Evas_Textblock_Cursor *cur2)
8698{
8699 Evas_Object_Textblock_Item *it;
8700 Evas_Object_Textblock_Item *it1, *it2;
8701 Eina_List *rects = NULL;
8702 Evas_Textblock_Rectangle *tr;
8703 size_t start, end;
8704 Eina_Bool switch_items;
8705 const Evas_Textblock_Cursor *cur;
8706
8707 cur = (cur1) ? cur1 : cur2;
8708
8709 if (!cur) return NULL;
8710
8711 /* Find the first and last items */
8712 it1 = it2 = NULL;
8713 start = end = 0;
8714 EINA_INLIST_FOREACH(ln->items, it)
8715 {
8716 size_t item_len;
8717 item_len = (it->type == EVAS_TEXTBLOCK_ITEM_TEXT) ?
8718 _ITEM_TEXT(it)->text_props.text_len
8719 : 1;
8720 if ((!cur1 || (cur1->pos < it->text_pos + item_len)) &&
8721 (!cur2 || (cur2->pos >= it->text_pos)))
8722 {
8723 if (!it1)
8724 {
8725 it1 = it;
8726 start = item_len; /* start stores the first item_len */
8727 }
8728 it2 = it;
8729 end = item_len; /* end stores the last item_len */
8730 }
8731 }
8732
8733 /* If we couldn't find even one item, return */
8734 if (!it1) return NULL;
8735
8736 /* If the first item is logically before or equal the second item
8737 * we have to set start and end differently than in the other case */
8738 if (it1->text_pos <= it2->text_pos)
8739 {
8740 start = (cur1) ? (cur1->pos - it1->text_pos) : 0;
8741 end = (cur2) ? (cur2->pos - it2->text_pos) : end;
8742 switch_items = EINA_FALSE;
8743 }
8744 else
8745 {
8746 start = (cur2) ? (cur2->pos - it1->text_pos) : start;
8747 end = (cur1) ? (cur1->pos - it2->text_pos) : 0;
8748 switch_items = EINA_TRUE;
8749 }
8750
8751 /* IMPORTANT: Don't use cur1/cur2 past this point (because they probably
8752 * don't make sense anymore. That's why there are start and end),
8753 * unless you know what you are doing */
8754
8755 /* Special case when they share the same item and it's a text item */
8756 if ((it1 == it2) && (it1->type == EVAS_TEXTBLOCK_ITEM_TEXT))
8757 {
8758 Evas_Coord x1, w1, x2, w2;
8759 Evas_Coord x, w, y, h;
8760 Evas_Object_Textblock_Text_Item *ti;
8761 int ret = 0;
8762
8763 ti = _ITEM_TEXT(it1);
8764 if (ti->parent.format->font.font)
8765 {
8766 ret = cur->ENFN->font_pen_coords_get(cur->ENDT,
8767 ti->parent.format->font.font,
8768 &ti->text_props,
8769 start,
8770 &x1, &y, &w1, &h);
8771 }
8772 if (!ret)
8773 {
8774 return NULL;
8775 }
8776 ret = cur->ENFN->font_pen_coords_get(cur->ENDT,
8777 ti->parent.format->font.font,
8778 &ti->text_props,
8779 end,
8780 &x2, &y, &w2, &h);
8781 if (!ret)
8782 {
8783 return NULL;
8784 }
8785
8786 /* Make x2 the one on the right */
8787 if (x2 < x1)
8788 {
8789 Evas_Coord tmp;
8790 tmp = x1;
8791 x1 = x2;
8792 x2 = tmp;
8793
8794 tmp = w1;
8795 w1 = w2;
8796 w2 = tmp;
8797 }
8798
8799#ifdef BIDI_SUPPORT
8800 if (ti->text_props.bidi.dir == EVAS_BIDI_DIRECTION_RTL)
8801 {
8802 x = x1 + w1;
8803 w = x2 + w2 - x;
8804 }
8805 else
8806#endif
8807 {
8808 x = x1;
8809 w = x2 - x1;
8810 }
8811 if (w > 0)
8812 {
8813 tr = calloc(1, sizeof(Evas_Textblock_Rectangle));
8814 rects = eina_list_append(rects, tr);
8815 tr->x = ln->x + it1->x + x;
8816 tr->y = ln->par->y + ln->y;
8817 tr->h = ln->h;
8818 tr->w = w;
8819 }
8820 }
8821 else if (it1 != it2)
8822 {
8823 /* Get the middle items */
8824 Evas_Coord min_x, max_x;
8825 Evas_Coord x, w;
8826 it = _ITEM(EINA_INLIST_GET(it1)->next);
8827 min_x = max_x = it->x;
8828
8829 if (it1->type == EVAS_TEXTBLOCK_ITEM_TEXT)
8830 {
8831 Evas_Coord y, h;
8832 Evas_Object_Textblock_Text_Item *ti;
8833 int ret;
8834 ti = _ITEM_TEXT(it1);
8835
8836 ret = cur->ENFN->font_pen_coords_get(cur->ENDT,
8837 ti->parent.format->font.font,
8838 &ti->text_props,
8839 start,
8840 &x, &y, &w, &h);
8841 if (!ret)
8842 {
8843 /* BUG! Skip the first item */
8844 x = w = 0;
8845 }
8846 else
8847 {
8848 _evas_textblock_range_calc_x_w(it1, &x, &w, EINA_TRUE,
8849 switch_items);
8850 }
8851 }
8852 else
8853 {
8854 x = 0;
8855 w = it1->w;
8856 _evas_textblock_range_calc_x_w(it1, &x, &w, EINA_TRUE,
8857 switch_items);
8858 }
8859 if (w > 0)
8860 {
8861 tr = calloc(1, sizeof(Evas_Textblock_Rectangle));
8862 rects = eina_list_append(rects, tr);
8863 tr->x = ln->x + it1->x + x;
8864 tr->y = ln->par->y + ln->y;
8865 tr->h = ln->h;
8866 tr->w = w;
8867 }
8868
8869 while (it && (it != it2))
8870 {
8871 max_x = it->x + it->adv;
8872 it = (Evas_Object_Textblock_Item *) EINA_INLIST_GET(it)->next;
8873 }
8874 if (min_x != max_x)
8875 {
8876 tr = calloc(1, sizeof(Evas_Textblock_Rectangle));
8877 rects = eina_list_append(rects, tr);
8878 tr->x = ln->x + min_x;
8879 tr->y = ln->par->y + ln->y;
8880 tr->h = ln->h;
8881 tr->w = max_x - min_x;
8882 }
8883 if (it2->type == EVAS_TEXTBLOCK_ITEM_TEXT)
8884 {
8885 Evas_Coord y, h;
8886 Evas_Object_Textblock_Text_Item *ti;
8887 int ret;
8888 ti = _ITEM_TEXT(it2);
8889
8890 ret = cur->ENFN->font_pen_coords_get(cur->ENDT,
8891 ti->parent.format->font.font,
8892 &ti->text_props,
8893 end,
8894 &x, &y, &w, &h);
8895 if (!ret)
8896 {
8897 /* BUG! skip the last item */
8898 x = w = 0;
8899 }
8900 else
8901 {
8902 _evas_textblock_range_calc_x_w(it2, &x, &w, EINA_FALSE,
8903 switch_items);
8904 }
8905 }
8906 else
8907 {
8908 x = 0;
8909 w = it2->w;
8910 _evas_textblock_range_calc_x_w(it2, &x, &w, EINA_FALSE,
8911 switch_items);
8912 }
8913 if (w > 0)
8914 {
8915 tr = calloc(1, sizeof(Evas_Textblock_Rectangle));
8916 rects = eina_list_append(rects, tr);
8917 tr->x = ln->x + it2->x + x;
8918 tr->y = ln->par->y + ln->y;
8919 tr->h = ln->h;
8920 tr->w = w;
8921 }
8922 }
8923 return rects;
8924}
8925
8926EAPI Eina_List *
8927evas_textblock_cursor_range_geometry_get(const Evas_Textblock_Cursor *cur1, const Evas_Textblock_Cursor *cur2)
8928{
8929 Evas_Object_Textblock *o;
8930 Evas_Object_Textblock_Line *ln1, *ln2;
8931 Evas_Object_Textblock_Item *it1, *it2;
8932 Eina_List *rects = NULL;
8933 Evas_Textblock_Rectangle *tr;
8934
8935 if (!cur1 || !cur1->node) return NULL;
8936 if (!cur2 || !cur2->node) return NULL;
8937 if (cur1->obj != cur2->obj) return NULL;
8938 o = (Evas_Object_Textblock *)(cur1->obj->object_data);
8939 if (!o->formatted.valid) _relayout(cur1->obj);
8940 if (evas_textblock_cursor_compare(cur1, cur2) > 0)
8941 {
8942 const Evas_Textblock_Cursor *tc;
8943
8944 tc = cur1;
8945 cur1 = cur2;
8946 cur2 = tc;
8947 }
8948
8949 ln1 = ln2 = NULL;
8950 it1 = it2 = NULL;
8951 _find_layout_item_match(cur1, &ln1, &it1);
8952 if (!ln1 || !it1) return NULL;
8953 _find_layout_item_match(cur2, &ln2, &it2);
8954 if (!ln2 || !it2) return NULL;
8955
8956 if (ln1 == ln2)
8957 {
8958 rects = _evas_textblock_cursor_range_in_line_geometry_get(ln1,
8959 cur1, cur2);
8960 }
8961 else
8962 {
8963 Evas_Object_Textblock_Line *plni, *lni;
8964 Eina_List *rects2 = NULL;
8965 /* Handle the first line */
8966 rects = _evas_textblock_cursor_range_in_line_geometry_get(ln1,
8967 cur1, NULL);
8968
8969 /* Handle the lines between the first and the last line */
8970 lni = (Evas_Object_Textblock_Line *) EINA_INLIST_GET(ln1)->next;
8971 if (!lni && (ln1->par != ln2->par))
8972 {
8973 lni = ((Evas_Object_Textblock_Paragraph *)
8974 EINA_INLIST_GET(ln1->par)->next)->lines;
8975 }
8976 while (lni && (lni != ln2))
8977 {
8978 tr = calloc(1, sizeof(Evas_Textblock_Rectangle));
8979 rects = eina_list_append(rects, tr);
8980 tr->x = lni->x;
8981 tr->y = lni->par->y + lni->y;
8982 tr->h = lni->h;
8983 tr->w = lni->w;
8984 plni = lni;
8985 lni = (Evas_Object_Textblock_Line *) EINA_INLIST_GET(lni)->next;
8986 if (!lni && (plni->par != ln2->par))
8987 {
8988 lni = ((Evas_Object_Textblock_Paragraph *)
8989 EINA_INLIST_GET(plni->par)->next)->lines;
8990 }
8991 }
8992 rects2 = _evas_textblock_cursor_range_in_line_geometry_get(ln2,
8993 NULL, cur2);
8994 rects = eina_list_merge(rects, rects2);
8995 }
8996 return rects;
8997}
8998
8999EAPI Eina_Bool
9000evas_textblock_cursor_format_item_geometry_get(const Evas_Textblock_Cursor *cur, Evas_Coord *cx, Evas_Coord *cy, Evas_Coord *cw, Evas_Coord *ch)
9001{
9002 Evas_Object_Textblock *o;
9003 Evas_Object_Textblock_Line *ln = NULL;
9004 Evas_Object_Textblock_Format_Item *fi;
9005 Evas_Object_Textblock_Item *it = NULL;
9006 Evas_Coord x, y, w, h;
9007
9008 if (!cur || !evas_textblock_cursor_format_is_visible_get(cur)) return EINA_FALSE;
9009 o = (Evas_Object_Textblock *)(cur->obj->object_data);
9010 if (!o->formatted.valid) _relayout(cur->obj);
9011 if (!evas_textblock_cursor_format_is_visible_get(cur)) return EINA_FALSE;
9012 _find_layout_item_line_match(cur->obj, cur->node, cur->pos, &ln, &it);
9013 fi = _ITEM_FORMAT(it);
9014 if ((!ln) || (!fi)) return EINA_FALSE;
9015 x = ln->x + fi->parent.x;
9016 y = ln->par->y + ln->y + ln->baseline + fi->y;
9017 w = fi->parent.w;
9018 h = fi->parent.h;
9019 if (cx) *cx = x;
9020 if (cy) *cy = y;
9021 if (cw) *cw = w;
9022 if (ch) *ch = h;
9023 return EINA_TRUE;
9024}
9025
9026EAPI Eina_Bool
9027evas_textblock_cursor_eol_get(const Evas_Textblock_Cursor *cur)
9028{
9029 Eina_Bool ret = EINA_FALSE;
9030 Evas_Textblock_Cursor cur2;
9031 if (!cur) return EINA_FALSE;
9032
9033 cur2.obj = cur->obj;
9034 evas_textblock_cursor_copy(cur, &cur2);
9035 evas_textblock_cursor_line_char_last(&cur2);
9036 if (cur2.pos == cur->pos)
9037 {
9038 ret = EINA_TRUE;
9039 }
9040 return ret;
9041}
9042
9043/* general controls */
9044EAPI Eina_Bool
9045evas_object_textblock_line_number_geometry_get(const Evas_Object *obj, int line, Evas_Coord *cx, Evas_Coord *cy, Evas_Coord *cw, Evas_Coord *ch)
9046{
9047 Evas_Object_Textblock_Line *ln;
9048
9049 TB_HEAD_RETURN(0);
9050 ln = _find_layout_line_num(obj, line);
9051 if (!ln) return EINA_FALSE;
9052 if (cx) *cx = ln->x;
9053 if (cy) *cy = ln->par->y + ln->y;
9054 if (cw) *cw = ln->w;
9055 if (ch) *ch = ln->h;
9056 return EINA_TRUE;
9057}
9058
9059EAPI void
9060evas_object_textblock_clear(Evas_Object *obj)
9061{
9062 Eina_List *l;
9063 Evas_Textblock_Cursor *cur;
9064
9065 TB_HEAD();
9066 if (o->paragraphs)
9067 {
9068 _paragraphs_free(obj, o->paragraphs);
9069 o->paragraphs = NULL;
9070 }
9071
9072 _nodes_clear(obj);
9073 o->cursor->node = NULL;
9074 o->cursor->pos = 0;
9075 EINA_LIST_FOREACH(o->cursors, l, cur)
9076 {
9077 cur->node = NULL;
9078 cur->pos = 0;
9079
9080 }
9081 _evas_textblock_changed(o, obj);
9082}
9083
9084EAPI void
9085evas_object_textblock_size_formatted_get(const Evas_Object *obj, Evas_Coord *w, Evas_Coord *h)
9086{
9087 TB_HEAD();
9088 if (!o->formatted.valid) _relayout(obj);
9089 if (w) *w = o->formatted.w;
9090 if (h) *h = o->formatted.h;
9091}
9092
9093static void
9094_size_native_calc_line_finalize(const Evas_Object *obj, Eina_List *items,
9095 Evas_Coord *ascent, Evas_Coord *descent, Evas_Coord *w)
9096{
9097 Evas_Object_Textblock_Item *it;
9098 Eina_List *i;
9099
9100 it = eina_list_data_get(items);
9101 *w = 0;
9102
9103 if (it)
9104 {
9105 /* If there are no text items yet, calc ascent/descent
9106 * according to the current format. */
9107 if (*ascent + *descent == 0)
9108 _layout_format_ascent_descent_adjust(obj, ascent, descent,
9109 it->format);
9110
9111 /* Add margins. */
9112 if (it->format)
9113 *w = it->format->margin.l + it->format->margin.r;
9114 }
9115
9116
9117 /* Adjust all the item sizes according to the final line size,
9118 * and update the x positions of all the items of the line. */
9119 EINA_LIST_FOREACH(items, i, it)
9120 {
9121 if (it->type == EVAS_TEXTBLOCK_ITEM_FORMAT)
9122 {
9123 Evas_Coord fw, fh, fy;
9124
9125 Evas_Object_Textblock_Format_Item *fi = _ITEM_FORMAT(it);
9126 if (!fi->formatme) goto loop_advance;
9127 _layout_calculate_format_item_size(obj, fi, ascent,
9128 descent, &fy, &fw, &fh);
9129 }
9130
9131loop_advance:
9132 *w += it->adv;
9133 }
9134}
9135
9136/* FIXME: doc */
9137static void
9138_size_native_calc_paragraph_size(const Evas_Object *obj,
9139 const Evas_Object_Textblock *o,
9140 const Evas_Object_Textblock_Paragraph *par,
9141 Evas_Coord *_w, Evas_Coord *_h)
9142{
9143 Eina_List *i;
9144 Evas_Object_Textblock_Item *it;
9145 Eina_List *line_items = NULL;
9146 Evas_Coord w = 0, y = 0, wmax = 0, h = 0, ascent = 0, descent = 0;
9147
9148 EINA_LIST_FOREACH(par->logical_items, i, it)
9149 {
9150 line_items = eina_list_append(line_items, it);
9151 if (it->type == EVAS_TEXTBLOCK_ITEM_FORMAT)
9152 {
9153 Evas_Object_Textblock_Format_Item *fi = _ITEM_FORMAT(it);
9154 if (fi->item && (_IS_LINE_SEPARATOR(fi->item) ||
9155 _IS_PARAGRAPH_SEPARATOR(o, fi->item)))
9156 {
9157 _size_native_calc_line_finalize(obj, line_items, &ascent,
9158 &descent, &w);
9159
9160 if (ascent + descent > h)
9161 h = ascent + descent;
9162
9163 y += h;
9164 if (w > wmax)
9165 wmax = w;
9166 h = 0;
9167 ascent = descent = 0;
9168 line_items = eina_list_free(line_items);
9169 }
9170 else
9171 {
9172 Evas_Coord fw, fh, fy;
9173 /* If there are no text items yet, calc ascent/descent
9174 * according to the current format. */
9175 if (it && (ascent + descent == 0))
9176 _layout_format_ascent_descent_adjust(obj, &ascent,
9177 &descent, it->format);
9178
9179 _layout_calculate_format_item_size(obj, fi, &ascent,
9180 &descent, &fy, &fw, &fh);
9181 }
9182 }
9183 else
9184 {
9185 _layout_format_ascent_descent_adjust(obj, &ascent,
9186 &descent, it->format);
9187 }
9188 }
9189
9190 _size_native_calc_line_finalize(obj, line_items, &ascent, &descent, &w);
9191
9192 line_items = eina_list_free(line_items);
9193
9194 /* Do the last addition */
9195 if (ascent + descent > h)
9196 h = ascent + descent;
9197
9198 if (w > wmax)
9199 wmax = w;
9200
9201 *_h = y + h;
9202 *_w = wmax;
9203}
9204
9205EAPI void
9206evas_object_textblock_size_native_get(const Evas_Object *obj, Evas_Coord *w, Evas_Coord *h)
9207{
9208 TB_HEAD();
9209 if (!o->native.valid)
9210 {
9211 Evas_Coord wmax = 0, hmax = 0;
9212 Evas_Object_Textblock_Paragraph *par;
9213 /* We just want the layout objects to update, should probably
9214 * split that. */
9215 if (!o->formatted.valid) _relayout(obj);
9216 EINA_INLIST_FOREACH(o->paragraphs, par)
9217 {
9218 Evas_Coord tw, th;
9219 _size_native_calc_paragraph_size(obj, o, par, &tw, &th);
9220 if (tw > wmax)
9221 wmax = tw;
9222 hmax += th;
9223 }
9224
9225 o->native.w = wmax;
9226 o->native.h = hmax;
9227
9228 o->native.valid = 1;
9229 o->content_changed = 0;
9230 o->format_changed = EINA_FALSE;
9231 }
9232 if (w) *w = o->native.w;
9233 if (h) *h = o->native.h;
9234}
9235
9236EAPI void
9237evas_object_textblock_style_insets_get(const Evas_Object *obj, Evas_Coord *l, Evas_Coord *r, Evas_Coord *t, Evas_Coord *b)
9238{
9239 TB_HEAD();
9240 if (!o->formatted.valid) _relayout(obj);
9241 if (l) *l = o->style_pad.l;
9242 if (r) *r = o->style_pad.r;
9243 if (t) *t = o->style_pad.t;
9244 if (b) *b = o->style_pad.b;
9245}
9246
9247/** @internal
9248 * FIXME: DELETE ME! DELETE ME!
9249 * This is an ugly workaround to get around the fact that
9250 * evas_object_textblock_coords_recalc isn't really called when it's supposed
9251 * to. When that bug is fixed please remove this. */
9252static void
9253_workaround_object_coords_recalc(void *data __UNUSED__, Evas *e __UNUSED__, Evas_Object *obj, void *event_info __UNUSED__)
9254{
9255 evas_object_textblock_coords_recalc(obj);
9256}
9257
9258/* all nice and private */
9259static void
9260evas_object_textblock_init(Evas_Object *obj)
9261{
9262 Evas_Object_Textblock *o;
9263#ifdef HAVE_LINEBREAK
9264 static Eina_Bool linebreak_init = EINA_FALSE;
9265 if (!linebreak_init)
9266 {
9267 linebreak_init = EINA_TRUE;
9268 init_linebreak();
9269 init_wordbreak();
9270 }
9271#endif
9272
9273 /* alloc image ob, setup methods and default values */
9274 obj->object_data = evas_object_textblock_new();
9275 /* set up default settings for this kind of object */
9276 obj->cur.color.r = 255;
9277 obj->cur.color.g = 255;
9278 obj->cur.color.b = 255;
9279 obj->cur.color.a = 255;
9280 obj->cur.geometry.x = 0.0;
9281 obj->cur.geometry.y = 0.0;
9282 obj->cur.geometry.w = 0.0;
9283 obj->cur.geometry.h = 0.0;
9284 obj->cur.layer = 0;
9285 /* set up object-specific settings */
9286 obj->prev = obj->cur;
9287 /* set up methods (compulsory) */
9288 obj->func = &object_func;
9289 obj->type = o_type;
9290
9291 o = (Evas_Object_Textblock *)(obj->object_data);
9292 o->cursor->obj = obj;
9293 o->legacy_newline = EINA_TRUE;
9294 evas_object_event_callback_priority_add(obj, EVAS_CALLBACK_RESIZE, -1000,
9295 _workaround_object_coords_recalc, NULL);
9296}
9297
9298static void *
9299evas_object_textblock_new(void)
9300{
9301 Evas_Object_Textblock *o;
9302
9303 /* alloc obj private data */
9304 EVAS_MEMPOOL_INIT(_mp_obj, "evas_object_textblock", Evas_Object_Textblock, 64, NULL);
9305 o = EVAS_MEMPOOL_ALLOC(_mp_obj, Evas_Object_Textblock);
9306 if (!o) return NULL;
9307 EVAS_MEMPOOL_PREP(_mp_obj, o, Evas_Object_Textblock);
9308 o->magic = MAGIC_OBJ_TEXTBLOCK;
9309 o->cursor = calloc(1, sizeof(Evas_Textblock_Cursor));
9310 _format_command_init();
9311 return o;
9312}
9313
9314static void
9315evas_object_textblock_free(Evas_Object *obj)
9316{
9317 Evas_Object_Textblock *o;
9318
9319 evas_object_textblock_clear(obj);
9320 evas_object_textblock_style_set(obj, NULL);
9321 while (evas_object_textblock_style_user_peek(obj))
9322 {
9323 evas_object_textblock_style_user_pop(obj);
9324 }
9325 o = (Evas_Object_Textblock *)(obj->object_data);
9326 free(o->cursor);
9327 while (o->cursors)
9328 {
9329 Evas_Textblock_Cursor *cur;
9330
9331 cur = (Evas_Textblock_Cursor *)o->cursors->data;
9332 o->cursors = eina_list_remove_list(o->cursors, o->cursors);
9333 free(cur);
9334 }
9335 if (o->repch) eina_stringshare_del(o->repch);
9336 if (o->ellip_ti) _item_free(obj, NULL, _ITEM(o->ellip_ti));
9337 o->magic = 0;
9338 EVAS_MEMPOOL_FREE(_mp_obj, o);
9339 _format_command_shutdown();
9340}
9341
9342
9343static void
9344evas_object_textblock_render(Evas_Object *obj, void *output, void *context, void *surface, int x, int y)
9345{
9346 Evas_Object_Textblock_Paragraph *par, *start = NULL;
9347 Evas_Object_Textblock_Line *ln;
9348 Evas_Object_Textblock *o;
9349 int i, j;
9350 int cx, cy, cw, ch, clip;
9351 const char vals[5][5] =
9352 {
9353 {0, 1, 2, 1, 0},
9354 {1, 3, 4, 3, 1},
9355 {2, 4, 5, 4, 2},
9356 {1, 3, 4, 3, 1},
9357 {0, 1, 2, 1, 0}
9358 };
9359
9360 /* render object to surface with context, and offxet by x,y */
9361 o = (Evas_Object_Textblock *)(obj->object_data);
9362 obj->layer->evas->engine.func->context_multiplier_unset(output,
9363 context);
9364 /* FIXME: This clipping is just until we fix inset handling correctly. */
9365 ENFN->context_clip_clip(output, context,
9366 obj->cur.geometry.x + x,
9367 obj->cur.geometry.y + y,
9368 obj->cur.geometry.w,
9369 obj->cur.geometry.h);
9370 clip = ENFN->context_clip_get(output, context, &cx, &cy, &cw, &ch);
9371 /* If there are no paragraphs and thus there are no lines,
9372 * there's nothing left to do. */
9373 if (!o->paragraphs) return;
9374
9375#define ITEM_WALK() \
9376 EINA_INLIST_FOREACH(start, par) \
9377 { \
9378 if (!par->visible) continue; \
9379 if (clip) \
9380 { \
9381 if ((obj->cur.geometry.y + y + par->y + par->h) < (cy - 20)) \
9382 continue; \
9383 if ((obj->cur.geometry.y + y + par->y) > (cy + ch + 20)) \
9384 break; \
9385 } \
9386 _layout_paragraph_render(o, par); \
9387 EINA_INLIST_FOREACH(par->lines, ln) \
9388 { \
9389 Evas_Object_Textblock_Item *itr; \
9390 \
9391 if (clip) \
9392 { \
9393 if ((obj->cur.geometry.y + y + par->y + ln->y + ln->h) < (cy - 20)) \
9394 continue; \
9395 if ((obj->cur.geometry.y + y + par->y + ln->y) > (cy + ch + 20)) \
9396 break; \
9397 } \
9398 EINA_INLIST_FOREACH(ln->items, itr) \
9399 { \
9400 Evas_Coord yoff; \
9401 yoff = ln->baseline; \
9402 if (itr->format->valign != -1.0) \
9403 { \
9404 yoff += itr->format->valign * (ln->h - itr->h); \
9405 } \
9406 if (clip) \
9407 { \
9408 if ((obj->cur.geometry.x + x + ln->x + itr->x + itr->w) < (cx - 20)) \
9409 continue; \
9410 if ((obj->cur.geometry.x + x + ln->x + itr->x) > (cx + cw + 20)) \
9411 break; \
9412 } \
9413 if ((ln->x + itr->x + itr->w) <= 0) continue; \
9414 if (ln->x + itr->x > obj->cur.geometry.w) break; \
9415 do
9416
9417#define ITEM_WALK_END() \
9418 while (0); \
9419 } \
9420 } \
9421 } \
9422 do {} while(0)
9423#define COLOR_SET(col) \
9424 ENFN->context_color_set(output, context, \
9425 (obj->cur.cache.clip.r * ti->parent.format->color.col.r) / 255, \
9426 (obj->cur.cache.clip.g * ti->parent.format->color.col.g) / 255, \
9427 (obj->cur.cache.clip.b * ti->parent.format->color.col.b) / 255, \
9428 (obj->cur.cache.clip.a * ti->parent.format->color.col.a) / 255);
9429#define COLOR_SET_AMUL(col, amul) \
9430 ENFN->context_color_set(output, context, \
9431 (obj->cur.cache.clip.r * ti->parent.format->color.col.r * (amul)) / 65025, \
9432 (obj->cur.cache.clip.g * ti->parent.format->color.col.g * (amul)) / 65025, \
9433 (obj->cur.cache.clip.b * ti->parent.format->color.col.b * (amul)) / 65025, \
9434 (obj->cur.cache.clip.a * ti->parent.format->color.col.a * (amul)) / 65025);
9435#define DRAW_TEXT(ox, oy) \
9436 if (ti->parent.format->font.font) ENFN->font_draw(output, context, surface, ti->parent.format->font.font, \
9437 obj->cur.geometry.x + ln->x + ti->parent.x + x + (ox), \
9438 obj->cur.geometry.y + ln->par->y + ln->y + yoff + y + (oy), \
9439 ti->parent.w, ti->parent.h, ti->parent.w, ti->parent.h, \
9440 &ti->text_props);
9441
9442 /* backing */
9443#define DRAW_RECT(ox, oy, ow, oh, or, og, ob, oa) \
9444 do \
9445 { \
9446 ENFN->context_color_set(output, \
9447 context, \
9448 (obj->cur.cache.clip.r * or) / 255, \
9449 (obj->cur.cache.clip.g * og) / 255, \
9450 (obj->cur.cache.clip.b * ob) / 255, \
9451 (obj->cur.cache.clip.a * oa) / 255); \
9452 ENFN->rectangle_draw(output, \
9453 context, \
9454 surface, \
9455 obj->cur.geometry.x + ln->x + x + (ox), \
9456 obj->cur.geometry.y + ln->par->y + ln->y + y + (oy), \
9457 (ow), \
9458 (oh)); \
9459 } \
9460 while (0)
9461
9462#define DRAW_FORMAT_DASHED(oname, oy, oh, dw, dp) \
9463 do \
9464 { \
9465 if (itr->format->oname) \
9466 { \
9467 unsigned char _or, _og, _ob, _oa; \
9468 int _ind, _dx = 0, _dn, _dr; \
9469 _or = itr->format->color.oname.r; \
9470 _og = itr->format->color.oname.g; \
9471 _ob = itr->format->color.oname.b; \
9472 _oa = itr->format->color.oname.a; \
9473 if (!EINA_INLIST_GET(itr)->next) \
9474 { \
9475 _dn = itr->w / (dw + dp); \
9476 _dr = itr->w % (dw + dp); \
9477 } \
9478 else \
9479 { \
9480 _dn = itr->adv / (dw + dp); \
9481 _dr = itr->adv % (dw + dp); \
9482 } \
9483 if (_dr > dw) _dr = dw; \
9484 for (_ind = 0 ; _ind < _dn ; _ind++) \
9485 { \
9486 DRAW_RECT(itr->x + _dx, oy, dw, oh, _or, _og, _ob, _oa); \
9487 _dx += dw + dp; \
9488 } \
9489 DRAW_RECT(itr->x + _dx, oy, _dr, oh, _or, _og, _ob, _oa); \
9490 } \
9491 } \
9492 while (0)
9493
9494#define DRAW_FORMAT(oname, oy, oh) \
9495 do \
9496 { \
9497 if (itr->format->oname) \
9498 { \
9499 unsigned char _or, _og, _ob, _oa; \
9500 _or = itr->format->color.oname.r; \
9501 _og = itr->format->color.oname.g; \
9502 _ob = itr->format->color.oname.b; \
9503 _oa = itr->format->color.oname.a; \
9504 if (!EINA_INLIST_GET(itr)->next) \
9505 { \
9506 DRAW_RECT(itr->x, oy, itr->w, oh, _or, _og, _ob, _oa); \
9507 } \
9508 else \
9509 { \
9510 DRAW_RECT(itr->x, oy, itr->adv, oh, _or, _og, _ob, _oa); \
9511 } \
9512 } \
9513 } \
9514 while (0)
9515
9516 {
9517 Evas_Coord look_for_y = 0 - (obj->cur.geometry.y + y);
9518 if (clip)
9519 {
9520 Evas_Coord tmp_lfy = cy - (obj->cur.geometry.y + y);
9521 if (tmp_lfy > look_for_y)
9522 look_for_y = tmp_lfy;
9523 }
9524
9525 if (look_for_y >= 0)
9526 start = _layout_find_paragraph_by_y(o, look_for_y);
9527
9528 if (!start)
9529 start = o->paragraphs;
9530 }
9531
9532 ITEM_WALK()
9533 {
9534 DRAW_FORMAT(backing, 0, ln->h);
9535 }
9536 ITEM_WALK_END();
9537
9538 /* There are size adjustments that depend on the styles drawn here back
9539 * in "_text_item_update_sizes" should not modify one without the other. */
9540
9541 /* prepare everything for text draw */
9542
9543 /* shadows */
9544 ITEM_WALK()
9545 {
9546 int shad_dst, shad_sz, dx, dy, haveshad;
9547 Evas_Object_Textblock_Text_Item *ti;
9548 ti = (itr->type == EVAS_TEXTBLOCK_ITEM_TEXT) ? _ITEM_TEXT(itr) : NULL;
9549 if (!ti) continue;
9550
9551 shad_dst = shad_sz = dx = dy = haveshad = 0;
9552 switch (ti->parent.format->style & EVAS_TEXT_STYLE_MASK_BASIC)
9553 {
9554 case EVAS_TEXT_STYLE_SHADOW:
9555 case EVAS_TEXT_STYLE_OUTLINE_SOFT_SHADOW:
9556 shad_dst = 1;
9557 haveshad = 1;
9558 break;
9559 case EVAS_TEXT_STYLE_OUTLINE_SHADOW:
9560 case EVAS_TEXT_STYLE_FAR_SHADOW:
9561 shad_dst = 2;
9562 haveshad = 1;
9563 break;
9564 case EVAS_TEXT_STYLE_FAR_SOFT_SHADOW:
9565 shad_dst = 2;
9566 shad_sz = 2;
9567 haveshad = 1;
9568 break;
9569 case EVAS_TEXT_STYLE_SOFT_SHADOW:
9570 shad_dst = 1;
9571 shad_sz = 2;
9572 haveshad = 1;
9573 break;
9574 default:
9575 break;
9576 }
9577 if (haveshad)
9578 {
9579 if (shad_dst > 0)
9580 {
9581 switch (ti->parent.format->style & EVAS_TEXT_STYLE_MASK_SHADOW_DIRECTION)
9582 {
9583 case EVAS_TEXT_STYLE_SHADOW_DIRECTION_BOTTOM_RIGHT:
9584 dx = 1;
9585 dy = 1;
9586 break;
9587 case EVAS_TEXT_STYLE_SHADOW_DIRECTION_BOTTOM:
9588 dx = 0;
9589 dy = 1;
9590 break;
9591 case EVAS_TEXT_STYLE_SHADOW_DIRECTION_BOTTOM_LEFT:
9592 dx = -1;
9593 dy = 1;
9594 break;
9595 case EVAS_TEXT_STYLE_SHADOW_DIRECTION_LEFT:
9596 dx = -1;
9597 dy = 0;
9598 break;
9599 case EVAS_TEXT_STYLE_SHADOW_DIRECTION_TOP_LEFT:
9600 dx = -1;
9601 dy = -1;
9602 break;
9603 case EVAS_TEXT_STYLE_SHADOW_DIRECTION_TOP:
9604 dx = 0;
9605 dy = -1;
9606 break;
9607 case EVAS_TEXT_STYLE_SHADOW_DIRECTION_TOP_RIGHT:
9608 dx = 1;
9609 dy = -1;
9610 break;
9611 case EVAS_TEXT_STYLE_SHADOW_DIRECTION_RIGHT:
9612 dx = 1;
9613 dy = 0;
9614 default:
9615 break;
9616 }
9617 dx *= shad_dst;
9618 dy *= shad_dst;
9619 }
9620 switch (shad_sz)
9621 {
9622 case 0:
9623 COLOR_SET(shadow);
9624 DRAW_TEXT(dx, dy);
9625 break;
9626 case 2:
9627 for (j = 0; j < 5; j++)
9628 {
9629 for (i = 0; i < 5; i++)
9630 {
9631 if (vals[i][j] != 0)
9632 {
9633 COLOR_SET_AMUL(shadow, vals[i][j] * 50);
9634 DRAW_TEXT(i - 2 + dx, j - 2 + dy);
9635 }
9636 }
9637 }
9638 break;
9639 default:
9640 break;
9641 }
9642 }
9643 }
9644 ITEM_WALK_END();
9645
9646 /* glows */
9647 ITEM_WALK()
9648 {
9649 Evas_Object_Textblock_Text_Item *ti;
9650 ti = (itr->type == EVAS_TEXTBLOCK_ITEM_TEXT) ? _ITEM_TEXT(itr) : NULL;
9651 if (!ti) continue;
9652
9653 if (ti->parent.format->style == EVAS_TEXT_STYLE_GLOW)
9654 {
9655 for (j = 0; j < 5; j++)
9656 {
9657 for (i = 0; i < 5; i++)
9658 {
9659 if (vals[i][j] != 0)
9660 {
9661 COLOR_SET_AMUL(glow, vals[i][j] * 50);
9662 DRAW_TEXT(i - 2, j - 2);
9663 }
9664 }
9665 }
9666 COLOR_SET(glow2);
9667 DRAW_TEXT(-1, 0);
9668 DRAW_TEXT(1, 0);
9669 DRAW_TEXT(0, -1);
9670 DRAW_TEXT(0, 1);
9671 }
9672 }
9673 ITEM_WALK_END();
9674
9675 /* outlines */
9676 ITEM_WALK()
9677 {
9678 Evas_Object_Textblock_Text_Item *ti;
9679 ti = (itr->type == EVAS_TEXTBLOCK_ITEM_TEXT) ? _ITEM_TEXT(itr) : NULL;
9680 if (!ti) continue;
9681
9682 if ((ti->parent.format->style == EVAS_TEXT_STYLE_OUTLINE) ||
9683 (ti->parent.format->style == EVAS_TEXT_STYLE_OUTLINE_SHADOW) ||
9684 (ti->parent.format->style == EVAS_TEXT_STYLE_OUTLINE_SOFT_SHADOW))
9685 {
9686 COLOR_SET(outline);
9687 DRAW_TEXT(-1, 0);
9688 DRAW_TEXT(1, 0);
9689 DRAW_TEXT(0, -1);
9690 DRAW_TEXT(0, 1);
9691 }
9692 else if (ti->parent.format->style == EVAS_TEXT_STYLE_SOFT_OUTLINE)
9693 {
9694 for (j = 0; j < 5; j++)
9695 {
9696 for (i = 0; i < 5; i++)
9697 {
9698 if (((i != 2) || (j != 2)) && (vals[i][j] != 0))
9699 {
9700 COLOR_SET_AMUL(outline, vals[i][j] * 50);
9701 DRAW_TEXT(i - 2, j - 2);
9702 }
9703 }
9704 }
9705 }
9706 }
9707 ITEM_WALK_END();
9708
9709 /* normal text and lines */
9710 ITEM_WALK()
9711 {
9712 Evas_Object_Textblock_Text_Item *ti;
9713 ti = (itr->type == EVAS_TEXTBLOCK_ITEM_TEXT) ? _ITEM_TEXT(itr) : NULL;
9714 /* NORMAL TEXT */
9715 if (ti)
9716 {
9717 COLOR_SET(normal);
9718 DRAW_TEXT(0, 0);
9719 }
9720
9721 /* STRIKETHROUGH */
9722 DRAW_FORMAT(strikethrough, (ln->h / 2), 1);
9723
9724 /* UNDERLINE */
9725 DRAW_FORMAT(underline, ln->baseline + 1, 1);
9726
9727 /* UNDERLINE DASHED */
9728 DRAW_FORMAT_DASHED(underline_dash, ln->baseline + 1, 1,
9729 ti->parent.format->underline_dash_width,
9730 ti->parent.format->underline_dash_gap);
9731
9732 /* UNDERLINE2 */
9733 DRAW_FORMAT(underline2, ln->baseline + 3, 1);
9734 }
9735 ITEM_WALK_END();
9736}
9737
9738static void
9739evas_object_textblock_render_pre(Evas_Object *obj)
9740{
9741 Evas_Object_Textblock *o;
9742 int is_v, was_v;
9743
9744 /* dont pre-render the obj twice! */
9745 if (obj->pre_render_done) return;
9746 obj->pre_render_done = 1;
9747 /* pre-render phase. this does anything an object needs to do just before */
9748 /* rendering. this could mean loading the image data, retrieving it from */
9749 /* elsewhere, decoding video etc. */
9750 /* then when this is done the object needs to figure if it changed and */
9751 /* if so what and where and add the appropriate redraw textblocks */
9752 o = (Evas_Object_Textblock *)(obj->object_data);
9753 if ((o->changed) || (o->content_changed) || (o->format_changed) ||
9754 ((obj->cur.geometry.w != o->last_w) ||
9755 (((o->valign != 0.0) || (o->have_ellipsis)) &&
9756 (obj->cur.geometry.h != o->last_h))))
9757 {
9758 _relayout(obj);
9759 o->redraw = 0;
9760 evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes, obj);
9761 is_v = evas_object_is_visible(obj);
9762 was_v = evas_object_was_visible(obj);
9763 goto done;
9764 }
9765 if (o->redraw)
9766 {
9767 o->redraw = 0;
9768 evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes, obj);
9769 is_v = evas_object_is_visible(obj);
9770 was_v = evas_object_was_visible(obj);
9771 goto done;
9772 }
9773 /* if someone is clipping this obj - go calculate the clipper */
9774 if (obj->cur.clipper)
9775 {
9776 if (obj->cur.cache.clip.dirty)
9777 evas_object_clip_recalc(obj->cur.clipper);
9778 obj->cur.clipper->func->render_pre(obj->cur.clipper);
9779 }
9780 /* now figure what changed and add draw rects */
9781 /* if it just became visible or invisible */
9782 is_v = evas_object_is_visible(obj);
9783 was_v = evas_object_was_visible(obj);
9784 if (is_v != was_v)
9785 {
9786 evas_object_render_pre_visible_change(&obj->layer->evas->clip_changes, obj, is_v, was_v);
9787 goto done;
9788 }
9789 if ((obj->cur.map != obj->prev.map) ||
9790 (obj->cur.usemap != obj->prev.usemap))
9791 {
9792 evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes, obj);
9793 goto done;
9794 }
9795 /* it's not visible - we accounted for it appearing or not so just abort */
9796 if (!is_v) goto done;
9797 /* clipper changed this is in addition to anything else for obj */
9798 evas_object_render_pre_clipper_change(&obj->layer->evas->clip_changes, obj);
9799 /* if we restacked (layer or just within a layer) and don't clip anyone */
9800 if (obj->restack)
9801 {
9802 evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes, obj);
9803 goto done;
9804 }
9805 /* if it changed color */
9806 if ((obj->cur.color.r != obj->prev.color.r) ||
9807 (obj->cur.color.g != obj->prev.color.g) ||
9808 (obj->cur.color.b != obj->prev.color.b) ||
9809 (obj->cur.color.a != obj->prev.color.a))
9810 {
9811 evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes, obj);
9812 goto done;
9813 }
9814 /* if it changed geometry - and obviously not visibility or color */
9815 /* calculate differences since we have a constant color fill */
9816 /* we really only need to update the differences */
9817 if ((obj->cur.geometry.x != obj->prev.geometry.x) ||
9818 (obj->cur.geometry.y != obj->prev.geometry.y) ||
9819 (obj->cur.geometry.w != obj->prev.geometry.w) ||
9820 (obj->cur.geometry.h != obj->prev.geometry.h))
9821 {
9822 evas_object_render_pre_prev_cur_add(&obj->layer->evas->clip_changes, obj);
9823 goto done;
9824 }
9825 done:
9826 evas_object_render_pre_effect_updates(&obj->layer->evas->clip_changes, obj, is_v, was_v);
9827}
9828
9829static void
9830evas_object_textblock_render_post(Evas_Object *obj)
9831{
9832/* Evas_Object_Textblock *o; */
9833
9834 /* this moves the current data to the previous state parts of the object */
9835 /* in whatever way is safest for the object. also if we don't need object */
9836 /* data anymore we can free it if the object deems this is a good idea */
9837/* o = (Evas_Object_Textblock *)(obj->object_data); */
9838 /* remove those pesky changes */
9839 evas_object_clip_changes_clean(obj);
9840 /* move cur to prev safely for object data */
9841 obj->prev = obj->cur;
9842/* o->prev = o->cur; */
9843/* o->changed = 0; */
9844}
9845
9846static unsigned int evas_object_textblock_id_get(Evas_Object *obj)
9847{
9848 Evas_Object_Textblock *o;
9849
9850 o = (Evas_Object_Textblock *)(obj->object_data);
9851 if (!o) return 0;
9852 return MAGIC_OBJ_TEXTBLOCK;
9853}
9854
9855static unsigned int evas_object_textblock_visual_id_get(Evas_Object *obj)
9856{
9857 Evas_Object_Textblock *o;
9858
9859 o = (Evas_Object_Textblock *)(obj->object_data);
9860 if (!o) return 0;
9861 return MAGIC_OBJ_CUSTOM;
9862}
9863
9864static void *evas_object_textblock_engine_data_get(Evas_Object *obj)
9865{
9866 Evas_Object_Textblock *o;
9867
9868 o = (Evas_Object_Textblock *)(obj->object_data);
9869 if (!o) return NULL;
9870 return o->engine_data;
9871}
9872
9873static int
9874evas_object_textblock_is_opaque(Evas_Object *obj __UNUSED__)
9875{
9876 /* this returns 1 if the internal object data implies that the object is */
9877 /* currently fulyl opque over the entire gradient it occupies */
9878 return 0;
9879}
9880
9881static int
9882evas_object_textblock_was_opaque(Evas_Object *obj __UNUSED__)
9883{
9884 /* this returns 1 if the internal object data implies that the object was */
9885 /* currently fulyl opque over the entire gradient it occupies */
9886 return 0;
9887}
9888
9889static void
9890evas_object_textblock_coords_recalc(Evas_Object *obj)
9891{
9892 Evas_Object_Textblock *o;
9893
9894 o = (Evas_Object_Textblock *)(obj->object_data);
9895 if ((obj->cur.geometry.w != o->last_w) ||
9896 (((o->valign != 0.0) || (o->have_ellipsis)) &&
9897 (obj->cur.geometry.h != o->last_h)))
9898 {
9899 o->formatted.valid = 0;
9900 o->changed = 1;
9901 }
9902}
9903
9904static void
9905evas_object_textblock_scale_update(Evas_Object *obj)
9906{
9907 Evas_Object_Textblock *o;
9908
9909 o = (Evas_Object_Textblock *)(obj->object_data);
9910 _evas_textblock_invalidate_all(o);
9911 _evas_textblock_changed(o, obj);
9912}
9913
9914void
9915_evas_object_textblock_rehint(Evas_Object *obj)
9916{
9917 Evas_Object_Textblock *o;
9918 Evas_Object_Textblock_Paragraph *par;
9919 Evas_Object_Textblock_Line *ln;
9920
9921 o = (Evas_Object_Textblock *)(obj->object_data);
9922 EINA_INLIST_FOREACH(o->paragraphs, par)
9923 {
9924 EINA_INLIST_FOREACH(par->lines, ln)
9925 {
9926 Evas_Object_Textblock_Item *it;
9927
9928 EINA_INLIST_FOREACH(ln->items, it)
9929 {
9930 if (it->type == EVAS_TEXTBLOCK_ITEM_TEXT)
9931 {
9932 Evas_Object_Textblock_Text_Item *ti = _ITEM_TEXT(it);
9933 if (ti->parent.format->font.font)
9934 {
9935#ifdef EVAS_FRAME_QUEUING
9936 evas_common_pipe_op_text_flush((RGBA_Font *) ti->parent.format->font.font);
9937#endif
9938 evas_font_load_hinting_set(obj->layer->evas,
9939 ti->parent.format->font.font,
9940 obj->layer->evas->hinting);
9941 }
9942 }
9943 }
9944 }
9945 }
9946 _evas_textblock_invalidate_all(o);
9947 _evas_textblock_changed(o, obj);
9948}
9949
9950/**
9951 * @}
9952 */
9953
9954#ifdef HAVE_TESTS
9955/* return EINA_FALSE on error, used in unit_testing */
9956EAPI Eina_Bool
9957_evas_textblock_check_item_node_link(Evas_Object *obj)
9958{
9959 Evas_Object_Textblock *o;
9960 Evas_Object_Textblock_Paragraph *par;
9961 Evas_Object_Textblock_Line *ln;
9962 Evas_Object_Textblock_Item *it;
9963
9964 o = (Evas_Object_Textblock *)(obj->object_data);
9965 if (!o) return EINA_FALSE;
9966
9967 if (!o->formatted.valid) _relayout(obj);
9968
9969 EINA_INLIST_FOREACH(o->paragraphs, par)
9970 {
9971 EINA_INLIST_FOREACH(par->lines, ln)
9972 {
9973 EINA_INLIST_FOREACH(ln->items, it)
9974 {
9975 if (it->text_node != par->text_node)
9976 return EINA_FALSE;
9977 }
9978 }
9979 }
9980 return EINA_TRUE;
9981}
9982
9983EAPI int
9984_evas_textblock_format_offset_get(const Evas_Object_Textblock_Node_Format *n)
9985{
9986 return n->offset;
9987}
9988#endif
9989
9990#if 0
9991/* Good for debugging */
9992void
9993pfnode(Evas_Object_Textblock_Node_Format *n)
9994{
9995 printf("Format Node: %p\n", n);
9996 printf("next = %p, prev = %p, last = %p\n", EINA_INLIST_GET(n)->next, EINA_INLIST_GET(n)->prev, EINA_INLIST_GET(n)->last);
9997 printf("text_node = %p, offset = %u, visible = %d\n", n->text_node, n->offset, n->visible);
9998 printf("'%s'\n", eina_strbuf_string_get(n->format));
9999}
10000
10001void
10002ptnode(Evas_Object_Textblock_Node_Text *n)
10003{
10004 printf("Text Node: %p\n", n);
10005 printf("next = %p, prev = %p, last = %p\n", EINA_INLIST_GET(n)->next, EINA_INLIST_GET(n)->prev, EINA_INLIST_GET(n)->last);
10006 printf("format_node = %p\n", n->format_node);
10007 printf("'%ls'\n", eina_ustrbuf_string_get(n->unicode));
10008}
10009
10010void
10011pitem(Evas_Object_Textblock_Item *it)
10012{
10013 Evas_Object_Textblock_Text_Item *ti;
10014 Evas_Object_Textblock_Format_Item *fi;
10015 printf("Item: %p\n", it);
10016 printf("Type: %s (%d)\n", (it->type == EVAS_TEXTBLOCK_ITEM_TEXT) ?
10017 "TEXT" : "FORMAT", it->type);
10018 printf("Text pos: %d Visual pos: %d\n", it->text_pos,
10019#ifdef BIDI_SUPPORT
10020 it->visual_pos
10021#else
10022 it->text_pos
10023#endif
10024 );
10025 printf("Coords: x = %d w = %d adv = %d\n", (int) it->x, (int) it->w,
10026 (int) it->adv);
10027 if (it->type == EVAS_TEXTBLOCK_ITEM_TEXT)
10028 {
10029 ti = _ITEM_TEXT(it);
10030 printf("Text: '%*ls'\n", ti->text_props.text_len, GET_ITEM_TEXT(ti));
10031 }
10032 else
10033 {
10034 fi = _ITEM_FORMAT(it);
10035 printf("Format: '%s'\n", fi->item);
10036 }
10037}
10038
10039void
10040ppar(Evas_Object_Textblock_Paragraph *par)
10041{
10042 Evas_Object_Textblock_Item *it;
10043 Eina_List *i;
10044 EINA_LIST_FOREACH(par->logical_items, i, it)
10045 {
10046 printf("***********************\n");
10047 pitem(it);
10048 }
10049}
10050
10051#endif
10052
diff --git a/libraries/evas/src/lib/canvas/evas_rectangle.c b/libraries/evas/src/lib/canvas/evas_rectangle.c
deleted file mode 100644
index da6b701..0000000
--- a/libraries/evas/src/lib/canvas/evas_rectangle.c
+++ /dev/null
@@ -1,98 +0,0 @@
1#include "evas_common.h"
2#include "evas_private.h"
3
4void
5evas_rects_return_difference_rects(Eina_Array *rects, int x, int y, int w, int h, int xx, int yy, int ww, int hh)
6{
7 if (!RECTS_INTERSECT(x, y, w, h, xx, yy, ww, hh))
8 {
9 evas_add_rect(rects, x, y, w, h);
10 evas_add_rect(rects, xx, yy, ww, hh);
11 }
12 else
13 {
14 int pt_x[4], pt_y[4], i, j;
15
16 if (x < xx)
17 {
18 pt_x[0] = x;
19 pt_x[1] = xx;
20 }
21 else
22 {
23 pt_x[0] = xx;
24 pt_x[1] = x;
25 }
26 if ((x + w) < (xx + ww))
27 {
28 pt_x[2] = x + w;
29 pt_x[3] = xx + ww;
30 }
31 else
32 {
33 pt_x[2] = xx + ww;
34 pt_x[3] = x + w;
35 }
36 if (y < yy)
37 {
38 pt_y[0] = y;
39 pt_y[1] = yy;
40 }
41 else
42 {
43 pt_y[0] = yy;
44 pt_y[1] = y;
45 }
46 if ((y + h) < (yy + hh))
47 {
48 pt_y[2] = y + h;
49 pt_y[3] = yy + hh;
50 }
51 else
52 {
53 pt_y[2] = yy + hh;
54 pt_y[3] = y + h;
55 }
56 for (j = 0; j < 3; j++)
57 {
58 for (i = 0; i < 3; i++)
59 {
60 int intsec1, intsec2;
61 int tx, ty, tw, th;
62
63 tx = pt_x[i];
64 ty = pt_y[j];
65 tw = pt_x[i + 1] - pt_x[i];
66 th = pt_y[j + 1] - pt_y[j];
67
68 intsec1 = (RECTS_INTERSECT(tx, ty, tw, th, x, y, w, h));
69 intsec2 = (RECTS_INTERSECT(tx, ty, tw, th, xx, yy, ww, hh));
70 if (intsec1 ^ intsec2)
71 {
72 evas_add_rect(rects, tx, ty, tw, th);
73 }
74 }
75 }
76/* if (tmp.count > 0) */
77/* { */
78/* unsigned int i; */
79
80/* for (i = 0; i < tmp.count; ++i) */
81/* { */
82/* if ((tmp.array[i].w > 0) && (tmp.array[i].h > 0)) */
83/* { */
84/* int intsec1, intsec2; */
85
86/* intsec1 = (RECTS_INTERSECT(tmp.array[i].x, tmp.array[i].y, tmp.array[i].w, tmp.array[i].h, x, y, w, h)); */
87/* intsec2 = (RECTS_INTERSECT(tmp.array[i].x, tmp.array[i].y, tmp.array[i].w, tmp.array[i].h, xx, yy, ww, hh)); */
88/* if (intsec1 ^ intsec2) */
89/* { */
90/* evas_add_rect(rects, tmp.array[i].x, tmp.array[i].y, tmp.array[i].w, tmp.array[i].h); */
91/* } */
92/* } */
93/* } */
94/* free(tmp.array); */
95/* } */
96
97 }
98}
diff --git a/libraries/evas/src/lib/canvas/evas_render.c b/libraries/evas/src/lib/canvas/evas_render.c
deleted file mode 100644
index 32ce988..0000000
--- a/libraries/evas/src/lib/canvas/evas_render.c
+++ /dev/null
@@ -1,1914 +0,0 @@
1#include "evas_common.h"
2#include "evas_private.h"
3#include <math.h>
4
5// debug rendering
6/* #define REND_DGB 1 */
7/* #define STDOUT_DBG 1 */
8
9#ifdef REND_DGB
10static FILE *dbf = NULL;
11
12static void
13rend_dbg(const char *txt)
14{
15 if (!dbf)
16 {
17#ifdef STDOUT_DBG
18 dbf = stdout;
19#else
20 dbf = fopen("EVAS-RENDER-DEBUG.log", "w");
21#endif
22 if (!dbf) return;
23 }
24 fputs(txt, dbf);
25 fflush(dbf);
26}
27#define RD(args...) \
28 { \
29 char __tmpbuf[4096]; \
30 \
31 snprintf(__tmpbuf, sizeof(__tmpbuf), ##args); \
32 rend_dbg(__tmpbuf); \
33 }
34#define RDI(xxxx) \
35 { \
36 char __tmpbuf[4096]; int __tmpi; \
37 for (__tmpi = 0; __tmpi < xxxx; __tmpi++) \
38 __tmpbuf[__tmpi] = ' '; \
39 __tmpbuf[__tmpi] = 0; \
40 rend_dbg(__tmpbuf); \
41 }
42#else
43#define RD(args...)
44#define RDI(x)
45#endif
46
47static Eina_List *
48evas_render_updates_internal(Evas *e, unsigned char make_updates, unsigned char do_draw);
49
50EAPI void
51evas_damage_rectangle_add(Evas *e, int x, int y, int w, int h)
52{
53 Eina_Rectangle *r;
54
55 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
56 return;
57 MAGIC_CHECK_END();
58 NEW_RECT(r, x, y, w, h);
59 if (!r) return;
60 e->damages = eina_list_append(e->damages, r);
61 e->changed = 1;
62}
63
64EAPI void
65evas_obscured_rectangle_add(Evas *e, int x, int y, int w, int h)
66{
67 Eina_Rectangle *r;
68
69 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
70 return;
71 MAGIC_CHECK_END();
72 NEW_RECT(r, x, y, w, h);
73 if (!r) return;
74 e->obscures = eina_list_append(e->obscures, r);
75}
76
77EAPI void
78evas_obscured_clear(Evas *e)
79{
80 Eina_Rectangle *r;
81
82 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
83 return;
84 MAGIC_CHECK_END();
85 EINA_LIST_FREE(e->obscures, r)
86 {
87 eina_rectangle_free(r);
88 }
89}
90
91static Eina_Bool
92_evas_render_has_map(Evas_Object *obj)
93{
94 return ((!((obj->func->can_map) && (obj->func->can_map(obj)))) &&
95 ((obj->cur.map) && (obj->cur.usemap)));
96 // return ((obj->cur.map) && (obj->cur.usemap));
97}
98
99static Eina_Bool
100_evas_render_had_map(Evas_Object *obj)
101{
102 return ((obj->prev.map) && (obj->prev.usemap));
103 // return ((!obj->cur.map) && (obj->prev.usemap));
104}
105
106static Eina_Bool
107_evas_render_is_relevant(Evas_Object *obj)
108{
109 return ((evas_object_is_visible(obj) && (!obj->cur.have_clipees)) ||
110 (evas_object_was_visible(obj) && (!obj->prev.have_clipees)));
111}
112
113static Eina_Bool
114_evas_render_can_render(Evas_Object *obj)
115{
116 return (evas_object_is_visible(obj) && (!obj->cur.have_clipees));
117}
118
119static void
120_evas_render_prev_cur_clip_cache_add(Evas *e, Evas_Object *obj)
121{
122 e->engine.func->output_redraws_rect_add(e->engine.data.output,
123 obj->prev.cache.clip.x,
124 obj->prev.cache.clip.y,
125 obj->prev.cache.clip.w,
126 obj->prev.cache.clip.h);
127 e->engine.func->output_redraws_rect_add(e->engine.data.output,
128 obj->cur.cache.clip.x,
129 obj->cur.cache.clip.y,
130 obj->cur.cache.clip.w,
131 obj->cur.cache.clip.h);
132}
133
134static void
135_evas_render_cur_clip_cache_del(Evas *e, Evas_Object *obj)
136{
137 Evas_Coord x, y, w, h;
138
139 x = obj->cur.cache.clip.x;
140 y = obj->cur.cache.clip.y;
141 w = obj->cur.cache.clip.w;
142 h = obj->cur.cache.clip.h;
143 if (obj->cur.clipper)
144 {
145 RECTS_CLIP_TO_RECT(x, y, w, h,
146 obj->cur.clipper->cur.cache.clip.x,
147 obj->cur.clipper->cur.cache.clip.y,
148 obj->cur.clipper->cur.cache.clip.w,
149 obj->cur.clipper->cur.cache.clip.h);
150 }
151 e->engine.func->output_redraws_rect_del(e->engine.data.output,
152 x, y, w, h);
153}
154
155static void
156_evas_render_phase1_direct(Evas *e,
157 Eina_Array *active_objects,
158 Eina_Array *restack_objects __UNUSED__,
159 Eina_Array *delete_objects __UNUSED__,
160 Eina_Array *render_objects)
161{
162 unsigned int i;
163 Eina_List *l;
164 Evas_Object *proxy;
165
166 RD(" [--- PHASE 1 DIRECT\n");
167 for (i = 0; i < active_objects->count; i++)
168 {
169 Evas_Object *obj;
170
171 obj = eina_array_data_get(active_objects, i);
172 if (obj->changed)
173 {
174 /* Flag need redraw on proxy too */
175 evas_object_clip_recalc(obj);
176 if (obj->proxy.proxies)
177 {
178 EINA_LIST_FOREACH(obj->proxy.proxies, l, proxy)
179 proxy->proxy.redraw = 1;
180 }
181 }
182 }
183 for (i = 0; i < render_objects->count; i++)
184 {
185 Evas_Object *obj;
186
187 obj = eina_array_data_get(render_objects, i);
188 RD(" OBJ [%p] changed %i\n", obj, obj->changed);
189 if (obj->changed)
190 {
191 /* Flag need redraw on proxy too */
192 evas_object_clip_recalc(obj);
193 obj->func->render_pre(obj);
194 if (obj->proxy.proxies)
195 {
196 obj->proxy.redraw = 1;
197 EINA_LIST_FOREACH(obj->proxy.proxies, l, proxy)
198 {
199 proxy->func->render_pre(proxy);
200 _evas_render_prev_cur_clip_cache_add(e, proxy);
201 }
202 }
203 else if (obj->proxy.redraw)
204 {
205 _evas_render_prev_cur_clip_cache_add(e, obj);
206 }
207 if (obj->pre_render_done)
208 {
209 RD(" pre-render-done smart:%p|%p [%p, %i] | [%p, %i] has_map:%i had_map:%i\n",
210 obj->smart.smart,
211 evas_object_smart_members_get_direct(obj),
212 obj->cur.map, obj->cur.usemap,
213 obj->prev.map, obj->prev.usemap,
214 _evas_render_has_map(obj),
215 _evas_render_had_map(obj));
216 if ((obj->smart.smart) &&
217 (_evas_render_has_map(obj)))
218 {
219 RD(" has map + smart\n");
220 _evas_render_prev_cur_clip_cache_add(e, obj);
221 }
222 }
223 else if (_evas_render_had_map(obj))
224 {
225 RD(" no pre-render done\n");
226 _evas_render_prev_cur_clip_cache_add(e, obj);
227 }
228 }
229 else
230 {
231 if (obj->smart.smart)
232 {
233 // obj->func->render_pre(obj);
234 }
235 else if ((obj->rect_del) ||
236 (evas_object_is_opaque(obj) && evas_object_is_visible(obj)))
237 {
238 RD(" rect del\n");
239 _evas_render_cur_clip_cache_del(e, obj);
240 }
241 }
242 }
243 RD(" ---]\n");
244}
245
246static Eina_Bool
247_evas_render_phase1_object_process(Evas *e, Evas_Object *obj,
248 Eina_Array *active_objects,
249 Eina_Array *restack_objects,
250 Eina_Array *delete_objects,
251 Eina_Array *render_objects,
252 int restack, int map,
253 int *redraw_all
254#ifdef REND_DGB
255 , int level
256#endif
257 )
258{
259 Eina_Bool clean_them = EINA_FALSE;
260 Evas_Object *obj2;
261 int is_active;
262 Eina_Bool hmap;
263
264 obj->rect_del = 0;
265 obj->render_pre = 0;
266
267#ifndef EVAS_FRAME_QUEUING
268 /* because of clip objects - delete 2 cycles later */
269 if (obj->delete_me == 2)
270#else
271 if (obj->delete_me == evas_common_frameq_get_frameq_sz() + 2)
272#endif
273 eina_array_push(delete_objects, obj);
274 else if (obj->delete_me != 0) obj->delete_me++;
275 /* If the object will be removed, we should not cache anything during this run. */
276 if (obj->delete_me != 0) clean_them = EINA_TRUE;
277
278 /* build active object list */
279 evas_object_clip_recalc(obj);
280 is_active = evas_object_is_active(obj);
281 obj->is_active = is_active;
282
283 RDI(level);
284 RD(" [--- PROCESS [%p] '%s' active = %i, del = %i | %i %i %ix%i\n", obj, obj->type, is_active, obj->delete_me, obj->cur.geometry.x, obj->cur.geometry.y, obj->cur.geometry.w, obj->cur.geometry.h);
285 if ((is_active) || (obj->delete_me != 0))
286 eina_array_push(active_objects, obj);
287
288#ifdef REND_DGB
289 if (!is_active)
290 {
291 RDI(level);
292 RD(" [%p] vis: %i, cache.clip.vis: %i cache.clip.a: %i [%p]\n", obj, obj->cur.visible, obj->cur.cache.clip.visible, obj->cur.cache.clip.a, obj->func->is_visible);
293 }
294#endif
295
296 map = _evas_render_has_map(obj);
297 hmap = _evas_render_had_map(obj);
298
299 if ((restack) && (!map))
300 {
301 if (!obj->changed)
302 {
303 eina_array_push(&e->pending_objects, obj);
304 obj->changed = 1;
305 }
306 obj->restack = 1;
307 clean_them = EINA_TRUE;
308 }
309
310 if (map)
311 {
312 RDI(level);
313 RD(" obj mapped\n");
314 if (obj->changed)
315 {
316 if (map != hmap)
317 {
318 *redraw_all = 1;
319 }
320 evas_object_clip_recalc(obj);
321 if ((obj->restack) &&
322 (is_active) && (!obj->clip.clipees) &&
323 ((evas_object_is_visible(obj) && (!obj->cur.have_clipees)) ||
324 (evas_object_was_visible(obj) && (!obj->prev.have_clipees))))
325 {
326 eina_array_push(render_objects, obj);
327 _evas_render_prev_cur_clip_cache_add(e, obj);
328 obj->render_pre = 1;
329 }
330 else if ((is_active) && (!obj->clip.clipees) &&
331 ((evas_object_is_visible(obj) && (!obj->cur.have_clipees)) ||
332 (evas_object_was_visible(obj) && (!obj->prev.have_clipees))))
333 {
334 eina_array_push(render_objects, obj);
335 _evas_render_prev_cur_clip_cache_add(e, obj);
336 obj->render_pre = 1;
337 }
338 }
339 return clean_them;
340 }
341 else if (_evas_render_had_map(obj))
342 {
343 RDI(level);
344 RD(" had map - restack objs\n");
345 // eina_array_push(restack_objects, obj);
346 _evas_render_prev_cur_clip_cache_add(e, obj);
347 if (obj->changed)
348 {
349 if (hmap)
350 {
351 if (!map)
352 {
353 if ((obj->cur.map) && (obj->cur.usemap)) map = 1;
354 }
355 }
356 if (map != hmap)
357 {
358 *redraw_all = 1;
359 }
360 }
361 }
362
363 /* handle normal rendering. this object knows how to handle maps */
364 if (obj->changed)
365 {
366 if (obj->smart.smart)
367 {
368 RDI(level);
369 RD(" changed + smart - render ok\n");
370 eina_array_push(render_objects, obj);
371 obj->render_pre = 1;
372 EINA_INLIST_FOREACH(evas_object_smart_members_get_direct(obj), obj2)
373 {
374 _evas_render_phase1_object_process(e, obj2,
375 active_objects,
376 restack_objects,
377 delete_objects,
378 render_objects,
379 obj->restack,
380 map,
381 redraw_all
382#ifdef REND_DGB
383 , level + 1
384#endif
385 );
386 }
387 }
388 else
389 {
390 if ((is_active) && (!obj->clip.clipees) &&
391 _evas_render_is_relevant(obj))
392 {
393 RDI(level);
394 RD(" relevant + active\n");
395 if (obj->restack)
396 eina_array_push(restack_objects, obj);
397 else
398 {
399 eina_array_push(render_objects, obj);
400 obj->render_pre = 1;
401 }
402 }
403 else
404 {
405 RDI(level);
406 RD(" skip - not smart, not active or clippees or not relevant\n");
407 }
408 }
409 }
410 else
411 {
412 RD(" not changed... [%i] -> (%i %i %p %i) [%i]\n",
413 evas_object_is_visible(obj),
414 obj->cur.visible, obj->cur.cache.clip.visible, obj->smart.smart, obj->cur.cache.clip.a,
415 evas_object_was_visible(obj));
416 if ((!obj->clip.clipees) && (obj->delete_me == 0) &&
417 (_evas_render_can_render(obj) ||
418 (evas_object_was_visible(obj) && (!obj->prev.have_clipees))))
419 {
420 if (obj->smart.smart)
421 {
422 RDI(level);
423 RD(" smart + visible/was visible + not clip\n");
424 eina_array_push(render_objects, obj);
425 obj->render_pre = 1;
426 EINA_INLIST_FOREACH
427 (evas_object_smart_members_get_direct(obj), obj2)
428 {
429 _evas_render_phase1_object_process(e, obj2,
430 active_objects,
431 restack_objects,
432 delete_objects,
433 render_objects,
434 restack, map,
435 redraw_all
436#ifdef REND_DGB
437 , level + 1
438#endif
439 );
440 }
441 }
442 else
443 {
444 if (evas_object_is_opaque(obj) &&
445 evas_object_is_visible(obj))
446 {
447 RDI(level);
448 RD(" opaque + visible\n");
449 eina_array_push(render_objects, obj);
450 obj->rect_del = 1;
451 }
452 else if (evas_object_is_visible(obj))
453 {
454 RDI(level);
455 RD(" visible\n");
456 eina_array_push(render_objects, obj);
457 obj->render_pre = 1;
458 }
459 else
460 {
461 RDI(level);
462 RD(" skip\n");
463 }
464 }
465 }
466 /*
467 else if (obj->smart.smart)
468 {
469 RDI(level);
470 RD(" smart + mot visible/was visible\n");
471 eina_array_push(render_objects, obj);
472 obj->render_pre = 1;
473 EINA_INLIST_FOREACH
474 (evas_object_smart_members_get_direct(obj), obj2)
475 {
476 _evas_render_phase1_object_process(e, obj2,
477 active_objects,
478 restack_objects,
479 delete_objects,
480 render_objects,
481 restack, map,
482 redraw_all
483#ifdef REND_DGB
484, level + 1
485#endif
486);
487}
488}
489 */
490}
491if (!is_active) obj->restack = 0;
492RDI(level);
493RD(" ---]\n");
494return clean_them;
495}
496
497static Eina_Bool
498_evas_render_phase1_process(Evas *e,
499 Eina_Array *active_objects,
500 Eina_Array *restack_objects,
501 Eina_Array *delete_objects,
502 Eina_Array *render_objects,
503 int *redraw_all)
504{
505 Evas_Layer *lay;
506 Eina_Bool clean_them = EINA_FALSE;
507
508 RD(" [--- PHASE 1\n");
509 EINA_INLIST_FOREACH(e->layers, lay)
510 {
511 Evas_Object *obj;
512
513 EINA_INLIST_FOREACH(lay->objects, obj)
514 {
515 clean_them |= _evas_render_phase1_object_process
516 (e, obj, active_objects, restack_objects, delete_objects,
517 render_objects, 0, 0, redraw_all
518#ifdef REND_DGB
519 , 1
520#endif
521 );
522 }
523 }
524 RD(" ---]\n");
525 return clean_them;
526}
527
528static void
529_evas_render_check_pending_objects(Eina_Array *pending_objects, Evas *e)
530{
531 unsigned int i;
532
533 for (i = 0; i < pending_objects->count; ++i)
534 {
535 Evas_Object *obj;
536 int is_active, ok = 0;
537
538 obj = eina_array_data_get(pending_objects, i);
539
540 if (!obj->layer) goto clean_stuff;
541
542 evas_object_clip_recalc(obj);
543 is_active = evas_object_is_active(obj);
544
545 if ((!is_active) && (!obj->is_active) && (!obj->render_pre) &&
546 (!obj->rect_del))
547 {
548 ok = 1;
549 goto clean_stuff;
550 }
551
552 if (obj->is_active == is_active)
553 {
554 if (obj->changed)
555 {
556 if (obj->smart.smart)
557 {
558 if (obj->render_pre || obj->rect_del) ok = 1;
559 }
560 else
561 if ((is_active) && (obj->restack) && (!obj->clip.clipees) &&
562 (_evas_render_can_render(obj) ||
563 (evas_object_was_visible(obj) && (!obj->prev.have_clipees))))
564 {
565 if (!(obj->render_pre || obj->rect_del)) ok = 1;
566 }
567 else
568 if (is_active && (!obj->clip.clipees) &&
569 (_evas_render_can_render(obj) ||
570 (evas_object_was_visible(obj) && (!obj->prev.have_clipees))))
571 {
572 if (obj->render_pre || obj->rect_del) ok = 1;
573 }
574 }
575 else
576 {
577 if ((!obj->clip.clipees) && (obj->delete_me == 0) &&
578 (!obj->cur.have_clipees || (evas_object_was_visible(obj) && (!obj->prev.have_clipees)))
579 && evas_object_is_opaque(obj) && evas_object_is_visible(obj))
580 {
581 if (obj->rect_del || obj->smart.smart) ok = 1;
582 }
583 }
584 }
585
586clean_stuff:
587 if (!ok)
588 {
589 eina_array_clean(&e->active_objects);
590 eina_array_clean(&e->render_objects);
591 eina_array_clean(&e->restack_objects);
592 eina_array_clean(&e->delete_objects);
593 e->invalidate = 1;
594 return ;
595 }
596 }
597}
598
599Eina_Bool
600pending_change(void *data, void *gdata __UNUSED__)
601{
602 Evas_Object *obj;
603
604 obj = data;
605 if (obj->delete_me) return EINA_FALSE;
606 if (obj->pre_render_done)
607 {
608 RD(" OBJ [%p] pending change %i -> 0, pre %i\n", obj, obj->changed, obj->pre_render_done);
609 obj->pre_render_done = 0;
610 //// FIXME: this wipes out changes
611 obj->changed = 0;
612 obj->changed_move_only = 0;
613 obj->changed_nomove = 0;
614 obj->changed_move = 0;
615 obj->changed_map = 0;
616 obj->changed_pchange = 0;
617 }
618 return obj->changed ? EINA_TRUE : EINA_FALSE;
619}
620/*
621 static void
622 unchange(Evas_Object *obj)
623 {
624 Evas_Object *obj2;
625
626 if (!obj->changed) return;
627 obj->changed = 0;
628 obj->changed_move_only = 0;
629 obj->changed_nomove = 0;
630 obj->changed_move = 0;
631 EINA_INLIST_FOREACH(evas_object_smart_members_get_direct(obj), obj2)
632 {
633 unchange(obj2);
634 }
635 }
636
637 static int
638 chlist(Evas_Object *obj, int i)
639 {
640 Evas_Object *obj2;
641 int j;
642 int ret = 0;
643
644 if (!obj->changed) return 0;
645 for (j = 0; j < i; j++) printf(" ");
646 printf("ch2 %p %s %i [%i %i %ix%i] v %i/%i [r%i] %p\n", obj,
647 obj->type,
648 obj->changed_move_only,
649 obj->cur.geometry.x,
650 obj->cur.geometry.y,
651 obj->cur.geometry.w,
652 obj->cur.geometry.h,
653 obj->cur.visible,
654 obj->prev.visible,
655 obj->restack,
656 obj->clip.clipees);
657 EINA_INLIST_FOREACH(evas_object_smart_members_get_direct(obj), obj2)
658 {
659 if (obj2->changed)
660 ret |= chlist(obj2, i + 1);
661 }
662 }
663 */
664static Eina_Bool
665_evas_render_can_use_overlay(Evas *e, Evas_Object *obj)
666{
667 Eina_Rectangle *r;
668 Evas_Object *tmp;
669 Eina_List *alphas = NULL;
670 Eina_List *opaques = NULL;
671 Evas_Object *video_parent = NULL;
672 Eina_Rectangle zone;
673 Evas_Coord xc1, yc1, xc2, yc2;
674 unsigned int i;
675 Eina_Bool nooverlay;
676
677 video_parent = _evas_object_image_video_parent_get(obj);
678
679 /* Check if any one is the stack make this object mapped */
680 tmp = obj;
681 while (tmp && !_evas_render_has_map(tmp))
682 tmp = tmp->smart.parent;
683
684 if (tmp && _evas_render_has_map(tmp)) return EINA_FALSE; /* we are mapped, we can't be an overlay */
685
686 if (!evas_object_is_visible(obj)) return EINA_FALSE; /* no need to update the overlay if it's not visible */
687
688 /* If any recoloring of the surface is needed, n overlay to */
689 if ((obj->cur.cache.clip.r != 255) ||
690 (obj->cur.cache.clip.g != 255) ||
691 (obj->cur.cache.clip.b != 255) ||
692 (obj->cur.cache.clip.a != 255))
693 return EINA_FALSE;
694
695 /* Check presence of transparent object on top of the video object */
696 EINA_RECTANGLE_SET(&zone,
697 obj->cur.cache.clip.x,
698 obj->cur.cache.clip.y,
699 obj->cur.cache.clip.w,
700 obj->cur.cache.clip.h);
701
702 for (i = e->active_objects.count - 1; i > 0; i--)
703 {
704 Eina_Rectangle self;
705 Eina_Rectangle *match;
706 Evas_Object *current;
707 Eina_List *l;
708 int xm1, ym1, xm2, ym2;
709
710 current = eina_array_data_get(&e->active_objects, i);
711
712 /* Did we find the video object in the stack ? */
713 if (current == video_parent || current == obj)
714 break;
715
716 EINA_RECTANGLE_SET(&self,
717 current->cur.cache.clip.x,
718 current->cur.cache.clip.y,
719 current->cur.cache.clip.w,
720 current->cur.cache.clip.h);
721
722 /* This doesn't cover the area of the video object, so don't bother with that object */
723 if (!eina_rectangles_intersect(&zone, &self))
724 continue ;
725
726 xc1 = current->cur.cache.clip.x;
727 yc1 = current->cur.cache.clip.y;
728 xc2 = current->cur.cache.clip.x + current->cur.cache.clip.w;
729 yc2 = current->cur.cache.clip.y + current->cur.cache.clip.h;
730
731 if (evas_object_is_visible(current) &&
732 (!current->clip.clipees) &&
733 (current->cur.visible) &&
734 (!current->delete_me) &&
735 (current->cur.cache.clip.visible) &&
736 (!current->smart.smart))
737 {
738 Eina_Bool included = EINA_FALSE;
739
740 if (evas_object_is_opaque(current) ||
741 ((current->func->has_opaque_rect) &&
742 (current->func->has_opaque_rect(current))))
743 {
744 /* The object is opaque */
745
746 /* Check if the opaque object is inside another opaque object */
747 EINA_LIST_FOREACH(opaques, l, match)
748 {
749 xm1 = match->x;
750 ym1 = match->y;
751 xm2 = match->x + match->w;
752 ym2 = match->y + match->h;
753
754 /* Both object are included */
755 if (xc1 >= xm1 && yc1 >= ym1 && xc2 <= xm2 && yc2 <= ym2)
756 {
757 included = EINA_TRUE;
758 break;
759 }
760 }
761
762 /* Not included yet */
763 if (!included)
764 {
765 Eina_List *ln;
766 Evas_Coord xn2, yn2;
767
768 r = eina_rectangle_new(current->cur.cache.clip.x, current->cur.cache.clip.y,
769 current->cur.cache.clip.w, current->cur.cache.clip.h);
770
771 opaques = eina_list_append(opaques, r);
772
773 xn2 = r->x + r->w;
774 yn2 = r->y + r->h;
775
776 /* Remove all the transparent object that are covered by the new opaque object */
777 EINA_LIST_FOREACH_SAFE(alphas, l, ln, match)
778 {
779 xm1 = match->x;
780 ym1 = match->y;
781 xm2 = match->x + match->w;
782 ym2 = match->y + match->h;
783
784 if (xm1 >= r->x && ym1 >= r->y && xm2 <= xn2 && ym2 <= yn2)
785 {
786 /* The new rectangle is over some transparent object,
787 so remove the transparent object */
788 alphas = eina_list_remove_list(alphas, l);
789 }
790 }
791 }
792 }
793 else
794 {
795 /* The object has some transparency */
796
797 /* Check if the transparent object is inside any other transparent object */
798 EINA_LIST_FOREACH(alphas, l, match)
799 {
800 xm1 = match->x;
801 ym1 = match->y;
802 xm2 = match->x + match->w;
803 ym2 = match->y + match->h;
804
805 /* Both object are included */
806 if (xc1 >= xm1 && yc1 >= ym1 && xc2 <= xm2 && yc2 <= ym2)
807 {
808 included = EINA_TRUE;
809 break;
810 }
811 }
812
813 /* If not check if it is inside any opaque one */
814 if (!included)
815 {
816 EINA_LIST_FOREACH(opaques, l, match)
817 {
818 xm1 = match->x;
819 ym1 = match->y;
820 xm2 = match->x + match->w;
821 ym2 = match->y + match->h;
822
823 /* Both object are included */
824 if (xc1 >= xm1 && yc1 >= ym1 && xc2 <= xm2 && yc2 <= ym2)
825 {
826 included = EINA_TRUE;
827 break;
828 }
829 }
830 }
831
832 /* No inclusion at all, so add it */
833 if (!included)
834 {
835 r = eina_rectangle_new(current->cur.cache.clip.x, current->cur.cache.clip.y,
836 current->cur.cache.clip.w, current->cur.cache.clip.h);
837
838 alphas = eina_list_append(alphas, r);
839 }
840 }
841 }
842 }
843
844 /* If there is any pending transparent object, then no overlay */
845 nooverlay = !!eina_list_count(alphas);
846
847 EINA_LIST_FREE(alphas, r)
848 eina_rectangle_free(r);
849 EINA_LIST_FREE(opaques, r)
850 eina_rectangle_free(r);
851
852 if (nooverlay)
853 return EINA_FALSE;
854
855 return EINA_TRUE;
856}
857
858Eina_Bool
859evas_render_mapped(Evas *e, Evas_Object *obj, void *context, void *surface,
860 int off_x, int off_y, int mapped,
861 int ecx, int ecy, int ecw, int ech
862#ifdef REND_DGB
863 , int level
864#endif
865 )
866{
867 void *ctx;
868 Evas_Object *obj2;
869 Eina_Bool clean_them = EINA_FALSE;
870
871 evas_object_clip_recalc(obj);
872 RDI(level);
873 RD(" { evas_render_mapped(%p, %p, %p, %p, %i, %i, %i, %i)\n", e, obj, context, surface, off_x, off_y, mapped, level);
874 if (mapped)
875 {
876 if ((!evas_object_is_visible(obj)) || (obj->clip.clipees) ||
877 (obj->cur.have_clipees))
878 {
879 RDI(level);
880 RD(" }\n");
881 return clean_them;
882 }
883 }
884 else if (!(((evas_object_is_active(obj) && (!obj->clip.clipees) &&
885 (_evas_render_can_render(obj))))
886 ))
887 {
888 RDI(level);
889 RD(" }\n");
890 return clean_them;
891 }
892
893 // set render_pre - for child objs that may not have gotten it.
894 obj->pre_render_done = 1;
895 RD(" Hasmap: %p (%d) %p %d -> %d\n",obj->func->can_map,
896 obj->func->can_map ? obj->func->can_map(obj): -1,
897 obj->cur.map, obj->cur.usemap,
898 _evas_render_has_map(obj));
899 if (_evas_render_has_map(obj))
900 {
901 const Evas_Map_Point *p, *p_end;
902 RGBA_Map_Point pts[4], *pt;
903 int sw, sh;
904 int changed = 0, rendered = 0;
905
906 clean_them = EINA_TRUE;
907
908 sw = obj->cur.geometry.w;
909 sh = obj->cur.geometry.h;
910 RDI(level);
911 RD(" mapped obj: %ix%i\n", sw, sh);
912 if ((sw <= 0) || (sh <= 0))
913 {
914 RDI(level);
915 RD(" }\n");
916 return clean_them;
917 }
918
919 pts[0].px = obj->cur.map->persp.px << FP;
920 pts[0].py = obj->cur.map->persp.py << FP;
921 pts[0].foc = obj->cur.map->persp.foc << FP;
922 pts[0].z0 = obj->cur.map->persp.z0 << FP;
923
924 p = obj->cur.map->points;
925 p_end = p + obj->cur.map->count;
926 pt = pts;
927 for (; p < p_end; p++, pt++)
928 {
929 pt->x = (lround(p->x) + off_x) * FP1;
930 pt->y = (lround(p->y) + off_y) * FP1;
931 pt->z = (lround(p->z) ) * FP1;
932 pt->fx = p->px;
933 pt->fy = p->py;
934 pt->fz = p->z;
935 pt->u = lround(p->u) * FP1;
936 pt->v = lround(p->v) * FP1;
937 if (pt->u < 0) pt->u = 0;
938 else if (pt->u > (sw * FP1)) pt->u = (sw * FP1);
939 if (pt->v < 0) pt->v = 0;
940 else if (pt->v > (sh * FP1)) pt->v = (sh * FP1);
941 pt->col = ARGB_JOIN(p->a, p->r, p->g, p->b);
942 }
943 /* Copy last for software engine */
944 if (obj->cur.map->count & 0x1)
945 {
946 pts[obj->cur.map->count] = pts[obj->cur.map->count - 1];
947 }
948
949
950 if (obj->cur.map->surface)
951 {
952 if ((obj->cur.map->surface_w != sw) ||
953 (obj->cur.map->surface_h != sh))
954 {
955 RDI(level);
956 RD(" new surf: %ix%i\n", sw, sh);
957 obj->layer->evas->engine.func->image_map_surface_free
958 (e->engine.data.output, obj->cur.map->surface);
959 obj->cur.map->surface = NULL;
960 }
961 }
962 if (!obj->cur.map->surface)
963 {
964 obj->cur.map->surface_w = sw;
965 obj->cur.map->surface_h = sh;
966
967 obj->cur.map->surface =
968 obj->layer->evas->engine.func->image_map_surface_new
969 (e->engine.data.output, obj->cur.map->surface_w,
970 obj->cur.map->surface_h,
971 obj->cur.map->alpha);
972 RDI(level);
973 RD(" fisrt surf: %ix%i\n", sw, sh);
974 changed = 1;
975 }
976 if (obj->smart.smart)
977 {
978 Evas_Object *o2;
979
980 EINA_INLIST_FOREACH(evas_object_smart_members_get_direct(obj), o2)
981 {
982 if (!evas_object_is_visible(o2) &&
983 !evas_object_was_visible(o2))
984 {
985 o2->changed = 0;
986 o2->changed_move_only = 0;
987 o2->changed_nomove = 0;
988 o2->changed_move = 0;
989 o2->changed_map = 0;
990 o2->changed_pchange = 0;
991 continue;
992 }
993 if (o2->changed)
994 {
995 // chlist(o2, 0);
996 changed = 1;
997 o2->changed = 0;
998 o2->changed_move_only = 0;
999 o2->changed_nomove = 0;
1000 o2->changed_move = 0;
1001 o2->changed_map = 0;
1002 o2->changed_pchange = 0;
1003 break;
1004 }
1005 }
1006 // unchange(obj);
1007 obj->changed = 0;
1008 obj->changed_move_only = 0;
1009 obj->changed_nomove = 0;
1010 obj->changed_move = 0;
1011 obj->changed_map = 0;
1012 obj->changed_pchange = 0;
1013 }
1014 else
1015 {
1016 if (obj->changed)
1017 {
1018 if ((obj->changed_pchange) && (obj->changed_map))
1019 changed = 1;
1020 obj->changed = 0;
1021 obj->changed_move_only = 0;
1022 obj->changed_nomove = 0;
1023 obj->changed_move = 0;
1024 obj->changed_map = 0;
1025 obj->changed_pchange = 0;
1026 }
1027 }
1028
1029 // clear surface before re-render
1030 if ((changed) && (obj->cur.map->surface))
1031 {
1032 int off_x2, off_y2;
1033
1034 RDI(level);
1035 RD(" children redraw\n");
1036 // FIXME: calculate "changes" within map surface and only clear
1037 // and re-render those
1038 if (obj->cur.map->alpha)
1039 {
1040 ctx = e->engine.func->context_new(e->engine.data.output);
1041 e->engine.func->context_color_set
1042 (e->engine.data.output, ctx, 0, 0, 0, 0);
1043 e->engine.func->context_render_op_set
1044 (e->engine.data.output, ctx, EVAS_RENDER_COPY);
1045 e->engine.func->rectangle_draw(e->engine.data.output,
1046 ctx,
1047 obj->cur.map->surface,
1048 0, 0,
1049 obj->cur.map->surface_w,
1050 obj->cur.map->surface_h);
1051 e->engine.func->context_free(e->engine.data.output, ctx);
1052 }
1053 ctx = e->engine.func->context_new(e->engine.data.output);
1054 off_x2 = -obj->cur.geometry.x;
1055 off_y2 = -obj->cur.geometry.y;
1056 if (obj->smart.smart)
1057 {
1058 EINA_INLIST_FOREACH
1059 (evas_object_smart_members_get_direct(obj), obj2)
1060 {
1061 clean_them |= evas_render_mapped(e, obj2, ctx,
1062 obj->cur.map->surface,
1063 off_x2, off_y2, 1,
1064 ecx, ecy, ecw, ech
1065#ifdef REND_DGB
1066 , level + 1
1067#endif
1068 );
1069 }
1070 }
1071 else
1072 {
1073 int x = 0, y = 0, w = 0, h = 0;
1074
1075 w = obj->cur.map->surface_w;
1076 h = obj->cur.map->surface_h;
1077 RECTS_CLIP_TO_RECT(x, y, w, h,
1078 obj->cur.geometry.x + off_x2,
1079 obj->cur.geometry.y + off_y2,
1080 obj->cur.geometry.w,
1081 obj->cur.geometry.h);
1082
1083 e->engine.func->context_clip_set(e->engine.data.output,
1084 ctx, x, y, w, h);
1085 obj->func->render(obj, e->engine.data.output, ctx,
1086 obj->cur.map->surface, off_x2, off_y2);
1087 }
1088 e->engine.func->context_free(e->engine.data.output, ctx);
1089 rendered = 1;
1090 }
1091
1092 RDI(level);
1093 RD(" draw map\n");
1094
1095 if (rendered)
1096 {
1097 obj->cur.map->surface = e->engine.func->image_dirty_region
1098 (e->engine.data.output, obj->cur.map->surface,
1099 0, 0, obj->cur.map->surface_w, obj->cur.map->surface_h);
1100 }
1101 e->engine.func->context_clip_unset(e->engine.data.output,
1102 e->engine.data.context);
1103 if (obj->cur.map->surface)
1104 {
1105 if (obj->smart.smart)
1106 {
1107 if (obj->cur.clipper)
1108 {
1109 int x, y, w, h;
1110 Evas_Object *tobj;
1111
1112 obj->cur.cache.clip.dirty = 1;
1113 tobj = obj->cur.map_parent;
1114 obj->cur.map_parent = obj->cur.clipper->cur.map_parent;
1115 evas_object_clip_recalc(obj);
1116 obj->cur.map_parent = tobj;
1117 x = obj->cur.cache.clip.x;
1118 y = obj->cur.cache.clip.y;
1119 w = obj->cur.cache.clip.w;
1120 h = obj->cur.cache.clip.h;
1121 RECTS_CLIP_TO_RECT(x, y, w, h,
1122 obj->cur.clipper->cur.cache.clip.x,
1123 obj->cur.clipper->cur.cache.clip.y,
1124 obj->cur.clipper->cur.cache.clip.w,
1125 obj->cur.clipper->cur.cache.clip.h);
1126 e->engine.func->context_clip_set(e->engine.data.output,
1127 e->engine.data.context,
1128 x + off_x, y + off_y, w, h);
1129 }
1130 }
1131 else
1132 {
1133 if (obj->cur.clipper)
1134 {
1135 int x, y, w, h;
1136
1137 evas_object_clip_recalc(obj);
1138 x = obj->cur.cache.clip.x;
1139 y = obj->cur.cache.clip.y;
1140 w = obj->cur.cache.clip.w;
1141 h = obj->cur.cache.clip.h;
1142 RECTS_CLIP_TO_RECT(x, y, w, h,
1143 obj->cur.clipper->cur.cache.clip.x,
1144 obj->cur.clipper->cur.cache.clip.y,
1145 obj->cur.clipper->cur.cache.clip.w,
1146 obj->cur.clipper->cur.cache.clip.h);
1147 e->engine.func->context_clip_set(e->engine.data.output,
1148 e->engine.data.context,
1149 x + off_x, y + off_y, w, h);
1150 }
1151 }
1152 }
1153// if (surface == e->engine.data.output)
1154 e->engine.func->context_clip_clip(e->engine.data.output,
1155 e->engine.data.context,
1156 ecx, ecy, ecw, ech);
1157 if (obj->cur.cache.clip.visible)
1158 {
1159 obj->layer->evas->engine.func->image_map_draw
1160 (e->engine.data.output, e->engine.data.context, surface,
1161 obj->cur.map->surface, obj->cur.map->count, pts,
1162 obj->cur.map->smooth, 0);
1163 }
1164 // FIXME: needs to cache these maps and
1165 // keep them only rendering updates
1166 // obj->layer->evas->engine.func->image_map_surface_free
1167 // (e->engine.data.output, obj->cur.map->surface);
1168 // obj->cur.map->surface = NULL;
1169 }
1170 else
1171 {
1172 if (mapped)
1173 {
1174 RDI(level);
1175 RD(" draw child of mapped obj\n");
1176 ctx = e->engine.func->context_new(e->engine.data.output);
1177 if (obj->smart.smart)
1178 {
1179 EINA_INLIST_FOREACH
1180 (evas_object_smart_members_get_direct(obj), obj2)
1181 {
1182 clean_them |= evas_render_mapped(e, obj2, ctx,
1183 surface,
1184 off_x, off_y, 1,
1185 ecx, ecy, ecw, ech
1186#ifdef REND_DGB
1187 , level + 1
1188#endif
1189 );
1190 }
1191 }
1192 else
1193 {
1194 if (!obj->cur.map)
1195 {
1196 int x, y, w, h;
1197
1198 RDI(level);
1199
1200 x = obj->cur.cache.clip.x + off_x;
1201 y = obj->cur.cache.clip.y + off_y;
1202 w = obj->cur.cache.clip.w;
1203 h = obj->cur.cache.clip.h;
1204
1205 if (obj->cur.clipper)
1206 {
1207 if (_evas_render_has_map(obj))
1208 evas_object_clip_recalc(obj);
1209
1210 RD(" clipper: %i %i %ix%i\n",
1211 obj->cur.clipper->cur.cache.clip.x + off_x,
1212 obj->cur.clipper->cur.cache.clip.y + off_y,
1213 obj->cur.clipper->cur.cache.clip.w,
1214 obj->cur.clipper->cur.cache.clip.h);
1215
1216 RECTS_CLIP_TO_RECT(x, y, w, h,
1217 obj->cur.clipper->cur.cache.clip.x + off_x,
1218 obj->cur.clipper->cur.cache.clip.y + off_y,
1219 obj->cur.clipper->cur.cache.clip.w,
1220 obj->cur.clipper->cur.cache.clip.h);
1221 }
1222
1223 RD(" clip: %i %i %ix%i [%i %i %ix%i]\n",
1224 obj->cur.cache.clip.x + off_x,
1225 obj->cur.cache.clip.y + off_y,
1226 obj->cur.cache.clip.w,
1227 obj->cur.cache.clip.h,
1228 obj->cur.geometry.x + off_x,
1229 obj->cur.geometry.y + off_y,
1230 obj->cur.geometry.w,
1231 obj->cur.geometry.h);
1232 e->engine.func->context_clip_set(e->engine.data.output,
1233 ctx, x, y, w, h);
1234 }
1235 else
1236 {
1237 RDI(level);
1238 RD(" noclip\n");
1239 }
1240 obj->func->render(obj, e->engine.data.output, ctx,
1241 surface, off_x, off_y);
1242 /*
1243 obj->layer->evas->engine.func->context_color_set(e->engine.data.output,
1244 ctx,
1245 0, 30, 0, 30);
1246 obj->layer->evas->engine.func->rectangle_draw(e->engine.data.output,
1247 ctx,
1248 surface,
1249 0, 0, 9999, 9999);
1250 */
1251 }
1252 e->engine.func->context_free(e->engine.data.output, ctx);
1253 }
1254 else
1255 {
1256 if (obj->cur.clipper)
1257 {
1258 int x, y, w, h;
1259
1260 if (_evas_render_has_map(obj))
1261 evas_object_clip_recalc(obj);
1262 x = obj->cur.cache.clip.x;
1263 y = obj->cur.cache.clip.y;
1264 w = obj->cur.cache.clip.w;
1265 h = obj->cur.cache.clip.h;
1266 RECTS_CLIP_TO_RECT(x, y, w, h,
1267 obj->cur.clipper->cur.cache.clip.x,
1268 obj->cur.clipper->cur.cache.clip.y,
1269 obj->cur.clipper->cur.cache.clip.w,
1270 obj->cur.clipper->cur.cache.clip.h);
1271 e->engine.func->context_clip_set(e->engine.data.output,
1272 e->engine.data.context,
1273 x + off_x, y + off_y, w, h);
1274 e->engine.func->context_clip_clip(e->engine.data.output,
1275 e->engine.data.context,
1276 ecx, ecy, ecw, ech);
1277 }
1278
1279 RDI(level);
1280 RD(" draw normal obj\n");
1281 obj->func->render(obj, e->engine.data.output, context, surface,
1282 off_x, off_y);
1283 }
1284 }
1285 RDI(level);
1286 RD(" }\n");
1287
1288 return clean_them;
1289}
1290
1291static void
1292_evas_render_cutout_add(Evas *e, Evas_Object *obj, int off_x, int off_y)
1293{
1294 if (evas_object_is_opaque(obj))
1295 {
1296 Evas_Coord cox, coy, cow, coh;
1297
1298 cox = obj->cur.cache.clip.x;
1299 coy = obj->cur.cache.clip.y;
1300 cow = obj->cur.cache.clip.w;
1301 coh = obj->cur.cache.clip.h;
1302 if ((obj->cur.map) && (obj->cur.usemap))
1303 {
1304 Evas_Object *oo;
1305
1306 oo = obj;
1307 while (oo->cur.clipper)
1308 {
1309 if ((oo->cur.clipper->cur.map_parent
1310 != oo->cur.map_parent) &&
1311 (!((oo->cur.map) && (oo->cur.usemap))))
1312 break;
1313 RECTS_CLIP_TO_RECT(cox, coy, cow, coh,
1314 oo->cur.geometry.x,
1315 oo->cur.geometry.y,
1316 oo->cur.geometry.w,
1317 oo->cur.geometry.h);
1318 oo = oo->cur.clipper;
1319 }
1320 }
1321 e->engine.func->context_cutout_add
1322 (e->engine.data.output, e->engine.data.context,
1323 cox + off_x, coy + off_y, cow, coh);
1324 }
1325 else
1326 {
1327 if (obj->func->get_opaque_rect)
1328 {
1329 Evas_Coord obx, oby, obw, obh;
1330
1331 obj->func->get_opaque_rect(obj, &obx, &oby, &obw, &obh);
1332 if ((obw > 0) && (obh > 0))
1333 {
1334 obx += off_x;
1335 oby += off_y;
1336 RECTS_CLIP_TO_RECT(obx, oby, obw, obh,
1337 obj->cur.cache.clip.x + off_x,
1338 obj->cur.cache.clip.y + off_y,
1339 obj->cur.cache.clip.w,
1340 obj->cur.cache.clip.h);
1341 e->engine.func->context_cutout_add
1342 (e->engine.data.output, e->engine.data.context,
1343 obx, oby, obw, obh);
1344 }
1345 }
1346 }
1347}
1348
1349static Eina_List *
1350evas_render_updates_internal(Evas *e,
1351 unsigned char make_updates,
1352 unsigned char do_draw)
1353{
1354 Evas_Object *obj;
1355 Eina_List *updates = NULL;
1356 Eina_List *ll;
1357 void *surface;
1358 Eina_Bool clean_them = EINA_FALSE;
1359 Eina_Bool alpha;
1360 Eina_Rectangle *r;
1361 int ux, uy, uw, uh;
1362 int cx, cy, cw, ch;
1363 unsigned int i, j;
1364 int haveup = 0;
1365 int redraw_all = 0;
1366
1367 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1368 return NULL;
1369 MAGIC_CHECK_END();
1370 if (!e->changed) return NULL;
1371
1372 evas_call_smarts_calculate(e);
1373
1374 RD("[--- RENDER EVAS (size: %ix%i)\n", e->viewport.w, e->viewport.h);
1375
1376 evas_event_callback_call(e, EVAS_CALLBACK_RENDER_PRE, NULL);
1377
1378 /* Check if the modified object mean recalculating every thing */
1379 if (!e->invalidate)
1380 _evas_render_check_pending_objects(&e->pending_objects, e);
1381
1382 /* phase 1. add extra updates for changed objects */
1383 if (e->invalidate || e->render_objects.count <= 0)
1384 clean_them = _evas_render_phase1_process(e,
1385 &e->active_objects,
1386 &e->restack_objects,
1387 &e->delete_objects,
1388 &e->render_objects,
1389 &redraw_all);
1390
1391 /* phase 1.5. check if the video should be inlined or stay in their overlay */
1392 alpha = e->engine.func->canvas_alpha_get(e->engine.data.output,
1393 e->engine.data.context);
1394
1395 EINA_LIST_FOREACH(e->video_objects, ll, obj)
1396 {
1397 /* we need the surface to be transparent to display the underlying overlay */
1398 if (alpha && _evas_render_can_use_overlay(e, obj))
1399 _evas_object_image_video_overlay_show(obj);
1400 else
1401 _evas_object_image_video_overlay_hide(obj);
1402 }
1403
1404
1405 /* phase 1.8. pre render for proxy */
1406 _evas_render_phase1_direct(e, &e->active_objects, &e->restack_objects,
1407 &e->delete_objects, &e->render_objects);
1408
1409 /* phase 2. force updates for restacks */
1410 for (i = 0; i < e->restack_objects.count; ++i)
1411 {
1412 obj = eina_array_data_get(&e->restack_objects, i);
1413 obj->func->render_pre(obj);
1414 _evas_render_prev_cur_clip_cache_add(e, obj);
1415 }
1416 eina_array_clean(&e->restack_objects);
1417
1418 /* phase 3. add exposes */
1419 EINA_LIST_FREE(e->damages, r)
1420 {
1421 e->engine.func->output_redraws_rect_add(e->engine.data.output,
1422 r->x, r->y, r->w, r->h);
1423 eina_rectangle_free(r);
1424 }
1425
1426 /* phase 4. framespace, output & viewport changes */
1427 if (e->framespace.changed)
1428 {
1429 int fx, fy, fw, fh;
1430
1431 fx = e->viewport.x - e->framespace.x;
1432 fy = e->viewport.y - e->framespace.y;
1433 fw = e->viewport.w + e->framespace.w;
1434 fh = e->viewport.h + e->framespace.h;
1435 e->engine.func->output_redraws_rect_add(e->engine.data.output,
1436 fx, fy, fw, fh);
1437 }
1438
1439 if (e->viewport.changed)
1440 {
1441 e->engine.func->output_redraws_rect_add(e->engine.data.output,
1442 0, 0,
1443 e->output.w, e->output.h);
1444 }
1445 if (e->output.changed)
1446 {
1447 e->engine.func->output_resize(e->engine.data.output,
1448 e->output.w, e->output.h);
1449 e->engine.func->output_redraws_rect_add(e->engine.data.output,
1450 0, 0,
1451 e->output.w, e->output.h);
1452 }
1453 if ((e->output.w != e->viewport.w) || (e->output.h != e->viewport.h))
1454 {
1455 ERR("viewport size != output size!");
1456 }
1457 if (redraw_all)
1458 {
1459 e->engine.func->output_redraws_rect_add(e->engine.data.output,
1460 0, 0,
1461 e->output.w, e->output.h);
1462 }
1463
1464 /* phase 5. add obscures */
1465 EINA_LIST_FOREACH(e->obscures, ll, r)
1466 {
1467 e->engine.func->output_redraws_rect_del(e->engine.data.output,
1468 r->x, r->y, r->w, r->h);
1469 }
1470 /* build obscure objects list of active objects that obscure */
1471 for (i = 0; i < e->active_objects.count; ++i)
1472 {
1473 obj = eina_array_data_get(&e->active_objects, i);
1474 if (UNLIKELY((evas_object_is_opaque(obj) ||
1475 ((obj->func->has_opaque_rect) &&
1476 (obj->func->has_opaque_rect(obj)))) &&
1477 evas_object_is_visible(obj) &&
1478 (!obj->clip.clipees) &&
1479 (obj->cur.visible) &&
1480 (!obj->delete_me) &&
1481 (obj->cur.cache.clip.visible) &&
1482 (!obj->smart.smart)))
1483 /* obscuring_objects = eina_list_append(obscuring_objects, obj); */
1484 eina_array_push(&e->obscuring_objects, obj);
1485 }
1486
1487 /* save this list */
1488 /* obscuring_objects_orig = obscuring_objects; */
1489 /* obscuring_objects = NULL; */
1490 /* phase 6. go thru each update rect and render objects in it*/
1491 if (do_draw)
1492 {
1493 unsigned int offset = 0;
1494
1495 while ((surface =
1496 e->engine.func->output_redraws_next_update_get
1497 (e->engine.data.output,
1498 &ux, &uy, &uw, &uh,
1499 &cx, &cy, &cw, &ch)))
1500 {
1501 int off_x, off_y;
1502
1503 RD(" [--- UPDATE %i %i %ix%i\n", ux, uy, uw, uh);
1504 if (make_updates)
1505 {
1506 Eina_Rectangle *rect;
1507
1508 NEW_RECT(rect, ux, uy, uw, uh);
1509 if (rect)
1510 updates = eina_list_append(updates, rect);
1511 }
1512 haveup = 1;
1513 off_x = cx - ux;
1514 off_y = cy - uy;
1515 /* build obscuring objects list (in order from bottom to top) */
1516 if (alpha)
1517 {
1518 e->engine.func->context_clip_set(e->engine.data.output,
1519 e->engine.data.context,
1520 ux + off_x, uy + off_y, uw, uh);
1521 }
1522 for (i = 0; i < e->obscuring_objects.count; ++i)
1523 {
1524 obj = (Evas_Object *)eina_array_data_get
1525 (&e->obscuring_objects, i);
1526 if (evas_object_is_in_output_rect(obj, ux, uy, uw, uh))
1527 {
1528 eina_array_push(&e->temporary_objects, obj);
1529
1530 /* reset the background of the area if needed (using cutout and engine alpha flag to help) */
1531 if (alpha)
1532 _evas_render_cutout_add(e, obj, off_x, off_y);
1533 }
1534 }
1535 if (alpha)
1536 {
1537 e->engine.func->context_color_set(e->engine.data.output,
1538 e->engine.data.context,
1539 0, 0, 0, 0);
1540 e->engine.func->context_multiplier_unset
1541 (e->engine.data.output, e->engine.data.context);
1542 e->engine.func->context_render_op_set(e->engine.data.output,
1543 e->engine.data.context,
1544 EVAS_RENDER_COPY);
1545 e->engine.func->rectangle_draw(e->engine.data.output,
1546 e->engine.data.context,
1547 surface,
1548 cx, cy, cw, ch);
1549 e->engine.func->context_cutout_clear(e->engine.data.output,
1550 e->engine.data.context);
1551 e->engine.func->context_clip_unset(e->engine.data.output,
1552 e->engine.data.context);
1553 }
1554 /* render all object that intersect with rect */
1555 for (i = 0; i < e->active_objects.count; ++i)
1556 {
1557 obj = eina_array_data_get(&e->active_objects, i);
1558
1559 /* if it's in our outpout rect and it doesn't clip anything */
1560 RD(" OBJ: [%p] '%s' %i %i %ix%i\n", obj, obj->type, obj->cur.geometry.x, obj->cur.geometry.y, obj->cur.geometry.w, obj->cur.geometry.h);
1561 if ((evas_object_is_in_output_rect(obj, ux, uy, uw, uh) ||
1562 (obj->smart.smart)) &&
1563 (!obj->clip.clipees) &&
1564 (obj->cur.visible) &&
1565 (!obj->delete_me) &&
1566 (obj->cur.cache.clip.visible) &&
1567// (!obj->smart.smart) &&
1568 ((obj->cur.color.a > 0 || obj->cur.render_op != EVAS_RENDER_BLEND)))
1569 {
1570 int x, y, w, h;
1571
1572 RD(" DRAW (vis: %i, a: %i, clipees: %p\n", obj->cur.visible, obj->cur.color.a, obj->clip.clipees);
1573 if ((e->temporary_objects.count > offset) &&
1574 (eina_array_data_get(&e->temporary_objects, offset) == obj))
1575 offset++;
1576 x = cx; y = cy; w = cw; h = ch;
1577 if (((w > 0) && (h > 0)) || (obj->smart.smart))
1578 {
1579 if (!obj->smart.smart)
1580 {
1581 RECTS_CLIP_TO_RECT(x, y, w, h,
1582 obj->cur.cache.clip.x + off_x,
1583 obj->cur.cache.clip.y + off_y,
1584 obj->cur.cache.clip.w,
1585 obj->cur.cache.clip.h);
1586 }
1587 if (obj->cur.mask)
1588 e->engine.func->context_mask_set(e->engine.data.output,
1589 e->engine.data.context,
1590 obj->cur.mask->func->engine_data_get(obj->cur.mask),
1591 obj->cur.mask->cur.geometry.x + off_x,
1592 obj->cur.mask->cur.geometry.y + off_y,
1593 obj->cur.mask->cur.geometry.w,
1594 obj->cur.mask->cur.geometry.h);
1595 else
1596 e->engine.func->context_mask_unset(e->engine.data.output,
1597 e->engine.data.context);
1598 e->engine.func->context_clip_set(e->engine.data.output,
1599 e->engine.data.context,
1600 x, y, w, h);
1601#if 1 /* FIXME: this can slow things down... figure out optimum... coverage */
1602 for (j = offset; j < e->temporary_objects.count; ++j)
1603 {
1604 Evas_Object *obj2;
1605
1606 obj2 = (Evas_Object *)eina_array_data_get
1607 (&e->temporary_objects, j);
1608 _evas_render_cutout_add(e, obj2, off_x, off_y);
1609 }
1610#endif
1611 clean_them |= evas_render_mapped(e, obj, e->engine.data.context,
1612 surface, off_x, off_y, 0,
1613 cx, cy, cw, ch
1614#ifdef REND_DGB
1615 , 1
1616#endif
1617 );
1618 e->engine.func->context_cutout_clear(e->engine.data.output,
1619 e->engine.data.context);
1620 }
1621 }
1622 }
1623 /* punch rect out */
1624 e->engine.func->output_redraws_next_update_push(e->engine.data.output,
1625 surface,
1626 ux, uy, uw, uh);
1627 /* free obscuring objects list */
1628 eina_array_clean(&e->temporary_objects);
1629 RD(" ---]\n");
1630 }
1631 /* flush redraws */
1632 if (haveup)
1633 {
1634 evas_event_callback_call(e, EVAS_CALLBACK_RENDER_FLUSH_PRE, NULL);
1635 e->engine.func->output_flush(e->engine.data.output);
1636 evas_event_callback_call(e, EVAS_CALLBACK_RENDER_FLUSH_POST, NULL);
1637 }
1638 }
1639 /* clear redraws */
1640 e->engine.func->output_redraws_clear(e->engine.data.output);
1641 /* and do a post render pass */
1642 for (i = 0; i < e->active_objects.count; ++i)
1643 {
1644 obj = eina_array_data_get(&e->active_objects, i);
1645 obj->pre_render_done = 0;
1646 RD(" OBJ [%p] post... %i %i\n", obj, obj->changed, do_draw);
1647 if ((obj->changed) && (do_draw))
1648 {
1649 RD(" OBJ [%p] post... func1\n", obj);
1650 obj->func->render_post(obj);
1651 obj->restack = 0;
1652 obj->changed = 0;
1653 obj->changed_move_only = 0;
1654 obj->changed_nomove = 0;
1655 obj->changed_move = 0;
1656 obj->changed_map = 0;
1657 obj->changed_pchange = 0;
1658 }
1659 else if ((obj->cur.map != obj->prev.map) ||
1660 (obj->cur.usemap != obj->prev.usemap))
1661 {
1662 RD(" OBJ [%p] post... func2\n", obj);
1663 obj->func->render_post(obj);
1664 obj->restack = 0;
1665 obj->changed = 0;
1666 obj->changed_move_only = 0;
1667 obj->changed_nomove = 0;
1668 obj->changed_move = 0;
1669 obj->changed_map = 0;
1670 obj->changed_pchange = 0;
1671 }
1672 /* moved to other pre-process phase 1
1673 if (obj->delete_me == 2)
1674 {
1675 delete_objects = eina_list_append(delete_objects, obj);
1676 }
1677 else if (obj->delete_me != 0) obj->delete_me++;
1678 */
1679 }
1680 /* free our obscuring object list */
1681 eina_array_clean(&e->obscuring_objects);
1682
1683 /* If some object are still marked as changed, do not remove
1684 them from the pending list. */
1685 eina_array_remove(&e->pending_objects, pending_change, NULL);
1686
1687 for (i = 0; i < e->render_objects.count; ++i)
1688 {
1689 obj = eina_array_data_get(&e->render_objects, i);
1690 obj->pre_render_done = 0;
1691 }
1692
1693 /* delete all objects flagged for deletion now */
1694 for (i = 0; i < e->delete_objects.count; ++i)
1695 {
1696 obj = eina_array_data_get(&e->delete_objects, i);
1697 evas_object_free(obj, 1);
1698 }
1699 eina_array_clean(&e->delete_objects);
1700
1701 e->changed = 0;
1702 e->viewport.changed = 0;
1703 e->output.changed = 0;
1704 e->framespace.changed = 0;
1705 e->invalidate = 0;
1706
1707 // always clean... lots of mem waste!
1708 /* If their are some object to restack or some object to delete,
1709 * it's useless to keep the render object list around. */
1710 if (clean_them)
1711 {
1712 eina_array_clean(&e->active_objects);
1713 eina_array_clean(&e->render_objects);
1714 eina_array_clean(&e->restack_objects);
1715 eina_array_clean(&e->delete_objects);
1716 eina_array_clean(&e->obscuring_objects);
1717 eina_array_clean(&e->temporary_objects);
1718 eina_array_clean(&e->clip_changes);
1719/* we should flush here and have a mempool system for this
1720 eina_array_flush(&e->active_objects);
1721 eina_array_flush(&e->render_objects);
1722 eina_array_flush(&e->restack_objects);
1723 eina_array_flush(&e->delete_objects);
1724 eina_array_flush(&e->obscuring_objects);
1725 eina_array_flush(&e->temporary_objects);
1726 eina_array_flush(&e->clip_changes);
1727 */
1728 e->invalidate = 1;
1729 }
1730
1731 evas_module_clean();
1732
1733 evas_event_callback_call(e, EVAS_CALLBACK_RENDER_POST, NULL);
1734
1735 RD("---]\n");
1736
1737 return updates;
1738}
1739
1740EAPI void
1741evas_render_updates_free(Eina_List *updates)
1742{
1743 Eina_Rectangle *r;
1744
1745 EINA_LIST_FREE(updates, r)
1746 eina_rectangle_free(r);
1747}
1748
1749EAPI Eina_List *
1750evas_render_updates(Evas *e)
1751{
1752 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1753 return NULL;
1754 MAGIC_CHECK_END();
1755
1756#ifdef EVAS_FRAME_QUEUING
1757 evas_common_frameq_flush_ready ();
1758#endif
1759
1760 if (!e->changed) return NULL;
1761 return evas_render_updates_internal(e, 1, 1);
1762}
1763
1764EAPI void
1765evas_render(Evas *e)
1766{
1767 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1768 return;
1769 MAGIC_CHECK_END();
1770
1771#ifdef EVAS_FRAME_QUEUING
1772 evas_common_frameq_flush_ready ();
1773#endif
1774
1775 if (!e->changed) return;
1776 evas_render_updates_internal(e, 0, 1);
1777}
1778
1779EAPI void
1780evas_norender(Evas *e)
1781{
1782 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1783 return;
1784 MAGIC_CHECK_END();
1785
1786 // if (!e->changed) return;
1787 evas_render_updates_internal(e, 0, 0);
1788}
1789
1790EAPI void
1791evas_render_idle_flush(Evas *e)
1792{
1793 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1794 return;
1795 MAGIC_CHECK_END();
1796
1797 evas_fonts_zero_presure(e);
1798
1799 if ((e->engine.func) && (e->engine.func->output_idle_flush) &&
1800 (e->engine.data.output))
1801 e->engine.func->output_idle_flush(e->engine.data.output);
1802
1803 eina_array_flush(&e->active_objects);
1804 eina_array_flush(&e->render_objects);
1805 eina_array_flush(&e->restack_objects);
1806 eina_array_flush(&e->delete_objects);
1807 eina_array_flush(&e->obscuring_objects);
1808 eina_array_flush(&e->temporary_objects);
1809 eina_array_flush(&e->clip_changes);
1810 eina_array_flush(&e->temporary_objects);
1811
1812 e->invalidate = 1;
1813}
1814
1815EAPI void
1816evas_sync(Evas *e)
1817{
1818#ifdef EVAS_FRAME_QUEUING
1819 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1820 return;
1821 MAGIC_CHECK_END();
1822
1823 evas_common_frameq_flush();
1824#else
1825 (void) e;
1826#endif
1827}
1828
1829static void
1830_evas_render_dump_map_surfaces(Evas_Object *obj)
1831{
1832 if ((obj->cur.map) && obj->cur.map->surface)
1833 {
1834 obj->layer->evas->engine.func->image_map_surface_free
1835 (obj->layer->evas->engine.data.output, obj->cur.map->surface);
1836 obj->cur.map->surface = NULL;
1837 }
1838
1839 if (obj->smart.smart)
1840 {
1841 Evas_Object *obj2;
1842
1843 EINA_INLIST_FOREACH(evas_object_smart_members_get_direct(obj), obj2)
1844 _evas_render_dump_map_surfaces(obj2);
1845 }
1846}
1847
1848EAPI void
1849evas_render_dump(Evas *e)
1850{
1851 Evas_Layer *lay;
1852
1853 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1854 return;
1855 MAGIC_CHECK_END();
1856
1857 EINA_INLIST_FOREACH(e->layers, lay)
1858 {
1859 Evas_Object *obj;
1860
1861 EINA_INLIST_FOREACH(lay->objects, obj)
1862 {
1863 if ((obj->type) && (!strcmp(obj->type, "image")))
1864 evas_object_inform_call_image_unloaded(obj);
1865 _evas_render_dump_map_surfaces(obj);
1866 }
1867 }
1868 if ((e->engine.func) && (e->engine.func->output_dump) &&
1869 (e->engine.data.output))
1870 e->engine.func->output_dump(e->engine.data.output);
1871}
1872
1873void
1874evas_render_invalidate(Evas *e)
1875{
1876 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
1877 return;
1878 MAGIC_CHECK_END();
1879
1880 eina_array_clean(&e->active_objects);
1881 eina_array_clean(&e->render_objects);
1882
1883 eina_array_flush(&e->restack_objects);
1884 eina_array_flush(&e->delete_objects);
1885
1886 e->invalidate = 1;
1887}
1888
1889void
1890evas_render_object_recalc(Evas_Object *obj)
1891{
1892 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
1893 return;
1894 MAGIC_CHECK_END();
1895
1896#ifndef EVAS_FRAME_QUEUING
1897 if ((!obj->changed) && (obj->delete_me < 2))
1898#else
1899 if ((!obj->changed))
1900#endif
1901 {
1902 Evas *e;
1903
1904 e = obj->layer->evas;
1905 if ((!e) || (e->cleanup)) return;
1906#ifdef EVAS_FRAME_QUEUING
1907 if (obj->delete_me >= evas_common_frameq_get_frameq_sz() + 2) return;
1908#endif
1909 eina_array_push(&e->pending_objects, obj);
1910 obj->changed = 1;
1911 }
1912}
1913
1914/* vim:set ts=8 sw=3 sts=3 expandtab cino=>5n-2f0^-2{2(0W1st0 :*/
diff --git a/libraries/evas/src/lib/canvas/evas_smart.c b/libraries/evas/src/lib/canvas/evas_smart.c
deleted file mode 100644
index 0cfba05..0000000
--- a/libraries/evas/src/lib/canvas/evas_smart.c
+++ /dev/null
@@ -1,266 +0,0 @@
1#include "evas_common.h"
2#include "evas_private.h"
3
4
5static void _evas_smart_class_callbacks_create(Evas_Smart *s);
6
7/* all public */
8
9EAPI void
10evas_smart_free(Evas_Smart *s)
11{
12 MAGIC_CHECK(s, Evas_Smart, MAGIC_SMART);
13 return;
14 MAGIC_CHECK_END();
15 s->delete_me = 1;
16 if (s->usage > 0) return;
17 if (s->class_allocated) free((void *)s->smart_class);
18 free(s->callbacks.array);
19 free(s);
20}
21
22EAPI Evas_Smart *
23evas_smart_class_new(const Evas_Smart_Class *sc)
24{
25 Evas_Smart *s;
26
27 if (!sc) return NULL;
28
29 /* api does not match abi! for now refuse as we only have 1 version */
30 if (sc->version != EVAS_SMART_CLASS_VERSION) return NULL;
31
32 s = evas_mem_calloc(sizeof(Evas_Smart));
33 if (!s) return NULL;
34
35 s->magic = MAGIC_SMART;
36
37 s->smart_class = sc;
38 _evas_smart_class_callbacks_create(s);
39
40 return s;
41}
42
43EAPI const Evas_Smart_Class *
44evas_smart_class_get(const Evas_Smart *s)
45{
46 MAGIC_CHECK(s, Evas_Smart, MAGIC_SMART);
47 return NULL;
48 MAGIC_CHECK_END();
49 return s->smart_class;
50}
51
52EAPI void *
53evas_smart_data_get(const Evas_Smart *s)
54{
55 MAGIC_CHECK(s, Evas_Smart, MAGIC_SMART);
56 return NULL;
57 MAGIC_CHECK_END();
58 return (void *)s->smart_class->data;
59}
60
61EAPI const Evas_Smart_Cb_Description **
62evas_smart_callbacks_descriptions_get(const Evas_Smart *s, unsigned int *count)
63{
64 MAGIC_CHECK(s, Evas_Smart, MAGIC_SMART);
65 if (count) *count = 0;
66 return NULL;
67 MAGIC_CHECK_END();
68
69 if (count) *count = s->callbacks.size;
70 return s->callbacks.array;
71}
72
73EAPI const Evas_Smart_Cb_Description *
74evas_smart_callback_description_find(const Evas_Smart *s, const char *name)
75{
76 if (!name) return NULL;
77 MAGIC_CHECK(s, Evas_Smart, MAGIC_SMART);
78 return NULL;
79 MAGIC_CHECK_END();
80 return evas_smart_cb_description_find(&s->callbacks, name);
81}
82
83EAPI Eina_Bool
84evas_smart_class_inherit_full(Evas_Smart_Class *sc, const Evas_Smart_Class *parent_sc, unsigned int parent_sc_size)
85{
86 unsigned int off;
87
88 /* api does not match abi! for now refuse as we only have 1 version */
89 if (parent_sc->version != EVAS_SMART_CLASS_VERSION) return EINA_FALSE;
90
91#define _CP(m) sc->m = parent_sc->m
92 _CP(add);
93 _CP(del);
94 _CP(move);
95 _CP(resize);
96 _CP(show);
97 _CP(hide);
98 _CP(color_set);
99 _CP(clip_set);
100 _CP(clip_unset);
101 _CP(calculate);
102 _CP(member_add);
103 _CP(member_del);
104#undef _CP
105
106 sc->parent = parent_sc;
107
108 off = sizeof(Evas_Smart_Class);
109 if (parent_sc_size == off) return EINA_TRUE;
110
111 memcpy(((char *)sc) + off, ((char *)parent_sc) + off, parent_sc_size - off);
112 return EINA_TRUE;
113}
114
115EAPI int
116evas_smart_usage_get(const Evas_Smart *s)
117{
118 MAGIC_CHECK(s, Evas_Smart, MAGIC_SMART);
119 return 0;
120 MAGIC_CHECK_END();
121 return s->usage;
122}
123
124
125/* internal funcs */
126void
127evas_object_smart_use(Evas_Smart *s)
128{
129 s->usage++;
130}
131
132void
133evas_object_smart_unuse(Evas_Smart *s)
134{
135 s->usage--;
136 if ((s->usage <= 0) && (s->delete_me)) evas_smart_free(s);
137}
138
139Eina_Bool
140evas_smart_cb_descriptions_resize(Evas_Smart_Cb_Description_Array *a, unsigned int size)
141{
142 void *tmp;
143
144 if (size == a->size)
145 return EINA_TRUE;
146
147 if (size == EINA_FALSE)
148 {
149 free(a->array);
150 a->array = NULL;
151 a->size = 0;
152 return EINA_TRUE;
153 }
154
155 tmp = realloc(a->array, (size + 1) * sizeof(Evas_Smart_Cb_Description *));
156 if (tmp)
157 {
158 a->array = tmp;
159 a->size = size;
160 a->array[size] = NULL;
161 return EINA_TRUE;
162 }
163 else
164 {
165 ERR("realloc failed!");
166 return EINA_FALSE;
167 }
168}
169
170static int
171_evas_smart_cb_description_cmp_sort(const void *p1, const void *p2)
172{
173 const Evas_Smart_Cb_Description **a = (const Evas_Smart_Cb_Description **)p1;
174 const Evas_Smart_Cb_Description **b = (const Evas_Smart_Cb_Description **)p2;
175 return strcmp((*a)->name, (*b)->name);
176}
177
178void
179evas_smart_cb_descriptions_fix(Evas_Smart_Cb_Description_Array *a)
180{
181 unsigned int i, j;
182
183 if (!a)
184 {
185 ERR("no array to fix!");
186 return;
187 }
188
189 qsort(a->array, a->size, sizeof(Evas_Smart_Cb_Description *),
190 _evas_smart_cb_description_cmp_sort);
191
192 DBG("%u callbacks", a->size);
193 if (a->size)
194 DBG("%s [type=%s]", a->array[0]->name, a->array[0]->type);
195
196 for (i = 0, j = 1; j < a->size; j++)
197 {
198 const Evas_Smart_Cb_Description *cur, *prev;
199
200 cur = a->array[j];
201 prev = a->array[i];
202
203 DBG("%s [type=%s]", cur->name, cur->type);
204
205 if (strcmp(cur->name, prev->name) != 0)
206 {
207 i++;
208 if (i != j)
209 a->array[i] = a->array[j];
210 }
211 else
212 {
213 if (strcmp(cur->type, prev->type) == 0)
214 WRN("duplicated smart callback description"
215 " with name '%s' and type '%s'", cur->name, cur->type);
216 else
217 ERR("callback descriptions named '%s' differ"
218 " in type, keeping '%s', ignoring '%s'",
219 cur->name, prev->type, cur->type);
220 }
221 }
222
223 evas_smart_cb_descriptions_resize(a, i + 1);
224}
225
226static void
227_evas_smart_class_callbacks_create(Evas_Smart *s)
228{
229 const Evas_Smart_Class *sc;
230 unsigned int n = 0;
231
232 for (sc = s->smart_class; sc; sc = sc->parent)
233 {
234 const Evas_Smart_Cb_Description *d;
235 for (d = sc->callbacks; d && d->name; d++)
236 n++;
237 }
238
239 if (n == 0) return;
240 if (!evas_smart_cb_descriptions_resize(&s->callbacks, n)) return;
241 for (n = 0, sc = s->smart_class; sc; sc = sc->parent)
242 {
243 const Evas_Smart_Cb_Description *d;
244 for (d = sc->callbacks; d && d->name; d++)
245 s->callbacks.array[n++] = d;
246 }
247 evas_smart_cb_descriptions_fix(&s->callbacks);
248}
249
250static int
251_evas_smart_cb_description_cmp_search(const void *p1, const void *p2)
252{
253 const char *name = p1;
254 const Evas_Smart_Cb_Description **v = (const Evas_Smart_Cb_Description **)p2;
255 /* speed up string shares searches (same pointers) */
256 if (name == (*v)->name) return 0;
257 return strcmp(name, (*v)->name);
258}
259
260const Evas_Smart_Cb_Description *
261evas_smart_cb_description_find(const Evas_Smart_Cb_Description_Array *a, const char *name)
262{
263 if (!a->array) return NULL;
264 return bsearch(name, a->array, a->size, sizeof(Evas_Smart_Cb_Description *),
265 _evas_smart_cb_description_cmp_search);
266}
diff --git a/libraries/evas/src/lib/canvas/evas_stack.c b/libraries/evas/src/lib/canvas/evas_stack.c
deleted file mode 100644
index a8dec0d..0000000
--- a/libraries/evas/src/lib/canvas/evas_stack.c
+++ /dev/null
@@ -1,391 +0,0 @@
1#include "evas_common.h"
2#include "evas_private.h"
3
4static Evas_Object *
5evas_object_above_get_internal(const Evas_Object *obj)
6{
7 if ((EINA_INLIST_GET(obj))->next)
8 return (Evas_Object *)((EINA_INLIST_GET(obj))->next);
9 else
10 {
11 if ((EINA_INLIST_GET(((Evas_Object*)(obj))->layer))->next)
12 {
13 Evas_Layer *l;
14
15 l = (Evas_Layer *)((EINA_INLIST_GET((((Evas_Object *)obj)->layer)))->next);
16 return l->objects;
17 }
18 }
19 return NULL;
20}
21
22static Evas_Object *
23evas_object_below_get_internal(const Evas_Object *obj)
24{
25 if ((EINA_INLIST_GET(obj))->prev)
26 return (Evas_Object *)((EINA_INLIST_GET(obj))->prev);
27 else
28 {
29 if ((EINA_INLIST_GET((((Evas_Object *)obj)->layer)))->prev)
30 {
31 Evas_Layer *l;
32
33 l = (Evas_Layer *)((EINA_INLIST_GET((((Evas_Object *)obj)->layer)))->prev);
34 return (Evas_Object *)((EINA_INLIST_GET((l->objects)))->last);
35 }
36 }
37 return NULL;
38}
39
40EAPI void
41evas_object_raise(Evas_Object *obj)
42{
43 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
44 return;
45 MAGIC_CHECK_END();
46 if (evas_object_intercept_call_raise(obj)) return;
47 if (!((EINA_INLIST_GET(obj))->next))
48 {
49 evas_object_inform_call_restack(obj);
50 return;
51 }
52 if (obj->smart.parent)
53 evas_object_smart_member_raise(obj);
54 else
55 {
56 if (obj->in_layer)
57 obj->layer->objects = (Evas_Object *)eina_inlist_demote(EINA_INLIST_GET(obj->layer->objects), EINA_INLIST_GET(obj));
58 }
59 if (obj->clip.clipees)
60 {
61 evas_object_inform_call_restack(obj);
62 return;
63 }
64 if (obj->layer) evas_render_invalidate(obj->layer->evas);
65 obj->restack = EINA_TRUE;
66 evas_object_change(obj);
67 evas_object_inform_call_restack(obj);
68 if (obj->layer->evas->events_frozen > 0) return;
69 if ((!evas_event_passes_through(obj)) && (!evas_event_freezes_through(obj)))
70 {
71 if (!obj->smart.smart)
72 {
73 if (evas_object_is_in_output_rect(obj,
74 obj->layer->evas->pointer.x,
75 obj->layer->evas->pointer.y,
76 1, 1) && obj->cur.visible)
77 evas_event_feed_mouse_move(obj->layer->evas,
78 obj->layer->evas->pointer.x,
79 obj->layer->evas->pointer.y,
80 obj->layer->evas->last_timestamp,
81 NULL);
82 }
83 }
84}
85
86EAPI void
87evas_object_lower(Evas_Object *obj)
88{
89 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
90 return;
91 MAGIC_CHECK_END();
92 if (evas_object_intercept_call_lower(obj)) return;
93 if (!((EINA_INLIST_GET(obj))->prev))
94 {
95 evas_object_inform_call_restack(obj);
96 return;
97 }
98 if (obj->smart.parent)
99 evas_object_smart_member_lower(obj);
100 else
101 {
102 if (obj->in_layer)
103 obj->layer->objects = (Evas_Object *)eina_inlist_promote(EINA_INLIST_GET(obj->layer->objects),
104 EINA_INLIST_GET(obj));
105 }
106 if (obj->clip.clipees)
107 {
108 evas_object_inform_call_restack(obj);
109 return;
110 }
111 if (obj->layer) evas_render_invalidate(obj->layer->evas);
112 obj->restack = EINA_TRUE;
113 evas_object_change(obj);
114 evas_object_inform_call_restack(obj);
115 if (obj->layer->evas->events_frozen > 0) return;
116 if ((!evas_event_passes_through(obj)) && (!evas_event_freezes_through(obj)))
117 {
118 if (!obj->smart.smart)
119 {
120 if (evas_object_is_in_output_rect(obj,
121 obj->layer->evas->pointer.x,
122 obj->layer->evas->pointer.y,
123 1, 1) && obj->cur.visible)
124 evas_event_feed_mouse_move(obj->layer->evas,
125 obj->layer->evas->pointer.x,
126 obj->layer->evas->pointer.y,
127 obj->layer->evas->last_timestamp,
128 NULL);
129 }
130 }
131}
132
133EAPI void
134evas_object_stack_above(Evas_Object *obj, Evas_Object *above)
135{
136 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
137 return;
138 MAGIC_CHECK_END();
139 MAGIC_CHECK(above, Evas_Object, MAGIC_OBJ);
140 return;
141 MAGIC_CHECK_END();
142 if (obj == above) return;
143 if (evas_object_intercept_call_stack_above(obj, above)) return;
144 if (!above)
145 {
146 evas_object_raise(obj);
147 return;
148 }
149 if ((EINA_INLIST_GET(obj))->prev == EINA_INLIST_GET(above))
150 {
151 evas_object_inform_call_restack(obj);
152 return;
153 }
154 if (obj->smart.parent)
155 {
156 if (obj->smart.parent != above->smart.parent)
157 {
158 ERR("BITCH! evas_object_stack_above(), %p not inside same smart as %p!", obj, above);
159 return;
160 }
161 evas_object_smart_member_stack_above(obj, above);
162 }
163 else
164 {
165 if (above->smart.parent)
166 {
167 ERR("BITCH! evas_object_stack_above(), %p stack above %p, but above has smart parent, obj does not", obj, above);
168 return;
169 }
170 if (obj->layer != above->layer)
171 {
172 ERR("BITCH! evas_object_stack_above(), %p stack above %p, not matching layers", obj, above);
173 return;
174 }
175 if (obj->in_layer)
176 {
177 obj->layer->objects = (Evas_Object *)eina_inlist_remove(EINA_INLIST_GET(obj->layer->objects),
178 EINA_INLIST_GET(obj));
179 obj->layer->objects = (Evas_Object *)eina_inlist_append_relative(EINA_INLIST_GET(obj->layer->objects),
180 EINA_INLIST_GET(obj),
181 EINA_INLIST_GET(above));
182 }
183 }
184 if (obj->clip.clipees)
185 {
186 evas_object_inform_call_restack(obj);
187 return;
188 }
189 if (obj->layer) evas_render_invalidate(obj->layer->evas);
190 obj->restack = EINA_TRUE;
191 evas_object_change(obj);
192 evas_object_inform_call_restack(obj);
193 if (obj->layer->evas->events_frozen > 0) return;
194 if ((!evas_event_passes_through(obj)) && (!evas_event_freezes_through(obj)))
195 {
196 if (!obj->smart.smart)
197 {
198 if (evas_object_is_in_output_rect(obj,
199 obj->layer->evas->pointer.x,
200 obj->layer->evas->pointer.y,
201 1, 1) && obj->cur.visible)
202 evas_event_feed_mouse_move(obj->layer->evas,
203 obj->layer->evas->pointer.x,
204 obj->layer->evas->pointer.y,
205 obj->layer->evas->last_timestamp,
206 NULL);
207 }
208 }
209}
210
211EAPI void
212evas_object_stack_below(Evas_Object *obj, Evas_Object *below)
213{
214 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
215 return;
216 MAGIC_CHECK_END();
217 MAGIC_CHECK(below, Evas_Object, MAGIC_OBJ);
218 return;
219 MAGIC_CHECK_END();
220 if (obj == below) return;
221 if (evas_object_intercept_call_stack_below(obj, below)) return;
222 if (!below)
223 {
224 evas_object_lower(obj);
225 return;
226 }
227 if ((EINA_INLIST_GET(obj))->next == EINA_INLIST_GET(below))
228 {
229 evas_object_inform_call_restack(obj);
230 return;
231 }
232 if (obj->smart.parent)
233 {
234 if (obj->smart.parent != below->smart.parent)
235 {
236 ERR("BITCH! evas_object_stack_below(), %p not inside same smart as %p!", obj, below);
237 return;
238 }
239 evas_object_smart_member_stack_below(obj, below);
240 }
241 else
242 {
243 if (below->smart.parent)
244 {
245 ERR("BITCH! evas_object_stack_below(), %p stack below %p, but below has smart parent, obj does not", obj, below);
246 return;
247 }
248 if (obj->layer != below->layer)
249 {
250 ERR("BITCH! evas_object_stack_below(), %p stack below %p, not matching layers", obj, below);
251 return;
252 }
253 if (obj->in_layer)
254 {
255 obj->layer->objects = (Evas_Object *)eina_inlist_remove(EINA_INLIST_GET(obj->layer->objects),
256 EINA_INLIST_GET(obj));
257 obj->layer->objects = (Evas_Object *)eina_inlist_prepend_relative(EINA_INLIST_GET(obj->layer->objects),
258 EINA_INLIST_GET(obj),
259 EINA_INLIST_GET(below));
260 }
261 }
262 if (obj->clip.clipees)
263 {
264 evas_object_inform_call_restack(obj);
265 return;
266 }
267 if (obj->layer) evas_render_invalidate(obj->layer->evas);
268 obj->restack = EINA_TRUE;
269 evas_object_change(obj);
270 evas_object_inform_call_restack(obj);
271 if (obj->layer->evas->events_frozen > 0) return;
272 if ((!evas_event_passes_through(obj)) && (!evas_event_freezes_through(obj)))
273 {
274 if (!obj->smart.smart)
275 {
276 if (evas_object_is_in_output_rect(obj,
277 obj->layer->evas->pointer.x,
278 obj->layer->evas->pointer.y,
279 1, 1) && obj->cur.visible)
280 evas_event_feed_mouse_move(obj->layer->evas,
281 obj->layer->evas->pointer.x,
282 obj->layer->evas->pointer.y,
283 obj->layer->evas->last_timestamp,
284 NULL);
285 }
286 }
287}
288
289EAPI Evas_Object *
290evas_object_above_get(const Evas_Object *obj)
291{
292 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
293 return NULL;
294 MAGIC_CHECK_END();
295 if (obj->smart.parent)
296 {
297 do
298 {
299 obj = (Evas_Object *)((EINA_INLIST_GET(obj))->next);
300 if ((obj) && (!obj->delete_me)) return (Evas_Object *)obj;
301 }
302 while (obj);
303 return NULL;
304 }
305 obj = evas_object_above_get_internal(obj);
306 while (obj)
307 {
308 if (!obj->delete_me) return (Evas_Object *)obj;
309 obj = evas_object_above_get_internal(obj);
310 }
311 return NULL;
312}
313
314EAPI Evas_Object *
315evas_object_below_get(const Evas_Object *obj)
316{
317 MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
318 return NULL;
319 MAGIC_CHECK_END();
320 if (obj->smart.parent)
321 {
322 do
323 {
324 obj = (Evas_Object *)((EINA_INLIST_GET(obj))->prev);
325 if ((obj) && (!obj->delete_me)) return (Evas_Object *)obj;
326 }
327 while (obj);
328 return NULL;
329 }
330 obj = evas_object_below_get_internal(obj);
331 while (obj)
332 {
333 if (!obj->delete_me) return (Evas_Object *)obj;
334 obj = evas_object_below_get_internal(obj);
335 }
336 return NULL;
337}
338
339
340
341EAPI Evas_Object *
342evas_object_bottom_get(const Evas *e)
343{
344 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
345 return NULL;
346 MAGIC_CHECK_END();
347 if (e->layers)
348 {
349 Evas_Object *obj;
350
351 obj = e->layers->objects;
352 while (obj)
353 {
354 if (!obj->delete_me) return obj;
355 obj = evas_object_above_get_internal(obj);
356 }
357 }
358 return NULL;
359}
360
361EAPI Evas_Object *
362evas_object_top_get(const Evas *e)
363{
364 Evas_Object *obj = NULL;
365 Eina_Inlist *list;
366 Evas_Layer *layer;
367
368 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
369 return NULL;
370 MAGIC_CHECK_END();
371
372 list = EINA_INLIST_GET(e->layers);
373 if (!list) return NULL;
374
375 layer = (Evas_Layer *) list->last;
376 if (!layer) return NULL;
377
378 list = EINA_INLIST_GET(layer->objects);
379 if (!list) return NULL;
380
381 obj = (Evas_Object *) list->last;
382 if (!obj) return NULL;
383
384 while (obj)
385 {
386 if (!obj->delete_me) return obj;
387 obj = evas_object_below_get_internal(obj);
388 }
389
390 return obj;
391}
diff --git a/libraries/evas/src/lib/canvas/evas_stats.c b/libraries/evas/src/lib/canvas/evas_stats.c
deleted file mode 100644
index cfb1a84..0000000
--- a/libraries/evas/src/lib/canvas/evas_stats.c
+++ /dev/null
@@ -1,185 +0,0 @@
1#include "evas_common.h"
2#include "evas_private.h"
3#include "evas_cs.h"
4
5EAPI Eina_Bool
6evas_cserve_want_get(void)
7{
8#ifdef EVAS_CSERVE
9 return evas_cserve_use_get();
10#endif
11 return 0;
12}
13
14EAPI Eina_Bool
15evas_cserve_connected_get(void)
16{
17#ifdef EVAS_CSERVE
18 return evas_cserve_have_get();
19#endif
20 return 0;
21}
22
23EAPI Eina_Bool
24evas_cserve_stats_get(Evas_Cserve_Stats *stats)
25{
26#ifdef EVAS_CSERVE
27 Op_Getstats_Reply st;
28
29 if (!evas_cserve_raw_stats_get(&st)) return 0;
30 if (!stats) return 1;
31 stats->saved_memory = st.saved_memory;
32 stats->wasted_memory = st.wasted_memory;
33 stats->saved_memory_peak = st.saved_memory_peak;
34 stats->wasted_memory_peak = st.wasted_memory_peak;
35 stats->saved_time_image_header_load = st.saved_time_image_header_load;
36 stats->saved_time_image_data_load = st.saved_time_image_data_load;
37 // may expand this in future
38 return 1;
39#else
40 (void) stats;
41 return 0;
42#endif
43}
44
45EAPI Eina_Bool
46evas_cserve_image_cache_contents_get(Evas_Cserve_Image_Cache *cache)
47{
48#ifdef EVAS_CSERVE
49 Op_Getinfo_Reply *info;
50 unsigned char *p;
51 int i, j;
52
53 if (!(info = evas_cserve_raw_info_get())) return 0;
54 if (!cache)
55 {
56 free(info);
57 return 1;
58 }
59 cache->active.mem_total = info->active.mem_total;
60 cache->active.count = info->active.count;
61 cache->cached.mem_total = info->cached.mem_total;
62 cache->cached.count = info->cached.count;
63 cache->images = NULL;
64 j = info->active.count + info->cached.count;
65 p = (unsigned char *)info;
66 p += sizeof(Op_Getinfo_Reply);
67 for (i = 0; i < j; i++)
68 {
69 Evas_Cserve_Image *im;
70 Op_Getinfo_Item it;
71 char *file, *key;
72
73 memcpy(&it, p, sizeof(Op_Getinfo_Item));
74 file = (char*) (p + sizeof(Op_Getinfo_Item));
75 key = file + strlen(file) + 1;
76 im = calloc(1, sizeof(Evas_Cserve_Image));
77 if (!im) continue;
78 if (file[0] != 0)
79 {
80 file = (char *)eina_stringshare_add(file);
81 if (!file)
82 {
83 free(im);
84 continue;
85 }
86 }
87 else
88 file = NULL;
89 if (key[0] != 0)
90 {
91 key = (char *)eina_stringshare_add(key);
92 if (!key)
93 {
94 if (file) eina_stringshare_del(file);
95 free(im);
96 continue;
97 }
98 }
99 else key = NULL;
100 cache->images = eina_list_append(cache->images, im);
101 im->file = file;
102 im->key = key;
103 im->w = it.w;
104 im->h = it.h;
105 im->cached_time = it.cached_time;
106 im->file_mod_time = it.file_mod_time;
107 im->file_checked_time = it.file_checked_time;
108 im->refcount = it.refcount;
109 im->data_refcount = it.data_refcount;
110 im->memory_footprint = it.memory_footprint;
111 im->head_load_time = it.head_load_time;
112 im->data_load_time = it.data_load_time;
113 im->active = it.active;
114 im->alpha = it.alpha;
115 im->data_loaded = it.data_loaded;
116 im->dead = it.dead;
117 im->useless = it.useless;
118 }
119 free(info);
120 return 1;
121#else
122 (void) cache;
123 return 0;
124#endif
125}
126
127EAPI void
128evas_cserve_image_cache_contents_clean(Evas_Cserve_Image_Cache *cache)
129{
130#ifdef EVAS_CSERVE
131 Evas_Cserve_Image *im;
132
133 EINA_LIST_FREE(cache->images, im)
134 {
135 if (im->file) eina_stringshare_del(im->file);
136 if (im->key) eina_stringshare_del(im->key);
137 free(im);
138 }
139#else
140 (void) cache;
141#endif
142}
143
144EAPI Eina_Bool
145evas_cserve_config_get(Evas_Cserve_Config *config)
146{
147#ifdef EVAS_CSERVE
148 Op_Getconfig_Reply conf;
149
150 if (!evas_cserve_raw_config_get(&conf)) return 0;
151 if (!config) return 1;
152 config->cache_max_usage = conf.cache_max_usage;
153 config->cache_item_timeout = conf.cache_item_timeout;
154 config->cache_item_timeout_check = conf.cache_item_timeout_check;
155 return 1;
156#else
157 (void) config;
158 return 0;
159#endif
160}
161
162EAPI Eina_Bool
163evas_cserve_config_set(const Evas_Cserve_Config *config)
164{
165#ifdef EVAS_CSERVE
166 Op_Setconfig conf;
167
168 if (!config) return 1;
169 conf.cache_max_usage = config->cache_max_usage;
170 conf.cache_item_timeout = config->cache_item_timeout;
171 conf.cache_item_timeout_check = config->cache_item_timeout_check;
172 return evas_cserve_raw_config_set(&conf);
173#else
174 (void) config;
175 return 0;
176#endif
177}
178
179EAPI void
180evas_cserve_disconnect(void)
181{
182#ifdef EVAS_CSERVE
183 evas_cserve_discon();
184#endif
185}
diff --git a/libraries/evas/src/lib/canvas/evas_touch_point.c b/libraries/evas/src/lib/canvas/evas_touch_point.c
deleted file mode 100644
index bdea73f..0000000
--- a/libraries/evas/src/lib/canvas/evas_touch_point.c
+++ /dev/null
@@ -1,110 +0,0 @@
1#include "evas_common.h"
2#include "evas_private.h"
3
4void
5_evas_touch_point_append(Evas *e, int id, Evas_Coord x, Evas_Coord y)
6{
7 Evas_Coord_Touch_Point *point;
8
9 /* create new Evas_Coord_Touch_Point */
10 point = (Evas_Coord_Touch_Point *)calloc(1, sizeof(Evas_Coord_Touch_Point));
11 point->x = x;
12 point->y = y;
13 point->id = id;
14 point->state = EVAS_TOUCH_POINT_DOWN;
15 e->touch_points = eina_list_append(e->touch_points, point);
16}
17
18void
19_evas_touch_point_update(Evas *e, int id, Evas_Coord x, Evas_Coord y, Evas_Touch_Point_State state)
20{
21 Eina_List *l;
22 Evas_Coord_Touch_Point *point = NULL;
23
24 EINA_LIST_FOREACH(e->touch_points, l, point)
25 {
26 if (point->id == id)
27 {
28 point->x = x;
29 point->y = y;
30 point->state = state;
31 break;
32 }
33 }
34}
35
36void
37_evas_touch_point_remove(Evas *e, int id)
38{
39 Eina_List *l;
40 Evas_Coord_Touch_Point *point = NULL;
41
42 EINA_LIST_FOREACH(e->touch_points, l, point)
43 {
44 if (point->id == id)
45 {
46 e->touch_points = eina_list_remove(e->touch_points, point);
47 free(point);
48 break;
49 }
50 }
51}
52
53EAPI unsigned int
54evas_touch_point_list_count(Evas *e)
55{
56 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
57 return 0;
58 MAGIC_CHECK_END();
59 return eina_list_count(e->touch_points);
60}
61
62EAPI void
63evas_touch_point_list_nth_xy_get(Evas *e, unsigned int n, Evas_Coord *x, Evas_Coord *y)
64{
65 Evas_Coord_Touch_Point *point = NULL;
66
67 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
68 if (x) *x = 0;
69 if (y) *y = 0;
70 return;
71 MAGIC_CHECK_END();
72
73 point = (Evas_Coord_Touch_Point *)eina_list_nth(e->touch_points, n);
74 if (!point)
75 {
76 if (x) *x = 0;
77 if (y) *y = 0;
78 return;
79 }
80 if (x) *x = point->x;
81 if (y) *y = point->y;
82}
83
84EAPI int
85evas_touch_point_list_nth_id_get(Evas *e, unsigned int n)
86{
87 Evas_Coord_Touch_Point *point = NULL;
88
89 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
90 return -1;
91 MAGIC_CHECK_END();
92
93 point = (Evas_Coord_Touch_Point *)eina_list_nth(e->touch_points, n);
94 if (!point) return -1;
95 return point->id;
96}
97
98EAPI Evas_Touch_Point_State
99evas_touch_point_list_nth_state_get(Evas *e, unsigned int n)
100{
101 Evas_Coord_Touch_Point *point = NULL;
102
103 MAGIC_CHECK(e, Evas, MAGIC_EVAS);
104 return EVAS_TOUCH_POINT_CANCEL;
105 MAGIC_CHECK_END();
106
107 point = (Evas_Coord_Touch_Point *)eina_list_nth(e->touch_points, n);
108 if (!point) return EVAS_TOUCH_POINT_CANCEL;
109 return point->state;
110}