diff options
Diffstat (limited to 'libraries/evas/src/lib/canvas')
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 @@ | |||
1 | MAINTAINERCLEANFILES = Makefile.in | ||
2 | |||
3 | AM_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 | |||
19 | noinst_LTLIBRARIES = libevas_canvas.la | ||
20 | libevas_canvas_la_SOURCES = \ | ||
21 | evas_callbacks.c \ | ||
22 | evas_clip.c \ | ||
23 | evas_data.c \ | ||
24 | evas_events.c \ | ||
25 | evas_filter.c \ | ||
26 | evas_focus.c \ | ||
27 | evas_key.c \ | ||
28 | evas_key_grab.c \ | ||
29 | evas_layer.c \ | ||
30 | evas_main.c \ | ||
31 | evas_name.c \ | ||
32 | evas_object_image.c \ | ||
33 | evas_object_main.c \ | ||
34 | evas_object_inform.c \ | ||
35 | evas_object_intercept.c \ | ||
36 | evas_object_line.c \ | ||
37 | evas_object_polygon.c \ | ||
38 | evas_object_rectangle.c \ | ||
39 | evas_object_smart.c \ | ||
40 | evas_object_smart_clipped.c \ | ||
41 | evas_object_box.c \ | ||
42 | evas_object_table.c \ | ||
43 | evas_object_text.c \ | ||
44 | evas_object_textblock.c \ | ||
45 | evas_object_grid.c \ | ||
46 | evas_font_dir.c \ | ||
47 | evas_rectangle.c \ | ||
48 | evas_render.c \ | ||
49 | evas_smart.c \ | ||
50 | evas_stack.c \ | ||
51 | evas_async_events.c \ | ||
52 | evas_stats.c \ | ||
53 | evas_touch_point.c \ | ||
54 | evas_map.c \ | ||
55 | evas_gl.c | ||
56 | |||
57 | #evas_object_textgrid.c | ||
58 | |||
59 | libevas_canvas_la_LIBADD = @EVAS_LIBS@ @EVIL_LIBS@ | ||
60 | |||
61 | if EVAS_USE_LINEBREAK | ||
62 | AM_CPPFLAGS += @LINEBREAK_CFLAGS@ | ||
63 | libevas_canvas_la_LIBADD += @LINEBREAK_LIBS@ | ||
64 | endif | ||
65 | |||
66 | clean-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 | |||
18 | VPATH = @srcdir@ | ||
19 | pkgdatadir = $(datadir)/@PACKAGE@ | ||
20 | pkgincludedir = $(includedir)/@PACKAGE@ | ||
21 | pkglibdir = $(libdir)/@PACKAGE@ | ||
22 | pkglibexecdir = $(libexecdir)/@PACKAGE@ | ||
23 | am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd | ||
24 | install_sh_DATA = $(install_sh) -c -m 644 | ||
25 | install_sh_PROGRAM = $(install_sh) -c | ||
26 | install_sh_SCRIPT = $(install_sh) -c | ||
27 | INSTALL_HEADER = $(INSTALL_DATA) | ||
28 | transform = $(program_transform_name) | ||
29 | NORMAL_INSTALL = : | ||
30 | PRE_INSTALL = : | ||
31 | POST_INSTALL = : | ||
32 | NORMAL_UNINSTALL = : | ||
33 | PRE_UNINSTALL = : | ||
34 | POST_UNINSTALL = : | ||
35 | build_triplet = @build@ | ||
36 | host_triplet = @host@ | ||
37 | @EVAS_USE_LINEBREAK_TRUE@am__append_1 = @LINEBREAK_CFLAGS@ | ||
38 | @EVAS_USE_LINEBREAK_TRUE@am__append_2 = @LINEBREAK_LIBS@ | ||
39 | subdir = src/lib/canvas | ||
40 | DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in | ||
41 | ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 | ||
42 | am__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 | ||
55 | am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ | ||
56 | $(ACLOCAL_M4) | ||
57 | mkinstalldirs = $(install_sh) -d | ||
58 | CONFIG_HEADER = $(top_builddir)/config.h | ||
59 | CONFIG_CLEAN_FILES = | ||
60 | CONFIG_CLEAN_VPATH_FILES = | ||
61 | LTLIBRARIES = $(noinst_LTLIBRARIES) | ||
62 | am__DEPENDENCIES_1 = | ||
63 | libevas_canvas_la_DEPENDENCIES = $(am__DEPENDENCIES_1) | ||
64 | am_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 | ||
77 | libevas_canvas_la_OBJECTS = $(am_libevas_canvas_la_OBJECTS) | ||
78 | AM_V_lt = $(am__v_lt_$(V)) | ||
79 | am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY)) | ||
80 | am__v_lt_0 = --silent | ||
81 | DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) | ||
82 | depcomp = $(SHELL) $(top_srcdir)/depcomp | ||
83 | am__depfiles_maybe = depfiles | ||
84 | am__mv = mv -f | ||
85 | COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ | ||
86 | $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) | ||
87 | LTCOMPILE = $(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) | ||
91 | AM_V_CC = $(am__v_CC_$(V)) | ||
92 | am__v_CC_ = $(am__v_CC_$(AM_DEFAULT_VERBOSITY)) | ||
93 | am__v_CC_0 = @echo " CC " $@; | ||
94 | AM_V_at = $(am__v_at_$(V)) | ||
95 | am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY)) | ||
96 | am__v_at_0 = @ | ||
97 | CCLD = $(CC) | ||
98 | LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ | ||
99 | $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ | ||
100 | $(AM_LDFLAGS) $(LDFLAGS) -o $@ | ||
101 | AM_V_CCLD = $(am__v_CCLD_$(V)) | ||
102 | am__v_CCLD_ = $(am__v_CCLD_$(AM_DEFAULT_VERBOSITY)) | ||
103 | am__v_CCLD_0 = @echo " CCLD " $@; | ||
104 | AM_V_GEN = $(am__v_GEN_$(V)) | ||
105 | am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY)) | ||
106 | am__v_GEN_0 = @echo " GEN " $@; | ||
107 | SOURCES = $(libevas_canvas_la_SOURCES) | ||
108 | DIST_SOURCES = $(libevas_canvas_la_SOURCES) | ||
109 | ETAGS = etags | ||
110 | CTAGS = ctags | ||
111 | DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) | ||
112 | ACLOCAL = @ACLOCAL@ | ||
113 | ALLOCA = @ALLOCA@ | ||
114 | AMTAR = @AMTAR@ | ||
115 | AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ | ||
116 | AR = @AR@ | ||
117 | AS = @AS@ | ||
118 | AUTOCONF = @AUTOCONF@ | ||
119 | AUTOHEADER = @AUTOHEADER@ | ||
120 | AUTOMAKE = @AUTOMAKE@ | ||
121 | AWK = @AWK@ | ||
122 | CC = @CC@ | ||
123 | CCDEPMODE = @CCDEPMODE@ | ||
124 | CFLAGS = @CFLAGS@ | ||
125 | CHECK_CFLAGS = @CHECK_CFLAGS@ | ||
126 | CHECK_LIBS = @CHECK_LIBS@ | ||
127 | CPP = @CPP@ | ||
128 | CPPFLAGS = @CPPFLAGS@ | ||
129 | CXX = @CXX@ | ||
130 | CXXCPP = @CXXCPP@ | ||
131 | CXXDEPMODE = @CXXDEPMODE@ | ||
132 | CXXFLAGS = @CXXFLAGS@ | ||
133 | CYGPATH_W = @CYGPATH_W@ | ||
134 | DEFS = @DEFS@ | ||
135 | DEPDIR = @DEPDIR@ | ||
136 | DIRECTFB_CFLAGS = @DIRECTFB_CFLAGS@ | ||
137 | DIRECTFB_LIBS = @DIRECTFB_LIBS@ | ||
138 | DLLTOOL = @DLLTOOL@ | ||
139 | DSYMUTIL = @DSYMUTIL@ | ||
140 | DUMPBIN = @DUMPBIN@ | ||
141 | ECHO_C = @ECHO_C@ | ||
142 | ECHO_N = @ECHO_N@ | ||
143 | ECHO_T = @ECHO_T@ | ||
144 | ECORE_EVAS_CFLAGS = @ECORE_EVAS_CFLAGS@ | ||
145 | ECORE_EVAS_LIBS = @ECORE_EVAS_LIBS@ | ||
146 | EDB_CFLAGS = @EDB_CFLAGS@ | ||
147 | EDB_LIBS = @EDB_LIBS@ | ||
148 | EDJE_CFLAGS = @EDJE_CFLAGS@ | ||
149 | EDJE_LIBS = @EDJE_LIBS@ | ||
150 | EET_CFLAGS = @EET_CFLAGS@ | ||
151 | EET_LIBS = @EET_LIBS@ | ||
152 | EFL_COVERAGE_CFLAGS = @EFL_COVERAGE_CFLAGS@ | ||
153 | EFL_COVERAGE_LIBS = @EFL_COVERAGE_LIBS@ | ||
154 | EFL_FNMATCH_LIBS = @EFL_FNMATCH_LIBS@ | ||
155 | EGREP = @EGREP@ | ||
156 | EINA_CFLAGS = @EINA_CFLAGS@ | ||
157 | EINA_LIBS = @EINA_LIBS@ | ||
158 | EVAS_CFLAGS = @EVAS_CFLAGS@ | ||
159 | EVAS_LIBS = @EVAS_LIBS@ | ||
160 | EVAS_SSE3_CFLAGS = @EVAS_SSE3_CFLAGS@ | ||
161 | EVIL_CFLAGS = @EVIL_CFLAGS@ | ||
162 | EVIL_LIBS = @EVIL_LIBS@ | ||
163 | EXEEXT = @EXEEXT@ | ||
164 | EXOTIC_CFLAGS = @EXOTIC_CFLAGS@ | ||
165 | EXOTIC_LIBS = @EXOTIC_LIBS@ | ||
166 | FGREP = @FGREP@ | ||
167 | FONTCONFIG_CFLAGS = @FONTCONFIG_CFLAGS@ | ||
168 | FONTCONFIG_LIBS = @FONTCONFIG_LIBS@ | ||
169 | FREETYPE_CFLAGS = @FREETYPE_CFLAGS@ | ||
170 | FREETYPE_LIBS = @FREETYPE_LIBS@ | ||
171 | FRIBIDI_CFLAGS = @FRIBIDI_CFLAGS@ | ||
172 | FRIBIDI_LIBS = @FRIBIDI_LIBS@ | ||
173 | GL_EET_CFLAGS = @GL_EET_CFLAGS@ | ||
174 | GL_EET_LIBS = @GL_EET_LIBS@ | ||
175 | GREP = @GREP@ | ||
176 | HARFBUZZ_CFLAGS = @HARFBUZZ_CFLAGS@ | ||
177 | HARFBUZZ_LIBS = @HARFBUZZ_LIBS@ | ||
178 | INSTALL = @INSTALL@ | ||
179 | INSTALL_DATA = @INSTALL_DATA@ | ||
180 | INSTALL_PROGRAM = @INSTALL_PROGRAM@ | ||
181 | INSTALL_SCRIPT = @INSTALL_SCRIPT@ | ||
182 | INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ | ||
183 | LD = @LD@ | ||
184 | LDFLAGS = @LDFLAGS@ | ||
185 | LIBOBJS = @LIBOBJS@ | ||
186 | LIBS = @LIBS@ | ||
187 | LIBTOOL = @LIBTOOL@ | ||
188 | LINEBREAK_CFLAGS = @LINEBREAK_CFLAGS@ | ||
189 | LINEBREAK_LIBS = @LINEBREAK_LIBS@ | ||
190 | LIPO = @LIPO@ | ||
191 | LN_S = @LN_S@ | ||
192 | LTLIBOBJS = @LTLIBOBJS@ | ||
193 | MAKEINFO = @MAKEINFO@ | ||
194 | MKDIR_P = @MKDIR_P@ | ||
195 | MODULE_ARCH = @MODULE_ARCH@ | ||
196 | NM = @NM@ | ||
197 | NMEDIT = @NMEDIT@ | ||
198 | OBJC = @OBJC@ | ||
199 | OBJCDEPMODE = @OBJCDEPMODE@ | ||
200 | OBJCFLAGS = @OBJCFLAGS@ | ||
201 | OBJDUMP = @OBJDUMP@ | ||
202 | OBJEXT = @OBJEXT@ | ||
203 | OTOOL = @OTOOL@ | ||
204 | OTOOL64 = @OTOOL64@ | ||
205 | PACKAGE = @PACKAGE@ | ||
206 | PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ | ||
207 | PACKAGE_NAME = @PACKAGE_NAME@ | ||
208 | PACKAGE_STRING = @PACKAGE_STRING@ | ||
209 | PACKAGE_TARNAME = @PACKAGE_TARNAME@ | ||
210 | PACKAGE_URL = @PACKAGE_URL@ | ||
211 | PACKAGE_VERSION = @PACKAGE_VERSION@ | ||
212 | PATH_SEPARATOR = @PATH_SEPARATOR@ | ||
213 | PIXMAN_CFLAGS = @PIXMAN_CFLAGS@ | ||
214 | PIXMAN_LIBS = @PIXMAN_LIBS@ | ||
215 | PKG_CONFIG = @PKG_CONFIG@ | ||
216 | PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@ | ||
217 | PKG_CONFIG_PATH = @PKG_CONFIG_PATH@ | ||
218 | PNG_CFLAGS = @PNG_CFLAGS@ | ||
219 | PNG_LIBS = @PNG_LIBS@ | ||
220 | RANLIB = @RANLIB@ | ||
221 | SDL_CFLAGS = @SDL_CFLAGS@ | ||
222 | SDL_LIBS = @SDL_LIBS@ | ||
223 | SED = @SED@ | ||
224 | SET_MAKE = @SET_MAKE@ | ||
225 | SHELL = @SHELL@ | ||
226 | SHM_OPEN_LINK = @SHM_OPEN_LINK@ | ||
227 | STRIP = @STRIP@ | ||
228 | SVG_CFLAGS = @SVG_CFLAGS@ | ||
229 | SVG_LIBS = @SVG_LIBS@ | ||
230 | VALGRIND_CFLAGS = @VALGRIND_CFLAGS@ | ||
231 | VALGRIND_LIBS = @VALGRIND_LIBS@ | ||
232 | VERSION = @VERSION@ | ||
233 | VMAJ = @VMAJ@ | ||
234 | WAYLAND_EGL_CFLAGS = @WAYLAND_EGL_CFLAGS@ | ||
235 | WAYLAND_EGL_LIBS = @WAYLAND_EGL_LIBS@ | ||
236 | XCB_CFLAGS = @XCB_CFLAGS@ | ||
237 | XCB_GL_CFLAGS = @XCB_GL_CFLAGS@ | ||
238 | XCB_GL_LIBS = @XCB_GL_LIBS@ | ||
239 | XCB_LIBS = @XCB_LIBS@ | ||
240 | XEXT_CFLAGS = @XEXT_CFLAGS@ | ||
241 | XEXT_LIBS = @XEXT_LIBS@ | ||
242 | XMKMF = @XMKMF@ | ||
243 | X_CFLAGS = @X_CFLAGS@ | ||
244 | X_EXTRA_LIBS = @X_EXTRA_LIBS@ | ||
245 | X_LIBS = @X_LIBS@ | ||
246 | X_PRE_LIBS = @X_PRE_LIBS@ | ||
247 | abs_builddir = @abs_builddir@ | ||
248 | abs_srcdir = @abs_srcdir@ | ||
249 | abs_top_builddir = @abs_top_builddir@ | ||
250 | abs_top_srcdir = @abs_top_srcdir@ | ||
251 | ac_ct_CC = @ac_ct_CC@ | ||
252 | ac_ct_CXX = @ac_ct_CXX@ | ||
253 | ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ | ||
254 | ac_ct_OBJC = @ac_ct_OBJC@ | ||
255 | altivec_cflags = @altivec_cflags@ | ||
256 | am__include = @am__include@ | ||
257 | am__leading_dot = @am__leading_dot@ | ||
258 | am__quote = @am__quote@ | ||
259 | am__tar = @am__tar@ | ||
260 | am__untar = @am__untar@ | ||
261 | bindir = @bindir@ | ||
262 | build = @build@ | ||
263 | build_alias = @build_alias@ | ||
264 | build_cpu = @build_cpu@ | ||
265 | build_os = @build_os@ | ||
266 | build_vendor = @build_vendor@ | ||
267 | builddir = @builddir@ | ||
268 | datadir = @datadir@ | ||
269 | datarootdir = @datarootdir@ | ||
270 | dlopen_libs = @dlopen_libs@ | ||
271 | docdir = @docdir@ | ||
272 | dvidir = @dvidir@ | ||
273 | edje_cc = @edje_cc@ | ||
274 | efl_doxygen = @efl_doxygen@ | ||
275 | efl_have_doxygen = @efl_have_doxygen@ | ||
276 | evas_engine_buffer_cflags = @evas_engine_buffer_cflags@ | ||
277 | evas_engine_buffer_libs = @evas_engine_buffer_libs@ | ||
278 | evas_engine_direct3d_cflags = @evas_engine_direct3d_cflags@ | ||
279 | evas_engine_direct3d_libs = @evas_engine_direct3d_libs@ | ||
280 | evas_engine_directfb_cflags = @evas_engine_directfb_cflags@ | ||
281 | evas_engine_directfb_libs = @evas_engine_directfb_libs@ | ||
282 | evas_engine_fb_cflags = @evas_engine_fb_cflags@ | ||
283 | evas_engine_fb_libs = @evas_engine_fb_libs@ | ||
284 | evas_engine_gl_cocoa_cflags = @evas_engine_gl_cocoa_cflags@ | ||
285 | evas_engine_gl_cocoa_libs = @evas_engine_gl_cocoa_libs@ | ||
286 | evas_engine_gl_common_libs = @evas_engine_gl_common_libs@ | ||
287 | evas_engine_gl_sdl_cflags = @evas_engine_gl_sdl_cflags@ | ||
288 | evas_engine_gl_sdl_libs = @evas_engine_gl_sdl_libs@ | ||
289 | evas_engine_gl_xcb_cflags = @evas_engine_gl_xcb_cflags@ | ||
290 | evas_engine_gl_xcb_libs = @evas_engine_gl_xcb_libs@ | ||
291 | evas_engine_gl_xlib_cflags = @evas_engine_gl_xlib_cflags@ | ||
292 | evas_engine_gl_xlib_libs = @evas_engine_gl_xlib_libs@ | ||
293 | evas_engine_psl1ght_cflags = @evas_engine_psl1ght_cflags@ | ||
294 | evas_engine_psl1ght_libs = @evas_engine_psl1ght_libs@ | ||
295 | evas_engine_software_16_ddraw_cflags = @evas_engine_software_16_ddraw_cflags@ | ||
296 | evas_engine_software_16_ddraw_libs = @evas_engine_software_16_ddraw_libs@ | ||
297 | evas_engine_software_16_sdl_cflags = @evas_engine_software_16_sdl_cflags@ | ||
298 | evas_engine_software_16_sdl_libs = @evas_engine_software_16_sdl_libs@ | ||
299 | evas_engine_software_16_wince_cflags = @evas_engine_software_16_wince_cflags@ | ||
300 | evas_engine_software_16_wince_libs = @evas_engine_software_16_wince_libs@ | ||
301 | evas_engine_software_16_x11_cflags = @evas_engine_software_16_x11_cflags@ | ||
302 | evas_engine_software_16_x11_libs = @evas_engine_software_16_x11_libs@ | ||
303 | evas_engine_software_8_x11_cflags = @evas_engine_software_8_x11_cflags@ | ||
304 | evas_engine_software_8_x11_libs = @evas_engine_software_8_x11_libs@ | ||
305 | evas_engine_software_ddraw_cflags = @evas_engine_software_ddraw_cflags@ | ||
306 | evas_engine_software_ddraw_libs = @evas_engine_software_ddraw_libs@ | ||
307 | evas_engine_software_gdi_cflags = @evas_engine_software_gdi_cflags@ | ||
308 | evas_engine_software_gdi_libs = @evas_engine_software_gdi_libs@ | ||
309 | evas_engine_software_xcb_cflags = @evas_engine_software_xcb_cflags@ | ||
310 | evas_engine_software_xcb_libs = @evas_engine_software_xcb_libs@ | ||
311 | evas_engine_software_xlib_cflags = @evas_engine_software_xlib_cflags@ | ||
312 | evas_engine_software_xlib_libs = @evas_engine_software_xlib_libs@ | ||
313 | evas_engine_wayland_egl_cflags = @evas_engine_wayland_egl_cflags@ | ||
314 | evas_engine_wayland_egl_libs = @evas_engine_wayland_egl_libs@ | ||
315 | evas_engine_wayland_shm_cflags = @evas_engine_wayland_shm_cflags@ | ||
316 | evas_engine_wayland_shm_libs = @evas_engine_wayland_shm_libs@ | ||
317 | evas_image_loader_bmp_cflags = @evas_image_loader_bmp_cflags@ | ||
318 | evas_image_loader_bmp_libs = @evas_image_loader_bmp_libs@ | ||
319 | evas_image_loader_edb_cflags = @evas_image_loader_edb_cflags@ | ||
320 | evas_image_loader_edb_libs = @evas_image_loader_edb_libs@ | ||
321 | evas_image_loader_eet_cflags = @evas_image_loader_eet_cflags@ | ||
322 | evas_image_loader_eet_libs = @evas_image_loader_eet_libs@ | ||
323 | evas_image_loader_generic_cflags = @evas_image_loader_generic_cflags@ | ||
324 | evas_image_loader_generic_libs = @evas_image_loader_generic_libs@ | ||
325 | evas_image_loader_gif_cflags = @evas_image_loader_gif_cflags@ | ||
326 | evas_image_loader_gif_libs = @evas_image_loader_gif_libs@ | ||
327 | evas_image_loader_ico_cflags = @evas_image_loader_ico_cflags@ | ||
328 | evas_image_loader_ico_libs = @evas_image_loader_ico_libs@ | ||
329 | evas_image_loader_jpeg_cflags = @evas_image_loader_jpeg_cflags@ | ||
330 | evas_image_loader_jpeg_libs = @evas_image_loader_jpeg_libs@ | ||
331 | evas_image_loader_pmaps_cflags = @evas_image_loader_pmaps_cflags@ | ||
332 | evas_image_loader_pmaps_libs = @evas_image_loader_pmaps_libs@ | ||
333 | evas_image_loader_png_cflags = @evas_image_loader_png_cflags@ | ||
334 | evas_image_loader_png_libs = @evas_image_loader_png_libs@ | ||
335 | evas_image_loader_psd_cflags = @evas_image_loader_psd_cflags@ | ||
336 | evas_image_loader_psd_libs = @evas_image_loader_psd_libs@ | ||
337 | evas_image_loader_svg_cflags = @evas_image_loader_svg_cflags@ | ||
338 | evas_image_loader_svg_libs = @evas_image_loader_svg_libs@ | ||
339 | evas_image_loader_tga_cflags = @evas_image_loader_tga_cflags@ | ||
340 | evas_image_loader_tga_libs = @evas_image_loader_tga_libs@ | ||
341 | evas_image_loader_tiff_cflags = @evas_image_loader_tiff_cflags@ | ||
342 | evas_image_loader_tiff_libs = @evas_image_loader_tiff_libs@ | ||
343 | evas_image_loader_wbmp_cflags = @evas_image_loader_wbmp_cflags@ | ||
344 | evas_image_loader_wbmp_libs = @evas_image_loader_wbmp_libs@ | ||
345 | evas_image_loader_xpm_cflags = @evas_image_loader_xpm_cflags@ | ||
346 | evas_image_loader_xpm_libs = @evas_image_loader_xpm_libs@ | ||
347 | exec_prefix = @exec_prefix@ | ||
348 | have_evas_engine_gl_x11 = @have_evas_engine_gl_x11@ | ||
349 | have_evas_engine_gl_xcb = @have_evas_engine_gl_xcb@ | ||
350 | have_evas_engine_gl_xlib = @have_evas_engine_gl_xlib@ | ||
351 | have_evas_engine_software_x11 = @have_evas_engine_software_x11@ | ||
352 | have_evas_engine_software_xcb = @have_evas_engine_software_xcb@ | ||
353 | have_evas_engine_software_xlib = @have_evas_engine_software_xlib@ | ||
354 | have_lcov = @have_lcov@ | ||
355 | host = @host@ | ||
356 | host_alias = @host_alias@ | ||
357 | host_cpu = @host_cpu@ | ||
358 | host_os = @host_os@ | ||
359 | host_vendor = @host_vendor@ | ||
360 | htmldir = @htmldir@ | ||
361 | includedir = @includedir@ | ||
362 | infodir = @infodir@ | ||
363 | install_sh = @install_sh@ | ||
364 | libdir = @libdir@ | ||
365 | libexecdir = @libexecdir@ | ||
366 | localedir = @localedir@ | ||
367 | localstatedir = @localstatedir@ | ||
368 | lt_ECHO = @lt_ECHO@ | ||
369 | lt_enable_auto_import = @lt_enable_auto_import@ | ||
370 | mandir = @mandir@ | ||
371 | mkdir_p = @mkdir_p@ | ||
372 | oldincludedir = @oldincludedir@ | ||
373 | pdfdir = @pdfdir@ | ||
374 | pkgconfig_requires_private = @pkgconfig_requires_private@ | ||
375 | prefix = @prefix@ | ||
376 | program_transform_name = @program_transform_name@ | ||
377 | psdir = @psdir@ | ||
378 | pthread_cflags = @pthread_cflags@ | ||
379 | pthread_libs = @pthread_libs@ | ||
380 | release_info = @release_info@ | ||
381 | requirement_evas = @requirement_evas@ | ||
382 | sbindir = @sbindir@ | ||
383 | sharedstatedir = @sharedstatedir@ | ||
384 | srcdir = @srcdir@ | ||
385 | sysconfdir = @sysconfdir@ | ||
386 | target_alias = @target_alias@ | ||
387 | top_build_prefix = @top_build_prefix@ | ||
388 | top_builddir = @top_builddir@ | ||
389 | top_srcdir = @top_srcdir@ | ||
390 | version_info = @version_info@ | ||
391 | MAINTAINERCLEANFILES = Makefile.in | ||
392 | AM_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) | ||
399 | noinst_LTLIBRARIES = libevas_canvas.la | ||
400 | libevas_canvas_la_SOURCES = \ | ||
401 | evas_callbacks.c \ | ||
402 | evas_clip.c \ | ||
403 | evas_data.c \ | ||
404 | evas_events.c \ | ||
405 | evas_filter.c \ | ||
406 | evas_focus.c \ | ||
407 | evas_key.c \ | ||
408 | evas_key_grab.c \ | ||
409 | evas_layer.c \ | ||
410 | evas_main.c \ | ||
411 | evas_name.c \ | ||
412 | evas_object_image.c \ | ||
413 | evas_object_main.c \ | ||
414 | evas_object_inform.c \ | ||
415 | evas_object_intercept.c \ | ||
416 | evas_object_line.c \ | ||
417 | evas_object_polygon.c \ | ||
418 | evas_object_rectangle.c \ | ||
419 | evas_object_smart.c \ | ||
420 | evas_object_smart_clipped.c \ | ||
421 | evas_object_box.c \ | ||
422 | evas_object_table.c \ | ||
423 | evas_object_text.c \ | ||
424 | evas_object_textblock.c \ | ||
425 | evas_object_grid.c \ | ||
426 | evas_font_dir.c \ | ||
427 | evas_rectangle.c \ | ||
428 | evas_render.c \ | ||
429 | evas_smart.c \ | ||
430 | evas_stack.c \ | ||
431 | evas_async_events.c \ | ||
432 | evas_stats.c \ | ||
433 | evas_touch_point.c \ | ||
434 | evas_map.c \ | ||
435 | evas_gl.c | ||
436 | |||
437 | |||
438 | #evas_object_textgrid.c | ||
439 | libevas_canvas_la_LIBADD = @EVAS_LIBS@ @EVIL_LIBS@ $(am__append_2) | ||
440 | all: 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 | ||
457 | Makefile: $(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 | |||
475 | clean-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 | ||
483 | libevas_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 | |||
486 | mostlyclean-compile: | ||
487 | -rm -f *.$(OBJEXT) | ||
488 | |||
489 | distclean-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 | |||
552 | mostlyclean-libtool: | ||
553 | -rm -f *.lo | ||
554 | |||
555 | clean-libtool: | ||
556 | -rm -rf .libs _libs | ||
557 | |||
558 | ID: $(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 | ||
566 | tags: TAGS | ||
567 | |||
568 | TAGS: $(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 | ||
589 | ctags: CTAGS | ||
590 | CTAGS: $(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 | |||
602 | GTAGS: | ||
603 | here=`$(am__cd) $(top_builddir) && pwd` \ | ||
604 | && $(am__cd) $(top_srcdir) \ | ||
605 | && gtags -i $(GTAGS_ARGS) "$$here" | ||
606 | |||
607 | distclean-tags: | ||
608 | -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags | ||
609 | |||
610 | distdir: $(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 | ||
640 | check-am: all-am | ||
641 | check: check-am | ||
642 | all-am: Makefile $(LTLIBRARIES) | ||
643 | installdirs: | ||
644 | install: install-am | ||
645 | install-exec: install-exec-am | ||
646 | install-data: install-data-am | ||
647 | uninstall: uninstall-am | ||
648 | |||
649 | install-am: all-am | ||
650 | @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am | ||
651 | |||
652 | installcheck: installcheck-am | ||
653 | install-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 | ||
658 | mostlyclean-generic: | ||
659 | |||
660 | clean-generic: | ||
661 | |||
662 | distclean-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 | |||
666 | maintainer-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) | ||
670 | clean: clean-am | ||
671 | |||
672 | clean-am: clean-generic clean-libtool clean-local \ | ||
673 | clean-noinstLTLIBRARIES mostlyclean-am | ||
674 | |||
675 | distclean: distclean-am | ||
676 | -rm -rf ./$(DEPDIR) | ||
677 | -rm -f Makefile | ||
678 | distclean-am: clean-am distclean-compile distclean-generic \ | ||
679 | distclean-tags | ||
680 | |||
681 | dvi: dvi-am | ||
682 | |||
683 | dvi-am: | ||
684 | |||
685 | html: html-am | ||
686 | |||
687 | html-am: | ||
688 | |||
689 | info: info-am | ||
690 | |||
691 | info-am: | ||
692 | |||
693 | install-data-am: | ||
694 | |||
695 | install-dvi: install-dvi-am | ||
696 | |||
697 | install-dvi-am: | ||
698 | |||
699 | install-exec-am: | ||
700 | |||
701 | install-html: install-html-am | ||
702 | |||
703 | install-html-am: | ||
704 | |||
705 | install-info: install-info-am | ||
706 | |||
707 | install-info-am: | ||
708 | |||
709 | install-man: | ||
710 | |||
711 | install-pdf: install-pdf-am | ||
712 | |||
713 | install-pdf-am: | ||
714 | |||
715 | install-ps: install-ps-am | ||
716 | |||
717 | install-ps-am: | ||
718 | |||
719 | installcheck-am: | ||
720 | |||
721 | maintainer-clean: maintainer-clean-am | ||
722 | -rm -rf ./$(DEPDIR) | ||
723 | -rm -f Makefile | ||
724 | maintainer-clean-am: distclean-am maintainer-clean-generic | ||
725 | |||
726 | mostlyclean: mostlyclean-am | ||
727 | |||
728 | mostlyclean-am: mostlyclean-compile mostlyclean-generic \ | ||
729 | mostlyclean-libtool | ||
730 | |||
731 | pdf: pdf-am | ||
732 | |||
733 | pdf-am: | ||
734 | |||
735 | ps: ps-am | ||
736 | |||
737 | ps-am: | ||
738 | |||
739 | uninstall-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 | |||
758 | clean-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 | |||
20 | static int _fd_write = -1; | ||
21 | static int _fd_read = -1; | ||
22 | |||
23 | static int _init_evas_event = 0; | ||
24 | |||
25 | typedef struct _Evas_Event_Async Evas_Event_Async; | ||
26 | |||
27 | struct _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 | |||
35 | int | ||
36 | evas_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 | |||
57 | int | ||
58 | evas_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 | |||
73 | EAPI int | ||
74 | evas_async_events_fd_get(void) | ||
75 | { | ||
76 | #ifdef BUILD_ASYNC_EVENTS | ||
77 | return _fd_read; | ||
78 | #else | ||
79 | return -1; | ||
80 | #endif | ||
81 | } | ||
82 | |||
83 | EAPI int | ||
84 | evas_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 | |||
126 | EAPI Eina_Bool | ||
127 | evas_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 | |||
4 | static void evas_object_event_callback_clear(Evas_Object *obj); | ||
5 | static void evas_event_callback_clear(Evas *e); | ||
6 | int _evas_event_counter = 0; | ||
7 | |||
8 | EVAS_MEMPOOL(_mp_fn); | ||
9 | EVAS_MEMPOOL(_mp_cb); | ||
10 | EVAS_MEMPOOL(_mp_pc); | ||
11 | |||
12 | void | ||
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 | |||
31 | void | ||
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 | |||
43 | void | ||
44 | evas_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 | |||
63 | static void | ||
64 | evas_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 | |||
77 | static void | ||
78 | evas_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 | |||
91 | void | ||
92 | evas_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 | |||
101 | void | ||
102 | evas_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 | |||
111 | void | ||
112 | evas_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 | |||
121 | void | ||
122 | evas_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 | |||
131 | void | ||
132 | evas_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 | |||
164 | void | ||
165 | evas_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 | |||
268 | static 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 | |||
280 | EAPI void | ||
281 | evas_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 | |||
287 | EAPI void | ||
288 | evas_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 | |||
321 | EAPI void * | ||
322 | evas_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 | |||
352 | EAPI void * | ||
353 | evas_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 | |||
383 | EAPI void | ||
384 | evas_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 | |||
390 | EAPI void | ||
391 | evas_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 | |||
423 | EAPI void * | ||
424 | evas_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 | |||
454 | EAPI void * | ||
455 | evas_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 | |||
485 | EAPI void | ||
486 | evas_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 | |||
505 | EAPI void | ||
506 | evas_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 | |||
525 | EAPI void | ||
526 | evas_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 | |||
4 | void | ||
5 | evas_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 | |||
17 | void | ||
18 | evas_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 | |||
31 | int | ||
32 | evas_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 | ||
78 | static void | ||
79 | evas_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 | |||
110 | void | ||
111 | evas_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 | |||
120 | void | ||
121 | evas_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 | ||
144 | void | ||
145 | evas_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 */ | ||
162 | extern const char *o_rect_type; | ||
163 | |||
164 | EAPI void | ||
165 | evas_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 | |||
257 | EAPI Evas_Object * | ||
258 | evas_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 | |||
266 | EAPI void | ||
267 | evas_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 | |||
314 | EAPI const Eina_List * | ||
315 | evas_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 | |||
5 | EAPI void | ||
6 | evas_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 | |||
24 | EAPI void * | ||
25 | evas_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 | |||
49 | EAPI void * | ||
50 | evas_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 | |||
4 | static 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 | |||
9 | static 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 | |||
23 | static 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 | |||
123 | static 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 | |||
133 | Eina_List * | ||
134 | evas_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 | |||
151 | static Eina_List * | ||
152 | evas_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 | |||
163 | EAPI void | ||
164 | evas_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 | |||
172 | EAPI Evas_Event_Flags | ||
173 | evas_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 | |||
181 | EAPI void | ||
182 | evas_event_freeze(Evas *e) | ||
183 | { | ||
184 | MAGIC_CHECK(e, Evas, MAGIC_EVAS); | ||
185 | return; | ||
186 | MAGIC_CHECK_END(); | ||
187 | e->events_frozen++; | ||
188 | } | ||
189 | |||
190 | EAPI void | ||
191 | evas_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 | |||
216 | EAPI int | ||
217 | evas_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 | |||
225 | EAPI void | ||
226 | evas_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 | |||
237 | EAPI void | ||
238 | evas_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 | |||
328 | static 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 | |||
435 | EAPI void | ||
436 | evas_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 | |||
521 | EAPI void | ||
522 | evas_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 | |||
542 | EAPI void | ||
543 | evas_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 | |||
590 | EAPI void | ||
591 | evas_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; | ||
859 | nogrep: | ||
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 | |||
1014 | EAPI void | ||
1015 | evas_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 | |||
1075 | EAPI void | ||
1076 | evas_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 | |||
1137 | EAPI void | ||
1138 | evas_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 | |||
1220 | EAPI void | ||
1221 | evas_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 | |||
1297 | EAPI void | ||
1298 | evas_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 | |||
1452 | EAPI void | ||
1453 | evas_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 | |||
1539 | EAPI void | ||
1540 | evas_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 | |||
1624 | EAPI void | ||
1625 | evas_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 | |||
1661 | EAPI void | ||
1662 | evas_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 | |||
1674 | EAPI Eina_Bool | ||
1675 | evas_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 | |||
1683 | EAPI void | ||
1684 | evas_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 | |||
1707 | EAPI Eina_Bool | ||
1708 | evas_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 | |||
1716 | EAPI void | ||
1717 | evas_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 | |||
1739 | EAPI Eina_Bool | ||
1740 | evas_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 | |||
1748 | EAPI void | ||
1749 | evas_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 | |||
1757 | EAPI Eina_Bool | ||
1758 | evas_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 | |||
1766 | EAPI void | ||
1767 | evas_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 | |||
1775 | EAPI Evas_Object_Pointer_Mode | ||
1776 | evas_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 | |||
1784 | EAPI void | ||
1785 | evas_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 | |||
1860 | EAPI int | ||
1861 | evas_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 | ||
6 | typedef 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; | ||
13 | typedef 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 | |||
197 | typedef struct Evas_Filter_Info_Blur | ||
198 | { | ||
199 | double quality; | ||
200 | int radius; | ||
201 | } Evas_Filter_Info_Blur; | ||
202 | |||
203 | typedef struct Evas_Filter_Info_GreyScale | ||
204 | { | ||
205 | double r,g,b; | ||
206 | } Evas_Filter_Info_GreyScale; | ||
207 | |||
208 | typedef struct Evas_Filter_Info_Brightness | ||
209 | { | ||
210 | double adjust; | ||
211 | } Evas_Filter_Info_Brightness; | ||
212 | |||
213 | typedef struct Evas_Filter_Info_Contrast | ||
214 | { | ||
215 | double adjust; | ||
216 | } Evas_Filter_Info_Contrast; | ||
217 | |||
218 | typedef int (*Filter_Size_FN)(Evas_Filter_Info *,int,int,int*,int*,Eina_Bool); | ||
219 | typedef uint8_t *(*Key_FN)(const Evas_Filter_Info *, uint32_t *); | ||
220 | |||
221 | struct fieldinfo | ||
222 | { | ||
223 | const char *field; | ||
224 | int type; | ||
225 | size_t offset; | ||
226 | }; | ||
227 | |||
228 | struct 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 | |||
237 | enum | ||
238 | { | ||
239 | TYPE_INT, | ||
240 | TYPE_FLOAT | ||
241 | }; | ||
242 | |||
243 | static int blur_size_get(Evas_Filter_Info*, int, int, int *, int *, Eina_Bool); | ||
244 | static uint8_t *gaussian_key_get(const Evas_Filter_Info *, uint32_t *); | ||
245 | |||
246 | static Eina_Bool gaussian_filter(Evas_Filter_Info *, RGBA_Image*, RGBA_Image*); | ||
247 | static Eina_Bool negation_filter(Evas_Filter_Info *, RGBA_Image*, RGBA_Image*); | ||
248 | static Eina_Bool sepia_filter(Evas_Filter_Info *, RGBA_Image*, RGBA_Image*); | ||
249 | static Eina_Bool greyscale_filter(Evas_Filter_Info*, RGBA_Image*, RGBA_Image*); | ||
250 | static Eina_Bool brightness_filter(Evas_Filter_Info*, RGBA_Image*, RGBA_Image*); | ||
251 | static Eina_Bool contrast_filter(Evas_Filter_Info *, RGBA_Image*, RGBA_Image*); | ||
252 | |||
253 | struct 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 | |||
272 | static 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 | |||
279 | static 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 | |||
291 | static struct fieldinfo brightnessfields[] = | ||
292 | { | ||
293 | { "adjust", TYPE_FLOAT, offsetof(Evas_Filter_Info_Brightness, adjust) }, | ||
294 | { NULL, 0, 0 }, | ||
295 | }; | ||
296 | |||
297 | static struct fieldinfo contrastfields[] = | ||
298 | { | ||
299 | { "adjust", TYPE_FLOAT, offsetof(Evas_Filter_Info_Contrast, adjust) }, | ||
300 | { NULL, 0, 0 }, | ||
301 | }; | ||
302 | |||
303 | static struct fieldinfo *filterfields[] = | ||
304 | { | ||
305 | NULL, | ||
306 | blurfields, | ||
307 | NULL, | ||
308 | NULL, | ||
309 | greyfields, | ||
310 | brightnessfields, | ||
311 | contrastfields, | ||
312 | }; | ||
313 | |||
314 | static Evas_Filter_Info *filter_alloc(Evas_Object *o); | ||
315 | |||
316 | EAPI Eina_Bool | ||
317 | evas_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 | |||
341 | EAPI Evas_Filter_Mode | ||
342 | evas_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 | |||
352 | EAPI Eina_Bool | ||
353 | evas_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 | |||
404 | EAPI Evas_Filter | ||
405 | evas_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 | |||
415 | EAPI Eina_Bool | ||
416 | evas_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 | |||
446 | EAPI int | ||
447 | evas_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 | |||
476 | EAPI Eina_Bool | ||
477 | evas_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 | |||
484 | EAPI const char * | ||
485 | evas_object_filter_param_str_get(Evas_Object *o __UNUSED__, | ||
486 | const char *param __UNUSED__) | ||
487 | { | ||
488 | return NULL; | ||
489 | } | ||
490 | |||
491 | EAPI Eina_Bool | ||
492 | evas_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 | |||
499 | EAPI Evas_Object * | ||
500 | evas_object_filter_param_obj_get(Evas_Object *o __UNUSED__, | ||
501 | const char *param __UNUSED__) | ||
502 | { | ||
503 | return NULL; | ||
504 | } | ||
505 | |||
506 | EAPI Eina_Bool | ||
507 | evas_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 | |||
542 | EAPI double | ||
543 | evas_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 | */ | ||
579 | int | ||
580 | evas_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 | |||
594 | Eina_Bool | ||
595 | evas_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 | */ | ||
618 | uint8_t * | ||
619 | evas_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 | |||
639 | Evas_Software_Filter_Fn | ||
640 | evas_filter_software_get(Evas_Filter_Info *info) | ||
641 | { | ||
642 | return filterinfo[info->filter].filter; | ||
643 | } | ||
644 | |||
645 | void | ||
646 | evas_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 | */ | ||
660 | static Evas_Filter_Info * | ||
661 | filter_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 | |||
678 | static int | ||
679 | blur_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 | */ | ||
709 | static uint8_t * | ||
710 | gaussian_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 | |||
760 | typedef int (*FilterH)(int, uint32_t *, int, uint32_t *); | ||
761 | typedef int (*FilterV)(int, uint32_t *, int, int, uint32_t *); | ||
762 | |||
763 | static int gaussian_filter_h(int rad, uint32_t *in, int w, uint32_t *out); | ||
764 | static int gaussian_filter_h64(int rad, uint32_t *in, int w, uint32_t *out); | ||
765 | static int gaussian_filter_hd(int rad, uint32_t *in, int w, uint32_t *out); | ||
766 | static int gaussian_filter_v(int rad, uint32_t *in, int h, int skip, uint32_t *out); | ||
767 | static int gaussian_filter_v64(int rad, uint32_t *in, int h, int skip, uint32_t *out); | ||
768 | static int gaussian_filter_vd(int rad, uint32_t *in, int h, int skip, uint32_t *out); | ||
769 | static const uint32_t *gaussian_row_get(int row, int *npoints, uint32_t *weight); | ||
770 | static const uint64_t *gaussian_row_get64(int row, int *npoints, uint64_t *weight); | ||
771 | static const double *gaussian_row_getd(int row, int *npoints, double *weight); | ||
772 | |||
773 | static Eina_Bool | ||
774 | gaussian_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 */ | ||
824 | static int | ||
825 | gaussian_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 */ | ||
854 | static int | ||
855 | gaussian_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 */ | ||
885 | static int | ||
886 | gaussian_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 | |||
912 | static int | ||
913 | gaussian_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 | |||
944 | static int | ||
945 | gaussian_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 | |||
976 | static int | ||
977 | gaussian_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 | |||
1008 | static const uint32_t * | ||
1009 | gaussian_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 | |||
1047 | static const uint64_t * | ||
1048 | gaussian_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 | |||
1087 | static const double * | ||
1088 | gaussian_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 | ||
1129 | static Eina_Bool | ||
1130 | negation_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 | |||
1186 | static Eina_Bool | ||
1187 | negation_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 | |||
1242 | static Eina_Bool | ||
1243 | sepia_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 | |||
1279 | static Eina_Bool | ||
1280 | greyscale_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 | |||
1329 | static Eina_Bool | ||
1330 | brightness_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 | |||
1400 | static Eina_Bool | ||
1401 | contrast_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 | |||
10 | EAPI void | ||
11 | evas_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 | |||
45 | EAPI Eina_Bool | ||
46 | evas_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 | |||
54 | EAPI Evas_Object * | ||
55 | evas_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 */ | ||
21 | static Eina_Hash *font_dirs = NULL; | ||
22 | static Eina_List *fonts_cache = NULL; | ||
23 | static Eina_List *fonts_zero = NULL; | ||
24 | |||
25 | typedef struct _Fndat Fndat; | ||
26 | |||
27 | struct _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 */ | ||
43 | static Eina_Bool font_cache_dir_free(const Eina_Hash *hash, const void *key, void *data, void *fdata); | ||
44 | static Evas_Font_Dir *object_text_font_cache_dir_update(char *dir, Evas_Font_Dir *fd); | ||
45 | static Evas_Font *object_text_font_cache_font_find_x(Evas_Font_Dir *fd, char *font); | ||
46 | static Evas_Font *object_text_font_cache_font_find_file(Evas_Font_Dir *fd, char *font); | ||
47 | static Evas_Font *object_text_font_cache_font_find_alias(Evas_Font_Dir *fd, char *font); | ||
48 | static Evas_Font *object_text_font_cache_font_find(Evas_Font_Dir *fd, char *font); | ||
49 | static Evas_Font_Dir *object_text_font_cache_dir_add(char *dir); | ||
50 | static void object_text_font_cache_dir_del(char *dir, Evas_Font_Dir *fd); | ||
51 | static int evas_object_text_font_string_parse(char *buffer, char dest[14][256]); | ||
52 | |||
53 | #ifdef HAVE_FONTCONFIG | ||
54 | static int fc_init = 0; | ||
55 | #endif | ||
56 | |||
57 | void | ||
58 | evas_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 | |||
80 | const char * | ||
81 | evas_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 | |||
101 | static Eina_List * | ||
102 | evas_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 | |||
132 | void | ||
133 | evas_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 | |||
150 | void | ||
151 | evas_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 | |||
176 | void | ||
177 | evas_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 | |||
216 | static void | ||
217 | evas_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 | ||
233 | static Evas_Font_Set * | ||
234 | evas_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 */ | ||
259 | static int _fc_slant_map[] = | ||
260 | { | ||
261 | FC_SLANT_ROMAN, | ||
262 | FC_SLANT_OBLIQUE, | ||
263 | FC_SLANT_ITALIC | ||
264 | }; | ||
265 | |||
266 | static 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 | ||
282 | static 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 | |||
298 | struct _Style_Map | ||
299 | { | ||
300 | const char *name; | ||
301 | int type; | ||
302 | }; | ||
303 | typedef struct _Style_Map Style_Map; | ||
304 | |||
305 | static 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 | |||
318 | static 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 | |||
333 | static 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 | */ | ||
346 | static 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 | |||
374 | int | ||
375 | evas_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 | |||
395 | void | ||
396 | evas_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 | |||
407 | Evas_Font_Description * | ||
408 | evas_font_desc_ref(Evas_Font_Description *fdesc) | ||
409 | { | ||
410 | fdesc->ref++; | ||
411 | return fdesc; | ||
412 | } | ||
413 | |||
414 | Evas_Font_Description * | ||
415 | evas_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 | |||
425 | Evas_Font_Description * | ||
426 | evas_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 | |||
438 | int | ||
439 | evas_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 | |||
448 | void | ||
449 | evas_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 | |||
487 | void * | ||
488 | evas_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 | |||
776 | void | ||
777 | evas_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 | |||
783 | Eina_List * | ||
784 | evas_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 | |||
847 | void | ||
848 | evas_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 */ | ||
858 | static Eina_Bool | ||
859 | font_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 | |||
865 | static Evas_Font_Dir * | ||
866 | object_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 | |||
913 | static Evas_Font * | ||
914 | object_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 | |||
946 | static Evas_Font * | ||
947 | object_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 | |||
962 | static Evas_Font * | ||
963 | object_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 | |||
973 | static Evas_Font * | ||
974 | object_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 | |||
988 | static Evas_Font_Dir * | ||
989 | object_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 | |||
1137 | static void | ||
1138 | object_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 | |||
1168 | static int | ||
1169 | evas_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 | |||
1197 | EAPI void | ||
1198 | evas_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 | |||
1210 | EAPI void | ||
1211 | evas_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 | |||
1221 | EAPI void | ||
1222 | evas_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 | |||
1232 | EAPI const Eina_List * | ||
1233 | evas_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 | |||
1241 | static void | ||
1242 | evas_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 | |||
1258 | EAPI void | ||
1259 | evas_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 | |||
1278 | EAPI Evas_Font_Hinting_Flags | ||
1279 | evas_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 | |||
1287 | EAPI Eina_Bool | ||
1288 | evas_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 | |||
1299 | EAPI void | ||
1300 | evas_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 | |||
1309 | EAPI void | ||
1310 | evas_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 | |||
1320 | EAPI int | ||
1321 | evas_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 | |||
1330 | EAPI Eina_List * | ||
1331 | evas_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 | |||
1340 | EAPI void | ||
1341 | evas_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 | |||
6 | struct _Evas_GL | ||
7 | { | ||
8 | DATA32 magic; | ||
9 | Evas *evas; | ||
10 | |||
11 | Eina_List *contexts; | ||
12 | Eina_List *surfaces; | ||
13 | }; | ||
14 | |||
15 | struct _Evas_GL_Context | ||
16 | { | ||
17 | void *data; | ||
18 | }; | ||
19 | |||
20 | struct _Evas_GL_Surface | ||
21 | { | ||
22 | void *data; | ||
23 | }; | ||
24 | |||
25 | EAPI Evas_GL * | ||
26 | evas_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 | |||
50 | EAPI void | ||
51 | evas_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 | |||
70 | EAPI Evas_GL_Config * | ||
71 | evas_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 | |||
82 | EAPI void | ||
83 | evas_gl_config_free(Evas_GL_Config *cfg) | ||
84 | { | ||
85 | if (cfg) free(cfg); | ||
86 | } | ||
87 | |||
88 | EAPI Evas_GL_Surface * | ||
89 | evas_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 | |||
122 | EAPI void | ||
123 | evas_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 | |||
147 | EAPI Evas_GL_Context * | ||
148 | evas_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 | |||
190 | EAPI void | ||
191 | evas_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 | |||
215 | EAPI Eina_Bool | ||
216 | evas_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 | |||
232 | EAPI const char * | ||
233 | evas_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 | |||
242 | EAPI Evas_GL_Func | ||
243 | evas_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 | |||
252 | EAPI Eina_Bool | ||
253 | evas_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 | |||
263 | EAPI Evas_GL_API * | ||
264 | evas_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 | |||
6 | static int | ||
7 | evas_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 | |||
18 | static int | ||
19 | evas_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 | |||
34 | EAPI const Evas_Modifier * | ||
35 | evas_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 | |||
43 | EAPI const Evas_Lock * | ||
44 | evas_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 | |||
52 | EAPI Eina_Bool | ||
53 | evas_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 | |||
68 | EAPI Eina_Bool | ||
69 | evas_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 | |||
84 | EAPI void | ||
85 | evas_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 | |||
99 | EAPI void | ||
100 | evas_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 | |||
124 | EAPI void | ||
125 | evas_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 | |||
139 | EAPI void | ||
140 | evas_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 | |||
165 | EAPI void | ||
166 | evas_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 | |||
181 | EAPI void | ||
182 | evas_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 | |||
197 | EAPI void | ||
198 | evas_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 | |||
213 | EAPI void | ||
214 | evas_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 | |||
231 | EAPI Evas_Modifier_Mask | ||
232 | evas_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 | |||
10 | static 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); | ||
11 | static 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 | |||
13 | static Evas_Key_Grab * | ||
14 | evas_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 | |||
74 | static Evas_Key_Grab * | ||
75 | evas_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 | |||
95 | void | ||
96 | evas_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 | |||
120 | void | ||
121 | evas_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 | |||
136 | EAPI Eina_Bool | ||
137 | evas_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 | |||
157 | EAPI void | ||
158 | evas_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 | |||
4 | static void _evas_layer_free(Evas_Layer *lay); | ||
5 | |||
6 | void | ||
7 | evas_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 | |||
25 | void | ||
26 | evas_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 | |||
43 | Evas_Layer * | ||
44 | evas_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 | |||
54 | static void | ||
55 | _evas_layer_free(Evas_Layer *lay) | ||
56 | { | ||
57 | free(lay); | ||
58 | } | ||
59 | |||
60 | void | ||
61 | evas_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 | |||
72 | void | ||
73 | evas_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 | |||
84 | void | ||
85 | evas_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 | |||
97 | Evas_Layer * | ||
98 | evas_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 | |||
109 | void | ||
110 | evas_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 | |||
127 | void | ||
128 | evas_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 | |||
138 | EAPI void | ||
139 | evas_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 | |||
182 | EAPI short | ||
183 | evas_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 | ||
6 | EAPI Eina_Bool lockdebug = EINA_FALSE; | ||
7 | EAPI int lockmax = 0; | ||
8 | #endif | ||
9 | |||
10 | static int _evas_init_count = 0; | ||
11 | int _evas_log_dom_global = -1; | ||
12 | EAPI int | ||
13 | evas_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 | |||
74 | EAPI int | ||
75 | evas_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 | |||
109 | EAPI Evas * | ||
110 | evas_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 | |||
148 | EAPI void | ||
149 | evas_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 | |||
266 | EAPI void | ||
267 | evas_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 | |||
297 | EAPI int | ||
298 | evas_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 | |||
307 | EAPI Evas_Engine_Info * | ||
308 | evas_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 | |||
324 | EAPI Eina_Bool | ||
325 | evas_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 | |||
336 | EAPI void | ||
337 | evas_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 | |||
359 | EAPI void | ||
360 | evas_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 | |||
372 | EAPI void | ||
373 | evas_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 | |||
398 | EAPI void | ||
399 | evas_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 | |||
415 | EAPI void | ||
416 | evas_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 | |||
433 | EAPI void | ||
434 | evas_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 | |||
450 | EAPI Evas_Coord | ||
451 | evas_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 | |||
460 | EAPI Evas_Coord | ||
461 | evas_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 | |||
470 | EAPI int | ||
471 | evas_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 | |||
480 | EAPI int | ||
481 | evas_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 | |||
490 | EAPI int | ||
491 | evas_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 | |||
503 | EAPI Eina_List * | ||
504 | evas_render_method_list(void) | ||
505 | { | ||
506 | return evas_module_engine_list(); | ||
507 | } | ||
508 | |||
509 | EAPI void | ||
510 | evas_render_method_list_free(Eina_List *list) | ||
511 | { | ||
512 | eina_list_free(list); | ||
513 | } | ||
514 | |||
515 | EAPI Eina_Bool | ||
516 | evas_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 | |||
528 | EAPI Eina_Bool | ||
529 | evas_object_image_extension_can_load_fast_get(const char *file) | ||
530 | { | ||
531 | return evas_common_extension_can_load_get(file); | ||
532 | } | ||
533 | |||
534 | EAPI void | ||
535 | evas_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 | |||
546 | EAPI void | ||
547 | evas_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 | |||
558 | EAPI int | ||
559 | evas_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 | |||
567 | EAPI Eina_Bool | ||
568 | evas_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 | |||
576 | EAPI void | ||
577 | evas_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 | |||
585 | EAPI void * | ||
586 | evas_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 | |||
594 | EAPI void | ||
595 | evas_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 | |||
605 | EAPI void | ||
606 | evas_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 | |||
616 | EAPI Eina_Bool | ||
617 | evas_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 | |||
625 | EAPI void | ||
626 | evas_nochange_push(Evas *e) | ||
627 | { | ||
628 | e->nochange++; | ||
629 | } | ||
630 | |||
631 | EAPI void | ||
632 | evas_nochange_pop(Evas *e) | ||
633 | { | ||
634 | e->nochange--; | ||
635 | } | ||
636 | |||
637 | void | ||
638 | _evas_walk(Evas *e) | ||
639 | { | ||
640 | e->walking_list++; | ||
641 | } | ||
642 | |||
643 | void | ||
644 | _evas_unwalk(Evas *e) | ||
645 | { | ||
646 | e->walking_list--; | ||
647 | if ((e->walking_list == 0) && (e->delete_me)) evas_free(e); | ||
648 | } | ||
649 | |||
650 | EAPI const char * | ||
651 | evas_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 | |||
674 | EAPI void | ||
675 | evas_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 | |||
680 | EAPI void | ||
681 | evas_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 | |||
686 | EAPI void | ||
687 | evas_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 | |||
692 | EAPI void | ||
693 | evas_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 | |||
698 | EAPI void | ||
699 | evas_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 | |||
705 | EAPI void | ||
706 | evas_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 | |||
5 | static 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 | |||
35 | static 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 | |||
113 | static 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 | |||
142 | static 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 | |||
157 | static 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 | |||
169 | static 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 | /****************************************************************************/ | ||
185 | static 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 | |||
222 | Eina_Bool | ||
223 | evas_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 | |||
365 | Eina_Bool | ||
366 | evas_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 | |||
371 | EAPI void | ||
372 | evas_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 | |||
414 | EAPI Eina_Bool | ||
415 | evas_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 | |||
424 | EAPI void | ||
425 | evas_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 | |||
433 | EAPI Evas_Object * | ||
434 | evas_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 | |||
442 | EAPI void | ||
443 | evas_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 | |||
508 | EAPI const Evas_Map * | ||
509 | evas_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 | |||
518 | EAPI Evas_Map * | ||
519 | evas_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 | |||
530 | EAPI void | ||
531 | evas_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 | |||
540 | EAPI Eina_Bool | ||
541 | evas_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 | |||
550 | EAPI void | ||
551 | evas_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 | |||
560 | EAPI Eina_Bool | ||
561 | evas_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 | |||
570 | EAPI Evas_Map * | ||
571 | evas_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 | |||
580 | EAPI void | ||
581 | evas_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 | |||
590 | EAPI int | ||
591 | evas_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 | |||
600 | EAPI void | ||
601 | evas_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 | |||
616 | EAPI void | ||
617 | evas_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 | |||
638 | EAPI void | ||
639 | evas_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 | |||
653 | EAPI void | ||
654 | evas_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 | |||
673 | EAPI void | ||
674 | evas_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 | |||
690 | EAPI void | ||
691 | evas_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 | |||
707 | EAPI void | ||
708 | evas_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 | |||
723 | EAPI void | ||
724 | evas_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 | |||
743 | EAPI void | ||
744 | evas_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 | |||
758 | EAPI void | ||
759 | evas_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 | |||
778 | EAPI void | ||
779 | evas_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 | |||
808 | EAPI void | ||
809 | evas_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 | |||
835 | EAPI void | ||
836 | evas_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 | |||
889 | EAPI void | ||
890 | evas_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 | |||
968 | EAPI void | ||
969 | evas_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 | |||
1009 | EAPI Eina_Bool | ||
1010 | evas_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 | |||
4 | EAPI void | ||
5 | evas_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 | |||
23 | EAPI const char * | ||
24 | evas_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 | |||
32 | EAPI Evas_Object * | ||
33 | evas_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 | |||
42 | static 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 | |||
64 | EAPI Evas_Object * | ||
65 | evas_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 | |||
7 | typedef struct _Evas_Object_Box_Iterator Evas_Object_Box_Iterator; | ||
8 | typedef struct _Evas_Object_Box_Accessor Evas_Object_Box_Accessor; | ||
9 | |||
10 | struct _Evas_Object_Box_Iterator | ||
11 | { | ||
12 | Eina_Iterator iterator; | ||
13 | |||
14 | Eina_Iterator *real_iterator; | ||
15 | const Evas_Object *box; | ||
16 | }; | ||
17 | |||
18 | struct _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 | |||
30 | static const Evas_Smart_Cb_Description _signals[] = | ||
31 | { | ||
32 | {SIG_CHILD_ADDED, ""}, | ||
33 | {SIG_CHILD_REMOVED, ""}, | ||
34 | {NULL, NULL} | ||
35 | }; | ||
36 | |||
37 | |||
38 | static 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 | |||
65 | EVAS_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 | |||
69 | static 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 | |||
80 | static Evas_Object * | ||
81 | _evas_object_box_iterator_get_container(Evas_Object_Box_Iterator *it) | ||
82 | { | ||
83 | return (Evas_Object *)it->box; | ||
84 | } | ||
85 | |||
86 | static 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 | |||
93 | static 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 | |||
104 | static Evas_Object * | ||
105 | _evas_object_box_accessor_get_container(Evas_Object_Box_Accessor *it) | ||
106 | { | ||
107 | return (Evas_Object *)it->box; | ||
108 | } | ||
109 | |||
110 | static 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 | |||
117 | static 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 | |||
125 | static 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 | |||
145 | static 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 | |||
153 | static void | ||
154 | _on_hints_changed(void *data __UNUSED__, Evas *evas __UNUSED__, Evas_Object *o , void *einfo __UNUSED__) | ||
155 | { | ||
156 | _sizing_eval(o); | ||
157 | } | ||
158 | |||
159 | static 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 | |||
182 | static 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 | |||
193 | static 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 | |||
217 | static 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 | |||
231 | static 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 | |||
237 | static 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 | |||
253 | static 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 | |||
269 | static 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 | |||
296 | static 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 | |||
323 | static 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 | |||
366 | static 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 | |||
399 | static 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 | |||
432 | static 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 | |||
471 | static 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 | |||
502 | static 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 | |||
511 | static 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 | |||
526 | static 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 | |||
546 | EAPI Evas_Object * | ||
547 | evas_object_box_add(Evas *evas) | ||
548 | { | ||
549 | return evas_object_smart_add(evas, _evas_object_box_smart_class_new()); | ||
550 | } | ||
551 | |||
552 | EAPI Evas_Object * | ||
553 | evas_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 | |||
564 | EAPI void | ||
565 | evas_object_box_smart_set(Evas_Object_Box_Api *api) | ||
566 | { | ||
567 | if (!api) | ||
568 | return; | ||
569 | _evas_object_box_smart_set(api); | ||
570 | } | ||
571 | |||
572 | EAPI const Evas_Object_Box_Api * | ||
573 | evas_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 | |||
588 | EAPI void | ||
589 | evas_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 | |||
606 | static 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 | |||
614 | static 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 | |||
633 | static 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 | |||
658 | static 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 | |||
675 | static 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 | |||
693 | static 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 | |||
747 | EAPI void | ||
748 | evas_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 | |||
851 | static 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 | |||
905 | EAPI void | ||
906 | evas_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 | |||
1010 | EAPI void | ||
1011 | evas_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 | |||
1071 | EAPI void | ||
1072 | evas_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 | |||
1131 | EAPI void | ||
1132 | evas_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 | |||
1215 | EAPI void | ||
1216 | evas_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 | |||
1299 | static 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 | |||
1363 | EAPI void | ||
1364 | evas_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 | |||
1478 | static 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 | |||
1543 | EAPI void | ||
1544 | evas_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 | |||
1658 | EAPI void | ||
1659 | evas_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 | |||
1706 | EAPI void | ||
1707 | evas_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 | |||
1717 | EAPI void | ||
1718 | evas_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 | |||
1733 | EAPI void | ||
1734 | evas_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 | |||
1744 | EAPI void | ||
1745 | evas_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 | |||
1760 | EAPI Evas_Object_Box_Option * | ||
1761 | evas_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 | |||
1786 | EAPI Evas_Object_Box_Option * | ||
1787 | evas_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 | |||
1812 | EAPI Evas_Object_Box_Option * | ||
1813 | evas_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 | |||
1838 | EAPI Evas_Object_Box_Option * | ||
1839 | evas_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 | |||
1864 | EAPI Evas_Object_Box_Option * | ||
1865 | evas_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 | |||
1890 | EAPI Eina_Bool | ||
1891 | evas_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 | |||
1916 | EAPI Eina_Bool | ||
1917 | evas_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 | |||
1939 | EAPI Eina_Bool | ||
1940 | evas_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 | |||
1970 | EAPI Eina_Iterator * | ||
1971 | evas_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 | |||
1994 | EAPI Eina_Accessor * | ||
1995 | evas_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 | |||
2018 | EAPI Eina_List * | ||
2019 | evas_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 | |||
2032 | EAPI const char * | ||
2033 | evas_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 | |||
2049 | EAPI int | ||
2050 | evas_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 | |||
2066 | EAPI Eina_Bool | ||
2067 | evas_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 | |||
2080 | EAPI Eina_Bool | ||
2081 | evas_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 | |||
2100 | EAPI Eina_Bool | ||
2101 | evas_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 | |||
2113 | EAPI Eina_Bool | ||
2114 | evas_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 | |||
4 | typedef struct _Evas_Object_Grid_Data Evas_Object_Grid_Data; | ||
5 | typedef struct _Evas_Object_Grid_Option Evas_Object_Grid_Option; | ||
6 | typedef struct _Evas_Object_Grid_Iterator Evas_Object_Grid_Iterator; | ||
7 | typedef struct _Evas_Object_Grid_Accessor Evas_Object_Grid_Accessor; | ||
8 | |||
9 | struct _Evas_Object_Grid_Option | ||
10 | { | ||
11 | Evas_Object *obj; | ||
12 | Eina_List *l; | ||
13 | int x, y, w, h; | ||
14 | }; | ||
15 | |||
16 | struct _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 | |||
26 | struct _Evas_Object_Grid_Iterator | ||
27 | { | ||
28 | Eina_Iterator iterator; | ||
29 | |||
30 | Eina_Iterator *real_iterator; | ||
31 | const Evas_Object *grid; | ||
32 | }; | ||
33 | |||
34 | struct _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 | |||
65 | static const char EVAS_OBJECT_GRID_OPTION_KEY[] = "|EvGd"; | ||
66 | |||
67 | static 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 | |||
78 | static Evas_Object * | ||
79 | _evas_object_grid_iterator_get_container(Evas_Object_Grid_Iterator *it) | ||
80 | { | ||
81 | return (Evas_Object *)it->grid; | ||
82 | } | ||
83 | |||
84 | static 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 | |||
91 | static 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 | |||
102 | static Evas_Object * | ||
103 | _evas_object_grid_accessor_get_container(Evas_Object_Grid_Accessor *it) | ||
104 | { | ||
105 | return (Evas_Object *)it->grid; | ||
106 | } | ||
107 | |||
108 | static 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 | |||
115 | static 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 | |||
121 | static 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 | |||
127 | static 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 | |||
133 | static 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 | |||
140 | static 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 | |||
147 | static 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 | |||
154 | EVAS_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 | |||
158 | static 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 | |||
169 | static 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 | |||
187 | static 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 | |||
196 | static 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 | |||
229 | static 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 | |||
238 | EAPI Evas_Object * | ||
239 | evas_object_grid_add(Evas *evas) | ||
240 | { | ||
241 | return evas_object_smart_add(evas, _evas_object_grid_smart_class_new()); | ||
242 | } | ||
243 | |||
244 | EAPI Evas_Object * | ||
245 | evas_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 | |||
256 | EAPI void | ||
257 | evas_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 | |||
266 | EAPI void | ||
267 | evas_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 | |||
276 | EAPI Eina_Bool | ||
277 | evas_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 | |||
315 | static 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 | |||
322 | EAPI Eina_Bool | ||
323 | evas_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 | |||
349 | EAPI void | ||
350 | evas_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 | |||
367 | EAPI Eina_Bool | ||
368 | evas_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 | |||
386 | EAPI Eina_Iterator * | ||
387 | evas_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 | |||
410 | EAPI Eina_Accessor * | ||
411 | evas_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 | |||
434 | EAPI Eina_List * | ||
435 | evas_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 | |||
448 | EAPI Eina_Bool | ||
449 | evas_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 | |||
455 | EAPI void | ||
456 | evas_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 */ | ||
22 | static const char o_type[] = "image"; | ||
23 | |||
24 | /* private struct for rectangle object internal data */ | ||
25 | typedef struct _Evas_Object_Image Evas_Object_Image; | ||
26 | |||
27 | struct _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 */ | ||
97 | static void evas_object_image_unload(Evas_Object *obj, Eina_Bool dirty); | ||
98 | static void evas_object_image_load(Evas_Object *obj); | ||
99 | static Evas_Coord evas_object_image_figure_x_fill(Evas_Object *obj, Evas_Coord start, Evas_Coord size, Evas_Coord *size_ret); | ||
100 | static Evas_Coord evas_object_image_figure_y_fill(Evas_Object *obj, Evas_Coord start, Evas_Coord size, Evas_Coord *size_ret); | ||
101 | |||
102 | static void evas_object_image_init(Evas_Object *obj); | ||
103 | static void *evas_object_image_new(void); | ||
104 | static void evas_object_image_render(Evas_Object *obj, void *output, void *context, void *surface, int x, int y); | ||
105 | static void evas_object_image_free(Evas_Object *obj); | ||
106 | static void evas_object_image_render_pre(Evas_Object *obj); | ||
107 | static void evas_object_image_render_post(Evas_Object *obj); | ||
108 | |||
109 | static unsigned int evas_object_image_id_get(Evas_Object *obj); | ||
110 | static unsigned int evas_object_image_visual_id_get(Evas_Object *obj); | ||
111 | static void *evas_object_image_engine_data_get(Evas_Object *obj); | ||
112 | |||
113 | static int evas_object_image_is_opaque(Evas_Object *obj); | ||
114 | static int evas_object_image_was_opaque(Evas_Object *obj); | ||
115 | static int evas_object_image_is_inside(Evas_Object *obj, Evas_Coord x, Evas_Coord y); | ||
116 | static int evas_object_image_has_opaque_rect(Evas_Object *obj); | ||
117 | static int evas_object_image_get_opaque_rect(Evas_Object *obj, Evas_Coord *x, Evas_Coord *y, Evas_Coord *w, Evas_Coord *h); | ||
118 | static int evas_object_image_can_map(Evas_Object *obj); | ||
119 | |||
120 | static void *evas_object_image_data_convert_internal(Evas_Object_Image *o, void *data, Evas_Colorspace to_cspace); | ||
121 | static void evas_object_image_filled_resize_listener(void *data, Evas *e, Evas_Object *obj, void *einfo); | ||
122 | |||
123 | static void _proxy_unset(Evas_Object *proxy); | ||
124 | static void _proxy_set(Evas_Object *proxy, Evas_Object *src); | ||
125 | static void _proxy_error(Evas_Object *proxy, void *context, void *output, void *surface, int x, int y); | ||
126 | |||
127 | static void _cleanup_tmpf(Evas_Object *obj); | ||
128 | |||
129 | static 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 | |||
155 | EVAS_MEMPOOL(_mp_obj); | ||
156 | |||
157 | static 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 | |||
171 | EAPI Evas_Object * | ||
172 | evas_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 | |||
189 | EAPI Evas_Object * | ||
190 | evas_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 | |||
198 | static 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 | |||
219 | static 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 | |||
275 | EAPI void | ||
276 | evas_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 | |||
305 | EAPI void | ||
306 | evas_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 | |||
403 | EAPI void | ||
404 | evas_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 | |||
423 | EAPI Eina_Bool | ||
424 | evas_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 | |||
453 | EAPI Evas_Object * | ||
454 | evas_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 | |||
469 | EAPI Eina_Bool | ||
470 | evas_object_image_source_unset(Evas_Object *obj) | ||
471 | { | ||
472 | return evas_object_image_source_set(obj, NULL); | ||
473 | } | ||
474 | |||
475 | EAPI void | ||
476 | evas_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 | |||
504 | EAPI void | ||
505 | evas_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 | |||
530 | EAPI void | ||
531 | evas_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 | |||
548 | EAPI Evas_Border_Fill_Mode | ||
549 | evas_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 | |||
563 | EAPI void | ||
564 | evas_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 | |||
593 | EAPI Eina_Bool | ||
594 | evas_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 | |||
609 | EAPI void | ||
610 | evas_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 | |||
627 | EAPI double | ||
628 | evas_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 | |||
642 | EAPI void | ||
643 | evas_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 | |||
671 | EAPI void | ||
672 | evas_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 | |||
698 | EAPI void | ||
699 | evas_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 | |||
716 | EAPI Evas_Fill_Spread | ||
717 | evas_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 | |||
731 | EAPI void | ||
732 | evas_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 | |||
794 | EAPI void | ||
795 | evas_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 | |||
814 | EAPI int | ||
815 | evas_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 | |||
829 | EAPI Evas_Load_Error | ||
830 | evas_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 | |||
844 | EAPI void * | ||
845 | evas_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 | |||
877 | EAPI void | ||
878 | evas_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 | |||
957 | EAPI void * | ||
958 | evas_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 | |||
1014 | EAPI void | ||
1015 | evas_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 | |||
1056 | EAPI void | ||
1057 | evas_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 | |||
1108 | EAPI void | ||
1109 | evas_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 | |||
1129 | EAPI void | ||
1130 | evas_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 | |||
1183 | EAPI Eina_Bool | ||
1184 | evas_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 | |||
1198 | EAPI void | ||
1199 | evas_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 | |||
1218 | EAPI Eina_Bool | ||
1219 | evas_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 | |||
1233 | EAPI void | ||
1234 | evas_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 | |||
1265 | EAPI Eina_Bool | ||
1266 | evas_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 | |||
1332 | EAPI Eina_Bool | ||
1333 | evas_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 | |||
1420 | EAPI void | ||
1421 | evas_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 | |||
1436 | EAPI void | ||
1437 | evas_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 | |||
1454 | EAPI Eina_Bool | ||
1455 | evas_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 | |||
1470 | EAPI void | ||
1471 | evas_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 | |||
1494 | EAPI double | ||
1495 | evas_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 | |||
1509 | EAPI void | ||
1510 | evas_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 | |||
1534 | EAPI void | ||
1535 | evas_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 | |||
1550 | EAPI void | ||
1551 | evas_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 | |||
1574 | EAPI int | ||
1575 | evas_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 | |||
1589 | EAPI void | ||
1590 | evas_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 | |||
1617 | EAPI void | ||
1618 | evas_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 | |||
1635 | EAPI void | ||
1636 | evas_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 | |||
1650 | EAPI Eina_Bool | ||
1651 | evas_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 | |||
1665 | EAPI void | ||
1666 | evas_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 | |||
1694 | EAPI Evas_Colorspace | ||
1695 | evas_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 | |||
1709 | EAPI void | ||
1710 | evas_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 | |||
1757 | EAPI const Evas_Video_Surface * | ||
1758 | evas_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 | |||
1773 | EAPI void | ||
1774 | evas_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 | |||
1796 | EAPI Evas_Native_Surface * | ||
1797 | evas_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 | |||
1813 | EAPI void | ||
1814 | evas_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 | |||
1849 | EAPI Evas_Image_Scale_Hint | ||
1850 | evas_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 | |||
1864 | EAPI void | ||
1865 | evas_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 | |||
1900 | EAPI void | ||
1901 | evas_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 | ||
1922 | EAPI Evas_Image_Content_Hint | ||
1923 | evas_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 | |||
1937 | EAPI Eina_Bool | ||
1938 | evas_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 */ | ||
1956 | EAPI Eina_Bool | ||
1957 | evas_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 | |||
1974 | EAPI int | ||
1975 | evas_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 | |||
1993 | EAPI Evas_Image_Animated_Loop_Hint | ||
1994 | evas_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 | |||
2013 | EAPI int | ||
2014 | evas_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 | |||
2033 | EAPI double | ||
2034 | evas_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 | |||
2062 | EAPI void | ||
2063 | evas_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 | |||
2099 | EAPI void | ||
2100 | evas_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 | |||
2109 | EAPI void | ||
2110 | evas_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 | |||
2156 | EAPI void | ||
2157 | evas_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 | |||
2167 | EAPI int | ||
2168 | evas_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 | |||
2177 | EAPI Eina_Bool | ||
2178 | evas_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 */ | ||
2195 | static 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 | |||
2214 | static 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 | */ | ||
2232 | static 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 | /* | ||
2257 | static 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 | */ | ||
2296 | static 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 | */ | ||
2380 | static void | ||
2381 | image_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 | */ | ||
2416 | static void | ||
2417 | image_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 | */ | ||
2446 | Filtered_Image * | ||
2447 | image_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 | |||
2526 | static void | ||
2527 | evas_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 | |||
2565 | static void | ||
2566 | evas_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 | |||
2619 | static Evas_Coord | ||
2620 | evas_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 | |||
2641 | static Evas_Coord | ||
2642 | evas_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 | |||
2663 | static void | ||
2664 | evas_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 | |||
2687 | static void * | ||
2688 | evas_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 | |||
2712 | static void | ||
2713 | evas_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 | |||
2752 | static void | ||
2753 | evas_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 | |||
3189 | static void | ||
3190 | evas_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 | |||
3468 | static void | ||
3469 | evas_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 | |||
3489 | static 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 | |||
3498 | static 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 | |||
3507 | static 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 | |||
3516 | static int | ||
3517 | evas_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 | |||
3592 | static int | ||
3593 | evas_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 | |||
3627 | static int | ||
3628 | evas_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 | |||
3759 | static int | ||
3760 | evas_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 | |||
3778 | static int | ||
3779 | evas_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 | |||
3805 | static int | ||
3806 | evas_object_image_can_map(Evas_Object *obj __UNUSED__) | ||
3807 | { | ||
3808 | return 1; | ||
3809 | } | ||
3810 | |||
3811 | static void * | ||
3812 | evas_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 | |||
3869 | static void | ||
3870 | evas_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 | |||
3879 | Eina_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 | |||
3890 | void | ||
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 | |||
3897 | void | ||
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 | |||
3906 | Evas_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 | |||
3914 | void | ||
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 | |||
3944 | void | ||
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 | |||
6 | void | ||
7 | evas_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 | |||
15 | void | ||
16 | evas_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 | |||
24 | void | ||
25 | evas_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 | |||
33 | void | ||
34 | evas_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 | |||
42 | void | ||
43 | evas_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 | |||
51 | void | ||
52 | evas_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 | |||
60 | void | ||
61 | evas_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 | |||
72 | void | ||
73 | evas_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 | |||
6 | static void evas_object_intercept_init(Evas_Object *obj); | ||
7 | static void evas_object_intercept_deinit(Evas_Object *obj); | ||
8 | |||
9 | static void | ||
10 | evas_object_intercept_init(Evas_Object *obj) | ||
11 | { | ||
12 | if (!obj->interceptors) | ||
13 | obj->interceptors = evas_mem_calloc(sizeof(Evas_Intercept_Func)); | ||
14 | } | ||
15 | |||
16 | static void | ||
17 | evas_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 | |||
39 | void | ||
40 | evas_object_intercept_cleanup(Evas_Object *obj) | ||
41 | { | ||
42 | if (obj->interceptors) free(obj->interceptors); | ||
43 | } | ||
44 | |||
45 | int | ||
46 | evas_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 | |||
60 | int | ||
61 | evas_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 | |||
75 | int | ||
76 | evas_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 | |||
90 | int | ||
91 | evas_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 | |||
105 | int | ||
106 | evas_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 | |||
120 | int | ||
121 | evas_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 | |||
135 | int | ||
136 | evas_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 | |||
150 | int | ||
151 | evas_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 | |||
165 | int | ||
166 | evas_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 | |||
180 | int | ||
181 | evas_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 | |||
195 | int | ||
196 | evas_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 | |||
210 | int | ||
211 | evas_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 | |||
227 | EAPI void | ||
228 | evas_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 | |||
240 | EAPI void * | ||
241 | evas_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 | |||
257 | EAPI void | ||
258 | evas_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 | |||
270 | EAPI void * | ||
271 | evas_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 | |||
287 | EAPI void | ||
288 | evas_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 | |||
300 | EAPI void * | ||
301 | evas_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 | |||
317 | EAPI void | ||
318 | evas_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 | |||
330 | EAPI void * | ||
331 | evas_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 | |||
347 | EAPI void | ||
348 | evas_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 | |||
360 | EAPI void * | ||
361 | evas_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 | |||
377 | EAPI void | ||
378 | evas_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 | |||
390 | EAPI void * | ||
391 | evas_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 | |||
407 | EAPI void | ||
408 | evas_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 | |||
420 | EAPI void * | ||
421 | evas_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 | |||
437 | EAPI void | ||
438 | evas_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 | |||
450 | EAPI void * | ||
451 | evas_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 | |||
467 | EAPI void | ||
468 | evas_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 | |||
480 | EAPI void * | ||
481 | evas_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 | |||
497 | EAPI void | ||
498 | evas_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 | |||
510 | EAPI void * | ||
511 | evas_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 | |||
527 | EAPI void | ||
528 | evas_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 | |||
540 | EAPI void * | ||
541 | evas_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 | |||
557 | EAPI void | ||
558 | evas_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 | |||
570 | EAPI void * | ||
571 | evas_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 */ | ||
5 | static const char o_type[] = "line"; | ||
6 | |||
7 | /* private struct for line object internal data */ | ||
8 | typedef struct _Evas_Object_Line Evas_Object_Line; | ||
9 | |||
10 | struct _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 */ | ||
29 | static void evas_object_line_init(Evas_Object *obj); | ||
30 | static void *evas_object_line_new(void); | ||
31 | static void evas_object_line_render(Evas_Object *obj, void *output, void *context, void *surface, int x, int y); | ||
32 | static void evas_object_line_free(Evas_Object *obj); | ||
33 | static void evas_object_line_render_pre(Evas_Object *obj); | ||
34 | static void evas_object_line_render_post(Evas_Object *obj); | ||
35 | |||
36 | static unsigned int evas_object_line_id_get(Evas_Object *obj); | ||
37 | static unsigned int evas_object_line_visual_id_get(Evas_Object *obj); | ||
38 | static void *evas_object_line_engine_data_get(Evas_Object *obj); | ||
39 | |||
40 | static int evas_object_line_is_opaque(Evas_Object *obj); | ||
41 | static int evas_object_line_was_opaque(Evas_Object *obj); | ||
42 | static int evas_object_line_is_inside(Evas_Object *obj, Evas_Coord x, Evas_Coord y); | ||
43 | static int evas_object_line_was_inside(Evas_Object *obj, Evas_Coord x, Evas_Coord y); | ||
44 | static void evas_object_line_coords_recalc(Evas_Object *obj); | ||
45 | |||
46 | static 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 | |||
75 | EVAS_MEMPOOL(_mp_obj); | ||
76 | |||
77 | EAPI Evas_Object * | ||
78 | evas_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 | |||
91 | EAPI void | ||
92 | evas_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 | |||
169 | EAPI void | ||
170 | evas_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 */ | ||
196 | static void | ||
197 | evas_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 | |||
220 | static void * | ||
221 | evas_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 | |||
239 | static void | ||
240 | evas_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 | |||
254 | static void | ||
255 | evas_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 | |||
282 | static void | ||
283 | evas_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 | |||
371 | static void | ||
372 | evas_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 | |||
388 | static 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 | |||
397 | static 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 | |||
406 | static 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 | |||
415 | static int | ||
416 | evas_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 | |||
423 | static int | ||
424 | evas_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 | |||
431 | static int | ||
432 | evas_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 | |||
440 | static int | ||
441 | evas_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 | |||
449 | static void | ||
450 | evas_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 | |||
4 | EVAS_MEMPOOL(_mp_obj); | ||
5 | EVAS_MEMPOOL(_mp_sh); | ||
6 | |||
7 | static Eina_Inlist * | ||
8 | get_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 */ | ||
15 | Evas_Object * | ||
16 | evas_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 | |||
33 | void | ||
34 | evas_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 | |||
70 | void | ||
71 | evas_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 | |||
113 | void | ||
114 | evas_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 | |||
136 | void | ||
137 | evas_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 | |||
188 | void | ||
189 | evas_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 | |||
223 | void | ||
224 | evas_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 | |||
232 | void | ||
233 | evas_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 | |||
322 | int | ||
323 | evas_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 | |||
336 | int | ||
337 | evas_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 | |||
349 | int | ||
350 | evas_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 | |||
358 | int | ||
359 | evas_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 | |||
368 | EAPI void | ||
369 | evas_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 | |||
378 | EAPI void | ||
379 | evas_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 | |||
389 | EAPI void | ||
390 | evas_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 | |||
447 | EAPI void | ||
448 | evas_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 | |||
530 | EAPI void | ||
531 | evas_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 | |||
618 | EAPI void | ||
619 | evas_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 | |||
637 | static 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 | |||
652 | EAPI void | ||
653 | evas_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 | |||
668 | EAPI void | ||
669 | evas_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 | |||
684 | EAPI void | ||
685 | evas_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 | |||
700 | EAPI void | ||
701 | evas_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 | |||
716 | EAPI void | ||
717 | evas_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 | |||
732 | EAPI void | ||
733 | evas_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 | |||
748 | EAPI void | ||
749 | evas_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 | |||
767 | EAPI void | ||
768 | evas_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 | |||
784 | EAPI void | ||
785 | evas_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 | |||
800 | EAPI void | ||
801 | evas_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 | |||
816 | EAPI void | ||
817 | evas_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 | |||
832 | EAPI void | ||
833 | evas_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 | |||
848 | EAPI void | ||
849 | evas_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 | |||
868 | EAPI void | ||
869 | evas_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 | |||
886 | EAPI void | ||
887 | evas_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 | |||
929 | EAPI void | ||
930 | evas_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 | |||
1023 | EAPI Eina_Bool | ||
1024 | evas_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 | |||
1033 | EAPI void | ||
1034 | evas_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 | |||
1079 | EAPI void | ||
1080 | evas_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 | |||
1097 | EAPI void | ||
1098 | evas_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 | |||
1110 | EAPI Eina_Bool | ||
1111 | evas_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 | |||
1120 | EAPI void | ||
1121 | evas_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 | |||
1133 | EAPI double | ||
1134 | evas_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 | |||
1143 | EAPI void | ||
1144 | evas_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 | |||
1155 | EAPI Evas_Render_Op | ||
1156 | evas_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 | |||
1165 | EAPI Evas * | ||
1166 | evas_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 | |||
1175 | EAPI Evas_Object * | ||
1176 | evas_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 | |||
1207 | EAPI Evas_Object * | ||
1208 | evas_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 | |||
1214 | EAPI Evas_Object * | ||
1215 | evas_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 | |||
1252 | EAPI Eina_List * | ||
1253 | evas_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 | */ | ||
1297 | EAPI Eina_List * | ||
1298 | evas_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 | |||
1336 | EAPI const char * | ||
1337 | evas_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 | |||
1346 | EAPI void | ||
1347 | evas_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 | |||
1355 | EAPI Eina_Bool | ||
1356 | evas_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 | |||
1364 | EAPI void | ||
1365 | evas_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 | |||
1373 | EAPI Eina_Bool | ||
1374 | evas_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 | |||
1382 | EAPI void | ||
1383 | evas_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 | |||
1391 | EAPI Eina_Bool | ||
1392 | evas_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 */ | ||
5 | static const char o_type[] = "polygon"; | ||
6 | |||
7 | /* private struct for line object internal data */ | ||
8 | typedef struct _Evas_Object_Polygon Evas_Object_Polygon; | ||
9 | typedef struct _Evas_Polygon_Point Evas_Polygon_Point; | ||
10 | |||
11 | struct _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 | |||
23 | struct _Evas_Polygon_Point | ||
24 | { | ||
25 | Evas_Coord x, y; | ||
26 | }; | ||
27 | |||
28 | /* private methods for polygon objects */ | ||
29 | static void evas_object_polygon_init(Evas_Object *obj); | ||
30 | static void *evas_object_polygon_new(void); | ||
31 | static void evas_object_polygon_render(Evas_Object *obj, void *output, void *context, void *surface, int x, int y); | ||
32 | static void evas_object_polygon_free(Evas_Object *obj); | ||
33 | static void evas_object_polygon_render_pre(Evas_Object *obj); | ||
34 | static void evas_object_polygon_render_post(Evas_Object *obj); | ||
35 | |||
36 | static unsigned int evas_object_polygon_id_get(Evas_Object *obj); | ||
37 | static unsigned int evas_object_polygon_visual_id_get(Evas_Object *obj); | ||
38 | static void *evas_object_polygon_engine_data_get(Evas_Object *obj); | ||
39 | |||
40 | static int evas_object_polygon_is_opaque(Evas_Object *obj); | ||
41 | static int evas_object_polygon_was_opaque(Evas_Object *obj); | ||
42 | static int evas_object_polygon_is_inside(Evas_Object *obj, Evas_Coord x, Evas_Coord y); | ||
43 | static int evas_object_polygon_was_inside(Evas_Object *obj, Evas_Coord x, Evas_Coord y); | ||
44 | |||
45 | static 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 | |||
74 | EVAS_MEMPOOL(_mp_obj); | ||
75 | |||
76 | EAPI Evas_Object * | ||
77 | evas_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 | |||
90 | EAPI void | ||
91 | evas_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 | |||
192 | EAPI void | ||
193 | evas_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 */ | ||
236 | static void | ||
237 | evas_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 | |||
258 | static void * | ||
259 | evas_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 | |||
272 | static void | ||
273 | evas_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 | |||
295 | static void | ||
296 | evas_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 | |||
338 | static void | ||
339 | evas_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 | |||
430 | static void | ||
431 | evas_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 | |||
446 | static 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 | |||
455 | static 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 | |||
464 | static 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 | |||
473 | static int | ||
474 | evas_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 | |||
481 | static int | ||
482 | evas_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. */ | ||
492 | static int | ||
493 | evas_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 | |||
547 | static int | ||
548 | evas_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 */ | ||
5 | static const char o_type[] = "rectangle"; | ||
6 | |||
7 | const char *o_rect_type = o_type; | ||
8 | |||
9 | /* private struct for rectangle object internal data */ | ||
10 | typedef struct _Evas_Object_Rectangle Evas_Object_Rectangle; | ||
11 | |||
12 | struct _Evas_Object_Rectangle | ||
13 | { | ||
14 | DATA32 magic; | ||
15 | void *engine_data; | ||
16 | }; | ||
17 | |||
18 | /* private methods for rectangle objects */ | ||
19 | static void evas_object_rectangle_init(Evas_Object *obj); | ||
20 | static void *evas_object_rectangle_new(void); | ||
21 | static void evas_object_rectangle_render(Evas_Object *obj, void *output, void *context, void *surface, int x, int y); | ||
22 | static void evas_object_rectangle_free(Evas_Object *obj); | ||
23 | static void evas_object_rectangle_render_pre(Evas_Object *obj); | ||
24 | static void evas_object_rectangle_render_post(Evas_Object *obj); | ||
25 | |||
26 | static unsigned int evas_object_rectangle_id_get(Evas_Object *obj); | ||
27 | static unsigned int evas_object_rectangle_visual_id_get(Evas_Object *obj); | ||
28 | static void *evas_object_rectangle_engine_data_get(Evas_Object *obj); | ||
29 | |||
30 | static int evas_object_rectangle_is_opaque(Evas_Object *obj); | ||
31 | static 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. */ | ||
34 | static void evas_object_rectangle_store(Evas_Object *obj); | ||
35 | static void evas_object_rectangle_unstore(Evas_Object *obj); | ||
36 | static int evas_object_rectangle_is_visible(Evas_Object *obj); | ||
37 | static int evas_object_rectangle_was_visible(Evas_Object *obj); | ||
38 | static int evas_object_rectangle_is_inside(Evas_Object *obj, double x, double y); | ||
39 | static int evas_object_rectangle_was_inside(Evas_Object *obj, double x, double y); | ||
40 | #endif | ||
41 | |||
42 | static 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 | |||
71 | EVAS_MEMPOOL(_mp_obj); | ||
72 | |||
73 | EAPI Evas_Object * | ||
74 | evas_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 */ | ||
88 | static void | ||
89 | evas_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 | |||
111 | static void * | ||
112 | evas_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 | |||
125 | static void | ||
126 | evas_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 | |||
140 | static void | ||
141 | evas_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 | |||
167 | static void | ||
168 | evas_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 | |||
272 | static void | ||
273 | evas_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 | |||
285 | static int | ||
286 | evas_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 | |||
298 | static int | ||
299 | evas_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 | |||
310 | static 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 | |||
319 | static 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 | |||
328 | static 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. */ | ||
339 | static void | ||
340 | evas_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 | |||
348 | static void | ||
349 | evas_object_rectangle_unstore(Evas_Object *obj) | ||
350 | { | ||
351 | /* store... nothing for rectangle objects... it's a bit silly */ | ||
352 | } | ||
353 | |||
354 | static int | ||
355 | evas_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 | |||
362 | static int | ||
363 | evas_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 | |||
370 | static int | ||
371 | evas_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 | |||
379 | static int | ||
380 | evas_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 | |||
4 | typedef struct _Evas_Object_Smart Evas_Object_Smart; | ||
5 | typedef struct _Evas_Smart_Callback Evas_Smart_Callback; | ||
6 | |||
7 | struct _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 | |||
20 | struct _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 */ | ||
30 | static void evas_object_smart_callbacks_clear(Evas_Object *obj); | ||
31 | static void evas_object_smart_init(Evas_Object *obj); | ||
32 | static void *evas_object_smart_new(void); | ||
33 | static void evas_object_smart_render(Evas_Object *obj, void *output, void *context, void *surface, int x, int y); | ||
34 | static void evas_object_smart_free(Evas_Object *obj); | ||
35 | static void evas_object_smart_render_pre(Evas_Object *obj); | ||
36 | static void evas_object_smart_render_post(Evas_Object *obj); | ||
37 | |||
38 | static unsigned int evas_object_smart_id_get(Evas_Object *obj); | ||
39 | static unsigned int evas_object_smart_visual_id_get(Evas_Object *obj); | ||
40 | static void *evas_object_smart_engine_data_get(Evas_Object *obj); | ||
41 | |||
42 | static 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 | |||
68 | EVAS_MEMPOOL(_mp_obj); | ||
69 | EVAS_MEMPOOL(_mp_cb); | ||
70 | |||
71 | /* public funcs */ | ||
72 | EAPI void | ||
73 | evas_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 | |||
87 | EAPI void * | ||
88 | evas_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 | |||
100 | EAPI Evas_Smart * | ||
101 | evas_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 | |||
115 | EAPI void | ||
116 | evas_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 | |||
175 | EAPI void | ||
176 | evas_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 | |||
203 | EAPI Evas_Object * | ||
204 | evas_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 | |||
213 | EAPI Eina_Bool | ||
214 | evas_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 | |||
235 | EAPI Eina_Bool | ||
236 | evas_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 | |||
257 | EAPI Eina_List * | ||
258 | evas_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 | |||
279 | const Eina_Inlist * | ||
280 | evas_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 | |||
294 | void | ||
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 | |||
302 | EAPI Evas_Object * | ||
303 | evas_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 | |||
328 | static 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 | |||
340 | EAPI void | ||
341 | evas_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 | |||
347 | EAPI void | ||
348 | evas_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 | |||
374 | EAPI void * | ||
375 | evas_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 | |||
405 | EAPI void * | ||
406 | evas_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 | |||
436 | EAPI void | ||
437 | evas_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 | |||
470 | EAPI Eina_Bool | ||
471 | evas_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 | |||
505 | EAPI void | ||
506 | evas_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 | |||
537 | EAPI void | ||
538 | evas_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 | |||
570 | EAPI void | ||
571 | evas_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 | |||
606 | EAPI Eina_Bool | ||
607 | evas_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 | |||
621 | EAPI void | ||
622 | evas_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 | |||
640 | EAPI void | ||
641 | evas_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 | |||
649 | EAPI int | ||
650 | evas_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 | */ | ||
663 | void | ||
664 | evas_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 | |||
705 | EAPI void | ||
706 | evas_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 */ | ||
716 | static void | ||
717 | evas_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 | |||
740 | void | ||
741 | evas_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 | |||
752 | void | ||
753 | evas_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 | |||
785 | void | ||
786 | evas_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 | |||
811 | void | ||
812 | evas_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 | |||
820 | void | ||
821 | evas_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 | |||
829 | void | ||
830 | evas_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 | |||
839 | void | ||
840 | evas_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 */ | ||
850 | static void | ||
851 | evas_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 | |||
871 | static void * | ||
872 | evas_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 | |||
885 | static void | ||
886 | evas_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 | |||
900 | static void | ||
901 | evas_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 | |||
906 | static void | ||
907 | evas_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 | } | ||
916 | done: | ||
917 | obj->pre_render_done = 1; | ||
918 | } | ||
919 | |||
920 | static void | ||
921 | evas_object_smart_render_post(Evas_Object *obj) | ||
922 | { | ||
923 | obj->prev = obj->cur; | ||
924 | } | ||
925 | |||
926 | static 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 | |||
935 | static 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 | |||
944 | static 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 | |||
8 | EAPI void | ||
9 | evas_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 | |||
32 | EAPI Evas_Object * | ||
33 | evas_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 | |||
42 | static void | ||
43 | evas_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 | |||
67 | static void | ||
68 | evas_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 | |||
85 | static void | ||
86 | evas_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 | |||
94 | static void | ||
95 | evas_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 | |||
102 | static void | ||
103 | evas_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 | |||
109 | static void | ||
110 | evas_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 | |||
116 | static void | ||
117 | evas_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 | |||
123 | static void | ||
124 | evas_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 | |||
130 | static void | ||
131 | evas_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 | |||
141 | static void | ||
142 | evas_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 | |||
152 | EAPI void | ||
153 | evas_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 | |||
171 | EAPI const Evas_Smart_Class * | ||
172 | evas_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 | |||
4 | typedef struct _Evas_Object_Table_Data Evas_Object_Table_Data; | ||
5 | typedef struct _Evas_Object_Table_Option Evas_Object_Table_Option; | ||
6 | typedef struct _Evas_Object_Table_Cache Evas_Object_Table_Cache; | ||
7 | typedef struct _Evas_Object_Table_Iterator Evas_Object_Table_Iterator; | ||
8 | typedef struct _Evas_Object_Table_Accessor Evas_Object_Table_Accessor; | ||
9 | |||
10 | struct _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 | |||
29 | struct _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 | |||
54 | struct _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 | |||
75 | struct _Evas_Object_Table_Iterator | ||
76 | { | ||
77 | Eina_Iterator iterator; | ||
78 | |||
79 | Eina_Iterator *real_iterator; | ||
80 | const Evas_Object *table; | ||
81 | }; | ||
82 | |||
83 | struct _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 | |||
114 | static const char EVAS_OBJECT_TABLE_OPTION_KEY[] = "|EvTb"; | ||
115 | |||
116 | static 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 | |||
127 | static Evas_Object * | ||
128 | _evas_object_table_iterator_get_container(Evas_Object_Table_Iterator *it) | ||
129 | { | ||
130 | return (Evas_Object *)it->table; | ||
131 | } | ||
132 | |||
133 | static 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 | |||
140 | static 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 | |||
151 | static Evas_Object * | ||
152 | _evas_object_table_accessor_get_container(Evas_Object_Table_Accessor *it) | ||
153 | { | ||
154 | return (Evas_Object *)it->table; | ||
155 | } | ||
156 | |||
157 | static 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 | |||
164 | static 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 | |||
191 | static void | ||
192 | _evas_object_table_cache_free(Evas_Object_Table_Cache *cache) | ||
193 | { | ||
194 | free(cache); | ||
195 | } | ||
196 | |||
197 | static 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 | |||
213 | static 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 | |||
224 | static 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 | |||
230 | static 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 | |||
236 | static 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 | |||
242 | static 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 | |||
249 | static 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 | |||
258 | static 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 | |||
267 | static 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 | |||
276 | static 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 | |||
316 | static 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 | |||
422 | static 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 | |||
449 | static 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 | |||
461 | static 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 | |||
519 | static 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 | |||
527 | static 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 | |||
542 | static 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 | |||
554 | static 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 | |||
570 | static 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 | |||
622 | static 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 | |||
769 | static 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 | |||
864 | static 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 | |||
872 | EVAS_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 | |||
876 | static 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 | |||
896 | static 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 | |||
921 | static 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 | |||
930 | static 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 | |||
948 | static 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 | |||
957 | EAPI Evas_Object * | ||
958 | evas_object_table_add(Evas *evas) | ||
959 | { | ||
960 | return evas_object_smart_add(evas, _evas_object_table_smart_class_new()); | ||
961 | } | ||
962 | |||
963 | EAPI Evas_Object * | ||
964 | evas_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 | |||
975 | EAPI void | ||
976 | evas_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 | |||
986 | EAPI Evas_Object_Table_Homogeneous_Mode | ||
987 | evas_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 | |||
993 | EAPI void | ||
994 | evas_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 | |||
1004 | EAPI void | ||
1005 | evas_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 | |||
1020 | EAPI void | ||
1021 | evas_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 | |||
1032 | EAPI void | ||
1033 | evas_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 | |||
1048 | EAPI Eina_Bool | ||
1049 | evas_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 | |||
1070 | EAPI Eina_Bool | ||
1071 | evas_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 | |||
1166 | static 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 | |||
1212 | EAPI Eina_Bool | ||
1213 | evas_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 | |||
1242 | EAPI void | ||
1243 | evas_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 | |||
1264 | EAPI void | ||
1265 | evas_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 | |||
1280 | EAPI Eina_Iterator * | ||
1281 | evas_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 | |||
1304 | EAPI Eina_Accessor * | ||
1305 | evas_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 | |||
1328 | EAPI Eina_List * | ||
1329 | evas_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 | |||
1342 | Evas_Object * | ||
1343 | evas_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 | |||
1356 | EAPI Eina_Bool | ||
1357 | evas_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 | |||
1364 | EAPI void | ||
1365 | evas_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 */ | ||
9 | static const char o_type[] = "text"; | ||
10 | |||
11 | /* private struct for text object internal data */ | ||
12 | typedef struct _Evas_Object_Text Evas_Object_Text; | ||
13 | typedef struct _Evas_Object_Text_Item Evas_Object_Text_Item; | ||
14 | |||
15 | struct _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 | |||
43 | struct _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 */ | ||
54 | static void evas_object_text_init(Evas_Object *obj); | ||
55 | static void *evas_object_text_new(void); | ||
56 | static void evas_object_text_render(Evas_Object *obj, void *output, void *context, void *surface, int x, int y); | ||
57 | static void evas_object_text_free(Evas_Object *obj); | ||
58 | static void evas_object_text_render_pre(Evas_Object *obj); | ||
59 | static void evas_object_text_render_post(Evas_Object *obj); | ||
60 | |||
61 | static unsigned int evas_object_text_id_get(Evas_Object *obj); | ||
62 | static unsigned int evas_object_text_visual_id_get(Evas_Object *obj); | ||
63 | static void *evas_object_text_engine_data_get(Evas_Object *obj); | ||
64 | |||
65 | static int evas_object_text_is_opaque(Evas_Object *obj); | ||
66 | static int evas_object_text_was_opaque(Evas_Object *obj); | ||
67 | |||
68 | static void evas_object_text_scale_update(Evas_Object *obj); | ||
69 | static void _evas_object_text_recalc(Evas_Object *obj); | ||
70 | |||
71 | static 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 | |||
100 | EVAS_MEMPOOL(_mp_obj); | ||
101 | |||
102 | static 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 | |||
124 | static 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 | |||
130 | static 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 | ||
147 | static 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 | |||
161 | static 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 | |||
214 | static 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 | |||
237 | static 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 | |||
253 | static 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 | |||
260 | EAPI Evas_Object * | ||
261 | evas_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 | |||
274 | EAPI void | ||
275 | evas_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 | |||
298 | EAPI const char * | ||
299 | evas_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 | |||
313 | EAPI void | ||
314 | evas_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 | |||
407 | EAPI void | ||
408 | evas_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 | */ | ||
436 | static 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 | */ | ||
475 | static 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 | */ | ||
529 | static 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 | |||
592 | EAPI void | ||
593 | evas_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 | |||
653 | EAPI void | ||
654 | evas_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 | |||
669 | EAPI const char * | ||
670 | evas_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 | |||
686 | EAPI const char * | ||
687 | evas_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 | |||
701 | EAPI Evas_BiDi_Direction | ||
702 | evas_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 | |||
720 | EAPI Evas_Coord | ||
721 | evas_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 | |||
735 | EAPI Evas_Coord | ||
736 | evas_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 | |||
750 | EAPI Evas_Coord | ||
751 | evas_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 | |||
765 | EAPI Evas_Coord | ||
766 | evas_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 | |||
780 | EAPI Evas_Coord | ||
781 | evas_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 | |||
797 | EAPI Evas_Coord | ||
798 | evas_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 | |||
814 | EAPI Evas_Coord | ||
815 | evas_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 | |||
831 | EAPI Eina_Bool | ||
832 | evas_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 | |||
874 | EAPI int | ||
875 | evas_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 | |||
891 | EAPI int | ||
892 | evas_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 | |||
933 | EAPI void | ||
934 | evas_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 | |||
959 | EAPI Evas_Text_Style_Type | ||
960 | evas_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 | |||
974 | EAPI void | ||
975 | evas_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 | |||
997 | EAPI void | ||
998 | evas_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 | |||
1023 | EAPI void | ||
1024 | evas_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 | |||
1046 | EAPI void | ||
1047 | evas_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 | |||
1072 | EAPI void | ||
1073 | evas_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 | |||
1095 | EAPI void | ||
1096 | evas_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 | |||
1121 | EAPI void | ||
1122 | evas_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 | |||
1144 | EAPI void | ||
1145 | evas_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 | |||
1170 | EAPI void | ||
1171 | evas_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 | |||
1202 | EAPI int | ||
1203 | evas_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 | |||
1215 | EAPI int | ||
1216 | evas_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 | |||
1228 | EAPI int | ||
1229 | evas_string_char_len_get(const char *str) | ||
1230 | { | ||
1231 | if (!str) return 0; | ||
1232 | return eina_unicode_utf8_get_len(str); | ||
1233 | } | ||
1234 | |||
1235 | void | ||
1236 | evas_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 */ | ||
1363 | static void | ||
1364 | evas_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 | |||
1385 | static void * | ||
1386 | evas_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 | |||
1403 | static void | ||
1404 | evas_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 | |||
1427 | static void | ||
1428 | evas_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 | |||
1671 | static void | ||
1672 | evas_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 | |||
1788 | static void | ||
1789 | evas_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 | |||
1805 | static unsigned int | ||
1806 | evas_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 | |||
1815 | static unsigned int | ||
1816 | evas_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 | |||
1825 | static void * | ||
1826 | evas_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 | |||
1835 | static int | ||
1836 | evas_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 | |||
1843 | static int | ||
1844 | evas_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 | |||
1851 | static void | ||
1852 | evas_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 | |||
1869 | void | ||
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 | |||
1903 | static 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 */ | ||
78 | static 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 | */ | ||
102 | typedef 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 | */ | ||
108 | typedef 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 | */ | ||
114 | typedef 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 | */ | ||
120 | typedef struct _Evas_Object_Textblock_Node_Text Evas_Object_Textblock_Node_Text; | ||
121 | /* | ||
122 | * Defined in Evas.h | ||
123 | typedef 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 | */ | ||
131 | typedef struct _Evas_Object_Textblock_Paragraph Evas_Object_Textblock_Paragraph; | ||
132 | /** | ||
133 | * @internal | ||
134 | * @typedef Evas_Object_Textblock_Line | ||
135 | * A layouting line. | ||
136 | */ | ||
137 | typedef struct _Evas_Object_Textblock_Line Evas_Object_Textblock_Line; | ||
138 | /** | ||
139 | * @internal | ||
140 | * @typedef Evas_Object_Textblock_Item | ||
141 | * A layouting item. | ||
142 | */ | ||
143 | typedef struct _Evas_Object_Textblock_Item Evas_Object_Textblock_Item; | ||
144 | /** | ||
145 | * @internal | ||
146 | * @typedef Evas_Object_Textblock_Item | ||
147 | * A layouting text item. | ||
148 | */ | ||
149 | typedef 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 | */ | ||
155 | typedef 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 | */ | ||
161 | typedef 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. */ | ||
217 | struct _Evas_Object_Style_Tag_Base | ||
218 | { | ||
219 | char *tag; | ||
220 | char *replace; | ||
221 | size_t tag_len; | ||
222 | size_t replace_len; | ||
223 | }; | ||
224 | |||
225 | struct _Evas_Object_Style_Tag | ||
226 | { | ||
227 | EINA_INLIST; | ||
228 | Evas_Object_Style_Tag_Base tag; | ||
229 | }; | ||
230 | |||
231 | struct _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 | |||
242 | struct _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 */ | ||
258 | static 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 | |||
297 | struct _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 | |||
312 | struct _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 | |||
322 | typedef enum _Evas_Textblock_Item_Type | ||
323 | { | ||
324 | EVAS_TEXTBLOCK_ITEM_TEXT, | ||
325 | EVAS_TEXTBLOCK_ITEM_FORMAT, | ||
326 | } Evas_Textblock_Item_Type; | ||
327 | |||
328 | struct _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 | |||
348 | struct _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 | |||
357 | struct _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 | |||
368 | struct _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 | |||
411 | struct _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 | |||
420 | struct _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 | ||
429 | struct _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 */ | ||
468 | static void evas_object_textblock_init(Evas_Object *obj); | ||
469 | static void *evas_object_textblock_new(void); | ||
470 | static void evas_object_textblock_render(Evas_Object *obj, void *output, void *context, void *surface, int x, int y); | ||
471 | static void evas_object_textblock_free(Evas_Object *obj); | ||
472 | static void evas_object_textblock_render_pre(Evas_Object *obj); | ||
473 | static void evas_object_textblock_render_post(Evas_Object *obj); | ||
474 | |||
475 | static unsigned int evas_object_textblock_id_get(Evas_Object *obj); | ||
476 | static unsigned int evas_object_textblock_visual_id_get(Evas_Object *obj); | ||
477 | static void *evas_object_textblock_engine_data_get(Evas_Object *obj); | ||
478 | |||
479 | static int evas_object_textblock_is_opaque(Evas_Object *obj); | ||
480 | static int evas_object_textblock_was_opaque(Evas_Object *obj); | ||
481 | |||
482 | static void evas_object_textblock_coords_recalc(Evas_Object *obj); | ||
483 | |||
484 | static void evas_object_textblock_scale_update(Evas_Object *obj); | ||
485 | |||
486 | static 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 | |||
536 | static Eina_Bool _evas_textblock_cursor_is_at_the_end(const Evas_Textblock_Cursor *cur); | ||
537 | static void _evas_textblock_node_text_remove(Evas_Object_Textblock *o, Evas_Object_Textblock_Node_Text *n); | ||
538 | static void _evas_textblock_node_text_remove_formats_between(Evas_Object_Textblock *o, Evas_Object_Textblock_Node_Text *n, int start, int end); | ||
539 | static Evas_Object_Textblock_Node_Format *_evas_textblock_cursor_node_format_before_or_at_pos_get(const Evas_Textblock_Cursor *cur); | ||
540 | static size_t _evas_textblock_node_format_pos_get(const Evas_Object_Textblock_Node_Format *fmt); | ||
541 | static void _evas_textblock_node_format_remove(Evas_Object_Textblock *o, Evas_Object_Textblock_Node_Format *n, int visual_adjustment); | ||
542 | static void _evas_textblock_node_format_free(Evas_Object_Textblock *o, Evas_Object_Textblock_Node_Format *n); | ||
543 | static void _evas_textblock_node_text_free(Evas_Object_Textblock_Node_Text *n); | ||
544 | static void _evas_textblock_changed(Evas_Object_Textblock *o, Evas_Object *obj); | ||
545 | static void _evas_textblock_invalidate_all(Evas_Object_Textblock *o); | ||
546 | static void _evas_textblock_cursors_update_offset(const Evas_Textblock_Cursor *cur, const Evas_Object_Textblock_Node_Text *n, size_t start, int offset); | ||
547 | static 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 | */ | ||
556 | static 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 | */ | ||
580 | static 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 | */ | ||
595 | static 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 | */ | ||
637 | static 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 | */ | ||
668 | static 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 | */ | ||
686 | static 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 | */ | ||
716 | static 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 | */ | ||
735 | static const char escape_strings[] = | ||
736 | /* most common escaped stuff */ | ||
737 | ""\0" "\x22\0" | ||
738 | "&\0" "\x26\0" | ||
739 | "<\0" "\x3c\0" | ||
740 | ">\0" "\x3e\0" | ||
741 | /* all the rest */ | ||
742 | " \0" "\xc2\xa0\0" | ||
743 | "¡\0" "\xc2\xa1\0" | ||
744 | "¢\0" "\xc2\xa2\0" | ||
745 | "£\0" "\xc2\xa3\0" | ||
746 | "¤\0" "\xc2\xa4\0" | ||
747 | "¥\0" "\xc2\xa5\0" | ||
748 | "¦\0" "\xc2\xa6\0" | ||
749 | "§\0" "\xc2\xa7\0" | ||
750 | "¨\0" "\xc2\xa8\0" | ||
751 | "©\0" "\xc2\xa9\0" | ||
752 | "ª\0" "\xc2\xaa\0" | ||
753 | "«\0" "\xc2\xab\0" | ||
754 | "¬\0" "\xc2\xac\0" | ||
755 | "®\0" "\xc2\xae\0" | ||
756 | "¯\0" "\xc2\xaf\0" | ||
757 | "°\0" "\xc2\xb0\0" | ||
758 | "±\0" "\xc2\xb1\0" | ||
759 | "²\0" "\xc2\xb2\0" | ||
760 | "³\0" "\xc2\xb3\0" | ||
761 | "´\0" "\xc2\xb4\0" | ||
762 | "µ\0" "\xc2\xb5\0" | ||
763 | "¶\0" "\xc2\xb6\0" | ||
764 | "·\0" "\xc2\xb7\0" | ||
765 | "¸\0" "\xc2\xb8\0" | ||
766 | "¹\0" "\xc2\xb9\0" | ||
767 | "º\0" "\xc2\xba\0" | ||
768 | "»\0" "\xc2\xbb\0" | ||
769 | "¼\0" "\xc2\xbc\0" | ||
770 | "½\0" "\xc2\xbd\0" | ||
771 | "¾\0" "\xc2\xbe\0" | ||
772 | "¿\0" "\xc2\xbf\0" | ||
773 | "À\0" "\xc3\x80\0" | ||
774 | "Á\0" "\xc3\x81\0" | ||
775 | "Â\0" "\xc3\x82\0" | ||
776 | "Ã\0" "\xc3\x83\0" | ||
777 | "Ä\0" "\xc3\x84\0" | ||
778 | "Å\0" "\xc3\x85\0" | ||
779 | "&Aelig;\0" "\xc3\x86\0" | ||
780 | "Ç\0" "\xc3\x87\0" | ||
781 | "È\0" "\xc3\x88\0" | ||
782 | "É\0" "\xc3\x89\0" | ||
783 | "Ê\0" "\xc3\x8a\0" | ||
784 | "Ë\0" "\xc3\x8b\0" | ||
785 | "Ì\0" "\xc3\x8c\0" | ||
786 | "Í\0" "\xc3\x8d\0" | ||
787 | "Î\0" "\xc3\x8e\0" | ||
788 | "Ï\0" "\xc3\x8f\0" | ||
789 | "&Eth;\0" "\xc3\x90\0" | ||
790 | "Ñ\0" "\xc3\x91\0" | ||
791 | "Ò\0" "\xc3\x92\0" | ||
792 | "Ó\0" "\xc3\x93\0" | ||
793 | "Ô\0" "\xc3\x94\0" | ||
794 | "Õ\0" "\xc3\x95\0" | ||
795 | "Ö\0" "\xc3\x96\0" | ||
796 | "×\0" "\xc3\x97\0" | ||
797 | "Ø\0" "\xc3\x98\0" | ||
798 | "Ù\0" "\xc3\x99\0" | ||
799 | "Ú\0" "\xc3\x9a\0" | ||
800 | "Û\0" "\xc3\x9b\0" | ||
801 | "Ý\0" "\xc3\x9d\0" | ||
802 | "&Thorn;\0" "\xc3\x9e\0" | ||
803 | "ß\0" "\xc3\x9f\0" | ||
804 | "à\0" "\xc3\xa0\0" | ||
805 | "á\0" "\xc3\xa1\0" | ||
806 | "â\0" "\xc3\xa2\0" | ||
807 | "ã\0" "\xc3\xa3\0" | ||
808 | "ä\0" "\xc3\xa4\0" | ||
809 | "å\0" "\xc3\xa5\0" | ||
810 | "æ\0" "\xc3\xa6\0" | ||
811 | "ç\0" "\xc3\xa7\0" | ||
812 | "è\0" "\xc3\xa8\0" | ||
813 | "é\0" "\xc3\xa9\0" | ||
814 | "ê\0" "\xc3\xaa\0" | ||
815 | "ë\0" "\xc3\xab\0" | ||
816 | "ì\0" "\xc3\xac\0" | ||
817 | "í\0" "\xc3\xad\0" | ||
818 | "î\0" "\xc3\xae\0" | ||
819 | "ï\0" "\xc3\xaf\0" | ||
820 | "ð\0" "\xc3\xb0\0" | ||
821 | "ñ\0" "\xc3\xb1\0" | ||
822 | "ò\0" "\xc3\xb2\0" | ||
823 | "ó\0" "\xc3\xb3\0" | ||
824 | "ô\0" "\xc3\xb4\0" | ||
825 | "õ\0" "\xc3\xb5\0" | ||
826 | "ö\0" "\xc3\xb6\0" | ||
827 | "÷\0" "\xc3\xb7\0" | ||
828 | "ø\0" "\xc3\xb8\0" | ||
829 | "ù\0" "\xc3\xb9\0" | ||
830 | "ú\0" "\xc3\xba\0" | ||
831 | "û\0" "\xc3\xbb\0" | ||
832 | "ü\0" "\xc3\xbc\0" | ||
833 | "ý\0" "\xc3\xbd\0" | ||
834 | "þ\0" "\xc3\xbe\0" | ||
835 | "ÿ\0" "\xc3\xbf\0" | ||
836 | "α\0" "\xce\x91\0" | ||
837 | "β\0" "\xce\x92\0" | ||
838 | "γ\0" "\xce\x93\0" | ||
839 | "δ\0" "\xce\x94\0" | ||
840 | "ε\0" "\xce\x95\0" | ||
841 | "ζ\0" "\xce\x96\0" | ||
842 | "η\0" "\xce\x97\0" | ||
843 | "θ\0" "\xce\x98\0" | ||
844 | "ι\0" "\xce\x99\0" | ||
845 | "κ\0" "\xce\x9a\0" | ||
846 | "λ\0" "\xce\x9b\0" | ||
847 | "μ\0" "\xce\x9c\0" | ||
848 | "ν\0" "\xce\x9d\0" | ||
849 | "ξ\0" "\xce\x9e\0" | ||
850 | "ο\0" "\xce\x9f\0" | ||
851 | "π\0" "\xce\xa0\0" | ||
852 | "ρ\0" "\xce\xa1\0" | ||
853 | "σ\0" "\xce\xa3\0" | ||
854 | "τ\0" "\xce\xa4\0" | ||
855 | "υ\0" "\xce\xa5\0" | ||
856 | "φ\0" "\xce\xa6\0" | ||
857 | "χ\0" "\xce\xa7\0" | ||
858 | "ψ\0" "\xce\xa8\0" | ||
859 | "ω\0" "\xce\xa9\0" | ||
860 | "…\0" "\xe2\x80\xa6\0" | ||
861 | "€\0" "\xe2\x82\xac\0" | ||
862 | "←\0" "\xe2\x86\x90\0" | ||
863 | "↑\0" "\xe2\x86\x91\0" | ||
864 | "→\0" "\xe2\x86\x92\0" | ||
865 | "↓\0" "\xe2\x86\x93\0" | ||
866 | "↔\0" "\xe2\x86\x94\0" | ||
867 | "←\0" "\xe2\x87\x90\0" | ||
868 | "→\0" "\xe2\x87\x92\0" | ||
869 | "∀\0" "\xe2\x88\x80\0" | ||
870 | "∃\0" "\xe2\x88\x83\0" | ||
871 | "∇\0" "\xe2\x88\x87\0" | ||
872 | "∏\0" "\xe2\x88\x8f\0" | ||
873 | "∑\0" "\xe2\x88\x91\0" | ||
874 | "∧\0" "\xe2\x88\xa7\0" | ||
875 | "∨\0" "\xe2\x88\xa8\0" | ||
876 | "∫\0" "\xe2\x88\xab\0" | ||
877 | "≠\0" "\xe2\x89\xa0\0" | ||
878 | "≡\0" "\xe2\x89\xa1\0" | ||
879 | "⊕\0" "\xe2\x8a\x95\0" | ||
880 | "⊥\0" "\xe2\x8a\xa5\0" | ||
881 | "†\0" "\xe2\x80\xa0\0" | ||
882 | "‡\0" "\xe2\x80\xa1\0" | ||
883 | "•\0" "\xe2\x80\xa2\0" | ||
884 | ; | ||
885 | |||
886 | EVAS_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 | */ | ||
894 | static 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 | */ | ||
939 | static 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 | */ | ||
962 | static 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 | */ | ||
986 | static 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. */ | ||
1035 | static int format_refcount = 0; | ||
1036 | /* Holders for the stringshares */ | ||
1037 | static const char *fontstr = NULL; | ||
1038 | static const char *font_fallbacksstr = NULL; | ||
1039 | static const char *font_sizestr = NULL; | ||
1040 | static const char *font_sourcestr = NULL; | ||
1041 | static const char *font_weightstr = NULL; | ||
1042 | static const char *font_stylestr = NULL; | ||
1043 | static const char *font_widthstr = NULL; | ||
1044 | static const char *langstr = NULL; | ||
1045 | static const char *colorstr = NULL; | ||
1046 | static const char *underline_colorstr = NULL; | ||
1047 | static const char *underline2_colorstr = NULL; | ||
1048 | static const char *underline_dash_colorstr = NULL; | ||
1049 | static const char *outline_colorstr = NULL; | ||
1050 | static const char *shadow_colorstr = NULL; | ||
1051 | static const char *glow_colorstr = NULL; | ||
1052 | static const char *glow2_colorstr = NULL; | ||
1053 | static const char *backing_colorstr = NULL; | ||
1054 | static const char *strikethrough_colorstr = NULL; | ||
1055 | static const char *alignstr = NULL; | ||
1056 | static const char *valignstr = NULL; | ||
1057 | static const char *wrapstr = NULL; | ||
1058 | static const char *left_marginstr = NULL; | ||
1059 | static const char *right_marginstr = NULL; | ||
1060 | static const char *underlinestr = NULL; | ||
1061 | static const char *strikethroughstr = NULL; | ||
1062 | static const char *backingstr = NULL; | ||
1063 | static const char *stylestr = NULL; | ||
1064 | static const char *tabstopsstr = NULL; | ||
1065 | static const char *linesizestr = NULL; | ||
1066 | static const char *linerelsizestr = NULL; | ||
1067 | static const char *linegapstr = NULL; | ||
1068 | static const char *linerelgapstr = NULL; | ||
1069 | static const char *itemstr = NULL; | ||
1070 | static const char *linefillstr = NULL; | ||
1071 | static const char *ellipsisstr = NULL; | ||
1072 | static const char *passwordstr = NULL; | ||
1073 | static const char *underline_dash_widthstr = NULL; | ||
1074 | static const char *underline_dash_gapstr = NULL; | ||
1075 | |||
1076 | /** | ||
1077 | * @internal | ||
1078 | * Init the format strings. | ||
1079 | */ | ||
1080 | static 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 | */ | ||
1131 | static 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 | */ | ||
1183 | static 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 | */ | ||
1207 | static 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 | */ | ||
1626 | static 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 | */ | ||
1644 | static 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 | */ | ||
1681 | static 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 | */ | ||
1729 | static 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 | */ | ||
1766 | static 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 | */ | ||
1794 | typedef struct _Ctxt Ctxt; | ||
1795 | |||
1796 | struct _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 | |||
1822 | static void _layout_text_add_logical_item(Ctxt *c, Evas_Object_Textblock_Text_Item *ti, Eina_List *rel); | ||
1823 | static void _text_item_update_sizes(Ctxt *c, Evas_Object_Textblock_Text_Item *ti); | ||
1824 | static 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 | */ | ||
1833 | static 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 | */ | ||
1885 | static 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 | |||
1900 | static 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 | |||
1926 | static 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 | */ | ||
1967 | static 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 | */ | ||
2000 | static 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 | */ | ||
2030 | static 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 | */ | ||
2048 | static 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 | */ | ||
2084 | static 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 | */ | ||
2104 | static 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 | */ | ||
2130 | static 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 | */ | ||
2171 | static 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 | */ | ||
2251 | static 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 | */ | ||
2279 | static 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 | */ | ||
2308 | static 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 */ | ||
2397 | static 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 | */ | ||
2504 | static 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 | |||
2529 | loop_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 | */ | ||
2582 | static 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 | */ | ||
2598 | static 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 | */ | ||
2620 | static 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 | */ | ||
2647 | static 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 | */ | ||
2706 | static 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 | */ | ||
2729 | static 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 | */ | ||
2830 | static 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 | */ | ||
2852 | static 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 | |||
2913 | skip: | ||
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 | */ | ||
2989 | static 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 | */ | ||
3023 | static 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 | */ | ||
3082 | static 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 | |||
3249 | static 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 */ | ||
3266 | static 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 | ||
3315 | static 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 */ | ||
3421 | static 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 */ | ||
3431 | static 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 */ | ||
3442 | static const Eina_Unicode _ellip_str[2] = { 0x2026, '\0' }; | ||
3443 | |||
3444 | static 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 | */ | ||
3495 | static 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 | ||
3550 | static 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 | |||
3562 | static 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 ^ */ | ||
3590 | static 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 | |||
3883 | end: | ||
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 | */ | ||
3900 | static 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 */ | ||
3991 | static 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 | */ | ||
4157 | static 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 | */ | ||
4334 | static 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 | */ | ||
4362 | static 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 | */ | ||
4421 | static 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 | |||
4442 | EAPI Evas_Object * | ||
4443 | evas_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 | |||
4456 | EAPI Evas_Textblock_Style * | ||
4457 | evas_textblock_style_new(void) | ||
4458 | { | ||
4459 | Evas_Textblock_Style *ts; | ||
4460 | |||
4461 | ts = calloc(1, sizeof(Evas_Textblock_Style)); | ||
4462 | return ts; | ||
4463 | } | ||
4464 | |||
4465 | EAPI void | ||
4466 | evas_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 | |||
4478 | EAPI void | ||
4479 | evas_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 | |||
4617 | EAPI const char * | ||
4618 | evas_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 | |||
4626 | static 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 | |||
4657 | EAPI void | ||
4658 | evas_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 | |||
4664 | EAPI const Evas_Textblock_Style * | ||
4665 | evas_object_textblock_style_get(const Evas_Object *obj) | ||
4666 | { | ||
4667 | TB_HEAD_RETURN(NULL); | ||
4668 | return o->style; | ||
4669 | } | ||
4670 | |||
4671 | EAPI void | ||
4672 | evas_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 | |||
4678 | EAPI const Evas_Textblock_Style * | ||
4679 | evas_object_textblock_style_user_peek(const Evas_Object *obj) | ||
4680 | { | ||
4681 | TB_HEAD_RETURN(NULL); | ||
4682 | return o->style_user; | ||
4683 | } | ||
4684 | |||
4685 | EAPI void | ||
4686 | evas_object_textblock_style_user_pop(Evas_Object *obj) | ||
4687 | { | ||
4688 | TB_HEAD(); | ||
4689 | _textblock_style_generic_set(obj, NULL, &(o->style_user)); | ||
4690 | } | ||
4691 | |||
4692 | EAPI void | ||
4693 | evas_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 | |||
4703 | EAPI void | ||
4704 | evas_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 | |||
4715 | EAPI Eina_Bool | ||
4716 | evas_object_textblock_legacy_newline_get(const Evas_Object *obj) | ||
4717 | { | ||
4718 | TB_HEAD_RETURN(EINA_FALSE); | ||
4719 | return o->legacy_newline; | ||
4720 | } | ||
4721 | |||
4722 | EAPI void | ||
4723 | evas_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 | |||
4733 | EAPI double | ||
4734 | evas_object_textblock_valign_get(const Evas_Object *obj) | ||
4735 | { | ||
4736 | TB_HEAD_RETURN(0.0); | ||
4737 | return o->valign; | ||
4738 | } | ||
4739 | |||
4740 | EAPI void | ||
4741 | evas_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 | |||
4747 | EAPI const char * | ||
4748 | evas_object_textblock_bidi_delimiters_get(const Evas_Object *obj) | ||
4749 | { | ||
4750 | TB_HEAD_RETURN(NULL); | ||
4751 | return o->bidi_delimiters; | ||
4752 | } | ||
4753 | |||
4754 | EAPI const char * | ||
4755 | evas_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 | */ | ||
4768 | static 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 | */ | ||
4783 | static 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 | */ | ||
4809 | static 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 | */ | ||
4856 | static 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 | |||
4912 | EAPI const char * | ||
4913 | evas_textblock_escape_string_get(const char *escape) | ||
4914 | { | ||
4915 | /* & -> & */ | ||
4916 | return _escaped_char_get(escape, escape + strlen(escape)); | ||
4917 | } | ||
4918 | |||
4919 | EAPI const char * | ||
4920 | evas_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 | |||
4925 | EAPI const char * | ||
4926 | evas_textblock_string_escape_get(const char *string, int *len_ret) | ||
4927 | { | ||
4928 | /* & -> & */ | ||
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 | */ | ||
4940 | static 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 | */ | ||
4959 | static 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 | |||
4971 | EAPI void | ||
4972 | evas_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 | |||
5003 | EAPI void | ||
5004 | evas_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 | */ | ||
5134 | static 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 | */ | ||
5159 | static 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 | } | ||
5183 | EAPI const char * | ||
5184 | evas_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 | |||
5242 | EAPI char * | ||
5243 | evas_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 | |||
5382 | EAPI char * | ||
5383 | evas_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, "<"); | ||
5407 | else if (ch == '>') | ||
5408 | eina_strbuf_append(sbuf, ">"); | ||
5409 | else if (ch == '&') | ||
5410 | eina_strbuf_append(sbuf, "&"); | ||
5411 | else if (ch == _PARAGRAPH_SEPARATOR) | ||
5412 | eina_strbuf_append(sbuf, "<ps/>"); | ||
5413 | else if (ch == _REPLACEMENT_CHAR) | ||
5414 | eina_strbuf_append(sbuf, ""); | ||
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 | */ | ||
5436 | static 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 | */ | ||
5496 | static 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 | */ | ||
5525 | static 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 | */ | ||
5561 | static 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 | */ | ||
5586 | static 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 | */ | ||
5616 | static 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 | */ | ||
5665 | static 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 | |||
5691 | EAPI Evas_Textblock_Cursor * | ||
5692 | evas_object_textblock_cursor_get(const Evas_Object *obj) | ||
5693 | { | ||
5694 | TB_HEAD_RETURN(NULL); | ||
5695 | return o->cursor; | ||
5696 | } | ||
5697 | |||
5698 | EAPI Evas_Textblock_Cursor * | ||
5699 | evas_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 | |||
5713 | EAPI void | ||
5714 | evas_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 | |||
5725 | EAPI Eina_Bool | ||
5726 | evas_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 | |||
5733 | EAPI const Eina_List * | ||
5734 | evas_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 | |||
5745 | EAPI const Evas_Object_Textblock_Node_Format * | ||
5746 | evas_textblock_node_format_first_get(const Evas_Object *obj) | ||
5747 | { | ||
5748 | TB_HEAD_RETURN(NULL); | ||
5749 | return o->format_nodes; | ||
5750 | } | ||
5751 | |||
5752 | EAPI const Evas_Object_Textblock_Node_Format * | ||
5753 | evas_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 | |||
5763 | EAPI const Evas_Object_Textblock_Node_Format * | ||
5764 | evas_textblock_node_format_next_get(const Evas_Object_Textblock_Node_Format *n) | ||
5765 | { | ||
5766 | return _NODE_FORMAT(EINA_INLIST_GET(n)->next); | ||
5767 | } | ||
5768 | |||
5769 | EAPI const Evas_Object_Textblock_Node_Format * | ||
5770 | evas_textblock_node_format_prev_get(const Evas_Object_Textblock_Node_Format *n) | ||
5771 | { | ||
5772 | return _NODE_FORMAT(EINA_INLIST_GET(n)->prev); | ||
5773 | } | ||
5774 | |||
5775 | EAPI void | ||
5776 | evas_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 | |||
5838 | found: | ||
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 | |||
5883 | EAPI void | ||
5884 | evas_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 | |||
5894 | EAPI void | ||
5895 | evas_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 | |||
5919 | EAPI Eina_Bool | ||
5920 | evas_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 | |||
5941 | EAPI Eina_Bool | ||
5942 | evas_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 | |||
5967 | EAPI void | ||
5968 | evas_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 | |||
5973 | EAPI Eina_Bool | ||
5974 | evas_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 | |||
6010 | EAPI Eina_Bool | ||
6011 | evas_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 | |||
6061 | EAPI Eina_Bool | ||
6062 | evas_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 | |||
6108 | EAPI Eina_Bool | ||
6109 | evas_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 | |||
6150 | EAPI Eina_Bool | ||
6151 | evas_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 | |||
6188 | EAPI Eina_Bool | ||
6189 | evas_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 | |||
6202 | EAPI void | ||
6203 | evas_textblock_cursor_paragraph_char_first(Evas_Textblock_Cursor *cur) | ||
6204 | { | ||
6205 | if (!cur) return; | ||
6206 | cur->pos = 0; | ||
6207 | |||
6208 | } | ||
6209 | |||
6210 | EAPI void | ||
6211 | evas_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 | |||
6230 | EAPI void | ||
6231 | evas_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 | |||
6264 | EAPI void | ||
6265 | evas_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 | */ | ||
6318 | static 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 | */ | ||
6369 | static 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 | */ | ||
6405 | static 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 | */ | ||
6485 | static 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 | */ | ||
6512 | static 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 | */ | ||
6567 | static 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 | */ | ||
6688 | static 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 | */ | ||
6737 | static 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 | */ | ||
6768 | static 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 | */ | ||
6785 | static 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 | |||
6808 | EAPI int | ||
6809 | evas_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 | |||
6827 | EAPI void | ||
6828 | evas_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 | |||
6873 | EAPI Eina_Bool | ||
6874 | evas_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 | |||
6901 | EAPI int | ||
6902 | evas_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 | |||
6929 | EAPI void | ||
6930 | evas_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 | */ | ||
6950 | static 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 | */ | ||
6968 | static 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 | */ | ||
6991 | static 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 | */ | ||
7064 | static 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 | */ | ||
7096 | static 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 | */ | ||
7153 | static 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 | |||
7168 | static 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 | |||
7179 | EAPI int | ||
7180 | evas_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 | |||
7252 | EAPI int | ||
7253 | evas_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 | */ | ||
7269 | static 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 | */ | ||
7291 | static 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 | |||
7404 | static 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 | |||
7416 | EAPI Eina_Bool | ||
7417 | evas_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 | |||
7550 | EAPI Eina_Bool | ||
7551 | evas_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 | |||
7566 | EAPI void | ||
7567 | evas_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 | |||
7642 | EAPI void | ||
7643 | evas_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 | |||
7734 | EAPI char * | ||
7735 | evas_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 | |||
7768 | static 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 | |||
7886 | static 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 | |||
7946 | EAPI Eina_List * | ||
7947 | evas_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 | |||
8012 | EAPI char * | ||
8013 | evas_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 | |||
8023 | EAPI const char * | ||
8024 | evas_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 | |||
8043 | EAPI int | ||
8044 | evas_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 | |||
8057 | EAPI const Evas_Object_Textblock_Node_Format * | ||
8058 | evas_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 | |||
8065 | EAPI const char * | ||
8066 | evas_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 | |||
8091 | EAPI void | ||
8092 | evas_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 | |||
8099 | EAPI Eina_Bool | ||
8100 | evas_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 | |||
8111 | EAPI int | ||
8112 | evas_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 | */ | ||
8285 | static 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 | |||
8400 | EAPI int | ||
8401 | evas_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 | |||
8407 | EAPI int | ||
8408 | evas_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 | |||
8414 | EAPI int | ||
8415 | evas_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 | |||
8445 | EAPI Eina_Bool | ||
8446 | evas_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 | |||
8462 | EAPI Eina_Bool | ||
8463 | evas_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 | |||
8570 | EAPI int | ||
8571 | evas_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 | */ | ||
8639 | static 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 | */ | ||
8694 | static 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 | |||
8926 | EAPI Eina_List * | ||
8927 | evas_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 | |||
8999 | EAPI Eina_Bool | ||
9000 | evas_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 | |||
9026 | EAPI Eina_Bool | ||
9027 | evas_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 */ | ||
9044 | EAPI Eina_Bool | ||
9045 | evas_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 | |||
9059 | EAPI void | ||
9060 | evas_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 | |||
9084 | EAPI void | ||
9085 | evas_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 | |||
9093 | static 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 | |||
9131 | loop_advance: | ||
9132 | *w += it->adv; | ||
9133 | } | ||
9134 | } | ||
9135 | |||
9136 | /* FIXME: doc */ | ||
9137 | static 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 | |||
9205 | EAPI void | ||
9206 | evas_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 | |||
9236 | EAPI void | ||
9237 | evas_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. */ | ||
9252 | static 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 */ | ||
9259 | static void | ||
9260 | evas_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 | |||
9298 | static void * | ||
9299 | evas_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 | |||
9314 | static void | ||
9315 | evas_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 | |||
9343 | static void | ||
9344 | evas_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 | |||
9738 | static void | ||
9739 | evas_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 | |||
9829 | static void | ||
9830 | evas_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 | |||
9846 | static 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 | |||
9855 | static 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 | |||
9864 | static 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 | |||
9873 | static int | ||
9874 | evas_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 | |||
9881 | static int | ||
9882 | evas_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 | |||
9889 | static void | ||
9890 | evas_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 | |||
9904 | static void | ||
9905 | evas_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 | |||
9914 | void | ||
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 */ | ||
9956 | EAPI 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 | |||
9983 | EAPI 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 */ | ||
9992 | void | ||
9993 | pfnode(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 | |||
10001 | void | ||
10002 | ptnode(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 | |||
10010 | void | ||
10011 | pitem(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 | |||
10039 | void | ||
10040 | ppar(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 | |||
4 | void | ||
5 | evas_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 | ||
10 | static FILE *dbf = NULL; | ||
11 | |||
12 | static void | ||
13 | rend_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 | |||
47 | static Eina_List * | ||
48 | evas_render_updates_internal(Evas *e, unsigned char make_updates, unsigned char do_draw); | ||
49 | |||
50 | EAPI void | ||
51 | evas_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 | |||
64 | EAPI void | ||
65 | evas_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 | |||
77 | EAPI void | ||
78 | evas_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 | |||
91 | static 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 | |||
99 | static 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 | |||
106 | static 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 | |||
113 | static Eina_Bool | ||
114 | _evas_render_can_render(Evas_Object *obj) | ||
115 | { | ||
116 | return (evas_object_is_visible(obj) && (!obj->cur.have_clipees)); | ||
117 | } | ||
118 | |||
119 | static 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 | |||
134 | static 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 | |||
155 | static 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 | |||
246 | static 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 | } | ||
491 | if (!is_active) obj->restack = 0; | ||
492 | RDI(level); | ||
493 | RD(" ---]\n"); | ||
494 | return clean_them; | ||
495 | } | ||
496 | |||
497 | static 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 | |||
528 | static 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 | |||
586 | clean_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 | |||
599 | Eina_Bool | ||
600 | pending_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 | */ | ||
664 | static 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 | |||
858 | Eina_Bool | ||
859 | evas_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 | |||
1291 | static 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 | |||
1349 | static Eina_List * | ||
1350 | evas_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 | |||
1740 | EAPI void | ||
1741 | evas_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 | |||
1749 | EAPI Eina_List * | ||
1750 | evas_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 | |||
1764 | EAPI void | ||
1765 | evas_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 | |||
1779 | EAPI void | ||
1780 | evas_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 | |||
1790 | EAPI void | ||
1791 | evas_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 | |||
1815 | EAPI void | ||
1816 | evas_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 | |||
1829 | static 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 | |||
1848 | EAPI void | ||
1849 | evas_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 | |||
1873 | void | ||
1874 | evas_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 | |||
1889 | void | ||
1890 | evas_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 | |||
5 | static void _evas_smart_class_callbacks_create(Evas_Smart *s); | ||
6 | |||
7 | /* all public */ | ||
8 | |||
9 | EAPI void | ||
10 | evas_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 | |||
22 | EAPI Evas_Smart * | ||
23 | evas_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 | |||
43 | EAPI const Evas_Smart_Class * | ||
44 | evas_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 | |||
52 | EAPI void * | ||
53 | evas_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 | |||
61 | EAPI const Evas_Smart_Cb_Description ** | ||
62 | evas_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 | |||
73 | EAPI const Evas_Smart_Cb_Description * | ||
74 | evas_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 | |||
83 | EAPI Eina_Bool | ||
84 | evas_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 | |||
115 | EAPI int | ||
116 | evas_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 */ | ||
126 | void | ||
127 | evas_object_smart_use(Evas_Smart *s) | ||
128 | { | ||
129 | s->usage++; | ||
130 | } | ||
131 | |||
132 | void | ||
133 | evas_object_smart_unuse(Evas_Smart *s) | ||
134 | { | ||
135 | s->usage--; | ||
136 | if ((s->usage <= 0) && (s->delete_me)) evas_smart_free(s); | ||
137 | } | ||
138 | |||
139 | Eina_Bool | ||
140 | evas_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 | |||
170 | static 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 | |||
178 | void | ||
179 | evas_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 | |||
226 | static 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 | |||
250 | static 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 | |||
260 | const Evas_Smart_Cb_Description * | ||
261 | evas_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 | |||
4 | static Evas_Object * | ||
5 | evas_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 | |||
22 | static Evas_Object * | ||
23 | evas_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 | |||
40 | EAPI void | ||
41 | evas_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 | |||
86 | EAPI void | ||
87 | evas_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 | |||
133 | EAPI void | ||
134 | evas_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 | |||
211 | EAPI void | ||
212 | evas_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 | |||
289 | EAPI Evas_Object * | ||
290 | evas_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 | |||
314 | EAPI Evas_Object * | ||
315 | evas_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 | |||
341 | EAPI Evas_Object * | ||
342 | evas_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 | |||
361 | EAPI Evas_Object * | ||
362 | evas_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 | |||
5 | EAPI Eina_Bool | ||
6 | evas_cserve_want_get(void) | ||
7 | { | ||
8 | #ifdef EVAS_CSERVE | ||
9 | return evas_cserve_use_get(); | ||
10 | #endif | ||
11 | return 0; | ||
12 | } | ||
13 | |||
14 | EAPI Eina_Bool | ||
15 | evas_cserve_connected_get(void) | ||
16 | { | ||
17 | #ifdef EVAS_CSERVE | ||
18 | return evas_cserve_have_get(); | ||
19 | #endif | ||
20 | return 0; | ||
21 | } | ||
22 | |||
23 | EAPI Eina_Bool | ||
24 | evas_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 | |||
45 | EAPI Eina_Bool | ||
46 | evas_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 | |||
127 | EAPI void | ||
128 | evas_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 | |||
144 | EAPI Eina_Bool | ||
145 | evas_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 | |||
162 | EAPI Eina_Bool | ||
163 | evas_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 | |||
179 | EAPI void | ||
180 | evas_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 | |||
4 | void | ||
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 | |||
18 | void | ||
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 | |||
36 | void | ||
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 | |||
53 | EAPI unsigned int | ||
54 | evas_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 | |||
62 | EAPI void | ||
63 | evas_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 | |||
84 | EAPI int | ||
85 | evas_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 | |||
98 | EAPI Evas_Touch_Point_State | ||
99 | evas_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 | } | ||